Initial commit: arr-stack homelab + local AI

Docker Compose media stack (gluetun, *arr, Jellyfin), Ternary-Bonsai AI
(Open WebUI, Forgejo, optional OpenHands), and Ansible bootstrap for the
SER5 Ubuntu host.
This commit is contained in:
tim 2026-07-22 06:28:49 -07:00
commit 3645d1314c
33 changed files with 2673 additions and 0 deletions

View file

@ -0,0 +1,102 @@
---
# Radeon 680M (RDNA2 iGPU) on SER5 PRO — Mesa Vulkan for llama.cpp / Jellyfin VAAPI
- name: Install software-properties-common (for add-apt-repository)
ansible.builtin.apt:
name: software-properties-common
state: present
tags: [amd, vulkan, gpu]
- name: Enable Ubuntu universe and multiverse components
ansible.builtin.command: add-apt-repository -y {{ item }}
loop:
- universe
- multiverse
register: apt_components
# With loop, changed_when runs per item — use item stdout, not .results
changed_when: "'Adding component' in (apt_components.stdout | default(''))"
failed_when: apt_components.rc is defined and apt_components.rc != 0
tags: [amd, vulkan, gpu]
- name: Update apt cache after enabling universe/multiverse
ansible.builtin.apt:
update_cache: true
tags: [amd, vulkan, gpu]
- name: Install AMD / Mesa / Vulkan packages
ansible.builtin.apt:
name: "{{ amd_vulkan_packages }}"
state: present
update_cache: false
tags: [amd, vulkan, gpu]
- name: Ensure video and render groups exist
ansible.builtin.group:
name: "{{ item }}"
state: present
loop:
- video
- render
tags: [amd, vulkan, gpu]
- name: Add stack user to video and render (GPU device access)
ansible.builtin.user:
name: "{{ stack_owner }}"
groups:
- video
- render
append: true
tags: [amd, vulkan, gpu]
- name: Check for DRM render nodes
ansible.builtin.find:
paths: /dev/dri
patterns: "renderD*,card*"
file_type: any
register: dri_nodes
tags: [amd, vulkan, gpu]
failed_when: false
- name: Report /dev/dri devices
ansible.builtin.debug:
msg: >-
DRM nodes:
{{ dri_nodes.files | map(attribute='path') | list | default(['(none found — check kernel / firmware)'], true) }}
tags: [amd, vulkan, gpu]
- name: Probe Vulkan (as stack user when possible)
become: true
become_user: "{{ stack_owner }}"
ansible.builtin.command: vulkaninfo --summary
register: vulkan_summary
changed_when: false
failed_when: false
tags: [amd, vulkan, gpu]
- name: Show Vulkan summary (first lines)
ansible.builtin.debug:
msg: "{{ (vulkan_summary.stdout_lines | default(['vulkaninfo failed or not usable yet']))[:40] }}"
tags: [amd, vulkan, gpu]
- name: Probe VA-API
ansible.builtin.command: vainfo
register: vainfo_out
changed_when: false
failed_when: false
tags: [amd, vulkan, gpu]
- name: Show vainfo snippet
ansible.builtin.debug:
msg: "{{ (vainfo_out.stdout_lines | default(vainfo_out.stderr_lines | default(['vainfo unavailable'])))[:25] }}"
tags: [amd, vulkan, gpu]
- name: udev rule — ensure render nodes are accessible by render group
ansible.builtin.copy:
dest: /etc/udev/rules.d/99-amd-render.rules
mode: "0644"
content: |
# Homelab: AMD GPU / APU render nodes for Docker + Vulkan
KERNEL=="renderD*", GROUP="render", MODE="0660"
KERNEL=="card*", GROUP="video", MODE="0660"
notify: Reload udev
tags: [amd, vulkan, gpu]