Skip to content

Ansible

All Ansible commands run from the ansible/ directory, with credentials loaded from .env into the shell:

Terminal window
cd ansible
export $(cat .env | grep -v '^#' | xargs)
InventoryUse
inventory/proxmox.proxmox.ymlDynamic — every VM and LXC, discovered from the Proxmox API
inventory/hosts.iniStatic localhost, for playbooks that run on the controller

Guests are grouped by Proxmox node and by Proxmox tag, so a guest tagged docker lands in tag_docker. The Docker playbooks target tag_docker:&proxmox_all_running — tagged and currently running.

Full detail: Inventory.

PlaybookWhat it does
restart-docker-stacks.ymlRestarts every running Compose stack with BWS secrets injected
setup_new_machine.ymlBaseline configuration for a freshly created guest
setup-step-ca-client.ymlTrusts the internal CA on a host
distribute-bws-token.ymlInstalls /etc/bws/token so bws works on the host
system-update.ymlPackage updates across the fleet
prune-docker-images.ymlReclaims disk from unused images
configure-lxc-mounts.ymlApplies LXC bind-mount configuration
clear-bash-history.ymlClears shell history on target hosts
test-playbook.yml / test-proxmox-hosts.ymlConnectivity and inventory checks

Per-playbook variables, host patterns and the traps worth knowing before a fleet-wide run: Playbooks.

Terminal window
# Fleet-wide
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/<playbook>.yml
# Scoped
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/<playbook>.yml --limit arcane
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/<playbook>.yml --limit 'arcane,traefik'
# Dry run
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/<playbook>.yml --check --diff

This is the playbook that matters most day to day, because it is the supported way to apply secrets:

Terminal window
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/restart-docker-stacks.yml
# One host, no secret injection
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/restart-docker-stacks.yml \
--limit traefik -e bws_inject_secrets=false

Variables and behaviour: Playbooks.

Six custom roles in playbooks/roles/, all idempotent and safe to re-run. setup_new_machine.yml applies all six in this order:

RoleWhat it does
step_ca_clientInternal CA trust — step CLI, bootstrap, system cert
custom_apt_repoNexus APT source and GPG key
bitwardenbw and bws CLIs, architecture-aware
lazygitPinned lazygit binary from its GitHub release
cli_toolszellij, zoxide, yq, dust, delta, helix, netwatch, plus fzf/jq/ncdu from APT
misemise from its official APT repository, plus system-wide shell activation

All but lazygit and cli_tools have their own README; those two are documented by their defaults/main.yml, which is also where the pinned versions live — bump the version variable there to upgrade a tool across the fleet.

From ansible/ansible.cfg: remote user is unknown224, become is off by default (pass --become or set become: true in the play), facts are cached as JSON in /tmp/ansible_facts for one hour, and logs are written to ansible/ansible.log.