added gitea for PoC
This commit is contained in:
parent
ded80f5a4b
commit
53433dc3de
102
poc/README.md
102
poc/README.md
@ -6,11 +6,12 @@ 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 | Local Git server (optional, off by default) |
|
||||
| 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.
|
||||
@ -18,7 +19,9 @@ Docker bridge network. Caddy handles ACME certificates automatically.
|
||||
## Prerequisites
|
||||
|
||||
- SSH access to `46.225.220.61` (root, key-based)
|
||||
- DNS A record: `vps-a.networkmonitor.cc` → `46.225.220.61`
|
||||
- DNS A records:
|
||||
- `vps-a.networkmonitor.cc` → `46.225.220.61`
|
||||
- `gitea.vps-a.networkmonitor.cc` → `46.225.220.61`
|
||||
- `rsync` installed locally (used to sync reconciler source)
|
||||
- Ansible 2.15+ with `community.general` and `ansible.posix` collections
|
||||
|
||||
@ -28,22 +31,16 @@ Install collections if needed:
|
||||
ansible-galaxy collection install community.general ansible.posix
|
||||
```
|
||||
|
||||
## Setup
|
||||
## Deployment (multi-phase)
|
||||
|
||||
### 1. Create vault file
|
||||
The deployment is intentionally multi-phase because some tokens can only be
|
||||
obtained after services are running.
|
||||
|
||||
### Phase 1: Initial deploy
|
||||
|
||||
```bash
|
||||
cd poc/ansible
|
||||
cp group_vars/all/vault.yml.example group_vars/all/vault.yml
|
||||
```
|
||||
|
||||
For the first deploy, leave all values as empty strings — the playbook
|
||||
auto-generates NetBird secrets and a reconciler token.
|
||||
|
||||
### 2. Deploy
|
||||
|
||||
```bash
|
||||
cd poc/ansible
|
||||
ansible-playbook -i inventory.yml playbook.yml
|
||||
```
|
||||
|
||||
@ -51,48 +48,61 @@ The playbook will:
|
||||
|
||||
1. Generate secrets (encryption key, TURN password, relay secret, reconciler
|
||||
token)
|
||||
2. Install Docker if not present
|
||||
3. Configure UFW firewall
|
||||
4. Rsync the reconciler source code to VPS-A
|
||||
5. Template all config files
|
||||
6. Build the reconciler Docker image on VPS-A
|
||||
7. Pull NetBird/Gitea images and start all services
|
||||
8. Run health checks and print a summary with generated secrets
|
||||
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** printed at the end into `vault.yml` so subsequent
|
||||
runs are idempotent.
|
||||
**Save the generated secrets** into `vault.yml` so subsequent runs are
|
||||
idempotent.
|
||||
|
||||
### 3. Create NetBird admin + API token
|
||||
### 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`
|
||||
5. Re-run the playbook:
|
||||
|
||||
### 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
|
||||
|
||||
```bash
|
||||
ansible-playbook -i inventory.yml playbook.yml
|
||||
```
|
||||
|
||||
The reconciler will now start successfully with a valid API token.
|
||||
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
|
||||
|
||||
### 4. (Optional) Enable Gitea
|
||||
### Phase 5: Push code and test CI
|
||||
|
||||
To enable Gitea-backed GitOps polling:
|
||||
```bash
|
||||
cd /path/to/netbird-gitops
|
||||
git remote add poc git@gitea.vps-a.networkmonitor.cc:BlastPilot/netbird-gitops.git
|
||||
git push poc main
|
||||
```
|
||||
|
||||
1. Open `http://vps-a.networkmonitor.cc:3000` and complete the install wizard
|
||||
2. Create an admin account (user: `blastpilot`)
|
||||
3. Create org `BlastPilot` and repo `netbird-gitops`
|
||||
4. Push `netbird.json` to the repo
|
||||
5. Generate a Gitea API token (Settings → Applications)
|
||||
6. In `vars.yml`, set `gitea_enabled: "true"`
|
||||
7. In `vault.yml`, fill in `vault_gitea_token` and `vault_gitea_admin_password`
|
||||
8. Re-run the playbook
|
||||
Then configure Gitea repo secrets (Settings → Actions → Secrets):
|
||||
- `RECONCILER_TOKEN` — the reconciler bearer token
|
||||
- `RECONCILER_URL` — `https://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
|
||||
|
||||
All commands below assume you have the reconciler token. Replace `<TOKEN>` with
|
||||
the value of `vault_reconciler_token`.
|
||||
Replace `<TOKEN>` with `vault_reconciler_token`.
|
||||
|
||||
### Health check
|
||||
|
||||
@ -127,14 +137,6 @@ curl -H "Authorization: Bearer <TOKEN>" \
|
||||
'https://vps-a.networkmonitor.cc/reconciler/export'
|
||||
```
|
||||
|
||||
### Enroll a peer
|
||||
|
||||
Use a setup key from the reconcile response (`created_keys` field):
|
||||
|
||||
```bash
|
||||
sudo netbird up --management-url https://vps-a.networkmonitor.cc --setup-key <KEY>
|
||||
```
|
||||
|
||||
## Teardown
|
||||
|
||||
Remove all containers and volumes:
|
||||
@ -143,6 +145,12 @@ Remove all containers and volumes:
|
||||
ssh root@46.225.220.61 "cd /opt/netbird-poc && docker compose down -v"
|
||||
```
|
||||
|
||||
Stop the runner:
|
||||
|
||||
```bash
|
||||
ssh root@46.225.220.61 "systemctl stop gitea-runner && systemctl disable gitea-runner"
|
||||
```
|
||||
|
||||
## File structure
|
||||
|
||||
```
|
||||
@ -158,7 +166,7 @@ poc/
|
||||
templates/
|
||||
docker-compose.yml.j2 # All services (NetBird + Gitea + Reconciler)
|
||||
management.json.j2 # NetBird management config
|
||||
Caddyfile.j2 # Caddy reverse proxy with reconciler route
|
||||
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
|
||||
|
||||
@ -12,15 +12,21 @@ coturn_version: "4.8.0-r0"
|
||||
# --- Reconciler ---
|
||||
reconciler_port: 8080
|
||||
|
||||
# --- Gitea (standalone mode by default) ---
|
||||
# String "false" because it goes into an env var verbatim.
|
||||
gitea_enabled: "false"
|
||||
# --- Gitea ---
|
||||
gitea_enabled: "true"
|
||||
gitea_version: "1.23"
|
||||
gitea_domain: "gitea.vps-a.networkmonitor.cc"
|
||||
gitea_http_port: 3000
|
||||
gitea_ssh_port: 2222
|
||||
gitea_admin_user: "blastpilot"
|
||||
gitea_org_name: "BlastPilot"
|
||||
gitea_repo_name: "netbird-gitops"
|
||||
|
||||
# --- Gitea Actions Runner ---
|
||||
gitea_runner_version: "0.2.11"
|
||||
gitea_runner_dir: "/opt/gitea-runner"
|
||||
gitea_runner_name: "poc-runner"
|
||||
gitea_runner_labels: "ubuntu-latest:docker://node:20-bookworm,ubuntu-22.04:docker://ubuntu:22.04"
|
||||
|
||||
# --- Paths ---
|
||||
base_dir: /opt/netbird-poc
|
||||
|
||||
@ -18,3 +18,7 @@ vault_netbird_api_token: ""
|
||||
|
||||
# Gitea API token (created via Gitea UI after first deploy):
|
||||
vault_gitea_token: ""
|
||||
|
||||
# Gitea Actions runner registration token
|
||||
# (get from Gitea: Site Administration → Actions → Runners):
|
||||
vault_gitea_runner_token: ""
|
||||
|
||||
@ -166,10 +166,10 @@
|
||||
port: "3478"
|
||||
proto: tcp
|
||||
|
||||
- name: Allow Gitea HTTP
|
||||
- name: Allow Gitea SSH
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ gitea_http_port | string }}"
|
||||
port: "{{ gitea_ssh_port | string }}"
|
||||
proto: tcp
|
||||
|
||||
- name: Enable UFW (default deny incoming)
|
||||
@ -327,7 +327,88 @@
|
||||
changed_when: false
|
||||
|
||||
# =========================================================================
|
||||
# 9. Summary
|
||||
# 9. Gitea Actions Runner
|
||||
# =========================================================================
|
||||
# The runner needs Gitea to be up and a registration token.
|
||||
# On first deploy, skip this (vault_gitea_runner_token is empty).
|
||||
# After Gitea is running, get the token from Site Administration →
|
||||
# Actions → Runners, add it to vault.yml, and re-run.
|
||||
|
||||
- name: Create runner directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_runner_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
when: vault_gitea_runner_token | default('') | length > 0
|
||||
|
||||
- name: Download act_runner binary
|
||||
ansible.builtin.get_url:
|
||||
url: "https://gitea.com/gitea/act_runner/releases/download/v{{ gitea_runner_version }}/act_runner-{{ gitea_runner_version }}-linux-amd64"
|
||||
dest: "{{ gitea_runner_dir }}/act_runner"
|
||||
mode: "0755"
|
||||
when: vault_gitea_runner_token | default('') | length > 0
|
||||
|
||||
- name: Check if runner is already registered
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_runner_dir }}/.runner"
|
||||
register: _runner_config
|
||||
when: vault_gitea_runner_token | default('') | length > 0
|
||||
|
||||
- name: Register runner with Gitea
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
{{ gitea_runner_dir }}/act_runner register
|
||||
--instance https://{{ gitea_domain }}
|
||||
--token {{ vault_gitea_runner_token }}
|
||||
--name {{ gitea_runner_name }}
|
||||
--labels {{ gitea_runner_labels }}
|
||||
--no-interactive
|
||||
chdir: "{{ gitea_runner_dir }}"
|
||||
when:
|
||||
- vault_gitea_runner_token | default('') | length > 0
|
||||
- not (_runner_config.stat.exists | default(false))
|
||||
|
||||
- name: Create systemd service for runner
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/systemd/system/gitea-runner.service
|
||||
mode: "0644"
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Gitea Actions Runner
|
||||
After=network.target docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory={{ gitea_runner_dir }}
|
||||
ExecStart={{ gitea_runner_dir }}/act_runner daemon
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
when: vault_gitea_runner_token | default('') | length > 0
|
||||
|
||||
- name: Start and enable runner service
|
||||
ansible.builtin.systemd:
|
||||
name: gitea-runner
|
||||
daemon_reload: true
|
||||
state: started
|
||||
enabled: true
|
||||
when: vault_gitea_runner_token | default('') | length > 0
|
||||
|
||||
- name: Skip runner (no token provided)
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
Skipping Gitea Actions runner — vault_gitea_runner_token is empty.
|
||||
After Gitea is running, get the token from
|
||||
https://{{ gitea_domain }}/-/admin/actions/runners
|
||||
and add it to vault.yml.
|
||||
when: vault_gitea_runner_token | default('') | length == 0
|
||||
|
||||
# =========================================================================
|
||||
# 10. Summary
|
||||
# =========================================================================
|
||||
|
||||
- name: Note about NetBird API token
|
||||
@ -343,11 +424,12 @@
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================================
|
||||
NetBird + Reconciler PoC deployed on VPS-A
|
||||
NetBird + Reconciler + Gitea PoC deployed on VPS-A
|
||||
============================================================
|
||||
|
||||
Dashboard: https://{{ netbird_domain }}
|
||||
Gitea: http://{{ netbird_domain }}:{{ gitea_http_port }}
|
||||
Gitea: https://{{ gitea_domain }}
|
||||
Gitea SSH: ssh://git@{{ gitea_domain }}:{{ gitea_ssh_port }}
|
||||
Reconciler: https://{{ netbird_domain }}/reconciler/health
|
||||
|
||||
Reconciler status: {{ 'healthy' if (_reconciler_check.status | default(0)) == 200 else 'NOT YET READY (see note above)' }}
|
||||
@ -362,5 +444,8 @@
|
||||
1. Open the dashboard and create an admin account
|
||||
2. Go to Settings > API > generate a Personal Access Token
|
||||
3. Put the token in vault.yml as vault_netbird_api_token
|
||||
4. Re-run: ansible-playbook -i inventory.yml playbook.yml
|
||||
4. Open Gitea, complete install wizard, create org + repo
|
||||
5. Go to Site Administration > Actions > Runners, copy token
|
||||
6. Put the token in vault.yml as vault_gitea_runner_token
|
||||
7. Re-run: ansible-playbook -i inventory.yml playbook.yml
|
||||
============================================================
|
||||
|
||||
@ -44,3 +44,11 @@
|
||||
# NetBird Dashboard (catch-all — must be last)
|
||||
reverse_proxy /* dashboard:80
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Gitea
|
||||
# =============================================================================
|
||||
{{ gitea_domain }} {
|
||||
import security_headers
|
||||
reverse_proxy gitea:{{ gitea_http_port }}
|
||||
}
|
||||
|
||||
@ -96,13 +96,14 @@ services:
|
||||
networks:
|
||||
- netbird
|
||||
environment:
|
||||
- GITEA__server__DOMAIN={{ netbird_domain }}
|
||||
- GITEA__server__ROOT_URL=http://{{ netbird_domain }}:{{ gitea_http_port }}
|
||||
- GITEA__server__DOMAIN={{ gitea_domain }}
|
||||
- GITEA__server__ROOT_URL=https://{{ gitea_domain }}
|
||||
- GITEA__server__SSH_DOMAIN={{ gitea_domain }}
|
||||
- GITEA__database__DB_TYPE=sqlite3
|
||||
- GITEA__actions__ENABLED=true
|
||||
volumes:
|
||||
- gitea_data:/data
|
||||
ports:
|
||||
- "{{ gitea_http_port }}:3000"
|
||||
- "{{ gitea_ssh_port }}:22"
|
||||
logging:
|
||||
driver: json-file
|
||||
|
||||
@ -2,11 +2,9 @@ NETBIRD_API_URL=http://management:80/api
|
||||
NETBIRD_API_TOKEN={{ vault_netbird_api_token }}
|
||||
RECONCILER_TOKEN={{ vault_reconciler_token }}
|
||||
GITEA_ENABLED={{ gitea_enabled }}
|
||||
{% if gitea_enabled == "true" %}
|
||||
GITEA_URL=http://gitea:{{ gitea_http_port }}
|
||||
GITEA_TOKEN={{ vault_gitea_token }}
|
||||
GITEA_REPO={{ gitea_org_name }}/{{ gitea_repo_name }}
|
||||
{% endif %}
|
||||
POLL_INTERVAL_SECONDS=30
|
||||
PORT={{ reconciler_port }}
|
||||
DATA_DIR=/data
|
||||
|
||||
60
state/test.json
Normal file
60
state/test.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"groups": {
|
||||
"ground-stations": {
|
||||
"peers": []
|
||||
},
|
||||
"pilots": {
|
||||
"peers": []
|
||||
}
|
||||
},
|
||||
"setup_keys": {
|
||||
"GS-TestHawk-1": {
|
||||
"type": "one-off",
|
||||
"expires_in": 604800,
|
||||
"usage_limit": 1,
|
||||
"auto_groups": [
|
||||
"ground-stations"
|
||||
],
|
||||
"enrolled": false
|
||||
},
|
||||
"Pilot-TestHawk-1": {
|
||||
"type": "one-off",
|
||||
"expires_in": 604800,
|
||||
"usage_limit": 1,
|
||||
"auto_groups": [
|
||||
"pilots"
|
||||
],
|
||||
"enrolled": false
|
||||
}
|
||||
},
|
||||
"policies": {
|
||||
"pilots-to-gs": {
|
||||
"description": "",
|
||||
"enabled": true,
|
||||
"sources": [
|
||||
"pilots"
|
||||
],
|
||||
"destinations": [
|
||||
"ground-stations"
|
||||
],
|
||||
"bidirectional": true,
|
||||
"protocol": "all",
|
||||
"action": "accept",
|
||||
"source_posture_checks": []
|
||||
}
|
||||
},
|
||||
"posture_checks": {},
|
||||
"networks": {},
|
||||
"peers": {},
|
||||
"users": {
|
||||
"admin@example.com": {
|
||||
"name": "admin",
|
||||
"role": "owner",
|
||||
"auto_groups": []
|
||||
}
|
||||
},
|
||||
"routes": {},
|
||||
"dns": {
|
||||
"nameserver_groups": {}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user