netbird Documentation

Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy netbird on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name netbird -p 8087:8087 --restart always influxdb:2
Configured Services & Ports
⚙️ ingest
image: build locally
🔌 Ports: 8087:8087
⚙️ influxdb
image: influxdb:2
⚙️ grafana
image: grafana/grafana:11.6.0
🔌 Ports: 3001:3000
docker-compose.yml
yaml (docker-compose.yml)
version: '3.8'

services:
  ingest:
    container_name: ingest
    build:
      context: ./ingest
    ports:
      - "8087:8087"
    environment:
      - INGEST_LISTEN_ADDR=:8087
      - INFLUXDB_URL=http://influxdb:8086/api/v2/write?org=netbird&bucket=metrics&precision=ns
      - INFLUXDB_TOKEN=${INFLUXDB_ADMIN_TOKEN:?required}
      - CONFIG_METRICS_SERVER_URL=${CONFIG_METRICS_SERVER_URL:-}
      - CONFIG_VERSION_SINCE=${CONFIG_VERSION_SINCE:-0.0.0}
      - CONFIG_VERSION_UNTIL=${CONFIG_VERSION_UNTIL:-99.99.99}
      - CONFIG_PERIOD_MINUTES=${CONFIG_PERIOD_MINUTES:-5}
    depends_on:
      - influxdb
    restart: unless-stopped
    networks:
      - metrics

  influxdb:
    container_name: influxdb
    image: influxdb:2
    # No ports exposed — only accessible within the metrics network
    volumes:
      - influxdb-data:/var/lib/influxdb2
      - ./influxdb/scripts:/docker-entrypoint-initdb.d
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_ADMIN_PASSWORD:?required}
      - DOCKER_INFLUXDB_INIT_ORG=netbird
      - DOCKER_INFLUXDB_INIT_BUCKET=metrics
      - DOCKER_INFLUXDB_INIT_RETENTION=365d
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${INFLUXDB_ADMIN_TOKEN:-}
    restart: unless-stopped
    networks:
      - metrics

  grafana:
    container_name: grafana
    image: grafana/grafana:11.6.0
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER:-admin}
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:?required}
      - GF_USERS_ALLOW_SIGN_UP=false
      - GF_INSTALL_PLUGINS=
      - INFLUXDB_ADMIN_TOKEN=${INFLUXDB_ADMIN_TOKEN:-}
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    depends_on:
      - influxdb
    restart: unless-stopped
    networks:
      - metrics

volumes:
  influxdb-data:
  grafana-data:

networks:
  metrics:
    driver: bridge

1. Project Overview & Quickstart (netbirdio/netbird)

File: README.md

🤖 NetBird Agent Network (Beta)

Identity-aware access control for AI agents — keyless access to LLM APIs and private
resources over the encrypted NetBird tunnel. See agent-network/ or
read the docs at netbird.ai.

NetBird combines a configuration-free peer-to-peer private network and a centralized access control system in a single platform, making it easy to create secure private networks for your organization or home.

Connect. NetBird creates a WireGuard-based overlay network that automatically connects your machines over an encrypted tunnel, leaving behind the hassle of opening ports, complex firewall rules, VPN gateways, and so forth.

Secure. NetBird enables secure remote access by applying granular access policies while allowing you to manage them intuitively from a single place. Works universally on any infrastructure.

https://github.com/user-attachments/assets/10cec749-bb56-4ab3-97af-4e38850108d2

Self-host NetBird (video)

Key features

Connectivity Management Security Automation Platforms
✓ Kernel WireGuard ✓ Admin Web UI ✓ SSO & MFA support ✓ Public API ✓ Linux
✓ Peer-to-peer connections ✓ Auto peer discovery and configuration ✓ Access control: groups & rules ✓ Setup keys for bulk provisioning ✓ macOS
✓ Connection relay fallback ✓ IdP integrations ✓ Activity logging ✓ Self-hosting quickstart script ✓ Windows
✓ Routes to external networks ✓ Private DNS ✓ Traffic events ✓ IdP groups sync with JWT ✓ Android
✓ Domain-based DNS routes ✓ Custom DNS zones ✓ Device posture checks ✓ Terraform provider ✓ Android TV
✓ Exit nodes ✓ Multiuser support ✓ Peer-to-peer encryption ✓ Ansible collection ✓ iOS
✓ IPv6 dual-stack overlay ✓ Multi-account profile switching ✓ SSH with central access policies ✓ Apple TV
✓ Browser SSH & RDP ✓ Quantum-resistance with Rosenpass ✓ FreeBSD
✓ Reverse proxy with auto-TLS ✓ Periodic re-authentication ✓ pfSense
✓ OPNsense
✓ MikroTik RouterOS
✓ OpenWRT
✓ Synology
✓ TrueNAS
✓ Proxmox
✓ Raspberry Pi
✓ Serverless
✓ Container

