Refactor Nextcloud configuration to use OCC script approach and add email/OIDC support

Major architectural changes:
- Replace config file templating with unified OCC command script
- Remove custom_apps mount overlay that caused Caddy serving issues
- Implement script-based configuration for idempotency and clarity

Configuration improvements:
- Add email/SMTP support with master switch (nextcloud_email_enabled)
- Add OIDC/SSO integration with Authentik support
- Add apps installation (user_oidc, calendar, contacts)
- Enable group provisioning and quota management from OIDC
- Set nextcloud_oidc_unique_uid to false per Authentik docs

Files removed:
- nextcloud.config.php.j2 (replaced by OCC commands)
- redis.config.php.j2 (replaced by OCC commands)
- optimization.yml (merged into configure.yml)

Files added:
- configure-nextcloud.sh.j2 (single source of truth for config)
- configure.yml (deploys and runs configuration script)

Documentation:
- Add comprehensive OIDC setup guide with Authentik integration
- Document custom scope mapping and group provisioning
- Add email configuration examples for common providers
- Update vault variables documentation
- Explain two-phase deployment approach

Host configuration:
- Change admin user from 'admin' to 'joakim'
- Add admin email configuration
This commit is contained in:
2025-12-21 14:54:44 +01:00
parent 846ab74f87
commit 89b43180fc
12 changed files with 887 additions and 213 deletions

View File

@@ -0,0 +1,189 @@
#!/bin/bash
# =================================================================
# Nextcloud Configuration Script
# =================================================================
# Rick-Infra - Nextcloud Role
#
# This script configures Nextcloud via OCC commands after initial
# installation. It is generated from Ansible variables and runs
# inside the Nextcloud container.
#
# Generated by: roles/nextcloud/templates/configure-nextcloud.sh.j2
# Managed by: Ansible
set +e # Continue on errors, report at end
ERRORS=0
# Helper function for OCC
occ() {
php /var/www/html/occ "$@" 2>&1
}
# Track errors
check_error() {
if [ $? -ne 0 ]; then
ERRORS=$((ERRORS + 1))
echo "ERROR: $1" >&2
fi
}
# =================================================================
# Redis Caching Configuration
# =================================================================
# Configure Redis for application-level caching and file locking
# WITHOUT enabling Redis sessions (which can cause performance issues)
occ config:system:set memcache.distributed --value='\OC\Memcache\Redis' --quiet
check_error "Failed to set memcache.distributed"
occ config:system:set memcache.locking --value='\OC\Memcache\Redis' --quiet
check_error "Failed to set memcache.locking"
occ config:system:set redis host --value='{{ valkey_unix_socket_path }}' --quiet
check_error "Failed to set redis.host"
occ config:system:set redis password --value='{{ valkey_password }}' --quiet
check_error "Failed to set redis.password"
occ config:system:set redis dbindex --value={{ nextcloud_valkey_db }} --type=integer --quiet
check_error "Failed to set redis.dbindex"
# =================================================================
# Maintenance Configuration
# =================================================================
occ config:system:set maintenance_window_start --value={{ nextcloud_maintenance_window_start }} --type=integer --quiet
check_error "Failed to set maintenance_window_start"
occ config:system:set default_phone_region --value='{{ nextcloud_default_phone_region }}' --quiet
check_error "Failed to set default_phone_region"
# =================================================================
# Database Optimization
# =================================================================
# Add missing database indices
occ db:add-missing-indices --quiet
check_error "Failed to add missing database indices"
# Convert filecache to bigint
occ db:convert-filecache-bigint --no-interaction --quiet
check_error "Failed to convert filecache to bigint"
# Update mimetype database mappings
occ maintenance:repair --include-expensive --quiet
check_error "Failed to run maintenance:repair"
# =================================================================
# App Installation and Enablement
# =================================================================
# Install apps first, then enable them. This must happen before
# app-specific configuration (e.g., OIDC provider setup)
{% if nextcloud_apps_install is defined and nextcloud_apps_install | length > 0 %}
# Install apps
{% for app in nextcloud_apps_install %}
occ app:install {{ app }} --quiet 2>&1 | grep -v "already installed" || true
check_error "Failed to install app: {{ app }}"
{% endfor %}
{% endif %}
# =================================================================
# Email/SMTP Configuration
# =================================================================
{% if nextcloud_email_enabled | default(false) %}
# Configure SMTP mode
occ config:system:set mail_smtpmode --value={{ nextcloud_smtp_mode }} --quiet
check_error "Failed to set mail_smtpmode"
# Configure SMTP server
occ config:system:set mail_smtphost --value='{{ nextcloud_smtp_host }}' --quiet
check_error "Failed to set mail_smtphost"
occ config:system:set mail_smtpport --value={{ nextcloud_smtp_port }} --type=integer --quiet
check_error "Failed to set mail_smtpport"
{% if nextcloud_smtp_secure %}
occ config:system:set mail_smtpsecure --value={{ nextcloud_smtp_secure }} --quiet
check_error "Failed to set mail_smtpsecure"
{% endif %}
{% if nextcloud_smtp_auth %}
# Configure SMTP authentication
occ config:system:set mail_smtpauth --value=1 --type=integer --quiet
check_error "Failed to set mail_smtpauth"
occ config:system:set mail_smtpauthtype --value={{ nextcloud_smtp_authtype }} --quiet
check_error "Failed to set mail_smtpauthtype"
occ config:system:set mail_smtpname --value='{{ nextcloud_smtp_username }}' --quiet
check_error "Failed to set mail_smtpname"
occ config:system:set mail_smtppassword --value='{{ nextcloud_smtp_password }}' --quiet
check_error "Failed to set mail_smtppassword"
{% endif %}
# Configure email addressing
occ config:system:set mail_from_address --value='{{ nextcloud_mail_from_address }}' --quiet
check_error "Failed to set mail_from_address"
occ config:system:set mail_domain --value='{{ nextcloud_mail_domain }}' --quiet
check_error "Failed to set mail_domain"
{% endif %}
# Set admin user email address
{% if nextcloud_admin_email %}
occ user:setting {{ nextcloud_admin_user }} settings email '{{ nextcloud_admin_email }}' --quiet
check_error "Failed to set admin user email"
{% endif %}
# =================================================================
# OIDC/SSO Provider Configuration
# =================================================================
{% if nextcloud_oidc_enabled | default(false) %}
# Configure OIDC provider (creates if doesn't exist, updates if exists)
occ user_oidc:provider {{ nextcloud_oidc_provider_id }} \
--clientid='{{ nextcloud_oidc_client_id }}' \
--clientsecret='{{ nextcloud_oidc_client_secret }}' \
--discoveryuri='{{ nextcloud_oidc_discovery_url }}' \
--scope='{{ nextcloud_oidc_scope }}' \
--unique-uid={{ '1' if nextcloud_oidc_unique_uid else '0' }} \
--check-bearer={{ '1' if nextcloud_oidc_check_bearer else '0' }} \
--send-id-token-hint={{ '1' if nextcloud_oidc_send_id_token_hint else '0' }} \
{% if nextcloud_oidc_mapping_display_name %}
--mapping-display-name='{{ nextcloud_oidc_mapping_display_name }}' \
{% endif %}
{% if nextcloud_oidc_mapping_email %}
--mapping-email='{{ nextcloud_oidc_mapping_email }}' \
{% endif %}
{% if nextcloud_oidc_mapping_quota %}
--mapping-quota='{{ nextcloud_oidc_mapping_quota }}' \
{% endif %}
{% if nextcloud_oidc_mapping_uid %}
--mapping-uid='{{ nextcloud_oidc_mapping_uid }}' \
{% endif %}
{% if nextcloud_oidc_mapping_groups %}
--mapping-groups='{{ nextcloud_oidc_mapping_groups }}' \
{% endif %}
--group-provisioning={{ '1' if nextcloud_oidc_group_provisioning else '0' }} \
--quiet 2>&1 | grep -v "already exists" || true
check_error "Failed to configure OIDC provider: {{ nextcloud_oidc_provider_id }}"
{% if nextcloud_oidc_single_login %}
# Enable single login (auto-redirect to SSO if only one provider)
occ config:app:set user_oidc allow_multiple_user_backends --value=0 --quiet
check_error "Failed to enable single login mode"
{% endif %}
{% endif %}
# =================================================================
# Exit Status
# =================================================================
if [ $ERRORS -gt 0 ]; then
echo "Configuration completed with $ERRORS error(s)" >&2
exit 1
else
echo "Nextcloud configuration completed successfully"
exit 0
fi

