Przejdź do treści
Serwery i hosting · · ~10 min czytania

WordPress na Nginx + PHP-FPM + MariaDB + Certbot (Debian 13)

Praktyczna ścieżka od świeżego hosta do WordPressa po HTTPS: warunki startowe, polecenia, testy oraz droga wycofania zmian.

Autor: Zespół LinuxLab

To jest minimalna, ręczna ścieżka dla nowego hosta z Debianem 13 i jednej instalacji WordPressa. Kończy się działającą stroną po HTTPS. Nie zastępuje hardeningu, monitoringu, kopii zapasowych ani procedury aktualizacji; przed produkcją trzeba je przygotować i przetestować osobno.

Każdy krok wykonujemy na hoście WordPressa jako root, chyba że opis wyraźnie mówi o przeglądarce lub konsoli MariaDB. Nazwy example.com, wordpress i wp_user są przykładami; przed skopiowaniem poleceń zastępujemy je własnymi, spójnymi wartościami.

Spis treści

  1. Czy ten wariant jest właściwy i co powstanie?
  2. Co przygotowujemy przed zmianą?
  3. Krok 1. Instalacja usług
  4. Jak działa połączenie Nginx z PHP-FPM?
  5. Krok 2. Baza i konto aplikacji
  6. Krok 3. Pliki WordPressa i sekrety
  7. Krok 4. Konfiguracja domeny w Nginx
  8. Krok 5. Certyfikat HTTPS
  9. Krok 6. Finalizacja w WordPressie
  10. Jak potwierdzamy sukces?
  11. Co sprawdzamy przed produkcją?
  12. Jak wycofujemy zmianę?

Czy ten wariant jest właściwy i co powstanie?

Ten wariant pasuje do pojedynczej, klasycznej instalacji WordPressa na nowym hoście. Nie opisuje klastra, wysokiej dostępności, zewnętrznej bazy danych ani istniejącego serwera Nginx z innymi stronami. Jeżeli host już obsługuje ruch produkcyjny, najpierw porównujemy jego obecną konfigurację z tą instrukcją i przygotowujemy osobny plan zmiany.

Budujemy stos LEMP (Linux, Nginx, MariaDB, PHP). Żądanie przebiega jako przeglądarka → Nginx → PHP-FPM → WordPress → MariaDB. Nginx odbiera HTTP i HTTPS, sam zwraca pliki statyczne, a żądania do plików PHP przekazuje do PHP-FPM (FastCGI Process Manager). PHP-FPM uruchamia kod WordPressa. MariaDB przechowuje treść, ustawienia i konta aplikacji. Certbot uzyskuje oraz instaluje certyfikat TLS (Transport Layer Security) od Let's Encrypt.

Po przejściu wszystkich kroków domena example.com będzie kierowała do WordPressa po HTTPS, a HTTP będzie przekierowywany na HTTPS. To jest wynik techniczny wdrożenia, a nie potwierdzenie gotowości całego serwisu do produkcji.

Co przygotowujemy przed zmianą?

Na początku ustalamy nazwę domeny, ścieżkę do strony, nazwę bazy i nazwę konta aplikacji. W przykładzie są to odpowiednio example.com, /var/www/example.com, wordpress i wp_user. Tych nazw używamy konsekwentnie w konfiguracji Nginx, MariaDB oraz WordPressa.

  • Host ma świeży Debian 13, dostęp administracyjny i działającą konsolę lub drugą sesję SSH na wypadek błędu konfiguracji.
  • Publiczny rekord DNS (Domain Name System) typu A i, jeżeli istnieje, AAAA wskazuje ten host. Dla walidacji HTTP-01 port 80 musi być osiągalny z Internetu, a do działania strony po HTTPS również port 443.
  • Katalog /var/www/example.com jest pusty. Nie kopiujemy poniższych plików na istniejącą stronę, ponieważ nadpisanie kodu lub konfiguracji może przerwać usługę.
  • Mamy unikalne hasło dla konta MariaDB aplikacji oraz miejsce w menedżerze haseł na to hasło i klucze WordPressa. Nie wpisujemy ich do historii powłoki, repozytorium ani dokumentacji.

Salts WordPressa to losowe klucze zapisane w wp-config.php, używane między innymi do ochrony sesji i danych uwierzytelniających. Nie są hasłem bazy danych, ale także są sekretem. Wygenerujemy je osobno i zachowamy wyłącznie w pliku konfiguracji na hoście.

Krok 1. Jak instalujemy i sprawdzamy usługi?

Logujemy się na host jako root albo najpierw przechodzimy do powłoki roota przez sudo -i. Najpierw aktualizujemy indeks pakietów i oglądamy symulację aktualizacji. Polecenie z -s niczego nie zmienia. Dopiero instalacja pakietów modyfikuje host.

id -u
apt update
apt-get -s upgrade

apt install -y \
  curl nginx mariadb-server \
  php8.4-fpm php8.4-mysql php8.4-curl php8.4-gd \
  php8.4-mbstring php8.4-xml php8.4-zip php8.4-intl

systemctl enable --now nginx php8.4-fpm mariadb

Pierwsze polecenie powinno wypisać 0. Jeżeli symulacja pokazuje niespodziewaną zmianę, zatrzymujemy się przed instalacją i sprawdzamy przyczynę. Debian 13 dostarcza pakiet php8.4-fpm, a wymagania WordPressa obejmują PHP, MariaDB lub MySQL oraz HTTPS.

Po instalacji sprawdzamy stan faktyczny. Wszystkie trzy usługi powinny wypisać active, a ostatnie polecenie powinno zwrócić nagłówek HTTP domyślnej strony Nginx.

systemctl is-active nginx php8.4-fpm mariadb
test -S /run/php/php8.4-fpm.sock && echo "Socket PHP-FPM istnieje"
curl -fsSI http://127.0.0.1/

Jeżeli usługa nie jest aktywna, nie przechodzimy do WordPressa. Najpierw odczytujemy jej log z bieżącego uruchomienia systemu, na przykład journalctl -u php8.4-fpm -b --no-pager.

Jak Nginx przekazuje żądanie PHP do PHP-FPM?

PHP-FPM (FastCGI Process Manager) jest menedżerem procesów PHP. Nie wystawia strony WWW bezpośrednio do Internetu. Nginx odbiera żądanie do index.php, przekazuje je przez lokalne gniazdo /run/php/php8.4-fpm.sock, a PHP-FPM wykonuje kod WordPressa i zwraca odpowiedź do Nginx. Dzięki temu w konfiguracji strony wskazujemy właśnie to gniazdo, a nie port HTTP PHP-FPM.

W dalszym kroku Nginx dostanie regułę fastcgi_pass, która wskazuje ten socket. Gdy ścieżka socketu lub wersja PHP na hoście jest inna, nie zgadujemy jej w konfiguracji; najpierw sprawdzamy aktywną usługę i jej pliki.

Krok 2. Jak tworzymy bazę i osobne konto aplikacji?

Najpierw uruchamiamy interaktywną kontrolę domyślnych ustawień MariaDB. Czytamy każde pytanie. W pakietach Debiana konto MariaDB root zwykle korzysta z lokalnego uwierzytelniania unix_socket, więc nie zmieniamy go na hasło tylko dlatego, że narzędzie o to pyta.

mariadb-secure-installation

Następnie tworzymy osobną bazę i konto wyłącznie dla WordPressa. W bloku SQL (Structured Query Language) zastępujemy TU_WSTAW_UNIKALNE_HASLO_BAZY rzeczywistym, unikalnym hasłem. Apostrofy otaczające wartość zostawiamy; jeśli samo hasło zawiera pojedynczy apostrof, w SQL zapisujemy go jako dwa kolejne apostrofy. To konto może łączyć się tylko lokalnie. Konto bazy wp_user nie jest kontem administratora WordPressa, które utworzymy później w przeglądarce.

mariadb

CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'TU_WSTAW_UNIKALNE_HASLO_BAZY';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Polecenie zaczyna lokalną konsolę MariaDB; pozostałe linie wykonujemy już w tej konsoli. Po wyjściu sprawdzamy połączenie dokładnie jako konto aplikacji. Program poprosi o hasło poza historią powłoki. Wynik z wartością 1 oznacza, że konto ma dostęp do właściwej bazy.

mariadb -u wp_user -p wordpress -e 'SELECT 1;'

Krok 3. Jak instalujemy pliki WordPressa i chronimy sekrety?

Najpierw tworzymy katalog strony i upewniamy się, że jest pusty. Drugie polecenie nie powinno nic wypisać. Jeżeli wypisze plik lub katalog, zatrzymujemy się: ścieżka może już zawierać inną instalację.

install -d -o root -g root -m 0755 /var/www/example.com
find /var/www/example.com -mindepth 1 -maxdepth 1 -print -quit

Na tym samym hoście pobieramy bieżące archiwum WordPressa i kopiujemy jego zawartość do pustego katalogu strony. Poniższy wariant pobiera aktualne wydanie, dlatego przed wdrożeniem produkcyjnym zapisujemy używaną wersję w ewidencji zmiany.

cd /tmp
curl -fsSLO https://wordpress.org/latest.tar.gz
tar xzf latest.tar.gz
cp -a /tmp/wordpress/. /var/www/example.com/

chown -R root:root /var/www/example.com
find /var/www/example.com -type d -exec chmod 0755 {} +
find /var/www/example.com -type f -exec chmod 0644 {} +
install -d -o www-data -g www-data -m 0755 \
  /var/www/example.com/wp-content/uploads

Cały kod pozostaje własnością root. Użytkownik procesu WWW www-data może zapisywać wyłącznie katalog uploads. Jeżeli konkretna wtyczka potrzebuje innego katalogu zapisywalnego, dodajemy wyłącznie ten katalog po sprawdzeniu jej wymagania. Aktualizacji rdzenia i wtyczek nie wykonujemy przez użytkownika PHP-FPM.

Teraz tworzymy wp-config.php. Plik powinien być czytelny dla grupy www-data, ponieważ PHP-FPM musi odczytać dane bazy, ale nie powinien być zapisywalny przez proces WWW.

cd /var/www/example.com
install -o root -g www-data -m 0640 wp-config-sample.php wp-config.php
editor /var/www/example.com/wp-config.php
stat -c '%U:%G %a %n' /var/www/example.com/wp-config.php

W edytorze ustawiamy DB_NAME na wordpress, DB_USER na wp_user, DB_PASSWORD na hasło utworzone w poprzednim kroku oraz DB_HOST na localhost. Zastępujemy też wszystkie definicje kluczy i salts nowymi wartościami z generatora WordPressa. Nie publikujemy ani nie commitujemy zawartości tego pliku. Ostatnie polecenie powinno wypisać root:www-data 640 /var/www/example.com/wp-config.php.

Krok 4. Jak łączymy domenę, Nginx i PHP-FPM?

Tworzymy serwer wirtualny Nginx w pliku /etc/nginx/sites-available/example.com. Wartość server_name i ścieżka root muszą odpowiadać wartościom przygotowanym wcześniej. Jeżeli ma działać także www.example.com, dodajemy go dopiero po skonfigurowaniu jego DNS i wydaniu certyfikatu dla obu nazw.

editor /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com;
    root /var/www/example.com;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
    }
}

Reguła try_files najpierw szuka rzeczywistego pliku lub katalogu, a gdy go nie ma, przekazuje adres do index.php. Dzięki temu WordPress obsługuje swoje przyjazne adresy. Blok PHP przekazuje wyłącznie żądania PHP do lokalnego PHP-FPM.

Aktywujemy plik, sprawdzamy składnię i dopiero po udanym teście przeładowujemy Nginx. Test z nagłówkiem Host pozwala sprawdzić nowy vhost jeszcze przed publicznym DNS.

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
curl -fsSI -H 'Host: example.com' http://127.0.0.1/

