Ansible Environment manager for cli
  • Go 97.8%
  • Makefile 2.2%
Find a file
Johannes Bülow 4ecb0c9033 Updated README with headless mode documentation:
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)
2026-07-03 15:10:00 +02:00
cache Update help texts, add global debug logging, add --version 2026-06-27 17:23:12 +02:00
cmd feat: add headless mode with env var secret support 2026-07-03 15:06:15 +02:00
config feat: add headless mode with env var secret support 2026-07-03 15:06:15 +02:00
debian Add Makefile and Debian package build infrastructure 2026-06-21 21:07:30 +02:00
debug Update help texts, add global debug logging, add --version 2026-06-27 17:23:12 +02:00
hetzner Fix multiple bugs found during code review 2026-07-03 13:27:41 +02:00
inventory Fix multiple bugs found during code review 2026-07-03 13:27:41 +02:00
proxmox Fix multiple bugs found during code review 2026-07-03 13:27:41 +02:00
secret Fix multiple bugs found during code review 2026-07-03 13:27:41 +02:00
vendor Fix multiple bugs found during code review 2026-07-03 13:27:41 +02:00
.gitignore Install to /usr/bin, add build/ to .gitignore 2026-06-21 21:09:28 +02:00
config.toml.example Update example config and inventory files 2026-06-27 18:13:30 +02:00
go.mod Fix multiple bugs found during code review 2026-07-03 13:27:41 +02:00
go.sum Fix multiple bugs found during code review 2026-06-27 16:47:14 +02:00
inventory.yaml.example Update example config and inventory files 2026-06-27 18:13:30 +02:00
LICENSE Initial commit: awmgr - Ansible VM Manager 2026-06-20 22:28:07 +02:00
main.go Add Makefile and Debian package build infrastructure 2026-06-21 21:07:30 +02:00
Makefile Install to /usr/bin, add build/ to .gitignore 2026-06-21 21:09:28 +02:00
README.md Updated README with headless mode documentation: 2026-07-03 15:10:00 +02:00

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 managementawmgr secrets set/get/delete/list for 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 -i script 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/tokenAWMGR_SECRET_PROXMOX_TOKEN
  • secret://hetzner/tokenAWMGR_SECRET_HETZNER_TOKEN
  • secret://ansible/ssh_passwordAWMGR_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 value or echo "value" | awmgr secrets set key

License

GNU General Public License v2.0