Go daemon that keeps Nebula VPN configuration in sync with the nebula-platform API. Polls for config version changes, pulls updated configurations (including certificate blocklists), validates them, and applies them atomically with crash durability.
Download from Releases:
curl -sL https://github.com/Project-Highway/nebula-guard/releases/latest/download/nebula-guard-linux-amd64 \
-o /usr/local/bin/nebula-guard
chmod +x /usr/local/bin/nebula-guardOr build from source:
make buildnebula-guardAll configuration is via environment variables.
| Variable | Default | Description |
|---|---|---|
PLATFORM_URL |
(required) | Platform API base URL |
NEBULA_DIR |
/etc/nebula |
Nebula configuration directory |
NEBULA_CONFIG |
$NEBULA_DIR/config.yml |
Nebula config file path |
VERSION_FILE |
$NEBULA_DIR/bl.version |
Local version tracking file |
LOCK_FILE |
/var/lock/nebula-config.lock |
Shared lock file (with renewal script) |
POLL_INTERVAL |
30 |
Poll interval in seconds |
POLL_JITTER |
5 |
Random jitter added to poll interval (seconds) |
STARTUP_JITTER |
30 |
Random delay before first poll (seconds) |
METRICS_ADDR |
:9101 |
Prometheus metrics listen address |
NEBULA_BINARY |
/usr/local/bin/nebula |
Path to nebula binary (for config validation) |
- On startup, waits a random jitter period to prevent thundering herd after fleet-wide deployments
- Every 30 seconds (+ random jitter), checks
GET /api/config/versionfor version changes - If the remote version is newer than the local version, pulls full config from
GET /api/config - Acquires an exclusive file lock (shared with the renewal script to prevent concurrent writes)
- Backs up the current config
- Writes the new config to a temp file
- Validates with
nebula -test— if validation fails, the update is rejected - Atomically replaces the config: fsync temp file, rename over live config, fsync parent directory
- Sends SIGHUP to the Nebula process to reload
- Saves the new version number and sends an acknowledgment to the platform
# /etc/systemd/system/nebula-guard.service
[Unit]
Description=Nebula Guard (config watcher)
After=nebula.service
BindsTo=nebula.service
[Service]
Type=simple
ExecStart=/usr/local/bin/nebula-guard
EnvironmentFile=/etc/nebula/nebula-guard.env
Restart=on-failure
RestartSec=10
WatchdogSec=120
[Install]
WantedBy=multi-party.targetAvailable at http://localhost:9101/metrics:
| Metric | Type | Description |
|---|---|---|
guard_blocklist_version |
Gauge | Current applied blocklist version |
guard_blocklist_entries |
Gauge | Number of entries in the active blocklist |
guard_updates_applied |
Counter | Total config updates applied |
guard_update_errors |
Counter | Total update failures |
guard_polls_total |
Counter | Total poll attempts |
guard_last_update_timestamp |
Gauge | Unix timestamp of last applied update |
guard_connected |
Gauge | 1 if last poll succeeded, 0 if not |
curl http://localhost:9101/health
# okmake build # build for current platform
make build-linux-amd64 # cross-compile for linux/amd64
make build-linux-arm64 # cross-compile for linux/arm64
make build-all # build both
make clean # remove artifactscmd/nebula-guard/ CLI entry point, signal handling, metrics server
internal/
config/ Environment-based configuration loading
poller/ Version polling + config pulling with exponential backoff
updater/ Atomic config writer: lock → backup → write → validate → rename → SIGHUP
metrics/ Prometheus gauge/counter definitions