MILE: All current services confirmed working on a fresh arch vps

This commit is contained in:
2025-12-16 20:40:25 +01:00
parent f40349c2e7
commit 9b12225ec8
6 changed files with 83 additions and 43 deletions

View File

@@ -78,6 +78,40 @@ nextcloud_php_memory_limit: "512M"
nextcloud_php_upload_limit: "512M" nextcloud_php_upload_limit: "512M"
``` ```
## Deployment Strategy
This role uses a **two-phase deployment** approach to work correctly with the Nextcloud container's initialization process:
### Phase 1: Container Initialization (automatic)
1. Create empty directories for volumes
2. Deploy environment configuration (`.env`)
3. Start Nextcloud container
4. Container entrypoint detects first-time setup (no `version.php`)
5. Container copies Nextcloud files to `/var/www/html/`
6. Container runs `occ maintenance:install` with PostgreSQL
7. Installation creates `config.php` with database credentials
### Phase 2: Custom Configuration (automatic)
8. Ansible waits for `occ status` to report `installed: true`
9. Ansible deploys custom `redis.config.php` (overwrites default)
10. Container restart applies custom configuration
**Why this order?**
The Nextcloud container's entrypoint uses `version.php` as a marker to determine if installation is needed. If you deploy any files into `/opt/nextcloud/config/` before the container starts, the initialization process fails:
- Container copies files including `version.php`
- Entrypoint sees `version.php` exists → assumes already installed
- Skips running `occ maintenance:install`
- Result: Empty `config.php`, 503 errors
By deploying custom configs **after** installation completes, we:
- ✅ Allow the container's auto-installation to run properly
- ✅ Override specific configs (like Redis) after the fact
- ✅ Maintain idempotency (subsequent runs just update configs)
See the official [Nextcloud Docker documentation](https://github.com/nextcloud/docker#auto-configuration-via-environment-variables) for more details on the auto-configuration process.
## Usage ## Usage
### Include in Playbook ### Include in Playbook
@@ -232,11 +266,13 @@ This role disables Redis sessions by **not setting** `REDIS_HOST` in the environ
**If you need Redis sessions** (e.g., multi-server setup with session sharing), you must: **If you need Redis sessions** (e.g., multi-server setup with session sharing), you must:
1. Enable `REDIS_HOST` in `nextcloud.env.j2` 1. Enable `REDIS_HOST` in `nextcloud.env.j2`
2. Set proper lock parameters in a custom PHP ini file 2. Add a custom PHP ini file with proper lock parameters:
3. Increase FPM workers significantly (15-20+) - `redis.session.lock_expire = 30` (locks expire after 30 seconds)
4. Monitor for orphaned session locks - `redis.session.lock_retries = 100` (max 100 retries, not infinite)
- `redis.session.lock_wait_time = 50000` (50ms between retries)
See `templates/redis-session-override.ini.j2` for an example of session lock tuning. 3. Mount the ini file with `zz-` prefix to load after the entrypoint's redis-session.ini
4. Increase FPM workers significantly (15-20+)
5. Monitor for orphaned session locks
## Troubleshooting ## Troubleshooting

View File

@@ -52,21 +52,12 @@
notify: restart nextcloud notify: restart nextcloud
tags: [config] tags: [config]
- name: Deploy custom Redis caching configuration # NOTE: Custom Redis config is deployed AFTER installation completes (see below)
template: # to avoid interfering with the container's first-time initialization process
src: redis.config.php.j2
dest: "{{ nextcloud_config_dir }}/redis.config.php"
mode: '0640'
notify: restart nextcloud
tags: [config, redis]
- name: Deploy Redis session lock override configuration # NOTE: redis-session-override.ini is NOT deployed because we use file-based sessions
template: # (not Redis sessions). If you enable REDIS_HOST in the future, you'll need to add
src: redis-session-override.ini.j2 # proper session lock configuration.
dest: "{{ nextcloud_home }}/redis-session-override.ini"
mode: '0644'
notify: restart nextcloud
tags: [config, redis]
- name: Create Quadlet systemd directory (system scope) - name: Create Quadlet systemd directory (system scope)
file: file:
@@ -130,21 +121,43 @@
delay: 10 delay: 10
tags: [verification] tags: [verification]
- name: Wait for Nextcloud installation to complete
shell: podman exec nextcloud php occ status --output=json 2>/dev/null || echo '{"installed":false}'
register: nc_status
until: (nc_status.stdout | from_json).installed | default(false) == true
retries: 60
delay: 5
changed_when: false
tags: [verification]
- name: Deploy custom Redis caching configuration (post-installation)
template:
src: redis.config.php.j2
dest: "{{ nextcloud_config_dir }}/redis.config.php"
mode: '0644'
notify: restart nextcloud
tags: [config, redis]
- name: Display Nextcloud deployment status - name: Display Nextcloud deployment status
debug: debug:
msg: | msg: |
✅ Nextcloud Cloud Storage deployed successfully! ✅ Nextcloud Cloud Storage deployed successfully!
🌐 Domain: {{ nextcloud_domain }} 🌐 Domain: {{ nextcloud_domain }}
🗄️ Database: {{ nextcloud_db_name }} (Unix socket) 🗄️ Database: {{ nextcloud_db_name }} (PostgreSQL via Unix socket)
🗄️ Cache: Valkey DB {{ nextcloud_valkey_db }} (Unix socket) 🗄️ Cache: Valkey DB {{ nextcloud_valkey_db }} (Redis-compatible via Unix socket)
🐳 Container: FPM via Podman Quadlet 🐳 Container: FPM via Podman Quadlet
🔒 Admin: {{ nextcloud_admin_user }} 🔒 Admin: {{ nextcloud_admin_user }}
⚙️ Configuration:
- Redis caching enabled (application-level cache & file locking)
- PHP sessions use file-based storage (not Redis)
- Custom redis.config.php deployed post-installation
🚀 Ready for file storage and collaboration! 🚀 Ready for file storage and collaboration!
📋 Next Steps: 📋 Next Steps:
- Access https://{{ nextcloud_domain }} to complete setup - Access https://{{ nextcloud_domain }} to log in
- Install desired Nextcloud apps - Install desired Nextcloud apps
- Configure user accounts - Configure user accounts and storage quotas
tags: [verification] tags: [verification]

View File

@@ -26,9 +26,6 @@ Volume={{ nextcloud_config_dir }}:/var/www/html/config:Z
# Custom apps (world-readable) # Custom apps (world-readable)
Volume={{ nextcloud_custom_apps_dir }}:/var/www/html/custom_apps:Z Volume={{ nextcloud_custom_apps_dir }}:/var/www/html/custom_apps:Z
# Redis session configuration override (zz- prefix ensures it loads last)
Volume={{ nextcloud_home }}/redis-session-override.ini:/usr/local/etc/php/conf.d/zz-redis-session-override.ini:Z,ro
# Infrastructure sockets (mounted with world-readable permissions on host) # Infrastructure sockets (mounted with world-readable permissions on host)
Volume={{ postgresql_unix_socket_directories }}:{{ postgresql_unix_socket_directories }}:Z Volume={{ postgresql_unix_socket_directories }}:{{ postgresql_unix_socket_directories }}:Z
Volume={{ valkey_unix_socket_path | dirname }}:{{ valkey_unix_socket_path | dirname }}:Z Volume={{ valkey_unix_socket_path | dirname }}:{{ valkey_unix_socket_path | dirname }}:Z

View File

@@ -1,16 +0,0 @@
; Redis Session Lock Override for Nextcloud
; Prevents orphaned session locks from causing infinite hangs
;
; Default Nextcloud container settings:
; redis.session.lock_expire = 0 (locks NEVER expire - causes infinite hangs)
; redis.session.lock_retries = -1 (infinite retries - causes worker exhaustion)
; redis.session.lock_wait_time = 10000 (10 seconds per retry - very slow)
;
; These settings ensure locks auto-expire and failed requests don't block workers forever:
; - Locks expire after 30 seconds (prevents orphaned locks)
; - Max 100 retries = 5 seconds total wait time (prevents infinite loops)
; - 50ms wait between retries (reasonable balance)
redis.session.lock_expire = 30
redis.session.lock_retries = 100
redis.session.lock_wait_time = 50000

View File

@@ -126,6 +126,11 @@
delay: 3 delay: 3
when: postgresql_service_state == "started" and postgresql_unix_socket_enabled and postgresql_listen_addresses == "" when: postgresql_service_state == "started" and postgresql_unix_socket_enabled and postgresql_listen_addresses == ""
# Containerized applications mount socket directories. If handlers run at the end of playbooks this will mount stale sockets.
- name: Flush handlers for socket connection
meta: flush_handlers
tags: always
- name: Display PostgreSQL infrastructure status - name: Display PostgreSQL infrastructure status
debug: debug:
msg: | msg: |
@@ -136,4 +141,4 @@
📊 Checksums: {{ 'Enabled' if postgresql_data_checksums else 'Disabled' }} 📊 Checksums: {{ 'Enabled' if postgresql_data_checksums else 'Disabled' }}
{% if postgresql_unix_socket_enabled %}🔌 Socket: {{ postgresql_unix_socket_directories }} (mode {{ postgresql_unix_socket_permissions }}){% endif %} {% if postgresql_unix_socket_enabled %}🔌 Socket: {{ postgresql_unix_socket_directories }} (mode {{ postgresql_unix_socket_permissions }}){% endif %}
🏗️ Ready for applications to create databases/users 🏗️ Ready for applications to create databases/users

View File

@@ -143,6 +143,11 @@
failed_when: valkey_ping_result_socket.stdout != "PONG" failed_when: valkey_ping_result_socket.stdout != "PONG"
when: valkey_service_state == "started" and valkey_unix_socket_enabled when: valkey_service_state == "started" and valkey_unix_socket_enabled
# Containerized applications mount socket directories. If handlers run at the end of playbooks this will mount stale sockets.
- name: Flush handlers for socket connection
meta: flush_handlers
tags: always
- name: Display Valkey infrastructure status - name: Display Valkey infrastructure status
debug: debug:
msg: | msg: |