fix(roles): no_log on uri tasks to mask bearer token under -vvvv
Ansible Collection for NetBird
An Ansible collection for managing NetBird self-hosted infrastructure via the NetBird REST API.
Features
This collection provides comprehensive management of NetBird resources:
- Users - Create, update, delete regular and service users
- Groups - Organize peers into logical groups
- Peers - Manage peer settings (SSH, expiration, etc.)
- Setup Keys - Create enrollment keys for new peers
- Policies - Define network access rules between groups
- Networks - Configure network routing with routers and resources
- IP/CIDR routing (
172.16.0.0/16,192.168.1.0/24) - Domain-based routing (
example.com,*.corp.example.com) - High availability with multiple routers and metrics
- IP/CIDR routing (
- Routes - Manage legacy routes (deprecated, use Networks instead)
- DNS - Configure nameserver groups and DNS settings
- Posture Checks - Define security compliance requirements
- Accounts - Manage account-wide settings (including extra settings, auto-update, peer expose)
- Tokens - Create and manage personal access tokens
- Identity Providers - Configure identity providers (Google, Okta, Entra, OIDC, etc.)
- Invites - Manage user invite links with expiration and regeneration
- Info - Gather information about any resource
Requirements
- Ansible >= 2.12
- Python >= 3.6
- A NetBird self-hosted instance with API access
- A NetBird Personal Access Token
Installation
This collection is not yet published to Ansible Galaxy. Install from source:
# Clone the repository
git clone https://github.com/YOUR_USERNAME/ansible-netbird.git
# Build and install the collection
cd ansible-netbird
ansible-galaxy collection build
ansible-galaxy collection install community-ansible_netbird-*.tar.gz
Authentication
All modules require API authentication. You can provide credentials in three ways:
Note:
api_urlis the base URL of your NetBird instance (e.g.,https://netbird.example.com). Do not include/api— the collection appends API paths automatically. A trailing slash is stripped automatically.
1. Module Parameters
- name: List peers
community.ansible_netbird.netbird_info:
api_url: "https://netbird.example.com"
api_token: "{{ netbird_token }}"
resource: peers
2. Environment Variables
export NETBIRD_API_URL="https://netbird.example.com"
export NETBIRD_API_TOKEN="your-personal-access-token"
- name: List peers (uses environment variables)
community.ansible_netbird.netbird_info:
resource: peers
3. Role Variables
- hosts: localhost
vars:
netbird_api_url: "https://netbird.example.com"
netbird_api_token: "{{ vault_netbird_token }}"
roles:
- community.ansible_netbird
Modules
netbird_user
Manage NetBird users (regular and service users). When updating an existing user, omitting auto_groups preserves the current group assignments rather than clearing them.
# Create a regular user
- name: Create user
community.ansible_netbird.netbird_user:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
email: "user@example.com"
name: "John Doe"
role: "user"
auto_groups:
- "developers"
state: present
# Create a service user
- name: Create service user
community.ansible_netbird.netbird_user:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "automation-service"
role: "admin"
is_service_user: true
state: present
netbird_group
Manage NetBird groups. When updating an existing group, omitting peers preserves the current peer membership rather than clearing it.
- name: Create a group
community.ansible_netbird.netbird_group:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "production-servers"
peers:
- "peer-id-1"
- "peer-id-2"
state: present
# Update name only -- peers are preserved
- name: Rename group without affecting peers
community.ansible_netbird.netbird_group:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
group_id: "{{ group.id }}"
name: "prod-servers"
state: present
netbird_peer
Manage NetBird peer settings.
- name: Configure peer
community.ansible_netbird.netbird_peer:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
peer_id: "peer-id-123"
name: "production-server-01"
ssh_enabled: true
login_expiration_enabled: true
state: present
netbird_setup_key
Manage NetBird setup keys for peer enrollment. When updating an existing key, omitting auto_groups preserves the current group assignments rather than clearing them.
- name: Create reusable setup key
community.ansible_netbird.netbird_setup_key:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "server-enrollment"
key_type: "reusable"
expires_in: 604800 # 7 days
auto_groups:
- "servers"
ephemeral: false
state: present
register: setup_key
- name: Display the key
debug:
msg: "Setup key: {{ setup_key.setup_key.key }}"
when: setup_key.changed
# Revoke a key without wiping its auto_groups
- name: Revoke setup key (auto_groups preserved)
community.ansible_netbird.netbird_setup_key:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
key_id: "{{ setup_key.setup_key.id }}"
revoked: true
state: present
netbird_policy
Manage NetBird access policies.
- name: Create access policy
community.ansible_netbird.netbird_policy:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "developers-to-servers"
description: "Allow developers SSH access to servers"
enabled: true
source_posture_checks:
- "posture-check-id"
rules:
- name: "ssh-access"
sources:
- "developers-group-id"
destinations:
- "servers-group-id"
bidirectional: false
protocol: "tcp"
ports:
- "22"
action: "accept"
- name: "web-access"
sources:
- "developers-group-id"
destinations:
- "servers-group-id"
protocol: "tcp"
port_ranges:
- start: 8000
end: 9000
action: "accept"
state: present
netbird_network
Manage NetBird networks with routers and resources. This module provides full routing capabilities, replacing the deprecated routes API.
# Simple network (container only)
- name: Create simple network
community.ansible_netbird.netbird_network:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "office-network"
description: "Main office network"
state: present
# Full network with routers and resources
- name: Create network with routing
community.ansible_netbird.netbird_network:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "internal-network"
description: "Corporate internal network"
routers:
- peer: "gateway-peer-id"
metric: 100
masquerade: true
resources:
- address: "172.16.0.0/16"
name: "internal-range"
description: "All internal IPs"
groups:
- "all-users-group-id"
state: present
# HA network with multiple routers
- name: Create HA network with failover
community.ansible_netbird.netbird_network:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "ha-network"
description: "High availability network"
routers:
- peer_groups:
- "primary-gateways"
metric: 100
masquerade: true
- peer_groups:
- "backup-gateways"
metric: 200
masquerade: true
resources:
- address: "192.168.0.0/16"
name: "private-networks"
groups:
- "developers-group-id"
state: present
# Domain-based routing
- name: Create network with domain routing
community.ansible_netbird.netbird_network:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "internal-services"
description: "Route traffic to internal domains"
routers:
- peer: "dns-gateway-peer-id"
metric: 100
masquerade: true
resources:
- address: "internal.example.com"
name: "internal-portal"
groups:
- "all-users-group-id"
- address: "*.corp.example.com"
name: "corp-subdomains"
description: "All corporate subdomains"
groups:
- "employees-group-id"
state: present
netbird_route
Manage NetBird routes (deprecated API, prefer netbird_network with routers/resources).
- name: Create route (legacy)
community.ansible_netbird.netbird_route:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
network_id: "internal-route"
network: "172.16.0.0/16"
description: "Route to internal network"
peer_id: "gateway-peer-id"
metric: 100
masquerade: true
enabled: true
groups:
- "all-group-id"
state: present
netbird_dns
Manage NetBird DNS settings and nameserver groups.
# Create nameserver group
- name: Create DNS nameserver group
community.ansible_netbird.netbird_dns:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
resource_type: nameserver_group
name: "internal-dns"
nameservers:
- ip: "10.0.0.53"
ns_type: "udp"
port: 53
groups: []
domains:
- "internal.example.com"
enabled: true
state: present
# Update DNS settings
- name: Configure DNS settings
community.ansible_netbird.netbird_dns:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
resource_type: settings
disabled_management_groups:
- "special-group-id"
state: present
netbird_posture_check
Manage NetBird posture checks for security compliance.
- name: Create version check
community.ansible_netbird.netbird_posture_check:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "minimum-version"
description: "Require minimum NetBird version"
checks:
nb_version_check:
min_version: "0.25.0"
state: present
- name: Create geo-location check
community.ansible_netbird.netbird_posture_check:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "allowed-countries"
checks:
geo_location_check:
locations:
- country_code: "US"
- country_code: "DE"
action: "allow"
state: present
netbird_account
Manage NetBird account settings.
- name: Configure account settings
community.ansible_netbird.netbird_account:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
peer_login_expiration_enabled: true
peer_login_expiration: 604800
peer_inactivity_expiration_enabled: true
peer_inactivity_expiration: 2592000
jwt_groups_enabled: true
jwt_groups_claim_name: "groups"
dns_domain: "netbird.example.com"
auto_update_always: true
auto_update_version: "latest"
peer_expose_enabled: true
extra_peer_approval_enabled: false
extra_network_traffic_logs_enabled: true
state: present
netbird_token
Manage NetBird personal access tokens.
- name: Create access token
community.ansible_netbird.netbird_token:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
user_id: "user-id-123"
name: "automation-token"
expires_in: 365
state: present
register: new_token
- name: Display token
debug:
msg: "Token: {{ new_token.token.plain_token }}"
when: new_token.changed
netbird_idp
Manage NetBird identity providers.
# Create an OIDC identity provider
- name: Configure identity provider
community.ansible_netbird.netbird_idp:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "corporate-sso"
type: "oidc"
issuer: "https://auth.example.com"
client_id: "your-client-id"
client_secret: "your-client-secret"
state: present
# Create a Google identity provider
- name: Configure Google IDP
community.ansible_netbird.netbird_idp:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
name: "google-workspace"
type: "google"
issuer: "https://accounts.google.com"
client_id: "your-google-client-id"
client_secret: "your-google-client-secret"
state: present
netbird_invite
Manage NetBird user invites.
# Create a user invite
- name: Invite a new user
community.ansible_netbird.netbird_invite:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
email: "newuser@example.com"
name: "New User"
role: "user"
auto_groups:
- "developers-group-id"
expires_in: 604800 # 7 days
state: present
# Regenerate an expired invite
- name: Regenerate invite link
community.ansible_netbird.netbird_invite:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
email: "newuser@example.com"
regenerate: true
state: present
# Delete an invite
- name: Remove invite
community.ansible_netbird.netbird_invite:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
invite_id: "invite-id-123"
state: absent
netbird_info
Gather information about NetBird resources.
- name: Get all peers
community.ansible_netbird.netbird_info:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
resource: peers
register: peers
- name: Get all groups
community.ansible_netbird.netbird_info:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
resource: groups
register: groups
- name: Get current user
community.ansible_netbird.netbird_info:
api_url: "{{ netbird_api_url }}"
api_token: "{{ netbird_api_token }}"
resource: current_user
register: me
Available resources: accounts, users, peers, groups, setup_keys, policies, networks, routes, dns_nameservers, dns_settings, posture_checks, events, countries, current_user, identity_providers, invites
Role Usage
The collection includes a role for declarative configuration:
- hosts: localhost
vars:
netbird_api_url: "https://netbird.example.com"
netbird_api_token: "{{ vault_netbird_token }}"
netbird_groups:
- name: "developers"
state: present
- name: "production"
state: present
netbird_setup_keys:
- name: "server-key"
key_type: "reusable"
expires_in: 604800
state: present
netbird_policies:
- name: "allow-all"
enabled: true
rules:
- name: "all-traffic"
sources: ["group-id-1"]
destinations: ["group-id-2"]
protocol: "all"
action: "accept"
state: present
# Networks with routing (replaces deprecated routes)
netbird_networks:
- name: "internal-network"
description: "Corporate internal network"
routers:
- peer: "gateway-peer-id"
metric: 100
masquerade: true
resources:
- address: "172.16.0.0/16"
name: "internal-range"
groups: ["developers-group-id"]
- address: "*.internal.example.com"
name: "internal-domains"
groups: ["developers-group-id"]
state: present
roles:
- community.ansible_netbird
See defaults/main.yml for all available role variables.
Examples
The examples/ directory contains complete playbook examples:
basic_setup.yml- Basic groups, keys, and policies setupfull_infrastructure.yml- Complete infrastructure configuration using the roledynamic_policies.yml- Create policies based on existing groupsinventory_from_netbird.yml- Export peers as Ansible inventorypeer_management.yml- Manage and audit peers
Config as Code (IaC Roles)
This collection includes roles and playbooks for managing your entire NetBird configuration as YAML files in Git — with preview/diff, strict mode, and automatic name-to-ID resolution.
Quick Start (Safe Workflow)
The recommended workflow uses the safe_apply_netbird playbook, which automatically backs up the current state before making any changes:
# 1. Export current state to YAML files
ansible-playbook community.ansible_netbird.export_netbird_config \
-e "netbird_api_url=https://netbird.example.com" \
-e "netbird_api_token=your-token"
# 2. Preview changes (default — backup + read-only diff, no modifications)
ansible-playbook community.ansible_netbird.safe_apply_netbird \
-e "config_dir=/path/to/your/config" \
-e "netbird_api_url=https://netbird.example.com" \
-e "netbird_api_token=your-token"
# 3. Apply changes (backup + preview + apply)
ansible-playbook community.ansible_netbird.safe_apply_netbird \
-e "config_dir=/path/to/your/config" \
-e "netbird_api_url=https://netbird.example.com" \
-e "netbird_api_token=your-token" \
-e "apply=true"
# 4. Apply with strict mode (also removes unmanaged resources)
ansible-playbook community.ansible_netbird.safe_apply_netbird \
-e "config_dir=/path/to/your/config" \
-e "netbird_api_url=https://netbird.example.com" \
-e "netbird_api_token=your-token" \
-e "apply=true" -e "use_strict=true"
# 5. Rollback to a backup
ansible-playbook community.ansible_netbird.safe_apply_netbird \
-e "config_dir=/path/to/backups/20260330T120000" \
-e "netbird_api_url=https://netbird.example.com" \
-e "netbird_api_token=your-token" \
-e "apply=true"
The safe_apply_netbird playbook always creates a timestamped backup in backups/ before doing anything. You can also use the individual playbooks directly:
# Export only
ansible-playbook community.ansible_netbird.export_netbird_config \
-e "netbird_api_url=..." -e "netbird_api_token=..."
# Configure only (preview by default, add -e commit=true to apply)
ansible-playbook community.ansible_netbird.configure_netbird \
-e "config_dir=..." -e "netbird_api_url=..." -e "netbird_api_token=..."
Using Roles Directly
For inventory-based workflows (e.g., AAP), use the roles directly in your own playbooks:
- name: Configure NetBird
hosts: netbird_control_nodes
gather_facts: false
roles:
- role: community.ansible_netbird.configure
run_once: true
vars:
config_dir: "{{ playbook_dir }}/../netbird_config/{{ netbird_env }}"
Features
- Preview mode (default) — shows a read-only diff of what would change before applying
- Strict mode — enforces full IaC by removing resources not defined in YAML
- Setup key management — create/rotate enrollment keys with auto_groups name resolution; key values registered for downstream Vault storage
- Name-based config — use plain names ("developers") instead of API IDs; resolved automatically
- Dependency ordering — resources applied in correct order (settings → posture checks → groups → setup keys → DNS → networks → policies)
- Export utility — captures current API state as clean, ready-to-use YAML config files
- Roles — use
community.ansible_netbird.configureandcommunity.ansible_netbird.exportdirectly in your own playbooks for full control
Config Directory Structure
my_netbird_config/
├── settings.yml # Account-wide settings
├── networks.yml # Networks with routers and resources
├── setup_keys.yml # Peer enrollment keys (optional)
├── access_control/
│ ├── groups.yml # Groups
│ ├── posture_checks.yml # Posture checks
│ └── policies.yml # Policies
└── dns/
├── nameservers.yml # DNS nameserver groups
├── zones.yml # DNS zones with records
└── settings.yml # DNS settings
A starter config_skeleton/ directory is included in the collection with empty defaults and commented examples.
See docs/guide_netbird_config_as_code.md for the full guide.
API Reference
This collection implements the NetBird REST API. Refer to the official documentation for detailed information about:
- Authentication
- Accounts
- Users
- Peers
- Groups
- Setup Keys
- Policies
- Networks
- DNS
- Posture Checks
- Identity Providers
- Events
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This collection is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.