Come ospitare il server VPN NetBird su un VPS
Guida a NetBird self-hosted su un VPS: DNS e TLS, script quickstart con versione fissata, setup keys per peer senza intervento e confronto con Headscale.
Cosa ti offre l'hosting autonomo del server VPN NetBird
L'hosting autonomo del server VPN NetBird colloca il control plane su un VPS di tua proprietà: è il componente che conserva l'elenco dei peer, decide quale macchina può raggiungere ciascuna altra macchina e aiuta due peer a trovarsi dietro NAT (network address translation). I tunnel restano comunque WireGuard, con traffico cifrato direttamente tra le tue macchine. La differenza è che nessuna azienda esterna conserva l'inventario dei tuoi dispositivi o gestisce il tuo flusso di accesso. È importante capire quale vantaggio offre questa configurazione, perché un control plane gestito da terzi non conserva comunque le chiavi che cifrano il traffico e cosa può realmente fare un server di coordinamento se viene compromesso è un elenco più limitato di quanto molti pensino prima di informarsi.
NetBird si colloca tra due concetti che potresti già conoscere. È una rete overlay mesh, quindi i peer si connettono tra loro invece di inviare tutto attraverso un unico gateway. È inoltre self-hostable end to end, quindi si contrappone a Headscale, il server di controllo Tailscale self-hosted. Se hai sempre usato soltanto un tunnel con gateway singolo, leggi prima la differenza tra WireGuard semplice e una rete overlay mesh, perché questo modello mentale rende utile il resto della guida.
Se quello che ti serve è un unico server dal quale esce tutto il traffico, una mesh introduce una complessità superiore a quella necessaria. Una VPN WireGuard semplice su un singolo VPS oppure un exit node Tailscale svolgono questo compito con una gestione molto più semplice. Se invece l'obiettivo è raggiungere una singola rete privata anziché collegare le macchine tra loro, un subnet router Tailscale su un VPS pubblicizza quell'intervallo a un tailnet che già utilizzi, senza richiedere nessuno dei componenti descritti di seguito.
Cosa esegue effettivamente lo stack
Il layout è cambiato di recente e la maggior parte delle guide meno recenti descrive quello precedente. Ad agosto 2026, nella release v0.76.2, lo script quickstart scrive per impostazione predefinita un file Compose con tre servizi.
netbird-servercontiene l'API di gestione, il servizio di segnalazione, il relay con un listener STUN integrato e un identity provider integrato. Nelle release precedenti questi componenti erano container separati e l'identity provider era un'installazione Zitadel distinta, che era necessario preparare prima.dashboardè la console web di amministrazione.traefikgestisce la terminazione TLS (transport layer security) e richiede un certificato a Let's Encrypt al primo avvio.
Esistono altri due servizi, che restano disattivati finché non si risponde affermativamente a una richiesta. Il servizio NetBird Proxy pubblica i servizi interni su hostname pubblici. CrowdSec filtra il traffico abusivo. Nessuno dei due è necessario per creare una mesh funzionante e, su un server di piccole dimensioni, entrambi consumano memoria.
Se provieni da wg-easy in un singolo container Docker, questo comporta un aumento del numero di componenti. Offre però policy di accesso e account per singolo utente, oltre a peer che si connettono direttamente tra loro invece di passare da un unico gateway.
Prerequisiti
Un nome di dominio pubblico è obbligatorio. Il dashboard, l'API e il relay usano tutti HTTPS sulla porta 443. Traefik ottiene il certificato da Let's Encrypt tramite una challenge HTTP, che richiede un nome risolto verso questo VPS da Internet. In questo flusso un semplice indirizzo IP non funziona.
Crea un record A, netbird.example.com, che punti all'indirizzo IPv4 pubblico del VPS, quindi attendi la propagazione prima di eseguire qualsiasi comando.
dig +short netbird.example.comDeve restituire l'indirizzo del server. Se esegui l'installer prima della propagazione DNS, la richiesta del certificato fallisce al primo avvio. I tentativi ripetuti di validazione non riusciti possono inoltre raggiungere i limiti di frequenza di Let's Encrypt. In quel caso devi attendere un'ora prima di riprovare.
Tre porte devono essere raggiungibili da Internet: TCP 80 per la challenge del certificato e il redirect a HTTPS, TCP 443 per il dashboard, l'API, il traffico signal e relay, e UDP 3478 per STUN.
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 3478/udp
sudo ufw reload
sudo ufw statusAprile anche nel firewall di rete del provider. Nella maggior parte dei pannelli VPS è un controllo separato. Questa è la causa per cui un server il cui ufw status locale sembra configurato correttamente continua a rifiutare le connessioni.
STUN (session traversal utilities for NAT) consente a un peer di conoscere l'indirizzo pubblico e la porta assegnati dal proprio NAT. In questo modo due peer possono tentare di creare un tunnel diretto. Se blocchi UDP 3478, i peer continuano a connettersi tramite il relay su TCP 443, quindi non è evidente che qualcosa non funzioni. Tuttavia, su ogni peer ottieni Connection type: Relayed e tutto il traffico attraversa il VPS invece di passare direttamente da un peer all'altro.
Per quanto riguarda il software, servono Docker con il plugin Compose v2, oltre a jq e curl. Lo script verifica la presenza di tutti questi componenti e si interrompe se ne manca uno. Se Docker è appena stato installato su questo server, configura prima Docker Compose funzionante sul VPS.
Porte se non usi il reverse proxy incluso
Senza Traefik, i singoli servizi vengono esposti direttamente e l'elenco delle porte si amplia:
- TCP 80, redirect HTTP
- TCP 443, HTTPS
- TCP 33073, gRPC di gestione
- TCP 10000, gRPC signal
- TCP 33080, relay tramite WebSocket o QUIC
- UDP 3478, STUN
Scegli questa configurazione solo se il server termina già TLS per un altro servizio. In caso contrario, Traefik incluso richiede meno regole e riduce il rischio di errori.
Installare il server NetBird con lo script di quickstart
Il comando documentato in una sola riga invia direttamente l'ultima release a una shell:
curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh | bashFissa invece una versione. latest cambia, quindi lo stesso comando eseguito a due settimane di distanza installa due versioni diverse e sul disco non resta alcuna indicazione di quale versione abbia scritto la configurazione. Scarica una release contrassegnata da un tag, leggila e poi eseguila.
mkdir -p ~/netbird
cd ~/netbird
curl -fsSL -o getting-started.sh \
https://github.com/netbirdio/netbird/releases/download/v0.76.2/getting-started.sh
less getting-started.sh
bash getting-started.shLo script chiede prima il dominio:
Enter the domain you want to use for NetBird (e.g. netbird.my-domain.com):Poi chiede come gestire TLS:
Which reverse proxy will you use?
[0] Traefik (recommended - automatic TLS, included in Docker Compose)
[1] Existing Traefik (labels for external Traefik instance)
[2] Nginx (generates config template)
[3] Nginx Proxy Manager (generates config + instructions)
[4] External Caddy (generates Caddyfile snippet)
[5] Other/Manual (displays setup documentation)
Enter choice [0-5] (default: 0):Scegli [0]. Le opzioni da 2 a 5 scrivono uno snippet di configurazione e lasciano a te il collegamento dei componenti. È la scelta corretta su un server che esegue già un proxy, ma non su un server nuovo. L'opzione 0 chiede quindi un indirizzo email Let's Encrypt, utilizzato per le notifiche di scadenza.
Alla prima installazione, rispondi no al servizio NetBird Proxy. Richiede altri due record DNS, proxy.netbird.example.com e il wildcard *.proxy.netbird.example.com, ma non serve per una semplice mesh. Rispondi no anche a CrowdSec. Entrambi possono essere aggiunti in seguito.
Lo script scrive nella directory corrente: docker-compose.yml, config.yaml con modalità 600, dashboard.env e traefik-dynamic.yaml quando scegli Traefik integrato. Tratta questa directory come stato persistente da conservare, perché config.yaml contiene la chiave che cifra i dati nello store. Perderla non è un problema che una reinstallazione possa risolvere.
docker compose ps
docker compose logs -f netbird-serverOgni servizio dovrebbe leggere running e il log del server dovrebbe stabilizzarsi, senza riavviarsi in loop. Controlla separatamente il certificato:
docker compose logs traefik | grep -i acmeACME (automatic certificate management environment) è il protocollo che Traefik usa per ottenere il certificato. Gli errori in questa fase dipendono quasi sempre dal DNS o dalla porta 80 chiusa.
Crea il primo account amministratore
Apri https://netbird.example.com. In una nuova installazione viene visualizzata la pagina di configurazione invece del modulo di accesso. Inserisci un indirizzo email, un nome e una password, quindi fai clic su Create Account. Questo diventa il primo account amministratore e la pagina reindirizza al modulo di accesso.
L'account viene archiviato nello user store interno di NetBird, gestito da un identity provider integrato nel container netbird-server. Non è coinvolto alcun servizio esterno. Questa è la differenza principale rispetto a NetBird self-hosted di un anno fa: un'installazione funzionante richiedeva prima di configurare Zitadel o Keycloak e copiare quattro valori OIDC (OpenID Connect) in setup.env, altrimenti il servizio non si avviava.
Se nel browser viene visualizzato un avviso relativo al certificato invece della pagina di configurazione, il certificato non è stato emesso. Risolvi il problema prima di proseguire, perché la dashboard comunica con l'API usando lo stesso hostname e, con un certificato non valido, può comportarsi in modo difficilmente interpretabile.
Collega il primo peer
Installa il client su una macchina Linux qualsiasi, incluso lo stesso VPS se vuoi inserirlo nella mesh:
curl -fsSL https://pkgs.netbird.io/install.sh | shSu Debian e Ubuntu, questo script configura il repository dei pacchetti di NetBird e installa quindi il client tramite apt. In questo modo, il pacchetto viene gestito dal package manager. Se non vuoi eseguire uno script tramite una pipe verso una shell, salvalo prima con curl -fsSL -o install.sh https://pkgs.netbird.io/install.sh e leggilo prima di eseguire sh install.sh. In ogni caso, verifica cosa è stato installato:
apt-cache policy netbirdnetbird è il client da riga di comando e il demone. netbird-ui è l'applicazione nell'area di notifica del desktop e non serve su un server headless.
Ora configura il client per usare il tuo server:
sudo netbird up --management-url https://netbird.example.comSe ometti --management-url, il client si registra presso il servizio ospitato di NetBird, perché questa è l'impostazione predefinita compilata nel programma. Il comando viene comunque eseguito correttamente, la macchina riceve comunque un indirizzo e la dashboard self-hosted rimane vuota. Quasi tutti incappano in questo problema almeno una volta.
Il comando stampa un URL da aprire in un browser per completare l'accesso. Dopo:
netbird status
ip addr show wt0Leggi quattro righe da netbird status: Management: Connected, Signal: Connected, una riga Relays: che elenca tutti i relay disponibili e un NetBird IP: nell'intervallo della rete overlay. wt0 è l'interfaccia WireGuard creata da NetBird e dovrebbe avere lo stesso indirizzo.
Collegare una seconda macchina senza intervento manuale con una chiave di configurazione
Il login tramite browser non funziona per una macchina senza browser e senza un operatore davanti. Una chiave di configurazione è un token di preautenticazione che registra una macchina senza il passaggio interattivo. Creane una nella dashboard, alla voce Setup Keys.
Esistono due tipi di chiave. Una chiave monouso autentica esattamente una macchina e viene quindi consumata. Una chiave riutilizzabile registra più macchine, con un limite facoltativo sul numero massimo. Entrambe hanno una scadenza ed entrambe possono assegnare automaticamente il nuovo peer a un gruppo, applicando le regole di accesso del gruppo non appena la macchina viene visualizzata.
sudo netbird up --setup-key <SETUP-KEY> \
--management-url https://netbird.example.com \
--hostname build-runner-01--hostname imposta il nome visualizzato nella dashboard. Senza questo parametro, il peer usa il nome assegnato dalla macchina; avere un insieme di voci chiamate tutte ubuntu non è utile.
Per i container e gli agenti di build di breve durata, contrassegna la chiave come ephemeral durante la creazione. I peer registrati con una chiave ephemeral vengono rimossi automaticamente dopo più di 10 minuti offline, evitando di accumulare voci non più attive nell'elenco dei peer.
Prima di basare il progetto sulle setup keys, considera un limite importante: la scadenza o l'eliminazione di una chiave impedisce le nuove registrazioni, ma non disconnette le macchine che l'hanno già utilizzata. Per rimuovere l'accesso di una macchina devi rimuovere il relativo peer.
Ti serve ancora un identity provider separato?
Per una piccola installazione, no. Lo user store integrato gestisce gli account creati dalla dashboard ed è sufficiente per pochi utenti.
Un identity provider esterno è utile se ne utilizzi già uno e non vuoi mantenere un secondo elenco di utenti. NetBird accetta qualsiasi provider che supporti OIDC. Registra un client OIDC confidential nel tuo provider, quindi aggiungilo nella dashboard di NetBird inserendo quattro valori: nome, client ID, client secret e issuer. NetBird fornisce un redirect URL da incollare nuovamente nel provider. Sono disponibili integrazioni dedicate per Google, Microsoft Entra ID, Okta, Zitadel, Keycloak, Authentik e Pocket ID; per tutti gli altri provider puoi usare OIDC generico. Se utilizzi già Authentik come single sign-on self-hosted, questa configurazione consente di mantenere un solo elenco di account invece di due.
Il login locale resta disponibile dopo l'aggiunta di un provider e ogni provider configurato viene visualizzato nella pagina di accesso. Mantieni un account admin locale con una password robusta. Se la configurazione OIDC non funziona, avrai comunque un modo per accedere.
NetBird o Headscale: quale control plane utilizzare?
Entrambi rimuovono la stessa dipendenza: il server di controllo gestito che, in alternativa, i client contatterebbero periodicamente. Non sono però progetti equivalenti.
Headscale reimplementa il server di controllo di Tailscale e consente di continuare a usare i client ufficiali di Tailscale. Non dispone di una console web ufficiale. Gli utenti e le chiavi di pre-autenticazione si gestiscono con il comando headscale usando un file di configurazione. Esistono interfacce web della community, ma non fanno parte del progetto. Questa soluzione è adatta a chi vuole mantenere lo stato nei file e gestire le modifiche con il version control.
NetBird include l'intero prodotto: il proprio client, la propria dashboard, un identity provider integrato e le policy di accesso modificabili dal browser. Sul VPS richiede quindi più componenti ed è molto più semplice da affidare a un collega che non aprirà mai un terminale.
Scegli Headscale se utilizzi già i client Tailscale o vuoi il control plane più minimale possibile. Scegli NetBird se più persone devono gestire i peer e vuoi una console e SSO senza doverle assemblare. Prima di scegliere, verifica cosa copre realmente il piano gratuito di Tailscale, perché un gruppo che rientra in sei utenti con dispositivi illimitati non paga nulla per un control plane gestito e potrebbe non avere alcun motivo per gestirne uno in proprio. Oltre questa soglia, il costo cresce in base al numero di persone e non al numero di macchine; quindi calcolare quanto costerebbe Tailscale al tuo gruppo fornisce una cifra da confrontare con il VPS e con le ore richieste da questa infrastruttura.
Dimensioni minime del VPS
Il minimo documentato è 1 CPU e 2 GB di memoria. Le note di NetBird indicano attualmente un requisito minimo di circa 1 GB di RAM, ora che la gestione degli utenti è locale, rispetto ai 2 GB-4 GB richiesti dalla configurazione precedente, che includeva un'installazione completa di Zitadel. Scegli 2 GB. Questa riserva di risorse consente di scaricare nuove immagini durante un aggiornamento mentre quelle precedenti sono ancora presenti sul disco.
Su un server con risorse limitate è sicuro omettere tre componenti. Rifiuta il servizio NetBird Proxy, che serve a pubblicare servizi interni su hostname pubblici e non riguarda la connessione tra peer. Rifiuta CrowdSec, che potrai aggiungere in seguito su un server esposto, invece di installarlo fin dal primo giorno. Mantieni lo storage SQLite predefinito nel volume netbird_data e passa a PostgreSQL solo quando distribuisci i componenti su più macchine o riscontri problemi reali di concorrenza. La documentazione indica questa migrazione come un'operazione eseguibile in un secondo momento.
Il relay è l'unico componente che non puoi rimuovere. Due peer il cui NAT assegna una porta diversa per ogni destinazione non riusciranno mai a stabilire un tunnel diretto. Il relay è quindi l'unico percorso che consente loro di comunicare. Disabilitarlo consente di risparmiare pochissima memoria e interrompe le connessioni in un modo difficile da diagnosticare.
Quando un solo server non è più sufficiente, i relay sono i primi componenti da spostare. Un relay autonomo viene eseguito con NB_LISTEN_ADDRESS, NB_EXPOSED_ADDRESS, NB_AUTH_SECRET e NB_ENABLE_STUN. Il secret condiviso deve essere identico sul relay e sul server principale. In caso contrario, i client non riescono ad autenticarsi al relay.
Modalità di errore e cosa verrà visualizzato
La dashboard mostra un avviso relativo al certificato. Traefik non ha ottenuto un certificato. Esegui docker compose logs traefik | grep -i acme. Le cause possibili sono due. dig +short netbird.example.com non restituisce ancora questo VPS oppure la porta TCP 80 è chiusa in un punto tra Let's Encrypt e il container, di solito nel firewall di rete del provider e non su ufw. Correggi la causa prima di riprovare in un ciclo, perché le validazioni non riuscite sono soggette a limiti di frequenza e per un'ora non potrai più effettuare tentativi.
Il client indica di essersi connesso, ma la dashboard è vuota. Il client si è registrato al servizio ospitato da NetBird perché mancava --management-url. Esegui netbird status --detail e leggi la riga Management:, che indica il server con cui sta comunicando effettivamente. Se visualizzi Management: Connected to https://api.netbird.io:443, il client si è connesso al cloud. Esegui sudo netbird down, quindi di nuovo sudo netbird up --management-url https://netbird.example.com.
Ogni peer mostra Connection type: Relayed. Non si stanno creando tunnel diretti, quindi tutto il traffico attraversa il VPS e aggiunge un hop di latenza. Controlla UDP 3478 nel firewall del VPS e nel firewall del provider, perché STUN consente a un peer di determinare il proprio indirizzo e la propria porta pubblici. netbird status --detail stampa anche Direct: false e i tipi di candidati ICE (interactive connectivity establishment) per ogni peer, mostrando fino a che punto è arrivato il tentativo. In alcune reti l'unico risultato possibile è il relay e non c'è alcun problema.
Un peer entra nella rete mesh, ma non riesce a raggiungere nulla. Far parte della mesh non significa che due peer possano comunicare. Questa possibilità è determinata dalle policy di accesso e un gruppo a cui non è associata alcuna policy non può raggiungere nessuna risorsa. Controlla la policy nella dashboard prima di eseguire il troubleshooting di route e firewall.
netbird status segnala un problema del daemon. Il servizio non è in esecuzione. Usa sudo netbird service status e sudo netbird service start. I log del client si trovano in /var/log/netbird/client.log. Per i problemi che non riesci a classificare, netbird debug bundle --anonymize --system-info raccoglie in un unico archivio i log, lo stato, le route, le impostazioni DNS e lo stato del firewall.
Backup e aggiornamenti
Due elementi sostengono l'intera installazione: la directory che contiene docker-compose.yml e config.yaml e il volume Docker che contiene il database e le chiavi di crittografia. Eseguire il backup di entrambi insieme. config.yaml contiene la chiave che crittografa i dati nell'archivio, quindi una copia del database senza questa chiave non può essere ripristinata in modo leggibile.
docker volume ls
docker compose down
sudo tar czf netbird-config.tgz -C ~ netbird
docker run --rm -v netbird_netbird_data:/data -v "$PWD":/backup \
alpine tar czf /backup/netbird-data.tgz -C /data .
docker compose up -dCompose antepone ai nomi dei volumi il nome della directory del progetto, quindi il volume documentato come netbird_data di solito viene visualizzato come netbird_netbird_data. Eseguire prima docker volume ls e usare il nome restituito, altrimenti docker run crea in modo silenzioso un volume vuoto e non archivia nulla. Conservare gli archivi fuori dal VPS. Se si dispone già di uno strumento di backup, restic o BorgBackup gestisce la copia offsite.
L'aggiornamento del server consiste nel recuperare le nuove immagini e ricreare i container:
docker compose pull
docker compose up -d
docker compose psPrima di affidarsi a questa procedura, eseguire docker compose config | grep image:. Qualsiasi tag con valore latest deve essere sostituito con una versione specifica, per lo stesso motivo per cui è stato fissato lo script di installazione: è necessario sapere quale versione è in esecuzione e avere una versione a cui tornare se un aggiornamento causa problemi. I client si aggiornano tramite il package manager con cui sono stati installati.
FAQ
Mi serve un identity provider personale per eseguire NetBird in modalità self-hosted?
No. Le release attuali includono un archivio utenti integrato. Puoi quindi creare il primo account amministratore nel browser all'indirizzo https://netbird.example.com e aggiungere successivamente altri utenti dalla dashboard. Un provider OIDC esterno è facoltativo e può essere aggiunto in seguito usando quattro valori: nome, ID client, secret client e issuer. Le guide che indicano di installare Zitadel o Keycloak prima di NetBird descrivono una configurazione che non è più necessaria. Seguirle aggiunge un servizio da gestire.
Perché tutti i miei peer mostrano Connection type: Relayed?
Non si stanno creando connessioni dirette. Il traffico passa quindi dal relay sul tuo VPS. La causa più comune è il blocco di UDP 3478, la porta STUN che i peer usano per rilevare il proprio indirizzo e la propria porta pubblici. Aprila nel firewall del VPS e nel firewall di rete separato del provider. Esegui nuovamente netbird status --detail e leggi la riga Direct:. In una rete il cui NAT assegna una porta diversa per ogni destinazione, l'uso del relay è l'unico risultato possibile e non indica una configurazione errata.
Il client si è connesso, ma la dashboard non mostra peer. Che cosa è successo?
Il client si è registrato presso il servizio hosted di NetBird invece che presso il tuo server. Questo accade quando --management-url viene omesso. netbird status --detail stampa il server con cui sta comunicando nella riga Management:. Un valore come https://api.netbird.io:443 lo conferma. Esegui sudo netbird down, quindi sudo netbird up --management-url https://netbird.example.com. Il peer comparirà nella dashboard.
Qual è la differenza tra NetBird self-hosted e Headscale?
Entrambi sostituiscono un server di controllo hosted con uno gestito autonomamente. Headscale è soltanto un control plane: lo gestisci con il comando headscale e un file di configurazione, non dispone di una console web ufficiale e controlla i client Tailscale ufficiali. NetBird include il proprio client, una dashboard amministrativa e l'integrazione con un identity provider nello stesso stack. Headscale è più semplice da eseguire e mantiene lo stato nei file. NetBird è più facile da affidare a persone che non usano un terminale.
Di quali dimensioni deve essere il VPS per un server NetBird self-hosted?
Il minimo documentato è 1 CPU e 2 GB di memoria. 2 GB è quindi la dimensione da acquistare. Il limite pratico è sceso a circa 1 GB nelle release recenti, perché l'identity provider è ora integrato invece di essere un deployment separato. Durante l'installazione, rifiuta i servizi proxy e CrowdSec opzionali. Mantieni inoltre l'archivio SQLite predefinito finché non hai realmente bisogno di PostgreSQL.