Instalare CentOS8 + NGINX + PHP-FPM + MariaDB + Google PageSpeed + Let’s Encrypt

Acest tutorial te ajută să îţi configurezi un server web cu CentOS8, NGINX, PHP-FPM, MariaDB, Google PageSpeed şi Let’s Encrypt.

Instalarea va fi făcută cu ultimele versiuni stabile disponibile la momentul de faţă. Pachetele sunt din repository-uri oficiale, acolo unde dezvoltatorii au asa ceva. Toate comenzile sunt executate ca root. În cazul în care foloseşti un utiliazator fără drepruri, adaugă sudo în faţa fiecărei comenzi.

Cele mai recente versiuni stabile la momentul scrierii/actualizării acestui articol:

CentOS 8.0
Nginx 1.16.0 stable
PHP 7.3.10
MariaDB 10.4.8
Modul Google PageSpeed 1.16.0
Certbot 0.39.0 (pentru Let's Encrypt)

Urmează pas cu pas instrucţiunile de mai jos şi vei obţine un server funcţional cu specificaţiile software de mai sus.

După instalarea inițială a CentOS, verifică dacă există actualizări ale sistemului de operare

# dnf update -y

Întâi securizează serverul (cu firewall) ca să nu ai surprize. De asemenea va fi nevoie să permiți accesul la protocoalele HTTP și HTTPS.

# dnf install -y firewalld
# systemctl start firewalld
# systemctl enable firewalld
# firewall-cmd --zone=public --permanent --add-service=http
# firewall-cmd --zone=public --permanent --add-service=https
# firewall-cmd --reload

Instalează câteva pachete necesare pentru configurarea serverului şi repository-ul EPEL

# dnf install -y vim wget dnf-utils epel-release

Microtutorial pentru vim

Fişierul se deschide cu comanda

# vim <fişier>

Ca să scrii text în fişier, intră în modul de inserare apăsând “i” sau “INSERT” şi apoi poţi scrie.
Ca să adaugi un text din clipboard, după ce intri în modul de inserare, apasă SHIFT+INSERT sau click dreapta.
Pentru a salva şi închide fişierul, întâi ieşi din modul de inserare apăsând tasta “ESC”, apoi scrie textul de mai jos şi apasă ENTER

:x

Instalare Nginx

Pentru a adăuga repository-ul oficial Nginx, crează fişierul Nginx.repo în /etc/yum.repos.d

# vim /etc/yum.repos.d/nginx.repo

Adaugă codul de mai jos în fişier şi se salvează-l

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

Instalează Nginx, porneşte serviciul şi activează-l să pornească automat la reboot

# dnf install -y nginx
# systemctl start nginx
# systemctl enable nginx

Verifică instalarea apelând serverul prin browser.

Instalare MariaDB

Dacă instalezi MariaDB din repository-ul CentOS, ar instala versiunea 10.3 (la momentul actual). MariaDB are repository oficial, aşa că îl adăugăm şi vom folosi versiunea 10.4.

# vim /etc/yum.repos.d/MariaDB.repo

Adaugă codul de mai jos în fişierul deschis şi se salvează-l

[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.4/centos8-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

Instalează MariaDB, porneşte serviciul şi activează-l să pornească automat la reboot

# dnf install -y boost-program-options
# dnf --disablerepo=AppStream install -y MariaDB-server MariaDB-client
# systemctl start mariadb
# systemctl enable mariadb

Rulează scriptul de securizare pentru MySQL/MariaDB şi setează o parola pentru root

# mysql_secure_installation

Instalare PHP

PHP-ul nu are un repository oficial, aşa că apelăm la unul extern care conţine pachetele necesare. Vom folosi REMI.

# dnf install -y http://rpms.remirepo.net/enterprise/remi-release-8.rpm

În acest moment, sunt disponibile mai multe versiuni de PHP disponibile. Ca să poţi instala PHP din REMI, trebuie să activezi versiunea dorită. În cazul de faţă, ultima versiune stabilă este PHP 7.3

# dnf -y module enable php:remi-7.3

Acum poţi instala PHP-FPM.

# dnf install -y php-fpm php-mysqlnd php-common php-json php-pdo php-cli

În funcţie de necesitățile aplicației/site-ului, trebuie să instalezi pachetele necesare și specifice acestuia.

Nota: pachetul php (simplu) nu a fost instalat şi nici nu este nevoie să fie instalat. Acel pachet este necesar doar când foloseşti PHP împreună cu Apache.

Configurare PHP-FPM

O recomandare pentru o (mică) îmbunătăţire a securităţii este să editezi php.ini

# vim /etc/php.ini

şi să setezi

cgi.fix_pathinfo=0

Păstrăm motivul şi mai facem încă o schimbare. Implicit, PHP afişează versiunea în header-ul primit de browser. Pentru a elimina versiunea, în același fișier, caută şi setează

expose_php = Off

Editează www.conf

# vim /etc/php-fpm.d/www.conf

Folosind nginx, trebuie schimbaţi parametrii user şi group

user = nginx
group = nginx

Schimbă parametrul listen şi setează-l ca mai jos

listen = /run/php-fpm/php-fpm.sock

Decomentează parametrii listen.owner şi listen.group şi stetează-i corect

listen.owner = nginx
listen.group = nginx

Porneşte PHP-FPM şi activează-l să pornească automat

# systemctl start php-fpm
# systemctl enable php-fpm

Notă: În acest moment, Nginx nu este configurat să servească pagini PHP. Îl vom configura mai târziu.

Instalare Google PageSpeed ca modul dinamic

Google oferă un repository oficial doar pentru Apache. Pentru Nginx vom adăuga un repository de la getpagespeed.com.

Antenţie: instalarea Google PageSpeed din repository-ul de mai jos funcţionează doar dacă ai instalat Nginx din repository-ul oficial şi nu din repository-ul CentOS.

# dnf install -y https://extras.getpagespeed.com/release-el8-latest.rpm

Instalează Google PageSpeed

# dnf install -y nginx-module-pagespeed

Notă: În acest moment, Nginx nu este configurat să folosească modulul PageSpeed. Îl vom configura mai târziu.

Instalare Let’s Encrypt

Este impropriu spus instalare Let’s Encrypt, pentru că acesta doar emite certificatele SSL/TLS. Deoarece valabilitatea certificatelor este de doar 90 de zile, ar fi de preferat ca aceste certificate să se reînnoiască automat. Pentru aceasta vom instala CertBot

# wget https://dl.eff.org/certbot-auto
# mv certbot-auto /usr/local/bin/certbot-auto
# chown root /usr/local/bin/certbot-auto
# chmod 0755 /usr/local/bin/certbot-auto

Configurare Nginx

Nginx crează un fişier implicit de configurare pentru domeniu. Este nevoie să-l modificăm

# vim /etc/nginx/conf.d/default.conf

Mai jos sunt modificările, dar la final ai un exemplu de fişier cu toate acestea (pentru subdomeniul casastii.nanlucian.com ca exemplu), păstrând comentariile implicite Nginx şi adăugând altele pentru secţiunile noi, dar eliminând directivele comentate şi nefolosite. Schimbările sunt:

  • setează server_name cu (sub)domeniul tău
  • în secţiunea location / { } găseşti directivele root şi index. Mută-le un “nivel” mai sus, în server { }
  • adaugă index.php în index (de preferat ar fi primul)
  • în secţiunea location / { } adaugă try_files $uri $uri/ =404;
  • decomentează error_page   404 /404.html;
  • decomentează secţiuna location ~ \.php$ { } şi adaugă şi acolo linia try_files $uri $uri/ =404;

Exemplu cu modificările făcute (ce este cu roșu este modificat față de configurarea default, dar mare parte trebuie și modificate conform nevoilor):

server {
    listen 80;
    server_name casastii.nanlucian.com;

    #urmatoarele 2 linii sunt mutate din location / { }
    root /var/www/html; #trebuie configurată calea corectă
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html; # linie decomentata

    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    # pass the PHP scripts to FastCGI server listening on /run/php-fpm/php-fpm.sock
    # sectiunea de mai jos era comentata
    location ~ \.php$ {
        try_files $uri $uri/ =404;
        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
        deny all;
    }
}

Recomand să schimbi numele fişierului din default.conf în <domeniu>.conf .

Mai devreme ai instalat modulul Google PageSpeed. Urmează activarea în /etc/nginx/nginx.conf

# vim /etc/nginx/nginx.conf

Înainte de a începe orice secţiune (ex: events { } ), încarcă modulul pagespeed adăugând linia

load_module "modules/ngx_pagespeed.so";

În secţiunea http { } adaugă

pagespeed FileCachePath /var/ngx_pagespeed_cache;
pagespeed on;

După salvarea şi închiderea fişierului, crează directorul pentru cache şi setează owner-ul nginx

# mkdir /var/ngx_pagespeed_cache
# chown nginx:nginx /var/ngx_pagespeed_cache

Implicit, PageSpeed afişează versiunea în header-ul primit de browser. Recomand ascunderea acesteia din motive de securitate. Cu cât oferi mai puţine particularități despre configurarea serverului tău, cu atât mai bine. Pe lângă setările de folosire a modulului, înainte de linia pagespeed on; , adaugă şi setarea:

pagespeed XHeaderValue "Un mesaj personalizat în locul versiunii";

Implicit, Nginx afişează versiunea în header-ul primit de browser. Din motive de securitate, este de preferat să dezactivezi afişarea versiunii. O poţi face tot în fişierul /etc/nginx/nginx.conf . În secţiunea http { } adaugă

server_tokens off;

Nu uita ca după ce finalizezi modificările în Nginx, să verifici sintaxa fişierelor de configurare şi (în caz că nu există nicio eroare) să dai restart la serviciu.

# nginx -t
# systemctl restart nginx

Generare certificat SSL/TLS

Având domeniul/domeniile configurate în Nginx, poţi genera certificatele SSL/TLS. La generarea cu comanda de mai jos, Certbot va oferi posibilitatea de a modifica fişierele de configurare Nginx, astfel încât să configureze automat redirecţionarea către HTTPS şi folosirea certificatelor. Dacă vrei să faci tu aceste modificări, manual, adaugă la final: certonly

# /usr/local/bin/certbot-auto --nginx

Şi cum spuneam mai sus, ar fi de preferat ca aceste certificate să se reînnoiască automat. Pentru asta editează cron-ul

# crontab -e

şi adaugă o linie similară cu cea de mai jos (Certbot recomandă de 2 ori/zi). La linia de mai jos, recomand să schimbaţi orele scrise.

0 3,15 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/local/bin/certbot-auto renew

Pentru crearea unei mașini virtuale (VM), multe servicii de hosting oferă posibilitatea utilizării cloud-init pentru o configurare inițială mai rapidă. Am creat un fișier pe care-l poți folosi ca template pentru secțiunea cloud-config. Trebuie făcute câteva modificări, menționate chiar în fișier.
Notă: fișierul pentru cloud-init a fost actualizat ultima dată pe configurația: CentOS 7.6, Nginx 1.14.2, PHP 7.3.1, MariaDB 10.3.12, Modul Google PageSpeed 1.13.35, Certbot 0.29.1 (pentru Let’s Encrypt).

webserver.cloud-init

Certificat SSL gratuit + reînnoire gratuită permanentă

SSLCertificatele SSL sunt vândute de o grămadă de site-uri. Unele sunt chiar cele  ale autorităţilor care le emit, altele le revând pe cele ale emitenţilor. Cu câţiva ani în urmă căutam să obţin astfel de certificate, dar gratuit. Cel mai la îndemână sunt certificatele self-signed, însă acestea nu sunt recunoscute de browsere ca fiind certificate valide, deoarece nu sunt emise de o autoritate. După o perioadă de căutări am găsit StartSSL, iar de curând CAcert.

StartSSL

StartSSL emite certificate SSL gratuite, care validează doar domeniul. Emite şi celelalte tipuri de certificate SSL mai avansate, acestea fiind contra cost. Emiterea certificatelor SSL gratuite se face pe baza confirmării unei adrese de e-mail care aparţine unei persoane responsabile de domeniu. Paşii de instalare sunt bine documentaţi. Cu puţin timp înainte de expirarea certificatului, puteţi emite unul nou pentru acelaşi domeniu. Nu am găsit limitări în legătură cu aceste “prelungiri”.
De asemenea am observat că StartSSL are o altă politică pentru certificatele plătite. Certificatele sunt împărţite pe clase:

  • clasa 1, singura gratuită, asigură doar validare de domeniu
  • clasa 2 asigură validare de identitate
  • clasa 3 asigură validarea companiei
  • clasa 4 asigură validarea extinsă a companiei; certificatele de clasă 4 sunt acelea cu bandă verde

Pentru a emite certificate pentru una din clasele 2, 3 sau 4, plăteşti 1 verificare anuală (pentru ce clasă de certificat SSL te interesează). Aceste validări sunt în general mai scumpe decât cumpărarea unui singur certificat SSL din acea clasă de pe alte site-uri. Avantajul StartSSL apare atunci când ai mai multe site-uri, deoarece cu o singură validare pentru o clasă, poţi emite oricâte certificate doreşti, pentru oricâte domenii şi subdomenii.

Notă: După emiterea unui certificat, dacă este instalat imediat, este posibil să nu fie acceptat de către Mozilla Firefox. Trebuie aşteptat un timp (până la 12 ore, dar din experienţă lucrurile se rezolvă în mai puţin de 3 ore) până când certificatul va fi recunoscut corect şi de Firefox.

CAcert

CAcert este site-ul unei organizaţii non-profit şi de asemenea emite certificate SSL gratuite. Deoarece am fost mulţumit de StartSSL, nu am folosit acest site şi nu am nicio expertiză referitoare la produsele şi serviciile lor.

 

Update decembrie 2017

Conform unei note StartSSL, certificatele lor nu mai sunt considerate “trusted” de browserele populare (Chrome, Firefox etc.), drept urmare acest serviciu nu mai poate oferi calitatea iniţială.

De curând am aflat de un nou serviciu:

Let’s Encrypt

Acesta pare a fi şi cel mai calitativ serviciu. Deşi certificatele expiră la fiecare 3 luni, Let’s Encrypt oferă posibilitatea de reînnoire automată a certificatelor, astfel că, dacă este bine configurat, nu o să aveţi surprize să rămâneţi cu un certificat expirat. Control panel-urile precum CPanel, Virtualmin şi altele, oferă plug-in-uri pentru integrarea cu Let’s Encrypt.

A fost anunţat faptul că din 2018 vor fi disponibile şi certificate wildcard, pentru un număr nelimitat de subdomenii.

Ce versiune de browser am?

Uneori avem nevoie să ştim ce versiune de browser avem. Unele site-uri cer un anumit browser sau o anumită versiune a unui browser. Mai jos puteţi citi cum anume să aflaţi versiunea pentru Google Chrome, Mozilla Firefox, Internet Explorer şi Microsoft Edge:

A. Google Chrome

I) Cea mai scurtă variantă este să scrieţi în bara de adrese: chrome://help sau chrome://version/

ChromeVer1II) O altă variantă este să urmaţi paşii:

