Kopie zapasowe VPS: restic, rclone i kopia poza serwerem
Co kopiować z VPS (bazy, wolumeny, konfiguracja), restic albo rclone crypt, szyfrowana kopia poza serwerem, test odtwarzania i harmonogram w cron.
Redakcja serwisu Dealownia · ceny i fakty ze stron dostawców, jak sprawdzamy
Codzienna, szyfrowana kopia zapasowa VPS-a, która leży u innej firmy niż serwer, sama usuwa stare wersje, raz w miesiącu jest sprawdzana odtworzeniem i wysyła sygnał, gdy się nie wykona. Opisujemy dwa sposoby: restic (kopie przyrostowe z deduplikacją) i prostsze archiwum tar wysyłane przez rclone z szyfrowaniem. W wariancie restic skrypt trzyma 7 kopii dziennych, 4 tygodniowe i 6 miesięcznych; w wariancie z archiwum – archiwa z ostatnich 30 dni. Liczby łatwo zmienić, opisujemy gdzie.
Czego potrzebujesz
- VPS z Ubuntu 24.04 LTS albo Debianem 12 lub 13 i dostęp przez
sudo. - Miejsce na kopie u innego dostawcy niż serwer: serwer SFTP (np. wynajęty „storage box”), przestrzeń zgodną z S3 albo dysk w chmurze obsługiwany przez rclone. Drugi VPS u tej samej firmy, w tej samej serwerowni, nie chroni przed awarią tej serwerowni ani blokadą konta.
- Menedżer haseł na hasło szyfrowania. Bez tego hasła kopii nie odczytasz – ani Ty, ani nikt inny.
Krok 1. Ustal, co kopiować
Kopiuj to, czego nie odtworzysz z repozytorium:
| Co | Gdzie zwykle leży | Jak |
|---|---|---|
| Bazy danych | kontenery Postgres, MariaDB | zrzut (pg_dump, mariadb-dump), nie surowe pliki |
| Dane aplikacji | wolumeny i katalogi ./data w /opt/apps |
pliki |
| Konfiguracja | /opt/apps/*/compose.yaml, .env, /etc/nginx, /etc/cron.d |
pliki |
| Certyfikaty i konto ACME | /etc/letsencrypt |
pliki |
Strony statyczne pomijamy – zbudujesz je ponownie z repozytorium. Surowych plików Postgresa i SQLite nie kopiuj w trakcie pracy bazy: zapisane w połowie transakcji dają kopię, której baza nie przyjmie. Bazy SQLite kopiuj poleceniem sqlite3 baza.db ".backup kopia.db", a Postgresa przez pg_dump. Pamiętaj, że w kopii są pliki .env z hasłami – całość traktuj jak sejf z hasłami.
Krok 2. Zrzuty baz przed kopią
Nazwę usługi (db), użytkownika i bazy weź ze swojego compose.yaml. Format -Fc jest skompresowany i odtwarza się przez pg_restore. Dla MariaDB: docker compose exec -T db mariadb-dump --single-transaction -u root -p"$HASLO" nazwa_bazy.
Krok 3a. restic: instalacja i repozytorium
Wersje w repozytoriach: Ubuntu 24.04 – 0.16.4, Debian 12 – 0.14.0, Debian 13 – 0.18.0. Na Debianie 12 rozważ oficjalny plik binarny z wydań restic na GitHubie – dokumentacja instalacji wprost poleca go, gdy pakiet dystrybucji jest stary.
Konfigurację trzymaj w pliku dostępnym tylko dla roota:
Ostatnia komenda wypisuje hasło – przepisz je teraz do menedżera haseł. sftp:kopie:/restic/vps korzysta z aliasu kopie w /root/.ssh/config (host, użytkownik, klucz), bo kopia będzie działać jako root. Inne formaty adresu według dokumentacji restic: s3:https://serwer/bucket dla usług zgodnych z S3 i rclone:zdalny:sciezka dla wszystkiego, co obsługuje rclone. restic szyfruje dane sam, więc pod nim nie potrzebujesz szyfrowania rclone.
Krok 3b. Alternatywa: archiwum i rclone crypt
Jeśli wolisz pojedyncze archiwa (łatwo je pobrać i rozpakować bez restic), pakuj je tar i wysyłaj przez rclone ze zdalnym typu crypt. Według dokumentacji rclone crypt najpierw konfigurujesz zwykły zdalny (np. chmura), potem drugi typu crypt z remote = chmura:kopie-vps. Domyślne filename_encryption = standard szyfruje też nazwy plików, a password2 (sól) dokumentacja zaleca ustawić inną niż hasło główne.
Hasło w rclone.conf jest tylko „lekko zaciemnione”, nie zaszyfrowane – plik konfiguracji ustaw na 600 i nie dokładaj go do samej kopii. Wysyłkę i rotację zapisz jako skrypt /usr/local/sbin/kopia-tar.sh (działa jako root, bo czyta /etc/letsencrypt):
Archiwum zawiera klucze prywatne z /etc/letsencrypt i pliki .env z hasłami, dlatego umask 077 i katalog z prawami 700 – nikt poza rootem go nie odczyta. Po udanej wysyłce lokalne archiwum jest usuwane, więc dysk serwera nie zapełnia się kopiami. Dzięki set -e przy błędzie tar albo rclone copy skrypt kończy się wcześniej i nie kasuje starych kopii po drugiej stronie. --min-age 30d zostawia archiwa z ostatnich 30 dni – zmień tę wartość, jeśli chcesz dłużej. Uprawnienia i pierwsze uruchomienie: sudo chmod 700 /usr/local/sbin/kopia-tar.sh && sudo /usr/local/sbin/kopia-tar.sh.
Krok 4. Skrypt kopii (wariant restic)
/usr/local/sbin/kopia.sh:
Pomyśl też o scenariuszu, w którym ktoś przejmuje serwer. Dane logowania do miejsca kopii leżą wtedy na tym samym serwerze i pozwalają nie tylko dopisywać, ale też kasować kopie. Jeśli miejsce na kopie to umożliwia, nadaj kontu serwera prawo tylko do zapisu (bez usuwania) albo włącz po stronie dostawcy migawki lub wersjonowanie, a usuwanie starych kopii uruchamiaj z innej maszyny. Przy kopii prywatnych projektów często wystarczy, że raz w miesiącu ściągniesz ostatnie archiwum na własny dysk.
Wykluczenia dopasuj do swoich katalogów – chodzi o surowe pliki baz, które zastępują zrzuty. forget zostawia 7 kopii dziennych, 4 tygodniowe i 6 miesięcznych (zmienisz to parametrami --keep-…), a --prune od razu zwalnia miejsce. Od wersji 0.17 restic umie też zapisać wynik komendy bez pliku pośredniego (backup --stdin-from-command -- pg_dump …), ale na Ubuntu 24.04 z pakietu tej opcji nie ma.
Krok 5. Harmonogram i sygnał „kopia się wykonała”
/etc/cron.d/kopia:
W wariancie z archiwum zamiast kopia.sh wpisz kopia-tar.sh. Adres z $? na końcu to funkcja Healthchecks.io: 0 oznacza sukces, inna liczba – błąd. Jeśli sygnał nie przyjdzie w ogóle (serwer leży, cron nie działa), usługa też zaalarmuje. Więcej o takim „martwym przełączniku” w poradniku o monitoringu serwera. Ostatnia linia pliku w /etc/cron.d musi kończyć się znakiem nowej linii, a końce linii muszą być w formacie LF.
Krok 6. Test odtworzenia
Kopia, której nikt nie odtworzył, jest tylko nadzieją. Raz w miesiącu:
check --read-data-subset=5% czyta losowe 5% danych z repozytorium i sprawdza, czy dają się odszyfrować. pg_restore --list (pakiet postgresql-client) pokaże spis tabel – jeśli plik jest uszkodzony, skończy się błędem. Pełny test raz na kwartał: nowy, tymczasowy VPS, odtworzenie konfiguracji i baz, uruchomienie usług. Wtedy dowiesz się, ile naprawdę trwa powrót do pracy.
Najczęstsze problemy
- Cron przestał uruchamiać wszystkie zadania. Plik w
/etc/cron.dzapisany na Windowsie ma końce linii CRLF. Jeden taki plik potrafi zatrzymać wszystkie zadania. Przed wgraniem usuń znaki\r(sed -i 's/\r$//' plik) i sprawdźjournalctl -u cron. - Zrzut bazy ma 0 bajtów, a kopia „się udała”. Bez
set -o pipefailbłądpg_dumpw potoku ginie. Skrypt z kroku 4 przerwie się na błędzie, a Healthchecks dostanie kod różny od zera. Fatal: wrong password or no key found. Inne hasło niż przyrestic initalbo zmienna z innego pliku. Dlatego hasło ma być w menedżerze haseł, a nie tylko na serwerze.- Repozytorium rośnie mimo
forget.forgetbez--pruneusuwa tylko wpisy migawek, dane zostają. Dodaj--prunealbo uruchamiajrestic pruneosobno. - Wysyłka przez rclone do dysku w chmurze kończy się błędem limitu. Wspólny identyfikator aplikacji rclone bywa ograniczany przez dostawcę. Załóż własny klucz API zgodnie z instrukcją danego zdalnego w dokumentacji rclone.
Co dalej
Dołóż monitoring z alertami, żeby dowiedzieć się o zapełnionym dysku, zanim kopia przestanie się mieścić. Jeśli kopiujesz narzędzia z jednego pliku compose, dopisz do skryptu zrzut każdej bazy. Serwer albo przestrzeń na kopie u innego dostawcy znajdziesz w dziale promocje: VPS.