Manage Ollama setup for homelab host
This commit is contained in:
parent
172bcca975
commit
5504dd7b2e
|
|
@ -853,6 +853,15 @@ other nodes can reach `OLLAMA_HOST=http://192.168.100.73:11434`:
|
||||||
./jeannie website-ollama-listen
|
./jeannie website-ollama-listen
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The Debian host bootstrap also manages Ollama when `debian_pc_install_ollama`
|
||||||
|
is true: it installs the service, stores models under `/data/ollama/models`,
|
||||||
|
binds the API to the configured LAN listener, and pulls the lightweight
|
||||||
|
`ai_gateway.model`. On an existing host, apply just this setup with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./jeannie ollama-setup
|
||||||
|
```
|
||||||
|
|
||||||
`jeannie` also has a backstage local AI helper for doctor commands.
|
`jeannie` also has a backstage local AI helper for doctor commands.
|
||||||
It is not a separate CLI action; when `ai_gateway.enabled` is true in
|
It is not a separate CLI action; when `ai_gateway.enabled` is true in
|
||||||
`homelab.yml`, doctor commands try the configured Ollama model and silently
|
`homelab.yml`, doctor commands try the configured Ollama model and silently
|
||||||
|
|
|
||||||
|
|
@ -853,6 +853,15 @@ other nodes can reach `OLLAMA_HOST=http://192.168.100.73:11434`:
|
||||||
./{{ main_script }} website-ollama-listen
|
./{{ main_script }} website-ollama-listen
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The Debian host bootstrap also manages Ollama when `debian_pc_install_ollama`
|
||||||
|
is true: it installs the service, stores models under `/data/ollama/models`,
|
||||||
|
binds the API to the configured LAN listener, and pulls the lightweight
|
||||||
|
`ai_gateway.model`. On an existing host, apply just this setup with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./{{ main_script }} ollama-setup
|
||||||
|
```
|
||||||
|
|
||||||
`{{ main_script }}` also has a backstage local AI helper for doctor commands.
|
`{{ main_script }}` also has a backstage local AI helper for doctor commands.
|
||||||
It is not a separate CLI action; when `ai_gateway.enabled` is true in
|
It is not a separate CLI action; when `ai_gateway.enabled` is true in
|
||||||
`homelab.yml`, doctor commands try the configured Ollama model and silently
|
`homelab.yml`, doctor commands try the configured Ollama model and silently
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ The playbook:
|
||||||
- installs user-level pipx CLI tools such as `yt-dlp`, plus runtime helpers
|
- installs user-level pipx CLI tools such as `yt-dlp`, plus runtime helpers
|
||||||
such as `ffmpeg` and `nodejs`
|
such as `ffmpeg` and `nodejs`
|
||||||
- installs `age` and `sops` for encrypted repo-managed secrets
|
- installs `age` and `sops` for encrypted repo-managed secrets
|
||||||
|
- installs and configures Ollama for homelab-local AI helpers when
|
||||||
|
`debian_pc_install_ollama` is true
|
||||||
- installs Zoom from the upstream `.deb` when requested on amd64
|
- installs Zoom from the upstream `.deb` when requested on amd64
|
||||||
- adds `jv` to expected local groups
|
- adds `jv` to expected local groups
|
||||||
- enables core services such as Docker, containerd, kubelet, ssh, cron, and
|
- enables core services such as Docker, containerd, kubelet, ssh, cron, and
|
||||||
|
|
@ -48,3 +50,13 @@ After the playbook finishes, initialize the Debian host's SOPS identity with:
|
||||||
./jeannie secrets-init
|
./jeannie secrets-init
|
||||||
./jeannie secrets-check
|
./jeannie secrets-check
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Ollama is configured to listen on the LAN and keep models under
|
||||||
|
`/data/ollama/models`. The default lightweight model for `jeannie` diagnostics is
|
||||||
|
pulled during bootstrap. To apply only the Ollama setup on an existing Debian
|
||||||
|
host, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./jeannie ollama-setup
|
||||||
|
./jeannie ai-check
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,16 @@ debian_pc_user: jv
|
||||||
debian_pc_user_home: "/home/{{ debian_pc_user }}"
|
debian_pc_user_home: "/home/{{ debian_pc_user }}"
|
||||||
debian_pc_kubernetes_minor_version: v1.36
|
debian_pc_kubernetes_minor_version: v1.36
|
||||||
debian_pc_enable_passwordless_sudo: true
|
debian_pc_enable_passwordless_sudo: true
|
||||||
|
debian_pc_install_ollama: true
|
||||||
|
debian_pc_ollama_install_url: https://ollama.com/install.sh
|
||||||
|
debian_pc_ollama_host: 0.0.0.0:11434
|
||||||
|
debian_pc_ollama_models_dir: /data/ollama/models
|
||||||
|
debian_pc_ollama_default_model: qwen2.5:0.5b
|
||||||
|
|
||||||
debian_pc_persistent_directories:
|
debian_pc_persistent_directories:
|
||||||
- /data/openebs/local/registry
|
- /data/openebs/local/registry
|
||||||
- /data/docker
|
- /data/docker
|
||||||
|
- /data/ollama/models
|
||||||
- "/home/{{ debian_pc_user }}/git-server"
|
- "/home/{{ debian_pc_user }}/git-server"
|
||||||
- "/home/{{ debian_pc_user }}/backups/gitea"
|
- "/home/{{ debian_pc_user }}/backups/gitea"
|
||||||
- "/home/{{ debian_pc_user }}/backups/gitea-restore-drills"
|
- "/home/{{ debian_pc_user }}/backups/gitea-restore-drills"
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,54 @@
|
||||||
mode: "{{ '0755' if item.startswith(debian_pc_user_home) else '0775' }}"
|
mode: "{{ '0755' if item.startswith(debian_pc_user_home) else '0775' }}"
|
||||||
loop: "{{ debian_pc_persistent_directories }}"
|
loop: "{{ debian_pc_persistent_directories }}"
|
||||||
|
|
||||||
|
- name: Check whether Ollama is already installed
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: command -v ollama >/dev/null 2>&1
|
||||||
|
register: debian_pc_ollama_installed
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
when: debian_pc_install_ollama | bool
|
||||||
|
|
||||||
|
- name: Install Ollama from official Linux installer
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -euo pipefail
|
||||||
|
tmp_installer="$(mktemp)"
|
||||||
|
trap 'rm -f "${tmp_installer}"' EXIT
|
||||||
|
curl -fsSL "{{ debian_pc_ollama_install_url }}" -o "${tmp_installer}"
|
||||||
|
sh "${tmp_installer}"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
when:
|
||||||
|
- debian_pc_install_ollama | bool
|
||||||
|
- debian_pc_ollama_installed.rc | default(1) != 0
|
||||||
|
|
||||||
|
- name: Ensure Ollama model storage exists on data disk
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ debian_pc_ollama_models_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: ollama
|
||||||
|
group: ollama
|
||||||
|
mode: "0775"
|
||||||
|
when: debian_pc_install_ollama | bool
|
||||||
|
|
||||||
|
- name: Ensure Ollama systemd override directory exists
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/systemd/system/ollama.service.d
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
when: debian_pc_install_ollama | bool
|
||||||
|
|
||||||
|
- name: Configure Ollama for homelab LAN access and data storage
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/systemd/system/ollama.service.d/homelab.conf
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
[Service]
|
||||||
|
Environment="OLLAMA_HOST={{ debian_pc_ollama_host }}"
|
||||||
|
Environment="OLLAMA_MODELS={{ debian_pc_ollama_models_dir }}"
|
||||||
|
register: debian_pc_ollama_override
|
||||||
|
when: debian_pc_install_ollama | bool
|
||||||
|
|
||||||
- name: Enable expected services when installed
|
- name: Enable expected services when installed
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
|
|
@ -237,6 +285,42 @@
|
||||||
loop: "{{ debian_pc_enable_services }}"
|
loop: "{{ debian_pc_enable_services }}"
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Enable and start Ollama
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: ollama
|
||||||
|
enabled: true
|
||||||
|
state: "{{ 'restarted' if debian_pc_ollama_override.changed | default(false) else 'started' }}"
|
||||||
|
daemon_reload: true
|
||||||
|
when: debian_pc_install_ollama | bool
|
||||||
|
|
||||||
|
- name: Wait for Ollama API
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: http://127.0.0.1:11434/api/tags
|
||||||
|
method: GET
|
||||||
|
status_code: 200
|
||||||
|
register: debian_pc_ollama_api
|
||||||
|
retries: 12
|
||||||
|
delay: 5
|
||||||
|
until: debian_pc_ollama_api.status == 200
|
||||||
|
when: debian_pc_install_ollama | bool
|
||||||
|
|
||||||
|
- name: Pull default Ollama model for backstage homelab diagnostics
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -euo pipefail
|
||||||
|
if ollama list | awk -v model="{{ debian_pc_ollama_default_model }}" 'NR > 1 && ($1 == model || $1 == model ":latest") { found = 1 } END { exit found ? 0 : 1 }'; then
|
||||||
|
echo present
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
ollama pull "{{ debian_pc_ollama_default_model }}"
|
||||||
|
echo pulled
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: debian_pc_ollama_pull_result
|
||||||
|
changed_when: "'pulled' in debian_pc_ollama_pull_result.stdout"
|
||||||
|
environment:
|
||||||
|
OLLAMA_HOST: http://127.0.0.1:11434
|
||||||
|
when: debian_pc_install_ollama | bool
|
||||||
|
|
||||||
- name: Check whether config archive is present
|
- name: Check whether config archive is present
|
||||||
ansible.builtin.stat:
|
ansible.builtin.stat:
|
||||||
path: "{{ debian_pc_config_archive }}"
|
path: "{{ debian_pc_config_archive }}"
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,8 @@ services:
|
||||||
ollama:
|
ollama:
|
||||||
host: debian
|
host: debian
|
||||||
url: http://192.168.100.73:11434
|
url: http://192.168.100.73:11434
|
||||||
|
bind_address: 0.0.0.0:11434
|
||||||
|
models_dir: /data/ollama/models
|
||||||
rpi_dns:
|
rpi_dns:
|
||||||
host: rpi4
|
host: rpi4
|
||||||
pihole_dns_port: 53
|
pihole_dns_port: 53
|
||||||
|
|
|
||||||
54
jeannie
54
jeannie
|
|
@ -58,6 +58,8 @@ mapping = {
|
||||||
"services.gitea.root_url": "LAB_GITEA_ROOT_URL",
|
"services.gitea.root_url": "LAB_GITEA_ROOT_URL",
|
||||||
"services.gitea.ssh_remote": "LAB_GITOPS_REPO_URL",
|
"services.gitea.ssh_remote": "LAB_GITOPS_REPO_URL",
|
||||||
"services.local_registry.endpoint": "LAB_REGISTRY_ENDPOINT",
|
"services.local_registry.endpoint": "LAB_REGISTRY_ENDPOINT",
|
||||||
|
"services.ollama.bind_address": "LAB_OLLAMA_BIND_ADDRESS",
|
||||||
|
"services.ollama.models_dir": "LAB_OLLAMA_MODELS_DIR",
|
||||||
"services.rpi_dns.pihole_web_port": "PIHOLE_WEB_PORT",
|
"services.rpi_dns.pihole_web_port": "PIHOLE_WEB_PORT",
|
||||||
"services.rpi_dns.uptime_kuma_port": "UPTIME_KUMA_PORT",
|
"services.rpi_dns.uptime_kuma_port": "UPTIME_KUMA_PORT",
|
||||||
"ai_gateway.provider": "LAB_AI_GATEWAY_PROVIDER",
|
"ai_gateway.provider": "LAB_AI_GATEWAY_PROVIDER",
|
||||||
|
|
@ -3389,9 +3391,10 @@ website_translation_model() {
|
||||||
}
|
}
|
||||||
|
|
||||||
website_ollama_listen() {
|
website_ollama_listen() {
|
||||||
local bind_address="${WEBSITE_OLLAMA_BIND_ADDRESS:-0.0.0.0:11434}"
|
local bind_address="${WEBSITE_OLLAMA_BIND_ADDRESS:-${LAB_OLLAMA_BIND_ADDRESS:-0.0.0.0:11434}}"
|
||||||
|
local models_dir="${LAB_OLLAMA_MODELS_DIR:-/data/ollama/models}"
|
||||||
local dropin_dir="/etc/systemd/system/ollama.service.d"
|
local dropin_dir="/etc/systemd/system/ollama.service.d"
|
||||||
local dropin_file="${dropin_dir}/homelab-listen.conf"
|
local dropin_file="${dropin_dir}/homelab.conf"
|
||||||
|
|
||||||
require_debian_server "website-ollama-listen"
|
require_debian_server "website-ollama-listen"
|
||||||
|
|
||||||
|
|
@ -3402,7 +3405,11 @@ website_ollama_listen() {
|
||||||
|
|
||||||
echo "Configuring ollama.service to listen on ${bind_address}..."
|
echo "Configuring ollama.service to listen on ${bind_address}..."
|
||||||
sudo mkdir -p "${dropin_dir}"
|
sudo mkdir -p "${dropin_dir}"
|
||||||
printf '[Service]\nEnvironment="OLLAMA_HOST=%s"\n' "${bind_address}" |
|
sudo mkdir -p "${models_dir}"
|
||||||
|
if id ollama >/dev/null 2>&1; then
|
||||||
|
sudo chown ollama:ollama "${models_dir}"
|
||||||
|
fi
|
||||||
|
printf '[Service]\nEnvironment="OLLAMA_HOST=%s"\nEnvironment="OLLAMA_MODELS=%s"\n' "${bind_address}" "${models_dir}" |
|
||||||
sudo tee "${dropin_file}" >/dev/null
|
sudo tee "${dropin_file}" >/dev/null
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl restart ollama.service
|
sudo systemctl restart ollama.service
|
||||||
|
|
@ -3413,6 +3420,42 @@ website_ollama_listen() {
|
||||||
echo "Ollama API is reachable on the Debian host."
|
echo "Ollama API is reachable on the Debian host."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ollama_setup() {
|
||||||
|
local bind_address="${LAB_OLLAMA_BIND_ADDRESS:-0.0.0.0:11434}"
|
||||||
|
local models_dir="${LAB_OLLAMA_MODELS_DIR:-/data/ollama/models}"
|
||||||
|
local model="${LAB_AI_GATEWAY_MODEL:-qwen2.5:0.5b}"
|
||||||
|
local installer_url="${LAB_OLLAMA_INSTALL_URL:-https://ollama.com/install.sh}"
|
||||||
|
local tmp_installer
|
||||||
|
|
||||||
|
require_debian_server "ollama-setup"
|
||||||
|
|
||||||
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
|
echo "curl is required to install Ollama." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v ollama >/dev/null 2>&1; then
|
||||||
|
echo "Installing Ollama from ${installer_url}..."
|
||||||
|
tmp_installer="$(mktemp)"
|
||||||
|
curl -fsSL "${installer_url}" -o "${tmp_installer}"
|
||||||
|
sudo sh "${tmp_installer}"
|
||||||
|
rm -f "${tmp_installer}"
|
||||||
|
else
|
||||||
|
echo "Ollama is already installed: $(command -v ollama)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
website_ollama_listen
|
||||||
|
|
||||||
|
echo "Ensuring Ollama model ${model} is available..."
|
||||||
|
if ollama list | awk -v model="${model}" 'NR > 1 && ($1 == model || $1 == model ":latest") { found = 1 } END { exit found ? 0 : 1 }'; then
|
||||||
|
echo "Ollama model ${model} is already present."
|
||||||
|
else
|
||||||
|
OLLAMA_HOST=http://127.0.0.1:11434 ollama pull "${model}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Ollama homelab setup is ready."
|
||||||
|
}
|
||||||
|
|
||||||
apps() {
|
apps() {
|
||||||
local buildx_builder_ready=false
|
local buildx_builder_ready=false
|
||||||
local demos_image_built=false
|
local demos_image_built=false
|
||||||
|
|
@ -4728,6 +4771,9 @@ case "${1:-}" in
|
||||||
website-ollama-listen)
|
website-ollama-listen)
|
||||||
website_ollama_listen
|
website_ollama_listen
|
||||||
;;
|
;;
|
||||||
|
ollama-setup)
|
||||||
|
ollama_setup
|
||||||
|
;;
|
||||||
deploy-gitea)
|
deploy-gitea)
|
||||||
deploy_gitea
|
deploy_gitea
|
||||||
;;
|
;;
|
||||||
|
|
@ -4789,7 +4835,7 @@ case "${1:-}" in
|
||||||
nuke
|
nuke
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Usage: $0 {up|rebuild-cluster|stop-cluster|start-cluster|status|apps|website-translation-model|website-ollama-listen|deploy-gitea|rpi-services|bootstrap-gitea-repo|backup-gitea|drill-gitea-restore|install-gitea-runner|move-prometheus-stack-workers|doctor-versions|doctor-edge|doctor-gitea|doctor-rpi|doctor-cluster|preflight|secrets-init|secrets-check|tailnet-policy-check|ai-index|ai-check|openwrt|nuke}"
|
echo "Usage: $0 {up|rebuild-cluster|stop-cluster|start-cluster|status|apps|website-translation-model|website-ollama-listen|ollama-setup|deploy-gitea|rpi-services|bootstrap-gitea-repo|backup-gitea|drill-gitea-restore|install-gitea-runner|move-prometheus-stack-workers|doctor-versions|doctor-edge|doctor-gitea|doctor-rpi|doctor-cluster|preflight|secrets-init|secrets-check|tailnet-policy-check|ai-index|ai-check|openwrt|nuke}"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue