↓ Przewiń do głównej treści
  1. Posts/

Instalacja PHP 7.2–8.3 na Debianie i Ubuntu (wiele wersji obok siebie)

·6 min
~/unixway
Autor
~/unixway
Techniczny blog po polsku o Linuksie, administracji serwerami i self-hostingu.
Spis treści

Debian i Ubuntu trzymają w oficjalnych repozytoriach tylko jedną wersję PHP — tę, która trafiła do danego wydania. Problem w tym, że realne aplikacje tego nie respektują: stary sklep potrzebuje PHP 7.4, świeży Laravel chce 8.3, a jedno i drugie ma działać na tym samym serwerze. Rozwiązaniem nie jest kompilacja ze źródeł, tylko repozytorium Ondřeja Surýego (packages.sury.org) — to z niego pochodzą pakiety phpX.Y, które można instalować równolegle, obok siebie.

Poniżej cała droga: od dodania repozytorium (nowoczesną metodą, bez przestarzałego apt-key), przez instalację wybranej wersji z PHP-FPM i rozszerzeniami, po ustawienie, która wersja ma być domyślna.

Wszystkie polecenia uruchamiamy jako root albo przez sudo. Przykłady są dla Debiana; na Ubuntu różni się tylko nazwa wydania zwracana przez lsb_release — reszta jest identyczna.

Zobacz całość w akcji
#

Zanim przejdziemy do szczegółów — tak wygląda cały proces na czystym Debianie 13: dodanie repozytorium Sury, instalacja PHP 8.3 z rozszerzeniami, druga wersja (7.4) obok i podgląd update-alternatives. Nagranie z prawdziwej sesji, bez montażu.

Przygotowanie — wymagane pakiety
#

Do pobrania klucza i obsługi repozytorium po HTTPS potrzebujemy kilku drobiazgów:

1
2
apt update
apt install -y ca-certificates apt-transport-https lsb-release curl gnupg

Dodanie repozytorium Sury
#

W internecie wciąż krąży metoda z apt-key add i kluczem w /etc/apt/trusted.gpg.d/. Nie używaj jej — apt-key jest wycofany (usunięty w Debianie 12+), a klucz w trusted.gpg.d ufa repozytorium dla całego systemu, nie tylko dla PHP. Poprawnie klucz trzymamy w /etc/apt/keyrings/ i przypinamy go do jednego repozytorium przez signed-by:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Katalog na klucze (na Debianie 12+ już istnieje, ale nie zaszkodzi)
install -m 0755 -d /etc/apt/keyrings

# Klucz GPG repozytorium Sury
curl -fsSLo /etc/apt/keyrings/php-sury.gpg https://packages.sury.org/php/apt.gpg

# Repozytorium przypięte do tego klucza i do wydania systemu
echo "deb [signed-by=/etc/apt/keyrings/php-sury.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" \
  > /etc/apt/sources.list.d/php-sury.list

apt update

$(lsb_release -sc) samo podstawia nazwę wydania (bookworm, trixie, noble…), więc tego samego polecenia użyjesz na każdej maszynie.

Instalacja wybranej wersji PHP
#

Każda wersja to osobny zestaw pakietów phpX.Y-*. Minimalny, sensowny zestaw dla aplikacji webowej pod Nginx to FPM + CLI + najczęściej używane rozszerzenia. Przykład dla PHP 8.3:

1
2
3
4
apt install -y \
  php8.3-fpm php8.3-cli php8.3-common \
  php8.3-curl php8.3-mbstring php8.3-xml php8.3-zip \
  php8.3-gd php8.3-intl php8.3-bcmath php8.3-mysql php8.3-opcache

Chcesz inną wersję? Podmień numer. Repozytorium Sury obsługuje pełen zakres — od starych, już niewspieranych wydań, po najnowsze:

WersjaStatus (2026)Kiedy jej użyć
php7.2, php7.3EOL (bez wsparcia)tylko legacy, którego nie da się jeszcze zmigrować
php7.4EOLstare CMS-y i sklepy (np. starszy Magento, WordPress z wtyczkami)
php8.0, php8.1EOL / kończące się wsparcieaplikacje w trakcie migracji
php8.2, php8.3wspieranenowe projekty, Laravel, Symfony

Instalacja np. PHP 7.4 wygląda tak samo — zmienia się tylko prefiks:

1
2
3
apt install -y php7.4-fpm php7.4-cli php7.4-common \
  php7.4-curl php7.4-mbstring php7.4-xml php7.4-zip \
  php7.4-gd php7.4-intl php7.4-mysql php7.4-opcache

Uwaga o bezpieczeństwie. Wersje oznaczone jako EOL nie dostają już poprawek bezpieczeństwa. Instaluj je świadomie — tylko pod konkretną aplikację, która jeszcze nie działa na nowszym PHP, i trzymaj taką usługę za reverse proxy, nie wystawiaj wprost do sieci.

Najczęściej potrzebne rozszerzenia
#

Rozszerzenia w repozytorium Sury to po prostu pakiety phpX.Y-<nazwa>. Nie trzeba nic kompilować — wystarczy je doinstalować i zrestartować FPM. Najczęściej spotykane:

PakietDo czego
php8.3-mysqlbazy MySQL / MariaDB (PDO)
php8.3-pgsqlPostgreSQL
php8.3-curlzapytania HTTP, API
php8.3-mbstringobsługa UTF-8 / wielobajtowych napisów
php8.3-xmlXML, SimpleXML, DOM
php8.3-gd lub php8.3-imagickprzetwarzanie obrazów
php8.3-ziparchiwa (wymaga tego m.in. Composer)
php8.3-intlinternacjonalizacja, sortowanie wg locale
php8.3-bcmathprecyzyjna arytmetyka (finanse)
php8.3-redis, php8.3-memcachedcache, sesje
php8.3-opcachekompilacja do bajtkodu — zawsze włącz na produkcji

Doinstalowanie później i restart puli:

1
2
apt install -y php8.3-redis
systemctl restart php8.3-fpm

Co masz aktualnie załadowane, sprawdzisz tak:

1
2
php8.3 -m            # lista modułów danej wersji
php8.3 -i | grep -i opcache   # szczegóły konkretnego rozszerzenia

Kilka wersji obok siebie i domyślne php
#

Po zainstalowaniu dwóch wersji masz do dyspozycji oddzielne binaria i usługi:

1
2
3
php7.4 -v
php8.3 -v
systemctl status php7.4-fpm php8.3-fpm

Polecenie php (bez numeru) wskazuje na jedną z nich — tę wybraną w systemie alternatyw. Którą? Zmienisz to interaktywnie:

1
update-alternatives --config php
1
2
3
4
5
6
7
8
9
There are 2 choices for the alternative php (providing /usr/bin/php).

  Selection    Path             Priority   Status
------------------------------------------------------------
* 0            /usr/bin/php8.3   83        auto mode
  1            /usr/bin/php7.4   74        manual mode
  2            /usr/bin/php8.3   83        manual mode

Press <enter> to keep the current choice[*], or type selection number:

To ustawia tylko domyślne php w CLI (np. dla Composera czy skryptów crona). Na to, której wersji użyje konkretna strona WWW, update-alternatives nie wpływa — o tym decyduje pula PHP-FPM wskazana w konfiguracji serwera WWW. I tu dochodzimy do sedna.

PHP-FPM vs mod_php — i wersja per-strona
#

Są dwa sposoby na uruchomienie PHP pod serwerem WWW:

  • libapache2-mod-php — PHP wbudowane w proces Apache. Prostsze w konfiguracji, ale wymusza tryb prefork, gorzej skaluje się pod obciążeniem, i co istotne: jeden Apache = jedna wersja PHP. Dla kilku wersji obok siebie odpada.
  • PHP-FPM — PHP działa jako osobna usługa (FastCGI). Każda wersja ma własną pulę i własny socket, więc różne strony na jednym serwerze mogą używać różnych wersji PHP jednocześnie. Działa i z Nginx, i z Apache (mod_proxy_fcgi). To domyślny wybór na produkcji.

Każda wersja wystawia własny socket uniksowy:

1
2
ls /run/php/
# php7.4-fpm.sock  php8.3-fpm.sock

W Nginx wybór wersji dla danej strony sprowadza się do wskazania właściwego socketu w fastcgi_pass:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# /etc/nginx/sites-available/moja-strona.pl
server {
    listen 80;
    server_name moja-strona.pl;
    root /var/www/moja-strona.pl;
    index index.php;

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

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        # TU wybierasz wersję PHP dla tej strony:
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

Druga strona, która potrzebuje PHP 7.4, dostaje identyczny blok z php7.4-fpm.sock — i tyle. Po zmianie:

1
nginx -t && systemctl reload nginx

Weryfikacja
#

Szybki test, że wszystko stoi:

1
2
3
php -v                       # domyślna wersja CLI
systemctl is-active php8.3-fpm   # czy pula FPM działa
php-fpm8.3 -t                # test składni konfiguracji FPM

A że PHP faktycznie obsługuje strony — najprościej plikiem info.php z phpinfo() w rootcie strony (po sprawdzeniu skasuj go, ujawnia konfigurację serwera).

Najczęstsze błędy
#

EXPKEYSIG ... DEB.SURY.ORG Automatic Signing Key przy apt update — klucz się odświeżył albo jest niekompletny. Pobierz go ponownie do keyringu (nie przez apt-key):

1
2
curl -fsSLo /etc/apt/keyrings/php-sury.gpg https://packages.sury.org/php/apt.gpg
apt update

lsb_release: command not found — brakuje pakietu lsb-release z sekcji „Przygotowanie”. Doinstaluj go albo wpisz nazwę wydania na sztywno, np. bookworm, zamiast $(lsb_release -sc).

Unable to locate package php8.3 — repozytorium nie zostało dodane poprawnie albo apt update nie zaciągnął nowej listy. Sprawdź cat /etc/apt/sources.list.d/php-sury.list i powtórz apt update.

Podsumowanie
#

Repozytorium Sury załatwia cały problem wielu wersji PHP bez kompilacji: dodajesz klucz nowocześnie przez signed-by, instalujesz phpX.Y-fpm z potrzebnymi rozszerzeniami, a każda wersja dostaje własny socket. Domyślną wersję CLI przełączasz przez update-alternatives, a wersję dla konkretnej strony — jednym wpisem fastcgi_pass w konfiguracji Nginx. Stare wydania instaluj tylko świadomie i nigdy nie wystawiaj EOL-owego PHP wprost do internetu.