1. Click pe butonul Menu
2. Mouse over pe Help
3. Click pe About Google Chrome

 

ChromeVer2

FirefoxVer1B. Mozilla Firefox

1. Click pe butonul Menu
2. Click pe Help
3. Click pe About Firefox (ultima opţiune)

FirefoxVer2

FirefoxVer3

IEVer1C. Internet Explorer

I) Cea mai scurtă variantă este să intraţi pe pagina de la Microsoft: https://windows.microsoft.com/ro-ro/internet-explorer/which-version-am-i-using

II) O altă variantă este să urmaţi paşii:

1. Click pe butonul Tools
2. Click pe About Internet Explorer

IEVer2

MSEdgeVer1 D. Microsoft Edge

1. Click pe butonul More
2. Click pe Settings
3. Scroll până jos

MSEdgeVer2

pcfg_openfile: unable to check htaccess file, ensure it is readable

Distracţia mereu începe atunci când primeşti o eroare… eronată. Pentru că eroarea a apărut dintr-un alt motiv decât este explicată. Aşa am întâmpinat eu această eroare la mutarea unui site de pe un server pe altul.

[Wed Jun 05 18:34:26 2013] [error] [client 2a02:2f0e:c0d0:98:d8ef::fc99:3969] PHP Warning: imagepng(): Unable to open ‘./images/captcha/feb84f81d7590126da1c977fe975583c.png’ for writing: Permission denied in /var/www/library/Zend/Captcha/Image.php on line 563
[Wed Jun 05 18:34:26 2013] [crit] [client 2a02:2f0e:c0d0:98:d8ef::fc99:3969] (13)Permission denied: /var/www/sub.domeniu.com/public_html/images/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://sub.domeniu.com/