View File

@@ -1,32 +0,0 @@
<?php
/**
* Nextcloud Additional Configuration
* Rick-Infra - Nextcloud Role
*
* This file provides additional configuration for Nextcloud
* that complements the main config.php file.
*
* Applied via: php occ config:system:set
*/
$CONFIG = array(
/**
* Maintenance Window
*
* Defines a maintenance window during which resource-intensive
* operations (like database updates) can be performed.
*
* Format: Hour (0-23, UTC)
*/
'maintenance_window_start' => {{ nextcloud_maintenance_window_start }},
/**
* Default Phone Region
*
* Sets the default country code for phone number validation.
* Used when users enter phone numbers without country prefix.
*
* Format: ISO 3166-1 alpha-2 country code
*/
'default_phone_region' => '{{ nextcloud_default_phone_region }}',
);

View File

@@ -23,9 +23,6 @@ Volume={{ nextcloud_data_dir }}:/var/www/html/data:Z
# Configuration (private - contains secrets)
Volume={{ nextcloud_config_dir }}:/var/www/html/config:Z
# Custom apps (world-readable)
Volume={{ nextcloud_custom_apps_dir }}:/var/www/html/custom_apps:Z
# Infrastructure sockets (mounted with world-readable permissions on host)
Volume={{ postgresql_unix_socket_directories }}:{{ postgresql_unix_socket_directories }}:Z
Volume={{ valkey_unix_socket_path | dirname }}:{{ valkey_unix_socket_path | dirname }}:Z

View File

@@ -1,34 +0,0 @@
<?php
/**
* Redis/Valkey Caching Configuration for Nextcloud
*
* This file provides Redis caching for Nextcloud application-level operations
* (distributed cache, file locking) WITHOUT enabling Redis for PHP sessions.
*
* IMPORTANT: This overrides the default /usr/src/nextcloud/config/redis.config.php
* which checks for REDIS_HOST environment variable. We deploy this custom version
* to enable Redis caching while keeping PHP sessions file-based for stability.
*
* Why not use REDIS_HOST env var?
* - Setting REDIS_HOST enables BOTH Redis sessions AND Redis caching
* - Redis session handling can cause severe performance issues:
* * Session lock contention under high concurrency
* * Infinite lock retries blocking FPM workers
* * Timeout orphaning leaving locks unreleased
* * Worker pool exhaustion causing cascading failures
*
* This configuration provides the benefits of Redis caching (fast distributed
* cache, reliable file locking) while avoiding the pitfalls of Redis sessions.
*
* Managed by: Ansible Nextcloud role
* Template: roles/nextcloud/templates/redis.config.php.j2
*/
$CONFIG = array(
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => array(
'host' => '{{ valkey_unix_socket_path }}',
'password' => '{{ valkey_password }}',
),
);