Quando i servizi di casa diventano tre o quattro (Home Assistant, Nextcloud, un’app per le foto, un pannello di monitoraggio), aprire una porta sul router per ognuno è la ricetta per perdere il controllo. Un reverse proxy risolve il problema: riceve tutte le richieste sulla porta 443, le smista in base al nome di dominio (ha.esempio.it, cloud.esempio.it) e gestisce da solo i certificati HTTPS di Let’s Encrypt. In questa guida realizziamo lo stesso esempio con i due strumenti più usati in ambito domestico: Nginx Proxy Manager, tutto a interfaccia grafica, e Caddy, che si configura con un file di testo di poche righe.
In breve
- Tempo: 30–45 minuti per strumento, esclusa la propagazione DNS.
- Difficoltà: media.
- Cosa serve: un server Linux con Docker e Docker Compose, un dominio di cui gestite i DNS, le porte 80 e 443 inoltrate dal router al server, almeno un servizio già funzionante in rete locale.
Versioni di riferimento: procedura verificata sulla documentazione ufficiale al 4 novembre 2026, con Nginx Proxy Manager 2.16.0 (immagine jc21/nginx-proxy-manager), Caddy 2.11 (immagine ufficiale caddy), Home Assistant 2026.10 e Nextcloud All-in-One.
Nginx Proxy Manager o Caddy: quale scegliere
| Nginx Proxy Manager | Caddy | |
|---|---|---|
| Configurazione | Interfaccia web sulla porta 81 | File di testo (Caddyfile) |
| Certificati | Let’s Encrypt con una casella da spuntare, anche con sfida DNS | HTTPS automatico di default per ogni nome di dominio |
| Websocket | Opzione Websockets Support per ogni host | Supportati senza configurazione |
| Accesso ristretto | Access Lists con regole allow/deny e password | Matcher client_ip, anche con la scorciatoia private_ranges |
| Backup della configurazione | Cartelle data e letsencrypt | Il Caddyfile più il volume dei dati |
Il nostro consiglio: Nginx Proxy Manager se volete vedere tutto in una pagina e non toccare file; Caddy se preferite una configurazione che si legge in dieci secondi, si versiona con git e si copia su un altro server. Non installateli entrambi sullo stesso host: si contenderebbero le porte 80 e 443.
Prima di iniziare: DNS, porte e un’avvertenza
- DNS: dal pannello del vostro registrar create un record A per ogni sottodominio (o un record jolly
*.esempio.it) che punti all’IP pubblico di casa. Con IP dinamico vi serve un servizio DDNS. - Porte: inoltrate dal router al server le porte TCP 80 e 443. La 80 serve alla sfida HTTP di Let’s Encrypt. La procedura per TIM, Vodafone, Fastweb e Fritz!Box è in https://hardwarfare.it/guide/tutorial/aprire-porte-router-tim-vodafone-fastweb-fritzbox/.
- CGNAT: se il vostro operatore non vi dà un IP pubblico, l’inoltro non funziona. Le alternative (tunnel, VPN, IPv6) sono in https://hardwarfare.it/guide-tecniche/guide-reti/cgnat-ip-pubblico-ddns-tailscale-cloudflare/.
- Docker: se non lo avete ancora, partite da https://hardwarfare.it/ai-software/linux/installare-docker-compose-ubuntu-debian/.
Attenzione: un reverse proxy rende i servizi raggiungibili da Internet. Esponete solo applicazioni con un login robusto e aggiornate regolarmente; le interfacce di amministrazione (quella di Nginx Proxy Manager sulla porta 81, Proxmox, il router) non vanno mai pubblicate. Proteggete anche il server stesso: accesso SSH con chiavi, firewall e fail2ban.
Un concetto che evita metà degli errori 502
La documentazione di Caddy lo dice in modo esplicito e vale anche per Nginx Proxy Manager: dentro un container Docker, localhost significa “questo container”, non “questo computer”. Se il proxy gira in un container e il servizio di destinazione è un altro container sulla stessa rete Docker, usate il nome del servizio e la porta interna (ad esempio app:3000, anche se all’esterno è pubblicata come 3030). Se il servizio gira sull’host o in rete host, come Home Assistant Container, usate l’IP di rete locale del server. Negli esempi che seguono scriviamo IP_SERVER.
Preparare Home Assistant ad accettare il proxy
Home Assistant blocca le richieste che arrivano da un reverse proxy non dichiarato. Dalla versione 2026.8 le impostazioni non si scrivono più nel blocco http: di configuration.yaml: andate in Impostazioni > Sistema > Rete, sezione HTTP server, attivate Trust X-Forwarded-For e inserite l’IP del proxy in Trusted proxies. Se indicate una rete, usate l’indirizzo di rete (192.168.1.0/24) e non quello di un host (192.168.1.50/24). Al salvataggio Home Assistant si riavvia e chiede di confermare le nuove impostazioni entro 5 minuti, altrimenti torna alle precedenti. Ricordate anche la porta: 8123 per Container, mentre da 2026.8 Home Assistant OS usa la 80 per impostazione predefinita.
Opzione A: Nginx Proxy Manager
1. Avvio del container
Create una cartella (ad esempio /opt/npm) e un file compose.yaml basato sull’esempio ufficiale:
services:
app:
image: 'jc21/nginx-proxy-manager:2.16.0'
restart: unless-stopped
environment:
TZ: "Europe/Rome"
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
cd /opt/npm
sudo docker compose up -dSe l’host non ha IPv6 attivo, la documentazione indica di aggiungere DISABLE_IPV6: 'true' tra le variabili d’ambiente.
Verifica: dopo circa un minuto l’interfaccia risponde su http://IP_SERVER:81 e mostra la schermata di creazione del primo utente amministratore. Scegliete una password lunga e unica. La porta 81 non va inoltrata dal router.
2. Il primo proxy host
- Aprite Proxy Hosts e aggiungete un nuovo Proxy Host.
- In Domain Names scrivete
ha.TUO_DOMINIO; Schemehttp; Forward Hostname / IP l’IP del server di Home Assistant; Forward Port 8123 (o 80 per HA OS). - Spuntate Websockets Support, indispensabile per Home Assistant, e Block Common Exploits.
- Nella scheda SSL scegliete Request a new Certificate, poi attivate Force SSL e HTTP/2 Support. HSTS Enabled attivatelo solo quando siete sicuri che il dominio resterà in HTTPS: i browser lo memorizzano.
Verifica: da una rete esterna (lo smartphone con il Wi-Fi spento) aprite https://ha.TUO_DOMINIO: il lucchetto deve indicare un certificato Let’s Encrypt e la dashboard deve aggiornarsi in tempo reale. Se la pagina si carica ma resta ferma su “connessione in corso”, mancano i websocket.
3. Servizi solo per la rete di casa
Per un servizio che volete raggiungere solo da casa (o via VPN), create in Access Lists una lista con una regola Allow per la vostra rete, ad esempio 192.168.1.0/24: quando esiste almeno una regola, Nginx Proxy Manager aggiunge in fondo un “deny all”. Poi associate la lista al proxy host. Ricordate che con la rete bridge di Docker il proxy deve vedere l’IP reale del client: verificatelo nei log prima di fidarvi della regola.
Opzione B: Caddy
1. Avvio del container
Struttura consigliata dalla documentazione: una cartella conf con dentro il Caddyfile, e due volumi per dati e configurazione. Il volume /data è importante: contiene i certificati e non va perso.
services:
caddy:
image: caddy:2.11
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./conf:/etc/caddy
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:La porta 443/udp serve a HTTP/3. Il nostro esempio non serve file statici, quindi abbiamo omesso il volume ./site:/srv dell’esempio ufficiale.
2. Il Caddyfile
Lo stesso scenario di prima, più Nextcloud All-in-One (che dietro un proxy si avvia con APACHE_PORT=11000, come spieghiamo in https://hardwarfare.it/ai-software/linux/installare-nextcloud-docker-aio-https/) e un servizio interno raggiungibile solo dalla rete locale:
ha.TUO_DOMINIO {
reverse_proxy IP_SERVER:8123
}
cloud.TUO_DOMINIO {
reverse_proxy IP_SERVER:11000
}
interno.TUO_DOMINIO {
@esterni not client_ip private_ranges
abort @esterni
reverse_proxy IP_SERVER:PORTA_SERVIZIO
header {
Strict-Transport-Security max-age=31536000;
X-Content-Type-Options nosniff
}
}Non serve altro: per ogni nome di dominio Caddy ottiene e rinnova il certificato da solo, passa i websocket senza configurazione e imposta le intestazioni X-Forwarded-For, X-Forwarded-Proto e X-Forwarded-Host. La scorciatoia private_ranges comprende 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 127.0.0.1/8, fd00::/8 e ::1. Come per Nginx Proxy Manager, controllate nei log che Caddy veda l’IP reale dei client: se vedesse l’indirizzo del gateway Docker (172.x, che rientra in private_ranges, come può accadere per le connessioni IPv6 inoltrate dal proxy di Docker), la regola lascerebbe passare tutti.
cd /opt/caddy
sudo docker compose up -dDopo ogni modifica al Caddyfile ricaricate la configurazione senza interrompere il servizio:
sudo docker compose exec -w /etc/caddy caddy caddy reloadVerifica: curl -I https://ha.TUO_DOMINIO deve rispondere con un codice HTTP valido e senza errori di certificato; da una rete esterna https://interno.TUO_DOMINIO deve chiudere la connessione, mentre da casa deve aprirsi. Se qualcosa non va, i log si leggono con sudo docker compose logs caddy.
Se qualcosa va storto
- 502 Bad Gateway: il proxy non raggiunge il servizio. Nove volte su dieci è
localhostusato dentro un container, una porta sbagliata (quella pubblicata invece di quella interna, o viceversa) o un firewall sull’host che blocca il traffico dalla rete Docker. Provate dall’hostcurl -I http://IP_SERVER:PORTA: se non risponde nemmeno lì, il problema non è il proxy. - Home Assistant risponde con 400 Bad Request: mancano Trust X-Forwarded-For e Trusted proxies, oppure l’IP del proxy non è quello che avete inserito (con Docker in rete bridge è un indirizzo della rete interna di Docker, di solito nell’intervallo 172.16.0.0/12, non quello del server: lo leggete nel log degli accessi negati di Home Assistant).
- “There is no server available at this domain” in Nginx Proxy Manager alla richiesta del certificato: il dominio non punta al vostro IP o la porta 80 non è inoltrata. Controllate il record DNS e l’inoltro sul router; con CGNAT la sfida HTTP non può riuscire e serve la sfida DNS (Use DNS Challenge).
- Il certificato non arriva con Caddy: stesse cause. Evitate di riavviare in continuazione il container: Let’s Encrypt applica limiti al numero di richieste, e un volume
/dataperso costringe a richiedere tutto da capo. - Nextcloud mostra avvisi sul proxy: la documentazione di AIO raccomanda che il proxy usi la porta 443 e, se il proxy sta su un’altra macchina, di indicare l’IP privato del server AIO al posto di
localhost.
Come tornare indietro
Fermate il proxy con sudo docker compose down nella sua cartella e rimuovete gli inoltri delle porte 80 e 443 dal router: i servizi tornano raggiungibili solo in rete locale, ai loro indirizzi e porte originali. Se avete attivato HSTS, i browser che hanno già visitato il dominio continueranno a pretendere HTTPS fino alla scadenza indicata in max-age: è il motivo per cui conviene attivarlo per ultimo. Le cartelle data e letsencrypt di Nginx Proxy Manager, o il volume caddy_data, conservano i certificati se volete ripartire.
La nostra lettura
Per un uso domestico Caddy è difficile da battere: la configurazione dell’esempio completo sta in quindici righe e non c’è nulla da cliccare per i certificati. Nginx Proxy Manager resta la scelta migliore per chi vuole un pannello, ed è molto più sicuro di una serie di porte aperte sul router. In entrambi i casi la regola è la stessa: il proxy è la porta d’ingresso di casa, e va trattato con la stessa cura della porta vera.
Fonti
- Nginx Proxy Manager – Guide
- Nginx Proxy Manager – Advanced Configuration
- Caddy – Keep Caddy Running
- Caddy – reverse_proxy
- Caddy – Request matchers
- Caddy – header
- Home Assistant – HTTP
- Nextcloud AIO – Reverse proxy
Immagine di copertina: EthernetSwitch.jpg di Raysonho @ Open Grid Scheduler / Grid Engine, licenza CC0, via Wikimedia Commons; elaborazione grafica HardWarfare.
Articolo redatto con il supporto di strumenti di intelligenza artificiale e verificato dalla redazione. Come usiamo l'AI · Come lavoriamo
