Backup nie jest od tego, żeby „coś tam było w panelu hostingu”. Backup jest od tego, żeby po błędzie, awarii, włamaniu albo przypadkowym rm -rf dało się postawić aplikację z powrotem. Najlepiej bez nerwowego szukania starego pliku .env, zgadywania hasła do bazy i ręcznego odtwarzania konfiguracji Nginx z pamięci.
Najczęstszy błąd na VPS-ie wygląda niewinnie: jest snapshot, więc właściciel aplikacji uznaje temat za załatwiony. Problem wychodzi dopiero przy odtwarzaniu. Snapshot ma trzy dni, baza była wtedy w trakcie zapisu, uploady użytkowników są nowsze niż obraz dysku, a konfiguracja Dockera została zmieniona po drodze i nie wiadomo jak. Technicznie coś istnieje. Praktycznie — aplikacja nadal leży.
Dobry backup VPS trzeba zaprojektować od strony odtwarzania, nie od strony kopiowania. Najpierw ustala się, co musi wrócić, w jakiej kolejności i po jakim maksymalnym czasie. Dopiero potem wybiera narzędzia: dump bazy, kopię katalogów, backup wolumenów Dockera, storage obiektowy, drugi serwer, harmonogram, retencję i test restore.
Snapshot VPS to nie zawsze prawdziwy backup
Snapshot VPS to zdjęcie stanu maszyny w konkretnym momencie. Zwykle obejmuje cały dysk albo wolumen, czasem także konfigurację maszyny. Jest szybki, wygodny i świetny przed ryzykowną operacją: aktualizacją systemu, migracją bazy, dużym deployem, zmianą partycji. Klikasz snapshot, robisz zmianę, coś wybucha, wracasz.
Tyle że snapshot to nie to samo co backup aplikacji.
Różnice są zasadnicze:
| Mechanizm | Co robi | Do czego się nadaje | Gdzie potrafi zawieść |
|---|---|---|---|
| Snapshot | zapisuje stan VPS-a lub dysku w danym momencie | szybki rollback po zmianie | może być w tej samej infrastrukturze, może złapać niespójną bazę, często ma krótką retencję |
| Backup plików | kopiuje wskazane katalogi i pliki | uploady, konfiguracje, pliki aplikacji | nie wystarczy dla działającej bazy danych |
| Backup bazy danych | robi logiczny dump albo backup fizyczny bazy | PostgreSQL, MySQL, MariaDB | źle wykonany dump może nie zawierać ról, uprawnień, procedur, eventów |
| Backup aplikacji | pozwala odtworzyć kod, build, zależności i runtime | aplikacje bez pełnego CI/CD albo bez repozytorium Git | sam kod bez .env, bazy i uploadów jest zwykle bezużyteczny |
| Backup konfiguracji | zapisuje ustawienia serwera i usług | Docker Compose, Nginx, Caddy, Traefik, systemd, cron | bez sekretów i mapowania wolumenów konfiguracja może nie uruchomić aplikacji |
| Replikacja | kopiuje dane prawie na bieżąco do drugiego miejsca | wysoka dostępność, szybkie przełączenie | skasowanie, uszkodzenie albo zainfekowanie danych też może się zreplikować |
| Disaster recovery | opisuje cały proces powrotu po awarii | odbudowa usługi po utracie VPS-a, regionu lub konta | bez testów jest tylko dokumentem, nie gwarancją |
Granica jest prosta: snapshot pomaga, gdy chcesz cofnąć maszynę. Backup pomaga, gdy chcesz odzyskać konkretne dane i postawić usługę nawet na nowym serwerze, u innego dostawcy.
Najbardziej zdradliwe są bazy danych. Jeżeli PostgreSQL albo MySQL pracuje w chwili tworzenia snapshota, obraz dysku może być tylko „crash-consistent”. To znaczy: podobny do sytuacji po nagłym odcięciu zasilania. Nowoczesne bazy zwykle umieją się po tym podnieść, ale „zwykle” to za mało, gdy mówimy o jedynej kopii danych klientów, zamówień, faktur albo treści użytkowników.
Dlatego snapshot traktuję jako warstwę pomocniczą:
- przed aktualizacją systemu — tak;
- przed migracją aplikacji — tak;
- jako jedyny backup produkcji — nie;
- jako backup bazy danych — tylko wtedy, gdy baza została wcześniej zatrzymana albo snapshot jest wykonany zgodnie z procedurą danej bazy;
- jako kopia poza dostawcą VPS — nie, jeśli snapshot siedzi u tego samego providera, na tym samym koncie i w tym samym regionie.
Tu wchodzi praktyczne rozróżnienie na RPO i RTO. RPO odpowiada na pytanie: ile danych możesz stracić? Przy blogu może to być 24 godziny. Przy sklepie — godzina bywa zbyt długa. Przy systemie płatności 5 minut może być problemem. RTO mówi: jak szybko usługa ma wrócić? Backup raz dziennie może być poprawny, ale jeśli restore trwa osiem godzin, to biznesowo nadal boli.
Minimum dla małego VPS-a produkcyjnego wygląda tak:
- codzienny backup PostgreSQL na VPS albo MySQL/MariaDB;
- codzienna kopia uploadów i konfiguracji;
- kopia poza VPS-em;
- retencja, np. 7 kopii dziennych, 4 tygodniowe, 6 miesięcznych;
- test odtworzenia przynajmniej raz po wdrożeniu i potem cyklicznie;
- osobne dane dostępowe do backupu, najlepiej bez prawa kasowania starych kopii.
Najgorszy układ to backup zapisywany na tym samym VPS-ie, na tym samym dysku, bez wysyłki na zewnątrz. Taki backup znika razem z awarią dysku, błędnym mkfs, włamaniem albo blokadą konta.
Backup bazy danych, plików i konfiguracji — co trzeba kopiować?
Dobry backup VPS krok po kroku zaczyna się od listy składników. Nie od narzędzia. Narzędzie można zmienić. Pominięty plik .env albo katalog z uploadami potrafi rozwalić cały plan odtwarzania.
Najwyższy priorytet mają dane, których nie odtworzysz z repozytorium:
- baza PostgreSQL/MySQL/MariaDB;
- katalogi z uploadami użytkowników;
- pliki
.envi inne sekrety aplikacji; - konfiguracja Docker Compose;
- konfiguracja Nginx, Caddy albo Traefik;
- niestandardowe certyfikaty TLS;
- klucze SSH potrzebne do deploya albo identyfikacji hosta;
- pliki aplikacji, jeśli nie są w Git;
- zadania cron, timery systemd, skrypty backupowe i deployowe;
- definicje usług systemd, jeżeli aplikacja działa poza Dockerem.
Baza danych wymaga osobnego traktowania. Kopiowanie katalogu z plikami PostgreSQL albo MySQL podczas pracy serwera to proszenie się o niespójność. Przy małych i średnich aplikacjach najprostszy jest logiczny dump.
Dla PostgreSQL sensowny punkt startowy:
install -m 700 -d /var/backups/vps/db
sudo -u postgres pg_dump -Fc appdb \
> /var/backups/vps/db/appdb_$(date -u +%Y%m%dT%H%M%SZ).dump
sudo -u postgres pg_dumpall --globals-only \
> /var/backups/vps/db/postgres_globals_$(date -u +%Y%m%dT%H%M%SZ).sql
pg_dump -Fc zapisuje bazę w formacie, który można wygodnie odtwarzać przez pg_restore. Druga komenda zapisuje role i ustawienia globalne. Bez tego po odtworzeniu może się okazać, że baza istnieje, ale aplikacja nie ma użytkownika, uprawnień albo oczekiwanej roli.
Dla MySQL albo MariaDB:
install -m 700 -d /var/backups/vps/db
mysqldump --defaults-extra-file=/root/.my.cnf \
--single-transaction \
--quick \
--routines \
--events \
--triggers \
appdb | gzip > /var/backups/vps/db/appdb_$(date -u +%Y%m%dT%H%M%SZ).sql.gz
Hasła nie warto wpisywać w komendzie po -p, bo ląduje w historii shella albo w liście procesów. Lepiej użyć pliku /root/.my.cnf z uprawnieniami 600.
Przy dużych bazach logiczny dump może być za wolny. W PostgreSQL wtedy wchodzi w grę pg_basebackup i archiwizacja WAL. W MySQL/MariaDB — fizyczne narzędzia backupowe, np. Percona XtraBackup dla zgodnych silników. Granica? Jeżeli dump trwa dłużej niż okno backupowe, obciąża produkcję albo restore zajmuje tyle, że przekracza akceptowalne RTO, trzeba przejść na cięższy mechanizm.
Uploady to drugi krytyczny punkt. Kod aplikacji często jest w Git, obrazy kontenerów w registry, ale zdjęcia klientów, załączniki, avatary, pliki PDF, eksporty i dokumenty są zwykle tylko na serwerze albo w wolumenie. W Dockerze trzeba sprawdzić, gdzie naprawdę trafiają dane:
docker volume ls
docker volume inspect nazwa_wolumenu
docker compose config
Typowe lokalizacje poza Dockerem:
/srv/app/storage
/srv/app/uploads
/var/www/app/shared
/var/www/html/wp-content/uploads
/opt/app/public/uploads
W przypadku Dockera nie wystarczy hasło „backup Docker volumes”. Trzeba rozdzielić typy wolumenów. Wolumen z uploadami można backupować plikowo. Wolumen z bazą danych backupuje się przez mechanizm bazy, nie przez tar na żywym katalogu danych. Surowy backup wolumenu PostgreSQL albo MySQL ma sens dopiero po zatrzymaniu kontenera albo przy procedurze gwarantującej spójność.
Pliki .env są małe, ale często ważniejsze niż cały kod. Zawierają adres bazy, hasła, tokeny API, sekrety JWT, klucze SMTP, dane S3, konfigurację płatności. Bez nich aplikacja może się uruchomić, ale nie zaloguje się do bazy, nie wyśle maila i nie podpisze sesji użytkowników.
W backupie powinny znaleźć się przynajmniej:
/srv/app/.env
/srv/app/.env.production
/srv/app/docker-compose.yml
/srv/app/docker-compose.override.yml
/srv/app/compose.yml
Nie wrzuca się takich plików luzem do nieszyfrowanego bucketu. To jest materiał dla zaszyfrowanego repozytorium backupowego albo menedżera sekretów. Jeżeli ktoś przejmuje kopię .env, często przejmuje też produkcyjną bazę i integracje zewnętrzne.
Konfiguracja reverse proxy decyduje o tym, czy ruch w ogóle trafi do aplikacji. Dla Nginx zwykle trzeba skopiować:
/etc/nginx/nginx.conf
/etc/nginx/sites-available/
/etc/nginx/sites-enabled/
/etc/nginx/conf.d/
Dla Caddy:
/etc/caddy/Caddyfile
/etc/caddy/
Dla Traefika:
traefik.yml
dynamic.yml
acme.json
docker-compose.yml
Przy acme.json trzeba pilnować uprawnień, bo plik może zawierać dane konta ACME i certyfikaty. Certyfikaty z Let’s Encrypt da się zwykle wygenerować ponownie, ale jeżeli masz certyfikaty komercyjne, wewnętrzne CA albo niestandardową konfigurację mTLS, backup jest obowiązkowy.
Klucze SSH to temat, który łatwo zepsuć w obie strony. Nie chodzi o bezmyślne kopiowanie całego /root/.ssh do bucketu. Chodzi o świadomą decyzję:
- host keys z
/etc/ssh/ssh_host_*zachowują tożsamość serwera; przy restore na nowym VPS-ie unikniesz ostrzeżeń wknown_hosts, ale musisz je chronić; - deploy keys używane do pobierania prywatnego repozytorium muszą być odtworzone albo zastąpione nowymi;
- prywatne klucze administratorów lepiej trzymać poza VPS-em, nie traktować serwera jako sejfu;
authorized_keysjest ważny, jeśli restore ma od razu wpuścić te same osoby i automaty.
Pliki aplikacji backupuje się tylko wtedy, gdy nie są odtwarzalne z Git, registry albo procesu CI/CD. Jeżeli aplikacja ma pełny pipeline, backup kodu jest drugorzędny. Jeżeli ktoś edytował pliki ręcznie na produkcji, kod produkcyjny staje się danymi. To nie jest eleganckie, ale w małych firmach się zdarza. Wtedy kopiujesz katalog aplikacji, a równolegle planujesz przeniesienie zmian do repozytorium.
Praktyczna lista kontrolna dla VPS-a:
[1] Baza danych:
PostgreSQL: dump bazy + globals
MySQL/MariaDB: dump z routines, events, triggers
[2] Dane użytkowników:
uploady, załączniki, eksporty, media, katalog storage
[3] Konfiguracja aplikacji:
.env, compose.yml, docker-compose.yml, pliki override
[4] Reverse proxy:
Nginx/Caddy/Traefik, reguły hostów, middleware, przekierowania
[5] System:
cron, systemd units, skrypty deploy/backup, konfiguracja firewall
[6] Dostęp:
deploy keys, authorized_keys, ewentualnie host keys
[7] Certyfikaty:
niestandardowe certyfikaty, acme.json, konfiguracja mTLS
Kolejność odtwarzania też ma znaczenie. Najpierw stawiasz system i runtime, potem konfigurację, potem bazę, następnie pliki użytkowników, na końcu reverse proxy i DNS. Jeżeli zrobisz odwrotnie, będziesz mieć publicznie działający serwer, który zwraca błędy, bo aplikacja nie ma jeszcze danych.
Automatyczne kopie do S3, Cloudflare R2, Backblaze B2 albo innego serwera
Automatyzacja backupu ma być nudna. Ten sam harmonogram, te same logi, ten sam format, ta sama retencja. Backup ręczny działa tylko do pierwszego urlopu, choroby albo weekendowego deploya.
Dobry układ dla małego VPS-a:
- lokalnie tworzysz dump bazy w
/var/backups/vps; - do zaszyfrowanego repozytorium dodajesz dump, uploady i konfigurację;
- repozytorium trafia poza VPS: do S3, Cloudflare R2, Backblaze B2 albo na drugi serwer po SFTP;
- stare kopie kasujesz według polityki retencji;
- regularnie uruchamiasz sprawdzenie integralności i test restore.
Do takiego scenariusza dobrze pasuje restic, bo działa jako pojedyncze narzędzie, obsługuje wiele backendów, przesyła tylko zmienione fragmenty plików, używa kryptografii i pozwala sprawdzać, czy dane da się odtworzyć. Restic obsługuje też storage zgodny z S3 przez składnię s3:https://server:port/bucket_name i standardowe zmienne AWS_ACCESS_KEY_ID oraz AWS_SECRET_ACCESS_KEY.
Przykład konfiguracji dla backup na Cloudflare R2:
install -m 700 -d /root/backup-env
cat > /root/backup-env/restic.env <<'EOF'
export RESTIC_REPOSITORY="s3:https://<ACCOUNT_ID>.r2.cloudflarestorage.com/<BUCKET_NAME>"
export AWS_ACCESS_KEY_ID="<ACCESS_KEY_ID>"
export AWS_SECRET_ACCESS_KEY="<SECRET_ACCESS_KEY>"
export RESTIC_PASSWORD_FILE="/root/backup-env/restic-password"
export AWS_DEFAULT_REGION="auto"
EOF
chmod 600 /root/backup-env/restic.env
openssl rand -base64 48 > /root/backup-env/restic-password
chmod 600 /root/backup-env/restic-password
Cloudflare R2 jest zgodne z API S3 w tym sensie, że wiele narzędzi i bibliotek S3 może działać po zmianie endpointu, ale nie jest kopią AWS S3 1:1; Cloudflare osobno dokumentuje, które operacje i funkcje API są obsługiwane. To ważne przy narzędziach korzystających z mniej popularnych funkcji S3. Przy prostym backupie plikowym zwykle liczą się operacje PUT, GET, LIST i multipart upload.
Stan na 20 czerwca 2026 r.: Cloudflare R2 Standard kosztuje 0,015 USD za GB-miesiąc, operacje Class A kosztują 4,50 USD za milion żądań, Class B 0,36 USD za milion żądań, a transfer egress do internetu jest bezpłatny. Bezpłatny próg obejmuje 10 GB-miesiąc storage, 1 mln operacji Class A i 10 mln operacji Class B miesięcznie. To jest powód, dla którego R2 dobrze pasuje do backupów, które czasem trzeba pobrać do testów albo odtworzyć poza chmurą źródłową — nie płacisz klasycznego rachunku za wyciągnięcie danych z bucketu.
Backblaze B2 ma inny profil. Stan na 20 czerwca 2026 r.: plan pay-as-you-go startuje od 6,95 USD za TB miesięcznie, pierwsze 10 GB storage jest bezpłatne, egress jest bezpłatny do poziomu 3× średniego miesięcznego storage, a nadwyżka kosztuje 0,01 USD/GB; operacje Class A, B i C są bezpłatne dla klientów pay-as-you-go, a Class D kosztuje 0,004 USD za 10 000 wywołań po pierwszych 2500 dziennie. To dobry wybór, gdy priorytetem jest niski koszt przechowywania i przewidywalny rachunek, zwłaszcza przy większych archiwach.
AWS S3 jest najbardziej rozbudowany, ale kosztowo trzeba patrzeć szerzej niż tylko na storage. S3 rozlicza m.in. przechowywanie, żądania, pobieranie danych, transfer, replikację i funkcje zarządzania. Transfer do S3 z internetu jest bezpłatny, pierwsze 100 GB miesięcznie transferu wychodzącego do internetu jest bezpłatne zbiorczo dla usług AWS i regionów z wyłączeniami, a transfer z S3 do CloudFront nie jest rozliczany jako zwykły transfer do internetu. W przykładzie AWS dla regionu Europe/Ireland transfer danych z S3 do internetu jest liczony po 0,09 USD/GB. S3 wybiera się nie dlatego, że jest najprostsze cenowo, tylko wtedy, gdy korzystasz już z AWS, potrzebujesz IAM, lifecycle policies, integracji, Object Lock albo firmowych procedur zgodności.
Drugi serwer przez SFTP też jest poprawną opcją. Szczególnie gdy chcesz pełnej kontroli, prostego SSH i kopii poza dostawcą VPS. Nie powinien to być jednak drugi VPS w tym samym panelu, tym samym regionie i na tym samym koncie. Awaria konta, blokada płatności albo problem dostawcy może wtedy zabrać produkcję i backup naraz.
Minimalny skrypt backupowy może wyglądać tak. Traktuj go jako szkielet: wybierz blok PostgreSQL albo MySQL, dopasuj ścieżki aplikacji i przetestuj restore na osobnej maszynie.
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
source /root/backup-env/restic.env
NOW="$(date -u +%Y%m%dT%H%M%SZ)"
WORK="/var/backups/vps/current"
rm -rf "$WORK"
install -m 700 -d "$WORK/db" "$WORK/config"
# PostgreSQL — użyj tego bloku, jeśli aplikacja działa na PostgreSQL
sudo -u postgres pg_dump -Fc appdb > "$WORK/db/postgres_appdb_$NOW.dump"
sudo -u postgres pg_dumpall --globals-only > "$WORK/db/postgres_globals_$NOW.sql"
# MySQL/MariaDB — użyj zamiast bloku PostgreSQL, jeśli aplikacja działa na MySQL/MariaDB
# mysqldump --defaults-extra-file=/root/.my.cnf \
# --single-transaction --quick --routines --events --triggers \
# appdb | gzip > "$WORK/db/mysql_appdb_$NOW.sql.gz"
# Konfiguracja reverse proxy i systemu
rsync -a /etc/nginx/ "$WORK/config/nginx/" 2>/dev/null || true
rsync -a /etc/caddy/ "$WORK/config/caddy/" 2>/dev/null || true
rsync -a /etc/traefik/ "$WORK/config/traefik/" 2>/dev/null || true
rsync -a /etc/systemd/system/ "$WORK/config/systemd/" 2>/dev/null || true
rsync -a /etc/cron.d/ "$WORK/config/cron.d/" 2>/dev/null || true
# Backup właściwy: dumpy + konfiguracja + uploady + pliki aplikacji wymagane do odtworzenia
restic backup \
"$WORK" \
/srv/app/uploads \
/srv/app/docker-compose.yml \
/srv/app/.env \
--tag vps-prod
# Retencja: 7 dziennych, 4 tygodniowe, 6 miesięcznych
restic forget \
--tag vps-prod \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--prune
# Szybka kontrola repozytorium
restic check --read-data-subset=1G
Pierwsze uruchomienie:
source /root/backup-env/restic.env
restic init
/usr/local/sbin/backup-vps.sh
restic snapshots
Automatyzacja przez systemd timer:
# /etc/systemd/system/backup-vps.service
[Unit]
Description=Backup VPS
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup-vps.sh
# /etc/systemd/system/backup-vps.timer
[Unit]
Description=Run VPS backup daily
[Timer]
OnCalendar=*-*-* 02:15:00
RandomizedDelaySec=20m
Persistent=true
[Install]
WantedBy=timers.target
Włączenie:
systemctl daemon-reload
systemctl enable --now backup-vps.timer
systemctl list-timers backup-vps.timer
journalctl -u backup-vps.service -n 100 --no-pager
Najważniejszy test nie brzmi: „czy backup się wykonał?”. Najważniejszy test brzmi: „czy da się z niego odtworzyć aplikację?”. Raz na jakiś czas postaw pusty VPS testowy i przejdź procedurę:
source /root/backup-env/restic.env
restic snapshots
restic restore latest --target /restore-test --tag vps-prod
Dalej:
- instalujesz PostgreSQL/MySQL;
- odtwarzasz role i bazę;
- kopiujesz
.env, compose i konfigurację proxy; - przywracasz uploady;
- uruchamiasz aplikację;
- sprawdzasz logowanie, upload pliku, wysyłkę maila, panel admina i zadania cron.
Dla PostgreSQL restore może wyglądać tak:
sudo -u postgres psql < /restore-test/var/backups/vps/current/db/postgres_globals_*.sql
createdb -O appuser appdb
pg_restore -d appdb /restore-test/var/backups/vps/current/db/postgres_appdb_*.dump
Dla MySQL/MariaDB:
gunzip -c /restore-test/var/backups/vps/current/db/mysql_appdb_*.sql.gz | mysql appdb
Na końcu sprawdzasz jeszcze jedną rzecz: czy konto używane do backupu może skasować kopie. Jeżeli klucz API zapisany na VPS-ie ma pełne prawa do bucketu, włamywacz po przejęciu serwera może usunąć produkcję i backup. Lepszy układ to osobny bucket, osobny klucz, minimalne uprawnienia, wersjonowanie albo mechanizm niezmienności tam, gdzie dany dostawca go obsługuje. Przy backupach ważniejsza od elegancji jest odporność na głupi, realny scenariusz: ktoś ma roota na VPS-ie.
FAQ: najczęstsze pytania o backup VPS
Czy snapshot VPS wystarczy jako jedyny backup?
Nie. Snapshot jest dobry do szybkiego cofnięcia maszyny, ale nie zastępuje backupu bazy danych, uploadów, plików .env i konfiguracji poza serwerem.
Jak często robić backup bazy danych na VPS?
Dla małej aplikacji minimum to raz dziennie. Dla sklepu, systemu rezerwacji albo aplikacji z częstymi zapisami lepszy jest backup co godzinę albo mechanizm z WAL/binlogami, żeby ograniczyć utratę danych.
Czy trzeba backupować Docker volumes?
Tak, ale z podziałem. Wolumeny z uploadami kopiuj plikowo. Wolumeny z bazą backupuj przez pg_dump, pg_basebackup, mysqldump albo narzędzie fizyczne, a nie przez zwykłe kopiowanie działającego katalogu danych.
Czy plik .env powinien trafić do backupu?
Tak, ale tylko do szyfrowanego backupu. Bez .env często nie odtworzysz połączenia z bazą, sesji, integracji płatności, SMTP i storage. Nieszyfrowana kopia .env w bucketcie to ryzyko przejęcia systemu.
Cloudflare R2, Backblaze B2 czy AWS S3 — co wybrać?
R2 jest mocnym wyborem, gdy chcesz prosty S3-compatible storage i brak klasycznych opłat za egress. B2 jest atrakcyjne przy tanim przechowywaniu większych archiwów. S3 wybierz, gdy już siedzisz w AWS albo potrzebujesz tamtejszych mechanizmów IAM, compliance, lifecycle i integracji.
Czy backup na tym samym VPS-ie ma sens?
Tylko jako etap tymczasowy przed wysyłką poza serwer. Kopia na tym samym dysku nie chroni przed awarią VPS-a, skasowaniem danych, ransomware ani blokadą konta u dostawcy.
Jak sprawdzić, czy backup naprawdę działa?
Odtwórz go na czystej maszynie testowej. Sam komunikat „backup completed” nie wystarcza. Test musi obejmować bazę, uploady, .env, konfigurację proxy i uruchomienie aplikacji.
Od czego zacząć, jeśli VPS nie ma żadnego backupu?
Najpierw zrób dump bazy i kopię uploadów do szyfrowanego repozytorium poza VPS-em. Potem dodaj .env, Docker Compose i konfigurację Nginx/Caddy/Traefik. Dopiero po tym dopracuj retencję, alerty, wersjonowanie i procedurę disaster recovery.

