OnUnitActiveSec alone left NEXT unset after enable; calendar every five minutes schedules reliably after boot. |
||
|---|---|---|
| .. | ||
| group_vars | ||
| inventory | ||
| roles | ||
| ansible.cfg | ||
| README.md | ||
| requirements.yml | ||
| site.yml | ||
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
- common — apt upgrade, essentials (
curlwgetnanobuild-essentialnet-tools), Microsoft Edit, tools, unattended-upgrades, fail2ban - docker — Docker CE + Compose plugin, enabled on boot, user in
docker - amd_vulkan — Mesa Vulkan, VA-API, firmware,
video/rendergroups, udev rules - firewall — UFW: deny inbound, allow stack ports from LAN only (
192.168.8.0/24) - stack —
/opt/stack+/storage, rsync project,.env, Vulkan compose override,arr-stack.serviceso compose comes up after reboot (restart: unless-stoppedon 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,timezonebonsai_backend/bonsai_ngl(defaultvulkan/99)ufw_allow_ssh_from_anywhere(defaultfalse— SSH only from LAN)deploy_stack_files— setfalseto skip rsync
Security notes
- Do not commit
wireguard/wg0.confor 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.