Visas sistēmas darbojas Tavs IP: 216.73.216.190 info@cloudhosting.lv +371 66 66 29 69 Klientu zona

← Visi jautājumi

LEMP uz Ubuntu 24.04: NGINX, PHP 8.3, MariaDB, SSL

Ubuntu 24.04 LTS savā repozitorijā piegādā PHP 8.3. Tas izņem soli, ar kuru sākas gandrīz visas vecākās pamācības, proti, sveša PHP repozitorija pievienošanu, un līdz ar to arī uzturēšanas slogu, kas tam sekoja. Zemāk ir pilns LEMP uzstādījums uz tīras 24.04 mašīnas: NGINX, MariaDB, PHP 8.3 caur unix ligzdu, bezmaksas Let's Encrypt sertifikāts un tās sertifikāta atjaunošanas detaļas, kuras parasti atklājas pēc kādām septiņdesmit dienām, svētdienas vakarā.

Pirms pirmās apt komandas

Vajadzīgs tīrs 24.04 serveris, root vai sudo konts, un DNS, kas jau norāda uz to. Ieraksti A ierakstu, un AAAA tikai tad, ja tiešām plāno to lietot, un pagaidi, līdz vārds atrisinās no ārpuses. Certbot neinteresē tavi nodomi, tikai tas, ko redz sertifikācijas centrs.

apt update
apt full-upgrade
reboot

Par IPv6 brīdinu uzreiz, jo tā ir visneskaidrākā kļūda visā procesā. Ja domēnam ir AAAA ieraksts, Let's Encrypt vispirms savienojas pa IPv6, un tālākais ir atkarīgs no tā, kā tieši v6 ceļš krīt. Ja uz [::]:80 neviens neklausās, savienojums tiek atteikts, un atteikums nav taimauts, tāpēc atkārtota mēģinājuma nav un izsniegšana krīt uzreiz. Ja ugunsmūris IPv6 paketes klusi met zemē, sanāk taimauts, un tieši šo vienu gadījumu Let's Encrypt atkārto pa IPv4, tāpēc pirmā izsniegšana var izdoties pat serverī ar salauztu IPv6. Atkārtojums attiecas tikai uz šo pirmo pieprasījumu. Tiklīdz 80. ports pāradresē pārbaudi uz HTTPS, un zemāk aprakstītais uzstādījums beigās ir tieši tāds, pāradresāciju atkal mēģina pa IPv6 jau bez rezerves ceļa, un pēc mēnešiem atjaunošana nomirst serverī, kuram neviens nav pieskāries. Abos gadījumos kļūdas tekstā ir tikai adrese, uz kuru gāja, un nekad vārds IPv6, tāpēc tajā var skatīties stundu un neko nesaprast. Vai nu IPv6 strādā līdz galam, vai AAAA ieraksta nav vispār. Šai kaudzei pilnīgi pietiek ar nelielu VPS mūsu Rīgas datu centrā.

NGINX

apt install -y nginx
systemctl enable --now nginx
nginx -v

Noble piegādā 1.24 zaru ar ierasto Debian struktūru: /etc/nginx/sites-available, /etc/nginx/sites-enabled, mape snippets un ufw profils. Noklusētā lapa ir universāls uztvērējs uz 80. porta un labprāt atbild arī uz hostnames, kurus tu nekad neesi konfigurējis, tāpēc noņem to, tiklīdz tava vietne ir vietā.

unlink /etc/nginx/sites-enabled/default

MariaDB

apt install -y mariadb-server
mariadb-secure-installation

10.11 sērijā, ko piegādā noble, skripts saucas mariadb-secure-installation. Vecais nosaukums mysql_secure_installation vēl darbojas kā saderības saite, bet tieši tas pazudīs pirmais. Svarīgāk ir cits: MariaDB root konts autentificējas caur unix_socket spraudni, tāpēc sudo mariadb ielaiž iekšā bez jebkādas paroles. Uzlikt virsū vēl root paroli galvenokārt sarežģī dublējumu skriptus. Uz jautājumu par root autentifikācijas maiņu atbildi ar nē, uz anonīmo lietotāju, testa datubāzes un attālinātā root dzēšanu ar jā.

