Files
deploy_home/ansible/roles/podman/tasks/containers/debyltech/cloud.yml
T
Bastian de BylandClaude Opus 5.5 fa5bbf8e54 feat(debyltech-cloud): add cloud.debyltech.com Nextcloud
A de Byl Technologies LLC Nextcloud cloned from the Skudak instance:
LibreSign signing for people without an account, registration off
(admin-created accounts only), no Group Folders. DNS is a terraform-managed
ALIAS to fulfillr.debyltech.com.

- containers/debyltech/cloud.yml: nextcloud/mariadb/redis on port 8091.
  It installs unattended on the first deploy, sends mail through SES as
  noreply@debyltech.com, and re-asserts the Skudak LibreSign settings.
- files/debyltechmail: skudakmail rebranded, with a new black-and-white
  wordmark and white web-UI logos.
- LibreSign is pinned to 14.2.2 from the GitHub release (sha256-checked)
  rather than `occ app:install`. The app store served a same-day 14.2.3
  whose tarball has no binary-signature metadata. 14.2.x also doesn't
  create its own download dirs, so they're pre-created.
- The backup runs nightly at 04:15 to TrueNAS /mnt/glacier/debyltechcloud and
  reaches personal iDrive via the "iDrive E2 Backup" task; the TrueNAS side
  excludes /debyltechcloud/_backup/config/**.
- Fix the libresign:configure:check gate in both instances: '\berror\b'
  becomes a backspace in Jinja and never matched, so a check reporting three
  errors passed clean. Now '\\berror\\b'.
- vault: cloud_debyltech_* secrets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 17:04:04 -04:00

616 lines
24 KiB
YAML

---
# de Byl Technologies Nextcloud (cloud.debyltech.com).
#
# Cloned from containers/skudak/cloud.yml, which carries the full reasoning for
# nearly every task below -- read the matching comment there before changing
# one here. Comments in this file cover only where the two instances differ.
#
# Differences from Skudak, by design:
# - Fresh install: NEXTCLOUD_ADMIN_* makes the first deploy install
# unattended, and LibreSign is installed from the app store rather than
# assumed present.
# - No Group Folders. Registration stays off, matching Skudak's live state:
# every account, staff and customer alike, is created by the admin, with
# customers in per-customer groups.
# - Outbound mail is AWS SES SMTP (noreply@debyltech.com), set here via occ
# so it lives in git rather than only in the admin UI.
# - Backups go to personal iDrive e2 via TrueNAS -- see the backup include
# at the bottom.
- name: create required debyltech cloud volumes
become: true
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ podman_subuid.stdout }}"
group: "{{ podman_subuid.stdout }}"
mode: 0755
notify: restorecon podman
loop:
- "{{ cloud_debyltech_path }}/apps"
- "{{ cloud_debyltech_path }}/config"
- "{{ cloud_debyltech_path }}/data"
- "{{ cloud_debyltech_path }}/mysql"
- "{{ cloud_debyltech_path }}/scripts"
- "{{ cloud_debyltech_path }}/redis"
- name: unshare chown the debyltech cloud volumes
become: true
become_user: "{{ podman_user }}"
changed_when: false
ansible.builtin.command: |
podman unshare chown -R 33:33 {{ cloud_debyltech_path }}/apps {{ cloud_debyltech_path }}/data {{ cloud_debyltech_path }}/config
- name: flush handlers
ansible.builtin.meta: flush_handlers
- import_tasks: podman/podman-check.yml
vars:
container_name: debyltech-cloud-db
container_image: "{{ db_image }}"
- name: create debyltech-cloud-db container
become: true
become_user: "{{ podman_user }}"
containers.podman.podman_container:
name: debyltech-cloud-db
image: "{{ db_image }}"
restart_policy: on-failure:3
log_driver: journald
network:
- shared
env:
MYSQL_ROOT_PASSWORD: "{{ cloud_debyltech_db_root_pass }}"
MYSQL_DATABASE: dtcloud
MYSQL_PASSWORD: "{{ cloud_debyltech_db_pass }}"
MYSQL_USER: dtcloud
volumes:
- "{{ cloud_debyltech_path }}/mysql:/var/lib/mysql"
- name: create systemd startup job for debyltech-cloud-db
include_tasks: podman/systemd-generate.yml
vars:
container_name: debyltech-cloud-db
# ---------------------------------------------------------------------------
# Redis: distributed cache + file locking. MUST exist before debyltech-cloud
# below -- see the Skudak equivalent for why.
- name: template debyltech cloud redis config
become: true
ansible.builtin.template:
src: nextcloud/redis-debyltech.conf.j2
dest: "{{ cloud_debyltech_path }}/redis/redis.conf"
owner: "{{ podman_subuid.stdout }}"
group: "{{ podman_subuid.stdout }}"
mode: 0640
notify: restorecon podman
no_log: true
- name: flush handlers
ansible.builtin.meta: flush_handlers
- name: unshare chown the debyltech redis config to the redis uid
become: true
become_user: "{{ podman_user }}"
changed_when: false
ansible.builtin.command: >
podman unshare chown 999:1000 {{ cloud_debyltech_path }}/redis/redis.conf
- import_tasks: podman/podman-check.yml
vars:
container_name: debyltech-cloud-redis
container_image: "{{ redis_image }}"
- name: create debyltech-cloud-redis container
become: true
become_user: "{{ podman_user }}"
containers.podman.podman_container:
name: debyltech-cloud-redis
image: "{{ redis_image }}"
restart_policy: on-failure:3
log_driver: journald
network:
- shared
volumes:
- "{{ cloud_debyltech_path }}/redis/redis.conf:/etc/redis/redis.conf:ro"
command: redis-server /etc/redis/redis.conf
- name: create systemd startup job for debyltech-cloud-redis
include_tasks: podman/systemd-generate.yml
vars:
container_name: debyltech-cloud-redis
- import_tasks: podman/podman-check.yml
vars:
container_name: debyltech-cloud
container_image: "{{ image }}"
- name: create debyltech cloud container
become: true
become_user: "{{ podman_user }}"
containers.podman.podman_container:
name: debyltech-cloud
image: "{{ image }}"
restart_policy: on-failure:3
log_driver: journald
network:
- shared
env:
MYSQL_PASSWORD: "{{ cloud_debyltech_db_pass }}"
MYSQL_DATABASE: dtcloud
MYSQL_HOST: debyltech-cloud-db
MYSQL_USER: dtcloud
# Read by the entrypoint ONLY on first start against an empty config
# volume, to run the install unattended; ignored on every start after.
NEXTCLOUD_ADMIN_USER: admin
NEXTCLOUD_ADMIN_PASSWORD: "{{ cloud_debyltech_admin_pass }}"
NEXTCLOUD_TRUSTED_DOMAINS: "{{ cloud_debyltech_server_name }}"
PHP_MEMORY_LIMIT: 1024M
PHP_UPLOAD_LIMIT: 512M
LC_ALL: C.UTF-8
LANG: C.UTF-8
REDIS_HOST: debyltech-cloud-redis
REDIS_HOST_PORT: "6379"
REDIS_HOST_PASSWORD: "{{ cloud_debyltech_redis_pass }}"
volumes:
- "{{ cloud_debyltech_path }}/apps:/var/www/html/custom_apps"
- "{{ cloud_debyltech_path }}/data:/var/www/html/data"
- "{{ cloud_debyltech_path }}/config:/var/www/html/config"
ports:
- "8091:80"
- name: create systemd startup job for debyltech-cloud
include_tasks: podman/systemd-generate.yml
vars:
container_name: debyltech-cloud
# ---------------------------------------------------------------------------
# LibreSign
- name: install libresign runtime dependencies in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command:
cmd: >
podman exec -u 0 debyltech-cloud
sh -c "apt-get update && apt-get install -y --no-install-recommends
poppler-utils ghostscript && rm -rf /var/lib/apt/lists/*"
register: libresign_deps
changed_when: "'is already the newest version' not in libresign_deps.stdout"
# On the FIRST deploy this also waits out the unattended install, which takes
# noticeably longer than a restart -- hence the larger budget than Skudak's.
- name: wait for nextcloud to be ready in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ status --output=json
register: debyltech_occ_ready
# String match, not from_json: before the install finishes occ can print a
# plain-text warning ahead of the JSON, and a parse error would abort the
# retry loop instead of waiting. Skudak's bare 'installed' check would also
# match "installed":false, which is exactly the state being waited out here.
until: >-
debyltech_occ_ready.rc == 0
and '"installed":true' in debyltech_occ_ready.stdout
retries: 60
delay: 5
changed_when: false
# LibreSign is PINNED (libresign_version / libresign_sha256 in tasks/main.yml)
# and installed from the upstream GitHub release, NOT `occ app:install`, which
# always takes whatever the app store has that day. On 2026-09-28 that was a
# same-day 14.2.3 whose tarball shipped without appinfo/install-*.json -- the
# maintainer-signed metadata LibreSign verifies its java/pdftk/jsignpdf
# downloads against -- so configure:check failed all three on a clean install.
#
# Upgrading: bump both pins together (the sha256 is on the GitHub release
# asset) and deploy; the tree is replaced and `occ upgrade` runs the app's
# migrations. Downgrading is refused below: Nextcloud does not support it, and
# the only way back is removing the app, which discards its config and CA.
- name: read installed libresign version in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ config:app:get libresign installed_version
register: libresign_installed
changed_when: false
failed_when: false
- name: refuse to downgrade libresign in debyltech-cloud
ansible.builtin.fail:
msg: >-
LibreSign {{ libresign_installed.stdout }} is installed but the pin is
{{ libresign_version }}. Nextcloud cannot downgrade an app in place --
raise the pin, or remove the app deliberately if nothing has been signed.
when:
- libresign_installed.rc == 0
- libresign_installed.stdout is version(libresign_version, '>')
- name: install pinned libresign release in debyltech-cloud
when: libresign_installed.rc != 0 or libresign_installed.stdout != libresign_version
block:
- name: fetch pinned libresign release
become: true
ansible.builtin.get_url:
url: "https://github.com/LibreSign/libresign/releases/download/v{{ libresign_version }}/libresign-v{{ libresign_version }}.tar.gz"
dest: "{{ cloud_debyltech_path }}/scripts/libresign-v{{ libresign_version }}.tar.gz"
checksum: "sha256:{{ libresign_sha256 }}"
mode: 0644
- name: remove previous libresign app tree
become: true
ansible.builtin.file:
path: "{{ cloud_debyltech_path }}/apps/libresign"
state: absent
- name: unpack pinned libresign release into custom_apps
become: true
ansible.builtin.unarchive:
src: "{{ cloud_debyltech_path }}/scripts/libresign-v{{ libresign_version }}.tar.gz"
dest: "{{ cloud_debyltech_path }}/apps/"
remote_src: true
# Unpacked as root the files keep the tarball's owners, which lie
# outside the podman user's subuid range, so the unshare chown below
# is refused. Same two-step as the debyltechmail copy.
owner: "{{ podman_subuid.stdout }}"
group: "{{ podman_subuid.stdout }}"
notify: restorecon podman
- name: unshare chown the libresign app tree
become: true
become_user: "{{ podman_user }}"
changed_when: false
ansible.builtin.command: >
podman unshare chown -R 33:33 {{ cloud_debyltech_path }}/apps/libresign
- name: flush handlers
ansible.builtin.meta: flush_handlers
# Only an in-place upgrade needs this; a first install is handled by the
# app:enable below.
- name: run libresign migrations in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud php occ upgrade
when: libresign_installed.rc == 0
- name: ensure libresign app is enabled in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ app:enable libresign
register: libresign_enable
changed_when: "'already enabled' not in libresign_enable.stdout"
# 14.2.x's downloader does not create its own target directories: on a fresh
# appdata every java/pdftk download fails with "Directory ... does not exist
# for sink value". Creating them first is harmless once they exist.
- name: pre-create libresign binary directories in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
changed_when: false
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud sh -c
'd=$(ls -d /var/www/html/data/appdata_*/libresign) &&
mkdir -p "$d/x86_64/linux/java" "$d/x86_64/pdftk"'
# "Finished with success" is printed even when every download failed, so this
# check only catches the command itself falling over. The real gate is the
# configure:check verify task below, which hashes each binary against the
# release's signed metadata.
- name: install libresign java/pdftk/jsignpdf binaries in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ libresign:install --java --pdftk --jsignpdf
register: libresign_install
changed_when: false
failed_when: "'Finished with success' not in libresign_install.stdout"
- name: check whether libresign root certificate is configured
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ libresign:configure:check --certificate
register: libresign_cert_check
changed_when: false
failed_when: false
# Guarded: re-running would mint a new root CA and orphan every certificate
# already issued. No --ou -- see skudak/cloud.yml.
- name: generate libresign root certificate for debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ libresign:configure:openssl
--cn="{{ libresign_debyltech_cert_cn }}"
-o "{{ libresign_debyltech_cert_o }}"
-c "{{ libresign_debyltech_cert_c }}"
-s "{{ libresign_debyltech_cert_st }}"
-l "{{ libresign_debyltech_cert_l }}"
when: "'error' in libresign_cert_check.stdout"
changed_when: true
# Signers are mostly customers WITHOUT an account, reached by emailed
# invitation; the ID-document gate would leave them unable to sign at all.
- name: relax libresign identification-document gate in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ config:app:set libresign identification_documents --value=0
register: libresign_ident
changed_when: "'is now set to' in libresign_ident.stdout"
# Must be exactly GRAPHIC_ONLY -- see skudak/cloud.yml.
- name: use signature-only stamp in debyltech-cloud libresign
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ config:app:set libresign signature_render_mode --value=GRAPHIC_ONLY
register: libresign_render
changed_when: "'is now set to' in libresign_render.stdout"
# Lets account-owned emails be added as signers. NEVER set the _email variant
# of this key to 'no' -- see skudak/cloud.yml.
- name: allow account-owned emails as libresign signers in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ config:app:set core
shareapi_restrict_user_enumeration_full_match --value=no
register: debyltech_enum_fullmatch
changed_when: "'is now set to' in debyltech_enum_fullmatch.stdout"
- name: drop libresign validation QR code from signed-PDF footer in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ config:app:set libresign write_qrcode_on_footer
--value=0 --type=boolean
register: libresign_qr
changed_when: "'is now set to' in libresign_qr.stdout"
- name: verify libresign configuration in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ libresign:configure:check
register: libresign_verify
changed_when: false
# Double backslashes: Jinja unescapes string literals, so a single '\b'
# becomes a BACKSPACE character and this could never match -- which is
# how a check reporting three errors passed clean on 2026-09-28.
failed_when: libresign_verify.stdout is search('\\berror\\b')
# ---------------------------------------------------------------------------
# Background jobs. A fresh install defaults to AJAX mode, which only runs jobs
# while someone has the web UI open -- LibreSign's queued signature mail and
# every cleanup job would stall. The cloud-cron timer included below drives
# cron.php; this tells Nextcloud to expect it.
- name: set debyltech-cloud background jobs to cron
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ config:app:set core backgroundjobs_mode --value=cron
register: debyltech_bgjobs
changed_when: "'is now set to' in debyltech_bgjobs.stdout"
- name: disable nextcloud signup link in debyltech-cloud config
become: true
ansible.builtin.lineinfile:
path: "{{ cloud_debyltech_path }}/config/config.php"
regexp: "^\\s*'simpleSignUpLink\\.shown'\\s*=>"
line: " 'simpleSignUpLink.shown' => false,"
insertbefore: '^\);'
create: false
# ---------------------------------------------------------------------------
# Branding: debyltechmail, cloned from skudakmail. custom_apps is a persisted
# bind mount, so only enabling and config need reasserting.
# Owned directly by the HOST uid that rootless podman maps www-data (33) to --
# subuid start + 32, since container uid 1 is the first subuid. Skudak copies
# as the subuid and then `podman unshare chown`s, which flips ownership back
# and forth so the copy reports changed on every run; here that would also
# re-import the theming logos below every time.
- name: deploy debyltechmail email-template app to debyltech-cloud
become: true
ansible.builtin.copy:
src: debyltechmail/
dest: "{{ cloud_debyltech_path }}/apps/debyltechmail/"
owner: "{{ podman_subuid.stdout | int + 32 }}"
group: "{{ podman_subuid.stdout | int + 32 }}"
mode: 0644
directory_mode: 0755
register: debyltechmail_copy
notify: restorecon podman
- name: enable debyltechmail app in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud php occ app:enable debyltechmail
register: debyltechmail_enable
changed_when: "'already enabled' not in debyltechmail_enable.stdout"
# System config, set only when it differs so a clean re-deploy reports no
# changes (Skudak's equivalents report changed on every run). Values are
# single-quoted into the shell, so the backslashes in mail_template_class pass
# through literally. overwrite.cli.url is what LibreSign invitation links and
# mail asset URLs are built from when sent by a background job.
- name: set debyltech-cloud system config
become: true
become_user: "{{ podman_user }}"
ansible.builtin.shell: |
set -o pipefail
occ() { podman exec -u www-data debyltech-cloud php occ "$@"; }
cur=$(occ config:system:get {{ item.k }} || true)
if [ "$cur" != {{ item.v | quote }} ]; then
occ config:system:set {{ item.k }} --value={{ item.v | quote }} --type={{ item.t | default('string') }} >/dev/null
echo CHANGED
fi
args:
executable: /bin/bash
register: debyltech_sysconfig
changed_when: "'CHANGED' in debyltech_sysconfig.stdout"
loop:
- {k: overwrite.cli.url, v: "https://{{ cloud_debyltech_server_name }}"}
- {k: overwriteprotocol, v: https}
- {k: loglevel, v: "2", t: integer}
- {k: log_rotate_size, v: "10485760", t: integer}
- {k: mail_template_class, v: "OCA\\Debyltechmail\\Mail\\DebyltechEMailTemplate"}
- {k: mail_smtpmode, v: smtp}
- {k: mail_smtphost, v: "{{ cloud_debyltech_smtp_host }}"}
- {k: mail_smtpport, v: "{{ cloud_debyltech_smtp_port }}", t: integer}
- {k: mail_smtpsecure, v: ssl}
- {k: mail_smtpauth, v: "true", t: boolean}
- {k: mail_from_address, v: noreply}
- {k: mail_domain, v: debyltech.com}
loop_control:
label: "{{ item.k }}"
- name: set debyltech-cloud SES SMTP credentials
become: true
become_user: "{{ podman_user }}"
ansible.builtin.shell: |
set -o pipefail
occ() { podman exec -u www-data debyltech-cloud php occ "$@"; }
cur=$(occ config:system:get {{ item.k }} || true)
if [ "$cur" != {{ item.v | quote }} ]; then
occ config:system:set {{ item.k }} --value={{ item.v | quote }} >/dev/null
echo CHANGED
fi
args:
executable: /bin/bash
register: debyltech_smtp_creds
changed_when: "'CHANGED' in debyltech_smtp_creds.stdout"
loop:
- {k: mail_smtpname, v: "{{ cloud_debyltech_smtp_user }}"}
- {k: mail_smtppassword, v: "{{ cloud_debyltech_smtp_pass }}"}
loop_control:
label: "{{ item.k }}"
no_log: true
# Compared first: theming:config prints "Updated" even when nothing changed.
- name: set debyltech-cloud theming
become: true
become_user: "{{ podman_user }}"
ansible.builtin.shell: |
set -o pipefail
occ() { podman exec -u www-data debyltech-cloud php occ "$@"; }
cur=$(occ config:app:get theming {{ item.k }} || true)
if [ "$cur" != {{ item.v | quote }} ]; then
occ theming:config {{ item.k }} {{ item.v | quote }} >/dev/null
echo CHANGED
fi
args:
executable: /bin/bash
loop:
- {k: name, v: "de Byl Technologies"}
- {k: slogan, v: "Hardware, firmware and design services"}
- {k: url, v: "https://debyltech.com"}
- {k: primary_color, v: "{{ theming_debyltech_primary }}"}
- {k: background_color, v: "{{ theming_debyltech_background }}"}
register: debyltech_theming
changed_when: "'CHANGED' in debyltech_theming.stdout"
loop_control:
label: "{{ item.k }}"
# The web UI logos ship inside the debyltechmail app (the white variants; the
# ink wordmark is the mail one). theming:config re-imports the file on every
# call, so it runs only when the app's files changed or no logo is set yet.
# `logo` is the wide wordmark on the login page; `logoheader` is the square
# mark in the top bar, where a wordmark would shrink to illegibility.
- name: check debyltech-cloud theming logos
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ config:app:get theming {{ item }}Mime
loop: [logo, logoheader]
register: debyltech_logo_mime
changed_when: false
failed_when: false
- name: set debyltech-cloud theming logos
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud php occ theming:config {{ item.item }}
/var/www/html/custom_apps/debyltechmail/img/{{ logo_files[item.item] }}
loop: "{{ debyltech_logo_mime.results }}"
when: debyltechmail_copy is changed or item.rc != 0 or item.stdout == ''
vars:
logo_files:
logo: debyltech-wordmark-white.png
logoheader: debyltech-mark-white.png
loop_control:
label: "{{ item.item }}"
# Fails the play if branding, the LibreSign settings above, or Redis locking
# have silently regressed -- see skudak/cloud.yml.
- name: template debyltechmail verification script
become: true
ansible.builtin.template:
src: nextcloud/debyltechmail-verify.php.j2
dest: "{{ cloud_debyltech_path }}/scripts/debyltechmail-verify.php"
owner: "{{ podman_subuid.stdout }}"
group: "{{ podman_subuid.stdout }}"
mode: 0644
notify: restorecon podman
- name: verify debyltech mail branding is live
become: true
become_user: "{{ podman_user }}"
ansible.builtin.shell: >
set -o pipefail;
podman exec -i -u www-data debyltech-cloud php
< {{ cloud_debyltech_path }}/scripts/debyltechmail-verify.php
args:
executable: /bin/bash
register: debyltechmail_verify
changed_when: false
- include_tasks: containers/cloud-cron.yml
vars:
cron_name: debyltech-cloud
cron_container: debyltech-cloud
cron_script_path: /usr/local/bin/debyltech-cloud-cron.sh
# BUSINESS data that DELIBERATELY reaches personal storage -- the opposite of
# Skudak, and on purpose: de Byl Technologies LLC is the owner's own company.
#
# Chain: this rsync -> TrueNAS /mnt/glacier/debyltechcloud (05:00 ZFS
# snapshot) -> the personal "iDrive E2 Backup" cloud-sync task, which pushes
# /mnt/glacier to the personal iDrive e2 bucket. Unlike /skudakcloud/**,
# /skudakapps/** and /skudakgit/**, there is NO exclude for /debyltechcloud/**
# on that task, and there must not be one -- that inclusion IS the offsite
# copy. If that ever changes, give it its own cloud-sync task first.
- include_tasks: containers/cloud-backup.yml
vars:
backup_name: debyltech-cloud
data_path: "{{ cloud_debyltech_path }}/data"
config_path: "{{ cloud_debyltech_path }}/config"
db_container: debyltech-cloud-db
ssh_key_path: /etc/ssh/backup_keys/debyltech-cloud
ssh_key_content: "{{ cloud_debyltech_backup_ssh_key }}"
ssh_user: debyltechcloud
remote_path: /mnt/glacier/debyltechcloud
script_path: /usr/local/bin/debyltech-cloud-backup.sh
# data/ is mode 770 here too; see skudak/cloud.yml.
backup_rsync_extra_args: "--chmod=Du=rwx,Dgo=rx"
# Between the 04:00 personal and 04:30 Skudak runs, before the 05:00
# TrueNAS snapshot.
backup_oncalendar: "*-*-* 04:15:00"