Quickstart with NetBird Cloud

Quickstart with self-hosted NetBird

This is the quickest way to try self-hosted NetBird. It should take around 5 minutes to get started if you already have a public domain and a VM. Follow the Advanced guide with a custom identity provider for installations with different IdPs.

Infrastructure requirements:

  • A Linux VM with at least 1 CPU and 2 GB of memory.
  • The VM should be publicly accessible on TCP ports 80 and 443 and UDP port 3478.
  • A public domain name pointing to the VM.

Software requirements:

Steps

  • Download and run the installation script:
bash
export NETBIRD_DOMAIN=netbird.example.com; curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh | bash

A bit on NetBird internals

  • Every machine in the network runs the NetBird agent, which manages WireGuard.
  • Every agent connects to the Management Service, which holds network state, manages peer IPs, and distributes updates to agents.
  • Agents use ICE (via pion/ice) to discover connection candidates for peer-to-peer connections.
  • Candidates are discovered with the help of STUN servers.
  • Agents negotiate a connection through the Signal Service, exchanging end-to-end encrypted messages with candidates.
  • When NAT traversal fails (e.g. mobile carrier-grade NAT) and a direct p2p connection isn't possible, the system falls back to a Relay Service and a secure WireGuard tunnel is established through it.

See a complete architecture overview for details.

Community projects

Note: The main branch may be in an unstable or even broken state during development.
For stable versions, see releases.

Support acknowledgement

In November 2022, NetBird joined the StartUpSecure program sponsored by the Federal Ministry of Education and Research of the Federal Republic of Germany. Together with the CISPA Helmholtz Center for Information Security, NetBird brings security best practices and simplicity to private networking.

Acknowledgements

We build on open source technologies like WireGuard®, Pion ICE, and Rosenpass. We greatly appreciate the work these projects are doing, and we'd love it if you could support them too (e.g., by starring or contributing).

This repository is licensed under the BSD-3-Clause license, which applies to all parts of the repository except for the directories management/, signal/ and relay/.
Those directories are licensed under the GNU Affero General Public License version 3.0 (AGPLv3). See the respective LICENSE files inside each directory.

WireGuard and the WireGuard logo are registered trademarks of Jason A. Donenfeld.


File: client/iface/mocks/README.md

Mocks

To generate (or refresh) mocks from iface package interfaces please install mockgen.
Run this command to update PacketFilter mock:

bash
mockgen -destination iface/mocks/filter.go -package mocks github.com/netbirdio/netbird/iface PacketFilter

File: client/internal/acl/mocks/README.md

Mocks

To generate (or refresh) mocks from acl package please install mockgen.
Run this command from the ./client/internal/acl folder to update iface mapper interface mock:

bash
mockgen -destination mocks/iface_mapper.go -package mocks . IFaceMapper

File: client/internal/ebpf/ebpf/src/readme.md

DNS forwarder

The agent attach the XDP program to the lo device. We can not use fake address in eBPF because the
traffic does not appear in the eBPF program. The program capture the traffic on wg_ip:53 and
overwrite in it the destination port to 5053.

Debug

The CONFIG_BPF_EVENTS kernel module is required for bpf_printk.
Apply this code to use bpf_printk

text
#define bpf_printk(fmt, ...)                                                   \
  ({                                                                           \
    char ____fmt[] = fmt;                                                      \
    bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__);                 \
  })

File: infrastructure_files/observability/grafana/dashboards/readme.md

Dashboard variables

  1. datasource: Select Prometheus server
  2. cluster: Filter NetBird instances by cluster
  3. environment: Filter by environment (dev, staging, UAT, prod)
  4. job: Select target NetBird instance if multiple are running
  5. host: Filter metrics by host

NOTE:

  • Your installation may have a subset of these variables.
  • The dashboard expects exported_endpoint instead of endpoint in HTTP request metrics.

File: management/README.md

netbird Management Server

netbird management server will control and synchronize peers configuration within your Netbird account and network.

Command Options

The CLI accepts the command management with the following options:

shell
start Netbird Management Server

Usage:
  netbird-mgmt management [flags]

