Run your own Autonomous System (AS) with BGP peering and a WireGuard mesh network.
Create an independent AS that:
- Announces your IP block to the Internet via BGP
- Provides connectivity to distributed nodes through a WireGuard mesh
- Enables you to host services accessible from the public Internet
INTERNET
│
│ BGP (your AS announced globally)
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ ISP / IXP (datacenter) │
│ (not under your control) │
└─────────────────────────────────────────────────────────────────────────────┘
│
│ BGP peering (eBGP)
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ BORDER ROUTER (your AS) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ BIRD │ │ netclient │ │ Egress GW │ │
│ │ AS 65000 │ │ (WireGuard)│ │ announces │ │
│ │ │ │ │ │ external │ │
│ │ announces: │ │ mesh IP: │ │ routes to │ │
│ │ ${MESH_ │ │ from range │ │ mesh │ │
│ │ ADDRESS_ │ │ │ │ │ │
│ │ RANGE} │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ Connects your AS to both: Internet (BGP) and your mesh (WireGuard) │
└─────────────────────────────────────────────────────────────────────────────┘
│
│ WireGuard mesh (Netmaker)
▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Mesh Node 1 │ │ Mesh Node 2 │ │ Mesh Node N │
│ IP from │ │ IP from │ │ IP from │
│ ${MESH_ │ │ ${MESH_ │ │ ${MESH_ │
│ ADDRESS_ │ │ ADDRESS_ │ │ ADDRESS_ │
│ RANGE} │ │ RANGE} │ │ RANGE} │
│ netclient │ │ netclient │ │ netclient │
│ (anywhere) │ │ (anywhere) │ │ (anywhere) │
└──────────────────┘ └──────────────────┘ └──────────────────┘
- A mesh node (IP from ${MESH_ADDRESS_RANGE}) wants to reach the Internet
- Traffic goes to the border router (egress gateway)
- Border router forwards to ISP via BGP peering
- Response comes back the same path
- Someone on the Internet wants to reach a mesh node IP
- BGP routing directs traffic to your ISP (your AS is announced)
- ISP sends to your border router
- Border router forwards via WireGuard mesh to the node
The border router must be configured as an egress gateway in Netmaker. This announces external routes (e.g., 0.0.0.0/0 or specific ranges) to all mesh nodes, so they know how to reach the Internet through the border router.
Without this, mesh nodes wouldn't know how to route responses back to external IPs.
| Component | Location | Purpose |
|---|---|---|
deploy/netmaker/ |
Public server | Netmaker control plane (mesh management) |
deploy/bird-border/ |
Datacenter | Border router: BGP + mesh gateway |
deploy/netclient/ |
Any location | Standalone mesh node |
Central control plane for the WireGuard mesh. Runs on a public server with:
- Netmaker API (behind nginx with Let's Encrypt)
- Mosquitto MQTT broker
- WireGuard coordination (no traffic passes through it)
The critical component that bridges your AS to the Internet:
- BIRD: BGP daemon, announces your IP block to the ISP
- netclient: Connects to the mesh
- Egress Gateway: Announces external routes to mesh nodes
Simple nodes that join the mesh:
- Run netclient to establish WireGuard tunnels
- Receive routes from egress gateway
- Can host services accessible from the Internet
| Network | CIDR | Purpose |
|---|---|---|
| Your AS block | ${MESH_ADDRESS_RANGE} | Public IPs announced via BGP |
| Mesh overlay | (same as above) | WireGuard mesh uses your public block |
| BGP peering | ${BGP_NETWORK_RANGE} | Link between you and ISP |
Note: In this design, mesh IPs are your public IPs. This means services on mesh nodes are directly reachable from the Internet once BGP is established.
- IP allocation: Obtain IP block from RIR (LACNIC, ARIN, etc.) or lease from provider
- AS number: Obtain from RIR or use private AS (64512-65534) for testing
- BGP peering: Agreement with ISP or IXP for BGP session
- Public server: For Netmaker control plane
- Datacenter presence: For border router (colocation or VPS with BGP support)
Before deploying, copy and customize environment files:
# Root configuration (optional - for shared values)
cp .env.example .env
# Component-specific configuration
cp deploy/netmaker/.env.example deploy/netmaker/.env
cp deploy/bird-border/.env.example deploy/bird-border/.env
cp deploy/netclient/.env.example deploy/netclient/.env
cp deploy/rpi-isp/.env.example deploy/rpi-isp/.env # if using mock ISPEdit each .env file with your specific values. See .env.example files for documentation.
cd deploy/netmaker
cp .env.example .env
# Edit .env with your domain and credentials
# Required: SERVER_HOST, MASTER_KEY
docker compose up -dSee deploy/netmaker/README.md for full instructions.
source .env
curl -X POST "https://${SERVER_HOST}/api/networks" \
-H "Authorization: Bearer $MASTER_KEY" \
-H "Content-Type: application/json" \
-d "{\"netid\": \"${MESH_NETWORK_ID}\", \"addressrange\": \"${MESH_ADDRESS_RANGE}\"}"cd deploy/bird-border
cp .env.example .env
# Add ENROLLMENT_TOKEN from Netmaker
docker compose up -dSee deploy/bird-border/README.md for BGP configuration.
Make the border router announce external routes to the mesh:
# Via Netmaker API
curl -X POST "https://${SERVER_HOST}/api/nodes/${MESH_NETWORK_ID}/<node-id>/creategateway" \
-H "Authorization: Bearer $MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"ranges":["0.0.0.0/0"],"natEnabled":"no"}'Or use Netmaker UI: Node → Edit → Enable Egress Gateway → Add range 0.0.0.0/0
cd deploy/netclient
cp .env.example .env
# Add ENROLLMENT_TOKEN
docker compose up -dFor development without real BGP peering, use a Raspberry Pi as mock ISP.
See deploy/rpi-isp/README.md for full mock ISP setup instructions.
┌─────────────────┐ ┌─────────────────┐
│ RPi (mock) │◄───── BGP ────────►│ Border Router │
│ AS ${ISP_AS} │ ${BGP_ │ AS ${BORDER_ │
│ ${ISP_IP} │ NETWORK_ │ ROUTER_AS} │
│ │ RANGE} │ ${BORDER_ │
│ announces test │ │ ROUTER_IP} │
│ prefixes │ │ │
│ │ │ egress gateway │
└─────────────────┘ └─────────────────┘
│
│ mesh
▼
┌─────────────────┐
│ Mesh Nodes │
│ ${MESH_ │
│ ADDRESS_ │
│ RANGE} │
└─────────────────┘
The border router needs a secondary IP in the RPi's network for BGP peering:
sudo ip addr add ${BORDER_ROUTER_IP}/24 dev ${BORDER_ROUTER_INTERFACE}docker exec bird-border birdc show protocols
docker exec bird-border birdc show routedocker exec netclient wg show
ping <mesh-node-ip> # other mesh nodes in ${MESH_ADDRESS_RANGE}# From RPi, should reach any mesh node
ping <mesh-node-ip> # any IP in ${MESH_ADDRESS_RANGE}- Use proper TLS certificates (Let's Encrypt)
- Enable MQTT authentication
- Use secrets management for MASTER_KEY
- Configure firewalls appropriately
- Multiple border routers with BGP failover
- Netmaker can run in HA mode
- Consider anycast for critical services
- For real deployment, use legitimately obtained IP space
- Default config uses example ranges (update in
.envfiles) - Contact your RIR (LACNIC, ARIN, RIPE, etc.) for production IP allocation
deploy/
├── netmaker/ # Netmaker server (public)
│ ├── docker-compose.yml
│ ├── mosquitto.conf
│ └── SETUP.md
├── bird-border/ # Border router + netclient
│ ├── docker-compose.yml
│ ├── bird.conf
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── SETUP.md
└── netclient/ # Standalone mesh node
├── docker-compose.yml
└── SETUP.md
- Netmaker Documentation
- Netmaker Technical Reference (project-specific configuration notes)
- BIRD Internet Routing Daemon
- BGP RFC 4271
- WireGuard
MIT