summaryrefslogtreecommitdiff
path: root/roles/apps/nextcloud
diff options
context:
space:
mode:
Diffstat (limited to 'roles/apps/nextcloud')
-rw-r--r--roles/apps/nextcloud/base/defaults/main.yml9
-rw-r--r--roles/apps/nextcloud/base/tasks/main.yml51
-rw-r--r--roles/apps/nextcloud/base/templates/cron@.service.j2 (renamed from roles/apps/nextcloud/templates/cron@.service.j2)2
-rwxr-xr-xroles/apps/nextcloud/base/templates/nextcloud-cron.j219
-rwxr-xr-xroles/apps/nextcloud/base/templates/nextcloud-occ.j2 (renamed from roles/apps/nextcloud/templates/nextcloud-occ.j2)2
-rwxr-xr-xroles/apps/nextcloud/base/templates/nextcloud-upgrade.j2 (renamed from roles/apps/nextcloud/templates/nextcloud-upgrade.j2)21
-rw-r--r--roles/apps/nextcloud/defaults/main.yml31
-rw-r--r--roles/apps/nextcloud/instance/defaults/main.yml9
-rw-r--r--roles/apps/nextcloud/instance/tasks/custom-image.yml (renamed from roles/apps/nextcloud/tasks/custom-image.yml)14
-rw-r--r--roles/apps/nextcloud/instance/tasks/main.yml196
-rw-r--r--roles/apps/nextcloud/instance/templates/apache-site.conf.j220
-rw-r--r--roles/apps/nextcloud/instance/templates/cron-.timer.j29
-rw-r--r--roles/apps/nextcloud/instance/templates/pod-spec-with-mariadb.yml.j2110
-rw-r--r--roles/apps/nextcloud/instance/templates/upgrade.sh.j277
-rw-r--r--roles/apps/nextcloud/meta/main.yml3
-rw-r--r--roles/apps/nextcloud/tasks/main.yml239
-rw-r--r--roles/apps/nextcloud/templates/apache-site.conf.j210
-rw-r--r--roles/apps/nextcloud/templates/cron-.timer.j29
-rw-r--r--roles/apps/nextcloud/templates/pod-spec-with-mariadb.yml.j2101
-rw-r--r--roles/apps/nextcloud/templates/run-cron.sh.j27
20 files changed, 536 insertions, 403 deletions
diff --git a/roles/apps/nextcloud/base/defaults/main.yml b/roles/apps/nextcloud/base/defaults/main.yml
new file mode 100644
index 00000000..1a8a6d52
--- /dev/null
+++ b/roles/apps/nextcloud/base/defaults/main.yml
@@ -0,0 +1,9 @@
+---
+nextcloud_app_uid: "950"
+nextcloud_app_gid: "950"
+
+nextcloud_db_uid: "951"
+nextcloud_db_gid: "951"
+
+nextcloud_redis_uid: "952"
+nextcloud_redis_gid: "952"
diff --git a/roles/apps/nextcloud/base/tasks/main.yml b/roles/apps/nextcloud/base/tasks/main.yml
new file mode 100644
index 00000000..4c85a35c
--- /dev/null
+++ b/roles/apps/nextcloud/base/tasks/main.yml
@@ -0,0 +1,51 @@
+---
+- name: add group for nextcloud app
+ group:
+ name: nc-app
+ gid: "{{ nextcloud_app_gid }}"
+
+- name: add user for nextcloud app
+ user:
+ name: nc-app
+ uid: "{{ nextcloud_app_uid }}"
+ group: nc-app
+ password: "!"
+
+- name: add group for nextcloud db
+ group:
+ name: nc-db
+ gid: "{{ nextcloud_db_gid }}"
+
+- name: add user for nextcloud db
+ user:
+ name: nc-db
+ uid: "{{ nextcloud_db_uid }}"
+ group: nc-db
+ password: "!"
+
+- name: add group for nextcloud redis
+ group:
+ name: nc-redis
+ gid: "{{ nextcloud_redis_gid }}"
+
+- name: add user for nextcloud redis
+ user:
+ name: nc-redis
+ uid: "{{ nextcloud_redis_uid }}"
+ group: nc-redis
+ password: "!"
+
+- name: install template systemd unit for cron trigger
+ template:
+ src: cron@.service.j2
+ dest: /etc/systemd/system/nextcloud-cron@.service
+
+- name: install management scripts
+ loop:
+ - nextcloud-upgrade
+ - nextcloud-occ
+ - nextcloud-cron
+ template:
+ src: "{{ item }}.j2"
+ dest: "/usr/local/bin/{{ item }}"
+ mode: 0755
diff --git a/roles/apps/nextcloud/templates/cron@.service.j2 b/roles/apps/nextcloud/base/templates/cron@.service.j2
index 822f64b4..d8cde0a3 100644
--- a/roles/apps/nextcloud/templates/cron@.service.j2
+++ b/roles/apps/nextcloud/base/templates/cron@.service.j2
@@ -3,7 +3,7 @@ Description=Nextcloud cron.php job for %i
[Service]
Type=oneshot
-ExecStart={{ nextcloud_base_path }}/%i/config/run-cron.sh
+ExecStart=/usr/local/bin/nextcloud-cron %i
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
diff --git a/roles/apps/nextcloud/base/templates/nextcloud-cron.j2 b/roles/apps/nextcloud/base/templates/nextcloud-cron.j2
new file mode 100755
index 00000000..cf1d9715
--- /dev/null
+++ b/roles/apps/nextcloud/base/templates/nextcloud-cron.j2
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+INST_NAME="$1"
+shift
+
+if [ -z "$INST_NAME" ]; then
+ echo "Usage: $0 <instance>"
+ exit 1
+fi
+
+set -eu
+
+pod_id=$(crictl pods -q --state ready --name "^nextcloud-$INST_NAME-{{ ansible_nodename }}$")
+if [ -z "$pod_id" ]; then echo "Pod not found"; exit 1; fi
+
+container_id=$(crictl ps -q --name '^nextcloud$' -p "$pod_id")
+if [ -z "$container_id" ]; then echo "Container not found"; exit 1; fi
+
+exec crictl exec "$container_id" bash -c 'php -f /var/www/html/occ status -e; if [ $? -eq 0 ]; then php -f /var/www/html/cron.php; else echo "not running cron script when in maintenance mode"; fi'
diff --git a/roles/apps/nextcloud/templates/nextcloud-occ.j2 b/roles/apps/nextcloud/base/templates/nextcloud-occ.j2
index f12f1259..01383c95 100755
--- a/roles/apps/nextcloud/templates/nextcloud-occ.j2
+++ b/roles/apps/nextcloud/base/templates/nextcloud-occ.j2
@@ -16,4 +16,4 @@ if [ -z "$pod_id" ]; then echo "Pod not found"; exit 1; fi
container_id=$(crictl ps -q --name '^nextcloud$' -p "$pod_id")
if [ -z "$container_id" ]; then echo "Container not found"; exit 1; fi
-exec crictl exec -it "$container_id" php /var/www/html/occ $@
+exec crictl exec -it "$container_id" php -f /var/www/html/occ $@
diff --git a/roles/apps/nextcloud/templates/nextcloud-upgrade.j2 b/roles/apps/nextcloud/base/templates/nextcloud-upgrade.j2
index f59f3be6..f6edcb44 100755
--- a/roles/apps/nextcloud/templates/nextcloud-upgrade.j2
+++ b/roles/apps/nextcloud/base/templates/nextcloud-upgrade.j2
@@ -9,6 +9,13 @@ fi
set -eu
+CURRENT_VERSION=$(nextcloud-occ "$INST_NAME" status -n --no-warnings --output plain | tr -d '\r' | awk -F : '/versionstring/ { print($2) }' | tr -d ' ')
+if [ "$CURRENT_VERSION" = "$VERSION" ]; then
+ echo "The current running version of nextcloud is already $CURRENT_VERSION, nothing to do here."
+ exit 0
+fi
+echo "will upgrade nextcloud instance $INST_NAME from '$CURRENT_VERSION' to '$VERSION'"
+
K8S_CONFIG_HASH_D="/etc/kubernetes/config-hashes/"
K8S_CONFIG_HASH_FILE="$K8S_CONFIG_HASH_D/nextcloud-$INST_NAME.yml"
K8S_MANIFEST_D="/etc/kubernetes/manifests/"
@@ -24,7 +31,7 @@ function cleanup {
}
trap cleanup EXIT
-IMAGE_BUILD_D="{{ nextcloud_base_path }}/$INST_NAME/build"
+IMAGE_BUILD_D=$(cat "$K8S_CONFIG_HASH_FILE" | grep "build/Dockerfile:" | tr -d ":" | xargs dirname)
IMAGE_NAME="nextcloud"
if [ -e "$IMAGE_BUILD_D/Dockerfile" ]; then
## this only works if docker is installed...
@@ -40,15 +47,9 @@ else
crictl pull "docker.io/library/nextcloud:$VERSION"
echo ""
fi
-{% if nextcloud_zfs is defined %}
-echo "*** creating ZFS snapshot"
-echo ""
-
-IMAGE_NAME_ESCAPED=${IMAGE_NAME/\//\\/}
-CURRENT_VERSION=$(cat "$K8S_MANIFEST_FILE" | awk '/image: "'"$IMAGE_NAME_ESCAPED"':.*"/ { print($2) }' | tr -d '"' | cut -d ':' -f 2)
-zfs snapshot "{{ nextcloud_zfs.pool }}/{{ nextcloud_zfs.name }}/$INST_NAME@upgrade_$CURRENT_VERSION-to-$VERSION""_$(date '+%Y-%m-%m_%H:%M:%S')"
-{% endif %}
+INSTANCE_BASE_D=$(dirname "$IMAGE_BUILD_D")
+"$INSTANCE_BASE_D/upgrade.sh" prepare "$CURRENT_VERSION" "$VERSION"
echo "*** Rebuilding config-hash file"
echo ""
@@ -68,4 +69,6 @@ cat "$TMP_D/config-hash.yml" > "$K8S_CONFIG_HASH_FILE"
cat "$TMP_D/manifest.yml" > "$K8S_MANIFEST_FILE"
echo ""
+"$INSTANCE_BASE_D/upgrade.sh" finalize "$CURRENT_VERSION" "$VERSION"
+
exit 0
diff --git a/roles/apps/nextcloud/defaults/main.yml b/roles/apps/nextcloud/defaults/main.yml
index f194a6f9..631b0a0a 100644
--- a/roles/apps/nextcloud/defaults/main.yml
+++ b/roles/apps/nextcloud/defaults/main.yml
@@ -1,31 +1,11 @@
---
-nextcloud_app_uid: "950"
-nextcloud_app_gid: "950"
-
-nextcloud_db_uid: "951"
-nextcloud_db_gid: "951"
-
-nextcloud_redis_uid: "952"
-nextcloud_redis_gid: "952"
-
-# nextcloud_base_path: /srv/nextcloud
-
-# nextcloud_zfs:
-# pool: storage
-# name: nextcloud
-# properties:
-# compression: lz4
-
# nextcloud_instances:
# example:
# new: yes
# version: 17.0.0
# port: 8100
-# hostnames:
-# - wolke.example.com
-# - cloud.example.com
-# zfs_properties:
-# quota: 100G
+# storage:
+# type: ...
# database:
# type: mariadb
# version: 10.4.8
@@ -34,3 +14,10 @@ nextcloud_redis_gid: "952"
# from: foo/bar:1.0 # optional
# dockerfile: |
# RUN apt-get install ...
+# publish:
+# zone: "{{ apps_publish_zone__foo }}"
+# hostnames:
+# - wolke.example.com
+# - cloud.example.com
+# tls:
+# certificate_provider: ...
diff --git a/roles/apps/nextcloud/instance/defaults/main.yml b/roles/apps/nextcloud/instance/defaults/main.yml
new file mode 100644
index 00000000..1a8a6d52
--- /dev/null
+++ b/roles/apps/nextcloud/instance/defaults/main.yml
@@ -0,0 +1,9 @@
+---
+nextcloud_app_uid: "950"
+nextcloud_app_gid: "950"
+
+nextcloud_db_uid: "951"
+nextcloud_db_gid: "951"
+
+nextcloud_redis_uid: "952"
+nextcloud_redis_gid: "952"
diff --git a/roles/apps/nextcloud/tasks/custom-image.yml b/roles/apps/nextcloud/instance/tasks/custom-image.yml
index 3d9e31d1..f9e130a2 100644
--- a/roles/apps/nextcloud/tasks/custom-image.yml
+++ b/roles/apps/nextcloud/instance/tasks/custom-image.yml
@@ -1,31 +1,31 @@
---
- name: create build directory for custom image
file:
- path: "{{ nextcloud_base_path }}/{{ item.key }}/build"
+ path: "{{ nextcloud_instance_basepath }}/build"
state: directory
- name: generate Dockerfile for custom image
copy:
content: |
- FROM {{ item.value.custom_image.from | default('nextcloud:' + item.value.version) }}
+ FROM {{ nextcloud_instances[nextcloud_instance].custom_image.from | default('nextcloud:' + nextcloud_instances[nextcloud_instance].version) }}
RUN set -x \
&& addgroup --gid {{ nextcloud_app_gid }} nc-app \
&& adduser --uid {{ nextcloud_app_uid }} --gid {{ nextcloud_app_gid }} --system --no-create-home --home /var/www/html --disabled-login --disabled-password nc-app
- {% if 'custom_image' in item.value %}
+ {% if 'custom_image' in nextcloud_instances[nextcloud_instance] %}
- {{ item.value.custom_image.dockerfile }}
+ {{ nextcloud_instances[nextcloud_instance].custom_image.dockerfile }}
{% endif %}
- dest: "{{ nextcloud_base_path }}/{{ item.key }}/build/Dockerfile"
+ dest: "{{ nextcloud_instance_basepath }}/build/Dockerfile"
register: nextcloud_custom_image_docker
- name: build custom image
docker_image:
- name: "nextcloud/{{ item.key }}:{{ item.value.version }}"
+ name: "nextcloud/{{ nextcloud_instance }}:{{ nextcloud_instances[nextcloud_instance].version }}"
state: present
force_source: "{{ nextcloud_custom_image_docker is changed }}"
source: build
build:
- path: "{{ nextcloud_base_path }}/{{ item.key }}/build"
+ path: "{{ nextcloud_instance_basepath }}/build"
network: host
pull: yes
diff --git a/roles/apps/nextcloud/instance/tasks/main.yml b/roles/apps/nextcloud/instance/tasks/main.yml
new file mode 100644
index 00000000..71a3ee79
--- /dev/null
+++ b/roles/apps/nextcloud/instance/tasks/main.yml
@@ -0,0 +1,196 @@
+---
+- name: prepare storage volume
+ vars:
+ storage_volume: "{{ nextcloud_instances[nextcloud_instance].storage }}"
+ include_role:
+ name: "storage/{{ nextcloud_instances[nextcloud_instance].storage.type }}/volume"
+
+- set_fact:
+ nextcloud_instance_basepath: "{{ storage_volume_mountpoint }}"
+
+- name: create nextcloud app subdirectory
+ file:
+ path: "{{ nextcloud_instance_basepath }}/nextcloud"
+ owner: "{{ nextcloud_app_uid }}"
+ group: "{{ nextcloud_app_gid }}"
+ state: directory
+
+- name: create nextcloud database subdirectory
+ file:
+ path: "{{ nextcloud_instance_basepath }}/{{ nextcloud_instances[nextcloud_instance].database.type }}"
+ owner: "{{ nextcloud_db_uid }}"
+ group: "{{ nextcloud_db_gid }}"
+ state: directory
+
+- name: create nextcloud redis subdirectory
+ file:
+ path: "{{ nextcloud_instance_basepath }}/redis"
+ owner: "{{ nextcloud_redis_uid }}"
+ group: "{{ nextcloud_redis_gid }}"
+ state: directory
+
+
+- name: create auxiliary config directory
+ file:
+ path: "{{ nextcloud_instance_basepath }}/config"
+ state: directory
+
+- name: create apache vhost config
+ template:
+ src: apache-site.conf.j2
+ dest: "{{ nextcloud_instance_basepath }}/config/apache-site.conf"
+
+- name: configure apache to run on port 8080 only
+ copy:
+ content: |
+ Listen 8080
+ dest: "{{ nextcloud_instance_basepath }}/config/ports.conf"
+
+
+- name: create tls directory
+ file:
+ path: "{{ nextcloud_instance_basepath }}/tls"
+ owner: "{{ nextcloud_app_uid }}"
+ group: "{{ nextcloud_app_gid }}"
+ mode: 0500
+ state: directory
+
+- name: generate/install TLS certificates for publishment
+ vars:
+ x509_certificate_name: "nextcloud-{{ nextcloud_instance }}_publish"
+ x509_certificate_hostnames: []
+ x509_certificate_config:
+ ca: "{{ nextcloud_instances[nextcloud_instance].publish.zone.certificate_ca_config }}"
+ cert:
+ common_name: "nextcloud-{{ nextcloud_instance }}.{{ inventory_hostname }}"
+ extended_key_usage:
+ - serverAuth
+ extended_key_usage_critical: yes
+ create_subject_key_identifier: yes
+ not_after: +100w
+ x509_certificate_renewal:
+ install:
+ - dest: "{{ nextcloud_instance_basepath }}/tls/cert.pem"
+ src:
+ - cert
+ owner: "{{ nextcloud_app_uid }}"
+ mode: "0400"
+ - dest: "{{ nextcloud_instance_basepath }}/tls/key.pem"
+ src:
+ - key
+ owner: "{{ nextcloud_app_uid }}"
+ mode: "0400"
+ include_role:
+ name: "x509/{{ nextcloud_instances[nextcloud_instance].publish.zone.certificate_provider }}/cert"
+
+
+- name: build custom image
+ # when: "'custom_image' in nextcloud_instances[nextcloud_instance]"
+ include_tasks: custom-image.yml
+
+- name: install pod manifest
+ vars:
+ kubernetes_standalone_pod:
+ name: "nextcloud-{{ nextcloud_instance }}"
+ spec: "{{ lookup('template', 'pod-spec-with-{{ nextcloud_instances[nextcloud_instance].database.type }}.yml.j2') }}"
+ mode: "0600"
+ config_hash_items:
+ - path: "{{ nextcloud_instance_basepath }}/config/apache-site.conf"
+ properties:
+ - checksum
+ - path: "{{ nextcloud_instance_basepath }}/config/ports.conf"
+ properties:
+ - checksum
+ - path: "{{ nextcloud_instance_basepath }}/build/Dockerfile"
+ properties:
+ - checksum
+ include_role:
+ name: kubernetes/standalone/pod
+
+
+- name: install upgrade helper script
+ template:
+ src: upgrade.sh.j2
+ dest: "{{ nextcloud_instance_basepath }}/upgrade.sh"
+ mode: 0755
+
+
+- name: install systemd timer unit
+ template:
+ src: cron-.timer.j2
+ dest: "/etc/systemd/system/nextcloud-cron-{{ nextcloud_instance }}.timer"
+
+- name: start/enable cron trigger systemd timer
+ systemd:
+ daemon_reload: yes
+ name: "nextcloud-cron-{{ nextcloud_instance }}.timer"
+ state: started
+ enabled: yes
+
+
+- name: configure nginx vhost for publishment
+ vars:
+ nginx_vhost__yaml: |
+ name: "nextcloud-{{ nextcloud_instance }}.{{ inventory_hostname }}"
+ template: generic
+ {% if 'tls' in nextcloud_instances[nextcloud_instance].publish %}
+ tls:
+ {{ nextcloud_instances[nextcloud_instance].publish.tls | to_nice_yaml(indent=2) | indent(2) }}
+ {% endif %}
+ hostnames:
+ {% for hostname in nextcloud_instances[nextcloud_instance].publish.hostnames %}
+ - {{ hostname }}
+ {% endfor %}
+ locations:
+ '/':
+ {% if nextcloud_instances[nextcloud_instance].publish.zone.publisher == inventory_hostname %}
+ proxy_pass: "https://127.0.0.1:{{ nextcloud_instances[nextcloud_instance].port }}"
+ {% else %}
+ proxy_pass: "https://{{ ansible_default_ipv4.address }}:{{ nextcloud_instances[nextcloud_instance].port }}"
+ {% endif %}
+ proxy_redirect:
+ - redirect: "https://$host:8080/"
+ replacement: "https://$host/"
+ proxy_ssl:
+ trusted_certificate: "/etc/ssl/apps-publish-{{ nextcloud_instances[nextcloud_instance].publish.zone.name }}/apps-publish-{{ nextcloud_instances[nextcloud_instance].publish.zone.name }}-ca-crt.pem"
+ verify: "on"
+ name: "nextcloud-{{ nextcloud_instance }}.{{ inventory_hostname }}"
+ protocols: "TLSv1.3"
+ extra_directives: |-
+ client_max_body_size 0;
+ types {
+ text/javascript js mjs;
+ }
+ nginx_vhost: "{{ nginx_vhost__yaml | from_yaml }}"
+ include_role:
+ name: nginx/vhost
+ apply:
+ delegate_to: "{{ nextcloud_instances[nextcloud_instance].publish.zone.publisher }}"
+
+
+# TODO:
+# do this automatically!
+- name: print info for new instance
+ when: "'new' in nextcloud_instances[nextcloud_instance] and nextcloud_instances[nextcloud_instance].new"
+ pause:
+ seconds: 5
+ prompt: |
+ ************* {{ nextcloud_instance }} is a new instance
+ **
+ ** Go to https://{{ nextcloud_instances[nextcloud_instance].publish.hostnames[0] }} and finalize the
+ ** installation. After that run the following commands:
+ **
+ ** $ nextcloud-occ {{ nextcloud_instance }} config:system:set default_phone_region --value='at'
+ ** $ nextcloud-occ {{ nextcloud_instance }} config:system:set memcache.locking --value '\OC\Memcache\Redis'
+ ** $ nextcloud-occ {{ nextcloud_instance }} config:system:set redis host --value '127.0.0.1'
+ ** $ nextcloud-occ {{ nextcloud_instance }} config:system:set redis port --type integer --value 6379
+ ** $ nextcloud-occ {{ nextcloud_instance }} config:system:set redis timeout --type float --value 0.0
+ ** $ nextcloud-occ {{ nextcloud_instance }} config:system:set redis password
+ ** $ nextcloud-occ {{ nextcloud_instance }} config:system:set maintenance_window_start --type integer --value 23
+ **
+ ** in case you want to use an exteranl collabora/code server:
+ **
+ ** $ nextcloud-occ {{ nextcloud_instance }} app:disable richdocumentscode
+ ** $ nextcloud-occ {{ nextcloud_instance }} app:remove richdocumentscode
+ **
+ ****************************************
diff --git a/roles/apps/nextcloud/instance/templates/apache-site.conf.j2 b/roles/apps/nextcloud/instance/templates/apache-site.conf.j2
new file mode 100644
index 00000000..8df06113
--- /dev/null
+++ b/roles/apps/nextcloud/instance/templates/apache-site.conf.j2
@@ -0,0 +1,20 @@
+IncludeOptional mods-available/socache_shmcb.load
+IncludeOptional mods-available/ssl.load
+IncludeOptional mods-available/ssl.conf
+
+<VirtualHost *:8080>
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ UseCanonicalName Off
+ UseCanonicalPhysicalPort Off
+
+ ServerName nextcloud-{{ nextcloud_instance }}.{{ inventory_hostname }}
+ SSLEngine on
+ SSLCertificateFile "/etc/ssl/publish/cert.pem"
+ SSLCertificateKeyFile "/etc/ssl/publish/key.pem"
+ SSLProtocol TLSv1.3
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
diff --git a/roles/apps/nextcloud/instance/templates/cron-.timer.j2 b/roles/apps/nextcloud/instance/templates/cron-.timer.j2
new file mode 100644
index 00000000..eead0fd0
--- /dev/null
+++ b/roles/apps/nextcloud/instance/templates/cron-.timer.j2
@@ -0,0 +1,9 @@
+[Unit]
+Description=Nextcloud cron.php job timer for {{ nextcloud_instance }}
+
+[Timer]
+OnCalendar=*:{{ 5 | random(seed=nextcloud_instance) }}/5
+Unit=nextcloud-cron@{{ nextcloud_instance }}.service
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/apps/nextcloud/instance/templates/pod-spec-with-mariadb.yml.j2 b/roles/apps/nextcloud/instance/templates/pod-spec-with-mariadb.yml.j2
new file mode 100644
index 00000000..c1a4f2ea
--- /dev/null
+++ b/roles/apps/nextcloud/instance/templates/pod-spec-with-mariadb.yml.j2
@@ -0,0 +1,110 @@
+securityContext:
+ allowPrivilegeEscalation: false
+containers:
+- name: nextcloud
+{# image: "nextcloud{% if 'custom_image' in nextcloud_instances[nextcloud_instance] %}/{{ nextcloud_instance }}{% endif %}:{{ nextcloud_instances[nextcloud_instance].version }}" #}
+ image: "nextcloud/{{ nextcloud_instance }}:{{ nextcloud_instances[nextcloud_instance].version }}"
+ securityContext:
+ runAsUser: {{ nextcloud_app_uid }}
+ runAsGroup: {{ nextcloud_app_gid }}
+ resources:
+ limits:
+ memory: "4Gi"
+{% if 'new' in nextcloud_instances[nextcloud_instance] and nextcloud_instances[nextcloud_instance].new %}
+ env:
+ - name: NEXTCLOUD_TRUSTED_DOMAINS
+ value: "{{ nextcloud_instances[nextcloud_instance].publish.hostnames | join(' ') }}"
+ - name: MYSQL_HOST
+ value: 127.0.0.1
+ - name: MYSQL_DATABASE
+ value: nextcloud
+ - name: MYSQL_USER
+ value: nextcloud
+ - name: MYSQL_PASSWORD
+ value: "{{ nextcloud_instances[nextcloud_instance].database.password }}"
+{% endif %}
+ volumeMounts:
+ - name: nextcloud
+ mountPath: /var/www/html
+ - name: config
+ mountPath: /etc/apache2/sites-available/000-default.conf
+ subPath: apache-site.conf
+ readOnly: true
+ - name: config
+ mountPath: /etc/apache2/ports.conf
+ subPath: ports.conf
+ readOnly: true
+ - name: tls
+ mountPath: /etc/ssl/publish
+ readOnly: true
+ ports:
+ - containerPort: 8080
+ hostPort: {{ nextcloud_instances[nextcloud_instance].port }}
+ hostIP: 127.0.0.1
+- name: redis
+ image: "redis:{{ nextcloud_instances[nextcloud_instance].redis.version }}"
+ args:
+ - --bind 127.0.0.1
+ securityContext:
+ runAsUser: {{ nextcloud_redis_uid }}
+ runAsGroup: {{ nextcloud_redis_gid }}
+ resources:
+ limits:
+ memory: "512Mi"
+ volumeMounts:
+ - name: redis
+ mountPath: /data
+- name: database
+ image: "mariadb:{{ nextcloud_instances[nextcloud_instance].database.version }}"
+ args:
+ - --transaction-isolation=READ-COMMITTED
+ - --log-bin=binlog
+ - --binlog-format=ROW
+{% for arg in (nextcloud_instances[nextcloud_instance].database.extra_args | default([])) %}
+ - {{ arg }}
+{% endfor %}
+ securityContext:
+ runAsUser: {{ nextcloud_db_uid }}
+ runAsGroup: {{ nextcloud_db_gid }}
+ resources:
+ limits:
+ memory: "2Gi"
+ env:
+ - name: MARIADB_AUTO_UPGRADE
+ value: "true"
+ - name: MARIADB_DISABLE_UPGRADE_BACKUP
+ value: "true"
+{% if 'new' in nextcloud_instances[nextcloud_instance] and nextcloud_instances[nextcloud_instance].new %}
+ - name: MARIADB_RANDOM_ROOT_PASSWORD
+ value: "true"
+ - name: MARIADB_DATABASE
+ value: nextcloud
+ - name: MARIADB_USER
+ value: nextcloud
+ - name: MARIADB_PASSWORD
+ value: "{{ nextcloud_instances[nextcloud_instance].database.password }}"
+{% endif %}
+ volumeMounts:
+ - name: database
+ mountPath: /var/lib/mysql
+volumes:
+- name: config
+ hostPath:
+ path: "{{ nextcloud_instance_basepath }}/config/"
+ type: Directory
+- name: tls
+ hostPath:
+ path: "{{ nextcloud_instance_basepath }}/tls/"
+ type: Directory
+- name: nextcloud
+ hostPath:
+ path: "{{ nextcloud_instance_basepath }}/nextcloud"
+ type: Directory
+- name: redis
+ hostPath:
+ path: "{{ nextcloud_instance_basepath }}/redis"
+ type: Directory
+- name: database
+ hostPath:
+ path: "{{ nextcloud_instance_basepath }}/{{ nextcloud_instances[nextcloud_instance].database.type }}"
+ type: Directory
diff --git a/roles/apps/nextcloud/instance/templates/upgrade.sh.j2 b/roles/apps/nextcloud/instance/templates/upgrade.sh.j2
new file mode 100644
index 00000000..62f6641e
--- /dev/null
+++ b/roles/apps/nextcloud/instance/templates/upgrade.sh.j2
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+set -e
+
+if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
+ echo "Usage: $0 (preapre|finalize) <old-version> <new-version>"
+ exit 1
+fi
+
+COMMAND="$1"
+OLD_VERSION="$2"
+NEW_VERSION="$3"
+POD_NAME="{{ nextcloud_instance }}-$(hostname)"
+
+maintenance_mode() {
+ POD_ID=$(crictl pods --name "$POD_NAME" --state ready -q)
+ CONTAINER_ID=$(crictl ps --pod "$POD_ID" --name nextcloud -q)
+ crictl exec "$CONTAINER_ID" php -f /var/www/html/occ maintenance:mode "$1"
+}
+
+wait_for_cronjobs() {
+ POD_ID=$(crictl pods --name "$POD_NAME" --state ready -q)
+ CONTAINER_ID=$(crictl ps --pod "$POD_ID" --name nextcloud -q)
+ crictl exec "$CONTAINER_ID" bash -c 'echo -n "waiting for running cron script "; while [ -n "$(pgrep -a php | grep cron.php)" ]; do echo -n "."; sleep 1; done; echo ""'
+}
+
+wait_for_upgrade_complete() {
+ NEW_VERSION="$1"
+
+ set +e
+ echo -n "waiting for new version to be ready "
+ while true; do
+ POD_ID=$(crictl pods --name "$POD_NAME" --state ready -q)
+ if [ -z $POD_ID ]; then continue; fi
+ CONTAINER_ID=$(crictl ps --pod "$POD_ID" --name nextcloud -q)
+ if [ -z $CONTAINER_ID ]; then continue; fi
+ STATUS_OUTPUT=$(crictl exec "$CONTAINER_ID" php -f /var/www/html/occ status -n --no-warnings --output plain)
+ if [ $? -eq 0 ]; then
+ RUNNING_VERSION=$(echo "$STATUS_OUTPUT" | awk -F : '/versionstring/ { print($2) }' | tr -d ' ')
+ if [ "$RUNNING_VERSION" = "$NEW_VERSION" ]; then
+ break
+ fi
+ echo -n "."
+ fi
+ sleep 1
+ done
+ echo ""
+ set -e
+ crictl exec "$CONTAINER_ID" bash -c 'echo -n "waiting for apache to start "; while [ -z "$(pgrep apache2)" ]; do echo -n "."; sleep 1; done; echo ""'
+}
+
+storage_snapshot() {
+ OLD_VERSION="$1"
+ NEW_VERSION="$2"
+
+{% if nextcloud_instances[nextcloud_instance].storage.type == 'zfs' %}
+ ZFS_VOLUME=$(findmnt -no source -T "{{ nextcloud_instance_basepath }}")
+ echo "creating snapshot for zfs volume: $ZFS_VOLUME"
+ zfs snapshot "$ZFS_VOLUME@upgrade_$OLD_VERSION-to-$NEW_VERSION""_$(date '+%Y-%m-%m_%H:%M:%S')"
+{% endif %}
+}
+
+case "$COMMAND" in
+ prepare)
+ maintenance_mode --on
+ wait_for_cronjobs
+ storage_snapshot "$OLD_VERSION" "$NEW_VERSION"
+ ;;
+ finalize)
+ wait_for_upgrade_complete "$NEW_VERSION"
+ maintenance_mode --off
+ ;;
+ *)
+ echo "unknown command: $COMMAND, must be prepare or finalize"
+ exit 1
+ ;;
+esac
diff --git a/roles/apps/nextcloud/meta/main.yml b/roles/apps/nextcloud/meta/main.yml
new file mode 100644
index 00000000..c00c47ce
--- /dev/null
+++ b/roles/apps/nextcloud/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - role: apps/nextcloud/base
diff --git a/roles/apps/nextcloud/tasks/main.yml b/roles/apps/nextcloud/tasks/main.yml
index d1a11b19..6e81f351 100644
--- a/roles/apps/nextcloud/tasks/main.yml
+++ b/roles/apps/nextcloud/tasks/main.yml
@@ -1,240 +1,7 @@
---
-- name: create zfs datasets
- when: nextcloud_zfs is defined
- block:
- - name: create zfs base dataset
- zfs:
- name: "{{ nextcloud_zfs.pool }}/{{ nextcloud_zfs.name }}"
- state: present
- extra_zfs_properties: "{{ nextcloud_zfs.properties | dehumanize_zfs_properties | default(omit) }}"
-
- - name: create zfs volumes for instances
- loop: "{{ nextcloud_instances | dict2items }}"
- loop_control:
- label: "{{ item.key }} ({{ (item.value.zfs_properties | default({})).items() | map('join', '=') | join(', ') }})"
- zfs:
- name: "{{ nextcloud_zfs.pool }}/{{ nextcloud_zfs.name }}/{{ item.key }}"
- state: present
- extra_zfs_properties: "{{ item.value.zfs_properties | dehumanize_zfs_properties | default(omit) }}"
-
- - name: configure nextcloud base bath
- set_fact:
- nextcloud_base_path: "{{ (zfs_pools[nextcloud_zfs.pool].mountpoint, nextcloud_zfs.name) | path_join }}"
-
-
-- name: create instance subdirectories
- when: nextcloud_zfs is not defined
+- name: instance specific tasks
loop: "{{ nextcloud_instances | list }}"
- file:
- path: "{{ nextcloud_base_path }}/{{ item }}"
- state: directory
-
-
-
-- name: add group for nextcloud app
- group:
- name: nc-app
- gid: "{{ nextcloud_app_gid }}"
-
-- name: add user for nextcloud app
- user:
- name: nc-app
- uid: "{{ nextcloud_app_uid }}"
- group: nc-app
- password: "!"
-
-- name: create nextcloud app subdirectory
- loop: "{{ nextcloud_instances | list }}"
- file:
- path: "{{ nextcloud_base_path }}/{{ item }}/nextcloud"
- owner: "{{ nextcloud_app_uid }}"
- group: "{{ nextcloud_app_gid }}"
- state: directory
-
-
-- name: add group for nextcloud db
- group:
- name: nc-db
- gid: "{{ nextcloud_db_gid }}"
-
-- name: add user for nextcloud db
- user:
- name: nc-db
- uid: "{{ nextcloud_db_uid }}"
- group: nc-db
- password: "!"
-
-- name: create nextcloud database subdirectory
- loop: "{{ nextcloud_instances | dict2items }}"
- loop_control:
- label: "{{ item.key }} ({{ item.value.database.type }})"
- file:
- path: "{{ nextcloud_base_path }}/{{ item.key }}/{{ item.value.database.type }}"
- owner: "{{ nextcloud_db_uid }}"
- group: "{{ nextcloud_db_gid }}"
- state: directory
-
-
-- name: add group for nextcloud redis
- group:
- name: nc-redis
- gid: "{{ nextcloud_redis_gid }}"
-
-- name: add user for nextcloud redis
- user:
- name: nc-redis
- uid: "{{ nextcloud_redis_uid }}"
- group: nc-redis
- password: "!"
-
-- name: create nextcloud database subdirectory
- loop: "{{ nextcloud_instances | list }}"
- file:
- path: "{{ nextcloud_base_path }}/{{ item }}/redis"
- owner: "{{ nextcloud_redis_uid }}"
- group: "{{ nextcloud_redis_gid }}"
- state: directory
-
-
-- name: create auxiliary config directory
- loop: "{{ nextcloud_instances | list }}"
- file:
- path: "{{ nextcloud_base_path }}/{{ item }}/config"
- state: directory
-
-- name: create apache vhost config
- loop: "{{ nextcloud_instances | list }}"
- template:
- src: apache-site.conf.j2
- dest: "{{ nextcloud_base_path }}/{{ item }}/config/apache-site.conf"
-
-- name: configure apache to run on port 8080 only
- loop: "{{ nextcloud_instances | list }}"
- copy:
- content: |
- Listen 8080
- dest: "{{ nextcloud_base_path }}/{{ item }}/config/ports.conf"
-
-
-- name: build custom image
- loop: "{{ nextcloud_instances | dict2items }}"
- loop_control:
- label: "{{ item.key }}"
- # when: "'custom_image' in item.value"
- include_tasks: custom-image.yml
-
-- name: install pod manifest
- loop: "{{ nextcloud_instances | dict2items }}"
loop_control:
- label: "{{ item.key }}"
- vars:
- kubernetes_standalone_pod:
- name: "nextcloud-{{ item.key }}"
- spec: "{{ lookup('template', 'pod-spec-with-{{ item.value.database.type }}.yml.j2') }}"
- mode: "0600"
- config_hash_items:
- - path: "{{ nextcloud_base_path }}/{{ item.key }}/config/apache-site.conf"
- properties:
- - checksum
- - path: "{{ nextcloud_base_path }}/{{ item.key }}/config/ports.conf"
- properties:
- - checksum
- - path: "{{ nextcloud_base_path }}/{{ item.key }}/build/Dockerfile"
- properties:
- - checksum
+ loop_var: nextcloud_instance
include_role:
- name: kubernetes/standalone/pod
-
-
-- name: install cron trigger script
- loop: "{{ nextcloud_instances | list }}"
- template:
- src: run-cron.sh.j2
- dest: "{{ nextcloud_base_path }}/{{ item }}/config/run-cron.sh"
- mode: 0755
-
-- name: install template systemd unit for cron trigger
- template:
- src: cron@.service.j2
- dest: /etc/systemd/system/nextcloud-cron@.service
-
-- name: install systemd timer unit
- loop: "{{ nextcloud_instances | list }}"
- template:
- src: cron-.timer.j2
- dest: "/etc/systemd/system/nextcloud-cron-{{ item }}.timer"
-
-- name: start/enable cron trigger systemd timer
- loop: "{{ nextcloud_instances | list }}"
- systemd:
- daemon_reload: yes
- name: "nextcloud-cron-{{ item }}.timer"
- state: started
- enabled: yes
-
-
-- name: configure nginx vhost
- loop: "{{ nextcloud_instances | dict2items }}"
- loop_control:
- label: "{{ item.key }}"
- vars:
- nginx_vhost:
- name: "nextcloud-{{ item.key }}"
- template: generic
- tls:
- certificate_provider: "{{ acme_client }}"
- hostnames: "{{ item.value.hostnames }}"
- locations:
- '/':
- proxy_pass: "http://127.0.0.1:{{ item.value.port }}"
- proxy_redirect:
- - redirect: "http://$host/"
- replacement: "https://$host/"
- - redirect: "http://$host:8080/"
- replacement: "https://$host/"
- extra_directives: |-
- client_max_body_size 0;
- types {
- text/javascript js mjs;
- }
- include_role:
- name: nginx/vhost
-
-
-- name: install management scripts
- loop:
- - nextcloud-upgrade
- - nextcloud-occ
- template:
- src: "{{ item }}.j2"
- dest: "/usr/local/bin/{{ item }}"
- mode: 0755
-
-## TODO:
-# do this automatically!
-- name: print info for new instance
- loop: "{{ nextcloud_instances | dict2items }}"
- loop_control:
- label: "{{ item.key }}"
- when: "'new' in item.value and item.value.new"
- pause:
- seconds: 5
- prompt: |
- ************* {{ item.key }} is a new instance
- **
- ** Go to https://{{ item.value.hostnames[0] }} and finalize the
- ** installation. After that run the following commands:
- **
- ** $ nextcloud-occ {{ item.key }} config:system:set default_phone_region --value='at'
- ** $ nextcloud-occ {{ item.key }} config:system:set memcache.locking --value '\OC\Memcache\Redis'
- ** $ nextcloud-occ {{ item.key }} config:system:set redis host --value '127.0.0.1'
- ** $ nextcloud-occ {{ item.key }} config:system:set redis port --type integer --value 6379
- ** $ nextcloud-occ {{ item.key }} config:system:set redis timeout --type float --value 0.0
- ** $ nextcloud-occ {{ item.key }} config:system:set redis password
- **
- ** in case you want to use an exteranl collabora/code server:
- **
- ** $ nextcloud-occ {{ item.key }} app:disable richdocumentscode
- ** $ nextcloud-occ {{ item.key }} app:remove richdocumentscode
- **
- ****************************************
+ name: apps/nextcloud/instance
diff --git a/roles/apps/nextcloud/templates/apache-site.conf.j2 b/roles/apps/nextcloud/templates/apache-site.conf.j2
deleted file mode 100644
index a52a7fc5..00000000
--- a/roles/apps/nextcloud/templates/apache-site.conf.j2
+++ /dev/null
@@ -1,10 +0,0 @@
-<VirtualHost *:8080>
- ServerAdmin webmaster@localhost
- DocumentRoot /var/www/html
-
- UseCanonicalName Off
- UseCanonicalPhysicalPort Off
-
- ErrorLog ${APACHE_LOG_DIR}/error.log
- CustomLog ${APACHE_LOG_DIR}/access.log combined
-</VirtualHost>
diff --git a/roles/apps/nextcloud/templates/cron-.timer.j2 b/roles/apps/nextcloud/templates/cron-.timer.j2
deleted file mode 100644
index 0c3f7cd7..00000000
--- a/roles/apps/nextcloud/templates/cron-.timer.j2
+++ /dev/null
@@ -1,9 +0,0 @@
-[Unit]
-Description=Nextcloud cron.php job timer for %i
-
-[Timer]
-OnCalendar=*:{{ 5 | random(seed=item) }}/5
-Unit=nextcloud-cron@{{ item }}.service
-
-[Install]
-WantedBy=timers.target
diff --git a/roles/apps/nextcloud/templates/pod-spec-with-mariadb.yml.j2 b/roles/apps/nextcloud/templates/pod-spec-with-mariadb.yml.j2
deleted file mode 100644
index a49bc3ea..00000000
--- a/roles/apps/nextcloud/templates/pod-spec-with-mariadb.yml.j2
+++ /dev/null
@@ -1,101 +0,0 @@
-securityContext:
- allowPrivilegeEscalation: false
-containers:
-- name: nextcloud
-{# image: "nextcloud{% if 'custom_image' in item.value %}/{{ item.key }}{% endif %}:{{ item.value.version }}" #}
- image: "nextcloud/{{ item.key }}:{{ item.value.version }}"
- securityContext:
- runAsUser: {{ nextcloud_app_uid }}
- runAsGroup: {{ nextcloud_app_gid }}
- resources:
- limits:
- memory: "4Gi"
-{% if 'new' in item.value and item.value.new %}
- env:
- - name: NEXTCLOUD_TRUSTED_DOMAINS
- value: "{{ item.value.hostnames | join(' ') }}"
- - name: OVERWRITEPROTOCOL
- value: "https"
- - name: MYSQL_HOST
- value: 127.0.0.1
- - name: MYSQL_DATABASE
- value: nextcloud
- - name: MYSQL_USER
- value: nextcloud
- - name: MYSQL_PASSWORD
- value: "{{ item.value.database.password }}"
-{% endif %}
- volumeMounts:
- - name: nextcloud
- mountPath: /var/www/html
- - name: config
- mountPath: /etc/apache2/sites-available/000-default.conf
- subPath: apache-site.conf
- readOnly: true
- - name: config
- mountPath: /etc/apache2/ports.conf
- subPath: ports.conf
- readOnly: true
- ports:
- - containerPort: 8080
- hostPort: {{ item.value.port }}
- hostIP: 127.0.0.1
-- name: redis
- image: "redis:{{ item.value.redis.version }}"
- args:
- - --bind 127.0.0.1
- securityContext:
- runAsUser: {{ nextcloud_redis_uid }}
- runAsGroup: {{ nextcloud_redis_gid }}
- resources:
- limits:
- memory: "512Mi"
- volumeMounts:
- - name: redis
- mountPath: /data
-- name: database
- image: "mariadb:{{ item.value.database.version }}"
- args:
- - --transaction-isolation=READ-COMMITTED
- - --log-bin=binlog
- - --binlog-format=ROW
-{% for arg in (item.value.database.extra_args | default([])) %}
- - {{ arg }}
-{% endfor %}
- securityContext:
- runAsUser: {{ nextcloud_db_uid }}
- runAsGroup: {{ nextcloud_db_gid }}
- resources:
- limits:
- memory: "2Gi"
-{% if 'new' in item.value and item.value.new %}
- env:
- - name: MYSQL_RANDOM_ROOT_PASSWORD
- value: "true"
- - name: MYSQL_DATABASE
- value: nextcloud
- - name: MYSQL_USER
- value: nextcloud
- - name: MYSQL_PASSWORD
- value: "{{ item.value.database.password }}"
-{% endif %}
- volumeMounts:
- - name: database
- mountPath: /var/lib/mysql
-volumes:
-- name: config
- hostPath:
- path: "{{ nextcloud_base_path }}/{{ item.key }}/config/"
- type: Directory
-- name: nextcloud
- hostPath:
- path: "{{ nextcloud_base_path }}/{{ item.key }}/nextcloud"
- type: Directory
-- name: redis
- hostPath:
- path: "{{ nextcloud_base_path }}/{{ item.key }}/redis"
- type: Directory
-- name: database
- hostPath:
- path: "{{ nextcloud_base_path }}/{{ item.key }}/{{ item.value.database.type }}"
- type: Directory
diff --git a/roles/apps/nextcloud/templates/run-cron.sh.j2 b/roles/apps/nextcloud/templates/run-cron.sh.j2
deleted file mode 100644
index 455bc3ec..00000000
--- a/roles/apps/nextcloud/templates/run-cron.sh.j2
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-POD_NAME="{{ item }}-$(hostname)"
-POD_ID=$(crictl pods --name "$POD_NAME" --state ready -q)
-CONTAINER_ID=$(crictl ps --pod "$POD_ID" --name nextcloud -q)
-
-exec crictl exec "$CONTAINER_ID" php -f /var/www/html/cron.php