Nebula - Secure Private Overlay Network for AI Agents

  Jul 25, 2026      2m        

Step-by-step guide to configure Nebula VPN for private AI agent communication in your homelab.

Nebula - Secure Private Overlay Network for AI Agents

Nebula is a scalable overlay networking tool designed to secure distributed systems. It creates a private, encrypted mesh network where nodes communicate peer-to-peer without exposing services to the public internet.

Perfect for homelab setups where you want your AI agents (Hermes Agent, custom LLM servers, etc.) to communicate privately and securely.

GitHub: https://github.com/slackhq/nebula

Why Nebula for AI Agents?

  • Private network: AI agents only accessible within your overlay network
  • Peer-to-peer: Direct communication between nodes, no central relay needed
  • Zero configuration: Automatic discovery via lighthouse nodes
  • Lightweight: Minimal overhead compared to traditional VPNs
  • Cloud-native: Works across different cloud providers and homelab setups

Architecture Overview

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│    Laptop   │     │ Homelab Hub │     │  Remote PC  │
│  10.20.0.2  │     │  10.20.0.3  │     │  10.20.0.4  │
└──────┬──────┘     └──────┬──────┘     └──────┬──────┘
       │                   │                   │
       └───────────────────┼───────────────────┘
                           │
                    ┌──────┴──────┐
                    │ Lighthouse  │
                    │  10.20.0.1  │
                    └─────────────┘

All nodes connect to a lighthouse for discovery, then communicate directly via encrypted peer-to-peer tunnels.

Setup Guide

On Lighthouse server

Create nebula/docker-compose.yml:

services:
  nebula:
    image: nebulaoss/nebula:1.10.3    # latest | https://hub.docker.com/r/nebulaoss/nebula/tags
    network_mode: host
    cap_add:
      - NET_ADMIN
    volumes:
      - ./config:/config
    restart: unless-stopped

Generate Certificate Authority (CA)

cd nebula
docker compose run --rm -w /config --entrypoint /nebula-cert nebula ca -name "Kyzlab, Inc" -duration 87600h
# Output:
# config
# ├── ca.key ← DO NOT share (master key)
# └── ca.crt ← Share with all nodes (public cert)

Generate Lighthouse Certificate

docker compose run --rm -w /config --entrypoint /nebula-cert nebula sign -name "lighthouse" -ip "10.20.0.1/24"
# Output:
# config
# ├── lighthouse.key
# └── lighthouse.crt

Configure Lighthouse

Create nebula/config/config.yml:

mkdir -p config
curl -L -o config/config.yml https://raw.githubusercontent.com/slackhq/nebula/master/examples/config.yml

Modify nebula/config/config.yml as following:

pki:
  ca: /config/ca.crt
  cert: /config/lighthouse.crt
  key: /config/lighthouse.key

static_host_map: {}

lighthouse:
  am_lighthouse: true
  serve_dns: true
  dns:
    # The DNS host defines the IP to bind the dns listener to. This also allows binding to the nebula node IP.
    host: 10.20.0.1    # ← Nebula IP of Lighthouse
    port: 53
  hosts: []

listen:
  host: "0.0.0.0"

punchy:
  punch: true
  respond: true

relay:
  am_relay: true    # ← Nodes having Public IPs
  use_relays: true

firewall:
  outbound:
    # Allow all outbound traffic from this node
    - port: any
      proto: any
      host: any
  inbound:
    # Allow all traffic between any nebula hosts
    - port: any
      proto: any
      host: any

Start Nebula Lighthouse:

docker-compose up -d

Allow the port and reload (if needed)

sudo ufw allow 4242/udp
sudo ufw reload

Generate Node Certificates

On Lighthouse server, for each node (laptop, homelab server, remote PC):

# Laptop
docker compose run --rm -w /config --entrypoint /nebula-cert nebula sign -name "laptop" -ip "10.20.0.2/24"

# Homelab server
docker compose run --rm -w /config --entrypoint /nebula-cert nebula sign -name "homelab" -ip "10.20.0.3/24"

# Remote PC
docker compose run --rm -w /config --entrypoint /nebula-cert nebula sign -name "remote-pc" -ip "10.20.0.4/24"

Each generates:

  • nebula/config/<node-name>.crt
  • nebula/config/<node-name>.key

Now that we have the node certificates, copy the following 3 files to each corresponding node:

  • nebula/config/ca.crt (identical on all machines)
  • nebula/config/<node-name>.crt
  • nebula/config/<node-name>.key

Then deploy Nebula on each node/host.

On each node

Create nebula/docker-compose.yml (the same as docker-compose.yml of the Lighthouse):

services:
  nebula:
    image: nebulaoss/nebula:1.10.3    # latest | https://hub.docker.com/r/nebulaoss/nebula/tags
    network_mode: host
    cap_add:
      - NET_ADMIN
    volumes:
      - ./config:/config
    restart: unless-stopped

Create nebula/config/config.yml:

mkdir -p config
curl -L -o config/config.yml https://raw.githubusercontent.com/slackhq/nebula/master/examples/config.yml

Rename:

  • nebula/config/<node-name>.crtnebula/config/node.crt
  • nebula/config/<node-name>.keynebula/config/node.key

Modify nebula/config/config.yml as following:

pki:
  ca: /config/ca.crt      # ← the same as "ca.crt" on Lighthouse server!
  cert: /config/node.crt
  key: /config/node.key

static_host_map:
  # Syntax → "{nebula ip}": ["{routable ip/dns name}:{routable port}"]
  "10.20.0.1": ['<LIGHTHOUSE PUBLIC IP OR DNS>:4242']

lighthouse:
  am_lighthouse: false
  hosts:
    - "10.20.0.1"

punchy:
  punch: true
  respond: true

relay:
  relays:  # ← Nebula IPs of the nodes having public IPs
    - 10.20.0.1
  am_relay: false
  use_relays: true

firewall:
  outbound:
    # Allow all outbound traffic from this node
    - port: any
      proto: any
      host: any
  inbound:
    # Allow all traffic between any nebula hosts
    - port: any
      proto: any
      host: any

Important: Replace <LIGHTHOUSE PUBLIC IP OR DNS> with your lighthouse server's public IP or domain.

Start Nebula Services:

docker compose up -d

Now, AI agents on all nodes can communicate peer-to-peer privately and directly.

Verify the Overlay Network

Ping Between Nodes

# From laptop to homelab
ping 10.20.0.3

# From homelab to remote PC
ping 10.20.0.4

SSH Over Nebula Network

ssh user@10.20.0.3

Transfer Large Files

scp largefile.tar.gz user@10.20.0.3:/home/user/

Troubleshooting

  • Can't ping: Check firewall rules, ensure both nodes have Nebula running
  • Lighthouse not found: Verify static_host_map has correct lighthouse IP:port.
  • Certificate errors: Ensure ca.crt is identical on all nodes
  • Slow connections: Check NAT traversal; add punch: true to config if behind NAT

References