Flags:
      --cert-file string            Location of your SSL certificate. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect
      --cert-key string             Location of your SSL certificate private key. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect
      --datadir string              server data directory location
  -h, --help                        help for management
      --letsencrypt-domain string   a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS
      --port int                    server port to listen on (default 33073)

Global Flags:
      --config string      Netbird config file location to write new config to (default "/etc/netbird")
      --log-file string    sets Netbird log path. If console is specified the the log will be output to stdout (default "/var/log/netbird/management.log")
      --log-level string    (default "info")

Run Management service (Docker)

You can run service in 2 modes - with TLS or without (not recommended).

Run with TLS (Let's Encrypt).

By specifying the --letsencrypt-domain the daemon will handle SSL certificate request and configuration.

In the following example 33073 is the management service default port, and 443 will be used as port for Let's Encrypt challenge and HTTP API.

The server where you are running a container has to have a public IP (for Let's Encrypt certificate challenge).

Replace with your server's public domain (e.g. mydomain.com or subdomain sub.mydomain.com).

bash
# create a volume
docker volume create netbird-mgmt
# run the docker container
docker run -d --name netbird-management \
-p 33073:33073  \
-p 443:443  \
-v netbird-mgmt:/var/lib/netbird  \
-v ./config.json:/etc/netbird/config.json  \
netbirdio/management:latest \
--letsencrypt-domain <YOUR-DOMAIN>

An example of config.json can be found here management.json

Trigger Let's encrypt certificate generation:

bash
curl https://<YOUR-DOMAIN>

The certificate will be persisted in the datadir/letsencrypt/ folder (e.g. /var/lib/netbird/letsencrypt/) inside the container.

Make sure that the datadir is mapped to some folder on a host machine. In case you used the volume command, you can run the following to retrieve the Mountpoint:

shell
docker volume inspect netbird-mgmt
[
    {
        "CreatedAt": "2021-07-25T20:45:28Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/mgmt/_data",
        "Name": "netbird-mgmt",
        "Options": {},
        "Scope": "local"
    }
]

Consequent restarts of the container will pick up previously generated certificate so there is no need to trigger certificate generation with the curl command on every restart.

Run without TLS.

bash
# create a volume
docker volume create netbird-mgmt
# run the docker container
docker run -d --name netbird-management \
-p 33073:33073  \
-v netbird-mgmt:/var/lib/netbird  \
-v ./config.json:/etc/netbird/config.json  \
netbirdio/management:latest

Debug tag

We also publish a docker image with the debug tag which has the log-level set to default, plus it uses the gcr.io/distroless/base:debug image that can be used with docker exec in order to run some commands in the Management container.

shell
shell $ docker run -d --name netbird-management-debug \
-p 33073:33073  \
-v netbird-mgmt:/var/lib/netbird  \
-v ./config.json:/etc/netbird/config.json  \
netbirdio/management:debug-latest

shell $ docker exec -ti netbird-management-debug /bin/sh
container-shell $

For development purposes:

Install golang gRpc tools:

bash
#!/bin/bash
go install google.golang.org/protobuf/cmd/[email protected]
go install google.golang.org/grpc/cmd/[email protected]

Generate gRpc code:

bash
#!/bin/bash
protoc -I proto/ proto/management.proto --go_out=. --go-grpc_out=.

File: sharedsock/example/README.md

How to run

This will only work on Linux

  1. Run netcat listening on the UDP port 51820. This is going to be our external process:
bash
nc -kluvw 1 51820
  1. Build and run the example Go code:
bash
go build -o sharedsock && sudo ./sharedsock
  1. Test the logic by sending a STUN binding request
bash
STUN_PACKET="000100002112A4425454" 
echo -n $STUN_PACKET | xxd -r -p | nc -u -w 1 localhost 51820
  1. You should see a similar output of the Go program. Note that you'll see some binary output in the netcat server too. This is due to the fact that kernel copies packets to both processes.
bash
read a STUN packet of size 18 from ...
  1. Send a non-STUN packet
bash
echo -n 'hello' |  nc -u -w 1 localhost 51820
  1. The Go program won't print anything.

File: signal/README.md

netbird Signal Server

This is a netbird signal-exchange server and client library to exchange
connection information between netbird peers

Command Options

The CLI accepts the the following options:

shell
start Netbird Signal Server daemon

Usage:
  netbird-signal run [flags]

Flags:
  -h, --help                        help for run
      --letsencrypt-domain string   a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS
      --port int                    Server port to listen on (e.g. 10000) (default 10000)
      --ssl-dir string              server ssl directory location. *Required only for Let's Encrypt certificates. (default "/var/lib/netbird/")
      --cert-file string            Location of your SSL certificate. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect
      --cert-key string             Location of your SSL certificate private key. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect

Global Flags:
      --log-file string    sets Netbird log path. If console is specified the the log will be output to stdout (default "/var/log/netbird/signal.log")
      --log-level string    (default "info")

Running the Signal service (Docker)

We have packed the Signal server into docker image. You can pull the image from
Docker Hub and execute it with the
following commands:

shell
docker pull netbirdio/signal:latest
docker run -d --name netbird-signal -p 10000:10000 netbirdio/signal:latest

The default log-level is set to INFO, if you need you can change it using by
updating the docker cmd as followed:

shell
docker run -d --name netbird-signal -p 10000:10000 netbirdio/signal:latest --log-level DEBUG

Run with TLS (Let's Encrypt).

By specifying the --letsencrypt-domain the daemon will handle SSL
certificate request and configuration.

In the following example 10000 is the signal service default port,
and 443 will be used as port for
Let's Encrypt challenge and HTTP API.

The server where you are running a container has to have a public IP (for
Let's Encrypt certificate challenge).

Replace <YOUR-DOMAIN> with your server's public domain (e.g. mydomain.com or
subdomain sub.mydomain.com).

bash
# create a volume
docker volume create netbird-signal
# run the docker container
docker run -d --name netbird-signal \
-p 10000:10000  \
-p 443:443  \
-v netbird-signal:/var/lib/netbird  \
netbirdio/signal:latest \
--letsencrypt-domain <YOUR-DOMAIN>

Metrics

The Signal Server exposes the following metrics in Prometheus format:

Application Metrics

  • active_peers: A Gauge metric that tracks the number of active peers
    connected to the server.
  • peer_connection_duration_seconds: A Histogram metric that measures the
    duration a peer was connected in seconds.
  • registrations_total: A Counter metric that counts the total number of peer
    registrations.
  • deregistrations_total: A Counter metric that counts the total number of
    peer deregistrations.
  • registration_failures_total: A Counter metric that counts the total number
    of failed peer registrations. Possible
    labels:
    • error: The type of error that caused the registration failure (
      e.g., missing_id, missing_meta, failed_header).
  • registration_delay_milliseconds: A Histogram metric that measures the time
    it took to register a peer in
    milliseconds.
  • get_registration_delay_milliseconds: A Histogram metric that measures the time
    it took to get a peer registration in
    milliseconds.
  • messages_forwarded_total: A Counter metric that counts the total number of
    messages forwarded between peers.
  • message_forward_failures_total: A Counter metric that counts the total
    number of failed message forwards between
    peers. Possible labels:
    • type: The type of failure (
      e.g., error, not_connected, not_registered).
  • message_forward_latency_milliseconds: A Histogram metric that measures the
    latency of message forwarding between
    peers in milliseconds.

Endpoint

The metrics are exposed in Prometheus format on the /metrics endpoint. By
default, the server listens on port 9090,
so the full endpoint would be:

http://:9090/metrics

For development purposes:

The project uses gRpc library and defines service in protobuf file located in:
proto/signalexchange.proto

To build the project you have to do the following things.

Install golang gRpc tools:

bash
#!/bin/bash
go install google.golang.org/protobuf/cmd/[email protected]
go install google.golang.org/grpc/cmd/[email protected]

Generate gRpc code:

bash
#!/bin/bash
protoc -I proto/ proto/signalexchange.proto --go_out=. --go-grpc_out=.

2. Official Technical Reference & Guides (netbirdio/docs)

The NetBird documentation

This repository contains assets required to build the documentation website for NetBird. It is built using Next.js with MDX support, a modern React framework for building static and dynamic websites.

We're glad that you want to contribute!

Requirements

  • node 16
  • npm 8+

Installation

text
$ npm install

Local Development

text
$ npm run dev

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

Contributing to the docs

You can click the Fork button in the upper-right area of the screen to create a copy of this repository in your GitHub account. This copy is called a fork. Make any changes you want in your fork, and when you are ready to send those changes to us, go to your fork and create a new pull request to let us know about it.

Once your pull request is created, a NetBird reviewer will take responsibility for providing clear, actionable feedback. As the owner of the pull request, it is your responsibility to modify your pull request to address the feedback that has been provided to you by the NetBird reviewer.

Also, note that you may end up having more than one NetBird reviewer provide you feedback or you may end up getting feedback from a NetBird reviewer that is different than the one initially assigned to provide you feedback.

Furthermore, in some cases, one of your reviewers might ask for a technical review from a NetBird author when needed. Reviewers will do their best to provide feedback in a timely fashion but response time can vary based on circumstances.

Code of conduct

Participation in the NetBird community is governed by the NetBirds' Code of Conduct.

Components and Use

This documentation uses several custom MDX components. Here's a guide to the most commonly used components:

Alert Components

Use these components to highlight important information:

Note

Displays informational content with an orange theme:

mdx
import {Note} from "@/components/mdx"

<Note>
    NetBird is an **[open-source](https://github.com/netbirdio/netbird)** project and can be self-hosted.
    See a comparison between the self-hosted and cloud-hosted versions [here](/selfhosted/self-hosted-vs-cloud-netbird).
</Note>

Warning

Displays warning content with a red theme:

mdx
import {Warning} from "@/components/mdx"

<Warning>
    The API is still in Beta state so some errors might not be handled properly yet.
</Warning>

Success

Displays success messages with a green theme:

mdx
import {Success} from "@/components/mdx"

<Success>
    Your configuration has been successfully applied.
</Success>

Tiles Component

Displays a grid of clickable cards with hover effects. Perfect for listing related resources or guides:

mdx
import {Tiles} from "@/components/Tiles"

<Tiles 
  title="About NetBird" 
  id="about-netbird" 
  items={[
    {
      href: '/about-netbird/how-netbird-works',
      name: 'How NetBird Works',
    },
    {
      href: '/about-netbird/netbird-vs-traditional-vpn',
      name: 'NetBird vs. Traditional VPN',
    },
  ]} 
/>

Props:

  • title (string, required): The heading title for the tiles section
  • id (string, optional): Optional id for the heading anchor
  • items (array, required): Array of objects with href, name, and description
  • buttonText (string, optional): Button text (defaults to "Read more" - currently unused as cards are fully clickable)

YouTube Component

Embeds YouTube videos with customizable parameters:

mdx
import {YouTube} from "@/components/YouTube"

<YouTube videoId="CFa7SY4Up9k" />

// With custom parameters
<YouTube 
  videoId="CFa7SY4Up9k" 
  title="Video Title"
  start={175}
  color="white"
  modestbranding={1}
  rel={1}
/>

// Or use a URL instead of videoId
<YouTube url="https://www.youtube.com/watch?v=CFa7SY4Up9k" />

Props:

  • videoId (string): YouTube video ID
  • url (string): YouTube URL (alternative to videoId)
  • title (string, optional): Video title
  • start (number, optional): Start time in seconds
  • color (string, optional): Progress bar color - 'white' or 'red' (default: 'white')
  • modestbranding (number, optional): Reduces YouTube branding - 0 or 1 (default: 1)
  • controls (number, optional): Show/hide controls - 0, 1, or 2 (default: 1)
  • rel (number, optional): Show related videos - 0 or 1 (default: 1)

Button Component

Creates styled buttons with multiple variants:

mdx
import {Button} from "@/components/Button"

// Primary button (default)

  Get started


// Secondary button

  Learn more


// Outline button

  Explore


// Text button

  Read more


// With left arrow

  Back

Props:

  • variant (string, optional): Button style - 'primary', 'secondary', 'filled', 'outline', or 'text' (default: 'primary')
  • href (string, optional): Link URL (creates a link if provided, otherwise renders as button)
  • arrow (string, optional): Arrow icon - 'left' or 'right'
  • children (required): Button text content

Other Common Components

Row and Col

Create two-column layouts:

mdx
import {Row, Col} from "@/components/mdx"

<Row>
  <Col>
    Left column content
  </Col>
  <Col sticky>
    Right column content (sticky on scroll)
  </Col>
</Row>

Properties and Property

Define API properties or configuration options:

mdx
import {Properties, Property} from "@/components/mdx"


  
    Your API key for authentication.
  
  
    Request timeout in seconds (default: 30).

Badge

Displays small status badges:

mdx
import {Badge} from "@/components/mdx"

New
Beta

Code Blocks

Code syntax highlighting (automatically available):

mdx
\`\`\`bash
npm install
npm run dev
\`\`\`

// Or use code groups for multiple languages
<CodeGroup>
  ```bash title="Installation"
  npm install
yarn title="installation"
yarn install
```

Thank you

NetBird thrives on community participation, and we appreciate your contributions to our website and our documentation!