feat: add basic nextcloud role
nextcloud with optional collabora base setup
This commit is contained in:
parent
19986e1205
commit
6ab3505dc8
11 changed files with 404 additions and 0 deletions
48
roles/nextcloud/defaults/main.yml
Normal file
48
roles/nextcloud/defaults/main.yml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# defaults file for nextcloud
|
||||
# Base directory configuration (inherited from base role or defined here)
|
||||
docker_compose_base_dir: /etc/docker/compose
|
||||
docker_volume_base_dir: /srv/data
|
||||
|
||||
nextcloud_service_name: nextcloud
|
||||
nextcloud_docker_compose_dir: "{{ docker_compose_base_dir }}/{{ nextcloud_service_name }}"
|
||||
nextcloud_docker_volume_dir: "{{ docker_volume_base_dir }}/{{ nextcloud_service_name }}"
|
||||
|
||||
nextcloud_domain: "nextcloud.local.test"
|
||||
nextcloud_image: "nextcloud:fpm"
|
||||
nextcloud_redis_image: "redis:latest"
|
||||
nextcloud_port: 80
|
||||
|
||||
nextcloud_postgres_image: "postgres:15"
|
||||
nextcloud_postgres_db: nextcloud
|
||||
nextcloud_postgres_user: nextcloud
|
||||
nextcloud_postgres_password: "changeme"
|
||||
|
||||
nextcloud_backend_network: nextcloud-internal
|
||||
nextcloud_traefik_network: proxy
|
||||
nextcloud_use_ssl: true
|
||||
|
||||
nextcloud_enable_collabora: true
|
||||
nextcloud_collabora_domain: "office.local.test"
|
||||
nextcloud_collabora_service_name: collabora
|
||||
nextcloud_collabora_image: collabora/code:latest
|
||||
nextcloud_collabora_disable_cert_verification: false
|
||||
|
||||
nextcloud_use_s3_storage: false
|
||||
nextcloud_s3_key: changeme
|
||||
nextcloud_s3_secret: changeme
|
||||
nextcloud_s3_region: "us-east-1"
|
||||
nextcloud_s3_bucket: nextcloud
|
||||
nextcloud_s3_host: s3.example.com
|
||||
nextcloud_s3_port: 443
|
||||
nextcloud_s3_ssl: true
|
||||
nextcloud_s3_usepath_style: true
|
||||
nextcloud_s3_autocreate: false
|
||||
|
||||
nextcloud_admin_user: admin
|
||||
nextcloud_admin_password: admin
|
||||
nextcloud_memory_limit_mb: 1024
|
||||
nextcloud_upload_limit_mb: 2048
|
||||
|
||||
nextcloud_scale_factor: 2
|
||||
7
roles/nextcloud/handlers/main.yml
Normal file
7
roles/nextcloud/handlers/main.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# handlers file for nextcloud
|
||||
- name: Restart nginx container
|
||||
community.docker.docker_container:
|
||||
name: "{{ nextcloud_docker_compose_dir | basename }}-nginx-1"
|
||||
restart: true
|
||||
17
roles/nextcloud/tasks/collabora.yml
Normal file
17
roles/nextcloud/tasks/collabora.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# tasks file for configuring Collabora in Nextcloud
|
||||
- name: Configure Collabora WOPI URL
|
||||
community.docker.docker_container_exec:
|
||||
container: "{{ nextcloud_docker_compose_dir | basename }}-nextcloud-1"
|
||||
command: php /var/www/html/occ config:app:set richdocuments wopi_url --value=https://{{ nextcloud_collabora_domain }}
|
||||
|
||||
- name: Configure certificate verification for Collabora
|
||||
community.docker.docker_container_exec:
|
||||
container: "{{ nextcloud_docker_compose_dir | basename }}-nextcloud-1"
|
||||
command: php /var/www/html/occ config:app:set richdocuments disable_certificate_verification --value={{ nextcloud_collabora_disable_cert_verification | ternary('yes', 'no') }}
|
||||
|
||||
- name: Set Collabora WOPI allowlist
|
||||
community.docker.docker_container_exec:
|
||||
container: "{{ nextcloud_docker_compose_dir | basename }}-nextcloud-1"
|
||||
command: php /var/www/html/occ config:app:set richdocuments wopi_allowlist --value=''
|
||||
63
roles/nextcloud/tasks/main.yml
Normal file
63
roles/nextcloud/tasks/main.yml
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# tasks file for nextcloud
|
||||
- name: Create docker compose directory
|
||||
file:
|
||||
path: "{{ nextcloud_docker_compose_dir }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Create nextcloud data directory
|
||||
file:
|
||||
path: "{{ nextcloud_docker_volume_dir }}/data"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Create postgres data directory
|
||||
file:
|
||||
path: "{{ nextcloud_docker_volume_dir }}/postgresql"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Create docker-compose file for nextcloud
|
||||
template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: "{{ nextcloud_docker_compose_dir }}/docker-compose.yml"
|
||||
mode: '0644'
|
||||
|
||||
- name: Create nginx template
|
||||
template:
|
||||
src: nginx.conf.j2
|
||||
dest: "{{ nextcloud_docker_compose_dir }}/nginx.conf"
|
||||
mode: '0644'
|
||||
notify: Restart nginx container
|
||||
|
||||
- name: Create database initialization script
|
||||
template:
|
||||
src: init-db.sql.j2
|
||||
dest: "{{ nextcloud_docker_compose_dir }}/init-db.sql"
|
||||
mode: '0644'
|
||||
|
||||
- name: Start nextcloud container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ nextcloud_docker_compose_dir }}"
|
||||
state: present
|
||||
|
||||
- name: Wait for Nextcloud to be ready
|
||||
ansible.builtin.shell:
|
||||
cmd: docker compose exec -T nextcloud php /var/www/html/occ status --output=json
|
||||
chdir: "{{ nextcloud_docker_compose_dir }}"
|
||||
retries: 30
|
||||
delay: 5
|
||||
register: nextcloud_ready
|
||||
until:
|
||||
- nextcloud_ready.rc == 0
|
||||
- (nextcloud_ready.stdout | from_json).installed == true
|
||||
changed_when: false
|
||||
|
||||
- name: Install nextcloud plugins
|
||||
ansible.builtin.include_tasks: plugins.yml
|
||||
|
||||
- name: Configure nextcloud collabora
|
||||
ansible.builtin.include_tasks: collabora.yml
|
||||
when: nextcloud_enable_collabora
|
||||
24
roles/nextcloud/tasks/plugins.yml
Normal file
24
roles/nextcloud/tasks/plugins.yml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# tasks file for installing Nextcloud plugins/apps
|
||||
- name: Install Collabora Online app (richdocuments)
|
||||
community.docker.docker_container_exec:
|
||||
container: "{{ nextcloud_docker_compose_dir | basename }}-nextcloud-1"
|
||||
command: php /var/www/html/occ app:install richdocuments
|
||||
register: install_collabora_result
|
||||
failed_when:
|
||||
- install_collabora_result.failed
|
||||
- '"already installed" not in install_collabora_result.stdout | default("")'
|
||||
- '"already installed" not in install_collabora_result.stderr | default("")'
|
||||
when: nextcloud_enable_collabora
|
||||
|
||||
- name: Enable Collabora Online app
|
||||
community.docker.docker_container_exec:
|
||||
container: "{{ nextcloud_docker_compose_dir | basename }}-nextcloud-1"
|
||||
command: php /var/www/html/occ app:enable richdocuments
|
||||
register: enable_collabora_result
|
||||
failed_when:
|
||||
- enable_collabora_result.failed
|
||||
- '"already enabled" not in enable_collabora_result.stdout | default("")'
|
||||
- '"already enabled" not in enable_collabora_result.stderr | default("")'
|
||||
when: nextcloud_enable_collabora
|
||||
137
roles/nextcloud/templates/docker-compose.yml.j2
Normal file
137
roles/nextcloud/templates/docker-compose.yml.j2
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
services:
|
||||
db:
|
||||
image: {{ nextcloud_postgres_image }}
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_DB: {{ nextcloud_postgres_db }}
|
||||
POSTGRES_USER: {{ nextcloud_postgres_user }}
|
||||
POSTGRES_PASSWORD: {{ nextcloud_postgres_password }}
|
||||
volumes:
|
||||
- {{ nextcloud_docker_volume_dir }}/postgresql/:/var/lib/postgresql/
|
||||
- ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro
|
||||
networks:
|
||||
- {{ nextcloud_backend_network }}
|
||||
|
||||
redis:
|
||||
image: {{ nextcloud_redis_image }}
|
||||
restart: always
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- {{ nextcloud_docker_volume_dir }}/redis/data:/data
|
||||
networks:
|
||||
- {{ nextcloud_backend_network }}
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
restart: always
|
||||
depends_on:
|
||||
- nextcloud
|
||||
volumes:
|
||||
- {{ nextcloud_docker_volume_dir }}/nextcloud/:/var/www/html:ro
|
||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
networks:
|
||||
- {{ nextcloud_backend_network }}
|
||||
- {{ nextcloud_traefik_network }}
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network={{ nextcloud_traefik_network }}
|
||||
- traefik.http.routers.{{ nextcloud_service_name }}.rule=Host(`{{ nextcloud_domain }}`)
|
||||
{% if nextcloud_use_ssl %}
|
||||
- traefik.http.routers.{{ nextcloud_service_name }}.entrypoints=websecure
|
||||
- traefik.http.routers.{{ nextcloud_service_name }}.tls=true
|
||||
{% else %}
|
||||
- traefik.http.routers.{{ nextcloud_service_name }}.entrypoints=web
|
||||
{% endif %}
|
||||
|
||||
nextcloud-cron:
|
||||
image: {{ nextcloud_image }}
|
||||
restart: always
|
||||
depends_on:
|
||||
- nextcloud
|
||||
entrypoint: /cron.sh
|
||||
environment:
|
||||
POSTGRES_HOST: db
|
||||
POSTGRES_DB: {{ nextcloud_postgres_db }}
|
||||
POSTGRES_USER: {{ nextcloud_postgres_user }}
|
||||
POSTGRES_PASSWORD: {{ nextcloud_postgres_password }}
|
||||
NEXTCLOUD_ADMIN_USER: {{ nextcloud_admin_user }}
|
||||
NEXTCLOUD_ADMIN_PASSWORD: {{ nextcloud_admin_password }}
|
||||
REDIS_HOST: redis
|
||||
PHP_MEMORY_LIMIT: {{ nextcloud_memory_limit_mb }}M
|
||||
PHP_UPLOAD_LIMIT: {{ nextcloud_upload_limit_mb }}M
|
||||
OVERWRITEPROTOCOL: https
|
||||
OVERWRITEHOST: {{ nextcloud_domain }}
|
||||
TRUSTED_PROXIES: "172.18.0.0/16 172.16.9.88/16 172.16.17.0/24 172.16.9.88"
|
||||
volumes:
|
||||
- {{ nextcloud_docker_volume_dir }}/nextcloud/:/var/www/html
|
||||
networks:
|
||||
- {{ nextcloud_backend_network }}
|
||||
|
||||
nextcloud:
|
||||
image: {{ nextcloud_image }}
|
||||
scale: {{ nextcloud_scale_factor }}
|
||||
restart: always
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
environment:
|
||||
POSTGRES_HOST: db
|
||||
POSTGRES_DB: {{ nextcloud_postgres_db }}
|
||||
POSTGRES_USER: {{ nextcloud_postgres_user }}
|
||||
POSTGRES_PASSWORD: {{ nextcloud_postgres_password }}
|
||||
NEXTCLOUD_ADMIN_USER: {{ nextcloud_admin_user }}
|
||||
NEXTCLOUD_ADMIN_PASSWORD: {{ nextcloud_admin_password }}
|
||||
REDIS_HOST: redis
|
||||
PHP_MEMORY_LIMIT: {{ nextcloud_memory_limit_mb }}M
|
||||
PHP_UPLOAD_LIMIT: {{ nextcloud_upload_limit_mb }}M
|
||||
OVERWRITEPROTOCOL: https
|
||||
OVERWRITEHOST: {{ nextcloud_domain }}
|
||||
TRUSTED_PROXIES: "172.18.0.0/16 172.16.9.88/16 172.16.17.0/24 172.16.9.88"
|
||||
{% if nextcloud_use_s3_storage %}
|
||||
OBJECTSTORE_S3_KEY: {{ nextcloud_s3_key }}
|
||||
OBJECTSTORE_S3_SECRET: {{ nextcloud_s3_secret }}
|
||||
OBJECTSTORE_S3_REGION: {{ nextcloud_s3_region }}
|
||||
OBJECTSTORE_S3_BUCKET: {{ nextcloud_s3_bucket }}
|
||||
OBJECTSTORE_S3_HOST: {{ nextcloud_s3_host }}
|
||||
OBJECTSTORE_S3_PORT: {{ nextcloud_s3_port }}
|
||||
OBJECTSTORE_S3_SSL: {{ nextcloud_s3_ssl }}
|
||||
OBJECTSTORE_S3_USEPATH_STYLE: {{ nextcloud_s3_usepath_style }}
|
||||
OBJECTSTORE_S3_AUTOCREATE: {{ nextcloud_s3_autocreate }}
|
||||
{% endif %}
|
||||
volumes:
|
||||
- {{ nextcloud_docker_volume_dir }}/nextcloud/:/var/www/html
|
||||
networks:
|
||||
- {{ nextcloud_backend_network }}
|
||||
|
||||
{% if nextcloud_enable_collabora %}
|
||||
collabora:
|
||||
image: {{ nextcloud_collabora_image }}
|
||||
restart: always
|
||||
environment:
|
||||
domain: ^{{ nextcloud_domain | replace('.', '\\.') }}$
|
||||
extra_params: >-
|
||||
--o:ssl.enable=false
|
||||
--o:ssl.termination=true
|
||||
--o:net.frame_ancestors=https://{{ nextcloud_domain }}
|
||||
cap_add:
|
||||
- MKNOD
|
||||
networks:
|
||||
- {{ nextcloud_traefik_network }}
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network={{ nextcloud_traefik_network }}
|
||||
- traefik.http.routers.{{ nextcloud_collabora_service_name }}.rule=Host(`{{ nextcloud_collabora_domain }}`)
|
||||
- traefik.http.services.{{ nextcloud_collabora_service_name }}.loadbalancer.server.port=9980
|
||||
{% if nextcloud_use_ssl %}
|
||||
- traefik.http.routers.{{ nextcloud_collabora_service_name }}.entrypoints=websecure
|
||||
- traefik.http.routers.{{ nextcloud_collabora_service_name }}.tls=true
|
||||
{% else %}
|
||||
- traefik.http.routers.{{ nextcloud_collabora_service_name }}.entrypoints=web
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
networks:
|
||||
{{ nextcloud_backend_network }}:
|
||||
{{ nextcloud_traefik_network }}:
|
||||
external: true
|
||||
10
roles/nextcloud/templates/init-db.sql.j2
Normal file
10
roles/nextcloud/templates/init-db.sql.j2
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
-- Grant necessary permissions to the Nextcloud PostgreSQL user
|
||||
-- CREATEROLE allows creating roles for Nextcloud apps
|
||||
ALTER USER {{ nextcloud_postgres_user }} WITH CREATEROLE;
|
||||
|
||||
-- Pre-create the Nextcloud database to prevent automatic user creation
|
||||
CREATE DATABASE {{ nextcloud_postgres_db }} OWNER {{ nextcloud_postgres_user }};
|
||||
|
||||
-- Grant CREATE permission on public schema in the new database
|
||||
\c {{ nextcloud_postgres_db }}
|
||||
GRANT CREATE ON SCHEMA public TO {{ nextcloud_postgres_user }};
|
||||
86
roles/nextcloud/templates/nginx.conf.j2
Normal file
86
roles/nextcloud/templates/nginx.conf.j2
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
upstream nextcloud_backend {
|
||||
{% for i in range(1, nextcloud_scale_factor + 1) %}
|
||||
server nextcloud-nextcloud-{{ i }}:9000;
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
# Serve Nextcloud files
|
||||
root /var/www/html;
|
||||
index index.php index.html /index.php$request_uri;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
types { application/javascript mjs; }
|
||||
|
||||
client_max_body_size {{ nextcloud_upload_limit_mb }}M;
|
||||
fastcgi_buffers 64 4k;
|
||||
|
||||
# Security headers
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
||||
add_header Referrer-Policy "no-referrer" always;
|
||||
|
||||
|
||||
# DAV
|
||||
location = /.well-known/carddav { return 308 https://$host/remote.php/dav; }
|
||||
location = /.well-known/caldav { return 308 https://$host/remote.php/dav; }
|
||||
|
||||
# Federated sharing / Webfinger / Nodeinfo / Host-meta
|
||||
# Forward them to index.php so Nextcloud can handle them
|
||||
location = /.well-known/webfinger { return 308 https://$host/index.php$request_uri; }
|
||||
location = /.well-known/nodeinfo { return 308 https://$host/index.php$request_uri; }
|
||||
location = /.well-known/host-meta { return 308 https://$host/index.php$request_uri; }
|
||||
location = /.well-known/host-meta.json { return 308 https://$host/index.php$request_uri; }
|
||||
location = /robots.txt { allow all; log_not_found off; access_log off; }
|
||||
# denies
|
||||
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ { deny all; }
|
||||
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { deny all; }
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php$request_uri;
|
||||
}
|
||||
|
||||
location ~ \.php(?:$|/) {
|
||||
# Only allow the front controller
|
||||
try_files $fastcgi_script_name =404;
|
||||
|
||||
include fastcgi_params;
|
||||
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
|
||||
# Pass to PHP-FPM in the nextcloud container
|
||||
fastcgi_pass nextcloud_backend;
|
||||
|
||||
# Tell Nextcloud it’s HTTPS (double proxy) and behind proxies
|
||||
fastcgi_param HTTPS on;
|
||||
fastcgi_param modHeadersAvailable true;
|
||||
fastcgi_param front_controller_active true;
|
||||
|
||||
# Preserve original host/proto from outer proxies via Traefik
|
||||
fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto;
|
||||
fastcgi_param HTTP_X_FORWARDED_HOST $http_host;
|
||||
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
|
||||
fastcgi_param HTTP_X_REAL_IP $remote_addr;
|
||||
fastcgi_intercept_errors on;
|
||||
fastcgi_request_buffering off;
|
||||
}
|
||||
|
||||
# Caching for static assets
|
||||
location ~ \.(?:css|js|mjs|woff2?|svg|gif|map)$ {
|
||||
try_files $uri /index.php$request_uri;
|
||||
expires 6M;
|
||||
access_log off;
|
||||
}
|
||||
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ {
|
||||
try_files $uri /index.php$request_uri;
|
||||
expires 6M;
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
3
roles/nextcloud/tests/inventory
Normal file
3
roles/nextcloud/tests/inventory
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
localhost
|
||||
|
||||
6
roles/nextcloud/tests/test.yml
Normal file
6
roles/nextcloud/tests/test.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
- hosts: localhost
|
||||
remote_user: root
|
||||
roles:
|
||||
- nextcloud
|
||||
3
roles/nextcloud/vars/main.yml
Normal file
3
roles/nextcloud/vars/main.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# vars file for nextcloud
|
||||
Loading…
Add table
Add a link
Reference in a new issue