Su AlmaLinux 9 la parte difficile non è “attivare HTTPS”, ma farlo in modo pulito: certificato corretto, catena completa, rinnovo automatico, permessi coerenti e nessun effetto collaterale su firewall, virtual host e redirect. Se il server espone un sito pubblico, TLS non è un optional: è il livello minimo di igiene operativa.
La scelta più pratica, nella maggior parte dei casi, è usare Let’s Encrypt con Certbot. Funziona bene sia con Apache sia con Nginx, integra il rinnovo automatico e riduce gli errori manuali. Il punto non è solo ottenere un certificato valido: bisogna verificare che il servizio lo serva davvero, che il rinnovo non si rompa al primo reload e che il traffico HTTP venga portato su HTTPS senza loop.
Prima decisione: Apache o Nginx, certificato pubblico o interno
Il flusso cambia poco tra Apache e Nginx, ma cambia il punto in cui si inserisce la configurazione. Se il sito è esposto su Internet e deve essere raggiungibile da browser standard, usa un certificato pubblico emesso da una CA riconosciuta. Se invece stai proteggendo servizi interni, pannelli amministrativi o backend non pubblici, può avere senso una CA interna, ma solo se hai già una distribuzione controllata dei trust store sui client.
Per un server web classico su AlmaLinux 9, la strada più lineare è questa: installare Certbot dai repository EPEL, generare il certificato con validazione HTTP-01, applicarlo al virtual host e verificare il rinnovo con un test simulato. Se la porta 80 non è raggiungibile dall’esterno, passa a DNS-01 o apri temporaneamente il traffico necessario. Non forzare workaround strani: il certificato deve essere rinnovabile senza interventi manuali.
Prerequisiti minimi sul sistema
Prima di toccare la configurazione, verifica che il sistema sia aggiornato, che l’orologio sia corretto e che il web server risponda almeno in HTTP. Un time skew serio rompe la validazione e rende i sintomi fuorvianti. Sui sistemi recenti, il servizio NTP è spesso già attivo, ma vale la pena controllarlo.
Comandi utili per l’ispezione iniziale:
sudo dnf update -y
sudo systemctl status chronyd
sudo timedatectl
sudo ss -lntp | egrep ':(80|443)\s'
Se non hai ancora un web server installato, il setup base può essere questo:
sudo dnf install -y httpd
sudo systemctl enable --now httpd
Oppure, per Nginx:
sudo dnf install -y nginx
sudo systemctl enable --now nginx
Il firewall va allineato prima dell’emissione del certificato, altrimenti la challenge HTTP fallisce in modo banale ma poco immediato da leggere se stai guardando solo il log di Certbot.
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services
Installare Certbot su AlmaLinux 9
Su AlmaLinux 9 la via più comune è abilitare EPEL e installare il pacchetto Certbot più il plugin del web server. Evita pacchetti presi a caso da fonti non allineate: per TLS la manutenzione conta più della scorciatoia iniziale.
sudo dnf install -y epel-release
sudo dnf install -y certbot python3-certbot-apache
Se usi Nginx:
sudo dnf install -y certbot python3-certbot-nginx
La differenza pratica è nel plugin: quello per Apache può modificare i virtual host e creare redirect; quello per Nginx aggiorna i blocchi server. In entrambi i casi conviene comunque sapere dove finiranno i file, così non si perde il controllo al primo rinnovo automatico.
Emissione del certificato con validazione HTTP-01
Per un dominio pubblico, la procedura più lineare è l’emissione diretta con il plugin del server web. Sostituisci example.com e www.example.com con i tuoi FQDN reali. Se il sito ha più alias, includili subito: aggiungerli dopo non è difficile, ma è un altro ciclo di rinnovo da gestire.
sudo certbot --apache -d example.com -d www.example.com
Per Nginx:
sudo certbot --nginx -d example.com -d www.example.com
Durante l’emissione, Certbot chiede di scegliere se forzare il redirect da HTTP a HTTPS. In un ambiente semplice la risposta è sì; in un ambiente con applicazioni legacy o proxy a monte, meglio verificare prima che non ci siano endpoint che dipendono ancora da HTTP. Il redirect va bene, ma deve essere intenzionale.
Dopo l’emissione, il certificato e la chain finiscono di norma sotto /etc/letsencrypt/live/. I file simbolici più importanti sono fullchain.pem e privkey.pem. Il primo serve al server web per presentare certificato e intermedi, il secondo è la chiave privata e va protetto come tale.
Configurazione Apache: virtual host, redirect e SSL sicuro
Su Apache, il punto critico è non lasciare una configurazione ibrida. Se attivi SSL ma dimentichi il virtual host HTTP, rischi di avere sia contenuto duplicato sia redirect incompleti. Se usi il plugin di Certbot, gran parte del lavoro viene automatizzata, ma è comunque utile conoscere il layout finale.
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Se vuoi un hardening minimo lato Apache, disabilita versioni vecchie di protocollo e suite deboli solo se il parco client lo consente. Su un sito moderno non hai motivo di tenere TLS 1.0 o 1.1. Un set sensato parte da TLS 1.2 e 1.3, con il resto escluso.
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite PROFILE=SYSTEM
SSLHonorCipherOrder off
Su AlmaLinux 9, la direttiva PROFILE=SYSTEM si appoggia alla policy di sicurezza del sistema. È una scelta ragionevole perché evita di inseguire a mano liste cipher che diventano obsolete. Se hai requisiti di compliance specifici, valuta il profilo crypto-policies del sistema prima di sovrascrivere tutto nel virtual host.
Configurazione Nginx: server block pulito e chain completa
Con Nginx il concetto è lo stesso, ma il file di configurazione è più esplicito. Il blocco HTTP deve fare redirect, il blocco HTTPS deve puntare ai file corretti e la chain deve essere completa. Un errore comune è usare solo il certificato senza intermedi, ottenendo un risultato che “sembra” funzionare in alcuni browser ma fallisce altrove.
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
root /usr/share/nginx/html;
index index.html index.htm;
}
Se il sito usa PHP-FPM, il TLS sta comunque sul layer Nginx, mentre PHP resta dietro FastCGI. In quel caso verifica che il backend non stia generando URL assoluti in HTTP, altrimenti ti ritrovi redirect parziali o mixed content. Il certificato è corretto, ma l’applicazione continua a comportarsi come se fosse in chiaro.
Verifica della catena, SNI e risposta reale del server
Non fermarti a “il lucchetto c’è”. Devi controllare la catena, il nome host, il protocollo negoziato e l’assenza di errori sulla presentazione del certificato. Un test rapido da terminale ti dice molto più di una visita casuale dal browser.
openssl s_client -connect example.com:443 -servername example.com -showcerts
curl -I https://example.com
Nell’output di openssl s_client cerca almeno questi punti: certificato emesso per il nome corretto, catena completa, assenza di errori di verify e protocollo TLS moderno. Con curl -I controlli che la risposta sia 200 o 301 coerente, non 5xx e non un redirect verso HTTP.
Se usi più virtual host sullo stesso IP, il parametro -servername è fondamentale. Senza SNI rischi di vedere il certificato “di default” invece di quello del sito reale, e la diagnosi diventa sbagliata. Questo errore è molto comune quando un server ospita più domini e qualcuno testa solo per IP.
Rinnovo automatico: il punto che rompe in produzione
Il certificato iniziale è la parte facile. La parte che conta è il rinnovo automatico. Certbot su AlmaLinux 9 installa spesso un timer systemd o un cron equivalente, ma non basta presumere che funzioni: va testato. Se il rinnovo fallisce, il sito non si rompe subito; si rompe alla scadenza, che è il peggior momento per scoprirlo.
sudo systemctl list-timers | grep certbot
sudo certbot renew --dry-run
Il dry run deve terminare senza errori di challenge o di reload del web server. Se fallisce, guarda i log del processo e del service manager. I percorsi più utili sono in genere /var/log/letsencrypt/letsencrypt.log e il journal di systemd.
sudo journalctl -u certbot -xe
sudo tail -n 100 /var/log/letsencrypt/letsencrypt.log
In alcuni casi il rinnovo funziona ma il reload del server web no. È un problema diverso: il certificato nuovo viene emesso, ma il processo in ascolto continua a servire quello vecchio finché non ricarichi la configurazione. Per questo conviene verificare che il timer o l’azione post-renew eseguano anche il reload del servizio.
Reload corretto e hook post-rinnovo
Apache e Nginx leggono i file del certificato all’avvio o al reload, non “magicamente” al cambio del file. Se Certbot rinnova i file ma non ricarica il demone, il browser continuerà a vedere il vecchio certificato. La soluzione è usare un hook post-rinnovo o verificare che il plugin scelto lo faccia già.
sudo systemctl reload httpd
sudo systemctl reload nginx
Per controllo manuale, puoi testare il rinnovo e vedere se il reload è parte del processo. Se preferisci un hook esplicito, il principio è semplice: rinnovo riuscito, poi reload, poi verifica del nuovo certificato. Non fare il contrario.
Un esempio di deploy hook minimale:
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-web.sh > /dev/null <<'EOF'
#!/bin/bash
systemctl reload httpd || systemctl reload nginx
EOF
sudo chmod 750 /etc/letsencrypt/renewal-hooks/deploy/reload-web.sh
Questa soluzione va bene solo se sul server gira uno dei due web server. Se il nodo fa da reverse proxy davanti a più servizi, il reload va indirizzato al demone corretto e non lasciato a una scelta ambigua. In ambienti misti, meglio uno script esplicito e versionato.
Hardening utile, non cosmetico
Una volta funzionante, TLS va rifinito con criteri pragmatici. Non serve cambiare dieci opzioni se poi lasci porte inutili aperte o secret sparsi in file leggibili da utenti non privilegiati. La sicurezza pratica è fatta di dettagli ripetibili.
- usa solo TLS 1.2 e 1.3, salvo client legacy documentati;
- mantieni la chiave privata in
/etc/letsencrypt/live/con permessi gestiti da root; - limita l’accesso SSH e l’esposizione delle porte al solo necessario;
- non committare chiavi, token o file di account ACME in repository;
- tieni un audit minimo dei rinnovi con log e alert sulla scadenza.
Su AlmaLinux 9 è sensato appoggiarsi anche alle crypto policy di sistema, perché centralizzano parte del comportamento TLS. Se devi allineare più servizi, un profilo coerente del sistema è meno fragile di singole eccezioni sparse nei file di configurazione dei vari daemon.
Problemi tipici e come leggerli senza perdere tempo
Se l’emissione fallisce, le cause ricorrenti sono sempre le stesse: DNS che punta altrove, porta 80 chiusa, virtual host sbagliato, challenge non raggiungibile o proxy/CDN che intercetta la richiesta. Prima di cambiare configurazioni a caso, verifica il layer coinvolto.
- DNS:
dig example.com +shortdeve restituire l’IP atteso. - Rete:
curl -I http://example.comdeve raggiungere il server e non un altro nodo. - Web server: i log di Apache o Nginx devono mostrare la richiesta della challenge ACME.
- Certbot:
/var/log/letsencrypt/letsencrypt.logdeve indicare l’errore reale, non solo il fallimento finale.
Se il browser mostra “mixed content”, il TLS è probabilmente corretto ma l’applicazione continua a generare risorse in HTTP. In quel caso il fix non è nel certificato: va corretto il codice, la configurazione dell’app o gli header del proxy. Per applicazioni PHP, spesso il problema è una base URL non allineata o una variabile di ambiente che indica ancora HTTP.
Verifica finale prima di mettere in produzione
Prima di considerare chiusa la configurazione, esegui una checklist minima. Devi sapere non solo che il sito apre in HTTPS, ma che lo fa in modo stabile e rinnovabile.
curl -I http://example.com
curl -I https://example.com
openssl s_client -connect example.com:443 -servername example.com < /dev/null | grep -E 'subject=|issuer=|Verify return code'
sudo certbot renew --dry-run
La condizione ideale è questa: HTTP risponde con redirect coerente, HTTPS presenta il certificato giusto, il rinnovo dry-run passa e il reload del servizio non produce errori. Se uno di questi punti fallisce, non è un dettaglio marginale: è un problema operativo che va corretto prima di andare avanti.
Se devi estendere il setup a più host, la regola è la stessa: automatizza il rinnovo, mantieni i file sotto controllo di root, documenta dove stanno i virtual host e conserva una procedura di rollback semplice. Il rollback, in pratica, è ripristinare il vecchio file di configurazione, ricaricare il servizio e verificare che il traffico torni al comportamento precedente. Nessun trucco, solo disciplina operativa.
Con AlmaLinux 9, TLS/SSL non richiede inventiva: richiede ordine. Se la base è solida, il certificato diventa un componente banale del sistema. Ed è esattamente così che deve essere.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.