Nebula is a scalable overlay networking tool by Slack that creates a private mesh VPN between your devices — no central server, no complex IPsec configuration. This guide walks through generating a certificate authority, setting up a Lighthouse node on Linux, and connecting Mac and iPhone clients. By the end, you'll have an encrypted 192.168.100.0/24 network your devices can reach each other on, wherever they are.
Generating a Certificate Authority (CA)
./nebula-cert ca -name "my-nebula-mesh" -ips "192.168.100.0/24"Signing Device Certificates
./nebula-cert sign -name "lighthouse" -ip "192.168.100.1/24"
./nebula-cert sign -name "mac" -ip "192.168.100.2/24"Configuring the Lighthouse Server (Linux)
The Lighthouse is the rendezvous point that helps Nebula nodes find each other. It doesn't route traffic — nodes connect directly peer-to-peer after the initial handshake.
Downloading the Lighthouse Binary
Go download the Lighthouse binary from here
In my case, I configured Lighthouse on a Linux-based server, so the filename is nebula-linux-amd64.tar.gz.
Unpack the Lighthouse binary:
tar -xzf nebula-linux-amd64.tar.gzYou should place the binary in a suitable location, such as /usr/local/bin/nebula, but for simplicity, I placed it in the root directory.
Creating the Systemd Service
Create a systemd service file so Nebula starts on boot and restarts automatically if it crashes:
# /etc/systemd/system/nebula.service
[Unit]
Description=Nebula Mesh VPN
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/root/nebula -config /etc/nebula/config.yaml
# Restart automatically if it exits
Restart=always
RestartSec=5
# Security (optional but recommended)
User=root
Group=root
# Increase file descriptor limit if needed
LimitNOFILE=65536
[Install]
WantedBy=multi-user.targetNow re-read the systemd service file: sudo systemctl daemon-reload
Lighthouse Configuration
sudo mkdir -p /etc/nebulaCopy ca.crt, lighthouse.crt, and lighthouse.key to /etc/nebula/.
Here's the Lighthouse configuration — it binds to all interfaces on the standard Nebula port and declares itself as a lighthouse. The firewall rules allow all traffic within the overlay network:
# /etc/nebula/config.yaml
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/lighthouse.crt
key: /etc/nebula/lighthouse.key
static_host_map: {}
listen:
host: 0.0.0.0
port: 4242
lighthouse:
am_lighthouse: true
punchy:
punch: true
respond: true
relay:
am_relay: true
firewall:
outbound:
- port: any
proto: any
cidr: 192.168.100.0/24
inbound:
- port: any
proto: any
cidr: 192.168.100.0/24
tun:
dev: nebula1
drop_local_broadcast: true
drop_multicast: trueEnabling and Starting the Service
Now enable and start the service, then verify it's running:
sudo systemctl enable --now nebulaCheck the service status and logs:
sudo systemctl status nebula
sudo journalctl -u nebula -n 50 --no-pagerYou should see the service running and no errors in the logs.
Configuring Nebula on macOS
Install Nebula via Homebrew, then create the config. The key difference from the Lighthouse config: am_lighthouse is false, we point hosts at the Lighthouse, and we enable punchy for NAT traversal:
# /opt/homebrew/etc/nebula/config.yaml
pki:
ca: /opt/homebrew/etc/nebula/ca.crt
cert: /opt/homebrew/etc/nebula/m1.crt
key: /opt/homebrew/etc/nebula/m1.key
static_host_map:
"192.168.100.1": ["<LIGHTHOUSE_PUBLIC_IP>:4242"]
lighthouse:
am_lighthouse: false
hosts:
- "192.168.100.1"
listen:
host: 0.0.0.0
port: 0
relay:
relays:
- 192.168.100.1
use_relays: true
punchy:
punch: true
respond: true
firewall:
outbound:
- port: any
proto: any
cidr: 192.168.100.0/24
inbound:
- port: any
proto: any
cidr: 192.168.100.0/24
tun:
dev: utun9
disabled: false
drop_local_broadcast: true
drop_multicast: trueInstall Nebula and start it as a background service:
brew install nebula
sudo brew services start nebulaCheck the logs to confirm the connection succeeded:
tail -100 /opt/homebrew/var/log/nebula.logVerify the service is running:
sudo brew services list
Name Status User File
nebula started root /Library/LaunchDaemons/homebrew.mxcl.nebula.plistTest connectivity to the Lighthouse:
ping 192.168.100.1Configuring Nebula on iPhone
Install the Mobile Nebula iOS client from the App Store, then prepare your config file.
# config.yaml for iPhone
pki:
ca: ca.crt
cert: iphone.crt
key: iphone.key
static_host_map:
"192.168.100.1": ["<LIGHTHOUSE_PUBLIC_IP:4242"]
lighthouse:
am_lighthouse: false
hosts:
- "192.168.100.1"
# portable devices is set to listen on all interfaces and port 0 (random)
listen:
host: 0.0.0.0
port: 0
relay:
relays:
- 192.168.100.1
use_relays: true
punchy:
punch: true
respond: true
firewall:
outbound:
- port: any
proto: any
cidr: 192.168.100.0/24
inbound:
- port: any
proto: any
cidr: 192.168.100.0/24
tun:
disabled: falseCopy config.yaml together with ca.crt to a shared folder or cloud storage where your iPhone can reach it.
In the Nebula iOS app, tap +, choose "from file," and select your config.yaml. In my case, it couldn't parse the CA certificate automatically, so I had to manually point it to ca.crt from the same shared folder.
The app will then display a public key. Transfer this key back to the machine where you have nebula-cert and the CA files, then sign a certificate for the iPhone:
./nebula-cert sign -name "iphone" -ip "192.168.100.3/24" -in-pub device.pubThe device.pub file is the public key exported from the iPhone Nebula client.
Copy the resulting iphone.crt back to your iPhone (the private key stays on the device — no .key file is generated by this flow). Point the Nebula app to the certificate and it should accept it. The iPhone should now connect to the Nebula network.
Configuring Nebula on Synology NAS
Running Nebula directly on DSM can break during OS updates, so running it inside a Docker/Container Manager container is highly recommended.
Sign a certificate for your Synology NAS:
./nebula-cert sign -name "synology" -ip "192.168.100.4/24"Configure your config.yaml for the Synology NAS (update the pki paths to /config/):
# config.yaml for the Synology NAS
pki:
ca: /config/ca.crt
cert: /config/synology.crt
key: /config/synology.key
static_host_map:
"192.168.100.1": ["<LIGHTHOUSE_PUBLIC_IP>:4242"]
lighthouse:
am_lighthouse: false
hosts:
- "192.168.100.1"
# since Synology is a stationary device behind a NAT,
# listen on 0.0.0.0 and defined port to avoid possible port conflicts
# in local network
listen:
host: 0.0.0.0
port: 4244
relay:
relays:
- 192.168.100.1
use_relays: true
punchy:
punch: true
respond: true
delay: 1s
firewall:
outbound:
- port: any
proto: any
cidr: 192.168.104.0/24
inbound:
- port: any
proto: any
cidr: 192.168.104.0/24
tun:
dev: nebula1
disabled: false
drop_local_broadcast: true
drop_multicast: true- Open Container Manager on your Synology NAS.
- Create a folder on your NAS file system (e.g., /volume1/docker/nebula/) and drop
ca.crt,synology.crt,synology.key, and your customizedconfig.ymlinside it. Paths in thepkisection of yourconfig.ymlshould start with/config/. - Download the official
nebulaoss/nebulaimage from the registry. - When configuring the container settings, you must apply these options:
- Network: Set Network Mode to Host.
- Volumes / File Mapping: Map your NAS folder
/volume1/docker/nebula/to/config/inside the container. - Capabilities / Execution: You must check the option to Run container with high privilege (Execute container using high privilege /
--cap-add=NET_ADMIN). This gives Docker the permission to spin up the virtual tun network adapter on your DSM kernel. - Execution Command: Set the launch command invocation argument to:
-config /config/config.yml
- Start the container. Your Synology NAS is now joined to the mesh network.
Certificates rotation
By default, certificates are valid for one year. You can find more details on rotating certificates in the Nebula documentation.
You can add -duration 8760h to the nebula-cert sign command to set the certificate duration to 8760 hours (365 days) explicitly; or you can set it to 87600h to set the duration to 10 years.
You now have a working Nebula mesh: Lighthouse on Linux, clients on Mac and iPhone, all reachable at 192.168.100.x. To add more devices, sign additional certificates with nebula-cert sign. The overlay network grows without touching the Lighthouse config.