Privacy Tools Guide

Nebula is an open-source overlay network built by Slack’s infrastructure team. It creates encrypted mesh tunnels directly between nodes using UDP hole-punching, with a central lighthouse that helps peers find each other without routing all traffic through it. This makes it fast, private, and suitable for distributed teams.

What You Need

Step 1: Install Nebula

Download the latest release on all nodes. On the lighthouse and each team machine:

# On x86_64 Linux
wget https://github.com/slackhq/nebula/releases/latest/download/nebula-linux-amd64.tar.gz
tar -xzf nebula-linux-amd64.tar.gz
sudo mv nebula nebula-cert /usr/local/bin/
sudo chmod +x /usr/local/bin/nebula /usr/local/bin/nebula-cert

For macOS:

brew install nebula

Verify:

nebula-cert --version

Step 2: Create the Certificate Authority

Run this once on a secure machine — not on the lighthouse. The CA key should never leave this machine.

mkdir -p ~/nebula-ca && cd ~/nebula-ca

# Create the CA certificate (valid 5 years)
nebula-cert ca -name "MyTeam CA" -duration 43800h

ls -la
# ca.crt  ca.key

Store ca.key in an encrypted location (e.g., a KeePassXC database or an offline machine). You only need it when creating new node certificates.

Step 3: Sign Node Certificates

Each node needs a certificate with a unique Nebula IP. Use the 10.42.0.0/16 range (or any RFC1918 range you prefer).

# Lighthouse
nebula-cert sign -name "lighthouse" -ip "10.42.0.1/24" -ca-crt ca.crt -ca-key ca.key

# Team member Alice
nebula-cert sign -name "alice" -ip "10.42.0.2/24" -ca-crt ca.crt -ca-key ca.key

# Team member Bob
nebula-cert sign -name "bob" -ip "10.42.0.3/24" -ca-crt ca.crt -ca-key ca.key

# Server (e.g., internal wiki)
nebula-cert sign -name "wiki" -ip "10.42.0.10/24" \
  -groups "servers" -ca-crt ca.crt -ca-key ca.key

The -groups flag lets you write firewall rules targeting a set of nodes rather than individual IPs.

Each sign command produces <name>.crt and <name>.key. Distribute each pair securely to the matching machine along with ca.crt.

Step 4: Configure the Lighthouse

Create /etc/nebula/config.yml on the lighthouse VPS:

pki:
  ca: /etc/nebula/ca.crt
  cert: /etc/nebula/lighthouse.crt
  key: /etc/nebula/lighthouse.key

static_host_map:
  "10.42.0.1": ["YOUR_VPS_PUBLIC_IP:4242"]

lighthouse:
  am_lighthouse: true
  interval: 60

listen:
  host: 0.0.0.0
  port: 4242

punchy:
  punch: true
  respond: true
  delay: 1s

tun:
  disabled: false
  dev: nebula1
  drop_local_broadcast: false
  drop_multicast: false
  tx_queue: 500
  mtu: 1300

firewall:
  outbound:
    - port: any
      proto: any
      host: any
  inbound:
    - port: any
      proto: icmp
      host: any
    - port: any
      proto: any
      host: any

Copy the certificates into place:

sudo mkdir -p /etc/nebula
sudo cp ca.crt lighthouse.crt lighthouse.key /etc/nebula/
sudo chmod 600 /etc/nebula/lighthouse.key

Step 5: Configure Team Member Nodes

Create /etc/nebula/config.yml on Alice’s machine (and each other team member, adjusting cert names):

pki:
  ca: /etc/nebula/ca.crt
  cert: /etc/nebula/alice.crt
  key: /etc/nebula/alice.key

static_host_map:
  "10.42.0.1": ["YOUR_VPS_PUBLIC_IP:4242"]

lighthouse:
  am_lighthouse: false
  interval: 60
  hosts:
    - "10.42.0.1"

listen:
  host: 0.0.0.0
  port: 4242

punchy:
  punch: true
  respond: true

tun:
  disabled: false
  dev: nebula1
  mtu: 1300

firewall:
  outbound:
    - port: any
      proto: any
      host: any
  inbound:
    - port: any
      proto: icmp
      host: any
    - port: 22
      proto: tcp
      host: any
    - port: 443
      proto: tcp
      groups:
        - servers

The inbound rules here allow ICMP from anyone on the mesh, SSH from any mesh peer, and HTTPS only from nodes in the servers group.

Step 6: Start Nebula

On the lighthouse and all nodes:

# Test first
sudo nebula -config /etc/nebula/config.yml -test

# Run as a systemd service
sudo tee /etc/systemd/system/nebula.service > /dev/null <<EOF
[Unit]
Description=Nebula overlay network
After=network.target

[Service]
ExecStart=/usr/local/bin/nebula -config /etc/nebula/config.yml
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now nebula
sudo systemctl status nebula

Step 7: Verify Connectivity

From Alice’s machine:

# Ping lighthouse
ping -c 3 10.42.0.1

# Ping Bob directly (should punch through NAT)
ping -c 3 10.42.0.2

# Check Nebula interface
ip addr show nebula1

# Check nebula logs for direct tunnel establishment
sudo journalctl -u nebula -f

Look for Direct connection established in the logs — this confirms peer-to-peer tunneling is working rather than relaying through the lighthouse.

Firewall Rules and Groups

Nebula’s firewall is evaluated on the receiving node. You can restrict access by group membership:

firewall:
  inbound:
    # Allow all team members to reach internal services
    - port: 8080
      proto: tcp
      groups:
        - team
    # Allow only servers to accept database connections
    - port: 5432
      proto: tcp
      groups:
        - servers

When you sign a certificate, add it to a group:

nebula-cert sign -name "carol" -ip "10.42.0.4/24" \
  -groups "team,developers" -ca-crt ca.crt -ca-key ca.key

Certificate Rotation

Certificates expire. To rotate before expiry:

# Generate new cert for alice (keep same IP)
nebula-cert sign -name "alice" -ip "10.42.0.2/24" \
  -duration 8760h -ca-crt ca.crt -ca-key ca.key

# Distribute alice.crt and alice.key to Alice's machine
# Restart nebula on Alice's machine
sudo systemctl restart nebula

Revoking a Node

Nebula 1.x does not have a CRL mechanism — to revoke access, you must issue a new CA and re-sign all nodes. Plan your team structure so that you can re-roll certificates when a member departs.

One workaround: use short-lived certificates (e.g., 90-day) and automate renewal with a script that requires re-authentication before issuing a new cert.