Una sola porta d'ingresso per ogni strumento interno: un pattern di self-hosting
Come far girare task board, dashboard, un vault delle password e altro dietro un unico reverse proxy: DNS wildcard, container sotto systemd, accessi a strati, rinomine sicure.

Ogni team operativo accumula piccoli strumenti. Una task board, un server di dashboard, una console per i container, un vault delle password, un paio di web app interne che qualcuno ha scritto. Ognuno nasce sulla propria porta con il proprio certificato e la propria idea di autenticazione, e nel giro di un anno nessuno sa più quali sono esposti, quali sono aggiornati, o quali hanno ancora un certificato valido. Questo è il pattern che usiamo per far girare un intero insieme di strumenti interni come un unico servizio ben tenuto: una porta d'ingresso, un modo di avviare le cose, una policy di accesso.
La forma dello stack
Il pattern ha quattro livelli, e ciascuno ha un compito:
- DNS: un nome wildcard, come
*.tools.example.com, che punta a un unico host. - Reverse proxy: Traefik su quell'host, che termina il TLS e instrada ogni hostname al container giusto.
- Container: ogni strumento nel proprio container Podman su una rete container privata, senza porte pubblicate sull'host tranne quelle del proxy.
- Supervisione: systemd avvia, riavvia e ordina tutto, così lo stack sopravvive a un riavvio senza intervento umano.
Con questo in piedi, aggiungere uno strumento è una breve checklist invece di un progetto: avviate un container sulla rete, aggiungete una route, fatto. Nessun nuovo buco nel firewall, nessun nuovo record DNS e nessuna nuova richiesta di certificato.
DNS: un wildcard, poi dimenticatevene
Un record wildcard significa che tasks.tools.example.com, grafana.tools.example.com e vault.tools.example.com risolvono tutti all'host del proxy senza che nessuno tocchi più il DNS. Abbinatelo a un certificato wildcard per lo stesso nome, e ogni nuovo strumento nasce con un TLS valido.
Tenete il wildcard su un sottodominio dedicato. Non volete che qualunquecosa.example.com atterri sul vostro host di tooling.
Il proxy: route come file che potete leggere
Traefik può scoprire le route dalle etichette dei container o da semplici file di configurazione. Per uno stack piccolo e longevo preferiamo i file: sono facili da revisionare, facili da mettere sotto controllo di versione, e non cambiano perché qualcuno ha riavviato un container con etichette diverse. Una route per un task manager appare così:
http:
routers:
tasks:
rule: "Host(`tasks.tools.example.com`)"
entryPoints: [websecure]
service: tasks
middlewares: [mgmt-only]
tls: {}
services:
tasks:
loadBalancer:
servers: [{ url: "http://tasks:3456" }]
middlewares:
mgmt-only:
ipAllowList:
sourceRange: ["192.0.2.0/24"]
Il middleware è la parte importante. Il proxy è l'unico punto in cui decidete chi può raggiungere uno strumento, quindi mettete la decisione lì.
Accesso: due serrature, non una
Gli strumenti interni hanno i propri login, e la loro qualità varia. Non fate affidamento solo su quelli. Mettete davanti due controlli a strati:
- Una allow list per sorgente sul proxy, limitata alle reti da cui il vostro team lavora davvero. Espandete ogni CIDR prima di scriverlo e rileggetelo dopo. Una lunghezza di prefisso digitata male può trasformare l'intervallo di un singolo ufficio in una larga parte di internet:
python3 -c "import ipaddress,sys; n=ipaddress.ip_network(sys.argv[1],strict=False); print(n, n[0], '->', n[-1], n.num_addresses)" 192.0.2.0/24
- Un middleware di autenticazione (basic auth su TLS come minimo, o forward authentication verso il vostro identity provider) per gli strumenti che non dovrebbero essere raggiungibili nemmeno dall'interno senza una seconda credenziale.
Il vault delle password merita una riflessione a parte. Un server compatibile con Bitwarden come Vaultwarden conserva i contenuti del vault cifrati dai client, quindi il server non li detiene mai in forma leggibile. È una proprietà forte, ma non elimina la necessità di limitare chi può raggiungere il server.
Container sotto systemd
Avviare i container a mano funziona fino al primo riavvio. Podman si integra con systemd tramite Quadlet: descrivete il container in un piccolo file unit e systemd lo tratta come qualunque altro servizio.
# /etc/containers/systemd/tasks.container
[Unit]
Description=Task manager
After=network-online.target
[Container]
Image=docker.io/vikunja/vikunja:<pinned-tag>
Network=tools.network
Volume=/srv/tools/tasks:/app/vikunja/files:Z
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
Dopo systemctl daemon-reload, systemctl start tasks lo esegue, e da quel momento parte al boot. Fissate i tag delle immagini invece di seguire latest, così un upgrade è una decisione che prendete voi, con un dump e un rollback pronti, invece di qualcosa che vi capita al prossimo riavvio.
Tenete SELinux in enforcing. Etichettate ogni volume per il container che lo possiede (:Z per un volume privato, :z per uno che più container devono condividere).
Rinominare senza rompere nulla
Prima o poi uno strumento si sposta: un nuovo host, un nuovo dominio, un nome più ordinato. Tenete il vecchio nome funzionante facendo rispondere al proxy con un redirect permanente verso il nuovo. Usate 308 Permanent Redirect invece di 301, perché un 308 dice ai client di ripetere lo stesso metodo e lo stesso body al nuovo indirizzo.
C'è una trappola che morde gli script, non i browser. I browser seguono i redirect. Molti client da riga di comando e molte librerie no, a meno che non glielo diciate. Uno script che invia una POST al vecchio nome riceve un 308, non lo segue, e va avanti. Non è stato creato nulla, nulla è fallito in modo rumoroso, e se lo script controlla solo che qualcosa abbia risposto, riporta successo. Con curl, usate -L per seguire, e controllate sempre codice di stato e body:
curl -s -o out.json -w '%{http_code}\n' -X POST https://tasks.tools.example.com/api/v1/...
Un body di risposta con le parole «Permanent Redirect» dove vi aspettavate JSON è il segnale. Quando rinominate, cercate nei vostri script e nelle integrazioni il vecchio nome e aggiornateli, e tenete il redirect solo come rete di sicurezza.
Backup, monitoraggio e aggiornamenti
Monitorate ogni route dall'esterno dell'host per la pagina attesa, non semplicemente per una risposta, e aggiornate uno strumento alla volta tenendo l'immagine precedente finché la nuova non ha girato per un po'.
Una checklist per il vostro tooling
- Sapete elencare ogni strumento interno, il suo hostname e chi può raggiungerlo?
- Qualche strumento pubblica la propria porta sull'host o su internet, aggirando il proxy?
- Tutti i vostri intervalli in allow list sono stretti quanto pensate? Espandeteli e guardate.
- I vostri container tornano su da soli dopo un riavvio?
- I vostri script controllano i codici di stato, o solo che qualcosa abbia risposto?
- Quando avete ripristinato l'ultima volta il vostro vault delle password?
Una porta d'ingresso, una policy e un modo di avviare le cose trasformano un cassetto di strumenti sparsi in un servizio su cui potete ragionare.
Se volete gli strumenti del vostro team gestiti così, sulla vostra istanza, i nostri ingegneri possono aiutarvi.
Related
- /what-we-do/platforms/operations-tooling/
- /what-we-do/operations/hardening-baseline/
Pubblicato il 24 agosto 2026.
Tutte le note dal campo