Deploy phase done: oCIS 7.1.0 в /opt/stacks/owncloud/ через traefik labels на owncloud.kzntsv.site (LE cert valid), user 'vitya' создан через LibreGraph API, WebDAV `/dav/files/vitya/` PROPFIND 200 OK. Decisions in close-note: oCIS vs Seafile/Nextcloud chosen for drop-in decomposedfs import + lightweight Go binary. user:1001:1001 override after mount perms fail (host vitya UID 1001 ≠ image ocis-user UID 1000). PROXY_ENABLE_BASIC_AUTH=true для WebDAV/LibreGraph admin API. Backup integration: /opt/stacks/owncloud добавлен в rsync sources в /opt/stacks/backup/scripts/run.sh (vds-backup-rsync-kreknin scope expanded). Status 🟡 — pending user-side rclone copy 24.7GB → WebDAV (full copy лежит на другом PC, не на этом). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.5 KiB
7.5 KiB
vds-backup-rsync-kreknin
Goal
Ежедневный rsync-бэкап важных директорий с VDS (89.253.255.94 / vds.kzntsv.site) → kreknin-synology (195.19.90.188 / kreknin.site) в 05:00 MSK. После каждого прохода — email-нотификация на vitya.kuznetsov@gmail.com со статусом (success/fail + transferred bytes + duration).
Open questions
Что бэкапить:Resolved 2026-05-20. Sources в/opt/stacks/backup/scripts/run.sh:/opt/stacks/{gitea,verdaccio/storage,verdaccio/config,registry,traefik,portainer,ntfy,backup}/opt/stacks/owncloud(added 2026-05-21 для owncloud-vds-deploy — oCIS data + config + .env + compose; post-import будет ~25GB, hardlink-incremental после первой ночи)/etc/{ssh,ufw,hosts,docker}/home/vitya/.ssh- DB dumps в
$DUMP_DIR(pg/maria/mongo/redis) — добавляются в rsync source list. - Не бэкапим:
/opt/stacks/databases/*/data(raw datadirs — running container locks; dumps вместо).
Куда на kreknin:/volume1/NetBackup/vds-kzntsv/<YYYY-MM-DD>/+ symlinklatest. Retention 7 daily snapshots (RETENTION_DAYS env). Weekly/monthly — defer (overkill для текущих ~12G).SSH key:продолжаем/home/vitya/.ssh/id_ed25519_kreknin— скрипт читает абсолютным path (work as root too).Tool:rsync--link-dest(built-in, hardlink-incremental). Encrypted (restic/borg) defer — VDS↔kreknin link trusted (оба ours), encryption key management = ops overhead. Если канал potentially compromised — переключить позже.Email механизм:msmtp+msmtp-mtaapt-installed на VDS. Config в/etc/msmtprc(chmod 600 root:root, system-wide since cron runs as root). SMTPsmtp.yandex.ru:465+ credsnoreply@snolla.comизnoreply-snolla-smtp.env. Test send → Yandex 250 OK ✅.- Phone confirm: user verifies ntfy push на
vds-backuptopic пришёл из реального cron run (или manual run).
Implementation sketch
/etc/cron.d/vds-backup:
# 05:00 MSK ежедневно
0 5 * * * vitya /opt/stacks/backup/scripts/run.sh
/opt/stacks/backup/scripts/run.sh:
#!/bin/bash
set -e
SOURCE_DIRS=(/opt/stacks/gitea/data /opt/stacks/verdaccio/storage /opt/stacks/verdaccio/config /opt/stacks/registry/docker /opt/stacks/registry/auth /opt/stacks/traefik /opt/stacks/portainer/data /etc/ssh /etc/ufw /etc/hosts /etc/docker /etc/letsencrypt)
DEST_BASE=/volume1/NetBackup/vds-kzntsv
TODAY=$(date +%Y-%m-%d)
LATEST=$DEST_BASE/latest
START_TIME=$(date +%s)
LOG=/tmp/backup-$TODAY.log
# DB dumps первым шагом — pg/maria/mongo в /tmp/db-dumps/$TODAY/, потом включаются в rsync
mkdir -p /tmp/db-dumps/$TODAY
docker exec postgres pg_dumpall -U postgres > /tmp/db-dumps/$TODAY/postgres.sql
docker exec mariadb mariadb-dump --all-databases -u root -p"$MARIA_PASS" > /tmp/db-dumps/$TODAY/mariadb.sql
docker exec mongo mongodump --out=/tmp/mongo --uri="mongodb://root:$MONGO_PASS@localhost:27017?tls=true&tlsAllowInvalidCertificates=true"
docker exec redis redis-cli --tls --insecure -a "$REDIS_PASS" --rdb /data/dump.rdb
# rsync с --link-dest для hardlink-incremental
rsync -azh --link-dest=$LATEST "${SOURCE_DIRS[@]}" /tmp/db-dumps/$TODAY \
-e "ssh -i ~/.ssh/id_ed25519_kreknin" \
vitya@195.19.90.188:$DEST_BASE/$TODAY/
ssh -i ~/.ssh/id_ed25519_kreknin vitya@195.19.90.188 \
"rm -f $LATEST && ln -sf $DEST_BASE/$TODAY $LATEST"
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
SIZE=$(du -sh $DEST_BASE/$TODAY 2>/dev/null | cut -f1)
# Email via msmtp
echo "Subject: VDS backup $TODAY — SUCCESS
Size: $SIZE, duration: ${DURATION}s
Source: vds.kzntsv.site
Dest: kreknin.site:$DEST_BASE/$TODAY/
" | msmtp vitya.kuznetsov@gmail.com
(скетч; добавить retention prune — find $DEST_BASE -maxdepth 1 -type d -name "20*" | sort | head -n -7 | xargs rm -rf, error trap, etc.)
Decisions log
- 2026-05-20 — rsync
--link-destchosen over restic/borg. Built-in, no encryption key management, VDS↔kreknin trusted link. Encryption defer if threat model changes. - 2026-05-20 — Cron runs as root, not vitya. Initial vitya run hit ~30 Permission Denied (gitea/portainer container-owned files, /etc/ssh host keys, /etc/ufw rules). Trade-off: больше privilege чем нужно, но альтернатива (sudo wrap rsync) — сложнее. Mitigation:
/etc/msmtprcchmod 600 root:root,/opt/stacks/backup/.envchmod 600. - 2026-05-20 — DB dump approach:
docker exec <container>с CLI-passed credentials, не URI params. Mongo требует legacy--ssl --sslAllowInvalidCertificates(НЕ--tls --tlsInsecuredespite --help listing--tlsInsecure— fails as unknown option pre---ssl). - 2026-05-20 — Retention начали с 7 daily snapshots (RETENTION_DAYS=7). Weekly/monthly defer — 12G/day @ 7 days = 84G headroom вне hardlinks, на kreknin 5.6T free; нет смысла усложнять.
- 2026-05-20 — Cron не был установлен на VDS из-коробки на Ubuntu 24.04 — apt install cron был нужен. Lesson для будущих vds-* tasks: проверять
which cronв preflight. - 2026-05-20 — msmtp
/etc/msmtprcsystem-wide (а не~/.msmtprc) потому что cron как root → msmtp picks up /etc/ first. - 2026-05-20 — Smoke run (2026-05-20 23:37 → 00:00) successful: 71,867 files / 11.74G transferred в 21m27s, all 4 DB dumps OK, latest symlink updated, ntfy + email sent.
Completed steps
- msmtp + msmtp-mta apt-installed;
/etc/msmtprcwritten с Yandex SMTP creds (chmod 600 root:root) /opt/stacks/backup/.envсоздан с DB passwords + kreknin creds + retention (chmod 600)/opt/stacks/backup/scripts/run.shнаписан (bash + flock single-instance + ERR trap)- DB dumps protocol: pg_dumpall, mariadb-dump --single-transaction, mongodump --ssl --sslAllowInvalidCertificates, redis-cli SAVE + docker cp
- rsync sources finalized: /opt/stacks/*, /etc/{ssh,ufw,hosts,docker}, /home/vitya/.ssh, $DUMP_DIR
/var/log/vds-backup/log dir (pre-created via sudo + chown vitya)/etc/cron.d/vds-backupinstalled (root,0 5 * * *)- apt install cron (Ubuntu 24.04 не имел его out-of-box); cron.service active + enabled
- Smoke run as root: 71,867 files / 11.74G на kreknin:/volume1/NetBackup/vds-kzntsv/2026-05-20, latest symlink set, ntfy publish 200, email Yandex 250 OK
- Permission errors из vitya-run выявлены и устранены переходом на root cron
Notes
- Триггер: после
[[vds-kzntsv-bootstrap]]Phase 3 + verdaccio/registry стабильны (done). - Integration с vds-ntfy-push — backup publish на topic
vds-backup(admin auth). - Retention vs disk: kreknin 5.7T free, daily 7 × ~12G full ≈ 85G headroom (hardlinks делают incremental ~1G/day после day 1).
- acme.json проходит через rsync (внутри /opt/stacks/traefik) — содержит LE private keys, но VDS↔kreknin link trusted, kreknin ACL restricted to vitya. Acceptable trade-off vs шифрование через restic.
- Atomic revert:
ssh vitya@89.253.255.94 'sudo systemctl stop cron; sudo rm /etc/cron.d/vds-backup; sudo apt-get remove -y cron msmtp msmtp-mta; sudo rm -rf /etc/msmtprc /opt/stacks/backup /var/log/vds-backup'