Skip to main content

CI/CD Pipeline

Nebula uses GitHub Actions for continuous integration and deployment with semantic versioning.

Overview

┌─────────────────────────────────────────────────────────────────┐
│ GitHub Repository │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Push to main / PR Push tag v* │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ CI Pipeline │ │ Release │ │
│ │ │ │ Pipeline │ │
│ │ • Lint │ │ │ │
│ │ • Test │ │ • Build │ │
│ │ • Build │ │ • Release │ │
│ │ (verify) │ │ • Deploy │ │
│ └─────────────┘ └─────────────┘ │
│ │ │
│ ┌───────────┼───────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ GitHub │ │ Deploy │ │ Deploy │ │
│ │ Release │ │ Agent │ │ Daemon │ │
│ │ │ │ (auto) │ │ (manual) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ nebulactl.com Production │
│ Server │
└─────────────────────────────────────────────────────────────────┘

Workflows

1. CI Pipeline (.github/workflows/ci.yml)

Triggers:

  • Push to main branch
  • Pull requests to main

Jobs:

JobDescriptionDuration
lintRun golangci-lint (v1.64)~1-2 min
testRun tests with race detector~1-2 min
buildBuild verification (4 platforms)~2-3 min
# Matrix build for all platforms
strategy:
matrix:
include:
- goos: linux, goarch: amd64
- goos: linux, goarch: arm64
- goos: darwin, goarch: amd64
- goos: darwin, goarch: arm64

2. Release Pipeline (.github/workflows/release.yml)

Triggers:

  • Push tag matching v* (e.g., v1.0.0, v1.1.0-beta.1)

Jobs:

┌─────────────────────────────────────────────────────────────────┐
│ Release Pipeline │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ build-linux-amd64│ │ build-other │ │
│ │ │ │ │ │
│ │ Docker + CGO │ │ Cross-compile │ │
│ │ (NVML support) │ │ CGO_ENABLED=0 │ │
│ │ │ │ │ │
│ │ • nebula-agent │ │ • linux/arm64 │ │
│ │ • nebulad │ │ • darwin/amd64 │ │
│ │ • nebulactl │ │ • darwin/arm64 │ │
│ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │
│ └──────────┬─────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ release │ │
│ │ │ │
│ │ • Create archives│ │
│ │ • SHA256 checksums │
│ │ • GitHub Release │ │
│ └────────┬─────────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌───────────────┐ │
│ │ deploy-agent │ │ deploy-daemon │ │
│ │ │ │ │ │
│ │ Auto deploy │ │ Manual │ │
│ │ to nebulactl │ │ approval │ │
│ │ .com │ │ required │ │
│ │ │ │ │ │
│ │ Skip for │ │ Environment: │ │
│ │ pre-releases │ │ production │ │
│ └──────────────┘ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Build Strategy

CGO-enabled Build (linux/amd64)

For full GPU monitoring support via NVIDIA NVML:

# scripts/Dockerfile.release
FROM golang:1.24.0-bookworm AS builder

RUN apt-get update && apt-get install -y gcc libc6-dev

# Build with CGO for NVML
RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build \
-ldflags="-s -w -X 'nebula/version.Version=${VERSION}'" \
-o /dist/nebula-agent ./cmd/nebula-agent

Cross-compilation (other platforms)

Pure Go build without CGO:

CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build \
-ldflags="-s -w -X 'nebula/version.Version=${VERSION}'" \
-o nebula-agent ./cmd/nebula-agent
PlatformCGOGPU Support
linux/amd64EnabledFull (NVML)
linux/arm64DisabledStub
darwin/amd64DisabledStub
darwin/arm64DisabledStub

Version Injection

Version info is injected at build time via ldflags:

LDFLAGS="-s -w \
-X 'nebula/version.Version=$VERSION' \
-X 'nebula/version.Commit=$COMMIT' \
-X 'nebula/version.BuildDate=$DATE'"

Check version:

./nebula-agent --version
# nebula-agent version 1.0.0 (abc1234) built 2024-01-15T10:30:00Z

