Prox 28eabc270e
Some checks failed
Reconcile / reconcile (push) Failing after 1m2s
updated inventory with proper key
2026-03-06 17:30:39 +02:00
..
2026-03-06 17:30:39 +02:00
2026-03-06 17:11:28 +02:00

NetBird GitOps Reconciler — PoC Deployment

Ansible playbook that deploys a self-contained stack on VPS-A for end-to-end testing of the NetBird GitOps reconciler.

Stack overview

Component Purpose
Caddy TLS termination, reverse proxy
NetBird Management, Signal, Relay, Dashboard, TURN
Reconciler Declarative config → NetBird API reconciler
Gitea Git server for GitOps source-of-truth
Gitea Runner Executes CI workflows (Actions)

All services run as Docker containers on a single VPS, connected via a netbird Docker bridge network. Caddy handles ACME certificates automatically.

Prerequisites

  • SSH access to 46.225.220.61 (root, key-based)
  • DNS A records:
    • vps-a.networkmonitor.cc46.225.220.61
    • gitea.vps-a.networkmonitor.cc46.225.220.61
  • rsync installed locally (used to sync reconciler source)
  • Ansible 2.15+ with community.general and ansible.posix collections

Install collections if needed:

ansible-galaxy collection install community.general ansible.posix

Deployment (multi-phase)

The deployment is intentionally multi-phase because some tokens can only be obtained after services are running.

Phase 1: Initial deploy

cd poc/ansible
cp group_vars/all/vault.yml.example group_vars/all/vault.yml
ansible-playbook -i inventory.yml playbook.yml

The playbook will:

  1. Generate secrets (encryption key, TURN password, relay secret, reconciler token)
  2. Install Docker, configure UFW
  3. Rsync the reconciler source code and build the Docker image
  4. Template configs and start all services
  5. Skip the Gitea Actions runner (no token yet)
  6. Print a summary with generated secrets

Save the generated secrets into vault.yml so subsequent runs are idempotent.

Phase 2: Create NetBird admin + API token

  1. Open https://vps-a.networkmonitor.cc in a browser
  2. Create the first admin account (embedded IdP — no external OAuth)
  3. Go to Settings → Personal Access Tokens → Generate
  4. Copy the token into vault.yml as vault_netbird_api_token

Phase 3: Set up Gitea

  1. Open https://gitea.vps-a.networkmonitor.cc and complete the install wizard
  2. Create an admin account (user: blastpilot)
  3. Create org BlastPilot and repo netbird-gitops
  4. Generate a Gitea API token (Settings → Applications) → vault_gitea_token
  5. Go to Site Administration → Actions → Runners → copy runner registration token → vault_gitea_admin_password and vault_gitea_runner_token

Phase 4: Re-deploy with all tokens

ansible-playbook -i inventory.yml playbook.yml

This run will:

  • Start the reconciler with a valid NetBird API token
  • Register and start the Gitea Actions runner
  • Wire the reconciler to poll Gitea for netbird.json changes

Phase 5: Push code and test CI

cd /path/to/netbird-gitops
git remote add poc git@gitea.vps-a.networkmonitor.cc:BlastPilot/netbird-gitops.git
git push poc main

Then configure Gitea repo secrets (Settings → Actions → Secrets):

  • RECONCILER_TOKEN — the reconciler bearer token
  • RECONCILER_URLhttps://vps-a.networkmonitor.cc/reconciler
  • GITEA_TOKEN — same Gitea API token

Create a branch, modify netbird.json, open a PR — the dry-run workflow should post a plan as a PR comment.

Testing

Replace <TOKEN> with vault_reconciler_token.

Health check

curl https://vps-a.networkmonitor.cc/reconciler/health

Dry-run reconcile

curl -X POST \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d @ansible/files/netbird-seed.json \
  'https://vps-a.networkmonitor.cc/reconciler/reconcile?dry_run=true'

Apply reconcile

curl -X POST \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d @ansible/files/netbird-seed.json \
  'https://vps-a.networkmonitor.cc/reconciler/reconcile'

Export current state

curl -H "Authorization: Bearer <TOKEN>" \
  'https://vps-a.networkmonitor.cc/reconciler/export'

Teardown

Remove all containers and volumes:

ssh root@46.225.220.61 "cd /opt/netbird-poc && docker compose down -v"

Stop the runner:

ssh root@46.225.220.61 "systemctl stop gitea-runner && systemctl disable gitea-runner"

File structure

poc/
  ansible/
    inventory.yml              # VPS-A host definition
    playbook.yml               # Main deployment playbook
    .gitignore                 # Excludes vault.yml
    group_vars/
      all/
        vars.yml               # Non-secret config (versions, ports, etc.)
        vault.yml.example      # Secret template — copy to vault.yml
    templates/
      docker-compose.yml.j2    # All services (NetBird + Gitea + Reconciler)
      management.json.j2       # NetBird management config
      Caddyfile.j2             # Caddy reverse proxy (NetBird + Gitea)
      dashboard.env.j2         # NetBird dashboard env
      relay.env.j2             # NetBird relay env
      turnserver.conf.j2       # TURN server config
      reconciler.env.j2        # Reconciler env
    files/
      netbird-seed.json        # Example desired state for testing
  README.md                    # This file