Files
homelab/ansible/playbooks/roles/ollama/tasks/main.yml
2026-05-25 20:21:24 -05:00

230 lines
7.0 KiB
YAML

---
# ------------------------------------------------------------------------------
# FILE: roles/ollama/tasks/main.yml
# DESCRIPTION: Deploys Ollama with AMD ROCm GPU acceleration on Ubuntu 24.04.
# Handles:
# - ROCm repository and driver stack installation
# - Data disk preparation (LVM, ext4, persistent mount)
# - Ollama installation and systemd service configuration
# - HSA override for RX 5000-series (gfx1010) compatibility
# - Initial model pull
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# ROCm prerequisites
# ------------------------------------------------------------------------------
- name: Install ROCm prerequisite packages
apt:
name:
- wget
- gnupg
- ca-certificates
- lvm2
state: present
update_cache: yes
- name: Add ROCm apt repository signing key
apt_key:
url: https://repo.radeon.com/rocm/rocm.gpg.key
state: present
- name: Add ROCm apt repository
apt_repository:
repo: "deb [arch=amd64] https://repo.radeon.com/rocm/apt/{{ ollama_rocm_version }} {{ ansible_distribution_release }} main"
state: present
filename: rocm
notify: update apt cache
- name: Flush handlers to update apt cache before ROCm install
meta: flush_handlers
# ------------------------------------------------------------------------------
# ROCm driver stack
# hip-runtime-amd pulls in the full ROCm stack as a dependency.
# rocminfo is used to verify GPU visibility after install.
# ------------------------------------------------------------------------------
- name: Install ROCm packages
apt:
name: "{{ ollama_rocm_packages }}"
state: present
notify: update initramfs
- name: Create /opt/rocm symlink to versioned directory
file:
src: "/opt/rocm-{{ ollama_rocm_version }}.0"
dest: /opt/rocm
state: link
force: false
- name: Add ROCm binaries to system PATH
copy:
dest: /etc/profile.d/rocm.sh
content: |
export PATH=$PATH:/opt/rocm/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/rocm/lib
mode: '0644'
- name: Add wed user to render and video groups for GPU access
user:
name: "{{ ansible_user }}"
groups:
- render
- video
append: yes
- name: Add ollama user to render and video groups (created by Ollama installer)
user:
name: ollama
groups:
- render
- video
append: yes
ignore_errors: yes
# ollama user does not exist yet at this point — Ollama installer creates it.
# This task re-runs after install via the post-install handler.
# ------------------------------------------------------------------------------
# Data disk — LVM setup on /dev/sdb
# Follows the same pattern as the monitoring role (cinderella-castle).
# Wipes any stale GPT/partition signatures before creating the PV to avoid
# the "GPT protective partition" error encountered during monitoring deploy.
# ------------------------------------------------------------------------------
- name: Wipe any existing partition signatures from data disk
command: wipefs -a {{ ollama_data_disk }}
args:
creates: /dev/{{ ollama_data_vg }}
when: ollama_setup_data_disk | bool
- name: Create LVM physical volume on data disk
command: pvcreate {{ ollama_data_disk }}
args:
creates: /dev/{{ ollama_data_vg }}
when: ollama_setup_data_disk | bool
- name: Create LVM volume group
lvg:
vg: "{{ ollama_data_vg }}"
pvs: "{{ ollama_data_disk }}"
when: ollama_setup_data_disk | bool
- name: Create LVM logical volume using 100% of VG
lvol:
vg: "{{ ollama_data_vg }}"
lv: "{{ ollama_data_lv }}"
size: 100%FREE
shrink: false
when: ollama_setup_data_disk | bool
- name: Format logical volume as ext4
filesystem:
fstype: ext4
dev: "/dev/{{ ollama_data_vg }}/{{ ollama_data_lv }}"
opts: "-L ollama-data"
when: ollama_setup_data_disk | bool
- name: Create Ollama model directory mount point
file:
path: "{{ ollama_data_dir }}"
state: directory
mode: '0755'
- name: Mount Ollama data volume and add fstab entry
mount:
path: "{{ ollama_data_dir }}"
src: "/dev/{{ ollama_data_vg }}/{{ ollama_data_lv }}"
fstype: ext4
opts: defaults,noatime
state: mounted
when: ollama_setup_data_disk | bool
# noatime: eliminates inode access time writes on every model file read.
# Meaningful win for large sequential reads like model loading.
# ------------------------------------------------------------------------------
# Ollama installation
# Uses the official install script which creates the ollama user and
# systemd service unit. We override the service with our own config.
# ------------------------------------------------------------------------------
- name: Download Ollama install script
get_url:
url: https://ollama.ai/install.sh
dest: /tmp/ollama_install.sh
mode: '0755'
- name: Run Ollama install script
command: /tmp/ollama_install.sh
environment: "{{ {} if ollama_version == 'latest' else {'OLLAMA_VERSION': ollama_version} }}"
args:
creates: /usr/local/bin/ollama
- name: Add ollama user to render and video groups (post-install)
user:
name: ollama
groups:
- render
- video
append: yes
- name: Set ownership of Ollama data directory to ollama user
file:
path: "{{ ollama_data_dir }}"
owner: ollama
group: ollama
recurse: yes
# ------------------------------------------------------------------------------
# Systemd service override
# Injects HSA_OVERRIDE_GFX_VERSION for RX 5000-series compatibility and
# sets OLLAMA_MODELS to the data disk mount point.
# ------------------------------------------------------------------------------
- name: Create systemd override directory for ollama service
file:
path: /etc/systemd/system/ollama.service.d
state: directory
mode: '0755'
- name: Deploy ollama systemd service override
template:
src: ollama-override.conf.j2
dest: /etc/systemd/system/ollama.service.d/override.conf
mode: '0644'
notify:
- reload systemd
- restart ollama
- name: Flush handlers to apply service config before model pull
meta: flush_handlers
- name: Enable and start Ollama service
systemd:
name: ollama
state: started
enabled: yes
daemon_reload: yes
- name: Wait for Ollama API to become available
uri:
url: "http://localhost:{{ ollama_port }}/api/tags"
status_code: 200
register: ollama_health
retries: 12
delay: 5
until: ollama_health.status == 200
# ------------------------------------------------------------------------------
# Initial model pull
# ------------------------------------------------------------------------------
- name: Pull initial model
command: ollama pull {{ ollama_default_model }}
environment:
OLLAMA_HOST: "http://localhost:{{ ollama_port }}"
register: model_pull
changed_when: "'pulled' in model_pull.stdout or model_pull.rc == 0"
timeout: 600
# Qwen3 8B Q4_K_M is ~5GB — allow 10 minutes on first pull.