Nebula

Updated: February 8, 2026

Nebula is a scalable overlay networking tool with a focus on performance, simplicity, and security. It allows you to connect devices across different networks into a single secure mesh network, similar to Tailscale but self-hosted and completely under your control. Nebula uses certificate authority-based authentication and encrypted tunnels to create a private network that can traverse NAT and firewalls.


Table of Contents

Installation

Manual Install

Nebula can be installed on various platforms:

# Linux
wget https://github.com/slackhq/nebula/releases/download/v1.7.2/nebula-linux-amd64.tar.gz
tar -xzf nebula-linux-amd64.tar.gz
sudo cp nebula /usr/local/bin/

# macOS
brew install nebula

# Or download binary
curl -OL https://github.com/slackhq/nebula/releases/download/v1.7.2/nebula-darwin-amd64.tar.gz
tar -xzf nebula-darwin-amd64.tar.gz
sudo cp nebula /usr/local/bin/

Nix Install

nix-env -iA nixpkgs.nebula

NixOS Configuration

Enable Nebula as a system service in your NixOS configuration:

{ config, pkgs, ... }:

{
  environment.systemPackages = with pkgs; [
    nebula
  ];

  # Enable Nebula service for a specific network (e.g., "mynet")
  services.nebula.networks.mynet = {
    enable = true;
    isLighthouse = false;
    isRelay = false;
    ca = ./ca.crt;
    cert = ./host.crt;
    key = ./host.key;

    # Static host map for initial connection
    staticHostMap = {
      "10.100.0.1" = [ "lighthouse.example.com:4242" ];
    };

    # Lighthouse addresses
    lighthouse = [ "10.100.0.1" ];

    listen = {
      host = "0.0.0.0";
      port = 4242;
    };

    tun = {
      disabled = false;
      device = "nebula1";
    };

    firewall = {
      outbound = [
        { port = "any"; proto = "any"; host = "any"; }
      ];
      inbound = [
        { port = "any"; proto = "any"; host = "any"; }
      ];
    };
  };

  # Optional: Enable IP forwarding for routing
  boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
}

Rebuild and switch:

sudo nixos-rebuild switch

Certificate Authority Setup

First, create a Certificate Authority (CA) for your Nebula network:

# Generate CA certificate and key valid 10 years
nebula-cert ca -name "MyNebulaCA" -duration 87600h

# This creates:
# - ca.crt (public certificate)
# - ca.key (private key - keep this secure!)

The ca.crt will be distributed to all hosts in the network. The ca.key should only exist on the machine where you sign certificates.

Lighthouse Setup

A lighthouse helps hosts discover each other. You typically need at least one lighthouse in your network.

Generate Lighthouse Certificate

# Generate certificate for lighthouse
nebula-cert sign -name "lighthouse1" -ip "192.100.100.1/24" -groups "desktop,lighthouse" ca.crt ca.key

This creates lighthouse1.crt and lighthouse1.key.

Lighthouse NixOS Configuration

services.nebula.networks.mynet = {
  enable = true;
  isLighthouse = true;
  ca = ./ca.crt;
  cert = ./lighthouse1.crt;
  key = ./lighthouse1.key;

  listen = {
    host = "0.0.0.0";
    port = 4242;
  };

  # Lighthouses don't need staticHostMap to other lighthouses
  staticHostMap = {};

  tun = {
    disabled = false;
    device = "nebula1";
  };

  firewall = {
    outbound = [
      { port = "any"; proto = "any"; host = "any"; }
    ];
    inbound = [
      { port = "any"; proto = "any"; host = "any"; }
    ];
  };
};

Client Configuration

Generate Client Certificate

# Generate certificate for a host named "server1" with IP 10.100.0.2
nebula-cert sign -name "server1" -ip "192.100.100.2/24" -groups "server" ca.crt ca.key

# For a client/laptop with a group
nebula-cert sign -name "laptop1" -ip "10.100.0.10/24" -groups "admin,dev" ca.crt ca.key

Client NixOS Configuration

services.nebula.networks.mynet = {
  enable = true;
  isLighthouse = false;
  ca = ./ca.crt;
  cert = ./server1.crt;
  key = ./server1.key;

  # Point to lighthouse for discovery
  staticHostMap = {
    "10.100.0.1" = [ "lighthouse.example.com:4242" ];
  };

  lighthouse = [ "10.100.0.1" ];

  listen = {
    host = "0.0.0.0";
    port = 4242;
  };

  tun = {
    disabled = false;
    device = "nebula1";
  };

  firewall = {
    outbound = [
      { port = "any"; proto = "any"; host = "any"; }
    ];
    inbound = [
      { port = "any"; proto = "any"; host = "any"; }
    ];
  };
};