La o astfel de eroare, m-am întrebat “de unde .htaccess acolo, pentru ca nu a fost niciodată?” Studiind puţin problema am constatat de fapt că nu erau suficiente drepturi pentru apache ca să scrie imaginea în directorul captcha. Este singurul lucru pe care l-am făcut ca să funcţioneze totul din nou şi să nu mai primesc eroarea. După cum se vede, nu are nicio legătură cu eroarea în sine.

Sugestie: verificaţi drepturile directorului începând de la document_root al (sub)domeniului respectiv. Nu a fost nevoie să dau permisiuni doar directorului captcha, ci şi la images. De asemenea, drepturi necesare nu au fost de scriere sau citire, ci de execuţie (+x).

Succes!

Redirecţionare 301

Se întâmplă să schimbi numele paginilor unui site (în sensul de a schimba adresa către pagina) dar ele în sine ca şi conţinut să fie acelaşi lucru, însă într-o astfel de situaţie apar 2 probleme:

1. Pot exista site-uri care au linkurile către adresa veche, pe care tocmai vrei s-o schimbi;
2. Motoarele de căutare vor considera că nu ai legăturile corect făcute.

Prima chestie e simplu de înţeles, a 2-a vrea să spună următorul lucru:
Se dă un site cu 3 pagini: index, pag1 şi pag2. Index are legătură la pag1 şi pag1 la pag2.
Când un motor de căutare citeşte index, el vede legătura la pag1. Când citeşte pag1, vede legărua la pag2. Bine-nţeles că o va citi şi pe aceasta. Dacă noi schimbăm pag2 în pag3, el ar putea să vină să citească din nou pag2 pentru a verifica actualizările, astfel că va primi 404 şi va spune că pag1 are un link mort către pag2, pt. că pag2 nu există. Din experienţă îmi dau seamă că, chiar dacă motorul de căutare revine şi reciteşte pag1, el vede link la pag3 şi va citi pag3, însă durează destul de mult până vine el şi elimină linkurile care nu mai sunt în pag1 ca să nu mai vadă pag2, ci doar la pag3.

Sper că aţi înţeles jocul de cuvinte. Acum, Google arată în Webmaster Tools că există nişte pagini acolo 404 care… au fost şterse de vreo 6 luni, dar el nu şi-a dat seama încă de faptul că linkurile au fost şterse.

Şi atunci, cea mai bună soluţie este Redirectarea 301. Ce înseamnă asta? Îi transmitem vizitatorului paginii şi chiar şi motorului de căutare că pagina a fost mutată permanent la o nouă adresă.

Cum facem rapid asta? Ne folosim de fişierul .htaccess şi folosim sintaxa

redirect 301 pag_vechie pag_noua

Pentru o redirectare a paginii pe acelaşi domeniu

redirect 301 /cale_veche/pag_veche.html /cale_noua/pag_noua.html

Pentru o redirectare pe un alt domeniu

redirect 301 /cale_veche/pag_veche.html http://www.domeniu_nou.tld/cale_noua/pag_noua.html

Succes!