Strony firmowe, landing page i serwisy w WordPress oraz Next.js — projektowane pod konwersję i widoczność w Google.
Tworzenie stron WWWProjektowanie UX/UIStrony dla firmLanding pageRedesign strony
Sam plik SQL ani komunikat „backup ukończony” nie potwierdzają możliwości odtworzenia strony. Pokazujemy kompletną metodę: kopię bazy i plików, kontrolę zestawu oraz przywrócenie w osobnej instalacji z testem treści, mediów i adresów.
Kompletna kopia zapasowa typowego WordPressa obejmuje bazę danych i pliki z tego samego punktu odtworzenia. Żeby sprawdzić jej przydatność, trzeba uruchomić z niej osobną stronę, odczytać dane i przetestować potrzebne funkcje. W tym poradniku przechodzimy przez jedną metodę: WP-CLI, archiwum tar, sumy SHA-256 oraz przywracanie do drugiej instalacji. Nie nadpisujemy działającej strony.
| Składnik | Wersja lub zakres |
|---|---|
| WordPress / PHP | 7.1 / 8.3.33 |
| Serwery baz | Dwie odseparowane instancje MySQL 8.4.10; tabele testowe InnoDB |
| Klient SQL / WP-CLI | MariaDB client 11.8.6 / WP-CLI 2.12.0 |
| Motyw | Twenty Twenty-Five 1.5 |
| Warstwa testowa | Lokalny Docker, gateway Nginx, syntetyczny formularz i przechwycenie wp_mail |
| Twoja sytuacja | Od czego zacząć | Kiedy zadanie jest zakończone |
|---|---|---|
| Mam tylko panel hostingu lub WordPressa | Użyj już dostępnego mechanizmu kopii. Sprawdź poniższą ścieżkę panelową; nie musisz instalować Dockera, aby zlecić i odebrać próbę restore. | Odzyskana kopia działa na osobnym celu, a pliki i baza są dostępne także po utracie konta hostingu. |
| Mam SSH i WP-CLI; chcę zabezpieczyć istniejącą stronę | Przeczytaj granicę danych, następnie sekcję Backup istniejącej strony: eksport, szyfrowanie i odzyskanie. Ustal rzeczywiste ścieżki z operatorem. | Pobrany z niezależnego magazynu zestaw odszyfrowuje się, przechodzi kontrolę sum i test odtworzenia. |
| Chcę przećwiczyć metodę bez ryzyka dla swojej strony | Wykonaj numerowane etapy 1–7 w Dockerze. Używamy tylko dostarczonych danych syntetycznych. | Cel zawiera stan A, źródło zachowuje B, media, logowanie i formularz przechodzą odbiór. |
Ścieżkę interfejsu sprawdziliśmy 7.09.2026 w aktualnej instrukcji producenta UpdraftPlus. Nie wykonaliśmy własnego testu tej wtyczki ani Twojego panelu i nie pokazujemy pozorowanych screenów. To mapa wyboru dla właściciela strony; udokumentowany test wykonania niżej dotyczy osobnego laboratorium WP-CLI.
Wersje, warunki izolacji, wyniki odtworzenia oraz obu scenariuszy błędów. Pomiary pochodzą z własnych danych syntetycznych.
| Element | Gdzie znajduje się stan | Co tracisz, jeśli go zabraknie |
|---|---|---|
| Wpisy, strony, konta, ustawienia | Baza MySQL/MariaDB | Sam katalog WordPressa nie odtworzy tych danych. |
| Media | Zwykle wp-content/uploads oraz rekordy w bazie | Rekord załącznika może istnieć, a obraz zwracać 404. |
| Wtyczki i motywy | Pliki oraz ich ustawienia w bazie | Inny kod może nie rozumieć odtworzonego schematu lub konfiguracji. |
| Konfiguracja | wp-config.php, zmienne środowiskowe, reguły serwera | Sama paczka plików nie odtworzy zewnętrznych sekretów i konfiguracji hostingu. |
| Dane poza katalogiem strony | Np. magazyn obiektowy, osobna aplikacja, kolejka | Ta procedura nie obejmie ich automatycznie. |
Podział na bazę i pliki oraz traktowanie ich jako wspólnego zestawu opisuje dokumentacja kopii WordPress. Eksport z Narzędzia → Eksport jest eksportem wybranych treści, nie zamiennikiem pełnego zestawu odtworzeniowego. Archiwum z hasłami i bazą traktuj jak dane poufne: nie umieszczaj go w public_html, repozytorium ani publicznym linku.
Kopia A odtworzy stan A, nie późniejsze zmiany B. Określ RPO, czyli ile najnowszych danych możesz stracić, oraz RTO, czyli ile może trwać przywrócenie usługi. Dla strony z rzadkimi zmianami i dla sklepu przyjmującego zamówienia będą to inne wartości. Czas importu bazy jest tylko częścią RTO: dochodzą dostęp do kopii, przygotowanie serwera, konfiguracja, testy i wznowienie ruchu.
Docker Compose, konfiguracja, syntetyczne dane, instrukcja i osobny protokół wykonania bloków w evidence/results-manual.json. To środowisko ćwiczeniowe, nie archiwum strony klienta.
Rozpakuj paczkę do nowego katalogu. Wszystkie dalsze polecenia wykonuj z katalogu zawierającego compose.yaml, Dockerfile i run.mjs. Środowisko source jest źródłem, restore — celem. Mają oddzielne serwery baz i wolumeny. Port źródła to 127.0.0.1:18881, celu 127.0.0.1:18882; nie zmieniaj mapowania na 0.0.0.0. Publiczny katalog w kontenerze to /var/www/html, a prywatny — /var/www/private. Nazwa projektu Compose jest stała: webalpha-blog-lab-20260907. Samo skopiowanie katalogu nie tworzy nowego zestawu wolumenów tej nazwy.
Sieć laboratorium jest odseparowana; aplikacja ma blokadę zewnętrznych żądań HTTP i wyłączony WP-CRON. To bariery uzupełniające, nie gwarancja izolacji dowolnej wtyczki. Nie importuj tu bazy klientów i nie wprowadzaj produkcyjnych kluczy. Kopia na prywatnym serwerze musi mieć dodatkowo kontrolę dostępu na serwerze lub VPN — samo noindex nie chroni danych.
docker compose config --format=json
docker compose up -d --build
docker compose ps
docker compose exec -T --user www-data source test -f /var/www/html/wp-config.php
docker compose exec -T --user www-data restore test -f /var/www/html/wp-config.php
docker compose exec -T --user www-data source wp db query 'SELECT DATABASE(), @@hostname, @@server_uuid, VERSION();'
docker compose exec -T --user www-data restore wp db query 'SELECT DATABASE(), @@hostname, @@server_uuid, VERSION();'
docker inspect --format '{{.Config.Hostname}}' "$(docker compose ps -q source-db)"
docker inspect --format '{{.Config.Hostname}}' "$(docker compose ps -q restore-db)"
docker compose exec -T --user www-data source wp db query 'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE();' --skip-column-names
docker compose exec -T --user www-data restore wp db query 'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE();' --skip-column-namesW tej paczce połączenie z bazą działa bez TLS, wyłącznie wewnątrz prywatnej sieci jednej maszyny, bez opublikowanych portów baz i bez prawdziwych danych. To jawne ograniczenie laboratorium, nie test TLS produkcji ani instrukcja wyłączania weryfikacji certyfikatów na hostingu. Dla zewnętrznej bazy skonfiguruj TLS z właściwym CA i nazwą hosta zgodnie z dokumentacją dostawcy; nie kopiuj laboratoryjnej konfiguracji klienta SQL do produkcji.
Sprawdź w konfiguracji nazwę projektu, brak bind mountów z danymi hosta, osobne wolumeny i bazy oraz porty wyłącznie na 127.0.0.1. Wszystkie usługi mają działać, a obie bazy mieć stan healthy. Obie nazwy baz mają wynosić wordpress_lab, hostname odpowiadać właściwemu kontenerowi source-db/restore-db, a UUID serwerów różnić się. Ostatnie dwa zapytania muszą zwrócić 0. Jeśli wp-config.php jeszcze nie istnieje, sprawdź docker compose logs i ponów kontrolę. Nie przechodź dalej po błędzie połączenia — to nie dowód pustej bazy. Nie używaj wolumenów z wcześniejszymi danymi; poprzedni wynik trzeba najpierw zabezpieczyć i świadomie wybrać nowy cel.
docker compose exec -T --user www-data source sh -eu -c 'test ! -L /var/www/html/wp-config.php; test -d /var/www/private; test ! -L /var/www/private; test -z "$(find /var/www/private -mindepth 1 -maxdepth 1 -print -quit)"; test ! -e wp-content/plugins/wa-lab-fault; test ! -e wp-content/mu-plugins/wa-lab-safety.php'
docker compose exec -T --user www-data restore sh -eu -c 'test ! -L /var/www/html/wp-config.php; test -d /var/www/private; test ! -L /var/www/private; test -z "$(find /var/www/private -mindepth 1 -maxdepth 1 -print -quit)"; test ! -e wp-content/plugins/wa-lab-fault; test ! -e wp-content/mu-plugins/wa-lab-safety.php'docker compose exec -T --user www-data source sh -eu -c 'umask 077; mkdir -p wp-content/mu-plugins /var/www/private/backup-A; cp /opt/wa-lab/lab-safety.php wp-content/mu-plugins/wa-lab-safety.php'
docker compose exec -T --user www-data restore sh -eu -c 'umask 077; mkdir -p wp-content/mu-plugins /var/www/private/backup-A; cp /opt/wa-lab/lab-safety.php wp-content/mu-plugins/wa-lab-safety.php'
docker compose exec -T --user www-data source wp core install --url=http://127.0.0.1:18881 --title='WebAlpha synthetic laboratory' --admin_user=wa_lab_admin --admin_password=local-only-WA-lab-20260907 --admin_email=admin@example.invalid --skip-email
docker compose exec -T --user www-data source wp config set WP_DEBUG false --raw
docker compose exec -T --user www-data source wp config set WP_DEBUG_LOG /var/www/private/debug.log
docker compose exec -T --user www-data source wp config set WP_DEBUG_DISPLAY false --raw
docker compose cp fixtures/seed.php source:/var/www/private/seed.php
docker compose cp fixtures/snapshot.php source:/var/www/private/snapshot.php
docker compose cp fixtures/snapshot.php restore:/var/www/private/snapshot.php
docker compose exec -T --user www-data source wp eval-file /var/www/private/seed.php
docker compose exec -T --user www-data source wp rewrite structure '/%postname%/' --hard
docker compose exec -T --user www-data source wp eval-file /var/www/private/snapshot.phpHasło powyżej jest jawne i przeznaczone tylko do syntetycznej instalacji lokalnej. Nigdy nie używaj go na hostingu. Seed tworzy trzy wpisy, dwie strony, trzy media, menu i ustawienie wa_lab_setting ze stanem A oraz adresem strony. Zapisz wynik snapshotu jako punkt porównania. Instalacja może też zawierać domyślne treści WordPressa; testy porównują wskazane dane kontrolne, nie zakładają, że cała baza ma tylko trzy wpisy.
docker compose ps
docker compose exec -T --user www-data source wp core version
docker compose exec -T source php --version
docker compose exec -T --user www-data source wp cli version
docker compose exec -T --user www-data source wp db query 'SELECT DATABASE(), @@hostname, VERSION();'
docker compose exec -T --user www-data restore wp db query 'SELECT DATABASE(), @@hostname, VERSION();'Dwa różne porty WWW nie dowodzą rozdzielenia baz. Sprawdź konfigurację Compose oraz wynik identyfikacji serwera bazy dla obu usług. Nie wypisuj DB_PASSWORD. Jeśli cel łączy się ze źródłowym serwerem lub nie potrafisz ustalić zakresu, przerwij przed importem. Polecenia w tym materiale nie używają --allow-root: WP-CLI działa jako użytkownik aplikacji.
Po przygotowaniu danych kontrolnych nie zmieniaj źródła do zakończenia obu kopii. Zapisz datę UTC, wersję WP/PHP/bazy, motyw, listę wtyczek i snapshot A w prywatnej dokumentacji zestawu. Eksport wykonujemy poza katalogiem WWW. W przykładzie cała baza należy do jednej instalacji; na współdzielonej bazie najpierw trzeba ustalić tabele należące do serwisu.
docker compose exec -T --user www-data source sh -c 'umask 077; mkdir -p /var/www/private/backup-A'
docker compose exec -T --user www-data source sh -eu -c 'umask 077; { date -u; wp core version; php --version; wp cli version; wp plugin list --fields=name,status,version; wp theme list --fields=name,status,version; wp db query "SELECT DATABASE(), @@hostname, VERSION();"; wp eval-file /var/www/private/snapshot.php; } > /var/www/private/backup-A/manifest.txt'
docker compose exec -T --user www-data source wp db query 'SELECT DISTINCT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_TYPE="BASE TABLE";' --skip-column-names
docker compose exec -T --user www-data source sh -eu -c 'umask 077; wp db export /var/www/private/backup-A/database.sql --single-transaction --add-drop-table'
docker compose exec -T --user www-data source sh -c 'test -s /var/www/private/backup-A/database.sql'
docker compose exec -T --user www-data source sh -c 'umask 077; tar -czf /var/www/private/backup-A/files.tar.gz -C /var/www/html .'
docker compose exec -T --user www-data source sh -c 'cd /var/www/private/backup-A && sha256sum database.sql files.tar.gz'Polecenie wp db export korzysta z konfiguracji bazy danej instalacji. --add-drop-table zapisuje w SQL instrukcje usuwające istniejące tabele przed ich odtworzeniem, dlatego późniejszy import wykonujemy wyłącznie na zweryfikowanym celu. --single-transaction nie tworzy atomowej kopii całej strony: nie obejmuje plików i nie rozwiązuje problemu zmian schematu ani tabel nietransakcyjnych. W ćwiczeniu nie ma równoległych zapisów.
Zapytanie o silniki tabel ma zwrócić wyłącznie InnoDB dla tego zestawu testowego. Jeżeli wynik jest inny, nie przenoś założenia spójności transakcyjnej na całą bazę. Przy każdym błędzie eksportu, braku miejsca, odmowie dostępu lub ostrzeżeniu tar o zmianie pliku zatrzymaj procedurę. Nie ignoruj kodu wyjścia tylko dlatego, że plik powstał. Sumy SHA-256 wykrywają zmianę bajtów przy przenoszeniu, lecz nie dowodzą poprawności SQL ani kompletności logicznej backupu. Do tego potrzebny jest restore i test danych.
Teraz, wyłącznie w syntetycznym źródle, utwórz stan B: zmieniony tytuł i ustawienie oraz nowy wpis po backupie. Przywrócony cel ma zachować stan A, natomiast źródło nadal B. Dzięki temu sprawdzisz zarówno granicę kopii, jak i to, czy odtworzenie nie zapisało danych do niewłaściwej bazy.
docker compose exec -T --user www-data source wp eval '$ids = get_option("wa_lab_fixture"); wp_update_post(array("ID" => $ids["posts"][0], "post_title" => "CHANGED AFTER BACKUP B"));'
docker compose exec -T --user www-data source wp option update wa_lab_setting '{"state":"B","url":"http://127.0.0.1:18881/wa-strona-1/"}' --format=json
docker compose exec -T --user www-data source wp post create --post_title='ADDED AFTER BACKUP B' --post_status=publish --porcelainPrzenosimy oba pliki bez publicznego adresu WWW, przez Docker CLI. Potok poniżej wykonaj w Bash i nie kontynuuj, jeśli którakolwiek jego część zwróci błąd. Oblicz ponownie SHA-256 po przeniesieniu i porównaj z własnymi wartościami źródła, nie z sumami innego przebiegu w naszym protokole: daty i lokalna konfiguracja mogą zmienić bajty archiwum. Sprawdź, czy archiwum daje się przeczytać i zawiera m.in. wp-config.php, wp-content oraz uploads z oczekiwanymi mediami. Dodatkowe poświadczenia środowiskowe pozostają osobnym elementem konfiguracji.
set -o pipefail
docker compose exec -T --user www-data source tar -cf - -C /var/www/private/backup-A . | docker compose exec -T --user www-data restore tar -xf - -C /var/www/private/backup-Adocker compose exec -T --user www-data restore sh -c 'cd /var/www/private/backup-A && sha256sum database.sql files.tar.gz'
docker compose exec -T --user www-data restore tar -tzf /var/www/private/backup-A/files.tar.gz
docker compose exec -T --user www-data restore wp db query 'SELECT DATABASE(), @@hostname, @@server_uuid, VERSION();'
docker compose exec -T --user www-data restore wp db query 'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE();' --skip-column-namesNie importuj niesprawdzonego dumpa z nieznanego źródła. To wykonywalny SQL, nie bierny dokument. Kopię danych klientów trzeba szyfrować i przechowywać z ograniczonym dostępem oraz zaplanowaną retencją. Przeniesienie między dwoma kontenerami na tym samym komputerze służy testowi przywrócenia; nie jest kopią w innej domenie awarii. W rzeczywistym procesie potrzebujesz także kopii poza tym serwerem i testu jej odzyskania.
docker compose exec -T --user www-data restore sh -eu -c 'test ! -e /var/www/private/pristine-files; umask 077; mkdir /var/www/private/pristine-files; find /var/www/html -mindepth 1 -maxdepth 1 -exec mv -t /var/www/private/pristine-files {} +'
docker compose exec -T --user www-data restore tar -xzf /var/www/private/backup-A/files.tar.gz -C /var/www/html
docker compose exec -T --user www-data source wp db query 'SELECT DATABASE(), @@hostname, @@server_uuid, VERSION();'
docker compose exec -T --user www-data restore wp db query 'SELECT DATABASE(), @@hostname, @@server_uuid, VERSION();'
docker compose exec -T --user www-data restore wp db query 'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE();' --skip-column-namesPierwsze polecenie przenosi wyłącznie zawartość prywatnego celu restore do pristine-files zamiast ją kasować. Jeśli taki katalog już istnieje, polecenie ma się zatrzymać: nie ponawiaj w ciemno i nie nadpisuj poprzedniej próby. Dopiero pusty webroot wypełniamy archiwum. Zachowane pliki startowe pozwalają obejrzeć konfigurację sprzed odtworzenia; nie stanowią kopii bazy ani rollbacku działającej produkcji.
Przed importem porównaj ponownie UUID z zapisanym preflightem: źródło nadal musi wskazywać pierwotny serwer source-db, a cel swój pierwotny restore-db. Ostatnie zapytanie ma zwrócić 0. W razie innego wyniku nie wykonuj następnego polecenia. Dopiero po tej kontroli uruchom import na celu.
docker compose exec -T --user www-data restore wp db import /var/www/private/backup-A/database.sqlPo odtworzeniu plików ponownie kontrolujemy bazę, ponieważ archiwum zawiera wp-config.php. W laboratorium poświadczenia są dostarczane przez środowisko oddzielnej usługi restore; przy zwykłej instalacji trzeba przed importem świadomie ustawić DB_HOST, DB_NAME, DB_USER i DB_PASSWORD celu. wp db import nie tworzy nowej bazy i nie wybiera bezpiecznego celu za administratora.
Kopia zawiera adres źródła. Aby nie ładować mediów i nie kierować użytkownika z powrotem na pierwotną stronę, zmieniamy go na adres celu. Najpierw wykonujemy dry-run. Dla ćwiczenia jest to zmiana portu 18881 → 18882; nie zastępuj tego przypadkowym wyszukiwaniem samej nazwy domeny w pliku SQL.
docker compose exec -T --user www-data restore wp search-replace 'http://127.0.0.1:18881' 'http://127.0.0.1:18882' --all-tables-with-prefix --skip-columns=guid --precise --dry-run
docker compose exec -T --user www-data restore wp search-replace 'http://127.0.0.1:18881' 'http://127.0.0.1:18882' --all-tables-with-prefix --skip-columns=guid --precise
docker compose exec -T --user www-data restore wp option get home
docker compose exec -T --user www-data restore wp option get siteurl
docker compose exec -T --user www-data restore wp option update blog_public 0
docker compose exec -T --user www-data restore wp cache flush
docker compose exec -T --user www-data restore wp rewrite flush --hard
docker compose exec -T --user www-data restore wp eval-file /var/www/private/snapshot.phpNarzędzie WP-CLI search-replace obsługuje dane serializowane PHP, których długości mogą zostać uszkodzone przez zwykły SQL REPLACE lub edytor tekstu. --all-tables-with-prefix obejmuje również tabele dodatków z prefiksem tej instalacji; nie oznacza wszystkich zewnętrznych magazynów. GUID pozostawiamy bez zmiany. Przed uruchomieniem sprawdź też, czy WP_HOME lub WP_SITEURL nie są narzucone w konfiguracji i nie przesłaniają wartości bazy.
Po zmianie adresów powtórz dry-run. Pozostałości w pominiętej kolumnie guid nie są tym samym co aktywne linki do starej witryny. Przejrzyj pozostałe wskazane tabele zamiast wykonywać coraz szersze podmiany. Ustawienie blog_public=0 jest prośbą dotyczącą indeksowania, nie blokadą dostępu i nie zabezpieczeniem e-maili czy webhooków.
Porównaj wynik z zapisanym stanem A: tytułem, treścią wpisów, stronami, kontem testowym, menu, ustawieniem kontrolnym oraz plikami mediów. Dane dodane po backupie nie powinny pojawić się w kopii A. Jeżeli obraz jest wpisany w bazie, ale jego plik nie istnieje, kopia jest niekompletna mimo poprawnego importu SQL. Jeżeli zmiana URL uszkodzi ustawienie serializowane, wykryje to odczyt jego wartości, nie samo otwarcie strony głównej.
docker compose exec -T --user www-data restore wp eval-file /var/www/private/snapshot.php
docker compose exec -T --user www-data restore wp post list --post_type=post --fields=ID,post_title,post_status
docker compose exec -T --user www-data restore wp option get wa_lab_setting --format=json
docker compose exec -T --user www-data source wp option get wa_lab_setting --format=json
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' http://127.0.0.1:18882/wa-strona-1/Otwórz lokalnie /wp-login.php na porcie 18882 i zaloguj się kontem laboratoryjnym z etapu instalacji. Następnie otwórz /wa-strona-2/ i wyślij wiadomość testową. Polecenia wp option get wa_lab_form_result oraz wp option get wa_lab_last_mail --format=json wykonane na restore pokażą zapisany wynik i odbiorcę receiver@example.invalid. Wtyczka laboratoryjna przechwytuje wywołanie wp_mail lokalnie — nie jest to test rzeczywistego dostarczenia SMTP. Nie używaj danych ani adresów klientów.
| Kontrola | Oczekiwany rezultat | Co zrobić przy błędzie |
|---|---|---|
| Baza celu | Oddzielny serwer i prawidłowy zestaw tabel | Przerwij przed dalszymi zapisami; sprawdź konfigurację po rozpakowaniu. |
| Treści oraz media | Stan A i właściwe pliki, nie tylko rekordy attachment | Porównaj manifest, archiwum i ścieżki uploads; wybierz kompletny zestaw. |
| home, siteurl i ustawienie serializowane | Adres celu i poprawna struktura wartości | Wróć do świeżego importu A, popraw zakres podmiany, ponów test. |
| HTTP strony i mediów | Oczekiwana treść i typ odpowiedzi, bez redirectu do źródła | Sprawdź konfigurację URL, permalinki, reguły serwera i cache. |
| Dostęp administracyjny | Logowanie kontem testowym i możliwość odczytu danych | Sprawdź cookies, URL, stan konta i wymagane dodatki uwierzytelniania. |
| Funkcje biznesowe | Wynik testu formularza lub integracji w trybie testowym | Nie uznawaj samej strony głównej za odbiór formularza, SMTP lub płatności. |
| Próba | Wynik z 7 września 2026 |
|---|---|
| Transfer kopii | Sumy database.sql i files.tar.gz były identyczne w źródle i celu. |
| Treści, media i menu | Cel odtworzył stan A; wszystkie trzy kontrolne media miały zgodne sumy. |
| Dane po wykonaniu kopii | Wpis dodany w B nie trafił do A; źródło zachowało swój stan B. |
| Zmiana URL | Dry-run wykazał 7 podmian; ustawienie serializowane zachowało stan A i uzyskało URL celu. |
| Funkcjonalność | Logowanie, treść permalinku oraz lokalny formularz przeszły kontrolę. |
| Czas poleceń odtworzenia | 4,3 s dla miniaturowego zestawu, bez czasu budowy środowiska i pełnego odbioru; nie jest to RTO produkcji. |
Po udanym odtworzeniu w prywatnym restore wykonaj próbę negatywną: przenieś katalog uploads do zachowanego katalogu pomocniczego. Rekordy załączników pozostaną w bazie, ale plik obrazu powinien przestać być dostępny. To pokazuje, dlaczego kontrola samej bazy i strony głównej jest niewystarczająca. Nie wykonuj tej próby na źródle ani na hostingu; dotyczy wyłącznie syntetycznych mediów ćwiczenia.
docker compose exec -T --user www-data restore sh -eu -c 'test ! -e /var/www/private/uploads-held; mv wp-content/uploads /var/www/private/uploads-held'
docker compose exec -T --user www-data restore wp eval '$ids = get_option("wa_lab_fixture"); echo wp_get_attachment_url($ids["media"][0]);'Otwórz zwrócony adres lokalnego obrazu lub sprawdź go przez curl — bez dodawania -L, które mogłoby ukryć przekierowanie do źródła. Oczekiwany status to 404. Jeżeli dostajesz obraz z cache lub innego magazynu, sprawdź skąd pochodzi; nie uznawaj tego za test lokalnych uploads. Następnie odtwórz wyłącznie ten podkatalog z zestawu A.
docker compose exec -T --user www-data restore tar -xzf /var/www/private/backup-A/files.tar.gz -C /var/www/html ./wp-content/uploads
docker compose exec -T --user www-data restore wp eval-file /var/www/private/snapshot.phpPonów ten sam adres obrazu: wymagamy teraz HTTP 200 oraz sum SHA-256 zgodnych ze snapshotem A dla wszystkich trzech mediów. Katalog uploads-held zostaje do inspekcji i nie jest automatycznie usuwany. Po tym teście powtórz kontrolę formularza oraz logowania i zapisz wynik odbioru.
Jeżeli celem przywrócenia jest naprawa awarii, przejdź do instrukcji debugowania WordPress i diagnozy błędu krytycznego. Przy podejrzeniu włamania zabezpiecz dowody i ustal czysty punkt odbudowy; sam restore może przywrócić tę samą infekcję. Szerszy zakres utrzymania opisujemy w poradniku bezpieczeństwa WordPress.
Kod, 37 kontroli natywnych oraz osobny protokół rzeczywistego WordPressa: 23 kontrole i 4 kontrole przywrócenia stanu. Bez danych strony klienta i haseł.
W dodatku evidence/wordpress-results.json zawiera 23 zaliczone kontrole nowego eksportu i rzeczywistej funkcji wtyczki oraz 4 kontrole przywrócenia stanu. Test funkcji przez HTTP odbył się na dotychczasowym izolowanym restore, nie na dodatkowym prywatnym katalogu odzyskiwania. Aby powtórzyć ten przebieg, najpierw ukończ bazowe laboratorium, a następnie z katalogu dodatku wykonaj polecenie niżej. Nie powtarzaj instalacji ani seedowania na zachowanych danych. Runner tworzy nowe artefakty i wymaga kilkuset MB wolnego miejsca na każdą próbę; nie usuwa starych wolumenów.
WA_WORDPRESS_LAB='/pelna/sciezka/wordpress-lab-2026-09-07' \
node test-wordpress.mjs ./wordpress-results-new.jsonTa ścieżka wymaga Unix, SSH, WP-CLI, tar oraz sha256sum lub shasum na serwerze; na swoim komputerze potrzebujesz Node.js 20+, GnuPG, tar i shasum. Dotyczy standardowego pojedynczego WordPressa, bazy InnoDB i fizycznego katalogu bez symlinków. Najpierw ustal DocumentRoot oraz wszystkie aliasy WWW; prywatny katalog nie może być dostępny przez żadną domenę. Ustal wszystkich zapisujących: użytkowników, CRON, webhooki, importy i administratorów. Flaga --writes-paused nie zatrzymuje ich za Ciebie — wpisujesz ją dopiero po faktycznym zapewnieniu spójności kopii. Przejrzyj export-backup.sh z pobranego dodatku, prześlij go przez SFTP do prywatnego katalogu serwera i w sesji SSH przejdź do tego katalogu. Dopiero tam wykonaj poniższy blok.
WA_WP_ROOT='/rzeczywista/sciezka/wordpress'
WA_BACKUP_PARENT='/rzeczywisty/prywatny/katalog'
bash export-backup.sh "$WA_WP_ROOT" "$WA_BACKUP_PARENT" --writes-pausedSkrypt najpierw sprawdza instalację, silniki tabel i wyjście poza katalog WordPressa, potem tworzy nowy katalog wa-backup.*. Zapisuje database.sql, files.tar.gz, manifest.txt oraz SHA256SUMS. Nie kasuje wcześniejszych zestawów ani nie wykonuje jawnych operacji modyfikowania bazy; część poleceń WP-CLI ładuje jednak kod WordPressa i dodatków, który może mieć własne skutki uboczne. Uwzględnij to przy zatrzymywaniu zapisów. Przy błędzie eksportu, uprawnień, tar lub miejsca skrypt zatrzymuje się; niepełny wynik nie nadaje się do odzyskiwania. Nie omijaj odmowy dla symlinków i nietypowej instalacji — najpierw zinwentaryzuj jej rzeczywiste magazyny. Zapisz też wymagane zmienne środowiskowe i konfigurację hostingu poza publicznym raportem.
Na swoim komputerze utwórz katalog z uprawnieniami 0700 poza folderem strony i poza automatycznie udostępnianą chmurą. Przez SFTP pobierz dokładnie cztery pliki z zakończonego zestawu do tego katalogu. Potwierdź klucz hosta z operatorem innym kanałem; nie wyłączaj kontroli znanego hosta i nie używaj zwykłego FTP. SFTP chroni transport, ale pobrane SQL i konfiguracja nadal są jawnymi plikami na dysku. Po pobraniu sprawdź sumy i dopiero utwórz archiwum szyfrowane.
set -euo pipefail
umask 077
WA_SET='/pelna/prywatna/sciezka/pobranego-zestawu'
(cd "$WA_SET" && shasum -a 256 -c SHA256SUMS)
WA_PACK=$(mktemp -d)
tar -cf "$WA_PACK/backup.tar" -C "$WA_SET" database.sql files.tar.gz manifest.txt SHA256SUMS
WA_VAULT=$(mktemp -d)
WA_GPG_HOME=$(mktemp -d)
node backup-vault.mjs seal "$WA_PACK/backup.tar" "$WA_VAULT" "$WA_GPG_HOME"
shasum -a 256 "$WA_VAULT/backup.tar.gpg"Narzędzie z paczki uruchamia GnuPG z szyfrowaniem symetrycznym AES256; nie implementuje własnej kryptografii. Hasło podaj w zaufanym oknie GnuPG/pinentry i zapisz w niezależnym menedżerze haseł. Nie wpisuj go jako argumentu, nie wklejaj na czat ani do pliku wysyłanego razem z kopią. Interaktywnego okna pinentry nie testowaliśmy: test automatyczny używał losowego hasła w prywatnym pliku. Bez poprawnego hasła szyfrowanej kopii nie da się odzyskać.
set -euo pipefail
WA_RETURNED='/pelna/prywatna/sciezka/pobranej/backup.tar.gpg'
WA_OPEN=$(mktemp -d)
node backup-vault.mjs open "$WA_RETURNED" "$WA_OPEN" "$WA_GPG_HOME"
tar -tf "$WA_OPEN/backup.tar"Kontynuuj tylko po kodzie wyjścia 0 i pełnym sukcesie odszyfrowania. Na liście własnego archiwum wymagaj dokładnie database.sql, files.tar.gz, manifest.txt i SHA256SUMS — bez ścieżek absolutnych oraz ../. Nie rozpakowuj niesprawdzonego archiwum z obcego źródła. Szyfrowanie symetryczne nie jest niezależnym podpisem autora. Przy błędzie GPG narzędzie nie udostępnia końcowego backup.tar; częściowy plik pozostaje tylko w prywatnym .pending-* do inspekcji. Nie rozpakowuj go i nie dodawaj opcji ignorowania błędów integralności.
set -euo pipefail
WA_RECOVERED=$(mktemp -d)
tar -xf "$WA_OPEN/backup.tar" -C "$WA_RECOVERED"
(cd "$WA_RECOVERED" && shasum -a 256 -c SHA256SUMS)Na hostingu z SSH odpowiednikiem kontenerowego polecenia jest wp --path=/rzeczywisty/katalog/wordpress wykonywane jako właściciel aplikacji. Nie kopiuj przykładowej ścieżki bez sprawdzenia. Przed zmianą określ wszystkie źródła danych, prawa dostępu, zewnętrzne sekrety, wersje i sposób zatrzymania zapisów. Cel musi mieć własną bazę, kontrolę dostępu i skutecznie zablokowane wysyłki oraz integracje przed pierwszym załadowaniem WordPressa. W przypadku hostingu bez takich możliwości użyj jego udokumentowanej metody odtwarzania i poproś o osobny cel testowy.
WA_RESTORE_ROOT='/rzeczywista/sciezka/odseparowanego-celu'
WA_RECOVERY_SET='/rzeczywisty/prywatny/katalog/odzyskanego-zestawu'
wp --path="$WA_RESTORE_ROOT" db query 'SELECT DATABASE(), @@hostname, VERSION();'
wp --path="$WA_RESTORE_ROOT" db query 'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE();' --skip-column-namesPierwszy wynik ma dokładnie odpowiadać zapisanej bazie celu, a nie bazie źródła. Ostatni wynik musi wynosić 0. Na hostingu współdzielonym dwa serwisy mogą korzystać z jednego serwera bazy, ale muszą mieć różne właściwe bazy i odseparowane uprawnienia; sama inna ścieżka WWW niczego nie dowodzi. Brak połączenia jest blokadą, nie wynikiem 0. Dopiero po tej kontroli importuj zatwierdzony SQL.
wp --path="$WA_RESTORE_ROOT" db import "$WA_RECOVERY_SET/database.sql"WA_OLD_URL='https://example.com'
WA_NEW_URL='https://kopia.example.com'
wp --path="$WA_RESTORE_ROOT" search-replace "$WA_OLD_URL" "$WA_NEW_URL" --all-tables-with-prefix --skip-columns=guid --precise --dry-runPo obejrzeniu raportu wykonaj to samo polecenie bez --dry-run, następnie wp --path=... cache flush i rewrite flush --hard, jeśli konfiguracja Apache dopuszcza zapis reguł. To nadal ten sam mechanizm serializacji z etapu 5, a nie zwykły REPLACE w SQL. Ustal wszystkie dotknięte magazyny i własne tabele dodatków; nie zakładaj, że jedna podmiana obejmie zewnętrzne dane. Na Nginx reguły permalinków wymagają właściwej konfiguracji serwera. Ponów test treści, mediów, konta, menu i testowego formularza z etapu 6 oraz sprawdź brak połączeń do źródła.
Zapisz osobno czas pobrania z magazynu, odszyfrowania, importu oraz odbioru funkcji. Sprawdź, czy administrator odzyskał kopię bez dostępu do pierwotnego hostingu. Po pracy zaplanuj retencję jawnych plików, prywatnych .partial oraz hasła; nie usuwaj jedynego poprawnego zestawu przed potwierdzonym restore. Zwykłe usunięcie pliku na SSD lub w synchronizowanym katalogu nie jest dowodem bezpiecznego wymazania wszystkich kopii.
Nie cofaj działającego sklepu przez bezrefleksyjny import starej bazy. Najpierw porównaj dane przyjęte od czasu A: zamówienia, płatności, konta, formularze, aktualizacje stanów i zadania integracji. Odtworzenie produkcji wymaga planu zachowania lub uzgodnienia tych zmian oraz okna operacyjnego. Ten poradnik pokazuje odtworzenie kopii na izolowanym celu, nie automatyczne przełączenie ruchu produkcyjnego.
Po udanym teście zapisz wynik, czas poszczególnych etapów i osobę odpowiedzialną. Powtarzaj próbę po istotnej zmianie architektury lub metody kopii. Częstotliwość i retencję dobierz do ryzyka oraz danych, a nie sztywnej zasady dla każdej witryny. Zobacz zakres opieki nad stroną WordPress albo ustal z nami opiekę obejmującą weryfikację kopii i odtwarzania.
Opisz rozmiar strony, hosting, sposób wykonywania kopii i krytyczne funkcje. Ustalimy zakres weryfikacji, odseparowanego testu przywracania oraz dalszej opieki. Nie wysyłaj haseł ani archiwum strony przez formularz.
Sprawdź opiekę nad WordPressStrony firmowe, landing page i serwisy w WordPress oraz Next.js — projektowane pod konwersję i widoczność w Google.
Tworzenie stron WWWProjektowanie UX/UIStrony dla firmLanding pageRedesign strony
Sklepy na PrestaShop i WooCommerce — wdrożenia, migracje i dedykowane moduły pisane przez zespół senior developerów.
Tworzenie sklepówNowy sklep PrestaShopMigracja na PrestaShopModuły PrestaShopIntegracja z hurtowniami
Pozycjonowanie, SEO techniczne i optymalizacja konwersji — widoczność, kliknięcia i zarejestrowane konwersje porównywane z baseline'em.
SEO dla firmLokalne SEOContent SEOAudyt SEOSEO techniczne
Utrzymanie, aktualizacje i stały rozwój — bierzemy odpowiedzialność za obszar techniczny również po starcie projektu.
Opieka nad stronąAktualizacje i serwerSupport w pakietach godzinRozwój stronyWdrożenia niestandardowe
Bezpłatna konsultacja
Opisz, czego potrzebujesz — zaproponujemy zakres, technologię i realny harmonogram. Bez zobowiązań.
Następny krok
Krótka rozmowa albo wiadomość — wrócimy z konkretną propozycją zakresu.
Formularz kontaktowyOpisz, czego potrzebujesz — strony, sklepu, integracji czy wsparcia technicznego. Odpowiemy z konkretnymi propozycjami i orientacyjną wyceną, zwykle w ciągu 24–48 godzin roboczych.
ul. Henryka Pachońskiego 7a
31-223 Kraków
Biuro czynne: pon.–pt., 9:00–17:00
Webalpha
NIP: 6562340974
REGON: 385895790