Tre pannelli web per Debian: hosting nginx, DNS authoritative, mail server. Zero Docker, zero database centrale, zero SaaS. La famiglia NetForge per chi ha deciso che self-hosted non deve fare schifo.
"Mailcow tira su 15 container, Plesk costa 600€/anno, BIND lo configuro a mano e DKIM non funziona mai al primo colpo." — ogni sysadmin nel 2026, prima di scoprire questa suite.
Tre pannelli, una filosofia, zero compromessi sulla sanità mentale.
arx, nomina e missus sono tre pannelli web autonomi che condividono la stessa filosofia, lo stesso stack tecnologico e la stessa avversione viscerale per le complicazioni inutili. Sono indipendenti: puoi installarne uno solo, due, tutti e tre o nessuno (in quest'ultimo caso però chiudi questa pagina).
Tutti e tre sono pacchetti .deb nativi per Debian 12/13. Niente Docker, niente Kubernetes, niente "container orchestration layer". Si installano con apt install come una qualunque cosa che funziona da vent'anni.
citadel
Hosting nginx + PHP + reverse proxy
i nomi
DNS authoritative su BIND9
colei che è inviata
Mail server Postfix+Dovecot+Rspamd
Sono come tre attrezzi della stessa cassetta: il martello, il cacciavite, la pinza. Ognuno fa una cosa sola. Non esiste il "martello che fa anche da cacciavite e fischietta": esiste il martello, e funziona benissimo perché fa solo il martello. arx ospita siti, nomina serve DNS, missus consegna mail. Punto.
Un VPS Debian, tre servizi essenziali, e uno scenario che non ha soluzioni decenti.
Hai un VPS Debian. Vuoi: ospitare 5 siti, servire DNS authoritative per 3 domini, ricevere mail per 2 domini. Operazioni triviali singolarmente, sintesi disastrosa nell'insieme. Le opzioni sul mercato:
rsync /srv/ + apt install + rehydratetar -czf di una cartellaDocker è un grande strumento. Ma per un VPS singolo con 3 servizi, aggiungere un container runtime, un demone Docker, una rete bridge, un sistema di volumi e 7 immagini significa aggiungere 6 layer di astrazione che non ti servono. Quando alle 3 di notte un sito non risponde, vuoi nginx -t e journalctl -u nginx, non docker exec -it nginx-container-7f8a /bin/sh seguito da "perché questo container non vede l'altro?".
Pannello hosting per siti statici, PHP e reverse proxy. Su un VPS, fortificato di default.
arx (lat.) — cittadella, fortezza. Un piccolo posto dove i tuoi siti vivono ben difesi.
Un dashboard web in Python per gestire siti nginx su un singolo VPS Debian 13. Tre tipi di sito (statico, PHP, reverse proxy), sicurezza reale di default, niente database centrale.
Statico (html/css/js), PHP (con pool FPM dedicato per sito), reverse proxy (verso un'app sul backend). Senza Docker, senza orchestration.
Un utente Unix per sito, processo PHP-FPM dedicato con open_basedir, disable_functions e systemd sandbox. SSH/SFTP isolato per utente.
TLS Let's Encrypt automatico, rinnovo via timer systemd (arx-renew.timer), zero crontab -e.
Se nomina è sulla stessa macchina, arx droppa file di zona in /srv/nomina/rpz/arx-<sito>.zone e nomina li include nelle response-policy. arx non possiede mai BIND9. Senza nomina, la feature è disattivata e Squid resta il gate autoritativo.
Outbound proxy. Il traffico di ogni sito esce da una catena nftables marcata col suo UID e viene NAT-redirect su una porta Squid dedicata, che legge l'SNI in chiaro dal ClientHello e applica l'ACL del sito (allow / splice transparent / drop). Nessun MitM TLS: niente CA da fare trustare ai client.
SSH dietro VPN, con heartbeat-rollback quando chiudi la porta 22 pubblica (se non riesci più a entrare, riapre da solo).
Modalità "dietro Cloudflare": fetch automatico delle CIDR Cloudflare, configura real_ip_header CF-Connecting-IP, ban con IP veri.
Login pannello con TOTP (Google Authenticator, Aegis, ...), ogni azione amministrativa finisce in un append-only log.
Jail per sshd, nginx-auth, wp-login, panel-auth. Ban via nftables (no iptables legacy).
/tmp, /var/tmp, /dev/shm (chi ti scrive PHP malevolo non può eseguire da lì)inet, IPv4+IPv6 in un'unica regola — il "ip6tables gotcha" è impossibile per costruzioneexec, system, passthru, shell_exec, proc_open, ... default offDNS authoritative su BIND9 con un pannello che non finge che BIND non esista.
nomina (lat.) — i nomi. Ospita i nomi, e ti lascia leggere ogni configurazione che produce.
Pannello web per BIND9 authoritative su Debian 12/13. Master, slave, forward zones. DNSSEC in un click. RPZ per security filtering. Propagation check live su Cloudflare e Quad9 in parallelo.
Master (la authority), slave (replica via AXFR), forward (rigira a un altro server). Scelta per zona, non globale.
KASP (Key And Signing Policy) gestisce KSK + ZSK automaticamente. Genera, ruota, esporta DS pronto da incollare al registrar.
Response Policy Zones per filtering. Feed pronti: URLhaus, Hagezi, OISD, NetForge mining. Aggiornamento periodico, blocco al volo.
Modifichi un record? nomina interroga in parallelo 1.1.1.1, 8.8.8.8, 9.9.9.9 e ti dice chi già vede l'aggiornamento. Niente watch dig.
I file BIND su disco sono la verità. Niente database che può divergere. rsync /srv/nomina/ è il backup completo.
Per AXFR e DDNS sicuri. Il pannello genera, distribuisce, ruota le chiavi TSIG — tu non vedi mai una shared secret a mano.
zones/<zone>.db # BIND zone file — fonte autoritativa
rpz/<feed>.zone # RPZ zones (whitelist, custom, feeds)
named.conf.local # included da /etc/bind/named.conf
response-policy.conf # blocco RPZ dentro options{}
dnssec/<zone>/ # KSK + ZSK + KASP key state
keys/tsig.conf # chiavi TSIG per AXFR / DDNS
admins.json # admins pannello (Argon2id)
server.json # opzioni named-level
audit.jsonl # append-only log azioni admin
backups/ # snapshot tarball
BIND9 da solo è come un trattore senza cabina: potente ma scomodo, ti spiove addosso al primo errore di sintassi. nomina ci mette intorno una cabina che ti permette di guidarlo senza imparare il manuale O'Reilly da 800 pagine, senza nascondertelo: i file BIND restano leggibili, modificabili a mano, e nomina li rispetta.
Postfix + Dovecot + Rspamd con un pannello che non è mailcow.
missus (lat.) — "colei che è inviata". La radice di missiva. Spedisce i tuoi messaggi senza drammi.
Mail server panel per Debian. Stack tradizionale e collaudato (Postfix MTA + Dovecot IMAP/POP3 + Rspamd antispam) con dashboard web che fa quello che dovrebbe da sempre: login, vedi, click, funziona.
La mail self-hosted è il task più difficile dell'amministrazione Linux. Tradizione consolidata. Eppure le opzioni sono:
Nessuno l'ha resa facile. missus risponde a quel gap.
Genera record SPF, DKIM, DMARC pronti da copiare. Poi li interroga per dirti se sono propagati. Niente più dig +short TXT _dmarc.example.com ogni 5 minuti.
Dashboard mostra "questa mail è arrivata, è passata da queue, Rspamd ha dato score 1.2, consegnata a inbox". Niente tail -f /var/log/mail.log | grep.
I report rua= finiscono in un cruscotto built-in che ti mostra chi sta cercando di spoofare il tuo dominio. Feature che SaaS fanno pagare $20-200/mese.
Restore full, per-domain o per-mailbox. Maildir = file su disco = backup è tar. Niente lock di database.
Greylisting, postscreen, DKIM auto-signed sull'outbound, rate limit per utente. L'admin che non apre mai "Advanced" ha già un setup decente.
Filtri server-side via Sieve / pigeonhole. Le regole funzionano sul server prima che il client le veda — coerenti tra Thunderbird, K-9, web.
/etc.Tre prodotti, le stesse fondamenta. Conoscine uno, conoscili tutti.
| Componente | Tecnologia | Perché |
|---|---|---|
| Linguaggio backend | Python 3.10+ | Tutti e tre. Stessa skill, stessa codebase familiare. |
| Web framework | FastAPI + Jinja2 | Server-side rendering, asincrono dove serve, niente SPA. |
| Frontend | Vanilla HTML/CSS/JS | Zero React, zero build step, zero node_modules da 800 MB. |
| Storage stato | File su disco + JSON/SQLite minimo | Zone files BIND, Maildir, nginx conf — tutto leggibile a mano. |
| OS target | Debian 12 (bookworm) + 13 (trixie) | Solo questi. Niente Ubuntu, niente RHEL, niente "should work on Arch". |
| Packaging | .deb nativi | apt install, dipendenze risolte, postinst pulito. |
| Service manager | systemd | Unit files standard, journalctl, timer per i job periodici. |
| Firewall | nftables (family inet) | IPv4+IPv6 in un'unica ruleset. Niente legacy iptables. |
| Ban | fail2ban (backend nftables) | Jail per ssh, panel-auth, e service-specific. |
| TLS | certbot (Let's Encrypt) | standalone o DNS-01, rinnovo via timer systemd. |
| Auth pannello | Argon2id + 2FA TOTP | Niente bcrypt vecchio, niente "password in chiaro nel JSON". |
| Audit log | audit.jsonl append-only | Una riga JSON per azione, immutabile per default. |
/srv/<prodotto>/ # source of truth (state, config, dati)
/etc/<prodotto>/env # env vars (SESSION_SECRET, etc)
/var/log/<prodotto>/ # log + journalctl
/usr/lib/<prodotto>/ # venv Python + binari
/etc/systemd/system/ # unit files: <prodotto>.service + .timer
Stessa convenzione per arx, nomina e missus. Tutto sotto /srv/<prodotto>/ è ciò che ti serve per il backup. Punto.
Il sysadmin tipico mette tutti e tre i pannelli su una sola macchina (o tre LXC su un solo Proxmox). La regola operativa è semplice: un daemon, un proprietario; gli altri sono client.
| Daemon / risorsa | Posseduto da | Gli altri pannelli |
|---|---|---|
| nginx | arx | nessuno tocca /etc/nginx/ |
| BIND9 | nomina | arx droppa file di zona RPZ in /srv/nomina/rpz/arx-<sito>.zone (opt-in) |
| Postfix / Dovecot / Rspamd | missus | arx è un client SMTP submission (smarthost 127.0.0.1:587 con SASL) |
| Tabelle nftables | ognuno la sua | table inet arx, table inet nomina, table inet missus — nessuno scrive nelle altrui |
| fail2ban jails | ognuno il suo | solo /etc/fail2ban/jail.d/<prodotto>.local, mai jail.local globale |
| certbot hooks | ognuno i suoi | pre/post idempotenti, ognuno reload solo del proprio service |
nomina su una macchina che ha già arx, niente si rompe: arx non possiede BIND9, non ha mai scritto in /etc/bind/. Quando installi missus, arx smette di mandare la mail di sistema via "nessuno" (oggi via env mail null) e inizia a parlare submission al suo nuovo vicino. Stessa direzione per ogni nuovo pannello che aggiungi alla famiglia.
Plugin discovery via Python entry_points esiste in tutti e tre i pannelli. Ma il core, da solo, copre il caso d'uso al 100% — nessun plugin obbligatorio, nessuna installazione "incompleta".
Ogni pannello ha un PluginRegistry che scopre estensioni installate come pacchetti Python separati e registrati nel group arx.plugins / missus.plugins / nomina.plugins. Un plugin può contribuire route HTTP, voci di sidebar, comandi CLI, hook pre/post-apply. Il core non importa nessun plugin di default: il modulo entra nel processo solo se installato esplicitamente.
Il principio guida è core completo, plugin facoltativi:
missus, non un mini-Postfix dentro arx. Anche con plugin disponibili, certe scelte di architettura non si discutono.Tarball di /srv/arx/ + rsync verso destinazione configurata (host:path o rclone S3-like). Feature core configurabile, non plugin separato — serve a tutti, non è specializzata.
arx non possiede Postfix — né come modulo né come plugin. Configura un smarthost esterno (host/porta/SASL): missus su 127.0.0.1:587 se presente, oppure Mailgun, Postmark, AWS SES — uguale.
arx non gestisce MySQL/Postgres/Redis — né come modulo né come plugin. Bring-your-own-host (separato), le app dei siti si connettono in rete. Riduce la blast radius e separa i fault domain.
Il vero test di un pannello: trasferirlo da una macchina all'altra senza piangere.
Tutti e tre i pannelli rispettano la stessa logica: i dati vivono in /srv/<prodotto>/, e il binario sa ricostruire tutto il resto da quei dati. Migrazione = 3 comandi.
# 1. Sul nuovo VPS, installa
new$ sudo apt install ./arx_0.1.0-1_all.deb
# 2. Trasferisci /srv/arx/ dal vecchio
old$ sudo systemctl stop arx
old$ rsync -avz /srv/arx/ root@new-vps:/srv/arx/
# 3. Sul nuovo, ricostruisci configurazioni native (nginx, certbot, ...)
new$ sudo arx rehydrate
new$ sudo systemctl start arx
# Tutti i siti, tutti i certificati, tutti i pool PHP — rigenerati e attivi.
/srv/arx/ contiene siti, conf, certificati, utenti
/srv/nomina/ contiene zone, RPZ, DNSSEC keys, TSIG
/srv/missus/ contiene Maildir, domini, DKIM, alias
Un pannello è serio quando puoi spegnere il VPS, distruggerlo, comprarne un altro, fare apt install + rsync + restart, e tutto torna come prima. Mailcow ti chiede uno script di backup-restore custom. Plesk ti vende un servizio. Questi tre fanno rsync e basta.
tar -czf /backup/arx-$(date +%F).tar.gz /srv/arx/, sync remoto a Wasabi/B2/MinIO con rclone. Stessa cosa per missus e nomina, ognuno col suo /srv/<prodotto>/. Per missus c'è in più il restore per-mailbox dal pannello: utente cancella errore, recuperi solo la sua casella, non tutto il server.
Il processo è volutamente noioso. Esattamente come dovrebbe essere.
apt update && apt install e basta. L'uso commerciale (clienti paganti, produzione a scopo di lucro) richiede una licenza NetForge attiva — il pannello è identico, la licenza regola l'uso non l'accesso ai pacchetti.
# Aggiungi la chiave GPG e la lista APT (codename: bookworm o trixie)
$ curl -fsSL https://apt.netforge.it/netforge.asc | sudo tee /etc/apt/keyrings/netforge.asc
$ echo "deb [signed-by=/etc/apt/keyrings/netforge.asc] https://apt.netforge.it/free trixie main" \
| sudo tee /etc/apt/sources.list.d/netforge.list
$ sudo apt update
$ sudo apt install arx
$ sudo arx admin create selif # crea primo admin
$ sudo systemctl start arx
$ ssh -L 9443:127.0.0.1:9443 selif@vps
# Browser: http://127.0.0.1:9443/
$ sudo apt install nomina
$ sudo nomina admin create selif
$ sudo systemctl start nomina
$ ssh -L 8443:127.0.0.1:8443 selif@vps
# Browser: http://127.0.0.1:8443/
$ sudo apt install missus
$ sudo missus admin create selif
$ sudo systemctl start missus
$ ssh -L 8443:127.0.0.1:8443 root@vps
# Browser: http://127.0.0.1:8443/
ssh -L) o WireGuard (per arx, è integrato). Niente porta 9443 esposta al mondo che vada in pasto a fail2ban tutto il giorno.
L'installazione del .deb fa postinst pulito. Non ti chiede mille domande in modo TUI. Cosa esegue:
arx, nomina, missus) e gruppo/srv/<prodotto>/ con permessi 0750, owner: utente di sistema/etc/<prodotto>/env/etc/nginx/conf.d/zz-arx.conf (include marker)/etc/bind/named.conf con include di /srv/nomina/named.conf.localsystemctl enable), non avvia (lo fai tu dopo aver creato l'admin)Licenza proprietaria, dual-use. Termini binding completi su netforge.it/terms.
Telemetry — "Brave-lite". Ogni pannello effettua un ping giornaliero a ping.netforge.it con i seguenti dati e nient'altro:
0.1.3)debian-13 via /etc/os-release)0 · 1-5 · 6-20 · 21-100 · 100+ (per arx: siti; per missus: domini + caselle; per nomina: zone + zone DNSSEC)Niente install_id, niente UUID, niente correlazione per-installazione. Modello ispirato all'analytics privacy-preserving di Brave: il server non può collegare un singolo ping a una specifica installazione. Fuori dallo scope GDPR per costruzione, niente dato personale.
Opt-out in due righe se preferisci:
arx telemetry disable # missus / nomina identici
echo 'NETFORGE_TELEMETRY=off' >> /etc/arx/env
Esegui <prodotto> telemetry status per vedere esattamente cosa verrebbe mandato la prossima volta.
Per chi non vuole aprire il browser. Tutti e tre hanno la loro CLI.
| Comando | Descrizione |
|---|---|
arx admin create <user> | Crea admin pannello (chiede password) |
arx admin passwd <user> | Reset password admin |
arx site create <dominio> | Nuovo sito (chiede tipo: static/php/proxy) |
arx site list | Lista siti gestiti |
arx cert renew <dominio> | Forza rinnovo TLS |
arx rehydrate | Ricostruisce config native da /srv/arx/ |
arx backup --out FILE | Tarball completo di /srv/arx/ |
| Comando | Descrizione |
|---|---|
nomina admin create <user> | Crea admin pannello |
nomina zone add <zone> --type master | Aggiungi zona authoritative |
nomina zone list | Lista zone |
nomina dnssec enable <zone> | Genera KSK+ZSK e firma la zona |
nomina dnssec ds <zone> | Stampa DS record da incollare al registrar |
nomina propagation <zone> <record> | Check live su Cloudflare/Quad9 |
nomina rehydrate | Riscrive named.conf + zone files da /srv/nomina/ |
| Comando | Descrizione |
|---|---|
missus admin create <user> | Crea admin pannello |
missus domain add <dominio> | Aggiungi dominio mail |
missus mailbox add <user@dom> | Crea casella (chiede password) |
missus dns advice <dominio> | Stampa SPF/DKIM/DMARC da pubblicare |
missus dns verify <dominio> | Verifica live i record sul DNS |
missus queue list | Mail in coda Postfix |
missus dmarc report <dominio> | Aggregato report DMARC ricevuti |
missus restore --domain <d> --from FILE | Restore granulare |
--json per output machine-readable. Esempio: nomina zone list --json | jq '.[] | select(.dnssec == true)' per vedere solo le zone firmate.
0 = ok, 1 = errore generico, 2 = errore di sintassi/argomenti. Scriptabile con set -e tranquillamente in cron e Ansible.
Le anti-feature, dichiarate. Sapere cosa non fa uno strumento è più importante di sapere cosa fa.
tar di una cartellarsync + rehydrate"Vogliamo che sia fattibile per uno, non impressionante per cento." Tre pannelli costruiti per il sysadmin solitario, il freelance, l'agenzia da 5 persone, la PMI con un VPS. Se devi gestire 500 server, esistono altri strumenti, e vanno benissimo. Per gli altri 95% dei casi, c'è questa suite.
I comandi che ti serviranno davvero, in una pagina da stampare.
# Stato + log
$ sudo systemctl status arx
$ sudo journalctl -u arx -f
# Nuovo sito statico
$ sudo arx site create blog.example.com --type static
$ sudo arx cert issue blog.example.com
# Nuovo sito PHP (con pool FPM dedicato)
$ sudo arx site create wp.example.com --type php --php 8.3
# Reverse proxy verso un'app
$ sudo arx site create api.example.com --type proxy --backend http://127.0.0.1:3000
# Backup completo
$ sudo arx backup --out /backup/arx-$(date +%F).tar.gz
# Aggiungi zona master, poi DNSSEC
$ sudo nomina zone add example.com --type master
$ sudo nomina dnssec enable example.com
$ sudo nomina dnssec ds example.com
# → copia il DS record nel pannello del registrar
# Modifica record + check propagazione live
$ sudo nomina record set example.com www A 1.2.3.4
$ sudo nomina propagation example.com www
# → mostra: 1.1.1.1 OK, 8.8.8.8 OK, 9.9.9.9 in attesa...
# Slave su un secondary box
$ sudo nomina zone add example.com --type slave --master 1.2.3.4
# RPZ: blocca un dominio per i client che usano questo resolver
$ sudo nomina rpz block bad-domain.com
# Setup primo dominio + DNS advice
$ sudo missus domain add example.com
$ sudo missus dns advice example.com
# → stampa SPF, DKIM, DMARC pronti da pubblicare
# Pubblicati i record? Verifica live
$ sudo missus dns verify example.com
# → SPF: OK, DKIM: OK, DMARC: OK (policy: quarantine)
# Crea casella
$ sudo missus mailbox add [email protected]
# Coda Postfix (chi sta ancora aspettando di partire)
$ sudo missus queue list
$ sudo missus queue flush
# Aggregato DMARC settimanale
$ sudo missus dmarc report example.com --since 7d
# Backup giornaliero, cron in /etc/cron.daily/netforge-backup
#!/bin/bash
DATE=$(date +%F)
DEST=/backup
mkdir -p $DEST
for svc in arx nomina missus; do
if [ -d /srv/$svc ]; then
tar -czf $DEST/$svc-$DATE.tar.gz /srv/$svc/
fi
done
# Sync remoto (Wasabi/B2/MinIO)
rclone sync $DEST remote:nf-backups/ --max-age 30d
# Su un VPS nuovo, dopo apt install <prodotto>
$ sudo systemctl stop arx
$ sudo tar -xzf arx-2026-04-30.tar.gz -C /
$ sudo arx rehydrate
$ sudo systemctl start arx
# Stesso pattern per nomina e missus.
# Pannello non risponde — tail dei log
$ sudo journalctl -u arx -n 100 --no-pager
# nginx complain — test sintassi
$ sudo nginx -t
# BIND complain — check config
$ sudo named-checkconf
$ sudo named-checkzone example.com /srv/nomina/zones/example.com.db
# Postfix — check generale
$ sudo postfix check
$ sudo journalctl -u postfix -f
# Audit log: chi ha fatto cosa, quando
$ sudo tail -f /srv/arx/audit.jsonl | jq
I tre prodotti sono in early development — le release pubbliche escono via netforge.it. Ne stiamo parlando, non vendendo: la guida è qui per dirti che esiste qualcuno che la pensa così sul self-hosted.
netforge.it →