Jeżeli nginx -t nie zakończy się powodzeniem, nie wykonujemy systemctl reload nginx. Poprawiamy wskazany plik albo przywracamy poprzednią konfigurację, zamiast próbować restartu na ślepo.

Krok 5. Jak wystawiamy certyfikat HTTPS?

Certbot z wtyczką Nginx użyje walidacji HTTP-01. Let's Encrypt pobiera z publicznego adresu domeny krótki token umieszczony tymczasowo przez Certbot. Udana odpowiedź dowodzi, że osoba uruchamiająca Certbot kontroluje konfigurację tej domeny. Przed tym krokiem sprawdzamy z zewnętrznej sieci, że DNS wskazuje właściwy host, a port 80 dociera do Nginx.

Przed uruchomieniem Certbota zachowujemy kopię działającej konfiguracji HTTP. Jest to droga powrotu, ponieważ opcja --redirect zmieni plik serwera Nginx tak, aby przekierowywał ruch HTTP na HTTPS.

cp -a /etc/nginx/sites-available/example.com \
  /root/example.com.nginx-before-certbot

apt install -y certbot python3-certbot-nginx
certbot --nginx --redirect -d example.com

Gdy oba adresy, example.com i www.example.com, poprawnie wskazują host, zmieniamy linię konfiguracji na server_name example.com www.example.com;, wykonujemy ponownie nginx -t i przeładowujemy Nginx. Dopiero potem podajemy obie nazwy w jednej komendzie. Nie zamawiamy certyfikatu dla nazwy, której DNS lub firewall nie jest gotowy.

# Wariant alternatywny: zamiast jednonazwowego polecenia powyżej
certbot --nginx --redirect -d example.com -d www.example.com

Po udanym wydaniu certyfikatu, niezależnie od wybranego wariantu, wykonujemy testy:

certbot certificates
certbot renew --dry-run

certbot certificates powinien pokazać wydany certyfikat, a certbot renew --dry-run sprawdza ścieżkę odnowienia bez zapisywania nowego certyfikatu. Osobno potwierdzamy, że lokalny pakiet ma skonfigurowane okresowe uruchamianie odnowienia; zależnie od dystrybucji może to być timer systemd lub zadanie cron.

Krok 6. Jak kończymy instalację w WordPressie?

Otwieramy https://example.com w przeglądarce i kończymy formularz instalacyjny WordPressa. Tworzymy w nim tytuł strony oraz konto administratora WordPressa. To konto służy do administracji aplikacją i jest całkowicie niezależne od konta MariaDB wp_user. Używamy unikalnego hasła, zapisujemy je w menedżerze haseł i nie wykorzystujemy ponownie hasła bazy danych.

Po zapisaniu formularza logujemy się do panelu administracyjnego, otwieramy stronę główną w osobnej karcie i sprawdzamy, czy nie występują błędy PHP ani ostrzeżenia o połączeniu z bazą.

Jak potwierdzamy, że wdrożenie działa?

Po finalizacji wykonujemy poniższe polecenia na hoście jako root. Są to wyłącznie odczyty stanu i test odnowienia; nie zmieniają treści WordPressa ani konfiguracji Nginx.

nginx -t
systemctl is-active nginx php8.4-fpm mariadb
curl -fsSI http://example.com/
curl -fsSI https://example.com/
certbot renew --dry-run

Pierwszy adres powinien zwrócić przekierowanie HTTP na HTTPS. Drugi powinien zwrócić prawidłową odpowiedź HTTPS; po ukończeniu instalacji zwykle będzie to odpowiedź 2xx, choć własna konfiguracja WordPressa może dodać przekierowanie 3xx. Sam kod HTTP nie zastępuje testu aplikacji: sprawdzamy też logowanie administratora, odczyt strony oraz przesłanie testowego pliku do biblioteki mediów.

Gdy wynik nie jest zgodny z oczekiwaniem, zaczynamy od logów odpowiedniej warstwy zamiast losowo zmieniać konfigurację:

journalctl -u nginx -u php8.4-fpm -u mariadb -b --no-pager

Co sprawdzamy przed dopuszczeniem strony do produkcji?

Minimalna instalacja działa, ale przed obsłużeniem rzeczywistych użytkowników potwierdzamy co najmniej następujące kwestie:

  • Istnieje przetestowana kopia bazy danych oraz plików strony, w szczególności wp-content/uploads i wp-config.php. Sama instalacja pakietów nie tworzy backupu.
  • Jest właściciel usługi, monitoring dostępności, monitoring odnowienia certyfikatu i uzgodnione okno aktualizacji.
  • Hasło bazy oraz salts nie trafiły do historii powłoki, plików Terraform/Ansible bez szyfrowania, repozytorium ani logów wdrożenia.
  • Uprawnienia pliku konfiguracji nadal odpowiadają oczekiwaniu: stat -c '%U:%G %a %n' /var/www/example.com/wp-config.php powinno pokazać root:www-data 640.
  • Znany jest proces aktualizacji WordPressa i wtyczek. W tym układzie nie nadajemy www-data prawa zapisu do całego kodu tylko po to, aby aktualizować go z panelu WWW.

Nie traktujemy tej listy jako pełnego hardeningu. Zakres polityki aktualizacji, WAF (Web Application Firewall), limitów PHP-FPM, konfiguracji cache, kopii i odtwarzania zależy od aplikacji oraz wymagań organizacji.

Jak bezpiecznie wycofujemy zmianę?

Zachowujemy otwartą sesję administracyjną lub konsolę dostawcy do czasu zakończenia testów. Jeżeli błąd wystąpił w konfiguracji Nginx, najpierw uruchamiamy nginx -t. Dopóki test nie przejdzie, nie przeładowujemy usługi.

Kopia utworzona przed Certbotem pozwala wycofać jego zmiany w pliku vhosta i wrócić do działającego HTTP. Wykonujemy to tylko wtedy, gdy kopia dotyczy właściwej wersji pliku i nie zawiera późniejszych, potrzebnych zmian.

cp -a /root/example.com.nginx-before-certbot \
  /etc/nginx/sites-available/example.com
nginx -t
systemctl reload nginx

Ta operacja nie usuwa wydanego certyfikatu i nie odtwarza danych WordPressa; przywraca tylko poprzedni plik Nginx. Dla strony, na której pojawiły się już dane, rollback wymaga zgodnej pary: kopii bazy danych i kopii plików z tego samego punktu w czasie. Nie kasujemy ręcznie bazy ani katalogu strony bez sprawdzonej kopii i procedury odtworzenia.

Jak przenosimy powtarzalne wdrożenie do automatyzacji?

Ręczna instrukcja pomaga zrozumieć kolejność i warunki powodzenia. Przy wielu środowiskach opisujemy pakiety, katalogi, konta MariaDB i konfigurację Nginx w rolach Ansible, a hosty możemy powoływać Terraformem. Automatyzacja nie usuwa jednak potrzeby testu DNS, certyfikatu, backupu i odtworzenia na konkretnym środowisku.

Jaki jest wynik i czego ten minimalny wariant nie zapewnia?

Po wykonaniu kroków mamy WordPressa na Debianie 13, z Nginx jako warstwą HTTP/HTTPS, PHP-FPM do wykonania PHP, MariaDB jako lokalną bazą oraz certyfikatem zarządzanym przez Certbot. Przed produkcją dokładamy sprawdzony backup, monitoring, aktualizacje i hardening dopasowany do realnej aplikacji. Dopiero wtedy prosta instalacja staje się utrzymywaną usługą.

Potrzebujesz szybkiego i bezpiecznego hostingu WordPress?

Wdrażamy i utrzymujemy stacki LEMP pod WordPressa - z hardeningiem, backupem i monitoringiem. Porozmawiajmy o Twoim projekcie, bezpłatnie i bez zobowiązań.