Nebula Cheat Sheet
Overview
Nebula is an open-source, scalable overlay networking tool originally developed at Slack to connect tens of thousands of hosts across multiple cloud providers, data centers, and employee devices into a single flat network. It uses a certificate-based identity system where each node receives a signed certificate containing its Nebula IP, groups, and metadata. All traffic between nodes is encrypted end-to-end using Noise protocol (similar to WireGuard), and nodes discover each other through designated lighthouse nodes that facilitate NAT traversal.
Unlike traditional VPN solutions, Nebula creates a true mesh network where traffic flows directly between peers rather than through a central gateway, minimizing latency and eliminating bottlenecks. Each node runs its own firewall with rules based on certificates, groups, and network properties, enabling fine-grained microsegmentation. Nebula supports Linux, macOS, Windows, iOS, and Android, runs entirely in user space without kernel modules, and can scale to networks with thousands of nodes with minimal overhead.
Installation
Linux
# Download latest release
NEBULA_VERSION=$(curl -s https://api.github.com/repos/slackhq/nebula/releases/latest | grep tag_name | cut -d'"' -f4)
wget https://github.com/slackhq/nebula/releases/download/${NEBULA_VERSION}/nebula-linux-amd64.tar.gz
tar xzf nebula-linux-amd64.tar.gz
sudo mv nebula nebula-cert /usr/local/bin/
# Verify
nebula --version
nebula-cert --version
macOS
brew install nebula
Windows
# Download from GitHub releases
# Extract nebula.exe and nebula-cert.exe to PATH
# Or use Scoop
scoop install nebula
Docker
docker run --rm -v $(pwd):/nebula \
--cap-add NET_ADMIN \
--device /dev/net/tun \
nebulaoss/nebula:latest \
-config /nebula/config.yml
Certificate Authority Setup
Create CA
# Create CA certificate (valid for 2 years)
nebula-cert ca -name "MyOrg CA" -duration 17520h
# This creates:
# ca.crt - CA certificate (distribute to all nodes)
# ca.key - CA private key (keep secure, offline)
# Create CA with specific groups
nebula-cert ca -name "MyOrg CA" -groups "servers,laptops,phones"
# View CA certificate
nebula-cert print -path ca.crt
Sign Node Certificates
# Sign certificate for a lighthouse
nebula-cert sign \
-name "lighthouse1" \
-ip "10.100.0.1/24" \
-groups "lighthouse,infrastructure"
# Sign certificate for a server
nebula-cert sign \
-name "webserver1" \
-ip "10.100.0.10/24" \
-groups "servers,web"
# Sign certificate for a laptop
nebula-cert sign \
-name "alice-laptop" \
-ip "10.100.0.100/24" \
-groups "laptops,engineering"
# Sign with custom duration
nebula-cert sign \
-name "temp-device" \
-ip "10.100.0.200/24" \
-groups "contractors" \
-duration 720h
# Sign with subnet routing
nebula-cert sign \
-name "site-router" \
-ip "10.100.0.5/24" \
-groups "routers" \
-subnets "192.168.1.0/24"
# Verify certificate
nebula-cert print -path webserver1.crt
# Each sign command creates:
# <name>.crt - Node certificate
# <name>.key - Node private key
Configuration
Lighthouse Configuration
# /etc/nebula/config.yml (lighthouse node)
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/lighthouse1.crt
key: /etc/nebula/lighthouse1.key
static_host_map:
# Empty on lighthouse itself
lighthouse:
am_lighthouse: true
# Listen interval
interval: 60
listen:
host: 0.0.0.0
port: 4242
punchy:
punch: true
respond: true
tun:
disabled: false
dev: nebula1
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
logging:
level: info
format: text
firewall:
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
outbound:
- port: any
proto: any
host: any
inbound:
- port: any
proto: icmp
host: any
- port: 22
proto: tcp
groups:
- infrastructure
- port: 443
proto: tcp
host: any
Node Configuration
# /etc/nebula/config.yml (regular node)
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/webserver1.crt
key: /etc/nebula/webserver1.key
static_host_map:
"10.100.0.1": ["203.0.113.10:4242"]
lighthouse:
am_lighthouse: false
interval: 60
hosts:
- "10.100.0.1"
listen:
host: 0.0.0.0
port: 0
punchy:
punch: true
respond: true
tun:
disabled: false
dev: nebula1
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
logging:
level: info
format: text
firewall:
outbound:
- port: any
proto: any
host: any
inbound:
- port: any
proto: icmp
host: any
- port: 22
proto: tcp
groups:
- engineering
- infrastructure
- port: 80
proto: tcp
host: any
- port: 443
proto: tcp
host: any
Running Nebula
Direct Execution
# Run in foreground
sudo nebula -config /etc/nebula/config.yml
# Test configuration
nebula -config /etc/nebula/config.yml -test
Systemd Service
# /etc/systemd/system/nebula.service
cat << 'EOF' | sudo tee /etc/systemd/system/nebula.service
[Unit]
Description=Nebula Overlay Network
Wants=basic.target network-online.target nss-lookup.target
After=basic.target network.target network-online.target
Before=sshd.service
[Service]
SyslogIdentifier=nebula
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/local/bin/nebula -config /etc/nebula/config.yml
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable nebula
sudo systemctl start nebula
sudo systemctl status nebula
Firewall Rules
Group-Based Access Control
firewall:
inbound:
# Allow ICMP from everyone
- port: any
proto: icmp
host: any
# SSH only from engineering and ops
- port: 22
proto: tcp
groups:
- engineering
- ops
# Web traffic from any Nebula host
- port: 80
proto: tcp
host: any
- port: 443
proto: tcp
host: any
# Database only from web servers
- port: 5432
proto: tcp
groups:
- web
# Monitoring from infrastructure group
- port: 9090
proto: tcp
groups:
- infrastructure
# Allow specific host by name
- port: any
proto: any
host: "admin-workstation"
# CIDR-based rules
- port: any
proto: any
cidr: 10.100.0.0/24
outbound:
- port: any
proto: any
host: any
Advanced Usage
Multiple Lighthouses
static_host_map:
"10.100.0.1": ["203.0.113.10:4242"]
"10.100.0.2": ["198.51.100.20:4242"]
lighthouse:
am_lighthouse: false
hosts:
- "10.100.0.1"
- "10.100.0.2"
Unsafe Routes (Route to Non-Nebula Subnets)
tun:
unsafe_routes:
- route: 192.168.1.0/24
via: 10.100.0.5 # Nebula IP of the gateway node
mtu: 1300
- route: 172.16.0.0/16
via: 10.100.0.6
Relay Nodes (for Difficult NAT)
# On relay node config
relay:
am_relay: true
use_relays: false
# On nodes that need relay
relay:
am_relay: false
use_relays: true
relays:
- 10.100.0.1
Certificate Rotation
# Check certificate expiration
nebula-cert print -path node.crt | grep "Not After"
# Issue new certificate with same IP
nebula-cert sign -name "webserver1" -ip "10.100.0.10/24" -groups "servers,web"
# Replace cert and key on node, then reload
sudo cp webserver1.crt /etc/nebula/
sudo cp webserver1.key /etc/nebula/
sudo systemctl reload nebula
DNS Integration
# Nebula doesn't include DNS, but you can use:
# 1. Add entries to /etc/hosts on each node
# 2. Run a DNS server (CoreDNS/dnsmasq) on a Nebula node
# 3. Use mDNS/Avahi for .local names
Troubleshooting
| Issue | Solution |
|---|---|
| Nodes can’t find each other | Verify lighthouse public IP in static_host_map |
| Handshake timeout | Check UDP port 4242 is open on lighthouse |
| Certificate error | Verify ca.crt matches, check cert expiration |
| Relay-only connections | NAT issue; enable punchy, check STUN/UPnP |
| High latency | Check if traffic is relayed vs direct peer |
| tun device not created | Need root/NET_ADMIN capability |
| Config test fails | Run nebula -config config.yml -test |
| Firewall blocking traffic | Check inbound rules match source groups |
Diagnostic Commands
# Check Nebula interface
ip addr show nebula1
# Test connectivity
ping 10.100.0.1
# View Nebula logs
journalctl -u nebula -f
# Send SIGHUP to reload config (without cert changes)
sudo kill -HUP $(pgrep nebula)
# Check listening port
sudo ss -ulnp | grep nebula
# Debug logging
# Set level: debug in config.yml, restart
Common Log Messages
# Successful handshake
Handshake message sent to 10.100.0.10
# NAT traversal working
punchy: sending punch to 10.100.0.10
# Certificate issue
Certificate is expired or not yet valid
# Firewall blocking
dropping inbound packet from 10.100.0.100: no matching firewall rule