From aedfddb3488322a712671d71da7c2bd45f4899ce Mon Sep 17 00:00:00 2001 From: vitya Date: Thu, 21 May 2026 00:02:59 +0300 Subject: [PATCH] =?UTF-8?q?feat(vds-backup-rsync-kreknin):=20done=20?= =?UTF-8?q?=E2=80=94=20daily=20VDS=E2=86=92kreknin=20live,=20cron=20armed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pipeline /opt/stacks/backup/scripts/run.sh + cron /etc/cron.d/vds-backup (root, 0 5 * * *) → kreknin /volume1/NetBackup/vds-kzntsv// + latest symlink. DB dumps (pg/maria/mongo/redis), /opt/stacks data, /etc/{ssh,ufw,hosts,docker}, vitya .ssh. Dual notify: msmtp+Yandex email + ntfy publish vds-backup topic. Retention 7 daily snapshots. Smoke run 2026-05-20 23:37 → 00:00: 71,867 files / 11.74G transferred, 21m27s, exit 0. Email Yandex 250, ntfy 200. SPOF gap closed for VDS. Sub-tasks discovered + resolved en route: - apt install cron (Ubuntu 24.04 minimal не имел его out-of-box) - mongodump требует legacy --ssl --sslAllowInvalidCertificates flags - Permission denials под vitya → cron as root - msmtprc moved to /etc/ для root cron Co-Authored-By: Claude Opus 4.7 (1M context) --- STATUS.md | 10 +++++--- vds-backup-rsync-kreknin.md | 50 ++++++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/STATUS.md b/STATUS.md index 479f417..27270ed 100644 --- a/STATUS.md +++ b/STATUS.md @@ -53,10 +53,12 @@ _Updated: 2026-05-20_ --- -## ⚪ [vds-backup-rsync-kreknin] — ежедневный rsync VDS→kreknin в 05:00 MSK + email-нотификация -**Status:** ready (заведена 2026-05-20). Детали + sketch implementation в [vds-backup-rsync-kreknin.md](vds-backup-rsync-kreknin.md). -**Where I stopped:** task создана для backup pipeline VDS → kreknin (closing SPOF gap из [[future-resilient-architecture-goals]]). SMTP creds для noreply@snolla.com на Yandex сохранены в `~/projects/.common/secrets/noreply-snolla-smtp.env`. Рекомендованный recipient `vitya.kuznetsov@gmail.com`. Дублирующий канал — [[vds-ntfy-push]] (push на телефон). -**Next action:** msmtp setup на VDS + rsync script с DB dumps + --link-dest incremental + cron 05:00 + email на vitya.kuznetsov@gmail.com + ntfy publish. Retention 7d/4w/6m. +## 🟢 [vds-backup-rsync-kreknin] — daily VDS→kreknin live, smoke green, cron armed +**Status:** done (2026-05-20 → 2026-05-21 00:00 first-run завершён успешно). Детали в [vds-backup-rsync-kreknin.md](vds-backup-rsync-kreknin.md). +**Result:** rsync `--link-dest` pipeline `/opt/stacks/backup/scripts/run.sh` под cron `0 5 * * *` (root) → kreknin `/volume1/NetBackup/vds-kzntsv//` + symlink `latest`. DB dumps (pg/maria/mongo/redis), system config (/etc/ssh, ufw, hosts, docker), ssh keys, /opt/stacks data. Notification dual-channel: email через msmtp+Yandex (`/etc/msmtprc`) + ntfy publish на `vds-backup` topic. Retention 7 daily snapshots. Smoke run done — 71,867 files / 11.74G в 21m27s, exit 0. Cron service installed (apt install cron — Ubuntu 24.04 не имел его) + enabled. Next run автоматически 2026-05-21 05:00 MSK. +**SPOF gap status:** closed for VDS — full restore from kreknin возможен (DB dumps + конфиги + ssh keys). +**Open:** phone-side smoke (user verifies ntfy push пришёл из реального backup run). +**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'` **Branch:** master --- diff --git a/vds-backup-rsync-kreknin.md b/vds-backup-rsync-kreknin.md index a02b0d6..db684cb 100644 --- a/vds-backup-rsync-kreknin.md +++ b/vds-backup-rsync-kreknin.md @@ -6,15 +6,17 @@ ## Open questions -- [ ] **Что бэкапить:** - - `/opt/stacks/` — все compose-стеки и их data (включая `gitea/data/`, `verdaccio/storage/`, `registry/docker/`, `databases/*/data/`, `traefik/letsencrypt/`, `portainer/data/`). Большой объём. - - `/etc/` — system config (sshd_config, ufw, fail2ban, /etc/hosts, /etc/docker/, /etc/letsencrypt если есть). - - `~/.ssh/` для vitya — authorized_keys. - - **DBs:** rsync raw datadir постгреса/мариа/монги — НЕ безопасно (running container держит locks). Нужен `pg_dump` / `mysqldump` / `mongodump` ПЕРЕД rsync — сложнее. -- [ ] **Куда на kreknin:** `/volume1/NetBackup/vds-kzntsv/` (или новая шара). Retention — daily 7 days, weekly 4, monthly 6 — через `--link-dest` hardlink-cascade или borg/restic. -- [ ] **Заходить на kreknin через SSH:** `vitya@195.19.90.188`, ключ `id_ed25519_kreknin`. Но ключ сейчас лежит на VDS в `/home/vitya/.ssh/id_ed25519_kreknin` (скопировал во время Phase 3 миграции) — продолжать использовать? -- [ ] **Tool:** raw rsync с `--link-dest` (built-in, простой); или **restic/borg** (encrypted, dedup, push). Encrypted backups важны если канал между VDS↔kreknin не доверять. -- [ ] **Email механизм:** установить `msmtp` + `mailx` на VDS, конфиг → SMTP через `smtp.yandex.ru:465` (creds — в `~/projects/.common/secrets/noreply-snolla-smtp.env` на Windows-side; на VDS залить аналог через scp). Или использовать `curl --mail-from ... smtp://`. +- [x] ~~**Что бэкапить:**~~ Resolved 2026-05-20. Sources в `/opt/stacks/backup/scripts/run.sh`: + - `/opt/stacks/{gitea,verdaccio/storage,verdaccio/config,registry,traefik,portainer,ntfy,backup}` + - `/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 вместо). +- [x] ~~**Куда на kreknin:**~~ `/volume1/NetBackup/vds-kzntsv//` + symlink `latest`. Retention 7 daily snapshots (RETENTION_DAYS env). Weekly/monthly — defer (overkill для текущих ~12G). +- [x] ~~**SSH key:**~~ продолжаем `/home/vitya/.ssh/id_ed25519_kreknin` — скрипт читает абсолютным path (work as root too). +- [x] ~~**Tool:**~~ rsync `--link-dest` (built-in, hardlink-incremental). Encrypted (restic/borg) defer — VDS↔kreknin link trusted (оба ours), encryption key management = ops overhead. Если канал potentially compromised — переключить позже. +- [x] ~~**Email механизм:**~~ `msmtp` + `msmtp-mta` apt-installed на VDS. Config в `/etc/msmtprc` (chmod 600 root:root, system-wide since cron runs as root). SMTP `smtp.yandex.ru:465` + creds `noreply@snolla.com` из `noreply-snolla-smtp.env`. Test send → Yandex 250 OK ✅. +- [ ] **Phone confirm:** user verifies ntfy push на `vds-backup` topic пришёл из реального cron run (или manual run). ## Implementation sketch @@ -70,11 +72,31 @@ Dest: kreknin.site:$DEST_BASE/$TODAY/ ## Decisions log -- _Пусто — задача только заведена._ +- **2026-05-20** — rsync `--link-dest` chosen 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/msmtprc` chmod 600 root:root, `/opt/stacks/backup/.env` chmod 600. +- **2026-05-20** — DB dump approach: `docker exec ` с CLI-passed credentials, не URI params. Mongo требует **legacy `--ssl --sslAllowInvalidCertificates`** (НЕ `--tls --tlsInsecure` despite --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/msmtprc` system-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 + +- [x] msmtp + msmtp-mta apt-installed; `/etc/msmtprc` written с Yandex SMTP creds (chmod 600 root:root) +- [x] `/opt/stacks/backup/.env` создан с DB passwords + kreknin creds + retention (chmod 600) +- [x] `/opt/stacks/backup/scripts/run.sh` написан (bash + flock single-instance + ERR trap) +- [x] DB dumps protocol: pg_dumpall, mariadb-dump --single-transaction, mongodump --ssl --sslAllowInvalidCertificates, redis-cli SAVE + docker cp +- [x] rsync sources finalized: /opt/stacks/*, /etc/{ssh,ufw,hosts,docker}, /home/vitya/.ssh, $DUMP_DIR +- [x] `/var/log/vds-backup/` log dir (pre-created via sudo + chown vitya) +- [x] `/etc/cron.d/vds-backup` installed (root, `0 5 * * *`) +- [x] apt install cron (Ubuntu 24.04 не имел его out-of-box); cron.service active + enabled +- [x] 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 +- [x] Permission errors из vitya-run выявлены и устранены переходом на root cron ## Notes -- Триггер: после `[[vds-kzntsv-bootstrap]]` Phase 3 + verdaccio/registry стабильны. -- SMTP creds: `C:\Users\vitya\projects\.common\secrets\noreply-snolla-smtp.env` (Windows-side, не в git'е). Сериализовать в `/etc/msmtprc` на VDS аккуратно (chmod 600). -- Retention vs disk: kreknin имеет ~5.6 TB free; daily 30 + weekly 6 + monthly 12 = ~50 snapshots, при ~10G inc + ~50G full = ~500G total. OK headroom. -- **Не бэкапить acme.json в plain текст** — содержит LE private keys. Encrypt через restic OR пропустить. +- Триггер: после `[[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'`