--- - name: Deploy LubeLogger on docker-node01 hosts: docker-node01 become: true vars: app_dir: /home/tommy/lubelogger app_port: 8099 handlers: - name: reload systemd ansible.builtin.systemd_service: daemon_reload: true tasks: - name: Create lubelogger directory ansible.builtin.file: path: "{{ app_dir }}" state: directory owner: tommy group: tommy mode: "0755" - name: Write docker-compose.yml ansible.builtin.copy: dest: "{{ app_dir }}/docker-compose.yml" owner: tommy group: tommy mode: "0644" content: | # lubelogger - Vehicle & small-engine maintenance tracker # Host: docker-node01 (.186), Port: {{ app_port }} # Traefik: lubelogger.goattw.net (Authelia protected, @file router -> :{{ app_port }}) # Backend: PostgreSQL 18 (tables live in the `app` schema). # In-app auth is ENABLED (root user) - the published host port is safe. # Do NOT lose the lubelogger-keys volume (ASP.NET DataProtection keyring). services: lubelogger: image: ghcr.io/hargata/lubelogger:v1.6.8 container_name: lubelogger restart: unless-stopped depends_on: - lubelogger-db ports: - "{{ app_port }}:8080" environment: TZ: America/Chicago LUBELOGGER_LOCALE_OVERRIDE: "en_US" POSTGRES_CONNECTION: "Host=lubelogger-db:5432;Username=lubelogger;Password={{ vault_lubelogger_db_password }};Database=lubelogger;" volumes: - lubelogger-data:/App/data - lubelogger-keys:/root/.aspnet/DataProtection-Keys networks: - lubelogger-int labels: - "docker-volume-backup.stop-during-backup=true" # Diun watches by default (digest); watch_repo + semver filter # so a NEW release tag (e.g. v1.6.9) pings the existing Diun->HA pipeline. - "diun.enable=true" - "diun.watch_repo=true" - 'diun.include_tags=^v[0-9]+\.[0-9]+\.[0-9]+$' lubelogger-db: image: postgres:18 container_name: lubelogger-db restart: unless-stopped environment: POSTGRES_USER: lubelogger POSTGRES_PASSWORD: "{{ vault_lubelogger_db_password }}" POSTGRES_DB: lubelogger TZ: America/Chicago volumes: - lubelogger-db:/var/lib/postgresql - /etc/localtime:/etc/localtime:ro networks: - lubelogger-int healthcheck: test: ["CMD-SHELL", "pg_isready -U lubelogger -d lubelogger"] interval: 10s timeout: 5s retries: 5 start_period: 30s labels: - "docker-volume-backup.stop-during-backup=true" networks: lubelogger-int: driver: bridge volumes: lubelogger-data: lubelogger-keys: lubelogger-db: - name: Remove stale .env (secret now sourced from ansible-vault) ansible.builtin.file: path: "{{ app_dir }}/.env" state: absent - name: Deploy lubelogger with docker compose community.docker.docker_compose_v2: project_src: "{{ app_dir }}" state: present pull: missing register: app_result - name: Show deployment result ansible.builtin.debug: msg: "lubelogger is {{ 'running (changed)' if app_result.changed else 'already up (no-op)' }} on port {{ app_port }}" # ---- Backup: pg_dump + data/keys volumes -> PBS (host/lubelogger, keep-daily 14) ---- # docker-volume-backup sidecar cannot target a PBS datastore natively, so the two # volumes ride the same proxmox-backup-client job as the SQL dump: one snapshot, # three archives, one retention. Secrets come from ansible-vault, never committed. - name: Install PBS backup credentials (from vault) ansible.builtin.copy: dest: /etc/lubelogger-backup.env owner: root group: root mode: "0600" content: | # Managed by deploy-lubelogger.yml. PBS push creds — NOT in git. PBS_PASSWORD={{ vault_lubelogger_pbs_token }} PBS_FINGERPRINT=90:6B:3E:85:C4:E7:77:F0:24:25:1D:B0:2C:F9:6D:08:AA:CE:08:CE:7B:04:4C:C7:C9:E0:CF:DD:99:44:DB:21 PBS_REPOSITORY='root@pam!vaultwarden-backup@192.168.99.153:rust-usb' no_log: true - name: Install lubelogger backup script ansible.builtin.copy: dest: /usr/local/bin/lubelogger-backup.sh owner: root group: root mode: "0700" content: | #!/bin/bash # LubeLogger backup -> Proxmox Backup Server. # One snapshot (host/lubelogger), three archives: Postgres logical dump + # the data and keys volumes (uploads, config, ASP.NET DataProtection keyring). # Managed by deploy-lubelogger.yml; driven by lubelogger-backup.timer. set -euo pipefail source /etc/lubelogger-backup.env export PBS_PASSWORD PBS_FINGERPRINT DATA_VOL=/var/lib/docker/volumes/lubelogger_lubelogger-data/_data KEYS_VOL=/var/lib/docker/volumes/lubelogger_lubelogger-keys/_data TMPDIR=$(mktemp -d) trap 'rm -rf "$TMPDIR"' EXIT # Logical DB dump (app schema + data); app stays online. docker exec lubelogger-db pg_dump -U lubelogger lubelogger > "$TMPDIR/lubelogger.sql" proxmox-backup-client backup \ "lubelogger-db.pxar:$TMPDIR" \ "lubelogger-data.pxar:$DATA_VOL" \ "lubelogger-keys.pxar:$KEYS_VOL" \ --repository "$PBS_REPOSITORY" \ --backup-type host \ --backup-id lubelogger proxmox-backup-client prune "host/lubelogger" \ --repository "$PBS_REPOSITORY" \ --keep-daily 14 notify: reload systemd - name: Install backup systemd service unit ansible.builtin.copy: dest: /etc/systemd/system/lubelogger-backup.service owner: root group: root mode: "0644" content: | [Unit] Description=LubeLogger backup (pg_dump + volumes) -> PBS After=docker.service Requires=docker.service [Service] Type=oneshot ExecStart=/usr/local/bin/lubelogger-backup.sh notify: reload systemd - name: Install backup systemd timer unit ansible.builtin.copy: dest: /etc/systemd/system/lubelogger-backup.timer owner: root group: root mode: "0644" content: | [Unit] Description=Daily LubeLogger backup to PBS [Timer] OnCalendar=*-*-* 03:30:00 Persistent=true [Install] WantedBy=timers.target notify: reload systemd - name: Enable lubelogger backup timer ansible.builtin.systemd_service: name: lubelogger-backup.timer enabled: true state: started