--- # Bootstrap Ubuntu Server 24.04 headless host for arr-stack + local AI (Vulkan) # # Usage (from this directory): # ansible-galaxy collection install -r requirements.yml # ansible-playbook site.yml -l ser5 # # Tags: common, docker, amd, vulkan, firewall, stack, upgrade, deploy - name: Prepare homelab host hosts: homelab gather_facts: true become: true pre_tasks: - name: Verify target is Ubuntu ansible.builtin.assert: that: - ansible_distribution == "Ubuntu" - ansible_distribution_major_version is version('24', '>=') fail_msg: "This playbook targets Ubuntu 24.04+. Found {{ ansible_distribution }} {{ ansible_distribution_version }}" tags: [always] - name: Resolve stack user uid/gid ansible.builtin.getent: database: passwd key: "{{ stack_owner }}" tags: [always] - name: Set PUID/PGID facts from passwd ansible.builtin.set_fact: ansible_user_uid: "{{ getent_passwd[stack_owner][1] }}" ansible_user_gid: "{{ getent_passwd[stack_owner][2] }}" tags: [always] roles: - role: common tags: [common] - role: docker tags: [docker] - role: amd_vulkan tags: [amd, vulkan, gpu] - role: firewall tags: [firewall] - role: stack tags: [stack] # After stack paths exist — ownership, sudo, groups, GPU nodes - role: users tags: [users, permissions] post_tasks: - name: Summary ansible.builtin.debug: msg: | Host ready: {{ inventory_hostname }} ({{ ansible_host }}) Stack root: {{ stack_root }} (owned by {{ stack_owner }}) Media root: {{ storage_root }} (owned by {{ stack_owner }}) User: {{ stack_owner }} — passwordless sudo, docker/video/render/… Docker: enabled on boot Vulkan: Mesa packages + permissive /dev/dri udev (trusted host) Firewall: UFW LAN {{ lan_subnet }} Next on the server (re-login once for groups): cd {{ stack_root }} docker compose build bonsai && docker compose up -d Open WebUI: http://{{ ansible_host }}:3000 Jellyfin: http://{{ ansible_host }}:8096 tags: [always]