sudo mariadb
CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'gara-nejausa-parole';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;

Ubuntu pakotne piesaista servisu pie 127.0.0.1 failā /etc/mysql/mariadb.conf.d/50-server.cnf. Atstāj tā. Pārbaudi ar ss -lntp | grep 3306, un par 3306. portu ugunsmūrī vairs nav jādomā.

PHP 8.3 un paplašinājumi, kas vajadzīgi īstai vietnei

apt install -y php8.3-fpm php8.3-cli php8.3-mysql php8.3-xml php8.3-curl php8.3-mbstring php8.3-zip php8.3-gd php8.3-intl php8.3-bcmath

Trīs lietas par šo sarakstu. Pirmkārt, php8.3-cli šajā rindā ir skaidrības, nevis nepieciešamības pēc: Debian un Ubuntu php8.3-fpm ir atkarīgs no php8.3-cli, tāpēc apt to uzstāda arī tad, ja to neprasi, un /usr/bin/php8.3 kopā ar php alternatīvu ir uz vietas uzreiz. Composer, WP-CLI un cron uzdevumiem interpretators ir jau no paša sākuma. Raksti to klāt tik un tā, jo tā paliek redzams, ka darbojas divi SAPI un tos konfigurē atsevišķi, un tieši par to ir nākamā rindkopa. Otrkārt, pakotnes php8.3-json nav: JSON kopš PHP 8.0 ir iebūvēts kodolā, un apt uz šādu pieprasījumu vienkārši atbild ar kļūdu. Tieši šī rinda, pārkopēta no PHP 7 laika pamācībām, visbiežāk salauž visu komandu. Treškārt, mysqli un PDO MySQL dod php8.3-mysql.

OPcache ir atsevišķā pakotnē php8.3-opcache un ienāk kopā ar augstāk minēto. Pārbaudi to tur, kur tas svarīgi: CLI un FPM lasa dažādas konfigurācijas mapes, /etc/php/8.3/cli/conf.d un /etc/php/8.3/fpm/conf.d, tāpēc php -m čaulā neko nepierāda par FPM. Uzliec pagaidu phpinfo() failu, apskati to caur NGINX un izdzēs.

systemctl status php8.3-fpm
ls -l /run/php/php8.3-fpm.sock

Kad ondrej PPA tiešām ir vajadzīgs

PHP 8.3 noble sastāvā saņem drošības labojumus visu LTS periodu, tāpēc PPA ir vērts pievienot tikai tad, ja lietotnei patiešām vajag jaunāku zaru vai tā ir iesprūdusi vecākā.

add-apt-repository ppa:ondrej/php
apt update
apt install -y php8.4-fpm php8.4-cli

Saproti, ko tikko izmainīji. Servisa nosaukums kļūst php8.4-fpm, konfigurācija pārceļas uz /etc/php/8.4, un ligzda kļūst /run/php/php8.4-fpm.sock. Ja tajā pašā darbu logā neizlabo fastcgi_pass, katrs PHP pieprasījums atgriež 502 Bad Gateway. Neatstāj divas FPM versijas darbojamies un norādītas uz svešām ligzdām. Un no tās dienas tavas vietnes PHP versija seko svešam izlaidumu grafikam, nevis Ubuntu.

Servera bloks, kas strādā

mkdir -p /var/www/example.com/public
chown -R www-data:www-data /var/www/example.com

Failā /etc/nginx/sites-available/example.com:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    root /var/www/example.com/public;
    index index.php index.html;

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

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

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Fails snippets/fastcgi-php.conf nāk līdzi Ubuntu pakotnei un jau uzstāda SCRIPT_FILENAME, sadala PATH_INFO un pievieno try_files ... =404 aizsargu, kas neļauj izpildīt patvaļīgus failus. Neraksti to no jauna ar roku. Ievēro punktu failu noteikuma formu: variants bez negatīvā priekšskatījuma, location ~ /\. { deny all; }, aizver arī /.well-known/acme-challenge/ un salauž gan izsniegšanu, gan visas turpmākās atjaunošanas.

