LAMP na Ubuntu 24.04: PHP-FPM i Apache
Instrukcja konfiguracji Apache, MariaDB z unix_socket, PHP 8.3 z PHP-FPM, vhosta name-based oraz bezpłatnego HTTPS Let's Encrypt na Ubuntu 24.04.
Co jest budowane
Stos LAMP składa się z czterech elementów działających na jednym serwerze Ubuntu 24.04: systemu Linux, usługi Apache obsługującej protokół HTTP, bazy danych MariaDB oraz środowiska PHP 8.3 wykonującego kod. Po zakończeniu konfiguracji będzie działać wirtualny host oparty na nazwie, obsługujący rzeczywisty katalog aplikacji, baza danych z dedykowanym użytkownikiem o minimalnych uprawnieniach, PHP połączone z Apache za pośrednictwem PHP-FPM oraz bezpłatny certyfikat Let's Encrypt.
Sama instalacja obejmuje cztery polecenia apt. Większość tego poradnika opisuje połączenie tych elementów oraz niewielki zestaw błędów, które powodują, że nowo utworzony stos wyświetla pustą stronę, przekazuje kod źródłowy do przeglądarki jako plik do pobrania albo odmawia dostępu do dopiero zainstalowanej bazy danych. Każdy z tych problemów ma rozpoznawalny charakterystyczny objaw. Poniżej podano jego nazwę oraz dokładny tekst wyświetlany w danej sytuacji.
Wymagania wstępne i istotne uwagi
Należy założyć użycie nowego VPS KVM z Ubuntu 24.04, użytkownikiem z uprawnieniami sudo lub kontem root oraz publicznym adresem IPv4. Minimalny stos działa przy 1 GB pamięci RAM. Przed wdrożeniem rzeczywistej aplikacji korzystającej z bazy danych należy zwiększyć pamięć do 2 GB, ponieważ domyślne bufory MariaDB oraz kilka procesów roboczych PHP-FPM szybko zużywają pierwszy gigabajt.
Przed uruchomieniem Certbot na końcu muszą być spełnione 2 warunki, dlatego należy przygotować je teraz. Wymagana jest nazwa domeny z rekordem A wskazującym publiczny adres IP VPS. Let's Encrypt przeprowadza walidację przez HTTP dla tej nazwy, a dla samego adresu IP nie można uzyskać certyfikatu. Porty 80 i 443 muszą być dostępne z internetu. U wielu dostawców oznacza to konieczność otwarcia ich w zaporze sieciowej w panelu sterowania oraz w ufw na serwerze. Zmiany DNS mogą propagować się do 1 godziny, dlatego rekord A należy skonfigurować z wyprzedzeniem. Będzie aktywny, gdy stanie się potrzebny.
Krok 1 - Zainstalowanie Apache i sprawdzenie strony domyślnej
sudo apt update
sudo apt install -y apache2apt uruchamia usługę i włącza jej automatyczne uruchamianie. Sprawdź jej stan:
systemctl status apache2Powinien pojawić się wiersz zawierający active (running). Otwórz teraz http://YOUR_SERVER_IP/ w przeglądarce. Prawidłowym wynikiem jest strona Apache2 Ubuntu Default Page z dużym banerem „It works!”. Potwierdza ona, że Apache udostępnia zawartość, a nie sygnalizuje błędu. Strona znajduje się w /var/www/html/index.html i jest udostępniana przez dostarczony domyślny wirtualny host 000-default.conf. Oba elementy zostaną później wyłączone. Na tym etapie ich obecność jest dokładnie tym, co powinno być widoczne.
Jeśli strona w ogóle się nie ładuje, ale systemctl wskazuje, że proces działa, przyczyną jest zapora sieciowa. To będzie następny krok.
Krok 2 — Otwieranie zapory dla HTTP i HTTPS
Pakiet apache2 rejestruje trzy profile aplikacji ufw. Należy je wyświetlić:
sudo ufw app listZostaną wyświetlone Apache, Apache Full oraz Apache Secure. Apache obejmuje tylko port 80, Apache Secure tylko port 443, a Apache Full obejmuje oba porty. Należy wybrać Apache Full, ponieważ TLS zostanie skonfigurowany na końcu.
sudo ufw allow OpenSSH
sudo ufw allow "Apache Full"
sudo ufw enableNależy zezwolić na OpenSSH przed uruchomieniem ufw enable. Domyślnie ufw odrzuca cały ruch przychodzący. Włączenie go bez reguły SSH odcina własne połączenie w chwili aktywacji. Bieżąca sesja pozostaje aktywna, ale nie można już nawiązać ponownego połączenia. Należy potwierdzić ustawienia za pomocą sudo ufw status. Wartości dla OpenSSH, Apache Full oraz ich odpowiedników v6 powinny wynosić ALLOW.
Krok 3 - Instalacja MariaDB i zabezpieczenie
sudo apt install -y mariadb-server
systemctl status mariadbUbuntu 24.04 dostarcza MariaDB 10.11, czyli wydanie z długoterminowym okresem wsparcia, dlatego nie jest potrzebne zewnętrzne repozytorium. Po uruchomieniu usługi należy ją zabezpieczyć:
sudo mysql_secure_installationWarto przeczytać wyświetlane pytania, zamiast bezmyślnie naciskać Enter. Po wyświetleniu pytania o bieżące hasło root należy nacisnąć Enter, ponieważ nie zostało ono jeszcze ustawione. W przypadku pytania „Switch to unix_socket authentication?” odpowiedź niczego nie zmienia, ponieważ uwierzytelnianie jest już włączone w tym pakiecie, dlatego należy nacisnąć n. Na pytanie „Change the root password?” należy odpowiedzieć n z powodu opisanego w następnym akapicie, a na pozostałe pytania odpowiedzieć Y: usunąć użytkowników anonimowych, zabronić zdalnego logowania użytkownika root, usunąć testową bazę danych i ponownie wczytać tabele uprawnień.
Poniższa kwestia często powoduje nieporozumienia. W MariaDB na Ubuntu konto bazy danych root korzysta z uwierzytelniania unix_socket, a nie z hasła. Oznacza to, że baza ufa użytkownikowi systemu operacyjnego, który został już uwierzytelniony. Dlatego z powłoki root działa następujące polecenie:
sudo mysql...i wyświetla monit MariaDB [(none)]> bez żądania hasła. To samo polecenie uruchomione przez użytkownika bez uprawnień zostaje odrzucone, co jest głównym celem tego rozwiązania: dostęp do użytkownika root bazy danych jest powiązany z użytkownikiem sudo na serwerze, a hasła nie można wykraść, wyłudzić ani odgadnąć metodą brute-force. Jest to bezpieczniejsze niż użycie hasła, dlatego należy pozostawić tę konfigurację bez zmian. Wynika z tego następująca zasada: nigdy nie należy konfigurować aplikacji z użyciem konta root. Należy utworzyć osobnego użytkownika dla każdej aplikacji (Krok 7), ponieważ aplikacja łącząca się przez TCP za pomocą nazwy użytkownika i hasła nie może korzystać z uwierzytelniania przez gniazdo, a każda aplikacja powinna mieć dostęp wyłącznie do własnej bazy danych.
Krok 4 — Instalacja PHP 8.3 z PHP-FPM
Domyślna wersja PHP w Ubuntu 24.04 to 8.3. Należy zainstalować menedżer procesów FPM oraz rozszerzenia wymagane przez typową aplikację:
sudo apt install -y php8.3-fpm php8.3-mysql php8.3-cli \
php8.3-curl php8.3-xml php8.3-mbstring php8.3-zipNa tej liście nie ma libapache2-mod-php. Ten starszy pakiet osadza interpreter PHP w każdym procesie Apache. Jest prosty, ale każdy proces roboczy zawiera kopię PHP, niezależnie od tego, czy obsługuje skrypt, czy obraz statyczny. Oba komponenty mają wspólny cykl życia. Rozwiązanie działa tylko z modułem MPM prefork Apache, który jest najmniej wydajny. PHP-FPM uruchamia PHP we własnej puli procesów, z którą Apache komunikuje się przez gniazdo. Apache może wtedy używać wielowątkowego modułu MPM event do obsługi plików statycznych i przekazywać do puli tylko żądania PHP. Pulę można konfigurować niezależnie od serwera WWW. Dokładnie ta sama konfiguracja FPM będzie działać później, jeśli przed Apache zostanie użyty nginx. Jest to obecnie rozwiązanie domyślne z uzasadnionych powodów.
Apache uzyskuje dostęp do FPM za pośrednictwem modułu proxy_fcgi. Należy go włączyć, włączyć konfigurację zainstalowaną przez pakiet FPM i ponownie uruchomić usługę:
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.3-fpm
sudo systemctl restart apache2a2enconf php8.3-fpm aktywuje /etc/apache2/conf-available/php8.3-fpm.conf. Plik ten zawiera regułę przekazującą pliki PHP do gniazda FPM. Reguła dopasowuje dowolny plik .php i przekazuje go do gniazda pod adresem /run/php/php8.3-fpm.sock:
<FilesMatch ".+\.ph(ar|p|tml)$">
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>Nie należy edytować tego pliku. Jest dostarczany z poprawną zawartością. Znajomość ścieżki gniazda ułatwia jednak diagnozowanie późniejszych błędów „PHP jest pobierane zamiast wykonywane” oraz „Primary script unknown”. Oba błędy wynikają z rozbieżności między Apache i FPM dotyczącej tego gniazda lub pliku znajdującego się za nim.
Krok 5 - Wirtualny host oparty na nazwie dla aplikacji
Wirtualne hostowanie oparte na nazwie pozwala obsługiwać wiele witryn z jednego adresu IP. Apache wybiera witrynę na podstawie nagłówka Host: w żądaniu. Należy utworzyć katalog aplikacji z dala od domyślnego katalogu /var/www/html:
sudo mkdir -p /var/www/testapp
sudo chown -R www-data:www-data /var/www/testapp
sudo chmod -R 755 /var/www/testappWłaściciel ma znaczenie. Apache i PHP-FPM działają w systemie Ubuntu jako użytkownik www-data. Dlatego pliki, które serwer WWW musi odczytywać, oraz katalogi, do których aplikacja musi zapisywać dane, na przykład katalog uploads, powinny należeć do www-data. Jeśli pliki będą również edytowane jako zalogowany użytkownik, często stosuje się rozwiązanie polegające na przypisaniu plików do własności tego użytkownika i dodaniu go do grupy www-data. W przypadku zwykłego wdrożenia najmniej zaskakującym wyborem jest www-data:www-data.
Należy utworzyć wirtualny host w /etc/apache2/sites-available/testapp.conf:
<VirtualHost *:80>
ServerName app.example.com
DocumentRoot /var/www/testapp
<Directory /var/www/testapp>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/testapp-error.log
CustomLog ${APACHE_LOG_DIR}/testapp-access.log combined
</VirtualHost>Należy ustawić ServerName na właściwą domenę. Options -Indexes uniemożliwia Apache wyświetlanie zawartości katalogu, gdy nie ma pliku indeksu. W przeciwnym razie odwiedzający mogą przeglądać drzewo kodu źródłowego. AllowOverride All umożliwia działanie pliku .htaccess, czego oczekuje większość aplikacji PHP w przypadku przyjaznych adresów URL. Jeśli aplikacja go nie wymaga, można zmienić tę wartość na None, aby uzyskać niewielki wzrost wydajności. Należy włączyć tę witrynę, wyłączyć domyślną, sprawdzić konfigurację i ponownie wczytać konfigurację:
sudo a2ensite testapp
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2Polecenie apache2ctl configtest powinno wyświetlić Syntax OK. Wiersz a2dissite 000-default jest często pomijany. Z tego powodu domyślna strona może później nadal się wyświetlać, co opisano w sekcji dotyczącej błędów.
Krok 6 - Sprawdzenie działania PHP, a następnie usunięcie pliku testowego
Umieść jednolinijkowy plik PHP w katalogu głównym aplikacji:
echo "<?php phpinfo();" | sudo tee /var/www/testapp/info.phpOtwórz adres http://app.example.com/info.php. Prawidłowy wynik to długa, fioletowo-szara tabela PHP Version 8.3.x zawierająca listę załadowanych modułów. Wiersz Server API powinien zawierać wartość FPM/FastCGI. Potwierdza to, że żądania są obsługiwane przez PHP-FPM, a nie przez mod_php.
Następnie natychmiast usuń ten plik:
sudo rm /var/www/testapp/info.phpphpinfo() ujawnia dokładną wersję PHP, wszystkie załadowane rozszerzenia, ścieżki do plików oraz szczegóły środowiska. Stanowi to cenną informację dla osób skanujących serwer w poszukiwaniu wersji ze znaną luką. Jest to test, a nie funkcja aplikacji. Należy usunąć ten plik natychmiast po wyświetleniu strony. Jeżeli przeglądarka zamiast tabeli proponuje pobranie pliku info.php, PHP nie jest skonfigurowane do współpracy z Apache. Przed wykonaniem jakichkolwiek innych czynności należy przejść do sekcji dotyczącej błędów.
Krok 7 - Utworzenie bazy danych aplikacji i użytkownika z minimalnymi uprawnieniami
Otwórz bazę danych jako uwierzytelniony za pomocą gniazda użytkownik root:
sudo mysqlNastępnie utwórz jedną bazę danych i jednego użytkownika ograniczonego wyłącznie do tej bazy:
CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;W tym miejscu celowo zastosowano trzy rozwiązania. utf8mb4 oznacza rzeczywiste czterobajtowe kodowanie UTF-8. Stary alias utf8 po cichu obcina znaki emoji i niektóre znaki CJK, dlatego należy zawsze używać utf8mb4. Nadanie uprawnień dotyczy appdb.*, a nie *.*. Ten użytkownik może uzyskiwać dostęp tylko do własnej bazy danych, więc luka typu SQL injection w aplikacji nie pozwoli mu odczytać tabel wszystkich pozostałych witryn. Natomiast 'appuser'@'localhost' ogranicza konto do połączeń nawiązywanych lokalnie na tym samym serwerze.
Przetestuj połączenie jako ten użytkownik:
mysql -u appuser -p appdbZostanie wyświetlona prośba o hasło, a następnie pojawi się znak zachęty MariaDB [appdb]>. Należy zauważyć brak flagi -h. Powinna pozostać pominięta, aby klient połączył się za pośrednictwem lokalnego gniazda Unix, które MariaDB traktuje dokładnie jako localhost. Należy znać jedną istotną różnicę: dla MySQL i MariaDB localhost oznacza gniazdo Unix, a 127.0.0.1 oznacza połączenie TCP. W standardowej instalacji MariaDB w Ubuntu 24.04 serwer nadal mapuje połączenie TCP z 127.0.0.1 na localhost, dlatego oba połączenia pasują do tego konta. Jednak na serwerach z włączonym skip-name-resolve, co jest częstą optymalizacją wydajności i standardem w wielu obrazach kontenerów, oba połączenia są dopasowywane jako pochodzące od różnych hostów. W takiej sytuacji aplikacja łącząca się przez 127.0.0.1 otrzyma odmowę z komunikatem ERROR 1045 (28000): Access denied for user 'appuser'@'127.0.0.1' (using password: YES) nawet przy prawidłowym haśle.
Skonfiguruj więc aplikację z hostem localhost, użytkownikiem appuser i bazą danych appdb, nigdy zaś z root. PHP mysqli oraz PDO przełączają się na lokalne gniazdo Unix, gdy host jest dosłownym ciągiem localhost, co odpowiada utworzonemu przed chwilą kontu. Jeśli framework wymaga numerycznego hosta TCP, utwórz użytkownika odpowiadającego faktycznemu sposobowi nawiązywania połączenia: 'appuser'@'127.0.0.1' lub @'%' (w połączeniu z regułą zapory), ale tylko wtedy, gdy baza danych musi być dostępna z innego komputera.
Krok 8 — Dodawanie HTTPS za pomocą Certbot
Udostępnianie formularza logowania przez zwykły HTTP przesyła hasła jawnym tekstem. Każda nowoczesna przeglądarka oznacza wtedy stronę jako „Niezabezpieczona”. Certbot rozwiązuje ten problem za pomocą jednego polecenia. Należy zainstalować go wraz z wtyczką Apache:
sudo apt install -y certbot python3-certbot-apache
sudo certbot --apacheCertbot korzysta tutaj z dwóch wtyczek. Uwierzytelniacz apache potwierdza kontrolę nad domeną, tymczasowo udostępniając plik weryfikacyjny przez działający Apache. Następnie instalator apache modyfikuje konfigurację wirtualnego hosta, aby dodać blok 443, wskazać nowy certyfikat i domyślnie przekierować cały ruch HTTP do HTTPS. Od wersji Certbot 2.0 nie jest wyświetlane pytanie o przekierowanie. Jeśli wymagane jest dalsze udostępnianie zwykłego HTTP, należy przekazać --no-redirect. Ponieważ w kroku 5 ustawiono rzeczywistą wartość ServerName, Certbot automatycznie wykrywa domenę. Certyfikaty są ważne przez 90 dni. Pakiet instaluje także licznik systemd, który odnawia certyfikaty. Licznik można sprawdzić za pomocą sudo certbot renew --dry-run. Wynik powinien kończyć się wartością Congratulations, all simulated renewals succeeded.
Pełny opis weryfikacji, licznika odnawiania oraz wymagań dotyczących DNS i zapory sieciowej znajduje się w powiązanym poradniku wydawanie bezpłatnych certyfikatów TLS Let's Encrypt za pomocą Certbot w Apache.
Kopie zapasowe, aktualizacje i wzmacnianie zabezpieczeń
Należy wykonać kopie zapasowe dwóch elementów przechowujących stan: baz danych i katalogu głównego witryny. Nocny zrzut logiczny jest najprostszym niezawodnym rozwiązaniem, sudo sh -c 'mysqldump --all-databases --single-transaction | gzip > /root/db-$(date +%F).sql.gz', a następnie należy skopiować go poza serwer. Objęcie całego potoku przez sudo sh -c ma znaczenie: bez tego powłoka wykonuje przekierowanie > /root/... jako bieżący użytkownik i kończy działanie błędem Permission denied, ponieważ tylko mysqldump odziedziczył sudo. --single-transaction zapewnia spójny migawkowy zapis tabel InnoDB bez ich blokowania. W połączeniu z tar elementów /var/www i /etc/apache2/sites-available umożliwia to odtworzenie całego stosu na nowym VPS na podstawie tych plików.
Aktualizacje są zwykłą procedurą sudo apt update && sudo apt upgrade. Problemem może być aktualizacja wersji PHP: gdy przyszła wersja Ubuntu zmieni domyślną wersję na PHP 8.4, apt może zainstalować php8.4-fpm obok wersji 8.3, gniazdo zmieni się na /run/php/php8.4-fpm.sock, a konfiguracja Apache nadal będzie wskazywać gniazdo wersji 8.3. Należy włączyć nową konfigurację (sudo a2enconf php8.4-fpm) i wyłączyć starą. W przeciwnym razie witryna zacznie zwracać Primary script unknown po aktualizacji, która poza tym przebiegła standardowo. Ponieważ nowe wersje PHP są wydawane szybciej niż wersje dystrybucji LTS, należy sprawdzać bieżące informacje o wydaniach PHP zamiast przypinać konkretną wersję poprawkową.
Dwa działania związane ze wzmacnianiem zabezpieczeń warto wykonać pierwszego dnia. Po pierwsze, należy skonfigurować na serwerze Fail2Ban do monitorowania SSH. Publicznie dostępny VPS w ciągu kilku minut zaczyna otrzymywać automatyczne próby logowania, a niewielki jail ogranicza tysiące prób do kilku przed zablokowaniem adresu. Po drugie, jeśli preferowane jest zarządzanie wirtualnymi hostami Apache, bazami danych MariaDB i użytkownikami za pomocą przeglądarki zamiast ręcznej edycji plików, internetowy panel administracyjny Webmin działa na dokładnie tym stosie i modyfikuje te same pliki konfiguracyjne, które zostały właśnie utworzone. Żadne z tych narzędzi nie zastępuje znajomości poszczególnych elementów, ale oba ograniczają codzienny nakład pracy.
Tryby awarii wraz z wyświetlanymi komunikatami
Strona domyślna nie znika. Zmieniono konfigurację hosta wirtualnego i wykonano ponowne wczytanie konfiguracji, ale przeglądarka nadal wyświetla „Apache2 Ubuntu Default Page” oraz baner „It works!”. Apache obsługuje pierwszy pasujący host wirtualny. Jeśli żaden ServerName nie pasuje do żądania, używana jest konfiguracja znajdująca się pierwsza w kolejności alfabetycznej. 000-default.conf znajduje się przed testapp.conf. Nazwa hosta w żądaniu nie pasuje do ServerName albo nie wykonano sudo a2dissite 000-default. Należy wyłączyć konfigurację domyślną za pomocą sudo systemctl reload apache2 i sprawdzić wynik poleceniem apache2ctl -S. Polecenie wyświetla mapę hostów wirtualnych i wskazuje konfigurację obsługującą hosta domyślnego. Należy również wyczyścić pamięć podręczną przeglądarki. Zapisana odpowiedź 200 ze starej strony może być nadal wyświetlana.
Plik .php jest pobierany zamiast wykonywany. Po otwarciu info.php przeglądarka pobiera plik zawierający nieprzetworzony kod źródłowy <?php albo wyświetla go jako zwykły tekst. Apache obsługuje plik jako zasób statyczny, ponieważ nie podłączono modułu obsługi PHP, pominięto sudo a2enmod proxy_fcgi lub sudo a2enconf php8.3-fpm albo nie uruchomiono ponownie Apache. Należy wykonać wszystkie trzy czynności (krok 4), a następnie ponownie wczytać stronę. Za pomocą apache2ctl -M | grep fcgi należy potwierdzić załadowanie modułu. Na liście powinien znajdować się proxy_fcgi_module. Jest to wyciek kodu źródłowego, a nie problem kosmetyczny. Należy go usunąć przed umieszczeniem na serwerze rzeczywistych danych.
ERROR 1698 (28000): Access denied for user 'root'@'localhost'. Wykonano mysql -u root lub mariadb -u root bez sudo. Konto root korzysta z uwierzytelniania unix_socket. Akceptowane jest ono tylko wtedy, gdy użytkownik systemu operacyjnego to rzeczywiście root. Należy użyć sudo mysql, bez -u root i bez hasła. Ten komunikat oznacza prawidłowe działanie uwierzytelniania za pomocą gniazda, a nie uszkodzoną instalację.
ERROR 1045 (28000): Access denied for user 'appuser'@'127.0.0.1' z poziomu aplikacji, mimo użycia prawidłowego hasła. Konto istnieje jako 'appuser'@'localhost', ale aplikacja łączy się przez TCP z 127.0.0.1 na serwerze, na którym wyłączono rozpoznawanie nazw hostów (skip-name-resolve). MariaDB traktuje te wartości jako różne hosty: localhost oznacza gniazdo Unix, a 127.0.0.1 oznacza TCP. Należy skonfigurować aplikację tak, aby używała hosta localhost. Wtedy połączenie będzie korzystać z gniazda i pasować do konta. Można też utworzyć drugie konto 'appuser'@'127.0.0.1', jeśli używany framework obsługuje wyłącznie TCP.
AH01071: Got error 'Primary script unknown' w /var/log/apache2/testapp-error.log, a przeglądarka wyświetla File not found.. Apache przekazał żądanie do PHP-FPM, ale FPM nie znalazł skryptu pod ścieżką przekazaną przez Apache. Występują zwykle dwie przyczyny. Gniazdo FPM w konfiguracji wskazuje wersję PHP, która nie jest zainstalowana, na przykład gniazdo php8.4 po aktualizacji, gdy działa tylko wersja 8.3. Pliku może też rzeczywiście nie być, ponieważ DocumentRoot i rzeczywisty katalog nie są zgodne. Należy sprawdzić istnienie gniazda za pomocą ls -l /run/php/, potwierdzić, że DocumentRoot odpowiada lokalizacji pliku, a następnie ponownie uruchomić php8.3-fpm i apache2.
AH00558: apache2: Could not reliably determine the server's fully qualified domain name przy każdym ponownym uruchomieniu. Jest to nieszkodliwe ostrzeżenie, a nie błąd. Apache informuje, że nie ustawiono globalnego ServerName. Aby wyłączyć to ostrzeżenie, należy wpisać ServerName your.domain do /etc/apache2/conf-available/servername.conf i uruchomić sudo a2enconf servername.
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80 podczas uruchamiania Apache. Inny serwer WWW zajmuje już port 80. Często jest to pozostały proces nginx z wcześniejszego testu. Należy znaleźć go za pomocą sudo ss -ltnp | grep :80, a następnie zatrzymać i wyłączyć drugą usługę przed uruchomieniem Apache.
FAQ
mod_php czy PHP-FPM — którego rozwiązania użyć?
Należy użyć PHP-FPM. mod_php osadza interpreter w każdym procesie Apache i wymusza użycie wolnego MPM prefork, dlatego Apache zużywa zasoby PHP nawet podczas serwowania statycznego obrazu. PHP-FPM uruchamia PHP jako oddzielną pulę, którą można niezależnie dostroić. Apache łączy się z nią przez gniazdo. Rozwiązanie działa z szybszym, wielowątkowym MPM event i można je później bez zmian przenieść do nginx. Jest to obecnie standardowa konfiguracja. mod_php ma sens wyłącznie w przypadku starszej aplikacji zależnej od określonego działania wewnątrz procesu.
Dlaczego przeglądarka pobiera plik PHP zamiast go wykonywać?
Apache traktuje plik .php jako statyczny plik do pobrania, ponieważ nie przypisano do niego obsługi PHP. W Ubuntu 24.04 z FPM oznacza to pominięcie jednego z elementów: sudo a2enmod proxy_fcgi, sudo a2enconf php8.3-fpm albo ponownego uruchomienia Apache. Należy wykonać wszystkie trzy czynności i ponownie wczytać konfigurację, a następnie za pomocą apache2ctl -M | grep fcgi sprawdzić, czy wymieniono proxy_fcgi_module. Do czasu usunięcia problemu serwer ujawnia kod źródłowy, dlatego należy potraktować go jako pilny.
Dlaczego dostęp do root w MariaDB jest odrzucany mimo podania prawidłowego hasła?
Ponieważ konto root nie ma hasła, MariaDB w Ubuntu uwierzytelnia konto root za pomocą unix_socket, wiążąc je z użytkownikiem root systemu operacyjnego. Polecenie mysql -u root wykonane z powłoki zwykłego użytkownika zwraca ERROR 1698 (28000): Access denied for user 'root'@'localhost' zgodnie z założeniami konfiguracji. Należy użyć sudo mysql, a dla każdej aplikacji utworzyć oddzielne konto uwierzytelniane hasłem zamiast ponownie używać konta root.
Jak dodać HTTPS do witryny LAMP?
Należy zainstalować certbot i python3-certbot-apache, skierować rekord A domeny na serwer, a następnie uruchomić sudo certbot --apache. Moduł uwierzytelniający apache potwierdza kontrolę nad domeną za pośrednictwem działającego Apache. Instalator modyfikuje konfigurację wirtualnego hosta dla portu 443 i konfiguruje automatyczne odnawianie certyfikatu. Pełny przewodnik po Certbot i Apache opisuje proces weryfikacji, licznik czasu odnawiania oraz typowe przyczyny niepowodzeń.