This commit is contained in:
boxswapper
2026-02-10 07:55:13 -07:00
parent 539eded8aa
commit 54c779da87

View File

@@ -1,163 +1,88 @@
--- ---
# ------------------------------------------------------------ - name: Deploy Ollama + Open WebUI
# Ansible Playbook – Deploy Ollama + Open‑WebUI with Podman hosts: your_gpu_servers
# ------------------------------------------------------------ become: yes
- name: Deploy Ollama + Open‑WebUI on a remote host using Podman
hosts: target # <-- change to your inventory group / host
become: true # we need root to manage containers/volumes
vars: vars:
# ----------------------------------------------------------------- ollama_port: 11434
# Port that the Open‑WebUI UI will listen on on the *host*.
# If you set the environment variable OPEN_WEBUI_PORT on the host
# before running the play, that value will be used, otherwise 3000.
# -----------------------------------------------------------------
open_webui_port: "{{ lookup('env', 'OPEN_WEBUI_PORT') | default('3000') }}" open_webui_port: "{{ lookup('env', 'OPEN_WEBUI_PORT') | default('3000') }}"
ollama_volume_name: ollama_ollama
# Secret key for the UI – you can also move this to a vault variable open_webui_volume_name: ollama_open_webui
webui_secret_key: "vk4HCy3FnlF0fqRT8MClJSGVmEdsP2tK" webui_secret_key: "vk4HCy3FnlF0fqRT8MClJSGVmEdsP2tK" # ← move to ansible-vault in production!
# -----------------------------------------------------------------
# Container images – pinning to tags is recommended for production.
# -----------------------------------------------------------------
ollama_image: "ollama/ollama:latest"
open_webui_image: "ghcr.io/open-webui/open-webui:main"
# npm_image: "jc21/nginx-proxy-manager:latest" # (commented out)
tasks: tasks:
- name: Create named volumes (optional but cleaner than host paths)
# ----------------------------------------------------------------- community.docker.docker_volume:
# 1️⃣ Install Podman (and the NVIDIA container toolkit if you need it) name: "{{ item }}"
# -----------------------------------------------------------------
- name: Install podman (Debian/Ubuntu)
ansible.builtin.apt:
name:
- podman
- ca-certificates
- curl
- gnupg
state: present state: present
update_cache: true loop:
when: ansible_facts.os_family == "Debian" - "{{ ollama_volume_name }}"
- "{{ open_webui_volume_name }}"
- name: Install podman (RHEL/CentOS/Fedora) - name: Deploy Ollama container
ansible.builtin.dnf: community.docker.docker_container:
name: podman
state: present
when: ansible_facts.os_family == "RedHat"
# -----------------------------------------------------------------
# 2️⃣ Create the named Podman volumes
# -----------------------------------------------------------------
- name: Create volume for Ollama data
containers.podman.podman_volume:
name: ollama name: ollama
state: present image: ollama/ollama:latest
- name: Create volume for Open‑WebUI data
containers.podman.podman_volume:
name: open-webui
state: present
# -----------------------------------------------------------------
# 3️⃣ Run the Ollama container (GPU‑enabled)
# -----------------------------------------------------------------
- name: Pull Ollama image
containers.podman.podman_image:
name: "{{ ollama_image }}"
pull: true
- name: Start Ollama container
containers.podman.podman_container:
name: ollama
image: "{{ ollma_image }}"
state: started state: started
restart_policy: unless-stopped restart_policy: unless-stopped
pull: true
tty: true tty: true
pull: true # same as `pull_policy: always` published_ports:
ports: - "{{ ollama_port }}:11434"
- "11434:11434"
volumes: volumes:
- "ollama:/root/.ollama" - "{{ ollama_volume_name }}:/root/.ollama"
# GPU access – expose *all* NVIDIA devices (the same as the compose file) device_requests:
devices: - driver: nvidia
- "/dev/nvidiactl:/dev/nvidiactl" count: -1 # -1 = all GPUs (or use device_ids: ['0', '1'] for specific)
- "/dev/nvidia-uvm:/dev/nvidia-uvm" capabilities:
- "/dev/nvidia-uvm-tools:/dev/nvidia-uvm-tools" - - gpu # nested list as per docs
- "/dev/nvidia0:/dev/nvidia0" comparisons:
- "/dev/nvidia1:/dev/nvidia1" image: strict
- "/dev/nvidia2:/dev/nvidia2" env: strict
- "/dev/nvidia3:/dev/nvidia3" volumes: strict
# If you only have a single GPU you can keep just /dev/nvidia0, # container_default_behavior: no_defaults # optional, modern default
# or use a loop with `count: all` in the compose – here we expose register: ollama_deploy
# the typical device nodes. Adjust if your system uses a different
# naming scheme.
env:
# Optional – explicit, matches the commented out env in the compose
NVIDIA_VISIBLE_DEVICES: "all"
# ----------------------------------------------------------------- - name: Deploy Open WebUI container
# 4️⃣ Run the Open‑WebUI container (depends on Ollama) community.docker.docker_container:
# -----------------------------------------------------------------
- name: Pull Open‑WebUI image
containers.podman.podman_image:
name: "{{ open_webui_image }}"
pull: true
- name: Start Open‑WebUI container
containers.podman.podman_container:
name: open-webui name: open-webui
image: "{{ open_webui_image }}" image: ghcr.io/open-webui/open-webui:main
state: started state: started
restart_policy: unless-stopped restart_policy: unless-stopped
ports: pull: true
published_ports:
- "{{ open_webui_port }}:8080" - "{{ open_webui_port }}:8080"
volumes: volumes:
- "open-webui:/app/backend/data" - "{{ open_webui_volume_name }}:/app/backend/data"
env: env:
OLLAMA_BASE_URL: "http://ollama:11434" OLLAMA_BASE_URL: "http://ollama:11434" # container → container via name
WEBUI_SECRET_KEY: "{{ webui_secret_key }}" WEBUI_SECRET_KEY: "{{ webui_secret_key }}"
extra_hosts: extra_hosts:
- "host.docker.internal:host-gateway" host.docker.internal: host-gateway
depends_on: # networks:
- ollama # ensures podman waits for ollama to be up # - name: bridge # default anyway
# No special GPU handling needed here – it talks to Ollama over the network depends_on: [] # no real depends_on in docker_container → use wait or handler if critical
comparisons:
image: strict
env: strict
volumes: strict
when: ollama_deploy.changed or not ollama_deploy.container # optional: only if ollama exists/changed
# ----------------------------------------------------------------- # Optional: wait for Ollama API to become responsive before starting WebUI
# 5️⃣ (Optional) Deploy the NPM / Nginx‑Proxy‑Manager service - name: Wait for Ollama to be ready
# ----------------------------------------------------------------- ansible.builtin.uri:
# Uncomment the block below if you ever need the commented‑out service url: "http://localhost:{{ ollama_port }}/api/tags"
# from the original compose file. method: GET
# status_code: 200
# - name: Pull NPM image return_content: no
# containers.podman.podman_image: register: ollama_ready
# name: "{{ npm_image }}" until: ollama_ready.status == 200
# pull: true retries: 30
# delay: 5
# - name: Start NPM container when: ollama_deploy.changed
# containers.podman.podman_container:
# name: npm
# image: "{{ npm_image }}"
# state: started
# restart_policy: unless-stopped
# ports:
# - "80:80"
# - "81:81"
# - "443:443"
# volumes:
# - "./data:/data"
# - "./letsencrypt:/etc/letsencrypt"
# ----------------------------------------------------------------- - name: Debug deployment status
# 6️⃣ Print a short summary for the operator
# -----------------------------------------------------------------
- name: Show deployment summary
ansible.builtin.debug: ansible.builtin.debug:
msg: | msg:
-------------------------------------------------------------- - "Ollama container: {{ ollama_deploy.container.State.Status | default('unknown') }}"
✅ Ollama → http://{{ ansible_host }}:11434 - "Open WebUI listening on port {{ open_webui_port }}"
✅ Open‑WebUI → http://{{ ansible_host }}:{{ open_webui_port }}
--------------------------------------------------------------
# ------------------------------------------------------------
# End of playbook
# ------------------------------------------------------------