Ugunsmūris

ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable
ufw status verbose

SSH atļauj pirms ufw ieslēgšanas, un, ja sshd klausās uz nestandarta porta, atļauj tieši to portu pēc numura. Profils Nginx Full aptver 80 un 443 un nāk no nginx-common pakotnes. Ja NGINX likts no ražotāja repozitorija, tāda profila nav, tad atver 80,443/tcp manuāli.

Sertifikāts

Abi ceļi ir derīgi. No Ubuntu arhīva:

apt install -y certbot python3-certbot-nginx

Vai no snap, kā iesaka pats certbot projekts un kur versijas ir svaigākas:

snap install core
snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot

Izvēlies vienu. Abi kopā nozīmē divus binārus, kas cīnās par /usr/bin/certbot, un divus taimerus, kas atjauno vienu un to pašu sertifikātu. Tad izsniedz:

certbot --nginx -d example.com -d www.example.com

nginx spraudnis pārraksta tavu servera bloku uz vietas: pievieno listen 443 ssl, sertifikātu ceļus, kopīgo TLS opciju failu un, ja piekrīti piedāvājumam, atsevišķu 80. porta bloku ar pāradresāciju uz HTTPS.

Viena pāradresācija, vienā vietā

Vai nu ļauj certbot uzrakstīt pāradresāciju, vai raksti pats, bet nekad abus. Divas pāradresācijas vienā pieprasījuma ceļā dod ciklu vai pārlūka sūdzību par pārāk daudz pāradresācijām, un bieži tas parādās tikai aiz proxy. Ar roku rakstīta tā izskatās garlaicīgi:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Šis bloks aizstāj 80. porta bloku ar tiem pašiem vārdiem, nevis stāv tam blakus. Divi bloki uz 80. porta ar vienādu server_name liek NGINX ierakstīt žurnālā brīdinājumu par konfliktējošu vārdu un klusi lietot pirmo no tiem. Lieto $host, nevis ierakstītu domēnu, un saglabā $request_uri, lai ceļš izdzīvo. Pāradresācija uz https://example.com/, kas ceļu nomet, vēlāk ir klasisks atjaunošanas kritiena iemesls, jo ACME pārbaudes adrese pārvēršas par sākumlapu. Ja TLS tiek terminēts priekšā, pāradresē pēc X-Forwarded-Proto, citādi cikls ir garantēts.

Ko taimeris patiesībā dara

systemctl list-timers | grep -i certbot
systemctl cat certbot.timer

apt pakotne uzstāda certbot.timer, snap uzstāda snap.certbot.renew.timer. Abi nostrādā divreiz dienā ar lielu nejaušu nobīdi, lai visa pasaule nesistu pa ACME API vienā minūtē. Vienība palaiž certbot -q renew, un renew nedara neko, kamēr sertifikātam nav palikušas aptuveni trīsdesmit dienas līdz beigām. Žurnāls, kas pilns ar no action taken, ir vesela sistēma, nevis salūzis cron. apt pakotne papildus noliek /etc/cron.d/certbot, kurš pārbauda systemd klātbūtni un izbeidzas, tāpēc dubultas atjaunošanas nav.

Atjaunošana atkārto /etc/letsencrypt/renewal/example.com.conf, nevis tavu komandu vēsturi: autentifikators, instalators, webroot ceļš, precīzs vārdu saraksts. Ja vēlāk pārbūvē vietnes struktūru, labo tieši šo failu. Un pārbaudi pārlādes ceļu. Ar nginx instalatoru certbot pats pārlādē NGINX. Ar tīru webroot autentifikatoru un bez instalatora NGINX neviens nepārlādē, un tas atmiņā tur veco sertifikātu, līdz kaut kas cits to restartē. Tieši tā perfekti atjaunots sertifikāts pārlūkā joprojām rādās kā beidzies. Zem [renewalparams] pievieno:

renew_hook = systemctl reload nginx

Kā testēt atjaunošanu, nesitot limitos

certbot renew --dry-run

