2040 lines
118 KiB
Plaintext
2040 lines
118 KiB
Plaintext
CHAT_OUTPUT_BEGIN
|
|
COMMAND_ID=BACKUP-PIPELINE-DEFINITION-AUDIT-061
|
|
STATUS=OK
|
|
RC=0
|
|
HOST=pve01
|
|
MODE=read-only
|
|
COMPONENT=backup-audit
|
|
REFERENCE_REGISTER_CHECK=OK
|
|
REFERENCE_SHA256=5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e
|
|
ERROR_REGISTER_CHECK=OK
|
|
ERROR_REGISTER_SHA256=f6d592c8d53021fe9feeb81a7e0cca33f4b44501143f6378290486e46d250bb1
|
|
COMMAND_SHA256=08de7a8820803f855426b27b3ecfd2e646209715ff5ac4aba48b73fa45623b28
|
|
DUPLICATE_FAILED_COMMAND_BLOCKED=false
|
|
EXECUTION_STARTED=true
|
|
CHANGES_MADE=false
|
|
SANITIZED=yes
|
|
SECRETS_INCLUDED=no
|
|
PRIVATE_ADDRESSES_INCLUDED=no
|
|
RAW_EVIDENCE_SHA256=5b51699fff305570e41040468ef3f04a84e21c0c977695ed1834aa40c01946b5
|
|
SANITIZED_OUTPUT_SHA256=384c3f223883553a582cbf25ff144f7ff8a0a1dc79110ffe089b7154a12aed74
|
|
OUTPUT_BEGIN
|
|
===== TIMER dpkg-db-backup.timer =====
|
|
# /usr/lib/systemd/system/dpkg-db-backup.timer
|
|
[Unit]
|
|
Description=Daily dpkg database backup timer
|
|
Documentation=man:dpkg(1)
|
|
|
|
[Timer]
|
|
OnCalendar=daily
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE dpkg-db-backup.service =====
|
|
# /usr/lib/systemd/system/dpkg-db-backup.service
|
|
[Unit]
|
|
Description=Daily dpkg database backup service
|
|
Documentation=man:dpkg(1)
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/libexec/dpkg/dpkg-db-backup
|
|
|
|
# /etc/systemd/system/dpkg-db-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/libexec/dpkg/dpkg-db-backup ; argv[]=/usr/libexec/dpkg/dpkg-db-backup ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER filebrowser-backup.timer =====
|
|
# /etc/systemd/system/filebrowser-backup.timer
|
|
[Unit]
|
|
Description=Run File Browser backup
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 03:35:00
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE filebrowser-backup.service =====
|
|
# /etc/systemd/system/filebrowser-backup.service
|
|
[Unit]
|
|
Description=File Browser backup
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/root/filebrowser-backup.sh
|
|
|
|
# /etc/systemd/system/filebrowser-backup.service.d/10-superseded-noop.conf
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/local/sbin/homelab-superseded-unit-ok filebrowser-backup.service superseded_by_current_appbackup_restore_proof
|
|
|
|
# /etc/systemd/system/filebrowser-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-superseded-unit-ok ; argv[]=/usr/local/sbin/homelab-superseded-unit-ok filebrowser-backup.service superseded_by_current_appbackup_restore_proof ; ignore_errors=no ; start_time=[Tue 2026-07-21 03:35:14 MSK] ; stop_time=[Tue 2026-07-21 03:35:14 MSK] ; pid=2211390 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-alertmanager-backup.timer =====
|
|
# /etc/systemd/system/homelab-alertmanager-backup.timer
|
|
[Unit]
|
|
Description=Daily Alertmanager two-cloud backup
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 06:35:00
|
|
RandomizedDelaySec=10m
|
|
Persistent=true
|
|
Unit=homelab-alertmanager-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-alertmanager-backup.service =====
|
|
# /etc/systemd/system/homelab-alertmanager-backup.service
|
|
[Unit]
|
|
Description=Alertmanager encrypted two-cloud application backup
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-alertmanager-backup-run
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-alertmanager-backup-run ; argv[]=/usr/local/sbin/homelab-alertmanager-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 06:40:25 MSK] ; stop_time=[Tue 2026-07-21 06:40:54 MSK] ; pid=2820982 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-appbackup-dockge-stacks.timer =====
|
|
# /etc/systemd/system/homelab-appbackup-dockge-stacks.timer
|
|
[Unit]
|
|
Description=Daily homelab app-level backup timer for dockge-stacks
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 03:40:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-appbackup-dockge-stacks.service =====
|
|
# /etc/systemd/system/homelab-appbackup-dockge-stacks.service
|
|
[Unit]
|
|
Description=Homelab app-level backup for dockge-stacks
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/appbackupctl run
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run dockge-stacks
|
|
|
|
# /etc/systemd/system/homelab-appbackup-dockge-stacks.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/appbackupctl ; argv[]=/usr/local/sbin/appbackupctl run ; ignore_errors=no ; start_time=[Tue 2026-07-21 03:51:25 MSK] ; stop_time=[Tue 2026-07-21 03:51:53 MSK] ; pid=2261529 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-appbackup-mariadb-batch.timer =====
|
|
# /etc/systemd/system/homelab-appbackup-mariadb-batch.timer
|
|
[Unit]
|
|
Description=Daily Homelab MariaDB app batch backup timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 05:35:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-appbackup-mariadb-batch.service =====
|
|
# /etc/systemd/system/homelab-appbackup-mariadb-batch.service
|
|
[Unit]
|
|
Description=Homelab MariaDB app batch backup
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/mariadb-apps-backup-run
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run bookstack
|
|
|
|
# /etc/systemd/system/homelab-appbackup-mariadb-batch.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/mariadb-apps-backup-run ; argv[]=/usr/local/sbin/mariadb-apps-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 05:46:14 MSK] ; stop_time=[Tue 2026-07-21 05:46:44 MSK] ; pid=2623964 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-appbackup-npmplus-edge.timer =====
|
|
# /etc/systemd/system/homelab-appbackup-npmplus-edge.timer
|
|
[Unit]
|
|
Description=Daily homelab app-level backup timer for npmplus-edge
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:05:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-appbackup-npmplus-edge.service =====
|
|
# /etc/systemd/system/homelab-appbackup-npmplus-edge.service
|
|
[Unit]
|
|
Description=Homelab app-level backup for npmplus-edge
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/npmplus-edge-backup-run
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run npmplus-edge
|
|
|
|
# /etc/systemd/system/homelab-appbackup-npmplus-edge.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/npmplus-edge-backup-run ; argv[]=/usr/local/sbin/npmplus-edge-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 04:19:17 MSK] ; stop_time=[Tue 2026-07-21 04:19:48 MSK] ; pid=2360589 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-appbackup-postgres-batch.timer =====
|
|
# /etc/systemd/system/homelab-appbackup-postgres-batch.timer
|
|
[Unit]
|
|
Description=Daily Homelab Postgres app batch backup timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 05:10:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-appbackup-postgres-batch.service =====
|
|
# /etc/systemd/system/homelab-appbackup-postgres-batch.service
|
|
[Unit]
|
|
Description=Homelab Postgres app batch backup
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/postgres-apps-backup-run
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run authentik
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run paperless
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run immich
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run netbox
|
|
|
|
# /etc/systemd/system/homelab-appbackup-postgres-batch.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/postgres-apps-backup-run ; argv[]=/usr/local/sbin/postgres-apps-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 05:29:05 MSK] ; stop_time=[Tue 2026-07-21 05:32:29 MSK] ; pid=2568901 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-appbackup-sqlite-batch.timer =====
|
|
# /etc/systemd/system/homelab-appbackup-sqlite-batch.timer
|
|
[Unit]
|
|
Description=Daily Homelab SQLite app batch backup timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:45:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-appbackup-sqlite-batch.service =====
|
|
# /etc/systemd/system/homelab-appbackup-sqlite-batch.service
|
|
[Unit]
|
|
Description=Homelab SQLite app batch backup
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/sqlite-apps-backup-run
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run vaultwarden
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run gitea
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run uptime-kuma
|
|
ExecStartPost=/usr/local/sbin/appbackupctl retention 14 dry-run gotify
|
|
|
|
# /etc/systemd/system/homelab-appbackup-sqlite-batch.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/sqlite-apps-backup-run ; argv[]=/usr/local/sbin/sqlite-apps-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 04:57:14 MSK] ; stop_time=[Tue 2026-07-21 05:00:36 MSK] ; pid=2476638 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-authentik-backup.timer =====
|
|
# /etc/systemd/system/homelab-authentik-backup.timer
|
|
[Unit]
|
|
Description=Run Homelab Authentik backup chain daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:50:00
|
|
RandomizedDelaySec=10min
|
|
Persistent=true
|
|
Unit=homelab-authentik-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-authentik-backup.service =====
|
|
# /etc/systemd/system/homelab-authentik-backup.service
|
|
[Unit]
|
|
Description=Homelab Authentik backup chain
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-authentik
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-authentik ; argv[]=/usr/local/sbin/homelab-backup-authentik ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-auto-backup.timer =====
|
|
# /etc/systemd/system/homelab-auto-backup.timer
|
|
[Unit]
|
|
Description=Run homelab automatic full backup weekly
|
|
|
|
[Timer]
|
|
OnCalendar=Sun *-*-* 03:30:00
|
|
Persistent=true
|
|
RandomizedDelaySec=20m
|
|
Unit=homelab-auto-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-auto-backup.service =====
|
|
# /etc/systemd/system/homelab-auto-backup.service
|
|
[Unit]
|
|
Description=Homelab automatic full backup with retention
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/root/homelab-auto-backup-with-retention.sh
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
|
|
# /etc/systemd/system/homelab-auto-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/root/homelab-auto-backup-with-retention.sh ; argv[]=/root/homelab-auto-backup-with-retention.sh ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-backup-coverage-matrix.timer =====
|
|
# /etc/systemd/system/homelab-backup-coverage-matrix.timer
|
|
[Unit]
|
|
Description=Homelab backup coverage matrix timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 08:35:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-backup-coverage-matrix.service =====
|
|
# /etc/systemd/system/homelab-backup-coverage-matrix.service
|
|
[Unit]
|
|
Description=Homelab backup coverage matrix
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-coverage-matrix
|
|
|
|
# /etc/systemd/system/homelab-backup-coverage-matrix.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-coverage-matrix ; argv[]=/usr/local/sbin/homelab-backup-coverage-matrix ; ignore_errors=no ; start_time=[Tue 2026-07-21 08:50:14 MSK] ; stop_time=[Tue 2026-07-21 08:50:15 MSK] ; pid=3277860 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-backup-freshness.timer =====
|
|
# /etc/systemd/system/homelab-backup-freshness.timer
|
|
[Unit]
|
|
Description=Run homelab backup freshness collector daily
|
|
|
|
[Timer]
|
|
OnCalendar=daily
|
|
Persistent=true
|
|
RandomizedDelaySec=20m
|
|
Unit=homelab-backup-freshness.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-backup-freshness.service =====
|
|
# /etc/systemd/system/homelab-backup-freshness.service
|
|
[Unit]
|
|
Description=Homelab backup freshness collector
|
|
Documentation=man:systemd.service(5)
|
|
After=local-fs.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
EnvironmentFile=-/etc/default/homelab-backup-freshness
|
|
ExecStart=/usr/local/sbin/homelab-backup-freshness.sh
|
|
|
|
# /etc/systemd/system/homelab-backup-freshness.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-freshness.sh ; argv[]=/usr/local/sbin/homelab-backup-freshness.sh ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-backup-healthcheck.timer =====
|
|
# /etc/systemd/system/homelab-backup-healthcheck.timer
|
|
[Unit]
|
|
Description=Run homelab backup healthcheck daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 07:00:00
|
|
Persistent=true
|
|
RandomizedDelaySec=10m
|
|
Unit=homelab-backup-healthcheck.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-backup-healthcheck.service =====
|
|
# /etc/systemd/system/homelab-backup-healthcheck.service
|
|
[Unit]
|
|
Description=Homelab backup healthcheck
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/root/homelab-backup-healthcheck-wrapper.sh
|
|
|
|
# /etc/systemd/system/homelab-backup-healthcheck.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/root/homelab-backup-healthcheck-wrapper.sh ; argv[]=/root/homelab-backup-healthcheck-wrapper.sh ; ignore_errors=no ; start_time=[Tue 2026-07-21 07:05:30 MSK] ; stop_time=[Tue 2026-07-21 07:05:43 MSK] ; pid=2900293 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-backup-matrix-refresh.timer =====
|
|
# /etc/systemd/system/homelab-backup-matrix-refresh.timer
|
|
[Unit]
|
|
Description=Refresh unified homelab backup matrix state
|
|
|
|
[Timer]
|
|
OnBootSec=2min
|
|
OnUnitActiveSec=5min
|
|
AccuracySec=30s
|
|
Persistent=true
|
|
Unit=homelab-backup-matrix-refresh.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-backup-matrix-refresh.service =====
|
|
# /etc/systemd/system/homelab-backup-matrix-refresh.service
|
|
[Unit]
|
|
Description=Generate unified homelab backup matrix state
|
|
After=local-fs.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-matrix-refresh
|
|
TimeoutStartSec=5min
|
|
Result=exit-code
|
|
ExecMainStatus=1
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-matrix-refresh ; argv[]=/usr/local/sbin/homelab-backup-matrix-refresh ; ignore_errors=no ; start_time=[Tue 2026-07-21 10:02:41 MSK] ; stop_time=[Tue 2026-07-21 10:02:42 MSK] ; pid=3525445 ; code=exited ; status=1 }
|
|
ActiveState=failed
|
|
===== TIMER homelab-backup-sla-health.timer =====
|
|
# /etc/systemd/system/homelab-backup-sla-health.timer
|
|
[Unit]
|
|
Description=Homelab backup freshness SLA health timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 08:00:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-backup-sla-health.service =====
|
|
# /etc/systemd/system/homelab-backup-sla-health.service
|
|
[Unit]
|
|
Description=Homelab backup freshness SLA health
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-sla-health
|
|
|
|
# /etc/systemd/system/homelab-backup-sla-health.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-sla-health ; argv[]=/usr/local/sbin/homelab-backup-sla-health ; ignore_errors=no ; start_time=[Tue 2026-07-21 08:07:25 MSK] ; stop_time=[Tue 2026-07-21 08:07:26 MSK] ; pid=3122093 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-beszel-backup.timer =====
|
|
# /etc/systemd/system/homelab-beszel-backup.timer
|
|
[Unit]
|
|
Description=Daily Beszel encrypted two-cloud backup
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 06:45:00
|
|
RandomizedDelaySec=10m
|
|
Persistent=true
|
|
Unit=homelab-beszel-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-beszel-backup.service =====
|
|
# /etc/systemd/system/homelab-beszel-backup.service
|
|
[Unit]
|
|
Description=Beszel encrypted two-cloud application backup
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-beszel-backup-run
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-beszel-backup-run ; argv[]=/usr/local/sbin/homelab-beszel-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 06:47:47 MSK] ; stop_time=[Tue 2026-07-21 06:48:22 MSK] ; pid=2848350 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-blackbox-exporter-backup.timer =====
|
|
# /etc/systemd/system/homelab-blackbox-exporter-backup.timer
|
|
[Unit]
|
|
Description=Daily Blackbox Exporter encrypted two-cloud backup
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 06:55:00
|
|
RandomizedDelaySec=10m
|
|
Persistent=true
|
|
Unit=homelab-blackbox-exporter-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-blackbox-exporter-backup.service =====
|
|
# /etc/systemd/system/homelab-blackbox-exporter-backup.service
|
|
[Unit]
|
|
Description=Blackbox Exporter encrypted two-cloud application backup
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-blackbox-exporter-backup-run
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-blackbox-exporter-backup-run ; argv[]=/usr/local/sbin/homelab-blackbox-exporter-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 06:57:30 MSK] ; stop_time=[Tue 2026-07-21 06:57:54 MSK] ; pid=2876084 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-cluster-admin-incident-engine-backup.timer =====
|
|
# /etc/systemd/system/homelab-cluster-admin-incident-engine-backup.timer
|
|
[Unit]
|
|
Description=Daily Cluster Admin Incident Engine two-cloud backup
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 07:25:00
|
|
RandomizedDelaySec=15m
|
|
Persistent=true
|
|
Unit=homelab-cluster-admin-incident-engine-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-cluster-admin-incident-engine-backup.service =====
|
|
# /etc/systemd/system/homelab-cluster-admin-incident-engine-backup.service
|
|
[Unit]
|
|
Description=Cluster Admin Incident Engine encrypted two-cloud backup
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-cluster-admin-incident-engine-backup-run
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-cluster-admin-incident-engine-backup-run ; argv[]=/usr/local/sbin/homelab-cluster-admin-incident-engine-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 07:36:14 MSK] ; stop_time=[Tue 2026-07-21 07:36:40 MSK] ; pid=3010566 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-crypto-portfolio-backup.timer =====
|
|
# /etc/systemd/system/homelab-crypto-portfolio-backup.timer
|
|
[Unit]
|
|
Description=Daily Gram Crypto portfolio backup
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 06:25:00
|
|
RandomizedDelaySec=15m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-crypto-portfolio-backup.service =====
|
|
# /etc/systemd/system/homelab-crypto-portfolio-backup.service
|
|
[Unit]
|
|
Description=Gram Crypto portfolio two-cloud backup
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/crypto-portfolio-backup-run
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/crypto-portfolio-backup-run ; argv[]=/usr/local/sbin/crypto-portfolio-backup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 06:32:25 MSK] ; stop_time=[Tue 2026-07-21 06:32:50 MSK] ; pid=2794060 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-edge-vm-vzdump-backup.timer =====
|
|
# /etc/systemd/system/homelab-edge-vm-vzdump-backup.timer
|
|
[Unit]
|
|
Description=Run Homelab edge-vm VM-level backup chain weekly
|
|
|
|
[Timer]
|
|
OnCalendar=Sun *-*-* 06:20:00
|
|
RandomizedDelaySec=20min
|
|
Persistent=true
|
|
Unit=homelab-edge-vm-vzdump-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-edge-vm-vzdump-backup.service =====
|
|
# /etc/systemd/system/homelab-edge-vm-vzdump-backup.service
|
|
[Unit]
|
|
Description=Homelab edge-vm VM-level vzdump backup chain
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-edge-vm-vzdump
|
|
|
|
# /etc/systemd/system/homelab-edge-vm-vzdump-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-edge-vm-vzdump ; argv[]=/usr/local/sbin/homelab-backup-edge-vm-vzdump ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-emergency-backup.timer =====
|
|
# /etc/systemd/system/homelab-emergency-backup.timer
|
|
[Unit]
|
|
Description=Daily homelab emergency/config backup timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 03:10:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-emergency-backup.service =====
|
|
# /etc/systemd/system/homelab-emergency-backup.service
|
|
[Unit]
|
|
Description=Homelab emergency/config backup to two encrypted clouds
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/backupctl run
|
|
ExecStartPost=/usr/local/sbin/backup-retention 14 dry-run
|
|
|
|
# /etc/systemd/system/homelab-emergency-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/backupctl ; argv[]=/usr/local/sbin/backupctl run ; ignore_errors=no ; start_time=[Tue 2026-07-21 03:13:14 MSK] ; stop_time=[Tue 2026-07-21 03:13:42 MSK] ; pid=2137825 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-extended-appbackup.timer =====
|
|
# /etc/systemd/system/homelab-extended-appbackup.timer
|
|
[Unit]
|
|
Description=Homelab extended P1/P2 appbackup timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 05:55:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-extended-appbackup.service =====
|
|
# /etc/systemd/system/homelab-extended-appbackup.service
|
|
[Unit]
|
|
Description=Homelab extended P1/P2 appbackup run
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-extended-appbackup-run
|
|
|
|
# /etc/systemd/system/homelab-extended-appbackup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-extended-appbackup-run ; argv[]=/usr/local/sbin/homelab-extended-appbackup-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 05:57:30 MSK] ; stop_time=[Tue 2026-07-21 06:06:46 MSK] ; pid=2671623 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-gitea-backup.timer =====
|
|
# /etc/systemd/system/homelab-gitea-backup.timer
|
|
[Unit]
|
|
Description=Run Homelab Gitea backup chain daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 05:10:00
|
|
RandomizedDelaySec=10min
|
|
Persistent=true
|
|
Unit=homelab-gitea-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-gitea-backup.service =====
|
|
# /etc/systemd/system/homelab-gitea-backup.service
|
|
[Unit]
|
|
Description=Homelab Gitea backup chain
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-gitea
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-gitea ; argv[]=/usr/local/sbin/homelab-backup-gitea ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-gitea-secondary-backup.timer =====
|
|
# /etc/systemd/system/homelab-gitea-secondary-backup.timer
|
|
[Unit]
|
|
Description=Daily verified Gitea backup to pve03
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:20:00
|
|
RandomizedDelaySec=10m
|
|
Persistent=true
|
|
Unit=homelab-gitea-secondary-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-gitea-secondary-backup.service =====
|
|
# /etc/systemd/system/homelab-gitea-secondary-backup.service
|
|
[Unit]
|
|
Description=Create and copy a verified Gitea backup to pve03
|
|
After=pve-cluster.service network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-gitea-secondary-backup
|
|
TimeoutStartSec=2h
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
UMask=0077
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-gitea-secondary-backup ; argv[]=/usr/local/sbin/homelab-gitea-secondary-backup ; ignore_errors=no ; start_time=[Tue 2026-07-21 04:28:14 MSK] ; stop_time=[Tue 2026-07-21 04:28:18 MSK] ; pid=2376819 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-legacy-monitoring-backups.timer =====
|
|
# /etc/systemd/system/homelab-legacy-monitoring-backups.timer
|
|
[Unit]
|
|
Description=Daily legacy monitoring applications two-cloud backup batch
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 07:05:00
|
|
RandomizedDelaySec=15m
|
|
Persistent=true
|
|
Unit=homelab-legacy-monitoring-backups.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-legacy-monitoring-backups.service =====
|
|
# /etc/systemd/system/homelab-legacy-monitoring-backups.service
|
|
[Unit]
|
|
Description=Legacy monitoring applications encrypted two-cloud backup batch
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-legacy-monitoring-backups-run
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-legacy-monitoring-backups-run ; argv[]=/usr/local/sbin/homelab-legacy-monitoring-backups-run ; ignore_errors=no ; start_time=[Tue 2026-07-21 07:18:55 MSK] ; stop_time=[Tue 2026-07-21 07:21:45 MSK] ; pid=2950676 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-mail-cloud-critical-upload.timer =====
|
|
# /etc/systemd/system/homelab-mail-cloud-critical-upload.timer
|
|
[Unit]
|
|
Description=Daily Homelab Mail Cloud critical/small baseline upload
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 06:40:00
|
|
RandomizedDelaySec=15m
|
|
Persistent=true
|
|
Unit=homelab-mail-cloud-critical-upload.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-mail-cloud-critical-upload.service =====
|
|
# /etc/systemd/system/homelab-mail-cloud-critical-upload.service
|
|
[Unit]
|
|
Description=Homelab Mail Cloud critical/small baseline upload
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-mail-cloud-critical-upload
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-mail-cloud-critical-upload ; argv[]=/usr/local/sbin/homelab-mail-cloud-critical-upload ; ignore_errors=no ; start_time=[Tue 2026-07-21 06:40:25 MSK] ; stop_time=[Tue 2026-07-21 06:42:44 MSK] ; pid=2820985 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-mail-cloud-edge-vm-upload.timer =====
|
|
# /etc/systemd/system/homelab-mail-cloud-edge-vm-upload.timer
|
|
[Unit]
|
|
Description=Weekly Homelab Mail Cloud edge-vm large chunked upload
|
|
|
|
[Timer]
|
|
OnCalendar=Sun *-*-* 09:30:00
|
|
RandomizedDelaySec=30m
|
|
Persistent=true
|
|
Unit=homelab-mail-cloud-edge-vm-upload.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-mail-cloud-edge-vm-upload.service =====
|
|
# /etc/systemd/system/homelab-mail-cloud-edge-vm-upload.service
|
|
[Unit]
|
|
Description=Homelab Mail Cloud edge-vm large chunked upload
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-mail-cloud-edge-vm-upload
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-mail-cloud-edge-vm-upload ; argv[]=/usr/local/sbin/homelab-mail-cloud-edge-vm-upload ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-mail-cloud-nextcloud-vm-upload.timer =====
|
|
# /etc/systemd/system/homelab-mail-cloud-nextcloud-vm-upload.timer
|
|
[Unit]
|
|
Description=Run Homelab Mail Cloud Nextcloud VM upload daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 07:30:00
|
|
RandomizedDelaySec=30m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-mail-cloud-nextcloud-vm-upload.service =====
|
|
# /etc/systemd/system/homelab-mail-cloud-nextcloud-vm-upload.service
|
|
[Unit]
|
|
Description=Homelab Mail Cloud Nextcloud VM vzdump upload
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-mail-cloud-nextcloud-vm-upload
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-mail-cloud-nextcloud-vm-upload ; argv[]=/usr/local/sbin/homelab-mail-cloud-nextcloud-vm-upload ; ignore_errors=no ; start_time=[Tue 2026-07-21 07:53:41 MSK] ; stop_time=[Tue 2026-07-21 07:56:26 MSK] ; pid=3068432 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-mail-cloud-restore-drill.timer =====
|
|
# /etc/systemd/system/homelab-mail-cloud-restore-drill.timer
|
|
[Unit]
|
|
Description=Weekly Homelab Mail Cloud restore drill
|
|
|
|
[Timer]
|
|
OnCalendar=Mon *-*-* 07:20:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
Unit=homelab-mail-cloud-restore-drill.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-mail-cloud-restore-drill.service =====
|
|
# /etc/systemd/system/homelab-mail-cloud-restore-drill.service
|
|
[Unit]
|
|
Description=Homelab Mail Cloud restore drill
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-mail-cloud-restore-drill
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
|
|
# /etc/systemd/system/homelab-mail-cloud-restore-drill.service.d/10-superseded-noop.conf
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/local/sbin/homelab-superseded-unit-ok homelab-mail-cloud-restore-drill.service superseded_by_safety_net_restore_check
|
|
|
|
# /etc/systemd/system/homelab-mail-cloud-restore-drill.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-superseded-unit-ok ; argv[]=/usr/local/sbin/homelab-superseded-unit-ok homelab-mail-cloud-restore-drill.service superseded_by_safety_net_restore_check ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-npmplus-kuma-config-backup.timer =====
|
|
# /etc/systemd/system/homelab-npmplus-kuma-config-backup.timer
|
|
[Unit]
|
|
Description=Run Homelab NPMplus + Kuma config backup chain daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:20:00
|
|
RandomizedDelaySec=10min
|
|
Persistent=true
|
|
Unit=homelab-npmplus-kuma-config-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-npmplus-kuma-config-backup.service =====
|
|
# /etc/systemd/system/homelab-npmplus-kuma-config-backup.service
|
|
[Unit]
|
|
Description=Homelab NPMplus + Kuma config backup chain
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-npmplus-kuma-configs
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-npmplus-kuma-configs ; argv[]=/usr/local/sbin/homelab-backup-npmplus-kuma-configs ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-router-running-config-mail-cloud.timer =====
|
|
# /etc/systemd/system/homelab-router-running-config-mail-cloud.timer
|
|
[Unit]
|
|
Description=Run Homelab router running-config Mail-cloud backup daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 05:15:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-router-running-config-mail-cloud.service =====
|
|
# /etc/systemd/system/homelab-router-running-config-mail-cloud.service
|
|
[Unit]
|
|
Description=Homelab router running-config Mail-cloud backup
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-router-running-config-mail-cloud
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-router-running-config-mail-cloud ; argv[]=/usr/local/sbin/homelab-router-running-config-mail-cloud ; ignore_errors=no ; start_time=[Tue 2026-07-21 05:17:57 MSK] ; stop_time=[Tue 2026-07-21 05:18:05 MSK] ; pid=2540965 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-vaultwarden-backup.timer =====
|
|
# /etc/systemd/system/homelab-vaultwarden-backup.timer
|
|
[Unit]
|
|
Description=Run Homelab Vaultwarden backup chain daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 05:30:00
|
|
RandomizedDelaySec=10min
|
|
Persistent=true
|
|
Unit=homelab-vaultwarden-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-vaultwarden-backup.service =====
|
|
# /etc/systemd/system/homelab-vaultwarden-backup.service
|
|
[Unit]
|
|
Description=Homelab Vaultwarden backup chain
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-vaultwarden
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-vaultwarden ; argv[]=/usr/local/sbin/homelab-backup-vaultwarden ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-verified-backup-health.timer =====
|
|
# /etc/systemd/system/homelab-verified-backup-health.timer
|
|
[Unit]
|
|
Description=Homelab verified backup health evidence timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 06:30:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-verified-backup-health.service =====
|
|
# /etc/systemd/system/homelab-verified-backup-health.service
|
|
[Unit]
|
|
Description=Homelab verified backup health evidence
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-backup-health-evidence
|
|
|
|
# /etc/systemd/system/homelab-verified-backup-health.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-backup-health-evidence ; argv[]=/usr/local/sbin/homelab-backup-health-evidence ; ignore_errors=no ; start_time=[Tue 2026-07-21 06:43:54 MSK] ; stop_time=[Tue 2026-07-21 06:45:16 MSK] ; pid=2823792 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-vm-backup-health.timer =====
|
|
# /etc/systemd/system/homelab-vm-backup-health.timer
|
|
[Unit]
|
|
Description=Homelab VM backup health timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 07:30:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-vm-backup-health.service =====
|
|
# /etc/systemd/system/homelab-vm-backup-health.service
|
|
[Unit]
|
|
Description=Homelab VM backup health
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-vm-backup-health
|
|
|
|
# /etc/systemd/system/homelab-vm-backup-health.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-vm-backup-health ; argv[]=/usr/local/sbin/homelab-vm-backup-health ; ignore_errors=no ; start_time=[Tue 2026-07-21 07:36:59 MSK] ; stop_time=[Tue 2026-07-21 07:36:59 MSK] ; pid=3011738 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-vm-backup-policy.timer =====
|
|
# /etc/systemd/system/homelab-vm-backup-policy.timer
|
|
[Unit]
|
|
Description=Homelab VM backup policy and feasibility health timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 08:18:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-vm-backup-policy.service =====
|
|
# /etc/systemd/system/homelab-vm-backup-policy.service
|
|
[Unit]
|
|
Description=Homelab VM backup policy and feasibility health
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-vm-backup-policy
|
|
|
|
# /etc/systemd/system/homelab-vm-backup-policy.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-vm-backup-policy ; argv[]=/usr/local/sbin/homelab-vm-backup-policy ; ignore_errors=no ; start_time=[Tue 2026-07-21 08:30:07 MSK] ; stop_time=[Tue 2026-07-21 08:30:13 MSK] ; pid=3198902 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-vm-full-backup.timer =====
|
|
# /etc/systemd/system/homelab-vm-full-backup.timer
|
|
[Unit]
|
|
Description=Daily full backup timer for VM170 and VM171
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 02:15:00
|
|
Persistent=true
|
|
AccuracySec=1min
|
|
Unit=homelab-vm-full-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-vm-full-backup.service =====
|
|
# /etc/systemd/system/homelab-vm-full-backup.service
|
|
[Unit]
|
|
Description=Full vzdump backup of VM170 and VM171 to offhost and two clouds
|
|
After=network-online.target pve-cluster.service
|
|
Wants=network-online.target
|
|
ConditionPathIsMountPoint=/mnt/staging
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-vm-full-backup
|
|
TimeoutStartSec=infinity
|
|
Nice=10
|
|
IOSchedulingClass=idle
|
|
IOSchedulingPriority=7
|
|
UMask=0077
|
|
|
|
# /etc/systemd/system/homelab-vm-full-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-vm-full-backup ; argv[]=/usr/local/sbin/homelab-vm-full-backup ; ignore_errors=no ; start_time=[Tue 2026-07-21 02:15:05 MSK] ; stop_time=[Tue 2026-07-21 03:09:43 MSK] ; pid=1933641 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-vm-local-dumps-2cloud.timer =====
|
|
# /etc/systemd/system/homelab-vm-local-dumps-2cloud.timer
|
|
[Unit]
|
|
Description=Homelab VM/CT existing local dumps two-cloud verifier timer
|
|
|
|
[Timer]
|
|
OnCalendar=Sun *-*-* 10:00:00
|
|
RandomizedDelaySec=30m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-vm-local-dumps-2cloud.service =====
|
|
# /etc/systemd/system/homelab-vm-local-dumps-2cloud.service
|
|
[Unit]
|
|
Description=Homelab VM/CT existing local dumps two-cloud verifier
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/homelab-vm-local-dumps-2cloud
|
|
|
|
# /etc/systemd/system/homelab-vm-local-dumps-2cloud.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-vm-local-dumps-2cloud ; argv[]=/usr/local/sbin/homelab-vm-local-dumps-2cloud ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER homelab-vm160-remote-backup.timer =====
|
|
# /etc/systemd/system/homelab-vm160-remote-backup.timer
|
|
[Unit]
|
|
Description=Daily VM160 remote full-image backup
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:10:00
|
|
RandomizedDelaySec=10m
|
|
Unit=homelab-vm160-remote-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE homelab-vm160-remote-backup.service =====
|
|
# /etc/systemd/system/homelab-vm160-remote-backup.service
|
|
[Unit]
|
|
Description=VM160 full-image backup streamed from pve02 to pve03
|
|
After=network-online.target pve-cluster.service
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
TimeoutStartSec=6h
|
|
ExecStart=/usr/local/sbin/homelab-vm160-remote-backup
|
|
Result=exit-code
|
|
ExecMainStatus=1
|
|
ExecStart={ path=/usr/local/sbin/homelab-vm160-remote-backup ; argv[]=/usr/local/sbin/homelab-vm160-remote-backup ; ignore_errors=no ; start_time=[Tue 2026-07-21 02:39:12 MSK] ; stop_time=[Tue 2026-07-21 02:39:14 MSK] ; pid=2028253 ; code=exited ; status=1 }
|
|
ActiveState=failed
|
|
===== TIMER immich-media-backup.timer =====
|
|
# /etc/systemd/system/immich-media-backup.timer
|
|
[Unit]
|
|
Description=Daily Immich media backup timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 08:15:00
|
|
Persistent=true
|
|
RandomizedDelaySec=10m
|
|
Unit=immich-media-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE immich-media-backup.service =====
|
|
# /etc/systemd/system/immich-media-backup.service
|
|
[Unit]
|
|
Description=Immich media backup to staging
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/root/immich-media-backup.sh
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
|
|
# /etc/systemd/system/immich-media-backup.service.d/10-superseded-noop.conf
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/local/sbin/homelab-superseded-unit-ok immich-media-backup.service superseded_by_current_appbackup_or_trust_proof
|
|
|
|
# /etc/systemd/system/immich-media-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-superseded-unit-ok ; argv[]=/usr/local/sbin/homelab-superseded-unit-ok immich-media-backup.service superseded_by_current_appbackup_or_trust_proof ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER memos-backup.timer =====
|
|
# /etc/systemd/system/memos-backup.timer
|
|
[Unit]
|
|
Description=Run Memos data backup daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 08:35:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE memos-backup.service =====
|
|
# /etc/systemd/system/memos-backup.service
|
|
[Unit]
|
|
Description=Memos data backup to pve01 staging
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/root/memos-backup.sh
|
|
|
|
# /etc/systemd/system/memos-backup.service.d/10-superseded-noop.conf
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/local/sbin/homelab-superseded-unit-ok memos-backup.service superseded_by_current_appbackup_or_trust_proof
|
|
|
|
# /etc/systemd/system/memos-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-superseded-unit-ok ; argv[]=/usr/local/sbin/homelab-superseded-unit-ok memos-backup.service superseded_by_current_appbackup_or_trust_proof ; ignore_errors=no ; start_time=[Tue 2026-07-21 08:41:14 MSK] ; stop_time=[Tue 2026-07-21 08:41:14 MSK] ; pid=3239605 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== TIMER netbird-vps-backup.timer =====
|
|
# /etc/systemd/system/netbird-vps-backup.timer
|
|
[Unit]
|
|
Description=Run NetBird VPS backup daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:25:00
|
|
Persistent=true
|
|
RandomizedDelaySec=15m
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE netbird-vps-backup.service =====
|
|
# /etc/systemd/system/netbird-vps-backup.service
|
|
[Unit]
|
|
Description=NetBird VPS backup to pve01 staging
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/root/netbird-vps-backup.sh
|
|
|
|
# /etc/systemd/system/netbird-vps-backup.service.d/10-superseded-noop.conf
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/local/sbin/homelab-superseded-unit-ok netbird-vps-backup.service superseded_by_current_appbackup_or_trust_proof
|
|
|
|
# /etc/systemd/system/netbird-vps-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-superseded-unit-ok ; argv[]=/usr/local/sbin/homelab-superseded-unit-ok netbird-vps-backup.service superseded_by_current_appbackup_or_trust_proof ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER paperless-backup.timer =====
|
|
# /etc/systemd/system/paperless-backup.timer
|
|
[Unit]
|
|
Description=Run Paperless backup daily
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 08:50:00
|
|
RandomizedDelaySec=20m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE paperless-backup.service =====
|
|
# /etc/systemd/system/paperless-backup.service
|
|
[Unit]
|
|
Description=Paperless backup to pve01 staging
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/root/paperless-backup.sh
|
|
|
|
# /etc/systemd/system/paperless-backup.service.d/10-superseded-noop.conf
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/local/sbin/homelab-superseded-unit-ok paperless-backup.service superseded_by_current_appbackup_or_trust_proof
|
|
|
|
# /etc/systemd/system/paperless-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/homelab-superseded-unit-ok ; argv[]=/usr/local/sbin/homelab-superseded-unit-ok paperless-backup.service superseded_by_current_appbackup_or_trust_proof ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER skladchik-reports-monitor-backup-restore-check.timer =====
|
|
# /etc/systemd/system/skladchik-reports-monitor-backup-restore-check.timer
|
|
[Unit]
|
|
Description=Weekly restore-check of Skladchik reports monitor cloud backups
|
|
|
|
[Timer]
|
|
OnCalendar=Sun *-*-* 04:55:00
|
|
RandomizedDelaySec=30min
|
|
Persistent=true
|
|
Unit=skladchik-reports-monitor-backup-restore-check.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE skladchik-reports-monitor-backup-restore-check.service =====
|
|
# /etc/systemd/system/skladchik-reports-monitor-backup-restore-check.service
|
|
[Unit]
|
|
Description=Restore-check Skladchik reports monitor cloud backups
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/skladchik-reports-monitor-backup-restore-check
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
|
|
# /etc/systemd/system/skladchik-reports-monitor-backup-restore-check.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/skladchik-reports-monitor-backup-restore-check ; argv[]=/usr/local/sbin/skladchik-reports-monitor-backup-restore-check ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
|
ActiveState=inactive
|
|
===== TIMER skladchik-reports-monitor-backup.timer =====
|
|
# /etc/systemd/system/skladchik-reports-monitor-backup.timer
|
|
[Unit]
|
|
Description=Daily Skladchik reports monitor backup to encrypted clouds
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:25:00
|
|
RandomizedDelaySec=15min
|
|
Persistent=true
|
|
Unit=skladchik-reports-monitor-backup.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
===== SERVICE skladchik-reports-monitor-backup.service =====
|
|
# /etc/systemd/system/skladchik-reports-monitor-backup.service
|
|
[Unit]
|
|
Description=Backup Skladchik reports monitor from edge-vm to encrypted clouds
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/sbin/skladchik-reports-monitor-backup
|
|
Nice=10
|
|
IOSchedulingClass=best-effort
|
|
IOSchedulingPriority=7
|
|
|
|
# /etc/systemd/system/skladchik-reports-monitor-backup.service.d/90-backup-matrix-refresh.conf
|
|
[Service]
|
|
ExecStartPost=-/usr/bin/systemctl start --no-block homelab-backup-matrix-refresh.service
|
|
Result=success
|
|
ExecMainStatus=0
|
|
ExecStart={ path=/usr/local/sbin/skladchik-reports-monitor-backup ; argv[]=/usr/local/sbin/skladchik-reports-monitor-backup ; ignore_errors=no ; start_time=[Tue 2026-07-21 04:34:48 MSK] ; stop_time=[Tue 2026-07-21 04:35:22 MSK] ; pid=2399885 ; code=exited ; status=0 }
|
|
ActiveState=inactive
|
|
===== REFERENCED_SCRIPTS =====
|
|
----- /opt/homelab-backup/backup-emergency-pack-v0.sh -----
|
|
41:rclone listremotes > "$PAYLOAD/inventory/rclone_remotes.txt" 2>&1 || true
|
|
59:It is deleted only after both encrypted cloud copies are uploaded and fully verified.
|
|
60:Recovery requires offline/break-glass access to rclone crypt credentials.
|
|
65:rm -rf "$PAYLOAD"
|
|
79: "archive_size_bytes": $ARCHIVE_SIZE_BYTES,
|
|
83: "local_staging_policy": "delete_after_both_clouds_verified",
|
|
90:echo "[STEP] local checksum"
|
|
91:(cd "$STAGE" && sha256sum "$ARCHIVE" manifest.json latest-backup-index.json > checksums.sha256 && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null)
|
|
94:rclone copy "$STAGE" "$REMOTE_A_JOB" --exclude "$ARCHIVE" --exclude "$ARCHIVE.sha256" --transfers=4 --checkers=8 --retries=5 --low-level-retries=20 --stats=30s
|
|
95:homelab-rclone-copy-chunked "$STAGE/$ARCHIVE" "$REMOTE_A_JOB/$ARCHIVE"
|
|
98:rclone copy "$STAGE" "$REMOTE_B_JOB" --exclude "$ARCHIVE" --exclude "$ARCHIVE.sha256" --transfers=4 --checkers=8 --retries=5 --low-level-retries=20 --stats=30s
|
|
99:homelab-rclone-copy-chunked "$STAGE/$ARCHIVE" "$REMOTE_B_JOB/$ARCHIVE"
|
|
102:rclone copy "$REMOTE_A_JOB" "$VERIFY/cloud_a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10; homelab-rehydrate-chunked-dir "$VERIFY/cloud_a"
|
|
103:(cd "$VERIFY/cloud_a" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB_ID" '.job_id == $job' manifest.json >/dev/null)
|
|
106:rclone copy "$REMOTE_B_JOB" "$VERIFY/cloud_b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10; homelab-rehydrate-chunked-dir "$VERIFY/cloud_b"
|
|
107:(cd "$VERIFY/cloud_b" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB_ID" '.job_id == $job' manifest.json >/dev/null)
|
|
110:(cd "$STAGE" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null)
|
|
113:rclone copyto "$STAGE/latest-backup-index.json" "$REMOTE_A_LATEST"
|
|
114:rclone copyto "$STAGE/latest-backup-index.json" "$REMOTE_B_LATEST"
|
|
115:rclone cat "$REMOTE_A_LATEST" | jq -e --arg job "$JOB_ID" '.job_id == $job' >/dev/null
|
|
116:rclone cat "$REMOTE_B_LATEST" | jq -e --arg job "$JOB_ID" '.job_id == $job' >/dev/null
|
|
124: "archive_size_bytes": $ARCHIVE_SIZE_BYTES,
|
|
128: "local_backup_deleted": true
|
|
132:echo "[STEP] delete local staging and verification copies"
|
|
133:rm -rf "$STAGE" "$VERIFY"
|
|
138:echo "[SUCCESS] uploaded to 2 clouds, verified from both clouds, local staging deleted"
|
|
----- /opt/homelab-backup/backup-emergency-pack-v0.sh.bak-chunkall-20260710T011410Z -----
|
|
41:rclone listremotes > "$PAYLOAD/inventory/rclone_remotes.txt" 2>&1 || true
|
|
59:It is deleted only after both encrypted cloud copies are uploaded and fully verified.
|
|
60:Recovery requires offline/break-glass access to rclone crypt credentials.
|
|
65:rm -rf "$PAYLOAD"
|
|
79: "archive_size_bytes": $ARCHIVE_SIZE_BYTES,
|
|
83: "local_staging_policy": "delete_after_both_clouds_verified",
|
|
90:echo "[STEP] local checksum"
|
|
91:(cd "$STAGE" && sha256sum "$ARCHIVE" manifest.json latest-backup-index.json > checksums.sha256 && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null)
|
|
94:rclone copy "$STAGE" "$REMOTE_A_JOB" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 --stats=30s
|
|
97:rclone copy "$STAGE" "$REMOTE_B_JOB" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 --stats=30s
|
|
100:rclone copy "$REMOTE_A_JOB" "$VERIFY/cloud_a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10
|
|
101:(cd "$VERIFY/cloud_a" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB_ID" '.job_id == $job' manifest.json >/dev/null)
|
|
104:rclone copy "$REMOTE_B_JOB" "$VERIFY/cloud_b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10
|
|
105:(cd "$VERIFY/cloud_b" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB_ID" '.job_id == $job' manifest.json >/dev/null)
|
|
108:(cd "$STAGE" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null)
|
|
111:rclone copyto "$STAGE/latest-backup-index.json" "$REMOTE_A_LATEST"
|
|
112:rclone copyto "$STAGE/latest-backup-index.json" "$REMOTE_B_LATEST"
|
|
113:rclone cat "$REMOTE_A_LATEST" | jq -e --arg job "$JOB_ID" '.job_id == $job' >/dev/null
|
|
114:rclone cat "$REMOTE_B_LATEST" | jq -e --arg job "$JOB_ID" '.job_id == $job' >/dev/null
|
|
122: "archive_size_bytes": $ARCHIVE_SIZE_BYTES,
|
|
126: "local_backup_deleted": true
|
|
130:echo "[STEP] delete local staging and verification copies"
|
|
131:rm -rf "$STAGE" "$VERIFY"
|
|
136:echo "[SUCCESS] uploaded to 2 clouds, verified from both clouds, local staging deleted"
|
|
----- /usr/local/sbin/appbackup-dockge-stacks -----
|
|
25:echo "[STEP] copy app data"
|
|
30:rm -rf "$PAYLOAD"
|
|
42: "archive_size_bytes": $SIZE,
|
|
46: "local_staging_policy": "delete_after_both_clouds_verified",
|
|
51:echo "[STEP] local checksum"
|
|
52:(cd "$STAGE" && sha256sum "$ARCHIVE" manifest.json latest-backup-index.json > checksums.sha256 && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e . manifest.json >/dev/null)
|
|
54:echo "[STEP] upload cloud A metadata"; rclone copy "$STAGE" "$RA" --exclude "$ARCHIVE" --exclude "$ARCHIVE.sha256" --transfers=4 --checkers=8 --retries=5 --low-level-retries=20 --stats=30s
|
|
55:echo "[STEP] upload cloud A archive chunks"; rclone deletefile "$RA/$ARCHIVE" >/dev/null 2>&1 || true; CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-rclone-copy-chunked "$STAGE/$ARCHIVE" "$RA/$ARCHIVE"
|
|
56:echo "[STEP] upload cloud B metadata"; rclone copy "$STAGE" "$RB" --exclude "$ARCHIVE" --exclude "$ARCHIVE.sha256" --transfers=4 --checkers=8 --retries=5 --low-level-retries=20 --stats=30s
|
|
57:echo "[STEP] upload cloud B archive chunks"; rclone deletefile "$RB/$ARCHIVE" >/dev/null 2>&1 || true; CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-rclone-copy-chunked "$STAGE/$ARCHIVE" "$RB/$ARCHIVE"
|
|
58:echo "[STEP] verify cloud A chunked"; CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-stage-verify-chunked "$RA" "$ARCHIVE" "$VERIFY/a" "$JOB"
|
|
59:echo "[STEP] verify cloud B chunked"; CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-stage-verify-chunked "$RB" "$ARCHIVE" "$VERIFY/b" "$JOB"
|
|
60:echo "[STEP] upload latest index"; rclone copyto "$STAGE/latest-backup-index.json" "$RAL"; rclone copyto "$STAGE/latest-backup-index.json" "$RBL"; rclone cat "$RAL" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null; rclone cat "$RBL" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null
|
|
68: "archive_size_bytes": $SIZE,
|
|
72: "local_backup_deleted": true
|
|
75:echo "[STEP] delete local staging and verification"
|
|
76:rm -rf "$STAGE" "$VERIFY"
|
|
79:echo "[SUCCESS] app backup uploaded to 2 clouds, verified from both clouds, local staging deleted"
|
|
----- /usr/local/sbin/appbackup-dockge-stacks.bak-chunkall-20260710T011410Z -----
|
|
25:echo "[STEP] copy app data"
|
|
30:rm -rf "$PAYLOAD"
|
|
42: "archive_size_bytes": $SIZE,
|
|
46: "local_staging_policy": "delete_after_both_clouds_verified",
|
|
51:echo "[STEP] local checksum"
|
|
52:(cd "$STAGE" && sha256sum "$ARCHIVE" manifest.json latest-backup-index.json > checksums.sha256 && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e . manifest.json >/dev/null)
|
|
54:rclone copy "$STAGE" "$RA" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 --stats=30s
|
|
56:rclone copy "$STAGE" "$RB" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 --stats=30s
|
|
58:rclone copy "$RA" "$VERIFY/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10
|
|
59:(cd "$VERIFY/a" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
61:rclone copy "$RB" "$VERIFY/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10
|
|
62:(cd "$VERIFY/b" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
64:(cd "$STAGE" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e . manifest.json >/dev/null)
|
|
66:rclone copyto "$STAGE/latest-backup-index.json" "$RAL"
|
|
67:rclone copyto "$STAGE/latest-backup-index.json" "$RBL"
|
|
68:rclone cat "$RAL" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null
|
|
69:rclone cat "$RBL" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null
|
|
77: "archive_size_bytes": $SIZE,
|
|
81: "local_backup_deleted": true
|
|
84:echo "[STEP] delete local staging and verification"
|
|
85:rm -rf "$STAGE" "$VERIFY"
|
|
88:echo "[SUCCESS] app backup uploaded to 2 clouds, verified from both clouds, local staging deleted"
|
|
----- /usr/local/sbin/appbackup-restore-check -----
|
|
22:ROOT="/var/tmp/homelab-app-restore-check/${JOB}"
|
|
24:rm -rf "$ROOT" && mkdir -p "$ROOT/a" "$ROOT/b"
|
|
25:trap "echo \"ERROR app restore-check failed; kept: $ROOT\"; exit 1" ERR
|
|
26:echo "restore-check app=$APP job=$JOB schema=$SCHEMA"
|
|
27:rclone copy "$RA" "$ROOT/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >"${LOGBASE}-a.log" 2>&1
|
|
30:(cd "$ROOT/a" && sha256sum -c checksums.sha256 >"${LOGBASE}-a-sha.log" && ARCHIVE="$(jq -r ".archive_name" manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
31:echo "OK cloud A app restore-check"
|
|
32:rclone copy "$RB" "$ROOT/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >"${LOGBASE}-b.log" 2>&1
|
|
35:(cd "$ROOT/b" && sha256sum -c checksums.sha256 >"${LOGBASE}-b-sha.log" && ARCHIVE="$(jq -r ".archive_name" manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
36:echo "OK cloud B app restore-check"
|
|
37:rm -rf "$ROOT"
|
|
38:rmdir /var/tmp/homelab-app-restore-check 2>/dev/null || true
|
|
39:rm -f "${LOGBASE}-a.log" "${LOGBASE}-a-sha.log" "${LOGBASE}-b.log" "${LOGBASE}-b-sha.log"
|
|
41:echo "OK app restore-check both clouds"
|
|
----- /usr/local/sbin/appbackup-restore-check.bak-chunkall-20260710T011410Z -----
|
|
9:ROOT="/var/tmp/homelab-app-restore-check/${JOB}"
|
|
10:rm -rf "$ROOT" && mkdir -p "$ROOT/a" "$ROOT/b"
|
|
11:trap "echo \"ERROR app restore-check failed; kept: $ROOT\"; exit 1" ERR
|
|
12:echo "restore-check app=$APP job=$JOB"
|
|
13:rclone copy "$RA" "$ROOT/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >/tmp/app-restore-a.log 2>&1
|
|
14:(cd "$ROOT/a" && sha256sum -c checksums.sha256 >/tmp/app-restore-a-sha.log && ARCHIVE="$(jq -r .archive_name manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
15:echo "OK cloud A app restore-check"
|
|
16:rclone copy "$RB" "$ROOT/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >/tmp/app-restore-b.log 2>&1
|
|
17:(cd "$ROOT/b" && sha256sum -c checksums.sha256 >/tmp/app-restore-b-sha.log && ARCHIVE="$(jq -r .archive_name manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
18:echo "OK cloud B app restore-check"
|
|
19:rm -rf "$ROOT"; rmdir /var/tmp/homelab-app-restore-check 2>/dev/null || true
|
|
21:echo "OK app restore-check both clouds"
|
|
----- /usr/local/sbin/appbackup-restore-check.bak-dual-read-20260711T051924Z -----
|
|
9:ROOT="/var/tmp/homelab-app-restore-check/${JOB}"
|
|
10:rm -rf "$ROOT" && mkdir -p "$ROOT/a" "$ROOT/b"
|
|
11:trap "echo \"ERROR app restore-check failed; kept: $ROOT\"; exit 1" ERR
|
|
12:echo "restore-check app=$APP job=$JOB"
|
|
13:rclone copy "$RA" "$ROOT/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >/tmp/app-restore-a.log 2>&1; homelab-rehydrate-chunked-dir "$ROOT/a" >>/tmp/app-restore-a.log 2>&1
|
|
14:(cd "$ROOT/a" && sha256sum -c checksums.sha256 >/tmp/app-restore-a-sha.log && ARCHIVE="$(jq -r .archive_name manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
15:echo "OK cloud A app restore-check"
|
|
16:rclone copy "$RB" "$ROOT/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >/tmp/app-restore-b.log 2>&1; homelab-rehydrate-chunked-dir "$ROOT/b" >>/tmp/app-restore-b.log 2>&1
|
|
17:(cd "$ROOT/b" && sha256sum -c checksums.sha256 >/tmp/app-restore-b-sha.log && ARCHIVE="$(jq -r .archive_name manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
18:echo "OK cloud B app restore-check"
|
|
19:rm -rf "$ROOT"; rmdir /var/tmp/homelab-app-restore-check 2>/dev/null || true
|
|
21:echo "OK app restore-check both clouds"
|
|
----- /usr/local/sbin/appbackup-restore-check.bak-flat-read-20260711T052854Z -----
|
|
22:ROOT="/var/tmp/homelab-app-restore-check/${JOB}"
|
|
24:rm -rf "$ROOT" && mkdir -p "$ROOT/a" "$ROOT/b"
|
|
25:trap "echo \"ERROR app restore-check failed; kept: $ROOT\"; exit 1" ERR
|
|
26:echo "restore-check app=$APP job=$JOB schema=$SCHEMA"
|
|
27:rclone copy "$RA" "$ROOT/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >"${LOGBASE}-a.log" 2>&1
|
|
29:(cd "$ROOT/a" && sha256sum -c checksums.sha256 >"${LOGBASE}-a-sha.log" && ARCHIVE="$(jq -r ".archive_name" manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
30:echo "OK cloud A app restore-check"
|
|
31:rclone copy "$RB" "$ROOT/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >"${LOGBASE}-b.log" 2>&1
|
|
33:(cd "$ROOT/b" && sha256sum -c checksums.sha256 >"${LOGBASE}-b-sha.log" && ARCHIVE="$(jq -r ".archive_name" manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
34:echo "OK cloud B app restore-check"
|
|
35:rm -rf "$ROOT"
|
|
36:rmdir /var/tmp/homelab-app-restore-check 2>/dev/null || true
|
|
37:rm -f "${LOGBASE}-a.log" "${LOGBASE}-a-sha.log" "${LOGBASE}-b.log" "${LOGBASE}-b-sha.log"
|
|
39:echo "OK app restore-check both clouds"
|
|
----- /usr/local/sbin/appbackup-restore-check.bak-flat-read-v2-20260711T053129Z -----
|
|
22:ROOT="/var/tmp/homelab-app-restore-check/${JOB}"
|
|
24:rm -rf "$ROOT" && mkdir -p "$ROOT/a" "$ROOT/b"
|
|
25:trap "echo \"ERROR app restore-check failed; kept: $ROOT\"; exit 1" ERR
|
|
26:echo "restore-check app=$APP job=$JOB schema=$SCHEMA"
|
|
27:rclone copy "$RA" "$ROOT/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >"${LOGBASE}-a.log" 2>&1
|
|
29:(cd "$ROOT/a" && sha256sum -c checksums.sha256 >"${LOGBASE}-a-sha.log" && ARCHIVE="$(jq -r ".archive_name" manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
30:echo "OK cloud A app restore-check"
|
|
31:rclone copy "$RB" "$ROOT/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >"${LOGBASE}-b.log" 2>&1
|
|
33:(cd "$ROOT/b" && sha256sum -c checksums.sha256 >"${LOGBASE}-b-sha.log" && ARCHIVE="$(jq -r ".archive_name" manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
34:echo "OK cloud B app restore-check"
|
|
35:rm -rf "$ROOT"
|
|
36:rmdir /var/tmp/homelab-app-restore-check 2>/dev/null || true
|
|
37:rm -f "${LOGBASE}-a.log" "${LOGBASE}-a-sha.log" "${LOGBASE}-b.log" "${LOGBASE}-b-sha.log"
|
|
39:echo "OK app restore-check both clouds"
|
|
----- /usr/local/sbin/appbackup-retention -----
|
|
32:trap "rm -rf \"$WORK\"" EXIT
|
|
35: rclone lsf "${REMOTE%/}" --dirs-only --max-depth 1 > "$ROOT_LIST"
|
|
36: rclone lsf "${REMOTE%/}/${NODE}/apps/${CANONICAL}" --dirs-only --max-depth 1 > "$LEGACY_LIST"
|
|
39: rclone lsf "${REMOTE%/}/hb" --dirs-only --max-depth 1 > "$HB_LIST"
|
|
40: if grep -Fxq "a/" "$HB_LIST"; then rclone lsf "${REMOTE%/}/hb/a" --dirs-only --max-depth 1 > "$NEW_LIST"; fi
|
|
73: rclone cat "${REMOTE%/}/${LATEST_REL}/manifest.json" | jq -e --arg job "$LATEST" ".job_id == \$job" >/dev/null || { echo "REFUSE latest missing/bad remote_index=$INDEX"; exit 5; }
|
|
78: if (( TOTAL <= KEEP )); then echo "nothing to delete"; continue; fi
|
|
83: [[ -n "$LATEST_REL" && "$REL" == "$LATEST_REL" ]] && { echo "REFUSE delete latest ${REL}"; exit 7; }
|
|
85: if [[ "$MODE" == apply ]]; then echo "DELETE schema=dual path=$REL"; rclone purge "$TARGET"; else echo "WOULD_DELETE schema=dual path=$REL"; fi
|
|
----- /usr/local/sbin/appbackup-retention.bak-dual-read-20260711T051924Z -----
|
|
15:for REMOTE in "$REMOTE_A" "$REMOTE_B"; do BASE="${REMOTE%/}/${NODE}/apps/${APP}"; echo "--- $BASE ---"; if [[ "$MODE" == "apply" ]]; then rclone cat "$BASE/$LATEST/manifest.json" | jq -e --arg job "$LATEST" ".job_id == \$job" >/dev/null || { echo "REFUSE latest missing/bad on $BASE"; exit 4; }; fi; mapfile -t DIRS < <(rclone lsf "$BASE" --dirs-only 2>/dev/null | while read -r D; do D="${D%/}"; [[ "$D" == homelab-${NODE}-app-${APP}-* ]] && echo "$D"; done | sort); TOTAL="${#DIRS[@]}"; echo "total=$TOTAL keep=$KEEP mode=$MODE latest=${LATEST:-none}"; if (( TOTAL <= KEEP )); then echo "nothing to delete"; continue; fi; DELETE_COUNT=$((TOTAL-KEEP)); for ((i=0; i<DELETE_COUNT; i++)); do TARGET_NAME="${DIRS[$i]}"; TARGET="$BASE/$TARGET_NAME"; [[ -n "$LATEST" && "$TARGET_NAME" == "$LATEST" ]] && { echo "REFUSE delete latest $TARGET"; exit 5; }; if [[ "$MODE" == "apply" ]]; then echo "DELETE $TARGET"; rclone purge "$TARGET"; else echo "WOULD_DELETE $TARGET"; fi; done; done
|
|
----- /usr/local/sbin/backupctl -----
|
|
12: check) bash -n "$SCRIPT" && [[ -f "$STATE" ]] && jq -e ".status == \"success\" and .local_backup_deleted == true" "$STATE" >/dev/null && echo "OK backup framework" ;;
|
|
13: restore-check) backup-restore-check ;;
|
|
14: audit) backupctl check && backup-restore-check && backupctl retention 7 dry-run && backup-report >/dev/null && echo "OK audit finished" ;;
|
|
16: remotes) source /etc/homelab-backup.env && NODE="$(hostname -s)" && echo "A=$REMOTE_A" && echo "B=$REMOTE_B" && rclone lsd "${REMOTE_A%/}/${NODE}/emergency-pack" | tail -n 5 && rclone lsd "${REMOTE_B%/}/${NODE}/emergency-pack" | tail -n 5 ;;
|
|
19: *) echo "usage: backupctl run|status|lastlog|check|restore-check|audit|report|remotes|retention|timer"; exit 2 ;;
|
|
----- /usr/local/sbin/backup-restore-check -----
|
|
8:ROOT="/var/tmp/homelab-restore-check/${JOB}"
|
|
9:rm -rf "$ROOT" && mkdir -p "$ROOT/a" "$ROOT/b"
|
|
10:trap 'echo "ERROR restore-check failed; kept: "; exit 1' ERR
|
|
11:echo "restore-check job=$JOB"
|
|
12:rclone copy "$RA" "$ROOT/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >/tmp/homelab-restore-a.log 2>&1; homelab-rehydrate-chunked-dir "$ROOT/a" >>/tmp/homelab-restore-a.log 2>&1
|
|
13:(cd "$ROOT/a" && sha256sum -c checksums.sha256 >/tmp/homelab-restore-a-sha.log && ARCHIVE="$(jq -r .archive_name manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
14:echo "OK cloud A restore-check"
|
|
15:rclone copy "$RB" "$ROOT/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >/tmp/homelab-restore-b.log 2>&1; homelab-rehydrate-chunked-dir "$ROOT/b" >>/tmp/homelab-restore-b.log 2>&1
|
|
16:(cd "$ROOT/b" && sha256sum -c checksums.sha256 >/tmp/homelab-restore-b-sha.log && ARCHIVE="$(jq -r .archive_name manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
17:echo "OK cloud B restore-check"
|
|
18:rm -rf "$ROOT"
|
|
20:echo "OK restore-check both clouds"
|
|
----- /usr/local/sbin/backup-restore-check.bak-chunkall-20260710T011410Z -----
|
|
8:ROOT="/var/tmp/homelab-restore-check/${JOB}"
|
|
9:rm -rf "$ROOT" && mkdir -p "$ROOT/a" "$ROOT/b"
|
|
10:trap 'echo "ERROR restore-check failed; kept: "; exit 1' ERR
|
|
11:echo "restore-check job=$JOB"
|
|
12:rclone copy "$RA" "$ROOT/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >/tmp/homelab-restore-a.log 2>&1
|
|
13:(cd "$ROOT/a" && sha256sum -c checksums.sha256 >/tmp/homelab-restore-a-sha.log && ARCHIVE="$(jq -r .archive_name manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
14:echo "OK cloud A restore-check"
|
|
15:rclone copy "$RB" "$ROOT/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 >/tmp/homelab-restore-b.log 2>&1
|
|
16:(cd "$ROOT/b" && sha256sum -c checksums.sha256 >/tmp/homelab-restore-b-sha.log && ARCHIVE="$(jq -r .archive_name manifest.json)" && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
17:echo "OK cloud B restore-check"
|
|
18:rm -rf "$ROOT"
|
|
20:echo "OK restore-check both clouds"
|
|
----- /usr/local/sbin/backup-retention -----
|
|
18: if [[ "$MODE" == "apply" ]]; then rclone cat "$BASE/$LATEST/manifest.json" | jq -e --arg job "$LATEST" ".job_id == \$job" >/dev/null || { echo "REFUSE latest missing/bad on $BASE"; exit 4; }; fi
|
|
19: mapfile -t DIRS < <(rclone lsf "$BASE" --dirs-only 2>/dev/null | while read -r D; do D="${D%/}"; [[ "$D" == homelab-${NODE}-${JOB}-* ]] && echo "$D"; done | sort)
|
|
22: if (( TOTAL <= KEEP )); then echo "nothing to delete"; continue; fi
|
|
24: for ((i=0; i<DELETE_COUNT; i++)); do TARGET_NAME="${DIRS[$i]}"; TARGET="$BASE/$TARGET_NAME"; [[ -n "$LATEST" && "$TARGET_NAME" == "$LATEST" ]] && { echo "REFUSE delete latest $TARGET"; exit 5; }; if [[ "$MODE" == "apply" ]]; then echo "DELETE $TARGET"; rclone purge "$TARGET"; else echo "WOULD_DELETE $TARGET"; fi; done
|
|
----- /usr/local/sbin/homelab-backup-edge-vm-vzdump -----
|
|
7:BASE_DIR="/mnt/staging/vzdump/edge-vm-vzdump"
|
|
8:OFFHOST_DIR="/mnt/staging/offhost/edge-vm-vzdump-from-pve03"
|
|
40:REMOTE_OUT="$(remote "OUT=/tmp/edge_vm_vzdump_${VMID}_${TS}.out; ERR=/tmp/edge_vm_vzdump_${VMID}_${TS}.err; : > \$OUT; : > \$ERR; vzdump '$VMID' --mode snapshot --compress zstd --dumpdir '$RUN_DIR' --remove 0 >\$OUT 2>\$ERR; RC=\$?; ARCHIVE=\$(find '$RUN_DIR' -maxdepth 1 -type f -name 'vzdump-qemu-${VMID}-*.vma.zst' -printf '%T@ %p\n' | sort -n | tail -n1 | cut -d' ' -f2-); LOGFILE=\$(find '$RUN_DIR' -maxdepth 1 -type f -name 'vzdump-qemu-${VMID}-*.log' -printf '%T@ %p\n' | sort -n | tail -n1 | cut -d' ' -f2-); SIZE=0; SHA=none; if [ -n \"\$ARCHIVE\" ] && [ -f \"\$ARCHIVE\" ]; then SIZE=\$(stat -c %s \"\$ARCHIVE\"); SHA=\$(sha256sum \"\$ARCHIVE\" | awk '{print \$1}'); fi; echo VZDUMP_RC=\$RC; echo ARCHIVE=\$ARCHIVE; echo LOGFILE=\$LOGFILE; echo SIZE=\$SIZE; echo SHA=\$SHA; echo OUT_TAIL=\$(tail -n 6 \$OUT | tr '\n' '|'); echo ERR_TAIL=\$(tail -n 6 \$ERR | tr '\n' '|')")"
|
|
62:dest "mkdir -p '$OFFHOST_DIR' && rm -f '$DEST_PATH.tmp' '$DEST_PATH.sha256'"
|
|
74:echo "STATUS=OK TS=$TS TYPE=edge-vm-vzdump-backup NODE=$NODE VMID=$VMID ARCHIVE=$ARCHIVE SIZE=$SIZE SHA256=$SHA SCSI1_BACKUP0=yes NOTES=timer_run" > "$HEALTH_DIR/edge-vm-vzdump-backup.txt"
|
|
75:echo "STATUS=OK TS=$TS TYPE=edge-vm-vzdump-offhost NODE=$NODE VMID=$VMID HOST=pve02 DEST=$DEST_PATH SIZE=$SIZE SHA256=$SHA NOTES=timer_run" > "$HEALTH_DIR/edge-vm-vzdump-offhost.txt"
|
|
76:echo "STATUS=OK TS=$TS TYPE=edge-vm-vzdump-restore-verify HOST=pve02 VMID=$VMID ARCHIVE=$DEST_PATH SIZE=$SIZE SHA256=$SHA ZSTD_RC=0 VMA_RC=0 NOTES=timer_run" > "$HEALTH_DIR/edge-vm-vzdump-restore.txt"
|
|
77:chmod 0644 "$HEALTH_DIR/edge-vm-vzdump-backup.txt" "$HEALTH_DIR/edge-vm-vzdump-offhost.txt" "$HEALTH_DIR/edge-vm-vzdump-restore.txt"
|
|
79:remote "find '$BASE_DIR' -mindepth 1 -maxdepth 1 -type d -name 'edge-vm-*' -printf '%T@ %p\n' | sort -nr | awk 'NR>${KEEP_LOCAL}{print \$2}' | xargs -r rm -rf"
|
|
80:dest "find '$OFFHOST_DIR' -maxdepth 1 -type f -name 'vzdump-qemu-${VMID}-*.vma.zst' -printf '%T@ %p\n' | sort -nr | awk 'NR>${KEEP_OFFHOST}{print \$2}' | while read f; do rm -f \"\$f\" \"\$f.sha256\"; done"
|
|
----- /usr/local/sbin/homelab-capacity-risk -----
|
|
32:LARGEST_BYTES="$(find /var/lib/vz/dump -maxdepth 1 -type f \( -name "vzdump-qemu-*.vma.zst" -o -name "vzdump-lxc-*.tar.zst" \) -printf "%s\n" 2>/dev/null | sort -n | tail -n1)"
|
|
----- /usr/local/sbin/homelab-chat-run -----
|
|
272: re.compile(r"(?i)\brclone\.conf\b"),
|
|
388: "reference_register_checked": True,
|
|
390: "error_register_checked": True,
|
|
489: rm -f \
|
|
----- /usr/local/sbin/homelab-edge-vm-offhost-freshness -----
|
|
9:OFFHOST_DIR=/mnt/staging/offhost/edge-vm-vzdump-from-pve03
|
|
85: /var/lib/vz/dump/vzdump-qemu-130-*.vma.zst) ;;
|
|
96:dest_size="$(field DEST_SIZE <<<"$inventory_out")"
|
|
100:[[ "$dest_size" =~ ^[0-9]+$ && "$count" =~ ^[0-9]+$ && "$available" =~ ^[0-9]+$ ]]
|
|
103:last_oldest_size=0
|
|
107: [[ "$dest_size" == "$SOURCE_SIZE" && "$dest_sha" == "$SOURCE_SHA" ]]
|
|
110: "$dest_size" "$last_oldest" "$last_oldest_size" "$last_oldest_sha" "$count" "$RESERVE")"
|
|
115: [[ "$dest_size" -ge 0 && "$dest_size" -lt "$SOURCE_SIZE" ]]
|
|
119: last_oldest_size="$(field OLDEST_SIZE <<<"$inventory_out")"
|
|
122: [[ "$last_oldest_size" =~ ^[0-9]+$ && "$last_oldest_size" -gt 1000000000 ]]
|
|
126: "$dest_size" "$last_oldest" "$last_oldest_size" "$last_oldest_sha" "$before_count" "$RESERVE")"
|
|
130: [[ "$(field DEST_SIZE <<<"$inventory_out")" == "$dest_size" ]]
|
|
136: remaining=$((SOURCE_SIZE-dest_size))
|
|
140: copy_out="$(run_pve03 copy "$SOURCE_PATH" "$SOURCE_SIZE" "$SOURCE_SHA" "$DST_IP" "$OFFHOST_DIR")"
|
|
141: grep -Fq 'SOURCE_COPY_STATUS=OK' <<<"$copy_out"
|
|
146: "$dest_size" "$last_oldest" "$last_oldest_size" "$last_oldest_sha" "$expected_final_count" "$RESERVE")"
|
|
156:printf 'STATUS=OK TS=%s TYPE=edge-vm-vzdump-backup NODE=%s VMID=%s ARCHIVE=%s SIZE=%s SHA256=%s NOTES=nightly_existing_dump_freshness\n' \
|
|
158: >"$HEALTH_DIR/edge-vm-vzdump-backup.txt"
|
|
159:printf 'STATUS=OK TS=%s TYPE=edge-vm-vzdump-offhost NODE=%s VMID=%s HOST=%s DEST=%s SIZE=%s SHA256=%s NOTES=nightly_existing_dump_freshness\n' \
|
|
161: >"$HEALTH_DIR/edge-vm-vzdump-offhost.txt"
|
|
162:printf 'STATUS=OK TS=%s TYPE=edge-vm-vzdump-restore-verify HOST=%s VMID=%s ARCHIVE=%s SIZE=%s SHA256=%s ZSTD_RC=0 VMA_RC=0 NOTES=nightly_existing_dump_freshness\n' \
|
|
164: >"$HEALTH_DIR/edge-vm-vzdump-restore.txt"
|
|
167: "$HEALTH_DIR/edge-vm-vzdump-backup.txt" \
|
|
168: "$HEALTH_DIR/edge-vm-vzdump-offhost.txt" \
|
|
169: "$HEALTH_DIR/edge-vm-vzdump-restore.txt"
|
|
----- /usr/local/sbin/homelab-extended-appbackup-run -----
|
|
12:run_one(){ APP="$1"; HOST="$2"; PATHS="$3"; NOTE="$4"; CONS="$5"; JOB_ID="homelab-${NODE}-app-${APP}-${RUN_TS}"; export JOB_ID; SHORT_TS="${RUN_TS:2:6}-${RUN_TS:9:6}"; export BACKUP_PATH_REL="$(homelab-backup-path job a "$APP" "$SHORT_TS")"; STAGE="${STAGING_ROOT}/${JOB_ID}"; PAYLOAD="$STAGE/payload"; ARCHIVE="${JOB_ID}.tar.gz"; LOG="/tmp/extended-appbackup-${APP}-${RUN_TS}.log"; rm -rf "$STAGE"; mkdir -p "$PAYLOAD/local"; echo "### app=$APP" >> "$REPORT"; echo "host=$HOST" >> "$REPORT"; echo "source_note=$NOTE" >> "$REPORT"; ssh -n -o BatchMode=yes -o ConnectTimeout=30 "$HOST" "sudo tar -C / --ignore-failed-read --exclude=.env --exclude=*.env --exclude=.env.* --exclude=*.bak* -czf - $PATHS" > "$PAYLOAD/local/${APP}-data.tar.gz" 2>"$LOG"; TAR_RC=$?; if [ "$TAR_RC" -eq 0 ] && tar -tzf "$PAYLOAD/local/${APP}-data.tar.gz" >/dev/null 2>&1; then SIZE="$(stat -c%s "$PAYLOAD/local/${APP}-data.tar.gz" 2>/dev/null || echo 0)"; echo "archive_payload_size_bytes=$SIZE" >> "$REPORT"; if [ "$SIZE" -le 128 ]; then echo "backup=BAD reason=archive_too_small" >> "$REPORT"; BAD=$((BAD+1)); rm -rf "$STAGE"; else sha256sum "$PAYLOAD/local/${APP}-data.tar.gz" > "$PAYLOAD/local/${APP}-data.tar.gz.sha256"; jq -n --arg type "extended-appbackup" --arg app "$APP" --arg host "$HOST" --arg source_note "$NOTE" --arg archive_payload_size_bytes "$SIZE" --arg env_files_read "no" --arg secret_values_printed "no" --arg consistency "$CONS" "{type:\$type,app_name:\$app,host:\$host,source_note:\$source_note,archive_payload_size_bytes:(\$archive_payload_size_bytes|tonumber),env_files_read:\$env_files_read,secret_values_printed:\$secret_values_printed,consistency:\$consistency}" > "$STAGE/metadata.json"; tar -C "$PAYLOAD" -czf "$STAGE/$ARCHIVE" .; rm -rf "$PAYLOAD"; JOB_ID="$JOB_ID" homelab-stage-2cloud-flat "$APP" "$STAGE" "$ARCHIVE" > "$LOG" 2>&1; RC=$?; if [ "$RC" -eq 0 ]; then echo "backup=OK" >> "$REPORT"; grep -E "^\[STEP\]|^\[SUCCESS\]" "$LOG" >> "$REPORT"; appbackupctl restore-check "$APP" >> "$REPORT" 2>&1 && echo "restore_check=OK" >> "$REPORT" || echo "restore_check=WARN_non_registry" >> "$REPORT"; OK=$((OK+1)); else echo "backup=BAD rc=$RC" >> "$REPORT"; grep -E "^\[ERROR\]|\[STEP\]|ERROR|error|failed|Failed|required|missing|denied|forbidden|checksum|rclone|copy|mkdir|jq|tar" "$LOG" | tail -n 60 >> "$REPORT"; BAD=$((BAD+1)); fi; fi; else echo "tar=BAD rc=$TAR_RC" >> "$REPORT"; grep -E "ERROR|error|failed|Failed|denied|No such|Cannot|tar:" "$LOG" | tail -n 40 >> "$REPORT"; BAD=$((BAD+1)); rm -rf "$STAGE"; fi; echo >> "$REPORT"; }
|
|
21:run_one healthchecks "$MON" "var/lib/healthchecks opt/stacks/healthchecks/local_settings.py" "healthchecks data plus local settings" "emergency_data_config_archive"
|
|
----- /usr/local/sbin/homelab-golden-state-extended-overlay -----
|
|
26:rclone copyto "$JSON" "$RA" >/tmp/golden-state-upload-a.log 2>&1 || BAD=$((BAD+1))
|
|
27:rclone copyto "$JSON" "$RB" >/tmp/golden-state-upload-b.log 2>&1 || BAD=$((BAD+1))
|
|
28:rclone cat "$RA" 2>/dev/null | jq -e --arg cp "$CP" ".control_plane_job == \$cp" >/dev/null || BAD=$((BAD+1))
|
|
29:rclone cat "$RB" 2>/dev/null | jq -e --arg cp "$CP" ".control_plane_job == \$cp" >/dev/null || BAD=$((BAD+1))
|
|
----- /usr/local/sbin/homelab-golden-state-index -----
|
|
28:rclone copyto "$JSON" "$RA" >/tmp/golden-state-upload-a.log 2>&1 || BAD=$((BAD+1))
|
|
29:rclone copyto "$JSON" "$RB" >/tmp/golden-state-upload-b.log 2>&1 || BAD=$((BAD+1))
|
|
30:rclone cat "$RA" 2>/dev/null | jq -e --arg cp "$CP" --arg ext "$EXT" ".control_plane_job == \$cp and .health.extended_appbackup == \$ext and .extended_appbackup_health == \$ext" >/dev/null || BAD=$((BAD+1))
|
|
31:rclone cat "$RB" 2>/dev/null | jq -e --arg cp "$CP" --arg ext "$EXT" ".control_plane_job == \$cp and .health.extended_appbackup == \$ext and .extended_appbackup_health == \$ext" >/dev/null || BAD=$((BAD+1))
|
|
----- /usr/local/sbin/homelab-health-metrics -----
|
|
16:category_for_check(){
|
|
22: *backup*|*vzdump*) printf "%s" "backup" ;;
|
|
31:tier_for_check(){
|
|
34: npmplus-kuma-config-*|authentik-*|gitea-*|vaultwarden-*|netbox-*|mail-cloud-restore-drill|edge-vm-vzdump-*|mkdocs-runtime-publish|npmplus-certificate-expiry) printf "%s" "P0" ;;
|
|
69: check="${base%.txt}"
|
|
70: category="$(category_for_check "$check")"
|
|
71: tier="$(tier_for_check "$check")"
|
|
75: check_esc="$(esc_label "$check")"
|
|
79: labels="host=\"$host_esc\",check=\"$check_esc\",category=\"$cat_esc\",tier=\"$tier_esc\",file=\"$file_esc\""
|
|
----- /usr/local/sbin/homelab-ingress-standby-refresh -----
|
|
16: rm -f "$TMP_STATE" "$RELAY" "$RESOURCES"
|
|
74:run_node "$SOURCE_NODE" vzdump 130 \
|
|
78: --remove 0 \
|
|
83:"find /var/lib/vz/dump -maxdepth 1 -type f -name 'vzdump-qemu-130-*.vma.zst' -printf '%T@ %p\n' | sort -rn | head -n 1 | cut -d' ' -f2-"
|
|
106:"chattr -i '$DEST_FILE' '$DEST_FILE.sha256' '$DEST_FILE.env' 2>/dev/null || true; rm -f '$DEST_TMP'"
|
|
155: -name 'vzdump-qemu-130-*.vma.zst' \
|
|
164: rm -f "$OLD" "$OLD.sha256" "$OLD.env"
|
|
173:run_node "$SOURCE_NODE" rm -f "$SOURCE_BACKUP"
|
|
----- /usr/local/sbin/homelab-mail-cloud-critical-upload -----
|
|
50:EXCLUDED=edge-vm-vzdump-large-archive,rclone-config,secrets,raw-env
|
|
80: rclone mkdir "${R}:$REMOTE_DIR" > "$WORK/logs/${SAFE}_mkdir.out" 2>"$WORK/logs/${SAFE}_mkdir.err"
|
|
82: homelab-rclone-copy-chunked "$BUNDLE" "${R}:$REMOTE_DIR/$(basename "$BUNDLE")" > "$WORK/logs/${SAFE}_upload_bundle.out" 2>"$WORK/logs/${SAFE}_upload_bundle.err"
|
|
84: rclone copyto "$BUNDLE_SHA" "${R}:$REMOTE_DIR/$(basename "$BUNDLE_SHA")" --checksum > "$WORK/logs/${SAFE}_upload_sha.out" 2>"$WORK/logs/${SAFE}_upload_sha.err"
|
|
86: rclone copyto "$WORK/components/MANIFEST.txt" "${R}:$REMOTE_DIR/MANIFEST.txt" --checksum > "$WORK/logs/${SAFE}_upload_manifest.out" 2>"$WORK/logs/${SAFE}_upload_manifest.err"
|
|
88: rclone copyto "$WORK/components/SHA256SUMS.txt" "${R}:$REMOTE_DIR/SHA256SUMS.txt" --checksum > "$WORK/logs/${SAFE}_upload_sums.out" 2>"$WORK/logs/${SAFE}_upload_sums.err"
|
|
90: homelab-rclone-cat-chunked "${R}:$REMOTE_DIR/$(basename "$BUNDLE")" > "$WORK/download/${SAFE}-$(basename "$BUNDLE")" 2>"$WORK/logs/${SAFE}_download_bundle.err"
|
|
108: rm -f "$WORK/download/${SAFE}-$(basename "$BUNDLE")"
|
|
109: rclone lsf "${R}:$TARGET_BASE" --dirs-only 2>/dev/null | sed 's#/$##' | sort > "$WORK/logs/${SAFE}_dirs.txt"
|
|
114: [ -n "$OLD" ] && rclone purge "${R}:$TARGET_BASE/$OLD" >> "$WORK/logs/${SAFE}_retention.out" 2>>"$WORK/logs/${SAFE}_retention.err"
|
|
140: rm -rf --one-file-system "$OLD_DIR"
|
|
----- /usr/local/sbin/homelab-mail-cloud-critical-upload.bak-chunkall-20260710T011410Z -----
|
|
50:EXCLUDED=edge-vm-vzdump-large-archive,rclone-config,secrets,raw-env
|
|
80: rclone mkdir "${R}:$REMOTE_DIR" > "$WORK/logs/${SAFE}_mkdir.out" 2>"$WORK/logs/${SAFE}_mkdir.err"
|
|
82: rclone copyto "$BUNDLE" "${R}:$REMOTE_DIR/$(basename "$BUNDLE")" --checksum > "$WORK/logs/${SAFE}_upload_bundle.out" 2>"$WORK/logs/${SAFE}_upload_bundle.err"
|
|
84: rclone copyto "$BUNDLE_SHA" "${R}:$REMOTE_DIR/$(basename "$BUNDLE_SHA")" --checksum > "$WORK/logs/${SAFE}_upload_sha.out" 2>"$WORK/logs/${SAFE}_upload_sha.err"
|
|
86: rclone copyto "$WORK/components/MANIFEST.txt" "${R}:$REMOTE_DIR/MANIFEST.txt" --checksum > "$WORK/logs/${SAFE}_upload_manifest.out" 2>"$WORK/logs/${SAFE}_upload_manifest.err"
|
|
88: rclone copyto "$WORK/components/SHA256SUMS.txt" "${R}:$REMOTE_DIR/SHA256SUMS.txt" --checksum > "$WORK/logs/${SAFE}_upload_sums.out" 2>"$WORK/logs/${SAFE}_upload_sums.err"
|
|
90: rclone copyto "${R}:$REMOTE_DIR/$(basename "$BUNDLE")" "$WORK/download/${SAFE}-$(basename "$BUNDLE")" > "$WORK/logs/${SAFE}_download_bundle.out" 2>"$WORK/logs/${SAFE}_download_bundle.err"
|
|
108: rm -f "$WORK/download/${SAFE}-$(basename "$BUNDLE")"
|
|
109: rclone lsf "${R}:$TARGET_BASE" --dirs-only 2>/dev/null | sed 's#/$##' | sort > "$WORK/logs/${SAFE}_dirs.txt"
|
|
114: [ -n "$OLD" ] && rclone purge "${R}:$TARGET_BASE/$OLD" >> "$WORK/logs/${SAFE}_retention.out" 2>>"$WORK/logs/${SAFE}_retention.err"
|
|
----- /usr/local/sbin/homelab-mail-cloud-edge-vm-upload -----
|
|
10:TARGET_BASE=full/edge-vm-vzdump
|
|
60:case "$SIZE" in ""|*[!0-9]*) fail size_bad 2 ;; esac
|
|
64:case "$SOURCE" in /mnt/staging/offhost/edge-vm-vzdump-from-pve03/vzdump-qemu-130-*.vma.zst) ;; *) fail source_path_bad 2 ;; esac
|
|
111:rclone about "$TARGET_REMOTE:" > "$WORK/logs/about.out" 2>"$WORK/logs/about.err" || ABOUT_RC=$?
|
|
114:DIRS="$(rclone lsf "$TARGET_REMOTE:$TARGET_BASE" --dirs-only 2>/dev/null | sed 's#/$##' | sort || true)"
|
|
116: if rclone cat "$TARGET_REMOTE:$TARGET_BASE/$D/$BASENAME.sha256" 2>/dev/null | grep -q "$SHA"; then
|
|
172:P1 Mail Cloud edge-vm recurring chunked vzdump upload
|
|
188:rclone mkdir "$TARGET_REMOTE:$REMOTE_PARTS" > "$WORK/logs/mkdir.out" 2>"$WORK/logs/mkdir.err" || MKDIR_RC=$?
|
|
190:rclone copy "$PARTS_DIR" "$TARGET_REMOTE:$REMOTE_PARTS" --transfers 2 --checkers 4 --retries 3 --low-level-retries 10 --progress > "$WORK/logs/upload_parts.out" 2>"$WORK/logs/upload_parts.err" || UPLOAD_PARTS_RC=$?
|
|
192:rclone copyto "$WORK/$BASENAME.sha256" "$TARGET_REMOTE:$REMOTE_SHA" --checksum > "$WORK/logs/upload_sha.out" 2>"$WORK/logs/upload_sha.err" || UPLOAD_SHA_RC=$?
|
|
194:rclone copyto "$WORK/MANIFEST.txt" "$TARGET_REMOTE:$REMOTE_MANIFEST" --checksum > "$WORK/logs/upload_manifest.out" 2>"$WORK/logs/upload_manifest.err" || UPLOAD_MANIFEST_RC=$?
|
|
196:rclone copyto "$WORK/SHA256SUMS.txt" "$TARGET_REMOTE:$REMOTE_SUMS" --checksum > "$WORK/logs/upload_sums.out" 2>"$WORK/logs/upload_sums.err" || UPLOAD_SUMS_RC=$?
|
|
199:rclone size "$TARGET_REMOTE:$TARGET_DIR" --json > "$WORK/logs/remote_size.json" 2>"$WORK/logs/remote_size.err" || SIZE_RC=$?
|
|
201:rclone lsf "$TARGET_REMOTE:$REMOTE_PARTS" --format "ps" > "$WORK/logs/remote_lsf_parts.txt" 2>"$WORK/logs/remote_lsf_parts.err" || LSF_PARTS_RC=$?
|
|
203:REMOTE_BYTES="$(python3 -c 'import json; print(json.load(open("'"$WORK"'/logs/remote_size.json")).get("bytes",""))' 2>/dev/null || echo unknown)"
|
|
204:REMOTE_COUNT="$(python3 -c 'import json; print(json.load(open("'"$WORK"'/logs/remote_size.json")).get("count",""))' 2>/dev/null || echo unknown)"
|
|
207:rclone copy "$TARGET_REMOTE:$REMOTE_PARTS" "$DL_DIR/parts" --transfers 2 --checkers 4 --retries 3 --low-level-retries 10 --progress > "$WORK/logs/download_parts.out" 2>"$WORK/logs/download_parts.err" || DOWNLOAD_PARTS_RC=$?
|
|
222: rm -rf "$DL_DIR" "$PARTS_DIR"
|
|
234: rclone lsf "$TARGET_REMOTE:$TARGET_BASE" --dirs-only 2>/dev/null | sed "s#/$##" | sort > "$DIR_LIST" || RETENTION_RC=$?
|
|
239: [ -n "$OLD" ] && rclone purge "$TARGET_REMOTE:$TARGET_BASE/$OLD" >> "$WORK/logs/retention.out" 2>>"$WORK/logs/retention.err"
|
|
----- /usr/local/sbin/homelab-mail-cloud-nextcloud-vm-upload -----
|
|
8:TARGET_BASE=full/nextcloud-vm-vzdump
|
|
11:SRC_GLOB=/var/lib/vz/dump/vzdump-qemu-150-*.vma.zst
|
|
23: local delete_count="${7:-0}"
|
|
25: echo "STATUS=$status TS=$TS TYPE=mail-cloud-nextcloud-vm MODE=recurring-chunked REMOTE=$TARGET_REMOTE DEST=${TARGET_DIR:-none} ARCHIVE=${BASENAME:-none} SIZE=${SIZE:-0} SHA256=${SHA:-none} PART_SIZE=$PART_SIZE PARTS=${PART_COUNT:-0} REMOTE_PARTS=$remote_parts REMOTE_BYTES=$remote_bytes UPLOAD_OK=$upload_ok DOWNLOAD_VERIFY=$download_verify RETENTION_KEEP=$KEEP DELETE_COUNT=$delete_count ALREADY_UPLOADED=$already_uploaded SECRET_PRINTED=no NOTES=$notes" > "$HEALTH"
|
|
77:P1 Mail Cloud Nextcloud VM recurring chunked vzdump upload
|
|
93:rclone mkdir "$TARGET_REMOTE:$REMOTE_PARTS" > "$WORK/logs/mkdir.out" 2>"$WORK/logs/mkdir.err" || MKDIR_RC=$?
|
|
95:rclone copy "$PARTS_DIR" "$TARGET_REMOTE:$REMOTE_PARTS" --transfers 2 --checkers 4 --retries 3 --low-level-retries 10 > "$WORK/logs/upload_parts.out" 2>"$WORK/logs/upload_parts.err" || UPLOAD_PARTS_RC=$?
|
|
97:rclone copyto "$WORK/$BASENAME.sha256" "$TARGET_REMOTE:$REMOTE_SHA" --checksum > "$WORK/logs/upload_sha.out" 2>"$WORK/logs/upload_sha.err" || UPLOAD_SHA_RC=$?
|
|
99:rclone copyto "$WORK/MANIFEST.txt" "$TARGET_REMOTE:$REMOTE_MANIFEST" --checksum > "$WORK/logs/upload_manifest.out" 2>"$WORK/logs/upload_manifest.err" || UPLOAD_MANIFEST_RC=$?
|
|
101:rclone copyto "$WORK/SHA256SUMS.txt" "$TARGET_REMOTE:$REMOTE_SUMS" --checksum > "$WORK/logs/upload_sums.out" 2>"$WORK/logs/upload_sums.err" || UPLOAD_SUMS_RC=$?
|
|
104:rclone lsf "$TARGET_REMOTE:$REMOTE_PARTS" --format ps > "$WORK/logs/remote_lsf_parts.txt" 2>"$WORK/logs/remote_lsf_parts.err" || LSF_PARTS_RC=$?
|
|
110:rclone copy "$TARGET_REMOTE:$REMOTE_PARTS" "$DL_DIR/parts" --transfers 2 --checkers 4 --retries 3 --low-level-retries 10 > "$WORK/logs/download_parts.out" 2>"$WORK/logs/download_parts.err" || DOWNLOAD_PARTS_RC=$?
|
|
120:rclone lsf "$TARGET_REMOTE:$TARGET_BASE" --dirs-only 2>/dev/null | sed 's#/$##' | sort > "$DIR_LIST" || RETENTION_RC=$?
|
|
126: [ -n "$OLD" ] && rclone purge "$TARGET_REMOTE:$TARGET_BASE/$OLD" >> "$WORK/logs/retention.out" 2>>"$WORK/logs/retention.err"
|
|
140: rm -rf "$PARTS_DIR" "$DL_DIR"
|
|
----- /usr/local/sbin/homelab-mail-cloud-restore-drill -----
|
|
52: homelab-rclone-cat-chunked "${R}:$CRIT_DEST/$CRIT_BUNDLE" > "$OUT" 2>"$WORK/logs/${SAFE}_crit_download.err"
|
|
83: rm -f "$OUT"
|
|
108: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/MANIFEST.txt" "$WORK/edge/MANIFEST.txt" > "$WORK/logs/edge_manifest_download.out" 2>"$WORK/logs/edge_manifest_download.err"
|
|
111: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/SHA256SUMS.txt" "$WORK/edge/SHA256SUMS.txt" > "$WORK/logs/edge_sums_download.out" 2>"$WORK/logs/edge_sums_download.err"
|
|
114: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/$EDGE_ARCHIVE.sha256" "$WORK/edge/$EDGE_ARCHIVE.sha256" > "$WORK/logs/edge_archive_sha_download.out" 2>"$WORK/logs/edge_archive_sha_download.err"
|
|
117: rclone lsf "${EDGE_REMOTE}:$EDGE_DEST/parts" --format ps > "$WORK/logs/edge_parts_lsf.txt" 2>"$WORK/logs/edge_parts_lsf.err"
|
|
130: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/parts/$FIRST_PART" "$WORK/edge/$FIRST_PART" > "$WORK/logs/edge_first_part_download.out" 2>"$WORK/logs/edge_first_part_download.err"
|
|
137: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/parts/$LAST_PART" "$WORK/edge/$LAST_PART" > "$WORK/logs/edge_last_part_download.out" 2>"$WORK/logs/edge_last_part_download.err"
|
|
168: rm -f "$WORK/edge/$FIRST_PART" "$WORK/edge/$LAST_PART"
|
|
----- /usr/local/sbin/homelab-mail-cloud-restore-drill.bak-chunkall-20260710T011410Z -----
|
|
52: rclone copyto "${R}:$CRIT_DEST/$CRIT_BUNDLE" "$OUT" > "$WORK/logs/${SAFE}_crit_download.out" 2>"$WORK/logs/${SAFE}_crit_download.err"
|
|
83: rm -f "$OUT"
|
|
108: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/MANIFEST.txt" "$WORK/edge/MANIFEST.txt" > "$WORK/logs/edge_manifest_download.out" 2>"$WORK/logs/edge_manifest_download.err"
|
|
111: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/SHA256SUMS.txt" "$WORK/edge/SHA256SUMS.txt" > "$WORK/logs/edge_sums_download.out" 2>"$WORK/logs/edge_sums_download.err"
|
|
114: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/$EDGE_ARCHIVE.sha256" "$WORK/edge/$EDGE_ARCHIVE.sha256" > "$WORK/logs/edge_archive_sha_download.out" 2>"$WORK/logs/edge_archive_sha_download.err"
|
|
117: rclone lsf "${EDGE_REMOTE}:$EDGE_DEST/parts" --format ps > "$WORK/logs/edge_parts_lsf.txt" 2>"$WORK/logs/edge_parts_lsf.err"
|
|
130: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/parts/$FIRST_PART" "$WORK/edge/$FIRST_PART" > "$WORK/logs/edge_first_part_download.out" 2>"$WORK/logs/edge_first_part_download.err"
|
|
137: rclone copyto "${EDGE_REMOTE}:$EDGE_DEST/parts/$LAST_PART" "$WORK/edge/$LAST_PART" > "$WORK/logs/edge_last_part_download.out" 2>"$WORK/logs/edge_last_part_download.err"
|
|
168: rm -f "$WORK/edge/$FIRST_PART" "$WORK/edge/$LAST_PART"
|
|
----- /usr/local/sbin/homelab-rclone-cat-chunked -----
|
|
4:TMP_BASE=${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}
|
|
7:cleanup(){ rm -rf "$WORK"; }
|
|
10:rclone copyto "${REMOTE_FILE}.parts/MANIFEST.parts.txt" "$MAN" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level ERROR
|
|
11:while read -r PART SIZE; do case "$PART" in part-*) rclone cat "${REMOTE_FILE}.parts/$PART" ;; esac; done < "$MAN"
|
|
----- /usr/local/sbin/homelab-rclone-cat-flat-chunked -----
|
|
5:trap "rm -f \"$TMP\"" EXIT
|
|
6:rclone cat "${DEST}.parts.txt" > "$TMP"
|
|
8:while read -r PART PART_SIZE; do [[ "$PART" =~ ^part-[0-9]{4}$ && "$PART_SIZE" =~ ^[0-9]+$ ]] || { echo "BAD FLAT PART MANIFEST" >&2; exit 2; }; rclone cat "${DEST}.${PART}"; COUNT=$((COUNT+1)); done < "$TMP"
|
|
----- /usr/local/sbin/homelab-rclone-copy-chunked -----
|
|
7:TMP_BASE=${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}
|
|
13:cleanup(){ rm -rf "$WORK"; }
|
|
23:printf "name=%s\\nsize=%s\\nsha256=%s\\nchunk_size=%s\\nparts=%s\\n" "$NAME" "$SIZE" "$SHA" "$CHUNK_SIZE" "$PART_COUNT" > "$WORK/MANIFEST.txt"
|
|
24:rclone purge "${DEST}.parts" >/dev/null 2>&1 || true
|
|
25:rclone mkdir "${DEST}.parts"
|
|
26:rclone copy "$PARTS" "${DEST}.parts" --transfers 2 --checkers 4 --retries 5 --low-level-retries 20 --stats 30s --log-level INFO
|
|
27:rclone copyto "$WORK/${NAME}.sha256" "${DEST}.sha256" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level INFO
|
|
28:rclone copyto "$WORK/MANIFEST.txt" "${DEST}.manifest.txt" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level INFO
|
|
29:rclone copyto "$WORK/MANIFEST.parts.txt" "${DEST}.parts/MANIFEST.parts.txt" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level INFO
|
|
30:REMOTE_COUNT=$(rclone lsf "${DEST}.parts" --files-only | grep -c "^part-" || true)
|
|
32:ACTUAL=$(while read -r PART SIZE_PART; do case "$PART" in part-*) rclone cat "${DEST}.parts/$PART" ;; esac; done < "$WORK/MANIFEST.parts.txt" | sha256sum | cut -d " " -f 1)
|
|
----- /usr/local/sbin/homelab-rclone-copy-flat-chunked -----
|
|
6:TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}"
|
|
12:trap "rm -rf \"$WORK\"" EXIT
|
|
21:printf "format=homelab-flat-chunks-v1\nname=%s\nsize=%s\nsha256=%s\nchunk_size=%s\nparts=%s\n" "$NAME" "$SIZE" "$SHA" "$CHUNK_SIZE" "$PART_COUNT" > "$WORK/MANIFEST.txt"
|
|
23:while read -r PART PART_SIZE; do [[ "$PART" =~ ^part-[0-9]{4}$ && "$PART_SIZE" =~ ^[0-9]+$ ]] || { echo "BAD PART MANIFEST" >&2; exit 4; }; rclone copyto "$WORK/parts/$PART" "${DEST}.${PART}" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level ERROR; REMOTE_BYTES="$(rclone size --json "${DEST}.${PART}" | jq -r ".bytes // -1")"; [[ "$REMOTE_BYTES" = "$PART_SIZE" ]] || { echo "REMOTE PART SIZE MISMATCH $PART" >&2; exit 5; }; UPLOADED=$((UPLOADED+1)); done < "$WORK/MANIFEST.parts.txt"
|
|
25:rclone copyto "$WORK/${NAME}.sha256" "${DEST}.sha256" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level ERROR
|
|
26:rclone copyto "$WORK/MANIFEST.txt" "${DEST}.manifest.txt" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level ERROR
|
|
27:rclone copyto "$WORK/MANIFEST.parts.txt" "${DEST}.parts.txt" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level ERROR
|
|
28:ACTUAL="$(homelab-rclone-cat-flat-chunked "$DEST" | sha256sum | awk "{print \$1}")"
|
|
----- /usr/local/sbin/homelab-rclone-crypt-healthcheck.sh -----
|
|
4:CRYPT_FILE="/etc/homelab/rclone/required-crypt-remotes.txt"
|
|
18: "checksums/"
|
|
21:echo "=== homelab rclone crypt healthcheck: $(hostname) ==="
|
|
40: if ! rclone listremotes | sed 's/:$//' | grep -qx "$REMOTE"; then
|
|
47: if ! rclone about "${REMOTE}:"; then
|
|
48: echo "FAIL: rclone about failed: $REMOTE"
|
|
54: ROOT_LIST="$(rclone lsf "${REMOTE}:/" || true)"
|
|
76: if rclone cat "${REMOTE}:/latest-backup-index.json" | jq -e '.schema and .remote and .status and .items' >/dev/null; then
|
|
----- /usr/local/sbin/homelab-rclone-required-check.sh -----
|
|
4:RAW_FILE="/etc/homelab/rclone/required-remotes.txt"
|
|
5:CRYPT_FILE="/etc/homelab/rclone/required-crypt-remotes.txt"
|
|
9:echo "=== homelab rclone required check: $(hostname) ==="
|
|
12:echo "=== installed rclone ==="
|
|
13:rclone version | head -5
|
|
17:CONFIGURED="$(rclone listremotes 2>/dev/null | sed 's/:$//' || true)"
|
|
19: echo "No rclone remotes configured yet."
|
|
----- /usr/local/sbin/homelab-router-hard-power-cycle -----
|
|
12:case "$MODE" in check|cycle) ;; *) echo HARD_WRAPPER_MODE_INVALID=yes; exit 64;; esac
|
|
23:SAFE_OUT="$(printf '%s\n' "$OUT" | sed -E '/(PASSWORD|TOKEN|SECRET|PRIVATE_KEY|ROOT_PASSWORD|ENCRYPTION_KEY|COOKIE|SESSION|AUTHORIZATION|API_KEY|LOCAL_KEY|rclone[.]conf|[.]env)/Id')"
|
|
----- /usr/local/sbin/homelab-router-running-config-mail-cloud -----
|
|
62: rm -f "$CONFIG"
|
|
66: rm -f "$CONFIG"
|
|
73: if ( cd "$BACKUP_ROOT" && sha256sum -c "$(basename "$SHA_FILE")" ) >"$WORK/sha-check.out" 2>"$WORK/sha-check.err"; then
|
|
79: if rclone mkdir "$REMOTE:$DEST" >"$WORK/rclone-mkdir.out" 2>"$WORK/rclone-mkdir.err" && homelab-rclone-copy-chunked "$ARCHIVE" "$REMOTE:$DEST/$(basename "$ARCHIVE")" >"$WORK/rclone-upload.out" 2>"$WORK/rclone-upload.err" && rclone copyto "$SHA_FILE" "$REMOTE:$DEST/$(basename "$SHA_FILE")" --checksum >"$WORK/rclone-upload-sha.out" 2>"$WORK/rclone-upload-sha.err"; then
|
|
86: if homelab-rclone-cat-chunked "$REMOTE:$DEST/$(basename "$ARCHIVE")" >"$DL" 2>"$WORK/rclone-download.err"; then
|
|
93:rclone lsf "$REMOTE:$TARGET_BASE" --dirs-only 2>/dev/null | sed 's#/$##' | sort > "$DIR_LIST" || RETENTION_RC=$?
|
|
98: [ -n "$OLD" ] && rclone purge "$REMOTE:$TARGET_BASE/$OLD" >>"$WORK/retention.out" 2>>"$WORK/retention.err"
|
|
103: rm -f "$old" "$old.sha256"
|
|
116:rm -rf "$WORK"
|
|
----- /usr/local/sbin/homelab-router-running-config-mail-cloud.bak-chunkall-20260710T011410Z -----
|
|
62: rm -f "$CONFIG"
|
|
66: rm -f "$CONFIG"
|
|
73: if ( cd "$BACKUP_ROOT" && sha256sum -c "$(basename "$SHA_FILE")" ) >"$WORK/sha-check.out" 2>"$WORK/sha-check.err"; then
|
|
79: if rclone mkdir "$REMOTE:$DEST" >"$WORK/rclone-mkdir.out" 2>"$WORK/rclone-mkdir.err" && rclone copyto "$ARCHIVE" "$REMOTE:$DEST/$(basename "$ARCHIVE")" --checksum >"$WORK/rclone-upload.out" 2>"$WORK/rclone-upload.err" && rclone copyto "$SHA_FILE" "$REMOTE:$DEST/$(basename "$SHA_FILE")" --checksum >"$WORK/rclone-upload-sha.out" 2>"$WORK/rclone-upload-sha.err"; then
|
|
86: if rclone copyto "$REMOTE:$DEST/$(basename "$ARCHIVE")" "$DL" >"$WORK/rclone-download.out" 2>"$WORK/rclone-download.err"; then
|
|
93:rclone lsf "$REMOTE:$TARGET_BASE" --dirs-only 2>/dev/null | sed 's#/$##' | sort > "$DIR_LIST" || RETENTION_RC=$?
|
|
98: [ -n "$OLD" ] && rclone purge "$REMOTE:$TARGET_BASE/$OLD" >>"$WORK/retention.out" 2>>"$WORK/retention.err"
|
|
103: rm -f "$old" "$old.sha256"
|
|
116:rm -rf "$WORK"
|
|
----- /usr/local/sbin/homelab-secret-exposure-guard -----
|
|
18:BADFILES="$(find "$REPO" -path "$REPO/.git" -prune -o -type f \( -iname "*.key" -o -iname "*.pem" -o -iname "*.p12" -o -iname "*.pfx" -o -iname "[SENSITIVE_FILE]" -o -iname ".env" -o -iname ".env.*" \) -print 2>/dev/null)"
|
|
----- /usr/local/sbin/homelab-stage-2cloud -----
|
|
20:jq -n --arg schema "homelab-app-backup-manifest-v1" --arg job "$JOB" --arg node "$NODE" --arg app "$APP" --arg created "$(date -u +%Y%m%dT%H%M%SZ)" --arg archive "$ARCHIVE" --arg sha "$SHA" --arg ra "$RA" --arg rb "$RB" --argjson size "$SIZE" --argjson meta "$META" '$meta + {schema:$schema,job_id:$job,node:$node,app_name:$app,created_utc:$created,archive_name:$archive,archive_size_bytes:$size,archive_sha256:$sha,remote_a_job_path:$ra,remote_b_job_path:$rb,local_staging_policy:"delete_after_both_clouds_verified",verification_policy:"full_roundtrip_download_plus_sha256"}' > "$STAGE/manifest.json"
|
|
22:echo "[STEP] local checksum"; (cd "$STAGE" && sha256sum "$ARCHIVE" manifest.json latest-backup-index.json > checksums.sha256 && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e . manifest.json >/dev/null)
|
|
23:echo "[STEP] upload cloud A metadata"; rclone copy "$STAGE" "$RA" --exclude "$ARCHIVE" --exclude "$ARCHIVE.sha256" --transfers=4 --checkers=8 --retries=5 --low-level-retries=20 --stats=30s
|
|
24:echo "[STEP] upload cloud A archive chunks"; rclone deletefile "$RA/$ARCHIVE" >/dev/null 2>&1 || true; CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-rclone-copy-chunked "$STAGE/$ARCHIVE" "$RA/$ARCHIVE"
|
|
25:echo "[STEP] upload cloud B metadata"; rclone copy "$STAGE" "$RB" --exclude "$ARCHIVE" --exclude "$ARCHIVE.sha256" --transfers=4 --checkers=8 --retries=5 --low-level-retries=20 --stats=30s
|
|
26:echo "[STEP] upload cloud B archive chunks"; rclone deletefile "$RB/$ARCHIVE" >/dev/null 2>&1 || true; CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-rclone-copy-chunked "$STAGE/$ARCHIVE" "$RB/$ARCHIVE"
|
|
27:echo "[STEP] verify cloud A chunked"; CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-stage-verify-chunked "$RA" "$ARCHIVE" "$VERIFY/a" "$JOB"
|
|
28:echo "[STEP] verify cloud B chunked"; CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-stage-verify-chunked "$RB" "$ARCHIVE" "$VERIFY/b" "$JOB"
|
|
29:echo "[STEP] upload latest index"; rclone copyto "$STAGE/latest-backup-index.json" "$RAL"; rclone copyto "$STAGE/latest-backup-index.json" "$RBL"; rclone cat "$RAL" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null; rclone cat "$RBL" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null
|
|
30:jq ". + {status:\"success\",local_backup_deleted:true}" "$STAGE/manifest.json" > "$STATE_ROOT/apps/latest-${APP}.json"
|
|
31:echo "[STEP] delete local staging"; rm -rf "$STAGE" "$VERIFY"; test ! -d "$STAGE" && test ! -d "$VERIFY"
|
|
33:echo "[SUCCESS] uploaded to 2 clouds, verified from both clouds, local staging deleted"
|
|
----- /usr/local/sbin/homelab-stage-2cloud.bak-global-chunkonly-20260710T011036Z -----
|
|
20:jq -n --arg schema "homelab-app-backup-manifest-v1" --arg job "$JOB" --arg node "$NODE" --arg app "$APP" --arg created "$(date -u +%Y%m%dT%H%M%SZ)" --arg archive "$ARCHIVE" --arg sha "$SHA" --arg ra "$RA" --arg rb "$RB" --argjson size "$SIZE" --argjson meta "$META" '$meta + {schema:$schema,job_id:$job,node:$node,app_name:$app,created_utc:$created,archive_name:$archive,archive_size_bytes:$size,archive_sha256:$sha,remote_a_job_path:$ra,remote_b_job_path:$rb,local_staging_policy:"delete_after_both_clouds_verified",verification_policy:"full_roundtrip_download_plus_sha256"}' > "$STAGE/manifest.json"
|
|
22:echo "[STEP] local checksum"; (cd "$STAGE" && sha256sum "$ARCHIVE" manifest.json latest-backup-index.json > checksums.sha256 && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e . manifest.json >/dev/null)
|
|
23:echo "[STEP] upload cloud A"; rclone copy "$STAGE" "$RA" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 --stats=30s
|
|
24:echo "[STEP] upload cloud B"; rclone copy "$STAGE" "$RB" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10 --stats=30s
|
|
25:echo "[STEP] verify cloud A"; rclone copy "$RA" "$VERIFY/a" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10; (cd "$VERIFY/a" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
26:echo "[STEP] verify cloud B"; rclone copy "$RB" "$VERIFY/b" --transfers=4 --checkers=8 --retries=3 --low-level-retries=10; (cd "$VERIFY/b" && sha256sum -c checksums.sha256 && tar -tzf "$ARCHIVE" >/dev/null && jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null)
|
|
27:echo "[STEP] upload latest index"; rclone copyto "$STAGE/latest-backup-index.json" "$RAL"; rclone copyto "$STAGE/latest-backup-index.json" "$RBL"; rclone cat "$RAL" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null; rclone cat "$RBL" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null
|
|
28:jq ". + {status:\"success\",local_backup_deleted:true}" "$STAGE/manifest.json" > "$STATE_ROOT/apps/latest-${APP}.json"
|
|
29:echo "[STEP] delete local staging"; rm -rf "$STAGE" "$VERIFY"; test ! -d "$STAGE" && test ! -d "$VERIFY"
|
|
31:echo "[SUCCESS] uploaded to 2 clouds, verified from both clouds, local staging deleted"
|
|
----- /usr/local/sbin/homelab-stage-2cloud-flat -----
|
|
31:jq -n --arg schema "homelab-app-backup-manifest-v2-flat" --arg layout "flat-v1" --arg job "$JOB" --arg node "$NODE" --arg app "$APP" --arg created "$CREATED" --arg archive "$ARCHIVE" --arg sha "$SHA" --arg ra "$RA" --arg rb "$RB" --arg rel "$REL" --argjson size "$SIZE" --argjson meta "$META" "\$meta + {schema:\$schema,layout:\$layout,job_id:\$job,node:\$node,app_name:\$app,created_utc:\$created,archive_name:\$archive,archive_size_bytes:\$size,archive_sha256:\$sha,path_rel:\$rel,remote_a_job_path:\$ra,remote_b_job_path:\$rb,local_staging_policy:\"delete_after_both_clouds_verified\",verification_policy:\"flat_chunks_full_roundtrip_sha256\"}" > "$STAGE/manifest.json"
|
|
33:(cd "$STAGE"; FILES=("$ARCHIVE" manifest.json latest-backup-index.json); [[ -f metadata.json ]] && FILES+=(metadata.json); sha256sum "${FILES[@]}" > checksums.sha256; sha256sum -c checksums.sha256 >/dev/null; tar -tzf "$ARCHIVE" >/dev/null; jq -e . manifest.json >/dev/null)
|
|
36: if rclone lsf "$REMOTE_DIR" --max-depth 1 2>/dev/null | grep -q .; then echo "REFUSE NONEMPTY CANARY TARGET $REMOTE_DIR" >&2; exit 6; fi
|
|
37: rclone mkdir "$REMOTE_DIR"
|
|
38: for F in metadata.json manifest.json latest-backup-index.json checksums.sha256; do [[ -f "$STAGE/$F" ]] && rclone copyto "$STAGE/$F" "$REMOTE_DIR/$F" --transfers 1 --checkers 2 --retries 5 --low-level-retries 20 --log-level ERROR; done
|
|
39: CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-rclone-copy-flat-chunked "$STAGE/$ARCHIVE" "$REMOTE_DIR/$ARCHIVE"
|
|
41: rclone copyto "$STAGE/latest-backup-index.json" "$LATEST_FILE" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level ERROR
|
|
42: rclone cat "$LATEST_FILE" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null
|
|
46:jq ". + {status:\"success\",local_backup_deleted:true}" "$STAGE/manifest.json" > "$STATE_ROOT/apps/latest-${APP}.json"
|
|
47:rm -rf "$STAGE" "$VERIFY"
|
|
----- /usr/local/sbin/homelab-stage-2cloud-flat-canary -----
|
|
29:jq -n --arg schema "homelab-app-backup-manifest-v2-flat" --arg layout "flat-v1" --arg job "$JOB" --arg node "$NODE" --arg app "$APP" --arg created "$CREATED" --arg archive "$ARCHIVE" --arg sha "$SHA" --arg ra "$RA" --arg rb "$RB" --arg rel "$REL" --argjson size "$SIZE" --argjson meta "$META" "\$meta + {schema:\$schema,layout:\$layout,job_id:\$job,node:\$node,app_name:\$app,created_utc:\$created,archive_name:\$archive,archive_size_bytes:\$size,archive_sha256:\$sha,path_rel:\$rel,remote_a_job_path:\$ra,remote_b_job_path:\$rb,local_staging_policy:\"delete_after_both_clouds_verified\",verification_policy:\"flat_chunks_full_roundtrip_sha256\"}" > "$STAGE/manifest.json"
|
|
31:(cd "$STAGE"; FILES=("$ARCHIVE" manifest.json latest-backup-index.json); [[ -f metadata.json ]] && FILES+=(metadata.json); sha256sum "${FILES[@]}" > checksums.sha256; sha256sum -c checksums.sha256 >/dev/null; tar -tzf "$ARCHIVE" >/dev/null; jq -e . manifest.json >/dev/null)
|
|
34: if rclone lsf "$REMOTE_DIR" --max-depth 1 2>/dev/null | grep -q .; then echo "REFUSE NONEMPTY CANARY TARGET $REMOTE_DIR" >&2; exit 6; fi
|
|
35: rclone mkdir "$REMOTE_DIR"
|
|
36: for F in metadata.json manifest.json latest-backup-index.json checksums.sha256; do [[ -f "$STAGE/$F" ]] && rclone copyto "$STAGE/$F" "$REMOTE_DIR/$F" --transfers 1 --checkers 2 --retries 5 --low-level-retries 20 --log-level ERROR; done
|
|
37: CHUNK_TMP_BASE="${CHUNK_TMP_BASE:-/mnt/staging/rclone-chunks}" homelab-rclone-copy-flat-chunked "$STAGE/$ARCHIVE" "$REMOTE_DIR/$ARCHIVE"
|
|
39: rclone copyto "$STAGE/latest-backup-index.json" "$LATEST_FILE" --transfers 1 --checkers 1 --retries 5 --low-level-retries 20 --log-level ERROR
|
|
40: rclone cat "$LATEST_FILE" | jq -e --arg job "$JOB" ".job_id == \$job" >/dev/null
|
|
44:jq ". + {status:\"success\",local_backup_deleted:true}" "$STAGE/manifest.json" > "$STATE_ROOT/apps/latest-${APP}.json"
|
|
45:rm -rf "$STAGE" "$VERIFY"
|
|
----- /usr/local/sbin/homelab-stage-verify-chunked -----
|
|
7:rm -rf "$VERIFY"
|
|
9:rclone copy "$REMOTE_DIR" "$VERIFY" --exclude "$ARCHIVE.parts/**" --exclude "$ARCHIVE.parts/" --exclude "$ARCHIVE.sha256" --exclude "$ARCHIVE.manifest.txt" --transfers=4 --checkers=8 --retries=5 --low-level-retries=20 --log-level ERROR
|
|
13:if [ -s checksums.sha256 ]; then grep -F -v " $ARCHIVE" checksums.sha256 > .checksums-no-archive.sha256 || true; if [ -s .checksums-no-archive.sha256 ]; then sha256sum -c .checksums-no-archive.sha256; fi; EXPECTED=$(grep -F " $ARCHIVE" checksums.sha256 | awk '{print $1; exit}'); else EXPECTED=$(rclone cat "${REMOTE_DIR}/${ARCHIVE}.sha256" | awk '{print $1; exit}'); fi
|
|
15:ACTUAL=$(homelab-rclone-cat-chunked "${REMOTE_DIR}/${ARCHIVE}" | sha256sum | awk '{print $1}')
|
|
17:homelab-rclone-cat-chunked "${REMOTE_DIR}/${ARCHIVE}" | tar -tzf - >/dev/null
|
|
----- /usr/local/sbin/homelab-stage-verify-flat-chunked -----
|
|
7:rm -rf "$VERIFY"
|
|
9:rclone copy "$REMOTE_DIR" "$VERIFY" --transfers 4 --checkers 8 --retries 5 --low-level-retries 20 --log-level ERROR
|
|
11:(cd "$VERIFY" && test -s manifest.json && if [[ -n "$JOB" ]]; then jq -e --arg job "$JOB" ".job_id == \$job" manifest.json >/dev/null; fi && sha256sum -c checksums.sha256 >/dev/null && tar -tzf "$ARCHIVE" >/dev/null)
|
|
----- /usr/local/sbin/homelab-vm160-remote-backup -----
|
|
8:PARENT=/mnt/staging/vzdump
|
|
22:SOURCE_ACTIVE="$(ssh "${SSH[@]}" "$SOURCE" "pgrep -af '(^|/)(vzdump|qmrestore|pctrestore|vma|zstd)([[:space:]]|$)'")" || SOURCE_ACTIVE_RC=$?
|
|
27:NAME="vzdump-qemu-${VMID}-${TS}.vma.zst"
|
|
35: ssh "${SSH[@]}" "$TARGET" "rm -rf -- '$DIR'" >/dev/null 2>&1 || true
|
|
41: rm -f "$LOG"
|
|
46:LATEST_SIZE="$(ssh "${SSH[@]}" "$TARGET" "find '$PARENT' -mindepth 2 -maxdepth 2 -type f -path '$PARENT/${PREFIX}*/vzdump-qemu-${VMID}-*.vma.zst' -printf '%s\n' | sort -nr | head -n1")"
|
|
55:ssh "${SSH[@]}" "$SOURCE" "vzdump $VMID --stdout 1 --mode snapshot --compress zstd --ionice 7" 2>"$LOG" | ssh "${SSH[@]}" "$TARGET" "cat > '$PART'"
|
|
57:ssh "${SSH[@]}" "$TARGET" "cat > '$DIR/vzdump.log'" < "$LOG"
|
|
66:rm -f "$LOG"
|
|
----- /usr/local/sbin/homelab-vm-backup-health -----
|
|
8:check_file(){
|
|
15:check_file /var/lib/homelab-health/backup.txt auto-vmct
|
|
16:check_file /var/lib/homelab-health/edge-vm-vzdump-backup.txt edge-vm-backup
|
|
17:check_file /var/lib/homelab-health/edge-vm-vzdump-offhost.txt edge-vm-offhost
|
|
18:check_file /var/lib/homelab-health/edge-vm-vzdump-restore.txt edge-vm-restore
|
|
----- /usr/local/sbin/homelab-vm-backup-policy -----
|
|
29:echo "## Latest local vzdump catalog" >> "$REPORT"
|
|
30:printf "%s\t%s\t%s\t%s\t%s\t%s\n" "kind" "vmid" "name" "size_bytes" "mtime_utc" "path" > "$CATALOG"
|
|
31:for f in $(find /var/lib/vz/dump -maxdepth 1 -type f \( -name "vzdump-qemu-*.vma.zst" -o -name "vzdump-lxc-*.tar.zst" \) 2>/dev/null | sort); do b="$(basename "$f")"; size="$(stat -c %s "$f" 2>/dev/null || echo 0)"; mt="$(date -u -d "@$(stat -c %Y "$f" 2>/dev/null || echo 0)" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo unknown)"; if echo "$b" | grep -q "^vzdump-qemu-"; then kind=qemu; vmid="$(echo "$b" | sed -n "s/^vzdump-qemu-\([0-9]\+\)-.*/\1/p")"; name="$(qm config "$vmid" 2>/dev/null | awk -F": " "/^name:/{print \$2; exit}")"; else kind=lxc; vmid="$(echo "$b" | sed -n "s/^vzdump-lxc-\([0-9]\+\)-.*/\1/p")"; name="$(pct config "$vmid" 2>/dev/null | awk -F": " "/^hostname:/{print \$2; exit}")"; fi; printf "%s\t%s\t%s\t%s\t%s\t%s\n" "$kind" "$vmid" "${name:-unknown}" "$size" "$mt" "$f" >> "$CATALOG"; done
|
|
37:echo "- Existing local dumps can be uploaded/verified to two clouds without creating new vzdump archives." >> "$REPORT"
|
|
38:echo "- New full vzdump for VM 170/171 is not started automatically because each VM has 120 GB bootdisk and /var/tmp has limited free space." >> "$REPORT"
|
|
42:echo "## Coverage checks" >> "$REPORT"
|
|
----- /usr/local/sbin/homelab-vm-full-backup -----
|
|
11:# shellcheck disable=SC1090
|
|
92:for cmd in vzdump qm zstd sha256sum rclone rsync ssh flock; do
|
|
130: -name "vzdump-qemu-${VMID}-*.vma.zst" \
|
|
138: vzdump "$VMID" \
|
|
145: --remove 0
|
|
151: -name "vzdump-qemu-${VMID}-*.vma.zst" \
|
|
261: CHUNK_TMP_BASE="$BACKUP_DIR/.rclone-chunks" homelab-rclone-copy-chunked "$ARCHIVE" "${DEST_ROOT}/${NAME}"
|
|
----- /usr/local/sbin/homelab-vm-full-backup.bak-chunkall-20260710T011410Z -----
|
|
11:# shellcheck disable=SC1090
|
|
92:for cmd in vzdump qm zstd sha256sum rclone rsync ssh flock; do
|
|
130: -name "vzdump-qemu-${VMID}-*.vma.zst" \
|
|
138: vzdump "$VMID" \
|
|
145: --remove 0
|
|
151: -name "vzdump-qemu-${VMID}-*.vma.zst" \
|
|
264: rclone copyto \
|
|
267: --check-first \
|
|
269: --checkers 2 \
|
|
275: rclone copyto \
|
|
278: --check-first \
|
|
280: --checkers 2 \
|
|
285: echo "Crypt-checking $NAME on $REMOTE"
|
|
287: rclone cryptcheck \
|
|
292: --checkers 1 \
|
|
----- /usr/local/sbin/homelab-vm-full-restore-drill -----
|
|
77: -name "vzdump-qemu-${source_vmid}-*.vma.zst" \
|
|
152:check_inventory() {
|
|
184:check_container_health() {
|
|
224:check_http() {
|
|
349:check_container_health() {
|
|
386:check_container_health "$test_vmid"
|
|
389: check_inventory "$source_vmid" "$test_vmid"
|
|
392: check_http "$source_vmid" "$test_vmid"
|
|
----- /usr/local/sbin/homelab-vm-full-restore-drill.bak.20260710T080231Z -----
|
|
77: -name "vzdump-qemu-${source_vmid}-*.vma.zst" \
|
|
152:check_inventory() {
|
|
184:check_container_health() {
|
|
224:check_http() {
|
|
349:check_container_health() {
|
|
386:check_container_health "$test_vmid"
|
|
389: check_inventory "$source_vmid" "$test_vmid"
|
|
392: check_http "$source_vmid" "$test_vmid"
|
|
----- /usr/local/sbin/homelab-vm-full-restore-drill.bak-docker-check-v2-20260710T050044Z -----
|
|
77: -name "vzdump-qemu-${source_vmid}-*.vma.zst" \
|
|
152:check_inventory() {
|
|
184:check_container_health() {
|
|
224:check_http() {
|
|
347: check_container_health "$test_vmid"
|
|
350: check_inventory "$source_vmid" "$test_vmid"
|
|
353: check_http "$source_vmid" "$test_vmid"
|
|
----- /usr/local/sbin/homelab-vm-full-restore-drill.bak-isolated-ip-20260710T044331Z -----
|
|
77: -name "vzdump-qemu-${source_vmid}-*.vma.zst" \
|
|
152:check_inventory() {
|
|
184:check_container_health() {
|
|
224:check_http() {
|
|
337: check_container_health "$test_vmid"
|
|
340: check_inventory "$source_vmid" "$test_vmid"
|
|
343: check_http "$source_vmid" "$test_vmid"
|
|
----- /usr/local/sbin/homelab-vm-full-retention -----
|
|
21: -name "vzdump-qemu-${vmid}-*.vma.zst" \
|
|
33: vzdump-qemu-"$vmid"-*.vma.zst)
|
|
35: rm -f \
|
|
73: rm -rf -- \"\$BASE/\$setname\"
|
|
91: rclone lsf "$path" \
|
|
105: rclone purge "${path}/${dir}"
|
|
----- /usr/local/sbin/homelab-vm-local-dumps-2cloud -----
|
|
30:CHKS="$WORK/checksums.txt"
|
|
39:echo "chunk_size_bytes=$CHUNK_SIZE_BYTES" >> "$LOG"
|
|
42: F="$(find /var/lib/vz/dump -maxdepth 1 -type f \( -name "vzdump-qemu-${id}-*.vma.zst" -o -name "vzdump-lxc-${id}-*.tar.zst" \) -printf "%T@ %p\n" 2>/dev/null | sort -n | tail -n 1 | cut -d" " -f2-)"
|
|
53: echo "$BN" | grep -q "^vzdump-qemu-" && KIND="qemu"
|
|
54: echo "$BN" | grep -q "^vzdump-lxc-" && KIND="lxc"
|
|
64: rm -rf "$CDIR"
|
|
66: echo "SPLIT file=$BN size=$SIZE chunk_size=$CHUNK_SIZE_SPLIT dir=$CDIR" >> "$LOG"
|
|
83:job,node,ts,vmids,count,total,chunked,chunk_size,tsv=sys.argv[1:]
|
|
91: "size_bytes":int(p[2]),
|
|
107: "chunk_size_bytes":int(chunk_size),
|
|
117: rclone mkdir "$DEST/files" >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
118: while IFS="$(printf "\t")" read -r id kind size sha mt bn path mode parts; do
|
|
121: echo "UPLOAD_CHUNKED dest=$DEST file=$bn size=$size parts=$parts" >> "$LOG"
|
|
122: rclone mkdir "$DEST/files/$bn.chunks" >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
126: rclone copyto "$part" "$DEST/files/$bn.chunks/$pn" --transfers 1 --checkers 4 >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
128: rclone copyto "$CDIR/chunks.sha256" "$DEST/files/$bn.chunks/chunks.sha256" >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
130: echo "UPLOAD_DIRECT dest=$DEST file=$bn size=$size" >> "$LOG"
|
|
131: rclone copyto "$path" "$DEST/files/$bn" --transfers 1 --checkers 4 >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
135: rclone copyto "$CHKS" "$DEST/checksums.txt" >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
136: rclone copyto "$FILES_TSV" "$DEST/files.tsv" >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
137: rclone copyto "$MAN" "$DEST/manifest.json" >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
144: rm -rf "$VBASE"
|
|
146: rclone copyto "$DEST/manifest.json" "$VBASE/manifest.json" >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
149: while IFS="$(printf "\t")" read -r id kind size sha mt bn path mode parts; do
|
|
154: rclone copy "$DEST/files/$bn.chunks" "$VDIR" --filter "+ part-*" --filter "+ chunks.sha256" --filter "- *" --transfers 1 --checkers 4 >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
163: rm -rf "$VDIR"
|
|
166: rclone copyto "$DEST/files/$bn" "$VBASE/$bn" --transfers 1 >> "$LOG" 2>&1 || BAD=$((BAD+1))
|
|
168: rm -f "$VBASE/$bn"
|
|
171: rm -rf "$VBASE"
|
|
184:rm -rf "$VERIFY_ROOT/$JOB_ID"
|
|
185:rm -rf "$CHUNK_ROOT/$JOB_ID"
|
|
198: --argjson chunk_size_bytes "$CHUNK_SIZE_BYTES" \
|
|
200: "{job_id:\$job_id,status:\$status,node:\$node,remote_a:\$remote_a,remote_b:\$remote_b,count:\$count,total_bytes:\$total_bytes,chunked_count:\$chunked_count,chunk_size_bytes:\$chunk_size_bytes,log:\$log,local_dumps_deleted:false}" \
|
|
----- /usr/local/sbin/homelab-vm-local-dumps-retention -----
|
|
32: mapfile -t JOBS < <(rclone lsf "$BASE/" --dirs-only 2>/dev/null | sed 's#/$##' | sort)
|
|
37: echo "nothing_to_delete" >> "$REPORT"
|
|
56: rclone purge "$PATH_REMOTE" >> "$REPORT" 2>&1 && DELETED=$((DELETED+1)) || BAD=$((BAD+1))
|
|
----- /usr/local/sbin/skladchik-reports-monitor-backup -----
|
|
28:command -v rclone >/dev/null
|
|
29:[ -x /usr/local/sbin/homelab-rclone-copy-chunked ] || { echo "missing /usr/local/sbin/homelab-rclone-copy-chunked" >&2; exit 10; }
|
|
36:cleanup(){ rm -rf "$TMP"; }
|
|
67:size_bytes=${SIZE}
|
|
71:log "LOCAL_ARCHIVE_OK size=$SIZE path=$ARCHIVE"
|
|
75: /usr/local/sbin/homelab-rclone-copy-chunked "$ARCHIVE" "${DEST_BASE}/$(basename "$ARCHIVE")"
|
|
76: /usr/local/sbin/homelab-rclone-copy-chunked "${ARCHIVE}.sha256" "${DEST_BASE}/$(basename "$ARCHIVE").sha256"
|
|
77: /usr/local/sbin/homelab-rclone-copy-chunked "${OUTDIR}/manifest.txt" "${DEST_BASE}/manifest.txt"
|
|
82: mapfile -t OLD < <(rclone lsf --dirs-only "${REMOTE}${REMOTE_BASE}/daily/" 2>/dev/null | sed 's#/$##' | sort | head -n -"${KEEP_DAILY}" || true)
|
|
83: for D in "${OLD[@]}"; do [ -n "$D" ] && rclone purge "${REMOTE}${REMOTE_BASE}/daily/${D}" >/dev/null 2>&1 || true; done
|
|
85:find "${LOCAL_ROOT}/daily" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null | sort | head -n -"${KEEP_DAILY}" | while read -r D; do [ -n "$D" ] && rm -rf "${LOCAL_ROOT}/daily/${D}"; done
|
|
----- /usr/local/sbin/skladchik-reports-monitor-backup.pre-restore-check-20260710T065311Z.bak -----
|
|
28:command -v rclone >/dev/null
|
|
29:[ -x /usr/local/sbin/homelab-rclone-copy-chunked ] || { echo "missing /usr/local/sbin/homelab-rclone-copy-chunked" >&2; exit 10; }
|
|
36:cleanup(){ rm -rf "$TMP"; }
|
|
66:size_bytes=${SIZE}
|
|
70:log "LOCAL_ARCHIVE_OK size=$SIZE path=$ARCHIVE"
|
|
74: /usr/local/sbin/homelab-rclone-copy-chunked "$ARCHIVE" "${DEST_BASE}/$(basename "$ARCHIVE")"
|
|
75: /usr/local/sbin/homelab-rclone-copy-chunked "${ARCHIVE}.sha256" "${DEST_BASE}/$(basename "$ARCHIVE").sha256"
|
|
76: /usr/local/sbin/homelab-rclone-copy-chunked "${OUTDIR}/manifest.txt" "${DEST_BASE}/manifest.txt"
|
|
81: mapfile -t OLD < <(rclone lsf --dirs-only "${REMOTE}${REMOTE_BASE}/daily/" 2>/dev/null | sed 's#/$##' | sort | head -n -"${KEEP_DAILY}" || true)
|
|
82: for D in "${OLD[@]}"; do [ -n "$D" ] && rclone purge "${REMOTE}${REMOTE_BASE}/daily/${D}" >/dev/null 2>&1 || true; done
|
|
84:find "${LOCAL_ROOT}/daily" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null | sort | head -n -"${KEEP_DAILY}" | while read -r D; do [ -n "$D" ] && rm -rf "${LOCAL_ROOT}/daily/${D}"; done
|
|
----- /usr/local/sbin/skladchik-reports-monitor-backup.pre-session-keepalive-20260710T071605Z.bak -----
|
|
28:command -v rclone >/dev/null
|
|
29:[ -x /usr/local/sbin/homelab-rclone-copy-chunked ] || { echo "missing /usr/local/sbin/homelab-rclone-copy-chunked" >&2; exit 10; }
|
|
36:cleanup(){ rm -rf "$TMP"; }
|
|
64:size_bytes=${SIZE}
|
|
68:log "LOCAL_ARCHIVE_OK size=$SIZE path=$ARCHIVE"
|
|
72: /usr/local/sbin/homelab-rclone-copy-chunked "$ARCHIVE" "${DEST_BASE}/$(basename "$ARCHIVE")"
|
|
73: /usr/local/sbin/homelab-rclone-copy-chunked "${ARCHIVE}.sha256" "${DEST_BASE}/$(basename "$ARCHIVE").sha256"
|
|
74: /usr/local/sbin/homelab-rclone-copy-chunked "${OUTDIR}/manifest.txt" "${DEST_BASE}/manifest.txt"
|
|
79: mapfile -t OLD < <(rclone lsf --dirs-only "${REMOTE}${REMOTE_BASE}/daily/" 2>/dev/null | sed 's#/$##' | sort | head -n -"${KEEP_DAILY}" || true)
|
|
80: for D in "${OLD[@]}"; do [ -n "$D" ] && rclone purge "${REMOTE}${REMOTE_BASE}/daily/${D}" >/dev/null 2>&1 || true; done
|
|
82:find "${LOCAL_ROOT}/daily" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null | sort | head -n -"${KEEP_DAILY}" | while read -r D; do [ -n "$D" ] && rm -rf "${LOCAL_ROOT}/daily/${D}"; done
|
|
----- /usr/local/sbin/skladchik-reports-monitor-backup-restore-check -----
|
|
4:CONF=/etc/skladchik-reports-monitor-backup-restore-check.conf
|
|
9:: "${WORK_ROOT:=/mnt/staging/skladchik-reports-monitor-backup-restore-check}"
|
|
12:HEALTH=/var/lib/skladchik-reports-monitor-backup/restore-check-health.txt
|
|
13:LOCK=/run/skladchik-reports-monitor-backup-restore-check.lock
|
|
19:log(){ printf '%s RESTORE_CHECK %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*" | tee -a "$LOGDIR/restore-check.log"; }
|
|
22:command -v rclone >/dev/null
|
|
28: if rclone lsf "${remote_path}.parts/" > "$plist" 2>/dev/null && grep -q '^part-' "$plist"; then
|
|
29: while IFS= read -r part; do [ -n "$part" ] && rclone cat "${remote_path}.parts/${part}" >> "$out"; done < <(grep '^part-' "$plist" | sort)
|
|
31: rclone copyto "$remote_path" "$out" >/dev/null
|
|
33: rm -f "$plist"
|
|
36:check_one_remote(){
|
|
39: latest="$(rclone lsf --dirs-only "${rbase}/" 2>/dev/null | sed 's#/$##' | grep -E '^[0-9]{8}T[0-9]{6}Z$' | sort | tail -n 1)"
|
|
85: [ "$(sqlite3 "$extract/var-lib-skladchik-reports-monitor/state.sqlite" 'PRAGMA integrity_check;' | tail -n 1)" = "ok" ]
|
|
97:check_one_remote CLOUD_1 "$CLOUD_1"
|
|
98:check_one_remote CLOUD_2 "$CLOUD_2"
|
|
101:find "$WORK_ROOT" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null | sort | head -n -"${KEEP_LOCAL}" | while read -r D; do [ -n "$D" ] && rm -rf "${WORK_ROOT}/${D}"; done
|
|
----- /usr/local/sbin/skladchik-reports-monitor-backup-restore-check.pre-session-keepalive-20260710T071605Z.bak -----
|
|
4:CONF=/etc/skladchik-reports-monitor-backup-restore-check.conf
|
|
9:: "${WORK_ROOT:=/mnt/staging/skladchik-reports-monitor-backup-restore-check}"
|
|
12:HEALTH=/var/lib/skladchik-reports-monitor-backup/restore-check-health.txt
|
|
13:LOCK=/run/skladchik-reports-monitor-backup-restore-check.lock
|
|
19:log(){ printf '%s RESTORE_CHECK %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*" | tee -a "$LOGDIR/restore-check.log"; }
|
|
22:command -v rclone >/dev/null
|
|
28: if rclone lsf "${remote_path}.parts/" > "$plist" 2>/dev/null && grep -q '^part-' "$plist"; then
|
|
29: while IFS= read -r part; do [ -n "$part" ] && rclone cat "${remote_path}.parts/${part}" >> "$out"; done < <(grep '^part-' "$plist" | sort)
|
|
31: rclone copyto "$remote_path" "$out" >/dev/null
|
|
33: rm -f "$plist"
|
|
36:check_one_remote(){
|
|
39: latest="$(rclone lsf --dirs-only "${rbase}/" 2>/dev/null | sed 's#/$##' | grep -E '^[0-9]{8}T[0-9]{6}Z$' | sort | tail -n 1)"
|
|
72: [ "$(sqlite3 "$extract/var-lib-skladchik-reports-monitor/state.sqlite" 'PRAGMA integrity_check;' | tail -n 1)" = "ok" ]
|
|
84:check_one_remote CLOUD_1 "$CLOUD_1"
|
|
85:check_one_remote CLOUD_2 "$CLOUD_2"
|
|
88:find "$WORK_ROOT" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null | sort | head -n -"${KEEP_LOCAL}" | while read -r D; do [ -n "$D" ] && rm -rf "${WORK_ROOT}/${D}"; done
|
|
|
|
OUTPUT_END
|
|
CHAT_OUTPUT_END
|