Relay Setup

Relays are useful for devices behind symmetric NAT that cannot make direct connections.

Generate Relay Certificate

nebula-cert sign -name "relay1" -ip "10.100.0.100/24" ca.crt ca.key

Relay NixOS Configuration

services.nebula.networks.mynet = {
  enable = true;
  isLighthouse = false;
  isRelay = true;
  ca = ./ca.crt;
  cert = ./relay1.crt;
  key = ./relay1.key;

  staticHostMap = {
    "10.100.0.1" = [ "lighthouse.example.com:4242" ];
  };

  lighthouse = [ "10.100.0.1" ];

  listen = {
    host = "0.0.0.0";
    port = 4242;
  };

  tun = {
    disabled = false;
    device = "nebula1";
  };
};

Client Using Relay

services.nebula.networks.mynet = {
  enable = true;
  ca = ./ca.crt;
  cert = ./client.crt;
  key = ./client.key;

  staticHostMap = {
    "10.100.0.1" = [ "lighthouse.example.com:4242" ];
  };

  lighthouse = [ "10.100.0.1" ];
  relays = [ "10.100.0.100" ];

  # Force relay usage if needed
  useRelay = true;
};

Firewall Configuration

System Firewall

Ensure Nebula’s UDP port is open:

networking.firewall.allowedUDPPorts = [ 4242 ];

Or for specific interface:

networking.firewall.extraCommands = ''
  iptables -A INPUT -i eth0 -p udp --dport 4242 -j ACCEPT
'';

Nebula Internal Firewall

Control traffic between hosts:

services.nebula.networks.mynet = {
  # ... other config ...

  firewall = {
    outbound = [
      # Allow all outbound traffic
      { port = "any"; proto = "any"; host = "any"; }
    ];

    inbound = [
      # Allow only specific ports
      { port = "22"; proto = "tcp"; host = "any"; }
      { port = "80"; proto = "tcp"; host = "10.100.0.2"; }
      { port = "443"; proto = "tcp"; host = "10.100.0.2"; }

      # Allow ICMP (ping)
      { port = "any"; proto = "icmp"; host = "any"; }
    ];
  };
};

Commands

Certificate Management

# Create CA
nebula-cert ca -name "MyNetwork"

# Sign host certificate
nebula-cert sign -name "hostname" -ip "10.100.0.X/24" ca.crt ca.key

# Sign with groups
nebula-cert sign -name "hostname" -ip "10.100.0.X/24" -groups "admin,dev" ca.crt ca.key

# Sign with additional IPs
nebula-cert sign -name "hostname" -ip "10.100.0.10/24" -subnets "192.168.1.0/24" ca.crt ca.key

# Verify certificate
nebula-cert verify ca.crt host.crt

# Show certificate info
nebula-cert print host.crt

# Revoke certificate (create new CA with CRL)
nebula-cert sign -name "hostname" -ip "10.100.0.X/24" ca.crt ca.key -revoke

Service Management

# NixOS service
systemctl status nebula@mynet
systemctl restart nebula@mynet
systemctl stop nebula@mynet
journalctl -u nebula@mynet -f

Network Diagnostics

# Check nebula interface
ip addr show nebula1

# Check routes
ip route show

# Ping another host in mesh
ping 10.100.0.2

# Check nebula status
nebula-test status

# Check connection to lighthouse
nebula-test ping lighthouse-ip

Troubleshooting

Common Issues

Hosts can’t connect:

# Check if nebula service is running
systemctl status nebula@mynet

# Check firewall rules
iptables -L -n -v

# Verify certificate is valid
nebula-cert verify ca.crt host.crt

# Check lighthouse is accessible
ping lighthouse.example.com
telnet lighthouse.example.com 4242

NAT traversal issues:

Performance issues:

# Check nebula connections
ip link show nebula1

# Monitor nebula traffic
tcpdump -i nebula1

# Check system load
htop

Certificate expiration:

# Check certificate expiration
nebula-cert print host.crt | grep -i not

# Renew certificates before expiration
nebula-cert sign -name "hostname" -ip "10.100.0.X/24" ca.crt ca.key

Debug Mode

Enable debug logging:

services.nebula.networks.mynet = {
  # ... other config ...

  # Add to config.yml for debug
  settings = {
    logging = {
      level = "debug";
      format = "text";
    };
  };
};

Or temporarily run nebula manually:

sudo nebula -config /var/lib/nebula/mynet/config.yml