Nextcloud
Deploy Nextcloud hub.
Ansible hosts group: nextcloud
Variables
| Option | Type | Description | Default |
|---|---|---|---|
cs_nc_version | string | Nextcloud version | 34.0.4 |
cs_ns_version_sha | string | SHA512 checksum of the Nextcloud release archive | sha512:... |
cs_nc_public_uri | string | Public URI for Nextcloud | https://nextcloud-{{ inventory_hostname }}.<cluster domain> |
cs_nc_extra_trusted_domains | list | Extra domains to add to Nextcloud's trusted domains | [] |
cs_nc_cluster_name | string | Nextcloud cluster name | {{ cs_cluster_name }} |
cs_nc_container_root | string | Root directory for Nextcloud | /app/nextcloud |
cs_nc_web_dir | string | Web directory for Nextcloud | {{ cs_nc_container_root }}/www |
cs_nc_data_dir | string | Data directory for Nextcloud | {{ cs_nc_container_root }}/data |
cs_nc_cert_dir | string | Certificate directory | {{ cs_nc_container_root }}/certs |
cs_nc_docker_network | string | Docker network for Nextcloud containers | nextcloud |
cs_nc_php_version | string | PHP version to use | 8.4 |
cs_nc_run_user | string | User to run Nextcloud | www-data |
cs_nc_run_group | string | Group to run Nextcloud | www-data |
cs_nc_logtimezone | string | Timezone for logs | Asia/Kolkata |
cs_nc_default_phone_region | string | Default phone region | IN |
cs_nc_dns_servers | list | DNS servers for Nextcloud | The cluster's DNS servers (from Vault) |
cs_nc_trusted_proxies | list | List of trusted proxies | The cluster CIDR and VPN CIDR (from Vault) |
cs_nc_apache_template_name | string | Apache template name | 100-nextcloud |
cs_nc_cron_system_timer_name | string | Systemd timer for cron | nextcloud-cron |
cs_nc_files_scanner_systemd_timer_name | string | Systemd timer for file scanning | nextcloud-scanfiles |
cs_nc_email_regex | string | Regex for email validation | (Standard email regex) |
cs_nc_external_drive_mount_web_paths | dict | External drive mounts (see below) | {} |
cs_nc_db_database | string | Database name | nextcloud-{{ inventory_hostname }} |
cs_nc_db_cluster_name | string | Database cluster name | {{ cs_nc_cluster_name }} |
cs_nc_db_cluster_node | string | Database cluster node | {{ inventory_hostname }} |
cs_nc_cache_redis_docker_image | string | Redis docker image | {{ cs_vm_artifact_registry_containers_home }}/redis |
cs_nc_cache_redis_docker_tag | string | Redis docker tag | 8.10.0-trixie |
cs_nc_cache_redis_container_name | string | Redis container name | nextcloud-redis |
cs_nc_cache_redis_server_dir | string | Redis data directory | /app/nextcloud-redis |
cs_nc_cache_redis_timeout | float | Redis timeout | 0.5 |
cs_nc_imaginary_docker_image | string | Imaginary docker image | {{ cs_vm_artifact_registry_containers_home }}/nextcloud-aio-imaginary |
cs_nc_imaginary_docker_image_tag | string | Imaginary docker tag | 20260929_105435 |
cs_nc_imaginary_docker_container_name | string | Imaginary container name | nextcloud-aio-imaginary |
cs_collabora_docker_image | string | Collabora docker image | {{ cs_vm_artifact_registry_containers_home }}/nextcloud-aio-collabora |
cs_collabora_docker_image_tag | string | Collabora docker tag | 20260929_105435 |
cs_collabora_container_name | string | Collabora container name | nextcloud-aio-collabora |
cs_nc_fts_image | string | Full Text Search docker image | {{ cs_vm_artifact_registry_containers_home }}/nextcloud-aio-fulltextsearch |
cs_nc_fts_image_tag | string | Full Text Search docker tag | 20260929_105435 |
cs_nc_fts_container_name | string | FTS container name | nextcloud-fulltextsearch |
cs_nc_fts_index_name | string | FTS index name | nextcloud-fulltextsearch |
cs_nc_fts_systemd_worker | string | FTS systemd worker name | nextcloud-fulltextsearch-worker |
cs_nc_fts_run_user_id | int | FTS run user ID | 1000 |
cs_nc_fts_run_group_id | int | FTS run group ID | 0 |
cs_nc_fts_data_dir | string | FTS data directory | /app/nextcloud-fulltextsearch/data |
cs_nc_whiteboard_docker_image | string | Whiteboard docker image | {{ cs_vm_artifact_registry_containers_home }}/nextcloud-whiteboard |
cs_nc_whiteboard_docker_image_tag | string | Whiteboard docker tag | v2.0.0 |
cs_nc_whiteboard_docker_container_name | string | Whiteboard container name | nextcloud-whiteboard |
cs_nc_talk_docker_image | string | Talk HPB docker image | {{ cs_vm_artifact_registry_containers_home }}/nextcloud-aio-talk |
cs_nc_talk_docker_image_tag | string | Talk HPB docker tag | 20260929_105435 |
cs_nc_talk_container_name | string | Talk HPB container name | nextcloud-aio-talk |
cs_nc_talk_recording_docker_image | string | Talk recording backend docker image | {{ cs_vm_artifact_registry_containers_home }}/nextcloud-aio-talk-recording |
cs_nc_talk_recording_docker_image_tag | string | Talk recording backend docker tag | 20260929_105435 |
cs_nc_talk_recording_container_name | string | Talk recording backend container name | nextcloud-aio-talk-recording |
cs_nc_talk_trusted_ca_dir | string | Talk signaling container's trusted CA directory | {{ cs_nc_cert_dir }}/talk-trusted-ca |
cs_nc_restic_node_name | string | Restic backup node name | {{ inventory_hostname }} |
cs_nc_restic_cluster_name | string | Restic cluster name | {{ cs_nc_cluster_name }} |
cs_nc_restic_repo_name | string | Restic repository name | nextcloud |
cs_nc_external_drive_mount_web_paths
cs_nc_external_drive_mount_web_paths:
<Nextcloud Mount point name>:
group: <Nextcloud group name>
disk_path: <Path to the disk>
enable_sharing: <true|false> # optional, defaults to true
previews: <true|false> # optional, defaults to true
filesystem_check_changes: <0|1|2> # optional, defaults to 1
encoding_compatibility: <true|false> # optional, defaults to false
readonly: <true|false> # optional, defaults to true
encrypt: <true|false> # optional, defaults to false
local_mnt_nextcloud:
disk_path: /mnt/external-hdd-15/local_mnt_nextcloud
group: local_mnt_nextcloud
readonly: false
Tasks
Prepare (nextcloud_prepare)
- Installs required system packages (ffmpeg, imagemagick, php, apache2, etc.).
- Configures PHP and Apache settings, including a 16G
upload_max_filesize/post_max_sizeto allow large file uploads. - Generates SSL certificates signed by the internal Root CA.
- Configures Apache virtual host for Nextcloud and enables the required Apache modules and the PHP-FPM configuration.
- Creates the
cs_nc_docker_networkDocker network shared by the hub component containers.
Prepare DB (nextcloud_prepare_db)
- Provisions the Nextcloud PostgreSQL user and database through the PostgreSQL maintenance connection. See Prepare PostgreSQL Database for the shared process and Vault prerequisite.
Install (nextcloud_install)
- Downloads the Nextcloud binary and verifies it against a SHA512 checksum.
- Issues a client certificate from the internal Root CA and connects to PostgreSQL with
sslmode=verify-full, using the user/database created bynextcloud_prepare_db. - Performs initial Nextcloud installation via
occ maintenance:install. - Writes
config/server.config.phpwith the trusted domains, trusted proxies, and email settings. - Enables the featured apps (
encryption,admin_audit,bruteforcesettings,files_external,suspicious_login,twofactor_totp,user_ldap), turns on server-side encryption with the master key, imports the Root CA into Nextcloud, adds missing database indices, and sets the admin audit log file. - Sets up systemd timers for Nextcloud cron and file scanning.
Cache (nextcloud_cache)
- Deploys a Redis container for caching and file locking, reachable on
127.0.0.1over TLS with client certificates and an ACL file. Theredis_cache_admin_passwordandredis_cache_nextcloud_user_passwordVault values must contain only ASCII letters and digits. - Configures Nextcloud to use Redis through
config/redis.config.php.
Mount (nextcloud_mount)
- Registers each entry of
cs_nc_external_drive_mount_web_pathsas a Nextcloud external storage mount (nextcloud_files_externalmodule).
Admin (nextcloud_admin)
- Fetches admin credentials from Vault.
- Enforces two-factor authentication for every group except
admin. - Recreates the admin user from the Vault credentials (through a temporary admin user), disables every other
member of the
admingroup, and makes sure the admin user is in theadmingroup.
Hub components
- Imaginary (
nextcloud_imaginary): Docker-based image processing service. - Collabora (
nextcloud_collabora): Online office suite integration. - Full Text Search (
nextcloud_fulltextsearch): ElasticSearch-based search service. - Whiteboard (
nextcloud_whiteboard): Collaborative whiteboard service. Every run generates a new JWT secret, passes it to the Whiteboard container, and stores the same value in the whiteboard app'sjwt_secret_keysetting, which the app keeps lazy-loaded and encrypted. The run deletes any existingjwt_secret_keyrow first and writes the new one withocc config:app:set --type=string --lazy --sensitive --no-interaction. Without--type=string,occexits 0 without storing the value, because it derives the type of this setting as string plus the sensitive flag and matches none of its type cases.--no-interactionauto-confirms the type prompt that--type=stringtriggers. - Hub Bundle (
nextcloud_hub_bundle): Installs the Nextcloud apps of the hub bundle (calendar, contacts, mail, spreed, deck, groupfolders, forms, notes, notify_push, and others) that are not already installed. - Talk (
nextcloud_talk): High-performance backend (HPB) for Nextcloud Talk video calls, including signaling server, TURN relay, and the call recording backend (registered with SSL validation on, and recording consent required for all calls). The signaling server and recording backend build their config fromNC_DOMAIN/HPB_DOMAINwith no separate port variable, so both carrycs_nc_public_uri's host and port together; the TURN relay gets a bare hostname instead (TALK_HOST,TURN_DOMAIN), since Janus's TURN config rejects anything but a plain hostname or IP. The signaling container bind-mountscs_nc_talk_trusted_ca_dir(a Nextcloud-managed copy of the internal Root CA, separate from the host-wide/usr/local/share/ca-certificatesthelinux_patchingrole maintains) read-only onto the container's own/usr/local/share/ca-certificates, so its callback to Nextcloud's HTTPS endpoint trusts that CA instead of failing verification.
Users (nextcloud_users)
- Creates every user in the Vault
users_dictthat does not exist yet (with a generated password), sets its email and display name, and enables TOTP two-factor authentication for it. - Creates the groups named in
users_dictand adds or removes users so their group membership matches. - Disables every Nextcloud user that is neither in
users_dictnor the admin user. - Fails before changing anything when the admin user is listed in
users_dict, an email address does not matchcs_nc_email_regex,groupsis not a dict, or a user is in theadmingroup.
Post install (nextcloud_post_install)
- Verifies the installed version matches
cs_nc_version. - Applies the theming (name, slogan, colors, logos, background) and the server info monitoring token.
- Opens the Apache port in UFW and adds the Nextcloud fail2ban filter and jail.
- Adds missing database indices and runs
occ maintenance:repair --include-expensive.
Backup (nextcloud_restic_backup)
- Performs Restic backups of Nextcloud web directory and database: a PostgreSQL dump is written to
db_backup.sqlinsidecs_nc_container_rootfor the duration of the backup. - Backs up only
cs_nc_container_root. Few things sit outside it and are left out on purpose:cs_nc_cache_redis_server_dirand the Full Text Search data directory (cs_nc_fts_data_dir) hold only a cache and a search index rebuilt from Nextcloud's real data, so backing them up would just waste space; and any path undercs_nc_external_drive_mount_web_pathsholds the operator's own files mounted from external storage, already stored and protected independently of this repo, not data Nextcloud itself generates. - Turns maintenance mode on, then stops the
apache2/php{{ cs_nc_php_version }}-fpmservices, the cron, file scanner, and full text search worker systemd units, and the Nextcloud hub component containers (Redis cache, Full Text Search, Imaginary, Whiteboard, Collabora, Talk, Talk recording) for the duration of the backup. Afterwards it removes the database dump, restarts them, and turns maintenance mode back off, even if the backup itself fails.
Restore (nextcloud_restic_restore)
- Runs the Prepare tasks first, so the packages, PHP, Apache, certificates, and Docker network exist on a fresh host.
- Removes the Nextcloud hub component containers (Redis cache, Full Text Search, Imaginary, Whiteboard, Collabora, Talk, Talk recording), and stops and disables the
apache2/php{{ cs_nc_php_version }}-fpmservices and the Nextcloud cron timer, file scanner timer, and full text search worker systemd units, tolerating any of those units not being present on the host. - Restores the latest Restic snapshot into a temporary directory under
/app/tmp(restores can exceed 50GB, too large for the default/tmp). - Imports
db_backup.sqlfrom the restored snapshot through the shared task, see Restore PostgreSQL Database for the process. - Rsyncs the restored web directory into
cs_nc_container_root, removes the temporary directory, and resets ownership/permissions recursively.
Cleanup (dangerously_cleanup_nextcloud)
Destructive. Only runs when this exact tag is passed explicitly (it is intentionally excluded from the plain nextcloud tag) and permanently deletes Nextcloud and all of its hub component data on the host:
- Stops, disables, and deletes the Nextcloud cron, file scanner, and full text search worker systemd units.
- Removes every Docker container whose name starts with
nextcloud(Redis cache, Collabora, Imaginary, Whiteboard, Talk, Talk recording, Full Text Search) and the sharednextcloudDocker network. - Disables the Apache site and deletes its
sites-availableconfig file (theapache2service itself is left running). - Deletes the PHP-FPM systemd override config (the
php{{ cs_nc_php_version }}-fpmservice itself is left running). - Deletes the Nextcloud fail2ban filter and jail config files only.
- Deletes the UFW rules opened for the Apache port and the Talk TURN port (TCP and UDP), and the UFW rules denying the Imaginary, Whiteboard, Collabora, Talk signaling, and Talk recording ports.
- Drops the Nextcloud database through the shared task, see Delete PostgreSQL Database for the process.
- Deletes
cs_nc_container_root,cs_nc_cache_redis_server_dir, and the parent directory of the Full Text Search data directory (cs_nc_fts_data_dir).
Tags
nextcloud: Full Nextcloud deployment.nextcloud_prepare: Prepare a system for Nextcloud.nextcloud_prepare_db: Provision the Nextcloud PostgreSQL user and database.nextcloud_install: Install Nextcloud.nextcloud_cache: Configure caching.nextcloud_mount: Register the external drive mounts.nextcloud_admin: Admin configuration.nextcloud_imaginary: Setup Imaginary.nextcloud_collabora: Setup Collabora Online.nextcloud_whiteboard: Setup Whiteboard.nextcloud_talk: Setup Talk High-performance backend (signaling + TURN) and the call recording backend.nextcloud_fulltextsearch: Setup Full Text Search.nextcloud_hub_bundle: Install the hub bundle apps.nextcloud_users: Manage users and groups from Vault.nextcloud_post_install: Final verification, theming, monitoring, firewall, and fail2ban setup.nextcloud_restic_backup: Run Restic backup for Nextcloud.nextcloud_restic_restore: Restore Nextcloud's web directory and database from the latest Restic snapshot.dangerously_cleanup_nextcloud: Destructive. Stops/removes Nextcloud systemd units, Docker containers/network, Apache site, PHP-FPM override, fail2ban files, UFW rules, the PostgreSQL database, and data directories. Never included by the plainnextcloudtag.
Vault configurations
- key:
{{ cs_project_code }}/application-deployer/clusters/{{ Lab Name or Cluster name }}/hosts/{{ hostname }}/apps/nextcloud/config
{
"admin_password": "<Admin Password>",
"users_dict": {
"<User Name>": {
"display_name": "Optional",
"email": "<Proper Email mandatory>",
"groups": {
"<Group Name>": {}
}
},
"user1": {
"display_name": "My Name",
"email": "email@localhost",
"groups": {
"sd_user": {}
}
}
},
"admin_user": "<Admin Username>",
"server_info_app_token": "<Monitoring application token>",
"redis_cache_admin_password": "<Redis admin password.>",
"redis_cache_nextcloud_user_password": "<Actual password used in nextcloud>",
"apache_port": "Apache listen port for Nextcloud",
"cache_redis_server_port": "Redis server port",
"collabora_http_port": "Collabora port",
"fts_servlet_port": "FTS servlet port",
"fts_transport_port": "FTS transport port",
"imaginary_port": "Imaginary port",
"talk_port": "Talk signaling server port (localhost)",
"talk_turn_port": "Talk TURN server port (public)",
"talk_recording_port": "Talk recording backend port (localhost)",
"whiteboard_port": "Whiteboard port"
}
Deployment
uv sync --all-extras --all-packages --no-progress
uv --offline run --no-sync --no-progress ansible-galaxy install -r requirements.yml
uv --offline run --no-sync --no-progress ansible-playbook playbook.yml --tags nextcloud