stack/ansible
tim 6c9e085cbd Fix Ansible stack deploy rsync chgrp permission errors
Skip owner/group preservation when syncing as non-root; Docker-owned
files under /opt/stack caused rsync code 23. Ownership is fixed after.
2026-07-22 11:09:04 -07:00
..
group_vars Initial commit: arr-stack homelab + local AI 2026-07-22 06:28:49 -07:00
inventory Initial commit: arr-stack homelab + local AI 2026-07-22 06:28:49 -07:00
roles Fix Ansible stack deploy rsync chgrp permission errors 2026-07-22 11:09:04 -07:00
ansible.cfg Initial commit: arr-stack homelab + local AI 2026-07-22 06:28:49 -07:00
README.md Initial commit: arr-stack homelab + local AI 2026-07-22 06:28:49 -07:00
requirements.yml Initial commit: arr-stack homelab + local AI 2026-07-22 06:28:49 -07:00
site.yml Initial commit: arr-stack homelab + local AI 2026-07-22 06:28:49 -07:00

Homelab Ansible — Ubuntu 24.04 (SER5 PRO)

Bootstraps the headless mini PC for arr-stack + Ternary-Bonsai (Vulkan).

Item Value
Host 192.168.8.123:22
User tim
SSH key ~/.ssh/id_ed25519
Stack /opt/stack
Media /storage

What it installs

  1. common — apt upgrade, essentials (curl wget nano build-essential net-tools), Microsoft Edit, tools, unattended-upgrades, fail2ban
  2. docker — Docker CE + Compose plugin, enabled on boot, user in docker
  3. amd_vulkan — Mesa Vulkan, VA-API, firmware, video/render groups, udev rules
  4. firewall — UFW: deny inbound, allow stack ports from LAN only (192.168.8.0/24)
  5. stack/opt/stack + /storage, rsync project, .env, Vulkan compose override, arr-stack.service so compose comes up after reboot (restart: unless-stopped on every service)

Prerequisites (control machine)

# Debian/Ubuntu control node
sudo apt install -y ansible git rsync

cd /path/to/arr-stack/ansible
ansible-galaxy collection install -r requirements.yml

SSH must already work:

ssh -i ~/.ssh/id_ed25519 tim@192.168.8.123

On the server, either enable passwordless sudo (recommended for automation):

echo 'tim ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/tim
sudo chmod 440 /etc/sudoers.d/tim

…or pass the sudo password each run with -K / --ask-become-pass.

Run

cd ansible

# Full bootstrap (prompt for sudo if not NOPASSWD)
ansible-playbook site.yml -K

# Or limit / tags
ansible-playbook site.yml -K --tags docker,amd,firewall
ansible-playbook site.yml -K --tags stack,deploy
ansible-playbook site.yml -K --check   # dry-run (partial)

First connection may prompt for host key (accept-new is set in ansible.cfg).

After the playbook

On the server (or via SSH):

ssh tim@192.168.8.123
# new shell so docker/video/render groups apply
cd /opt/stack

# WireGuard (if not copied): edit wireguard/wg0.conf
# Model (~7.2G):
./scripts/download-bonsai-model.sh

# Vulkan image + stack
docker compose build bonsai
docker compose up -d
docker compose ps

Verify GPU / tools inside the host:

vulkaninfo --summary
ls -l /dev/dri
groups   # should include docker, video, render
edit --version   # Microsoft terminal editor
curl --version && wget --version && nano --version

Survive reboots:

systemctl is-enabled docker arr-stack
systemctl status arr-stack
# containers use restart: unless-stopped; arr-stack.service runs compose up -d on boot

Layout on the server

/opt/stack/                 # compose, config, models, workspace, wireguard
  docker-compose.yml
  docker-compose.override.yml   # /dev/dri for bonsai + jellyfin
  .env
  config/
  models/bonsai/
  workspace/
  wireguard/wg0.conf

/storage/                   # 1TB media disk
  media/{movies,tv,music}
  torrents/{movies,tv,music}

.env points DATA_DIR=/storage and CONFIG_DIR=/opt/stack/config.

Variables

Edit group_vars/all.yml (or host_vars) for:

  • lan_subnet, timezone
  • bonsai_backend / bonsai_ngl (default vulkan / 99)
  • ufw_allow_ssh_from_anywhere (default false — SSH only from LAN)
  • deploy_stack_files — set false to skip rsync

Security notes

  • Do not commit wireguard/wg0.conf or production .env.
  • UFW allows service ports only from lan_subnet.
  • Fail2ban protects SSH.
  • Re-login after first run so group membership (docker, render) is active.