Záloha, kterou jste nikdy nezkusili obnovit, není záloha — je to naděje. A naděje vám v pět ráno, když lehne produkční stroj, moc nepomůže. V následujících krocích vám ukážu přesně to, co v praxi děláme sami: offsite, inkrementální a šifrované zálohy produkčních serverů na Hetzner Storage Box. Žádná magie, jen ověřený řetězec příkazů, který na Debianu 12 a Ubuntu 22.04+ funguje tak, jak má.
Proč vůbec řešit offsite zálohu
Pravidlo 3-2-1 říká: tři kopie dat, na dvou různých typech úložiště, jedna mimo lokalitu. Snapshoty na stejném serveru vám nezachrání zadek, když shoří datacentrum, smaže vás ransomware nebo si někdo splete rm -rf. Offsite kopie musí být na jiném místě i na jiné infrastruktuře než produkce — a hlavně musí přežít i to, když celý produkční stroj definitivně lehne.
Proč zrovna Storage Box
Storage Box je levné síťové úložiště od Hetzneru (řádově jednotky eur měsíčně za 1 TB) a mluví vším, co k zálohám potřebujete: SFTP, SCP, rsync, BorgBackup, restic přes SFTP backend, WebDAV i Samba/CIFS (a k tomu FTP/FTPS). Nečekejte ale plnohodnotný interaktivní shell — SSH tu slouží hlavně jako transport pro SFTP/SCP/rsync/Borg; na portu 23 běží jen omezený shell s pevnou sadou příkazů. Pro nás jsou klíčové tři věci:
- Je to jiná infrastruktura než váš produkční server — přesně to, co offsite část 3-2-1 vyžaduje.
- Umí sub-účty — každý zálohovaný server dostane vlastní přihlašovací údaje omezené na svůj podadresář.
- Umí serverové snapshoty (automatické i ruční) jako druhou pojistku proti tomu, aby vám kompromitovaný server smazal i zálohy.
Krok 1: Zapnout port 23, vygenerovat a nahrát SSH klíč
SFTP a SCP jsou na Storage Boxu na portu 22 vždy aktivní a nejdou vypnout. Pro rsync a BorgBackup ale potřebujete port 23 — rozšířenou SSH službu, kterou zapnete v konzoli Storage Boxu (Hetzner Console → Change settings) přepínačem SSH support. Po aktivaci chvíli počkejte, než port naběhne. Protože v článku používáme restic i Borg, zapneme SSH support a všechno povedeme přes port 23 (SFTP i SCP na něm fungují také).
Na produkčním serveru pak vygenerujte klíč — ideálně vyhrazený jen pro zálohy:
ssh-keygen -t ed25519 -f /root/.ssh/storagebox -C "backup"
Veřejný klíč nahrajete přes SFTP; pozor, sftp má přepínač portu velké -P (kdežto ssh malé -p):
echo -e "mkdir .ssh\nchmod 700 .ssh\nput /root/.ssh/storagebox.pub .ssh/authorized_keys\nchmod 600 .ssh/authorized_keys" \
| sftp -P 23 [email protected]
Aby restic ani vy nemuseli u každého příkazu řešit nestandardní port, zapište si spojení do ~/.ssh/config:
Host storagebox
HostName u123456.your-storagebox.de
User u123456
Port 23
IdentityFile /root/.ssh/storagebox
Tip z praxe: pro každý server si na Storage Boxu založte sub-účet (
u123456-sub1) omezený na vlastní podadresář. Když se jeden server zkompromituje, útočník nevidí zálohy ostatních.
Krok 2: Konzistentní dump databáze
Zálohovat živé datové soubory MySQL/MariaDB znamená koledovat si o rozbitou tabulku. Před samotnou zálohou proto uděláme konzistentní dump:
mariadb-dump --single-transaction --quick --routines --triggers --events \
--all-databases | gzip > /var/backups/db/all-$(date +\%F).sql.gz
--single-transaction otevře u InnoDB transakci a nasnímá konzistentní stav k jejímu začátku, aniž by blokoval běžná čtení a zápisy (DML). Dvě věci si ale pohlídejte: konzistence platí jen pro transakční tabulky (InnoDB) a souběžné DDL (ALTER, CREATE, DROP, RENAME nebo TRUNCATE TABLE) může dump během běhu rozbít nebo způsobit nekonzistenci. Zbylé přepínače: --routines, --triggers a --events přiberou do dumpu uložené procedury, spouště a naplánované události; --quick streamuje řádky ze serveru bez bufferování v paměti a --all-databases dumpne všechny databáze.
Na Debianu 12 (MariaDB 10.11) je nástroj mariadb-dump, mysqldump zůstává jako symlink; na MySQL 8 použijete mysqldump se stejnými přepínači. Tenhle dump pak zazálohujete jako obyčejný soubor.
Krok 3: Inicializace repozitáře a první záloha
My primárně sáhneme po resticu — inkrementální, deduplikuje a šifruje u klienta. Je v repozitářích obou distribucí:
apt install restic
Přihlašovací údaje a heslo repozitáře držte mimo příkazovou řádku, v proměnných prostředí:
export RESTIC_REPOSITORY="sftp:storagebox:/backups/nazev-serveru"
export RESTIC_PASSWORD_FILE="/root/.restic-pass"
Restic pro SFTP volá standardní ssh, takže si vytáhne port i klíč z ~/.ssh/config. Repozitář jednou inicializujete a pak už jen zálohujete:
restic init
restic backup /etc /var/www /var/backups/db
restic snapshots
Každá další záloha přenese jen změněné bloky.
Kdo preferuje Borg, inicializuje obdobně přes SSH — na Storage Boxu ale přidejte --remote-path, aby se na serveru použila kompatibilní verze Borgu (výchozí vzdálená je 1.2):
borg init --encryption=repokey-blake2 --remote-path=borg-1.4 \
ssh://[email protected]:23/./backups
Verzi v --remote-path zvolte podle své lokální instalace. borg init platí pro Borg 1.x; v Borgu 2.x je ekvivalentem borg repo-create. Zálohuje se pak borg create. Borg navíc umí serverový append-only režim, což je pěkná obrana proti mazání záloh.
Krok 4: Retence, ať vám úložiště nepřeteče
Bez úklidu repozitář poroste donekonečna. Restic řeší mazání starých snapshotů i fyzické uvolnění místa jedním příkazem:
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
U Borgu (verze 1.2 na Debianu 12 i Ubuntu 22.04) jsou to dva kroky: borg prune staré archivy jen označí ke smazání, ale místo v repozitáři neuvolní — to udělá až následný borg compact. Prune navíc chce cestu k repozitáři a bez výběru archivů (-a/--glob-archives) aplikuje politiku na všechny archivy, takže si ho nejdřív ověřte nasucho:
borg prune --list --dry-run --keep-daily=7 --keep-weekly=4 --keep-monthly=6 /cesta/k/repo
borg prune --keep-daily=7 --keep-weekly=4 --keep-monthly=6 /cesta/k/repo
borg compact /cesta/k/repo
Retenci si nastavte podle toho, jak daleko do minulosti se reálně potřebujete vracet.
Krok 5: Šifrování na straně klienta
Tohle je zásadní a děje se automaticky: restic i Borg šifrují data ještě na produkčním serveru (restic používá AES-256), na Storage Box putuje už jen šifrovaný text. Poskytovatel úložiště tak nevidí obsah vašich dat. Nečekejte ale, že je skryté úplně všechno — z metadat je pořád vidět velikost repozitáře i časy a frekvence záloh. A i tahle ochrana platí jen za předpokladu, že heslo repozitáře nikdy neopustí váš server.
Cena za pohodlí: ztratíte-li heslo repozitáře, ztratíte data. Heslo proto uložte i mimo zálohovaný server — do správce hesel, ne jen do souboru vedle zálohy.
Krok 6: Automatizace přes systemd timer
Ruční záloha je záloha, na kterou se zapomene. My to řešíme systemd timerem. Type=oneshot umí víc ExecStart= příkazů za sebou, takže dump databáze, samotnou zálohu i úklid retence dáme jako tři samostatné kroky:
# /etc/systemd/system/restic-backup.service
[Service]
Type=oneshot
EnvironmentFile=/etc/restic/env
ExecStart=/usr/local/bin/db-dump.sh
ExecStart=/usr/bin/restic backup /etc /var/www /var/backups/db
ExecStart=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
Kroky běží popořadě a když některý selže, další už nenaběhne — což je tu žádoucí: pokud selže samotná záloha, forget --prune staré snapshoty nesmaže.
# /etc/systemd/system/restic-backup.timer
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=1800
[Install]
WantedBy=timers.target
Časovač povolíte a rovnou spustíte jedním příkazem:
systemctl enable --now restic-backup.timer
enable časovač trvale povolí (naběhne po každém startu systému), --now ho zapne hned v aktuální relaci — samotná záloha ale proběhne až v čase z OnCalendar. Persistent=true dožene zameškaný běh, když byl server vypnutý, RandomizedDelaySec rozprostře náběh. Kdo nechce systemd, dá totéž do cronu — princip je stejný, jen bez hlídání zameškaných běhů.
Krok 7 (a nejdůležitější): testujte obnovu
A jsme u jádra pudla. Záloha, kterou jste nikdy neobnovili, je jen domněnka. Restore proto testujeme pravidelně — do dočasného adresáře, ať nepřepíšeme produkci:
restic restore latest --target /tmp/restore-test
Zvlášť ověřte, že se z dumpu skutečně naimportuje databáze do prázdné instance. A jednou za čas nechte restic ověřit integritu i s reálným čtením dat z úložiště:
restic check --read-data-subset=10%
Do kalendáře si dejte tvrdý termín „zkušební obnovy" — třeba čtvrtletně. Den, kdy zjistíte, že záloha je nepoužitelná, si vyberte vy, ne náhoda.
Shrnutí
Offsite zálohu na Storage Box postavíte za odpoledne a stojí pár eur měsíčně: zapnutý port 23, sub-účet pro oddělení přístupů, konzistentní dump databáze, inkrementální šifrovaná záloha resticem (nebo Borgem), rozumná retence a systemd timer, který to hlídá za vás. Šifrování u klienta drží obsah dat mimo dosah poskytovatele úložiště. Ale to, co odděluje funkční zálohu od falešného klidu, je jediná disciplína — pravidelně testovat obnovu. Bez ní zálohy nemají hodnotu.