Najczęściej trafiają do nas dwa rodzaje klientów. Pierwszy: macie jedną czy dwie ważne strony na hostingu współdzielonym i zrobiło się ciasno. Strona zwalnia w godzinach szczytu, limity są niejasne, a gdy coś się psuje, support odpisuje szablonem. Drugi: jesteście agencją interaktywną z dziesiątkami stron klientów rozrzuconych po różnych hostingach i VPS-ach, i nikt już nie wie na pewno, gdzie jest jaka wersja PHP ani kiedy ostatnio robiono kopię.
Problem w obu przypadkach wygląda podobnie. Jedna zainfekowana strona ciągnie za sobą sąsiadów. Aktualizacja wtyczki kładzie stronę główną w piątek wieczorem. Maile z formularza kontaktowego lądują w spamie. A kopia zapasowa niby jest, tylko nikt nigdy nie próbował z niej niczego odtworzyć.
Co robimy
Stawiamy platformę na serwerze dedykowanym (OVH lub Hetzner) albo na maszynie wirtualnej w Waszym Proxmoxie i doprowadzamy ją do stanu, w którym strony po prostu działają.
- Nginx + PHP-FPM. Każda strona ma osobnego użytkownika systemowego i własną pulę PHP-FPM. Strona nie widzi plików sąsiada, a ta „ciężka” nie zajmuje wszystkich workerów. Kilka wersji PHP działa obok siebie: stara strona na 7.4 nie blokuje nowych na 8.3.
- Cache. OPcache, FastCGI cache w Nginx dla anonimowych odwiedzających, Redis jako object cache tam, gdzie wtyczki go obsługują.
- Bazy danych. MariaDB z osobnym użytkownikiem dla każdej strony, bez dostępu z zewnątrz.
- TLS. Certyfikaty Let’s Encrypt wystawiane i odnawiane automatycznie, z monitoringiem daty ważności.
- Ochrona. Limit zapytań na
wp-login.phpixmlrpc.php(albo całkowita blokada xmlrpc, jeśli nie jest potrzebny), CrowdSec lub fail2ban na logach Nginx i SSH, w razie potrzeby WAF przed stronami. - Poczta. Strony wysyłają maile przez porządny SMTP z SPF, DKIM i DMARC, a nie przez gołe
mail()z niepodpisanego adresu. - Kopie i monitoring. Codzienne kopie plików i baz na osobny storage, sprawdzanie dostępności każdej strony i ważności certyfikatów, powiadomienia na Telegram lub e-mail.
Panel czy czysta konfiguracja
Są dwie drogi i żadna nie wygrywa we wszystkim.
Panel typu HestiaCP jest wygodny dla agencji. Ktoś z zespołu sam założy stronę, skrzynkę czy bazę dla nowego klienta, bez pisania do admina. Część naszych własnych stron też stoi na HestiaCP. Ale panel to kolejna rzecz do aktualizowania i pilnowania pod kątem podatności. Ma też własne pomysły na to, gdzie leżą konfiguracje, więc ręczne zmiany obok panelu potrafią zniknąć po aktualizacji.
Czysta konfiguracja przez Ansible sprawdza się, gdy stron jest niewiele albo są ważne i rzadko się zmieniają. Wszystko jest opisane w repozytorium: vhosty, pule PHP, użytkownicy, cron. Serwer da się odtworzyć od zera, a każdą zmianę widać w historii Gita. Za to nową stronę dodaje ktoś, kto umie uruchomić playbook.
Często robimy wariant mieszany: panel do codziennej pracy agencji, a system bazowy, zabezpieczenia, monitoring i kopie — przez Ansible, poza panelem.
Osobna sprawa to repozytoria. Nowsze wersje PHP na Debianie zwykle pochodzą z zewnętrznego repozytorium, któremu co jakiś czas wygasa klucz podpisu. Wtedy apt update po cichu przestaje przynosić poprawki bezpieczeństwa. Takie rzeczy łapiemy monitoringiem, a nie przypadkiem po pół roku.
Aktualizacje: psuje nie serwer, tylko wtyczki
Z praktyki: serwer pada rzadko. Strony psują się po aktualizacji wtyczki, motywu albo rdzenia CMS. Dlatego automatyczne aktualizacje bez sprawdzania to zły pomysł, a ręczne zawsze się odkłada.
Robimy to tak: strona jest kopiowana na staging, tam idą aktualizacje, potem automatyczny test — strona główna, kilka kluczowych adresów, koszyk lub formularz, przegląd logu pod kątem błędów PHP. Jeśli wszystko gra, te same aktualizacje trafiają na produkcję. Jeśli nie — produkcji nie ruszamy, a Wy dostajecie raport, co dokładnie się zepsuło.
wp core update --minor
wp plugin update --all --exclude=woocommerce
wp core verify-checksums
curl -fsS -o /dev/null -w '%{http_code}\n' https://staging.example/
Duże wydania, WooCommerce, płatne wtyczki z licencją aktualizujemy ręcznie i z uprzedzeniem. W Joomli zasada jest ta sama, inne są tylko narzędzia.
Kiedy to nie zadziała: jeśli strona była mocno przerabiana „na żywo” i żadna kopia nie zachowuje się jak oryginał, najpierw trzeba uporządkować sam kod. To osobna praca.
Kopie i migracja
Kopia, z której nikt nigdy nie odtwarzał, to nadzieja, a nie kopia. Dlatego co jakiś czas automatycznie stawiamy stronę z backupu w odizolowanym środowisku i sprawdzamy, czy się otwiera i czy baza jest cała.
Migrację z hostingu współdzielonego robimy bez przestoju: przenosimy pliki i bazę, testujemy stronę na nowym serwerze przez wpis w hosts, wcześniej obniżamy TTL w DNS, na koniec synchronizujemy ostatnie zmiany i przełączamy rekordy. Pocztę przenosimy osobno, razem z archiwum, jeśli była na tym samym hostingu.
Co dostajecie
- Serwer w pełni na Was: dostęp root i dostęp do panelu, jeśli jest.
- Odizolowane strony z własnymi użytkownikami, pulami PHP i bazami.
- Aktualizacje przez staging i raport po każdym cyklu.
- Ochronę logowania, xmlrpc i SSH oraz certyfikaty odnawiane automatycznie.
- Skonfigurowane SPF, DKIM i DMARC — maile ze stron docierają do adresatów.
- Kopie na osobnym storage’u z regularnym testem odtwarzania.
- Monitoring dostępności i powiadomienia, które trafiają także do Was.
- Dokumentację: co gdzie stoi, jak dodać stronę, jak odtworzyć się z kopii.
Jeśli macie jedną stronę, której ciasno na hostingu współdzielonym, albo agencję z dziesiątkami klientów i zoo serwerów — napiszcie, ile jest stron i gdzie teraz działają. Przyjrzymy się i zaproponujemy, jak zebrać to w jednym miejscu.