feat: add Docker Compose configuration for Nextcloud, including services and environment variables

This commit is contained in:
martin.fencl
2026-08-06 20:50:07 +02:00
parent 4050875b8a
commit 43d910a44c
2 changed files with 388 additions and 13 deletions
@@ -0,0 +1,73 @@
services:
nextcloud:
image: nextcloud:33.0-apache
container_name: nextcloud
restart: unless-stopped
networks:
- cloud
depends_on:
- nextclouddb
- redis
ports:
- 8080:80
volumes:
- /data/compose/nextcloud/config:/var/www/html/config
- /data/compose/nextcloud/data:/var/www/html/data
- /data/compose/nextcloud/custom_apps:/var/www/html/custom_apps
environment:
- TZ=Europe/Prague
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=dbpassword
- MYSQL_HOST=nextclouddb
- REDIS_HOST=redis
- NEXTCLOUD_ADMIN_USER=root
- NEXTCLOUD_ADMIN_PASSWORD=1234SilneHeslo.-.
nextclouddb:
image: mariadb
container_name: nextcloud-db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
networks:
- cloud
volumes:
- /data/compose/nextcloud/nextclouddb:/var/lib/mysql
environment:
- TZ=Europe/Prague
- MYSQL_RANDOM_ROOT_PASSWORD=true
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=dbpassword
- MARIADB_AUTO_UPGRADE=1
redis:
image: redis:alpine
container_name: redis
restart: unless-stopped
networks:
- cloud
volumes:
- /data/compose/nextcloud/redis:/data
collabora:
image: collabora/code
container_name: collabora
restart: unless-stopped
networks:
- cloud
environment:
- TZ=Europe/Prague
- password=password
- username=nextcloud
- domain=cloud.martinfencl.eu
- extra_params=--o:ssl.enable=false --o:ssl.termination=true
- aliasgroup1=https://cloud.martinfencl.eu:443,https://collabora.martinfencl.eu:443
- dictionaries=de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru cs_CZ
ports:
- 9980:9980
networks:
cloud:
driver: bridge
+314 -12
View File
@@ -18,9 +18,24 @@
# Docker Compose configuration. # Docker Compose configuration.
nextcloud_project: "nextcloud-collabora" nextcloud_project: "nextcloud-collabora"
nextcloud_compose_file: "/data/compose/nextcloud/docker-compose-nextcloud.yml"
nextcloud_service: "nextcloud" nextcloud_service: "nextcloud"
# Compose file stored in Git.
nextcloud_compose_local_file: >-
{{ playbook_dir }}/../docker-compose/docker-compose-nextcloud.yml
# Compose file location on the Nextcloud VM.
nextcloud_compose_file: >-
/data/compose/nextcloud/docker-compose-nextcloud.yml
# Temporary Compose file on the Proxmox host.
nextcloud_compose_controller_staging_file: >-
/tmp/docker-compose-nextcloud-{{ backup_timestamp }}.yml
# Temporary Compose file on the Nextcloud VM.
nextcloud_compose_vm_staging_file: >-
/tmp/docker-compose-nextcloud-{{ backup_timestamp }}.yml
# Container names. # Container names.
nextcloud_container: "nextcloud" nextcloud_container: "nextcloud"
nextcloud_db_container: "nextcloud-db" nextcloud_db_container: "nextcloud-db"
@@ -50,6 +65,79 @@
{{ nextcloud_container | quote }} {{ nextcloud_container | quote }}
php occ maintenance:mode --off php occ maintenance:mode --off
# -------------------------------------------------------------------------
# Compose installation script
# -------------------------------------------------------------------------
compose_install_script: |
set -Eeuo pipefail
current_step="Compose installation initialization"
trap '
rc=$?
echo >&2
echo "Compose installation failed" >&2
echo "Step: ${current_step}" >&2
echo "Line: ${LINENO}" >&2
echo "Command: ${BASH_COMMAND}" >&2
echo "Return code: ${rc}" >&2
exit "${rc}"
' ERR
source_file={{ nextcloud_compose_vm_staging_file | quote }}
destination_file={{ nextcloud_compose_file | quote }}
destination_dir="$(dirname "${destination_file}")"
cleanup() {
rm -f "${source_file}"
}
trap cleanup EXIT
current_step="checking staged Compose file"
echo "Checking staged Docker Compose file"
test -s "${source_file}"
current_step="validating staged Compose file"
echo "Validating staged Docker Compose file"
{{ docker_cmd }} compose \
-p {{ nextcloud_project | quote }} \
-f "${source_file}" \
config --quiet
current_step="creating Compose destination directory"
echo "Ensuring Compose destination directory exists"
mkdir -p "${destination_dir}"
current_step="comparing Compose files"
if [ -f "${destination_file}" ] && \
cmp -s "${source_file}" "${destination_file}"
then
echo "Compose file is already up to date"
exit 0
fi
current_step="installing Compose file"
echo "Installing Compose file"
install \
-m 0644 \
"${source_file}" \
"${destination_file}"
current_step="validating installed Compose file"
echo "Validating installed Docker Compose file"
{{ docker_cmd }} compose \
-p {{ nextcloud_project | quote }} \
-f "${destination_file}" \
config --quiet
echo "Compose file updated"
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Preflight script # Preflight script
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@@ -88,6 +176,7 @@
current_step="validating Docker Compose configuration" current_step="validating Docker Compose configuration"
echo "Validating Docker Compose configuration" echo "Validating Docker Compose configuration"
{{ docker_cmd }} compose \ {{ docker_cmd }} compose \
-p {{ nextcloud_project | quote }} \ -p {{ nextcloud_project | quote }} \
-f {{ nextcloud_compose_file | quote }} \ -f {{ nextcloud_compose_file | quote }} \
@@ -101,7 +190,12 @@
{{ nextcloud_db_container | quote }} \ {{ nextcloud_db_container | quote }} \
{{ redis_container | quote }} {{ redis_container | quote }}
do do
state="$(docker inspect --format '{% raw %}{{.State.Running}}{% endraw %}' "${container}" 2>/dev/null || true)" state="$(
docker inspect \
--format '{% raw %}{{.State.Running}}{% endraw %}' \
"${container}" \
2>/dev/null || true
)"
if [ "${state}" != "true" ]; then if [ "${state}" != "true" ]; then
echo "Container ${container} is not running" >&2 echo "Container ${container} is not running" >&2
@@ -111,12 +205,14 @@
current_step="checking Nextcloud status" current_step="checking Nextcloud status"
echo "Checking Nextcloud status" echo "Checking Nextcloud status"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ status php occ status
current_step="checking MariaDB" current_step="checking MariaDB"
echo "Checking MariaDB" echo "Checking MariaDB"
{{ docker_cmd }} exec \ {{ docker_cmd }} exec \
{{ nextcloud_db_container | quote }} \ {{ nextcloud_db_container | quote }} \
sh -c ' sh -c '
@@ -133,6 +229,7 @@
current_step="checking Redis" current_step="checking Redis"
echo "Checking Redis" echo "Checking Redis"
{{ docker_cmd }} exec \ {{ docker_cmd }} exec \
{{ redis_container | quote }} \ {{ redis_container | quote }} \
redis-cli -h 127.0.0.1 ping | redis-cli -h 127.0.0.1 ping |
@@ -166,12 +263,14 @@
current_step="enabling maintenance mode" current_step="enabling maintenance mode"
echo "Enabling Nextcloud maintenance mode" echo "Enabling Nextcloud maintenance mode"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ maintenance:mode --on php occ maintenance:mode --on
current_step="creating configuration archive" current_step="creating configuration archive"
echo "Backing up Nextcloud configuration and custom applications" echo "Backing up Nextcloud configuration and custom applications"
{{ docker_cmd }} exec \ {{ docker_cmd }} exec \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
sh -c ' sh -c '
@@ -182,18 +281,21 @@
current_step="copying configuration archive" current_step="copying configuration archive"
echo "Copying configuration archive" echo "Copying configuration archive"
{{ docker_cmd }} cp \ {{ docker_cmd }} cp \
{{ nextcloud_container | quote }}:/tmp/nextcloud_conf.tgz \ {{ nextcloud_container | quote }}:/tmp/nextcloud_conf.tgz \
{{ (backup_dir ~ '/nextcloud_conf.tgz') | quote }} {{ (backup_dir ~ '/nextcloud_conf.tgz') | quote }}
current_step="removing temporary configuration archive" current_step="removing temporary configuration archive"
echo "Removing temporary configuration archive" echo "Removing temporary configuration archive"
{{ docker_cmd }} exec \ {{ docker_cmd }} exec \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
rm -f /tmp/nextcloud_conf.tgz rm -f /tmp/nextcloud_conf.tgz
current_step="creating database dump" current_step="creating database dump"
echo "Backing up Nextcloud database" echo "Backing up Nextcloud database"
{{ docker_cmd }} exec \ {{ docker_cmd }} exec \
{{ nextcloud_db_container | quote }} \ {{ nextcloud_db_container | quote }} \
sh -c ' sh -c '
@@ -220,6 +322,7 @@
current_step="disabling maintenance mode after backup" current_step="disabling maintenance mode after backup"
echo "Disabling Nextcloud maintenance mode after backup" echo "Disabling Nextcloud maintenance mode after backup"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ maintenance:mode --off php occ maintenance:mode --off
@@ -265,6 +368,7 @@
current_step="validating Docker Compose configuration" current_step="validating Docker Compose configuration"
echo "Validating Docker Compose configuration" echo "Validating Docker Compose configuration"
{{ docker_cmd }} compose \ {{ docker_cmd }} compose \
-p {{ nextcloud_project | quote }} \ -p {{ nextcloud_project | quote }} \
-f {{ nextcloud_compose_file | quote }} \ -f {{ nextcloud_compose_file | quote }} \
@@ -272,6 +376,7 @@
current_step="pulling Nextcloud image" current_step="pulling Nextcloud image"
echo "Pulling the current Nextcloud image" echo "Pulling the current Nextcloud image"
{{ docker_cmd }} compose \ {{ docker_cmd }} compose \
-p {{ nextcloud_project | quote }} \ -p {{ nextcloud_project | quote }} \
-f {{ nextcloud_compose_file | quote }} \ -f {{ nextcloud_compose_file | quote }} \
@@ -279,6 +384,7 @@
current_step="recreating Nextcloud container" current_step="recreating Nextcloud container"
echo "Recreating the Nextcloud container" echo "Recreating the Nextcloud container"
{{ docker_cmd }} compose \ {{ docker_cmd }} compose \
-p {{ nextcloud_project | quote }} \ -p {{ nextcloud_project | quote }} \
-f {{ nextcloud_compose_file | quote }} \ -f {{ nextcloud_compose_file | quote }} \
@@ -294,7 +400,12 @@
while true while true
do do
container_state="$(docker inspect --format '{% raw %}{{.State.Running}}{% endraw %}' {{ nextcloud_container | quote }} 2>/dev/null || true)" container_state="$(
docker inspect \
--format '{% raw %}{{.State.Running}}{% endraw %}' \
{{ nextcloud_container | quote }} \
2>/dev/null || true
)"
if [ "${container_state}" = "true" ]; then if [ "${container_state}" = "true" ]; then
break break
@@ -343,12 +454,14 @@
if [ "${maintenance_state}" = "true" ] || \ if [ "${maintenance_state}" = "true" ] || \
[ "${maintenance_state}" = "1" ]; then [ "${maintenance_state}" = "1" ]; then
echo "Maintenance mode is enabled; disabling it" echo "Maintenance mode is enabled; disabling it"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ maintenance:mode --off php occ maintenance:mode --off
fi fi
current_step="verifying maintenance mode before OCC upgrade" current_step="verifying maintenance mode before OCC upgrade"
maintenance_state="$( maintenance_state="$(
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
@@ -364,24 +477,28 @@
current_step="running Nextcloud database upgrade" current_step="running Nextcloud database upgrade"
echo "Running the Nextcloud database upgrade" echo "Running the Nextcloud database upgrade"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ upgrade --no-interaction php occ upgrade --no-interaction
current_step="updating Nextcloud applications" current_step="updating Nextcloud applications"
echo "Updating Nextcloud applications" echo "Updating Nextcloud applications"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ app:update --all php occ app:update --all
current_step="running Nextcloud maintenance repair" current_step="running Nextcloud maintenance repair"
echo "Running Nextcloud maintenance repair" echo "Running Nextcloud maintenance repair"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ maintenance:repair --include-expensive php occ maintenance:repair --include-expensive
current_step="reading final Nextcloud status" current_step="reading final Nextcloud status"
echo "Reading Nextcloud status" echo "Reading Nextcloud status"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ status php occ status
@@ -416,7 +533,12 @@
{{ nextcloud_db_container | quote }} \ {{ nextcloud_db_container | quote }} \
{{ redis_container | quote }} {{ redis_container | quote }}
do do
state="$(docker inspect --format '{% raw %}{{.State.Running}}{% endraw %}' "${container}" 2>/dev/null || true)" state="$(
docker inspect \
--format '{% raw %}{{.State.Running}}{% endraw %}' \
"${container}" \
2>/dev/null || true
)"
if [ "${state}" != "true" ]; then if [ "${state}" != "true" ]; then
echo "Container ${container} is not running" >&2 echo "Container ${container} is not running" >&2
@@ -426,6 +548,7 @@
current_step="checking MariaDB" current_step="checking MariaDB"
echo "Checking MariaDB after upgrade" echo "Checking MariaDB after upgrade"
{{ docker_cmd }} exec \ {{ docker_cmd }} exec \
{{ nextcloud_db_container | quote }} \ {{ nextcloud_db_container | quote }} \
sh -c ' sh -c '
@@ -442,6 +565,7 @@
current_step="checking Redis" current_step="checking Redis"
echo "Checking Redis after upgrade" echo "Checking Redis after upgrade"
{{ docker_cmd }} exec \ {{ docker_cmd }} exec \
{{ redis_container | quote }} \ {{ redis_container | quote }} \
redis-cli -h 127.0.0.1 ping | redis-cli -h 127.0.0.1 ping |
@@ -449,11 +573,13 @@
current_step="checking Nextcloud status" current_step="checking Nextcloud status"
echo "Checking Nextcloud status after upgrade" echo "Checking Nextcloud status after upgrade"
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
php occ status php occ status
current_step="checking Nextcloud maintenance state" current_step="checking Nextcloud maintenance state"
maintenance_state="$( maintenance_state="$(
{{ docker_cmd }} exec -u www-data \ {{ docker_cmd }} exec -u www-data \
{{ nextcloud_container | quote }} \ {{ nextcloud_container | quote }} \
@@ -503,6 +629,168 @@
state: present state: present
update_cache: true update_cache: true
# -------------------------------------------------------------------------
# Compose synchronization
# -------------------------------------------------------------------------
- name: Nextcloud | Check Compose file in repository
ansible.builtin.stat:
path: "{{ nextcloud_compose_local_file }}"
register: nextcloud_compose_local_stat
delegate_to: localhost
run_once: true
changed_when: false
- name: Nextcloud | Fail when repository Compose file is missing
ansible.builtin.assert:
that:
- nextcloud_compose_local_stat.stat.exists
- nextcloud_compose_local_stat.stat.isreg
- nextcloud_compose_local_stat.stat.size | int > 0
fail_msg: >-
Nextcloud Compose file is missing or empty:
{{ nextcloud_compose_local_file }}
quiet: true
run_once: true
- name: Nextcloud | Synchronize Compose file to VM
block:
- name: Nextcloud | Stage Compose file on Proxmox host
ansible.builtin.copy:
src: "{{ nextcloud_compose_local_file }}"
dest: "{{ nextcloud_compose_controller_staging_file }}"
mode: "0600"
register: nextcloud_compose_controller_copy
- name: Nextcloud | Upload Compose file to VM staging path
ansible.builtin.command:
argv:
- sshpass
- -e
- scp
- -o
- StrictHostKeyChecking=no
- -o
- UserKnownHostsFile=/dev/null
- -o
- LogLevel=ERROR
- -o
- ConnectTimeout=15
- "{{ nextcloud_compose_controller_staging_file }}"
- >-
{{ vm_user }}@{{ vm_ip }}:
{{ nextcloud_compose_vm_staging_file }}
environment:
SSHPASS: "{{ vm_password }}"
register: nextcloud_compose_upload
changed_when: nextcloud_compose_upload.rc == 0
no_log: true
- name: Nextcloud | Validate and install Compose file on VM
ansible.builtin.command:
argv:
- sshpass
- -e
- ssh
- -o
- StrictHostKeyChecking=no
- -o
- UserKnownHostsFile=/dev/null
- -o
- LogLevel=ERROR
- -o
- ConnectTimeout=15
- -o
- ServerAliveInterval=10
- -o
- ServerAliveCountMax=3
- "{{ vm_user }}@{{ vm_ip }}"
- >-
{{
('sudo -n bash -lc ' ~
(compose_install_script | quote))
if vm_use_sudo
else
('bash -lc ' ~
(compose_install_script | quote))
}}
environment:
SSHPASS: "{{ vm_password }}"
register: nextcloud_compose_install
changed_when: >-
'Compose file updated' in
(nextcloud_compose_install.stdout | default(''))
failed_when: false
no_log: true
- name: Nextcloud | Show Compose installation result
ansible.builtin.debug:
msg: |
Compose installation return code:
{{ nextcloud_compose_install.rc }}
STDOUT:
{{ nextcloud_compose_install.stdout | default('') | trim }}
STDERR:
{{ nextcloud_compose_install.stderr | default('') | trim }}
when:
- debug_level == 1 or nextcloud_compose_install.rc != 0
- name: Nextcloud | Fail when Compose installation failed
ansible.builtin.assert:
that:
- nextcloud_compose_install.rc == 0
fail_msg: |
Failed to install Nextcloud Compose file.
Source file:
{{ nextcloud_compose_local_file }}
Destination file:
{{ nextcloud_compose_file }}
Return code:
{{ nextcloud_compose_install.rc }}
STDOUT:
{{ nextcloud_compose_install.stdout | default('') | trim }}
STDERR:
{{ nextcloud_compose_install.stderr | default('') | trim }}
quiet: true
always:
- name: Nextcloud | Remove staged Compose file from Proxmox host
ansible.builtin.file:
path: "{{ nextcloud_compose_controller_staging_file }}"
state: absent
changed_when: false
- name: Nextcloud | Remove staged Compose file from VM
ansible.builtin.command:
argv:
- sshpass
- -e
- ssh
- -o
- StrictHostKeyChecking=no
- -o
- UserKnownHostsFile=/dev/null
- -o
- LogLevel=ERROR
- -o
- ConnectTimeout=15
- "{{ vm_user }}@{{ vm_ip }}"
- >-
rm -f
{{ nextcloud_compose_vm_staging_file | quote }}
environment:
SSHPASS: "{{ vm_password }}"
changed_when: false
failed_when: false
no_log: true
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Preflight # Preflight
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@@ -528,10 +816,12 @@
- "{{ vm_user }}@{{ vm_ip }}" - "{{ vm_user }}@{{ vm_ip }}"
- >- - >-
{{ {{
('sudo -n bash -lc ' ~ (preflight_script | quote)) ('sudo -n bash -lc ' ~
(preflight_script | quote))
if vm_use_sudo if vm_use_sudo
else else
('bash -lc ' ~ (preflight_script | quote)) ('bash -lc ' ~
(preflight_script | quote))
}} }}
environment: environment:
SSHPASS: "{{ vm_password }}" SSHPASS: "{{ vm_password }}"
@@ -646,10 +936,12 @@
- "{{ vm_user }}@{{ vm_ip }}" - "{{ vm_user }}@{{ vm_ip }}"
- >- - >-
{{ {{
('sudo -n bash -lc ' ~ (backup_script | quote)) ('sudo -n bash -lc ' ~
(backup_script | quote))
if vm_use_sudo if vm_use_sudo
else else
('bash -lc ' ~ (backup_script | quote)) ('bash -lc ' ~
(backup_script | quote))
}} }}
environment: environment:
SSHPASS: "{{ vm_password }}" SSHPASS: "{{ vm_password }}"
@@ -713,10 +1005,12 @@
- "{{ vm_user }}@{{ vm_ip }}" - "{{ vm_user }}@{{ vm_ip }}"
- >- - >-
{{ {{
('sudo -n bash -lc ' ~ (upgrade_script | quote)) ('sudo -n bash -lc ' ~
(upgrade_script | quote))
if vm_use_sudo if vm_use_sudo
else else
('bash -lc ' ~ (upgrade_script | quote)) ('bash -lc ' ~
(upgrade_script | quote))
}} }}
environment: environment:
SSHPASS: "{{ vm_password }}" SSHPASS: "{{ vm_password }}"
@@ -869,10 +1163,12 @@
- "{{ vm_user }}@{{ vm_ip }}" - "{{ vm_user }}@{{ vm_ip }}"
- >- - >-
{{ {{
('sudo -n bash -lc ' ~ (postcheck_script | quote)) ('sudo -n bash -lc ' ~
(postcheck_script | quote))
if vm_use_sudo if vm_use_sudo
else else
('bash -lc ' ~ (postcheck_script | quote)) ('bash -lc ' ~
(postcheck_script | quote))
}} }}
environment: environment:
SSHPASS: "{{ vm_password }}" SSHPASS: "{{ vm_password }}"
@@ -969,6 +1265,12 @@
Backup directory: Backup directory:
{{ backup_dir }} {{ backup_dir }}
Compose source:
{{ nextcloud_compose_local_file }}
Compose destination:
{{ nextcloud_compose_file }}
Installed: Installed:
{{ nc_status.json.installed | default('?') }} {{ nc_status.json.installed | default('?') }}