- Go 97.8%
- Makefile 2.2%
Added "Headless mode" to features list
Added "Headless Mode" section with environment variable examples and naming conventions
Updated secrets examples to show non-interactive usage (argument and stdin)
|
||
|---|---|---|
| cache | ||
| cmd | ||
| config | ||
| debian | ||
| debug | ||
| hetzner | ||
| inventory | ||
| proxmox | ||
| secret | ||
| vendor | ||
| .gitignore | ||
| config.toml.example | ||
| go.mod | ||
| go.sum | ||
| inventory.yaml.example | ||
| LICENSE | ||
| main.go | ||
| Makefile | ||
| README.md | ||
awmgr — Ansible VM Manager
awmgr is a CLI tool that generates dynamic Ansible inventories for VMs running on Proxmox VE and Hetzner Cloud, making it easy to run Ansible playbooks against your infrastructure.
Features
- Dynamic inventory — automatically discovers VMs/containers from Proxmox VE and servers from Hetzner Cloud
- Static hosts — define additional hosts (Raspberry Pis, bare metal, etc.) in a separate config file
- Custom groups — mix static and dynamic hosts into any group structure
- Caching — caches inventory data with configurable TTL to avoid repeated API calls
- Interactive mode — fuzzy-search host/group selection when running playbooks
- Pre-flight ping — test connectivity before executing a playbook
- Filtering — filter by provider, hostname, or tag/label across both providers
- Profiles — define overrides and working directories per environment (dev/staging/prod)
- System keyring integration — store credentials in GNOME Keyring / KDE Wallet via libsecret, reference them as
secret://<key>in config - Secrets management —
awmgr secrets set/get/delete/listfor managing keyring entries - Headless mode — run on servers without a desktop by using environment variables for secrets
- Ansible vault — pass vault password files to ansible-playbook
- Dynamic inventory script — use as a drop-in
-iscript for ansible-playbook
Installation
go install git.jmbit.de/jmb/awmgr@latest
Or build from source:
git clone <repo-url>
cd awmgr
go build -o awmgr .
Configuration
Main config (~/.config/awmgr/config.toml)
[defaults]
[defaults.ansible]
user = "myuser"
ssh_key = "/home/myuser/.ssh/id_ed25519"
[defaults.cache]
ttl = 60
[defaults.proxmox]
url = "https://pve.example.com:8006/api2/json"
token_id = "root@pam!mytoken"
token_secret = "secret://proxmox/token"
insecure = true
[defaults.hetzner]
token = "secret://hetzner/token"
[profile.staging]
[profile.staging.ansible]
user = "deploy"
[profile.production]
[profile.production.hetzner]
token = "secret://hetzner/token-prod"
Inventory config
Without profile: ~/.config/awmgr/inventory.yaml
With --profile staging: ~/.config/awmgr/staging/inventory/inventory.yaml
static:
hosts:
raspberry-pi-1:
ansible_host: 192.168.1.50
ansible_user: pi
groups:
raspberries:
hosts:
- raspberry-pi-1
web_servers:
hosts:
- my-proxmox-vm
- my-hcloud-server
vars:
http_port: 80
Directory Layout with Profiles
When using --profile <name>, the profile directory ~/.config/awmgr/<profile>/ becomes the working directory:
~/.config/awmgr/
├── config.toml
├── staging/
│ ├── playbooks/
│ │ └── site.yml
│ ├── inventory/
│ │ └── inventory.yaml
│ └── roles/
└── production/
├── playbooks/
│ └── site.yml
├── inventory/
│ └── inventory.yaml
└── roles/
Playbook paths are relative to the profile directory:
awmgr --profile staging run playbooks/site.yml
Persist a default profile so --profile is not needed on every command:
awmgr profile set staging
awmgr profile show
awmgr profile clear
Usage
# Generate inventory JSON
awmgr inventory
# Use as dynamic inventory script
ansible-playbook -i <(awmgr inventory) site.yml
# List all hosts in a table
awmgr list
# Filter by provider, name, or tag
awmgr list --filter provider=proxmox
awmgr inventory --filter tag=webserver
# Run a playbook (from CWD or profile directory)
awmgr run site.yml
# Limit to a host or group
awmgr run site.yml -l webservers
# Interactive host/group selection
awmgr run site.yml -i
# Pre-flight ping check before running
awmgr run site.yml --ping
# Use a config profile
awmgr --profile staging run playbooks/site.yml
# Merge an extra inventory file
awmgr run site.yml --extra-inventory monitoring/hosts.yml
# Pass extra arguments to ansible-playbook
awmgr run site.yml -- -v --check
# Store credentials in system keyring (interactive)
awmgr secrets set proxmox/token
awmgr secrets set hetzner/token
# Store credentials non-interactively (headless/CI)
awmgr secrets set proxmox/token "my-secret-value"
echo "my-secret-value" | awmgr secrets set proxmox/token
awmgr secrets list
awmgr secrets get proxmox/token
awmgr secrets delete proxmox/token
Profiles
| Feature | Without --profile |
With --profile staging |
|---|---|---|
| Config section | Top-level keys or [defaults] |
[defaults] + [profile.staging] overrides |
| Inventory | ~/.config/awmgr/inventory.yaml |
~/.config/awmgr/staging/inventory/inventory.yaml |
| Working dir | Current directory | ~/.config/awmgr/staging/ |
| Playbooks | Relative to CWD | Relative to profile dir |
Headless Mode
For running on servers without a desktop environment (no DBus/keyring), use --headless mode with environment variables:
# Set secrets via environment variables
export AWMGR_SECRET_PROXMOX_TOKEN="your-token-secret"
export AWMGR_SECRET_HETZNER_TOKEN="your-hetzner-token"
# Run in headless mode
awmgr --headless inventory
awmgr --headless run site.yml
Environment variable names follow the pattern AWMGR_SECRET_<KEY> where slashes are replaced with underscores and the name is uppercased:
secret://proxmox/token→AWMGR_SECRET_PROXMOX_TOKENsecret://hetzner/token→AWMGR_SECRET_HETZNER_TOKENsecret://ansible/ssh_password→AWMGR_SECRET_ANSIBLE_SSH_PASSWORD
In headless mode:
- Interactive prompts (
-i) are disabled - Missing environment variables produce clear error messages
- Secrets can be set via argument or stdin:
awmgr secrets set key valueorecho "value" | awmgr secrets set key
License
GNU General Public License v2.0