Files
deploy_home/ansible/roles/podman/tasks/containers/home/cloud.yml
T
Bastian de Byl 5776dbe1bf UPS monitoring, Nextcloud cron, container image bumps
ups role: NUT server on home.debyl.io for the CyberPower PR1500RT2U that backs
both it and truenas.localdomain, with staged shutdown (TrueNAS sheds at t+2min,
host at 10% charge) and best-effort IPMI power-on when mains returns. The 10%
threshold leans on ignorelb + override.battery.charge.low rather than a custom
poller, because CyberPower asserts its own low-battery flag far too early.
Credentials come from vault vars; nothing sensitive is templated in the clear.

Nextcloud background jobs: both instances have backgroundjobs_mode "cron", which
expects an external caller every ~5 minutes, and nothing was calling. The
personal instance had not run a background job since 2026-05-14 and skudak since
2024-11-20. Consequently trash and file versions never expired, stale chunked
uploads accumulated, calendar reminders never fired, and nextcloud.log was never
rotated -- which quietly made the existing log_rotate_size cap inert. Added a
systemd timer per instance, skipping cleanly when the container is down or in
maintenance so deploy windows don't show up as failed units.

Trash retention on the personal instance: the default "auto" only expires when
disk space demands it, so 66 GB of >30-day deletions sat on a host with 1.3 TB
free -- effectively unbounded. "auto, 30" makes the 30-day expiry unconditional
while still purging early under pressure.

Image bumps:
  nextcloud       33.0.0  -> 34.0.2   (both cloud and skudak-cloud)
  greg-time-bot   3.9.25  -> 3.10.0
  fulfillr        20260723.2044 -> 20260728.2155  (prod and dev)

The fulfillr bump records what is already deployed: both containers were rolled
to that image on 2026-07-29 for SCRUM-156 (digital product releases + customer
update campaign). Committing it keeps the repo from claiming an older tag than
the host is actually running, which would otherwise roll fulfillr backwards on
the next clean-checkout deploy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 13:00:51 -04:00

130 lines
3.9 KiB
YAML

---
- name: create required 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_path }}/apps"
- "{{ cloud_path }}/config"
- "{{ cloud_path }}/data"
- "{{ cloud_path }}/mysql"
- name: unshare chown the nextcloud volumes
become: true
become_user: "{{ podman_user }}"
changed_when: false
ansible.builtin.command: |
podman unshare chown -R 33:33 {{ cloud_path }}/apps {{ cloud_path }}/data {{ cloud_path}}/config
- name: flush handlers
ansible.builtin.meta: flush_handlers
- import_tasks: podman/podman-check.yml
vars:
container_name: cloud-db
container_image: "{{ db_image }}"
- name: create cloud-db container
become: true
become_user: "{{ podman_user }}"
containers.podman.podman_container:
name: cloud-db
image: "{{ db_image }}"
restart_policy: on-failure:3
log_driver: journald
network:
- shared
env:
MYSQL_ROOT_PASSWORD: "{{ cloud_db_root_pass }}"
MYSQL_DATABASE: cloud
MYSQL_PASSWORD: "{{ cloud_db_pass }}"
MYSQL_USER: cloud
volumes:
- "{{ cloud_path }}/mysql:/var/lib/mysql"
- name: create systemd startup job for cloud-db
include_tasks: podman/systemd-generate.yml
vars:
container_name: cloud-db
- import_tasks: podman/podman-check.yml
vars:
container_name: cloud
container_image: "{{ image }}"
- name: create cloud container
become: true
become_user: "{{ podman_user }}"
containers.podman.podman_container:
name: cloud
image: "{{ image }}"
restart_policy: on-failure:3
log_driver: journald
network:
- shared
env:
MYSQL_PASSWORD: "{{ cloud_db_pass }}"
MYSQL_DATABASE: cloud
MYSQL_HOST: cloud-db
MYSQL_USER: cloud
volumes:
- "{{ cloud_path }}/apps:/var/www/html/custom_apps"
- "{{ cloud_path }}/data:/var/www/html/data"
- "{{ cloud_path }}/config:/var/www/html/config"
ports:
- "8089:80"
- name: create systemd startup job for cloud
include_tasks: podman/systemd-generate.yml
vars:
container_name: cloud
# Unbounded by default: nextcloud.log.1 had reached 1.12 GB and was being
# rsynced to TrueNAS and pushed to S3 on every run. Cap at 10 MiB.
- name: cap nextcloud log rotation size for cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data cloud
php occ config:system:set log_rotate_size --value 10485760 --type integer
register: cloud_log_rotate
changed_when: "'System config value log_rotate_size' in cloud_log_rotate.stdout"
failed_when: false
# Nextcloud's default ('auto') only expires trash when disk space is needed,
# so 66 GB of >30-day deletions sat untouched on a host with 1.3 TB free --
# the retention was effectively unbounded. 'auto, 30' makes the 30-day
# expiry unconditional while still purging early under space pressure.
- name: set nextcloud trashbin retention for cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data cloud
php occ config:system:set trashbin_retention_obligation --value "auto, 30"
register: cloud_trashbin_retention
changed_when: "'System config value trashbin_retention_obligation' in cloud_trashbin_retention.stdout"
failed_when: false
- include_tasks: containers/cloud-cron.yml
vars:
cron_name: cloud
cron_container: cloud
cron_script_path: /usr/local/bin/cloud-cron.sh
- include_tasks: containers/cloud-backup.yml
vars:
backup_name: cloud
data_path: "{{ cloud_path }}/data"
config_path: "{{ cloud_path }}/config"
db_container: cloud-db
ssh_key_path: /etc/ssh/backup_keys/cloud
ssh_key_content: "{{ cloud_backup_ssh_key }}"
ssh_user: cloud
remote_path: /mnt/glacier/nextcloud
script_path: /usr/local/bin/cloud-backup.sh