Ansible
Updating Pinned Software
The Ansible project is the source of truth for pinned service versions. Review an upstream release, update its variable in https://github.com/tuero/homelab-ansible, run a verified backup for stateful services, deploy the affected tag, verify it, and commit the pin. Ansible is not scheduled to upgrade services automatically.
| Software | Pin variable(s) | Deploy command |
|---|---|---|
| AdGuard Home | adguardhome_version | ./run.sh --limit infra_servers --tags adguard |
| Tailscale | tailscale_version | ./run.sh --limit infra_servers --tags tailscale |
| Docker Engine | docker_ce_version, docker_containerd_version, docker_buildx_version, docker_compose_version | ./run.sh --limit services_servers --tags docker |
| ARR applications | arr_images.radarr, arr_images.sonarr, arr_images.bazarr, arr_images.prowlarr | ./run.sh --limit services_servers --tags arr |
| Gluetun and qBittorrent | gluetun_image, qbittorrent_image | ./run.sh --limit services_servers --tags downloads |
| Caddy | caddy_version, caddy_cloudflare_module_version | ./run.sh --limit services_servers --tags proxy |
| Homepage and Uptime Kuma | homepage_image, uptime_kuma_image | ./run.sh --limit services_servers --tags monitoring |
| LLVM | llvm_version, llvm_package_version | ./run.sh --limit gpu_servers --tags dev |
| GCC | gcc_version | ./run.sh --limit gpu_servers --tags dev |
| NVIDIA driver and CUDA | nvidia_driver_package, cuda_toolkit_version, cuda_toolkit_package_version | ./run.sh --limit gpu_servers --tags cuda |
| JupyterLab | jupyter_python_version, jupyterlab_version, jupyter_ipykernel_version | ./run.sh --limit gpu_servers --tags jupyter |
Docker images are pinned by release tag and digest. A changed image reference pulls and recreates its container while retaining bind-mounted appdata under /srv/docker/appdata; do not delete application directories to upgrade.
Finding APT Package Pins
APT pins are long repository version strings. Do not try to increment them by hand: copy a version reported by the host’s configured repository.
apt-cache policy <package>
apt-cache madison <package>For LLVM, first choose the target major in llvm_version, then inspect the matching clang package and copy its full Candidate value into llvm_package_version:
ssh tuero@10.0.0.111
apt-cache policy clang-23
for package in clang-23 clang-format-23 clangd-23 clang-tidy-23; do
apt-cache policy "$package"
doneAll four LLVM packages share llvm_package_version, so use a version available for all four. The same procedure finds pins for the other APT-managed software:
# Lumbridge
apt-cache policy tailscale
# Ardougne
for package in docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin; do
apt-cache policy "$package"
done
# Varrock
apt-cache policy nvidia-driver-595-open cuda-toolkit-13-3Repository:
- Local:
~/Documents/homelab-ansible/ - Remote: homelab-ansible
Ansible configures already-created Ubuntu VMs. See Proxmox for VM creation and Backups and Recovery before rebuilding a stateful services VM.
Prerequisites
- The controller can reach
10.0.0.111,10.0.0.112, and10.0.0.113over SSH. - Cloud-Init has created user
tueroand installed the controller’s SSH key. - The inventory IPs match Inventory and Services.
- TrueNAS and required shares already exist.
- Proxmox GPU passthrough is already attached to the GPU VM.
group_vars/all/vault.ymlexists and is encrypted.
Install Ansible on the controller:
# Ubuntu
sudo apt update
sudo apt install -y ansible
# macOS
brew install ansibleVault
The active roles reference these secret variables:
vault_truenas_smb_password
vault_github_private_key
vault_github_public_key
vault_jupyter_password_hash
vault_adguard_password
vault_pia_username
vault_pia_password
vault_cloudflare_api_tokenDo not put secret values in this note. For a new repository only, create and encrypt the Vault without overwriting an existing file:
cd ~/Documents/homelab-ansible
test ! -e group_vars/all/vault.yml \
&& cp group_vars/all/vault.yml.example group_vars/all/vault.yml \
&& ansible-vault encrypt group_vars/all/vault.ymlEdit an existing encrypted Vault with:
cd ~/Documents/homelab-ansible
ansible-vault edit group_vars/all/vault.ymlThe example file may lag the active roles. Ensure all variables above are present before a full run.
Inventory
inventory/hosts.yml currently defines:
gpu_servers: gpu-server -> 10.0.0.111
infra_servers: infra -> 10.0.0.112
services_servers: services -> 10.0.0.113All hosts use SSH user tuero.
Full Deployment
Test connectivity, then run the site:
cd ~/Documents/homelab-ansible
ansible all -m ping --ask-vault-pass
./run.shrun.sh installs required Ansible Galaxy collections and invokes site.yml --ask-vault-pass.
The full role order is:
all VMs: common
GPU VM:
dev_tools -> truenas_mounts -> github_ssh -> nvidia_cuda
-> jupyter -> post_install
Infra VM:
tailscale -> adguard
Services VM:
truenas_mounts -> service_appdata_restore (recovery only) -> docker
-> arr_stack -> downloads_stack -> reverse_proxy -> monitoring_stack
-> service_backupsTargeted Runs
./run.sh --limit gpu_servers
./run.sh --limit infra_servers
./run.sh --limit services_servers
./run.sh --limit 'infra_servers:services_servers'Examples for existing hosts:
./run.sh --limit infra_servers --tags tailscale
./run.sh --limit infra_servers --tags adguard
./run.sh --limit services_servers --tags arr
./run.sh --limit services_servers --tags downloads
./run.sh --limit services_servers --tags proxy
./run.sh --limit services_servers --tags monitoring
./run.sh --limit services_servers --tags backups
./run.sh --limit gpu_servers --tags jupyterTag-only runs assume their prerequisites already exist. For a normal fresh VM, prefer the full host-group run instead of assembling the machine from individual tags. The only exception is Backups and Recovery > Recover a Fresh Services VM, where appdata must be restored before Docker starts any service.
Fresh VM Expectations
A full run should install software, mount storage, render Compose configuration, create the shared Docker network, and start services. It does not restore Web UI-generated application state. The service_appdata_restore role has never and restore tags, so it is skipped unless explicitly selected and authorized.
On a blank deployment, complete Manual Steps > Services VM Starting Blank Only. On a recovery, use Backups and Recovery > Recover a Fresh Services VM; restored appdata includes the application Web UI configuration, so qBittorrent and ARR reconfiguration should not be necessary.
Verification
ansible all -m ping --ask-vault-pass
ssh tuero@10.0.0.111 nvidia-smi
ssh tuero@10.0.0.112 systemctl is-active AdGuardHome tailscaled
ssh tuero@10.0.0.113 systemctl is-active docker containerd
ssh tuero@10.0.0.113 systemctl list-timers service-appdata-backup.timerThe common role installs and starts qemu-guest-agent. Verify it inside each guest with:
systemctl is-active qemu-guest-agent