From 2af73b780b53683c8df38c735a20fb66b63a14d0 Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 20 Mar 2026 13:20:58 +0100 Subject: [PATCH] ... --- .gitignore | 1 + ansible/deploy-ai-at-home.yml | 8 ++++ ansible/deploy-ollama.yml | 6 +++ ansible/deploy-openwebui.yml | 6 +++ .../inventory/example/host_vars/yourpc.yml | 8 ++++ ansible/inventory/example/hosts | 8 ++++ ansible/roles/ai_at_home/defaults/main.yml | 19 ++++++++ ansible/roles/ai_at_home/files/runme.sh | 17 +++++++ ansible/roles/ai_at_home/files/runme_wip.sh | 3 ++ ansible/roles/ai_at_home/files/stopme.sh | 15 +++++++ .../roles/ai_at_home/tasks/deploy/apisix.yml | 21 +++++++++ .../roles/ai_at_home/tasks/deploy/main.yml | 45 +++++++++++++++++++ ansible/roles/ai_at_home/tasks/main.yml | 5 +++ .../ai_at_home/templates/aiathome.config | 5 +++ .../ai_at_home/templates/apisix_config.yml | 11 +++++ .../ai_at_home/templates/composefile.yml | 26 +++++++++++ .../roles/ai_at_home/templates/sablier.yml | 34 ++++++++++++++ ansible/roles/ollama/defaults/main.yml | 5 +++ ansible/roles/ollama/tasks/deploy/main.yml | 18 ++++++++ ansible/roles/ollama/tasks/main.yml | 5 +++ ansible/roles/ollama/tasks/teardown/main.yml | 0 .../roles/ollama/templates/composefile.yml | 20 +++++++++ ansible/roles/openwebui/defaults/main.yml | 5 +++ ansible/roles/openwebui/tasks/deploy/main.yml | 19 ++++++++ ansible/roles/openwebui/tasks/main.yml | 5 +++ .../roles/openwebui/tasks/teardown/main.yml | 1 + .../roles/openwebui/templates/composefile.yml | 17 +++++++ 27 files changed, 333 insertions(+) create mode 100644 .gitignore create mode 100644 ansible/deploy-ai-at-home.yml create mode 100644 ansible/deploy-ollama.yml create mode 100644 ansible/deploy-openwebui.yml create mode 100644 ansible/inventory/example/host_vars/yourpc.yml create mode 100644 ansible/inventory/example/hosts create mode 100644 ansible/roles/ai_at_home/defaults/main.yml create mode 100644 ansible/roles/ai_at_home/files/runme.sh create mode 100644 ansible/roles/ai_at_home/files/runme_wip.sh create mode 100644 ansible/roles/ai_at_home/files/stopme.sh create mode 100644 ansible/roles/ai_at_home/tasks/deploy/apisix.yml create mode 100644 ansible/roles/ai_at_home/tasks/deploy/main.yml create mode 100644 ansible/roles/ai_at_home/tasks/main.yml create mode 100644 ansible/roles/ai_at_home/templates/aiathome.config create mode 100644 ansible/roles/ai_at_home/templates/apisix_config.yml create mode 100644 ansible/roles/ai_at_home/templates/composefile.yml create mode 100644 ansible/roles/ai_at_home/templates/sablier.yml create mode 100644 ansible/roles/ollama/defaults/main.yml create mode 100644 ansible/roles/ollama/tasks/deploy/main.yml create mode 100644 ansible/roles/ollama/tasks/main.yml create mode 100644 ansible/roles/ollama/tasks/teardown/main.yml create mode 100644 ansible/roles/ollama/templates/composefile.yml create mode 100644 ansible/roles/openwebui/defaults/main.yml create mode 100644 ansible/roles/openwebui/tasks/deploy/main.yml create mode 100644 ansible/roles/openwebui/tasks/main.yml create mode 100644 ansible/roles/openwebui/tasks/teardown/main.yml create mode 100644 ansible/roles/openwebui/templates/composefile.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e3a6ad2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +ansible/inventory/joe_at_home diff --git a/ansible/deploy-ai-at-home.yml b/ansible/deploy-ai-at-home.yml new file mode 100644 index 0000000..1707d4a --- /dev/null +++ b/ansible/deploy-ai-at-home.yml @@ -0,0 +1,8 @@ +--- +- name: Install Ai @ Home + hosts: ai_at_home + + roles: + - ollama + - openwebui + - ai_at_home \ No newline at end of file diff --git a/ansible/deploy-ollama.yml b/ansible/deploy-ollama.yml new file mode 100644 index 0000000..cf4079b --- /dev/null +++ b/ansible/deploy-ollama.yml @@ -0,0 +1,6 @@ +--- +- name: Install Ollama + hosts: ollama + + roles: + - ollama \ No newline at end of file diff --git a/ansible/deploy-openwebui.yml b/ansible/deploy-openwebui.yml new file mode 100644 index 0000000..6ed13cd --- /dev/null +++ b/ansible/deploy-openwebui.yml @@ -0,0 +1,6 @@ +--- +- name: Install Openwebui + hosts: openwebui + + roles: + - openwebui \ No newline at end of file diff --git a/ansible/inventory/example/host_vars/yourpc.yml b/ansible/inventory/example/host_vars/yourpc.yml new file mode 100644 index 0000000..4afa0ef --- /dev/null +++ b/ansible/inventory/example/host_vars/yourpc.yml @@ -0,0 +1,8 @@ +--- +ai_at_home_install_dir: /home/youruser/Projekte/ai_at_home +openwebui_install_dir: "{{ ai_at_home_install_dir }}/openwebui" + +common_container_labels: +- sablier.enable=true +ollama_container_labels: {{ common_container_labels + ["sablier.group=ai_backends"] }} +openwebui_container_labels: {{ common_container_labels + ["sablier.group=ai_frontends"] }} diff --git a/ansible/inventory/example/hosts b/ansible/inventory/example/hosts new file mode 100644 index 0000000..c15882e --- /dev/null +++ b/ansible/inventory/example/hosts @@ -0,0 +1,8 @@ +[ollama] +yourpc + +[openwebui] +yourpc + +[ai_at_home] +yourpc diff --git a/ansible/roles/ai_at_home/defaults/main.yml b/ansible/roles/ai_at_home/defaults/main.yml new file mode 100644 index 0000000..b88c48b --- /dev/null +++ b/ansible/roles/ai_at_home/defaults/main.yml @@ -0,0 +1,19 @@ +--- +sablier_image: sablierapp/sablier +sablier_image_tag: latest +apisix_image: apache/apisix +apisix_image_tag: latest + + + +ai_at_home_install_dir: /opt/ai_at_home + +ollama_install_dir: /opt/ollama +ollama_composefile: "{{ ollama_install_dir }}/compose/composefile.yml" +openwebui_install_dir: /opt/openwebui +openwebui_composefile: "{{ openwebui_install_dir }}/compose/composefile.yml" + + +# images +# gpt-oss:20b +# qwen3-coder-next diff --git a/ansible/roles/ai_at_home/files/runme.sh b/ansible/roles/ai_at_home/files/runme.sh new file mode 100644 index 0000000..c87f4b2 --- /dev/null +++ b/ansible/roles/ai_at_home/files/runme.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -a + +CONFIG_FILE=$(dirname "$(readlink -f "$0")")/aiathome.config +OLLAMA_COMPOSEFILE=${OLLAMA_COMPOSEFILE:-/opt/ollama/compose/composefile.yml} +OPENWEBUI_COMPOSEFILE=${OPENWEBUI_COMPOSEFILE:-/opt/openwebui/compose/composefile.yml} + +[[ -f ${CONFIG_FILE} ]] && source ${CONFIG_FILE} + +docker compose -f ${OLLAMA_COMPOSEFILE} up -d +docker compose -f ${OPENWEBUI_COMPOSEFILE} up -d + +# TODO: Create a stack based on the config and define multiple backends... +# Launch Backends on Demand instead of just using ollama... +# Maybe with the traefik middleware? https://plugins.traefik.io/plugins/6715d1d37dd5a6c3095befd4/sablier +#https://github.com/sablierapp/sablier \ No newline at end of file diff --git a/ansible/roles/ai_at_home/files/runme_wip.sh b/ansible/roles/ai_at_home/files/runme_wip.sh new file mode 100644 index 0000000..b2aa584 --- /dev/null +++ b/ansible/roles/ai_at_home/files/runme_wip.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +# \ No newline at end of file diff --git a/ansible/roles/ai_at_home/files/stopme.sh b/ansible/roles/ai_at_home/files/stopme.sh new file mode 100644 index 0000000..af79f9a --- /dev/null +++ b/ansible/roles/ai_at_home/files/stopme.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -a + +CONFIG_FILE=$(dirname "$(readlink -f "$0")")/aiathome.config +OLLAMA_COMPOSEFILE=${OLLAMA_COMPOSEFILE:-/opt/ollama/compose/composefile.yml} +OPENWEBUI_COMPOSEFILE=${OPENWEBUI_COMPOSEFILE:-/opt/openwebui/compose/composefile.yml} + +[[ -f ${CONFIG_FILE} ]] && source ${CONFIG_FILE} + +docker compose -f ${OLLAMA_COMPOSEFILE} stop +docker compose -f ${OPENWEBUI_COMPOSEFILE} stop + +docker compose -f ${OLLAMA_COMPOSEFILE} rm -f +docker compose -f ${OPENWEBUI_COMPOSEFILE} rm -f \ No newline at end of file diff --git a/ansible/roles/ai_at_home/tasks/deploy/apisix.yml b/ansible/roles/ai_at_home/tasks/deploy/apisix.yml new file mode 100644 index 0000000..f4043a5 --- /dev/null +++ b/ansible/roles/ai_at_home/tasks/deploy/apisix.yml @@ -0,0 +1,21 @@ +--- +- name: Create directories + ansible.builtin.file: + state: directory + path: "{{ item }}" + loop: + - "{{ apisix_install_dir }}" + - "{{ apisix_install_dir }}/config" + + +- name: Pull Apisix Image + community.docker.docker_image: + source: pull + name: "{{ apisix_image }}:{{ apisix_image_tag }}" + +- name: Copy Config file + +docker run -d --name apache-apisix \ + -p 9080:9080 \ + -e APISIX_STAND_ALONE=true \ + apache/apisix \ No newline at end of file diff --git a/ansible/roles/ai_at_home/tasks/deploy/main.yml b/ansible/roles/ai_at_home/tasks/deploy/main.yml new file mode 100644 index 0000000..0c651d7 --- /dev/null +++ b/ansible/roles/ai_at_home/tasks/deploy/main.yml @@ -0,0 +1,45 @@ +--- +- name: Create Install Dir + ansible.builtin.file: + path: "{{ ai_at_home_install_dir }}" + state: directory + mode: "0755" + loop: + - "{{ ai_at_home_install_dir }}" + - "{{ ai_at_home_install_dir }}/compose" + - "{{ ai_at_home_install_dir }}/sablier/config" + - "{{ ai_at_home_install_dir }}/apisix/plugins" + - "{{ ai_at_home_install_dir }}/apisix/config" + + +- name: Pull Images + community.docker.docker_image: + source: pull + name: "{{ item }}" + loop: + - "{{ sablier_image }}:{{ sablier_image_tag }}" + - "{{ apisix_image }}:{{ apisix_image_tag }}" + +- name: Copy Templates + ansible.builtin.template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + mode: "0644" + loop: + - src: aiathome.config + dest: "{{ ai_at_home_install_dir }}/aiathome.config" + - src: composefile.yml + dest: "{{ ai_at_home_install_dir }}/compose/composefile.yml" + - src: sablier.yml + dest: "{{ ai_at_home_install_dir }}/sablier/sablier.yml" + + + +- name: Copy Script + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ ai_at_home_install_dir }}/{{ item }}" + mode: "0755" + loop: + - runme.sh + - stopme.sh diff --git a/ansible/roles/ai_at_home/tasks/main.yml b/ansible/roles/ai_at_home/tasks/main.yml new file mode 100644 index 0000000..52a9446 --- /dev/null +++ b/ansible/roles/ai_at_home/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- name: Include selected operations for Ai @ Home + tags: + - aiathome + ansible.builtin.include_tasks: "{{ deployment_action|default('deploy') }}/main.yml" \ No newline at end of file diff --git a/ansible/roles/ai_at_home/templates/aiathome.config b/ansible/roles/ai_at_home/templates/aiathome.config new file mode 100644 index 0000000..13a8f17 --- /dev/null +++ b/ansible/roles/ai_at_home/templates/aiathome.config @@ -0,0 +1,5 @@ +OLLAMA_COMPOSEFILE={{ ollama_composefile }} +OPENWEBUI_COMPOSEFILE={{ openwebui_composefile }} + +# vllm/openwebui/ollama/openclawd etc.. +AI_STACK= \ No newline at end of file diff --git a/ansible/roles/ai_at_home/templates/apisix_config.yml b/ansible/roles/ai_at_home/templates/apisix_config.yml new file mode 100644 index 0000000..49f4ddb --- /dev/null +++ b/ansible/roles/ai_at_home/templates/apisix_config.yml @@ -0,0 +1,11 @@ +--- +deployment: + role: data_plane + role_data_plane: + config_provider: yaml + +wasm: + plugins: + - name: proxywasm_sablier_plugin + priority: 7997 + file: /wasm/sablierproxywasm.wasm diff --git a/ansible/roles/ai_at_home/templates/composefile.yml b/ansible/roles/ai_at_home/templates/composefile.yml new file mode 100644 index 0000000..afee14c --- /dev/null +++ b/ansible/roles/ai_at_home/templates/composefile.yml @@ -0,0 +1,26 @@ +--- +services: + apisix: + image: {{ apisix_image }}:{{ apisix_image_tag }} + env: + APISIX_STAND_ALONE: "true" + network_mode: host + volumes: + - {{ apisix_install_dir }}/config/apisix_config.yml:/usr/local/apisix/conf/config.yaml + + sablier: + image: {{ sablier_image }}:{{ sablier_image_tag }} + command: + - start + - --provider.name=docker + network_mode: host + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - {{ ai_at_home_install_dir }}/sablier/config:/etc/sablier + + +docker run --name sablier \ + -p 10000:10000 \ + -v /var/run/docker.sock:/var/run/docker.sock \ + sablierapp/sablier:1.10.5 \ + start --provider.name=docker \ No newline at end of file diff --git a/ansible/roles/ai_at_home/templates/sablier.yml b/ansible/roles/ai_at_home/templates/sablier.yml new file mode 100644 index 0000000..92ee386 --- /dev/null +++ b/ansible/roles/ai_at_home/templates/sablier.yml @@ -0,0 +1,34 @@ +--- +provider: + # Provider to use to manage containers (docker, swarm, kubernetes) + name: docker +server: + # The server port to use + port: 10000 + # The base path for the API + base-path: / +storage: + # File path to save the state (default stateless) + file: +sessions: + # The default session duration (default 5m) + default-duration: 5m + # The expiration checking interval. + # Higher duration gives less stress on CPU. + # If you only use sessions of 1h, setting this to 5m is a good trade-off. + expiration-interval: 20s +logging: + level: debug +strategy: + dynamic: + # Custom themes folder, will load all .html files recursively (default empty) + custom-themes-path: + # Show instances details by default in waiting UI + show-details-by-default: false + # Default theme used for dynamic strategy (default "hacker-terminal") + default-theme: hacker-terminal + # Default refresh frequency in the HTML page for dynamic strategy + default-refresh-frequency: 5s + blocking: + # Default timeout used for blocking strategy (default 1m) + default-timeout: 1m \ No newline at end of file diff --git a/ansible/roles/ollama/defaults/main.yml b/ansible/roles/ollama/defaults/main.yml new file mode 100644 index 0000000..d8f16c2 --- /dev/null +++ b/ansible/roles/ollama/defaults/main.yml @@ -0,0 +1,5 @@ +--- +ollama_install_dir: /opt/ollama +ollama_image: ollama/ollama +ollama_image_tag: latest +ollama_container_labels: [] diff --git a/ansible/roles/ollama/tasks/deploy/main.yml b/ansible/roles/ollama/tasks/deploy/main.yml new file mode 100644 index 0000000..11f5a62 --- /dev/null +++ b/ansible/roles/ollama/tasks/deploy/main.yml @@ -0,0 +1,18 @@ +--- +- name: Create Ollama Directories + ansible.builtin.file: + state: directory + path: "{{ ollama_install_dir }}/{{ item }}" + loop: + - data + - compose + +- name: Pull Ollama Image + community.docker.docker_image: + source: pull + name: "{{ ollama_image }}:{{ ollama_image_tag }}" + +- name: Copy composefile + ansible.builtin.template: + src: templates/composefile.yml + dest: "{{ ollama_install_dir }}/compose/composefile.yml" diff --git a/ansible/roles/ollama/tasks/main.yml b/ansible/roles/ollama/tasks/main.yml new file mode 100644 index 0000000..fa2e584 --- /dev/null +++ b/ansible/roles/ollama/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- name: Include selected operations for Ollama + tags: + - ollama + ansible.builtin.include_tasks: "{{ deployment_action|default('deploy') }}/main.yml" \ No newline at end of file diff --git a/ansible/roles/ollama/tasks/teardown/main.yml b/ansible/roles/ollama/tasks/teardown/main.yml new file mode 100644 index 0000000..e69de29 diff --git a/ansible/roles/ollama/templates/composefile.yml b/ansible/roles/ollama/templates/composefile.yml new file mode 100644 index 0000000..0cb63b2 --- /dev/null +++ b/ansible/roles/ollama/templates/composefile.yml @@ -0,0 +1,20 @@ +services: + + ollama: + image: {{ ollama_image }}:{{ ollama_image_tag }} + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: [gpu] + network_mode: host + volumes: + - {{ ollama_install_dir }}/data:/root/.ollama + tty: true + restart: unless-stopped + {% if ollama_container_labels %} + labels: + {{ ollama_container_labels|to_nice_yaml|indent(4) }} + {% endif %} diff --git a/ansible/roles/openwebui/defaults/main.yml b/ansible/roles/openwebui/defaults/main.yml new file mode 100644 index 0000000..6ff614e --- /dev/null +++ b/ansible/roles/openwebui/defaults/main.yml @@ -0,0 +1,5 @@ +--- +openwebui_install_dir: /opt/openwebui +openwebui_image: ghcr.io/open-webui/open-webui +openwebui_image_tag: main-slim +openwebui_container_labels: [] \ No newline at end of file diff --git a/ansible/roles/openwebui/tasks/deploy/main.yml b/ansible/roles/openwebui/tasks/deploy/main.yml new file mode 100644 index 0000000..8ac06e7 --- /dev/null +++ b/ansible/roles/openwebui/tasks/deploy/main.yml @@ -0,0 +1,19 @@ +--- + +- name: Create Directories + ansible.builtin.file: + state: directory + path: "{{ openwebui_install_dir }}/{{ item }}" + loop: + - data + - compose + +- name: Pull Openwebui Image + community.docker.docker_image: + source: pull + name: "{{ openwebui_image }}:{{ openwebui_image_tag }}" + +- name: Copy composefile + ansible.builtin.template: + src: templates/composefile.yml + dest: "{{ openwebui_install_dir }}/compose/composefile.yml" diff --git a/ansible/roles/openwebui/tasks/main.yml b/ansible/roles/openwebui/tasks/main.yml new file mode 100644 index 0000000..5ece749 --- /dev/null +++ b/ansible/roles/openwebui/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- name: Include selected operations for OpenWebUi + tags: + - openwebui + ansible.builtin.include_tasks: "{{ deployment_action|default('deploy') }}/main.yml" \ No newline at end of file diff --git a/ansible/roles/openwebui/tasks/teardown/main.yml b/ansible/roles/openwebui/tasks/teardown/main.yml new file mode 100644 index 0000000..73b314f --- /dev/null +++ b/ansible/roles/openwebui/tasks/teardown/main.yml @@ -0,0 +1 @@ +--- \ No newline at end of file diff --git a/ansible/roles/openwebui/templates/composefile.yml b/ansible/roles/openwebui/templates/composefile.yml new file mode 100644 index 0000000..2c906bc --- /dev/null +++ b/ansible/roles/openwebui/templates/composefile.yml @@ -0,0 +1,17 @@ +--- +services: + open-webui: + image: {{ openwebui_image }}:{{ openwebui_image_tag }} + network_mode: host + environment: + FORWARDED_ALLOW_IPS: '*' + OLLAMA_BASE_URL: http://localhost:11434 + OFFLINE_MODE: True + DEFAULT_USER_ROLE: user + volumes: + - {{ openwebui_install_dir }}/data:/app/backend/data + + {% if openwebui_container_labels %} + labels: + {{ openwebui_container_labels|to_nice_yaml|indent(4) }} + {% endif %}