Compare commits

..

26 commits

Author SHA1 Message Date
8f3f6dd3d5 Adds tasks to gather and run open background jobs on demand (run with --tags run_background_jobs) 2025-04-18 22:54:35 +02:00
23e504e481 Always teardown the Docker Compose stack before updating it (will not delete any data) 2025-04-18 21:57:59 +02:00
f36c602a0e Update all apps 2025-04-18 21:37:23 +02:00
b8acfca98e Add missing indices 2025-04-18 21:36:15 +02:00
a70efcf8e9 Runs maintenance:repair --include-expensive 2025-04-18 21:29:56 +02:00
81b86deddc Maintenance activities should run at night between 01:00-05:00 UTC 2025-04-18 21:20:37 +02:00
16304bd7c4 Sets default_phone_region 2025-04-18 21:19:52 +02:00
abbf7b50dc Docker Compose should always pull 2025-04-18 21:12:21 +02:00
93ed612a65 Explicitly handles maintenance mode around instance setup; Provides and runs database utils scripts 2025-04-18 21:11:32 +02:00
11fe863b6d Updates Nextcloud image to 31 2025-04-18 14:56:02 +02:00
a4bf1371ab Merge pull request 'Restores a /bin/sh wrapper' (#10) from restore-bin-sh-call into master
Reviewed-on: #10
2024-09-14 10:47:22 +02:00
0be8dd75b4 Restores a /bin/sh wrapper 2024-09-14 10:47:28 +02:00
abafdee753 Merge pull request 'Adds support to provision trusted_proxies; fixes docker-compose's TTY error' (#9) from feature/trusted_proxies into master
Reviewed-on: #9
2024-09-14 10:40:56 +02:00
08fb859479 Adds support to provision trusted_proxies 2024-09-14 10:39:34 +02:00
4b8ac2f48d Merge pull request 'Provides Nextcloud Hub 8 (Nextcloud 29)' (#8) from feature/nextcloud-29 into master
Reviewed-on: #8
2024-09-14 10:08:00 +02:00
365e166cbf Provides Nextcloud Hub 8 (Nextcloud 29) 2024-09-14 10:03:27 +02:00
19e2864e9b Merge pull request 'Adds task to install a list of Nextcloud apps' (#7) from feature/auto-install-apps into master
Reviewed-on: #7
2023-12-10 11:43:16 +01:00
edf24dd5a6 Adds task to install a list of Nextcloud apps 2023-12-10 11:34:42 +01:00
c3d3daa97d Merge pull request 'Switching from geerlingguy.docker to community.docker' (#6) from feature/community-docker into master
Reviewed-on: #6
2023-12-10 11:00:23 +01:00
7513615b6f Switching from geerlingguy.docker to community.docker 2023-12-10 10:41:26 +01:00
69d47f03af Merge pull request 'Various Nginx improvements' (#5) from feature/nginx-performance into master
Reviewed-on: #5
2023-12-10 10:37:05 +01:00
51636d9538 Various Nginx improvements 2023-12-10 10:35:30 +01:00
1961184f93 Fixes container restart policy 2023-10-29 21:56:57 +01:00
9ffd149c65 Adds Redis cache (#4)
Requires adding a Redis host password through `redis_host_password`.

If you are updating you existing Nextcloud, you might have to manually update the `<nextcloud-data-volume>/config/config.php` and replace `memcache...` properties with:

```
  'memcache.distributed' => '\OC\Memcache\Redis',
  'memcache.local' => '\OC\Memcache\Redis',
  'memcache.locking' => '\OC\Memcache\Redis',
  'redis' => array(
     'host' => 'redis',
     'port' => 6379,
     ),
```

Co-authored-by: Jan Beilicke <dev@jotbe.io>
Reviewed-on: #4
2023-10-29 19:40:26 +01:00
13e163913a Switches Nextcloud image to Alpine (#3)
Co-authored-by: Jan Beilicke <dev@jotbe.io>
Reviewed-on: #3
2023-10-29 11:32:14 +01:00
d860a9c086 Pins Nextcloud to version 27 and switches from Apache to Nginx to improve performance esp. of video streaming (#2)
Streaming videos had been a pain with the default Nextcloud Docker image which uses Apache. This PR will replace that Docker image with Nextcloud 27 FPM and provides an Nginx to serve the app.

Additionally, with moving from the latest Nextcloud (-Apache) image to a pinned version, it will be way clearer, which version is about to be deployed, major upgrades have to be done consciously and without skipping major versions which Nextcloud does not support.

Co-authored-by: Jan Beilicke <dev@jotbe.io>
Reviewed-on: #2
2023-10-28 23:38:27 +02:00
18 changed files with 513 additions and 158 deletions

0
LICENSE Executable file → Normal file
View file

2
README.md Executable file → Normal file
View file

@ -17,6 +17,8 @@ TODO
Dependencies
------------
- Collection: community.docker
Example Playbook
----------------

59
defaults/main.yml Executable file → Normal file
View file

@ -1,39 +1,40 @@
---
# defaults file for nextcloud
nextcloud_install_user: '{{ ansible_user }}' # This user must be present on the host
nextcloud_install_path: '/home/{{ nextcloud_install_user }}'
nextcloud_multitenant_label:
nextcloud_mariadb_root_password: changeme
nextcloud_mysql_host: mysqldb
nextcloud_mysql_database: nextcloud
mariadb_root_password: changeme
mysql_host: mysqldb
mysql_database: nextcloud
nextcloud_mariadb_user: nextcloud
nextcloud_mariadb_password: nextcloud
nextcloud_admin_user: admin
nextcloud_admin_password: mynextcloud
nextcloud_virtual_host: localhost
nextcloud_trusted_domains: "localhost {{ ansible_host }} {{ nextcloud_virtual_host }}"
nextcloud_letsencrypt_host:
nextcloud_letsencrypt_email:
nextcloud_smtp_host:
nextcloud_smtp_secure:
nextcloud_smtp_port: 25
nextcloud_smtp_authtype: PLAIN
nextcloud_smtp_name:
nextcloud_smtp_password:
nextcloud_mail_from_address:
nextcloud_mail_domain:
nextcloud_trusted_domains: localhost
nextcloud_trusted_proxies: [ '172.18.0.0/16' ]
nextcloud_default_phone_region: DE
nextcloud_database_utils:
- nextcloud-mysql-innodb-convert-row-format.sh
virtual_host: localhost
letsencrypt_host:
letsencrypt_email:
docker_user: deploy
smtp_host:
smtp_secure:
smtp_port: 25
smtp_authtype: PLAIN
smtp_name:
smtp_password:
mail_from_address:
mail_domain:
nextcloud_overwrite_cli_url:
nextcloud_overwrite_host:
nextcloud_overwrite_protocol:
nextcloud_enable_restic_compose_backup: False
nextcloud_restic_aws_access_key_id:
nextcloud_restic_aws_secret_access_key:
nextcloud_restic_repository:
nextcloud_restic_password:
nextcloud_restic_keep_daily: 7
nextcloud_restic_keep_weekly: 4
nextcloud_restic_keep_monthly: 12
nextcloud_restic_keep_yearly: 3
nextcloud_restic_cron_schedule: "0 1 * * *"
# Internal variables
nextcloud_multitenant_postfix: "{{ '_' + nextcloud_multitenant_label if (nextcloud_multitenant_label) else '' }}"
nextcloud_app_list_to_install: []
restic_aws_access_key_id:
restic_aws_secret_access_key:
restic_repository:
restic_password:
restic_keep_daily: 7
restic_keep_weekly: 4
restic_keep_monthly: 12
restic_keep_yearly: 3
restic_cron_schedule: "0 1 * * *"

View file

@ -1,3 +0,0 @@
FROM jwilder/nginx-proxy:alpine
COPY uploadsize.conf /etc/nginx/conf.d/uploadsize.conf

View file

@ -1,2 +0,0 @@
client_max_body_size 10G;
proxy_request_buffering off;

View file

@ -0,0 +1,16 @@
#!/bin/sh
# Source: https://help.nextcloud.com/t/upgrade-to-nextcloud-hub-10-31-0-0-incorrect-row-format-found-in-your-database/218366/13
# # Prompt for database credentials
# read -p "Enter Database Name: " MYSQL_DATABASE
# read -p "Enter Username: " MYSQL_USER
# read -s -p "Enter Password: " MYSQL_PASSWORD
# echo
mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" -Bse "
SELECT CONCAT('ALTER TABLE \`', TABLE_NAME, '\` ROW_FORMAT=DYNAMIC;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '$MYSQL_DATABASE'
AND ENGINE = 'InnoDB'
" | mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"

206
files/nginx.conf Normal file
View file

@ -0,0 +1,206 @@
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
types {
application/javascript js mjs;
}
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
send_timeout 3600;
tcp_nopush on;
tcp_nodelay on;
open_file_cache max=500 inactive=10m;
open_file_cache_errors on;
reset_timedout_connection on;
set_real_ip_from revproxy;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# Prevent nginx HTTP Server Detection
server_tokens off;
keepalive_timeout 65;
#gzip on;
upstream php-handler {
server nextcloud-app:9000;
}
server {
listen 80;
# HSTS settings
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
# set max upload size
client_max_body_size 512M;
# Do not limit download file size (default: 1G)
fastcgi_max_temp_file_size 0;
#fastcgi_buffers 64 4K;
fastcgi_buffers 64 64K;
fastcgi_buffer_size 256k;
fastcgi_busy_buffers_size 3840K;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
fastcgi_connect_timeout 3600;
fastcgi_cache_key $http_cookie$request_method$host$request_uri;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
gzip_disable "MSIE [1-6]\."
# Pagespeed is not supported by Nextcloud, so if your server is built
# with the `ngx_pagespeed` module, uncomment this line to disable it.
#pagespeed off;
# HTTP response headers borrowed from Nextcloud `.htaccess`
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
# Path to the root of your installation
root /var/www/html;
# Specify how to handle directories -- specifying `/index.php$request_uri`
# here as the fallback means that Nginx always exhibits the desired behaviour
# when a client requests a path that corresponds to a directory that exists
# on the server. In particular, if that directory contains an index.php file,
# that file is correctly served; if it doesn't, then the request is passed to
# the front-end controller. This consistent behaviour means that we don't need
# to specify custom rules for certain paths (e.g. images and other assets,
# `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
# `try_files $uri $uri/ /index.php$request_uri`
# always provides the desired behaviour.
index index.php index.html /index.php$request_uri;
# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 /remote.php/webdav/$is_args$args;
}
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Make a regex exception for `/.well-known` so that clients can still
# access it despite the existence of the regex rule
# `location ~ /(\.|autotest|...)` which would otherwise handle requests
# for `/.well-known`.
location ^~ /.well-known {
# The rules in this block are an adaptation of the rules
# in `.htaccess` that concern `/.well-known`.
location = /.well-known/carddav { return 301 /remote.php/dav/; }
location = /.well-known/caldav { return 301 /remote.php/dav/; }
location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
location /.well-known/pki-validation { try_files $uri $uri/ =404; }
# Let Nextcloud's API for `/.well-known` URIs handle all other
# requests by passing them to the front-end controller.
return 301 /index.php$request_uri;
}
# Rules borrowed from `.htaccess` to hide certain paths from clients
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
# Ensure this block, which passes PHP files to the PHP process, is above the blocks
# which handle static assets (as seen below). If this block is not declared first,
# then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
# to the URI, resulting in a HTTP 500 error response.
location ~ \.php(?:$|/) {
# Required for legacy support
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
#fastcgi_param HTTPS on;
fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
fastcgi_param front_controller_active true; # Enable pretty urls
fastcgi_cache_valid 404 1m;
fastcgi_cache_valid any 1h;
fastcgi_cache_methods GET HEAD;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ \.(?:css|js|svg|gif)$ {
try_files $uri /index.php$request_uri;
expires 6M; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets
}
location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets
}
# Rule borrowed from `.htaccess`
location /remote {
return 301 /remote.php$request_uri;
}
location / {
try_files $uri $uri/ /index.php$request_uri;
}
}
}

0
handlers/main.yml Executable file → Normal file
View file

1
meta/main.yml Executable file → Normal file
View file

@ -49,7 +49,6 @@ galaxy_info:
dependencies:
- geerlingguy.pip
- geerlingguy.docker
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.

259
tasks/main.yml Executable file → Normal file
View file

@ -2,72 +2,134 @@
# tasks file for nextcloud
- name: Ensure nextcloud config directory exists
file:
path: "{{ nextcloud_install_path }}/nextcloud"
path: /home/{{ docker_user }}/nextcloud
state: directory
owner: '{{ nextcloud_install_user }}'
group: '{{ nextcloud_install_user }}'
owner: '{{ docker_user }}'
group: '{{ docker_user }}'
- name: Provide nginx.conf
copy:
src: nginx.conf
dest: /home/{{ docker_user }}/nextcloud/nginx.conf
owner: "{{ docker_user }}"
group: "{{ docker_user }}"
mode: '0644'
- name: Ensure database utils scripts directory exists
file:
path: /home/{{ docker_user }}/nextcloud/utils
state: directory
owner: '{{ docker_user }}'
group: '{{ docker_user }}'
- name: Provide database utils scripts
copy:
src: "{{ item }}"
dest: /home/{{ docker_user }}/nextcloud/utils/
owner: "{{ docker_user }}"
group: "{{ docker_user }}"
mode: '0644'
loop: "{{ nextcloud_database_utils }}"
when:
- nextcloud_database_utils is defined
- nextcloud_database_utils | length > 0
- name: Provide docker-compose.yml
template:
src: templates/docker-compose.nextcloud.yml.j2
dest: "{{ nextcloud_install_path }}/nextcloud/docker-compose.yml"
owner: "{{ nextcloud_install_user }}"
group: "{{ nextcloud_install_user }}"
dest: /home/{{ docker_user }}/nextcloud/docker-compose.yml
owner: "{{ docker_user }}"
group: "{{ docker_user }}"
mode: '0644'
- name: Output docker-compose.yml
shell: cat {{ nextcloud_install_path }}/nextcloud/docker-compose.yml
shell: cat /home/{{ docker_user }}/nextcloud/docker-compose.yml
register: output
- debug:
var: output
- name: Provide compose project env vars
template:
src: templates/env.j2
dest: "{{ nextcloud_install_path }}/nextcloud/.env"
owner: "{{ nextcloud_install_user }}"
group: "{{ nextcloud_install_user }}"
mode: '0640'
tags: config
- name: Provide database env vars
template:
src: templates/db.env.j2
dest: "{{ nextcloud_install_path }}/nextcloud/db.env"
owner: "{{ nextcloud_install_user }}"
group: "{{ nextcloud_install_user }}"
copy:
dest: /home/{{ docker_user }}/nextcloud/db.env
owner: "{{ docker_user }}"
group: "{{ docker_user }}"
mode: '0640'
tags: config
content: |
# See https://github.com/docker-library/mariadb/issues/262
MYSQL_INITDB_SKIP_TZINFO=1
MYSQL_ROOT_PASSWORD={{ mariadb_root_password }}
MYSQL_DATABASE={{ mysql_database }}
MYSQL_PASSWORD={{ nextcloud_mariadb_password }}
MYSQL_USER={{ nextcloud_mariadb_user }}
- name: Provide Nextcloud env vars
template:
src: templates/nextcloud.env.j2
dest: "{{ nextcloud_install_path }}/nextcloud/nextcloud.env"
owner: "{{ nextcloud_install_user }}"
group: "{{ nextcloud_install_user }}"
copy:
dest: /home/{{ docker_user }}/nextcloud/nextcloud.env
owner: "{{ docker_user }}"
group: "{{ docker_user }}"
mode: '0640'
tags: config
content: |
VIRTUAL_HOST={{ virtual_host }}
LETSENCRYPT_HOST={{ letsencrypt_host }}
LETSENCRYPT_EMAIL={{ letsencrypt_email }}
MYSQL_HOST={{ mysql_host }}
MYSQL_DATABASE={{ mysql_database }}
MYSQL_PASSWORD={{ nextcloud_mariadb_password }}
MYSQL_USER={{ nextcloud_mariadb_user }}
NEXTCLOUD_ADMIN_USER={{ nextcloud_admin_user }}
NEXTCLOUD_ADMIN_PASSWORD={{ nextcloud_admin_password }}
NEXTCLOUD_TRUSTED_DOMAINS={{ nextcloud_trusted_domains }}
SMTP_HOST={{ smtp_host }}
SMTP_SECURE={{ smtp_secure }}
SMTP_PORT={{ smtp_port }}
SMTP_AUTHTYPE={{ smtp_authtype }}
SMTP_NAME={{ smtp_name }}
SMTP_PASSWORD={{ smtp_password }}
MAIL_FROM_ADDRESS={{ mail_from_address }}
MAIL_DOMAIN={{ mail_domain }}
REDIS_HOST=redis
REDIS_HOST_PASSWORD={{ redis_host_password }}
- name: Provide Redis env vars
copy:
dest: /home/{{ docker_user }}/nextcloud/redis.env
owner: "{{ docker_user }}"
group: "{{ docker_user }}"
mode: '0640'
content: |
REDIS_PASSWORD={{ redis_host_password }}
- name: Provide restic-compose-backup env vars
template:
src: templates/restic-compose-backup.env.j2
dest: "{{ nextcloud_install_path }}/nextcloud/restic-compose-backup.env"
owner: "{{ nextcloud_install_user }}"
group: "{{ nextcloud_install_user }}"
copy:
dest: /home/{{ docker_user }}/nextcloud/restic-compose-backup.env
owner: "{{ docker_user }}"
group: "{{ docker_user }}"
mode: '0640'
tags: config
content: |
AWS_ACCESS_KEY_ID={{ restic_aws_access_key_id }}
AWS_SECRET_ACCESS_KEY={{ restic_aws_secret_access_key }}
RESTIC_REPOSITORY={{ restic_repository }}
RESTIC_PASSWORD={{ restic_password }}
# snapshot prune rules
RESTIC_KEEP_DAILY={{ restic_keep_daily}}
RESTIC_KEEP_WEEKLY={{ restic_keep_weekly }}
RESTIC_KEEP_MONTHLY={{ restic_keep_monthly }}
RESTIC_KEEP_YEARLY={{ restic_keep_yearly }}
# Cron schedule. Run every day at 1am
CRON_SCHEDULE="{{ restic_cron_schedule }}"
when: nextcloud_enable_restic_compose_backup == true
- name: "docker-compose: Teardown existing Nextcloud service"
- name: "docker-compose: Teardown existing Nextcloud service (will keep your volumes)"
docker_compose:
project_src: "{{ nextcloud_install_path }}/nextcloud/"
project_src: "/home/{{ docker_user }}/nextcloud/"
state: absent
tags: ['never', 'teardown']
tags: ['teardown']
- name: "docker-compose: Start Nextcloud service"
docker_compose:
project_src: "{{ nextcloud_install_path }}/nextcloud/"
project_src: "/home/{{ docker_user }}/nextcloud/"
pull: true
register: output
tags: service_start
@ -76,11 +138,12 @@
- assert:
that:
- "output.ansible_facts['nextcloud-app']['nextcloud{{ nextcloud_multitenant_postfix }}_nextcloud-app_1'].state.running"
- "output.services['nextcloud-app']['nextcloud-app'].state.running"
- "output.services['web']['nextcloud_web_1'].state.running"
- name: "Get container IP"
- name: Get container IP
set_fact:
nextcloud_ip: "{{ output.ansible_facts['nextcloud-app']['nextcloud' + nextcloud_multitenant_postfix + '_nextcloud-app_1'].networks['nextcloud' + nextcloud_multitenant_postfix + '_default'].IPAddress }}"
nextcloud_ip: "{{ output.services['web']['nextcloud_web_1'].networks.nextcloud_default.IPAddress }}"
- name: "Waiting for Nextcloud container to become available"
become: false
@ -88,36 +151,128 @@
host: "{{ nextcloud_ip }}"
port: 80
- name: "docker-compose: Enable maintenance mode using occ"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ maintenance:mode --on'
- name: "docker-compose: Set overwriteprotocol using occ"
shell:
chdir: "{{ nextcloud_install_path }}/nextcloud/"
cmd: docker-compose exec -T -u www-data nextcloud{{ nextcloud_multitenant_postfix }}_nextcloud-app_1 /bin/bash -c './occ config:system:set overwriteprotocol --value="{{ nextcloud_overwrite_protocol }}"'
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ config:system:set overwriteprotocol --value="{{ nextcloud_overwrite_protocol }}"'
- name: "docker-compose: Set overwrite.cli.url using occ"
shell:
chdir: "{{ nextcloud_install_path }}/nextcloud/"
cmd: docker-compose exec -T -u www-data nextcloud{{ nextcloud_multitenant_postfix }}_nextcloud-app_1 /bin/bash -c './occ config:system:set overwrite.cli.url --value="{{ nextcloud_overwrite_cli_url }}"'
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ config:system:set overwrite.cli.url --value="{{ nextcloud_overwrite_cli_url }}"'
- name: "docker-compose: Set overwritehost using occ"
shell:
cmd: docker-compose exec -T -u www-data nextcloud{{ nextcloud_multitenant_postfix }}_nextcloud-app_1 /bin/bash -c './occ config:system:set overwritehost --value="{{ nextcloud_overwrite_host }}"'
chdir: "{{ nextcloud_install_path }}/nextcloud/"
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ config:system:set overwritehost --value="{{ nextcloud_overwrite_host }}"'
- name: "docker-compose: Set trusted_proxies using occ"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ config:system:set trusted_proxies {{ idx }} --value="{{ item }}"'
loop: "{{ nextcloud_trusted_proxies }}"
loop_control:
index_var: idx
- name: "docker-compose: Fix ownership of /var/www/html"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: "docker-compose exec -T --user root nextcloud-app /bin/sh -c 'chown -R www-data: /var/www/html'"
- name: "docker-compose: Install Nextcloud apps (will not fail)"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ app:install "{{ item }}"'
loop: "{{ nextcloud_app_list_to_install }}"
when: nextcloud_app_list_to_install | count
failed_when: false
register: nextcloud_app_install_result
- name: "Output app install result"
debug:
var: "{{ nextcloud_app_install_result }}"
- name: "docker-compose: Set default_phone_region using occ"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ config:system:set default_phone_region --value="{{ nextcloud_default_phone_region }}"'
- name: "docker-compose: Set maintenance_window_start to 1 using occ (This will run maintenance tasks between 01:00-05:00 UTC)"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ config:system:set maintenance_window_start --value=1 --type=integer'
- name: "docker-compose: Update all apps using occ"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ app:update --all'
- name: "docker-compose: Add missing indices using occ"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ db:add-missing-indices'
- name: "docker-compose: Run maintenance:repair --include-expensive using occ"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ maintenance:repair --include-expensive'
- name: "docker-compose: Run database utils"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T mysqldb /bin/sh '/opt/utils/{{ item }}'
loop: "{{ nextcloud_database_utils }}"
when:
- nextcloud_database_utils is defined
- nextcloud_database_utils | length > 0
- name: Run background jobs
tags: ['never', 'run_background_jobs']
block:
- name: Get list of background jobs
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ background-job:list --output=json'
register: background_jobs
- name: Output background jobs
debug:
msg: "{{ background_jobs.stdout }}"
- name: Run background jobs
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ background-job:execute --force-execute {{ item.id }}'
loop: "{{ background_jobs.stdout }}"
register: background_jobs_execution_result
- name: Output background jobs execution result
debug:
msg: "{{ background_jobs_execution_result }}"
- name: "docker-compose: Disable maintenance mode using occ"
shell:
chdir: /home/{{ docker_user }}/nextcloud/
cmd: docker-compose exec -T -u www-data nextcloud-app /bin/sh -c './occ maintenance:mode --off'
- name: "Test whether Nextcloud is healthy from the outside"
when: not ansible_check_mode
become: false
uri:
url: "{{ nextcloud_overwrite_cli_url }}/login"
return_content: yes
timeout: 300
validate_certs: no
register: url_check
delegate_to: localhost
until: "'Nextcloud' in url_check.content"
retries: 5
delay: 10
tags: health
- debug:
var: url_check
tags: debug
tags:
- never
- debug

View file

@ -1,6 +0,0 @@
# See https://github.com/docker-library/mariadb/issues/262
MYSQL_INITDB_SKIP_TZINFO=1
MYSQL_ROOT_PASSWORD={{ nextcloud_mariadb_root_password }}
MYSQL_DATABASE={{ nextcloud_mysql_database }}
MYSQL_PASSWORD={{ nextcloud_mariadb_password }}
MYSQL_USER={{ nextcloud_mariadb_user }}

80
templates/docker-compose.nextcloud.yml.j2 Executable file → Normal file
View file

@ -10,8 +10,9 @@ services:
image: mariadb:10.4.11
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- mysqldb{{ nextcloud_multitenant_postfix }}:/var/lib/mysql
- mysqldb:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
- ./utils/:/opt/utils:ro
env_file:
- db.env
{% if nextcloud_enable_restic_compose_backup %}
@ -21,38 +22,60 @@ services:
restart: unless-stopped
nextcloud-app:
image: nextcloud:apache
networks:
- public
- default
image: nextcloud:31-fpm-alpine
restart: unless-stopped
container_name: nextcloud-app
depends_on:
- mysqldb
- redis
volumes:
- nextcloud{{ nextcloud_multitenant_postfix }}:/var/www/html
- nextcloud:/var/www/html
- /etc/localtime:/etc/localtime:ro
env_file:
- nextcloud.env
redis:
image: bitnami/redis:latest
restart: unless-stopped
volumes:
- redis:/data
env_file:
- redis.env
web:
image: nginx
restart: unless-stopped
depends_on:
- nextcloud-app
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- /etc/localtime:/etc/localtime:ro
- nextcloud:/var/www/html
networks:
- public
- default
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_public"
- "traefik.http.routers.nextcloud{{ nextcloud_multitenant_postfix }}.rule=Host(`{{ nextcloud_virtual_host }}`)"
- "traefik.http.routers.nextcloud{{ nextcloud_multitenant_postfix }}.entrypoints=websecure"
- "traefik.http.routers.nextcloud{{ nextcloud_multitenant_postfix }}.tls=true"
- "traefik.http.routers.nextcloud{{ nextcloud_multitenant_postfix }}.tls.certresolver=defaultresolver"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-rep.redirectregex.regex=https://(.*)/.well-known/(card|cal)dav"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-rep.redirectregex.replacement=https://$$1/remote.php/dav/"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-rep.redirectregex.permanent=true"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.SSLRedirect=true"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.browserXSSFilter=true"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.forceSTSHeader=true"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.STSSeconds=315360000"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.STSIncludeSubdomains=true"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.STSPreload=true"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.featurePolicy=payment 'none'"
- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}.headers.customFrameOptionsValue=SAMEORIGIN"
#- "traefik.http.middlewares.nextcloud{{ nextcloud_multitenant_postfix }}-headers.headers.contentSecurityPolicy=default-src 'self'; img-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; block-all-mixed-content"
- "traefik.http.routers.nextcloud{{ nextcloud_multitenant_postfix }}.middlewares=nextcloud{{ nextcloud_multitenant_postfix }}-rep,nextcloud{{ nextcloud_multitenant_postfix }}-headers"
- "traefik.http.routers.nextcloud.rule=Host(`{{ nextcloud_virtual_host }}`)"
- "traefik.http.routers.nextcloud.entrypoints=websecure"
- "traefik.http.routers.nextcloud.tls=true"
- "traefik.http.routers.nextcloud.tls.certresolver=defaultresolver"
- "traefik.http.middlewares.nextcloud-rep.redirectregex.regex=https://(.*)/.well-known/(card|cal)dav"
- "traefik.http.middlewares.nextcloud-rep.redirectregex.replacement=https://$$1/remote.php/dav/"
- "traefik.http.middlewares.nextcloud-rep.redirectregex.permanent=true"
- "traefik.http.middlewares.nextcloud-headers.headers.SSLRedirect=true"
- "traefik.http.middlewares.nextcloud-headers.headers.browserXSSFilter=true"
- "traefik.http.middlewares.nextcloud-headers.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.nextcloud-headers.headers.forceSTSHeader=true"
- "traefik.http.middlewares.nextcloud-headers.headers.STSSeconds=315360000"
- "traefik.http.middlewares.nextcloud-headers.headers.STSIncludeSubdomains=true"
- "traefik.http.middlewares.nextcloud-headers.headers.STSPreload=true"
- "traefik.http.middlewares.nextcloud-headers.headers.featurePolicy=payment 'none'"
- "traefik.http.middlewares.nextcloud-headers.headers.referrerPolicy=no-referrer"
- "traefik.http.middlewares.nextcloud.headers.customFrameOptionsValue=SAMEORIGIN"
#- "traefik.http.middlewares.nextcloud-headers.headers.contentSecurityPolicy=default-src 'self'; img-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; block-all-mixed-content"
- "traefik.http.routers.nextcloud.middlewares=nextcloud-rep,nextcloud-headers"
{% if nextcloud_enable_restic_compose_backup %}
- "restic-compose-backup.volumes=true"
- "restic-compose-backup.volumes.include=nextcloud"
@ -69,12 +92,13 @@ services:
# We need to communicate with docker
- /var/run/docker.sock:/tmp/docker.sock:ro
# Persistent storage of restic cache (greatly speeds up all restic operations)
- backup-cache{{ nextcloud_multitenant_postfix }}:/cache
- backup-cache:/cache
{% endif %}
volumes:
mysqldb{{ nextcloud_multitenant_postfix }}:
nextcloud{{ nextcloud_multitenant_postfix }}:
mysqldb:
redis:
nextcloud:
{% if nextcloud_enable_restic_compose_backup %}
backup-cache{{ nextcloud_multitenant_postfix }}:
backup-cache:
{% endif %}

View file

@ -1,5 +0,0 @@
#
# Docker Compose configuration
#
# Project name for this Docker Compose setup
COMPOSE_PROJECT_NAME=nextcloud{{ nextcloud_multitenant_postfix }}

View file

@ -1,21 +0,0 @@
# See https://github.com/nextcloud/docker/ for available env vars
VIRTUAL_HOST={{ nextcloud_virtual_host }}
LETSENCRYPT_HOST={{ nextcloud_letsencrypt_host }}
LETSENCRYPT_EMAIL={{ nextcloud_letsencrypt_email }}
MYSQL_HOST={{ nextcloud_mysql_host }}
MYSQL_DATABASE={{ nextcloud_mysql_database }}
MYSQL_PASSWORD={{ nextcloud_mariadb_password }}
MYSQL_USER={{ nextcloud_mariadb_user }}
NEXTCLOUD_ADMIN_USER={{ nextcloud_admin_user }}
NEXTCLOUD_ADMIN_PASSWORD={{ nextcloud_admin_password }}
NEXTCLOUD_TRUSTED_DOMAINS={{ nextcloud_trusted_domains }}
OVERWRITEPROTOCOL=https
OVERWRITECLIURL=https://{{ nextcloud_virtual_host }}
SMTP_HOST={{ nextcloud_smtp_host }}
SMTP_SECURE={{ nextcloud_smtp_secure }}
SMTP_PORT={{ nextcloud_smtp_port }}
SMTP_AUTHTYPE={{ nextcloud_smtp_authtype }}
SMTP_NAME={{ nextcloud_smtp_name }}
SMTP_PASSWORD={{ nextcloud_smtp_password }}
MAIL_FROM_ADDRESS={{ nextcloud_mail_from_address }}
MAIL_DOMAIN={{ nextcloud_mail_domain }}

View file

@ -1,11 +0,0 @@
AWS_ACCESS_KEY_ID={{ nextcloud_restic_aws_access_key_id }}
AWS_SECRET_ACCESS_KEY={{ nextcloud_restic_aws_secret_access_key }}
RESTIC_REPOSITORY={{ nextcloud_restic_repository }}
RESTIC_PASSWORD={{ nextcloud_restic_password }}
# snapshot prune rules
RESTIC_KEEP_DAILY={{ nextcloud_restic_keep_daily}}
RESTIC_KEEP_WEEKLY={{ nextcloud_restic_keep_weekly }}
RESTIC_KEEP_MONTHLY={{ nextcloud_restic_keep_monthly }}
RESTIC_KEEP_YEARLY={{ nextcloud_restic_keep_yearly }}
# Cron schedule. Run every day at 1am
CRON_SCHEDULE="{{ nextcloud_restic_cron_schedule }}"

0
tests/inventory Executable file → Normal file
View file

0
tests/test.yml Executable file → Normal file
View file

0
vars/main.yml Executable file → Normal file
View file