Files
netbird-iac/ansible/netbird/README.md
2026-02-15 18:37:15 +02:00

293 lines
7.4 KiB
Markdown

# NetBird Deployment
Self-hosted NetBird VPN with embedded IdP (no external SSO required).
## Quick Start
```bash
cd ansible/deployments/netbird
# 1. Generate secrets
./generate-vault.sh
ansible-vault encrypt group_vars/vault.yml
# 2. Deploy
ansible-playbook playbook-ssl.yml -i inventory.yml --ask-vault-pass
# 3. Create admin (manual - see below)
# 4. Create PAT (manual - see below)
# 5. Provision groups and users
ansible-playbook setup-groups.yml -i inventory.yml --ask-vault-pass
ansible-playbook setup-users.yml -i inventory.yml --ask-vault-pass
```
## Prerequisites
- Ubuntu 22.04+ VPS with public IP
- Ports 80, 443, 3478 (TCP/UDP) open
- Ansible 2.14+
## Deployment Modes
| Playbook | Use Case |
| --------------------- | ------------------------------------------------------------------------ |
| `playbook-ssl-ip.yml` | HTTPS with self-signed cert on IP (recommended for isolated deployments) |
| `playbook-ssl.yml` | HTTPS with Let's Encrypt (requires domain) |
| `playbook-no-ssl.yml` | HTTP only (not recommended) |
## Full Workflow
### Step 1: Configure Inventory
Edit `inventory.yml`:
```yaml
all:
children:
netbird_servers:
hosts:
netbird-vps:
ansible_host: YOUR_SERVER_IP
ansible_user: root
ansible_python_interpreter: /usr/bin/python3
```
### Step 2: Generate Secrets
```bash
./generate-vault.sh
ansible-vault encrypt group_vars/vault.yml
```
This creates:
- `vault_turn_password` - TURN server authentication
- `vault_relay_secret` - Relay server secret
- `vault_encryption_key` - Embedded IdP encryption (BACK THIS UP!)
- `vault_admin_password` - Initial admin password
- `vault_netbird_service_pat` - Leave empty for now
### Step 3: Deploy NetBird
```bash
ansible-playbook playbook-ssl-ip.yml -i inventory.yml --ask-vault-pass
```
Wait for deployment to complete. Dashboard will be available at `https://YOUR_IP`.
### Step 4: Create Admin User (Manual)
1. Open `https://YOUR_IP` in browser (accept certificate warning)
2. Create admin account:
- **Email**: `admin@achilles.local` (from `group_vars/netbird_servers.yml`)
- **Password**: Use `vault_admin_password` from vault
```bash
# View password
ansible-vault view group_vars/vault.yml | grep vault_admin_password
```
### Step 5: Create Service User & PAT (Manual)
After logging in as admin:
1. Go to **Team****Service Users**
2. Click **Create Service User**
- Name: `Automation Service`
- Role: `Admin`
3. Click on the created service user
4. Click **Create Token**
- Name: `ansible-automation`
- Expiration: 365 days
5. **Copy the token** (shown only once!)
### Step 6: Store PAT in Vault
```bash
ansible-vault edit group_vars/vault.yml
```
Set:
```yaml
vault_netbird_service_pat: "nbp_xxxxxxxxxxxxxxxxxxxx"
```
### Step 7: Create Groups
```bash
ansible-playbook setup-groups.yml -i inventory.yml --ask-vault-pass
```
This creates:
- Battalion groups: `battalion-1-pilots`, `battalion-1-ground-stations`, etc.
- Dev team group: `dev-team`
- Setup keys for each group
- Access policies (battalion isolation + dev access)
### Step 8: Provision Users
Edit `group_vars/netbird_servers.yml` to define users:
```yaml
netbird_users:
# Dev team (full access)
- email: "vlad.stus@achilles.local"
name: "Vlad Stus"
role: "admin"
auto_groups:
- "dev-team"
# Battalion users
- email: "pilot1.bat1@achilles.local"
name: "Pilot One B1"
role: "user"
battalion: "battalion-1"
type: "pilot"
- email: "gs-operator1.bat1@achilles.local"
name: "GS Operator One B1"
role: "user"
battalion: "battalion-1"
type: "ground-station"
```
Then run:
```bash
ansible-playbook setup-users.yml -i inventory.yml --ask-vault-pass
```
**Dry run** (preview without creating):
```bash
ansible-playbook setup-users.yml -i inventory.yml --ask-vault-pass -e "dry_run=true"
```
Credentials are saved to `files/credentials/users-YYYY-MM-DD.yml`.
## User Roles
| Role | Permissions |
| ------- | ------------------------------------------ |
| `owner` | Full control, can delete account |
| `admin` | Manage users, groups, policies, setup keys |
| `user` | Connect peers, view own peers |
## User Types (for battalion assignment)
| Type | Auto-Group |
| ---------------- | ----------------------------- |
| `pilot` | `{battalion}-pilots` |
| `ground-station` | `{battalion}-ground-stations` |
## Backup & Restore
**Create backup** (downloads to `~/achilles-backups/netbird/`):
```bash
ansible-playbook backup.yml -i inventory.yml
```
**Restore latest backup**:
```bash
ansible-playbook restore.yml -i inventory.yml
```
**Restore specific backup**:
```bash
ansible-playbook restore.yml -i inventory.yml -e "backup_file=netbird-backup-20250116T120000.tar.gz"
```
Backups include:
- Management SQLite database (peers, routes, policies, users)
- Configuration files (docker-compose.yml, Caddyfile, etc.)
## Cleanup
**Soft cleanup** (stop containers, keep data):
```bash
ansible-playbook cleanup-soft.yml -i inventory.yml
```
**Full cleanup** (remove everything including data):
```bash
ansible-playbook cleanup-full.yml -i inventory.yml
```
## Connecting Peers
After provisioning, users connect with:
```bash
# Using setup key (for automated deployments)
netbird up --management-url https://YOUR_IP --setup-key SETUP_KEY
# Using user credentials (interactive)
netbird up --management-url https://YOUR_IP
# Then login with email/password in browser
```
## File Structure
```
ansible/deployments/netbird/
├── backup.yml # Backup management DB and config
├── cleanup-full.yml # Remove everything
├── cleanup-soft.yml # Stop containers only
├── generate-vault.sh # Generate random secrets
├── group_vars/
│ ├── netbird_servers.yml # Main configuration
│ ├── vault.yml # Encrypted secrets
│ └── vault.yml.example # Template for vault
├── inventory.yml # Server inventory
├── playbook-no-ssl.yml # HTTP deployment
├── playbook-ssl-ip.yml # HTTPS with self-signed (IP)
├── playbook-ssl.yml # HTTPS with Let's Encrypt
├── restore.yml # Restore from backup
├── setup-bootstrap.yml # Bootstrap admin (if API available)
├── setup-groups.yml # Create groups, keys, policies
├── setup-users.yml # Provision users
├── templates/ # Jinja2 templates
└── files/
└── credentials/ # Generated user passwords (gitignored)
```
## Troubleshooting
### Certificate Warning
Expected for SSL-IP mode. Accept the self-signed certificate in your browser.
### "Unauthenticated" after login
JWKS race condition bug in NetBird. Wait 30 seconds and try again, or restart the management container:
```bash
ssh root@YOUR_IP "cd /opt/netbird && docker compose restart management"
```
### API returns 404 on /api/instance/setup
The bootstrap API isn't exposed in all NetBird versions. Create admin manually in the dashboard.
### View logs
```bash
ssh root@YOUR_IP "cd /opt/netbird && docker compose logs -f"
```
### Check container status
```bash
ssh root@YOUR_IP "cd /opt/netbird && docker compose ps"
```