Semantic Versioning

Tag Format

PatternExampleTypeDeploy to Server
vX.Y.Zv1.0.0StableYes
vX.Y.Z-*v1.1.0-beta.1Pre-releaseNo
vX.Y.Z-rc.Nv2.0.0-rc.1Release CandidateNo

Creating a Release

# Stable release
git tag -a v1.0.0 -m "Release v1.0.0: Initial release"
git push origin v1.0.0

# Pre-release (for testing)
git tag v1.1.0-beta.1
git push origin v1.1.0-beta.1

Release Artifacts

Each release creates:

nebula-v1.0.0-linux-amd64.tar.gz
nebula-v1.0.0-linux-arm64.tar.gz
nebula-v1.0.0-darwin-amd64.tar.gz
nebula-v1.0.0-darwin-arm64.tar.gz
checksums.txt

Archive contents:

nebula-v1.0.0-linux-amd64.tar.gz
├── nebula-agent
├── nebulactl
└── nebulad (Linux only)

Deployment

Agent Deployment (Automatic)

On stable releases, agent binaries are deployed to:

https://nebulactl.com/linux/amd64/nebula-agent
https://nebulactl.com/linux/arm64/nebula-agent
https://nebulactl.com/darwin/amd64/nebula-agent
https://nebulactl.com/darwin/arm64/nebula-agent

Daemon Deployment (Manual Approval)

Nebulad deployment requires manual approval:

  1. Release workflow runs
  2. deploy-daemon job waits for approval
  3. Reviewer approves in GitHub Actions
  4. Binary deployed to production server

First-time setup:

  • Creates /var/lib/nebulad directory
  • Installs systemd service
  • Enables autostart

Updates:

  • Stops service
  • Replaces binary
  • Restarts service

GitHub Configuration

Required Secrets

SecretDescription
DEPLOY_SSH_KEYSSH private key (ed25519) for server access

Required Variables

VariableValue
DEPLOY_HOSTServer IP (e.g., 193.8.184.128)

Environment Setup

Create production environment:

  1. Settings → Environments → New environment
  2. Name: production
  3. Configure protection rules:
    • Required reviewers: Add yourself or team
    • Deployment branches: Select main

SSH Key Setup

# Generate key
ssh-keygen -t ed25519 -C "github-actions-deploy" -f github_deploy_key -N ""

# Add public key to server
ssh root@your-server "cat >> ~/.ssh/authorized_keys" < github_deploy_key.pub

# Add private key to GitHub Secrets as DEPLOY_SSH_KEY
cat github_deploy_key

Local Development

Run CI Locally

# Lint
make ci-lint

# Test
make ci-test

# Build all platforms
make dist

# Show version info
make version

Manual Deploy

# Deploy agent to nebulactl.com
make deploy

# Deploy daemon
make deploy-daemon HOST=192.168.1.100

# Deploy daemon with systemd setup
make deploy-daemon-full HOST=192.168.1.100

Troubleshooting

CI Failed

# Check lint locally
make ci-lint

# Check tests
go test -v -race ./...

# Verify build
go build ./...

Deploy Failed

# Check SSH connection
ssh -i ~/.ssh/deploy_key root@SERVER "echo OK"

# Check service status
ssh root@SERVER "systemctl status nebulad"

# View logs
ssh root@SERVER "journalctl -u nebulad -n 100"

Release Not Deploying

  1. Check tag format: must be vX.Y.Z (not v1.0.0-beta)
  2. Check DEPLOY_HOST variable is set
  3. Check DEPLOY_SSH_KEY secret is valid
  4. For daemon: approve in GitHub Actions UI

Files Reference

FilePurpose
.github/workflows/ci.ymlCI pipeline (lint, test, build)
.github/workflows/release.ymlRelease and deployment
.github/workflows/deploy-daemon.ymlManual daemon deploy
scripts/Dockerfile.releaseDocker build for CGO
scripts/templates/nebulad.serviceSystemd unit file
.golangci.ymlLinter configuration
MakefileBuild and deploy commands