--- # 2026-10-05 Hyperling # Install a local LLM for use offline. # - https://zeroclaw.net/blog/install-zeroclaw # - https://zeroclaw.net/blog/set-up-zeroclaw-bot-ollama-telegram # # Packages Details # - https://archlinux.org/packages/extra/x86_64/zeroclaw/ # - https://archlinux.org/packages/extra/x86_64/ollama/ # # Individual Guides # - https://github.com/zeroclaw-labs/zeroclaw # - https://wiki.archlinux.org/title/Ollama # # Model Explanations # - https://webscraft.org/blog/ollama-na-8-gb-ram-yaki-modeli-pratsyuyut-u-2026?lang=en # # Models # - https://ollama.com/search # Currently only testing this on Arch based distros (pacman). - name: Workstation | Linux | Software | ZeroClaw block: - name: Workstation | Linux | Software | ZeroClaw | Facts 01 ansible.builtin.set_fact: zeroclaw: zeroclaw ollama: ollama llm_installs: ##### QWEN ##### ### 3.5, the recommended latest model of QWEN. - qwen3.5:0.8b - qwen3.5:2b - qwen3.5:4b #- qwen3.5:9b #- qwen3.5:27b #- qwen3.5:35b ### 3.0 Coder #- qwen3-coder:30b ### 2.5 Coder, 7b recommended for code tasks vs QWEN 3.5 4b. - qwen2.5-coder:0.5b - qwen2.5-coder:1.5b - qwen2.5-coder:3b - qwen2.5-coder:7b #- qwen2.5-coder:14b #- qwen2.5-coder:32b ### 2.5, does not have "thinking" as an attribute, tempting! #- qwen2.5:0.5b #- qwen2.5:1.5b #- qwen2.5:3b #- qwen2.5:7b #- qwen2.5:14b #- qwen2.5:32b ### Others, TBD #- deepseek-r1:1.5b #- deepseek-r1:7b #- mistal:7b #- ministral:3b #- ministral:8b #- mistal:7b #- glm4-flash llm_removals: - qwen3:4b # QWEN3 is the most similar to Ask Brave. zerocode: zerocode - name: Workstation | Linux | Software | ZeroClaw | Facts 02 ansible.builtin.set_fact: ollama_runit_dir: "{{ runit_script_dir }}/{{ ollama }}" ollama_runit_log_dest: "{{ global_log }}/{{ ollama }}" zeroclaw_runit_dir: "{{ runit_script_dir }}/{{ zeroclaw }}" zeroclaw_runit_log_dest: "{{ global_log }}/{{ zeroclaw }}" - name: Workstation | Linux | Software | ZeroClaw | Facts 03 ansible.builtin.set_fact: ollama_runit_script: "{{ ollama_runit_dir }}/{{ runit_service_script }}" ollama_runit_log_dir: "{{ ollama_runit_dir }}/{{ runit_log_dir }}" ollama_runit_log_config: "{{ ollama_runit_log_dest }}/{{ global_log_config }}" zeroclaw_runit_script: "{{ zeroclaw_runit_dir }}/{{ runit_service_script }}" zeroclaw_runit_log_dir: "{{ zeroclaw_runit_dir }}/{{ runit_log_dir }}" zeroclaw_runit_log_config: "{{ zeroclaw_runit_log_dest }}/{{ global_log_config }}" - name: Workstation | Linux | Software | ZeroClaw | Facts 04 ansible.builtin.set_fact: ollama_runit_log_script: "{{ ollama_runit_log_dir }}/{{ runit_log_script }}" zeroclaw_runit_log_script: "{{ zeroclaw_runit_log_dir }}/{{ runit_log_script }}" - name: Workstation | Linux | Software | ZeroClaw | Install ansible.builtin.package: name: - "{{ zeroclaw }}" - "{{ ollama }}" - "{{ zerocode }}" state: present - name: Workstation | Linux | Software | ZeroClaw | ollama | runit | Dir | Run ansible.builtin.file: name: "{{ ollama_runit_dir }}" state: directory owner: root mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | ollama | runit | Dir | Log Run ansible.builtin.file: name: "{{ ollama_runit_log_dir }}" state: directory owner: root mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | ollama | runit | Dir | Log Config ansible.builtin.file: name: "{{ ollama_runit_log_dest }}" state: directory owner: "{{ user }}" mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | ollama | runit | Script | Run ansible.builtin.copy: content: | #!/bin/sh -e # Allow pulling LLMs for use with ZeroClaw. exec 2>&1 export HOME={{ user_user.home }} export OLLAMA_KEEP_ALIVE=-1 export OLLAMA_MAX_LOADED_MODELS=1 exec chpst -u {{ user }} ollama serve dest: "{{ ollama_runit_script }}" mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | ollama | runit | Script | Log ansible.builtin.copy: content: | #!/bin/sh -e exec svlogd -tt {{ ollama_runit_log_dest }} dest: "{{ ollama_runit_log_script }}" mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | ollama | runit | Script | Log Config ansible.builtin.copy: content: | s10000000 # rotate at 10 MB n5 # keep 5 old files dest: "{{ ollama_runit_log_config }}" owner: "{{ user }}" mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | ollama | Enable ansible.builtin.service: name: "{{ ollama }}" state: started enabled: true - name: Workstation | Linux | Software | ZeroClaw | zeroclaw | runit | Dir | Run ansible.builtin.file: name: "{{ zeroclaw_runit_dir }}" state: directory owner: root mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | zeroclaw | runit | Dir | Log ansible.builtin.file: name: "{{ zeroclaw_runit_log_dir }}" state: directory owner: root mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | zeroclaw | runit | Dir | Log Config ansible.builtin.file: name: "{{ zeroclaw_runit_log_dest }}" state: directory owner: "{{ user }}" mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | zeroclaw | runit | Script | File ansible.builtin.copy: content: | #!/bin/sh -e # Allow using the ZeroClaw frontend. exec 2>&1 exec chpst -u {{ user }} zeroclaw daemon dest: "{{ zeroclaw_runit_script }}" mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | zeroclaw | runit | Script | Log ansible.builtin.copy: content: | #!/bin/sh -e exec svlogd -tt {{ zeroclaw_runit_log_dest }} dest: "{{ zeroclaw_runit_log_script }}" mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | zeroclaw | runit | Script | Log Config ansible.builtin.copy: content: | s1000000 # rotate at 1 MB n5 # keep 5 old files dest: "{{ zeroclaw_runit_log_config }}" mode: "0755" when: ansible_service_mgr == "runit" - name: Workstation | Linux | Software | ZeroClaw | zeroclaw | Enable ansible.builtin.service: name: "{{ zeroclaw }}" state: started enabled: true - name: Workstation | Linux | Software | ZeroClaw | ollama | Wait ansible.builtin.uri: url: http://127.0.0.1:11434/ status_code: 200 timeout: 5 register: health until: health.status == 200 retries: 12 delay: 5 - name: Workstation | Linux | Software | ZeroClaw | ollama | Models | Install ansible.builtin.shell: | set -o pipefail item='{{ item }}' if ollama list | grep -q $item; then echo "OKAY" && return else ollama pull $item 1>/dev/null && echo "INSTALLED" && return fi echo "FAILED" loop: "{{ llm_installs }}" register: shell_check changed_when: "'INSTALLED' in shell_check.stdout" failed_when: "'FAILED' in shell_check.stdout" become: true become_user: "{{ user }}" - name: Workstation | Linux | Software | ZeroClaw | ollama | Models | Remove ansible.builtin.shell: | set -o pipefail item='{{ item }}' if ollama list | grep -q $item; then ollama rm $item && echo "INSTALLED" && return else echo "OKAY" && return fi echo "FAILED" loop: "{{ llm_removals }}" register: shell_check changed_when: "'INSTALLED' in shell_check.stdout" failed_when: "'FAILED' in shell_check.stdout" become: true become_user: "{{ user }}" - name: Workstation | Linux | Software | ZeroClaw | zeroclaw | Wait ansible.builtin.uri: url: http://127.0.0.1:42617/health status_code: 200 timeout: 5 register: health until: health.status == 200 retries: 12 delay: 5 when: ansible_pkg_mgr == "pacman"