Nebula

Updated: April 6, 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

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 as network with name of megaport
nebula-cert ca -name "megaport" -duration 87600h

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

# Check CA information (expiration, network, subnets etc)
nebula-cert print -path ca.crt

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.

iPhone Nebula App

The Nebula app will provide a device.pub that is shared.
Place that device.pub on the machine where you can sign and send back a cert pair. (Single File)

nebula-cert sign -in-pub device.pub -name "phoneName" -ip "10.99.0.152/16" -groups "admin" ca.crt ca.key

The app will need the signed cert and ca.crt.
The process is started where you will want to import your config.yml
With these 3 things your phone should be able to connect to the Nebula Mesh.
For phones, because they travel, set listen port to 0.0.0.0:0
This sets the port to search dynamically back to the network which can help with port conflicts.

Lighthouse Setup

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

Generate Lighthouse Certificate

Set a name, nebula ip address and group
The cert will have expiration of CA that signed as well as network (megaport)

# Generates (sign) certificate for a host machine. key and cert will bear hostname
nebula-cert sign -name "hostname" -ip "10.99.0.42/24" -groups "admin,server" 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