Šis iet pret staging vidi, tāpēc produkcijas limiti paliek neskarti. Tiek pārbaudīts DNS, pārbaudes uzdevums un spraudnis, bet mapē /etc/letsencrypt/live nekas netiek ierakstīts, tāpēc par pārlādes soli tas neko nepasaka. Lai pārbaudītu pašu plānoto ceļu, palaid vienību ar roku: systemctl start certbot.service vai snap.certbot.renew.service snap gadījumā. Tas ir īsts atjaunošanas mēģinājums, kurš neko nedara, ja termiņš vēl nav pienācis.

Jaunam hostname, par kuru neesi drošs, izsniedz vispirms ar --test-cert, pārliecinies, ka viss iet cauri, un tikai tad izsniedz īsto. Ko nedrīkst darīt, ir atkārtoti dzīt certbot --nginx tiem pašiem vārdiem, kamēr meklē kļūdu. Identiski sertifikāti ātri sasniedz nedēļas dublikātu limitu, un neizdevušās validācijas skaita atsevišķu stundas limitu, tāpēc beigās izsniegšana ir aizvērta uz pilnīgi pareizi nokonfigurēta servera.

Divas kļūdas, kas salauž atjaunošanu vēlāk

ACME pārbaudes adrese. Viss, kas neļauj atdot http://example.com/.well-known/acme-challenge/<token>, salauž atjaunošanu nedēļas pēc tam, kad esi par serveri aizmirsis. Parastie vaininieki: augstāk minētais punktu failu liegums, pāradresācija, kas nomet ceļu, basic auth vai IP saraksts uz visu vietni, vai WAF noteikums priekšā. Validācija seko pāradresācijām, arī uz HTTPS, tāpēc pati par sevi 301 nav problēma. Pārbaudi ar roku:

mkdir -p /var/www/example.com/public/.well-known/acme-challenge
echo ok > /var/www/example.com/public/.well-known/acme-challenge/test
curl -IL http://example.com/.well-known/acme-challenge/test

Ķēdes beigās gribi 200, pēc tam izdzēs failu. Ja vietne ir aiz basic auth, izgriez izņēmumu: location ^~ /.well-known/acme-challenge/ { auth_basic off; allow all; }.

Novecojusi simboliskā saite. /etc/letsencrypt/live/example.com/fullchain.pem ir saite uz /etc/letsencrypt/archive/, un atjaunošana šo saiti pārliek. Divi ieradumi to sabojā. Pem failu kopēšana uz /etc/nginx/ssl un NGINX norādīšana turp nozīmē, ka atjaunošana svaigina failus, kurus neviens neatdod. Bet dzēšana un certbot palaišana no jauna rada otru līniju ar nosaukumu example.com-0001, kura mierīgi atjaunojas, kamēr NGINX joprojām lasa pamesto example.com mapi. Salīdzini abas puses:

certbot certificates
grep -R ssl_certificate /etc/nginx/sites-enabled/
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject

Patiesība ir s_client datumi. Ja tie nesakrīt ar certbot certificates, tu vai nu atdod veco ceļu, vai neesi pārlādējis NGINX.

Pārbaudes pirms darbu var uzskatīt par pabeigtu

nginx -t
systemctl status nginx php8.3-fpm mariadb --no-pager
systemctl is-enabled nginx php8.3-fpm mariadb certbot.timer
ss -lntp

Pēc tam pārstartē serveri un atkārto pārbaudes, jo kaudze, kas strādā tikai līdz nākamajam kodola atjauninājumam, nav pabeigta. Atstāj ieslēgtu unattended-upgrades drošības labojumiem un atceries, ka pēc paplašinājuma atjaunināšanas PHP-FPM vajag restartu, nevis reload. Ja negribi visu šo uzturēt pats, WordPress hostings sedz to pašu kaudzi tavā vietā, un mūsu inženieri ir pieejami visu diennakti caur IT atbalstu, ja pašbūvēts serveris sāk niķoties.

Gribi, lai to darām mēs?
VPS. NVMe virtuālie serveri, gatavi minūtes laikā.
Uzzināt vairāk

Gatavs sākt?

Palaid dažās minūtēs vai aprunājies ar inženieri par piemērotāko risinājumu.