3 Commits

Author SHA1 Message Date
c4ch3c4d3 a1c4892b37 Fix local installer compatibility on newer hosts
Made-with: Cursor
2026-04-26 16:31:51 -06:00
c4ch3c4d3 eb3f8b3f25 Update Lab 2 Ollama Gemma model
Made-with: Cursor
2026-04-25 15:35:39 -06:00
bzuccaro e78581c2c9 Remove Kiln from local courseware setup 2026-04-24 22:11:44 -06:00
13 changed files with 71 additions and 81 deletions
+3 -5
View File
@@ -4,7 +4,7 @@ This project builds a student-friendly local lab environment for the courseware
- `./deploy-courseware.sh` installs and configures the environment, then starts every managed service. - `./deploy-courseware.sh` installs and configures the environment, then starts every managed service.
- `./destroy-courseware.sh` stops the managed services, uninstalls courseware-managed Ollama, and removes the project-owned lab state. - `./destroy-courseware.sh` stops the managed services, uninstalls courseware-managed Ollama, and removes the project-owned lab state.
- `./labctl` provides day-two controls such as `assets lab2`, `ollama_models`, `update_wiki`, `start`, `stop`, `status`, `urls`, `logs`, and `open kiln`. - `./labctl` provides day-two controls such as `assets lab2`, `ollama_models`, `update_wiki`, `start`, `stop`, `status`, `urls`, and `logs`.
## What It Installs ## What It Installs
@@ -16,7 +16,6 @@ This project builds a student-friendly local lab environment for the courseware
- Embedding Atlas - Embedding Atlas
- Promptfoo - Promptfoo
- Unsloth Studio - Unsloth Studio
- Kiln Desktop
- Course-specific support assets for lab 1, lab 2, and lab 4 - Course-specific support assets for lab 1, lab 2, and lab 4
## Lab 1 Defaults ## Lab 1 Defaults
@@ -32,7 +31,7 @@ Lab 1 is now provisioned directly by the installer:
`./labctl up` now pre-pulls the Gemma 4 E2B Ollama variants used by the wiki widgets: `./labctl up` now pre-pulls the Gemma 4 E2B Ollama variants used by the wiki widgets:
- `cajina/gemma4_e2b-q2_k_xl:v01` - `gemma4:e2b-it-q8_0`
- `batiai/gemma4-e2b:q4` - `batiai/gemma4-e2b:q4`
- `batiai/gemma4-e2b:q6` - `batiai/gemma4-e2b:q6`
@@ -125,7 +124,7 @@ Default endpoints:
The deployment will: The deployment will:
- bind `sshd` to `127.0.0.1:22` only - leave the host's SSH listen addresses under local control while requiring `127.0.0.1:22` for WeTTY
- install WeTTY and expose it at `http://127.0.0.1:7681/wetty` - install WeTTY and expose it at `http://127.0.0.1:7681/wetty`
- leave login identity management to the host, so any existing local account with password-based SSH access can sign in through the browser terminal - leave login identity management to the host, so any existing local account with password-based SSH access can sign in through the browser terminal
@@ -138,7 +137,6 @@ The deployment will:
- `./labctl update_wiki` hard-resets the managed wiki checkout to the remote latest, rebuilds it, and restarts only the managed wiki service on port `80`. - `./labctl update_wiki` hard-resets the managed wiki checkout to the remote latest, rebuilds it, and restarts only the managed wiki service on port `80`.
- `./labctl start core` starts only `ollama` and `open-webui`. - `./labctl start core` starts only `ollama` and `open-webui`.
- `./labctl start all` starts every managed web service. - `./labctl start all` starts every managed web service.
- `./labctl open kiln` launches the Kiln desktop app installed into the project state.
- The scripted Promptfoo install drops a starter config at `state/lab6/promptfoo.yaml`. - The scripted Promptfoo install drops a starter config at `state/lab6/promptfoo.yaml`.
- `labctl start all` includes Promptfoo via `promptfoo view` and the cloned wiki app. - `labctl start all` includes Promptfoo via `promptfoo view` and the cloned wiki app.
- Lab 2 includes `state/lab2/download_whiterabbitneo-gguf.sh`, which uses `git` + `git lfs` to pull only the supported WhiteRabbitNeo quants. Add `--download-only` if you want the files without Ollama registration. - Lab 2 includes `state/lab2/download_whiterabbitneo-gguf.sh`, which uses `git` + `git lfs` to pull only the supported WhiteRabbitNeo quants. Add `--download-only` if you want the files without Ollama registration.
+5 -4
View File
@@ -7,7 +7,6 @@ courseware_venvs_dir: "{{ courseware_state_dir }}/venvs"
courseware_models_dir: "{{ courseware_state_dir }}/models" courseware_models_dir: "{{ courseware_state_dir }}/models"
courseware_datasets_dir: "{{ courseware_state_dir }}/datasets" courseware_datasets_dir: "{{ courseware_state_dir }}/datasets"
courseware_tools_dir: "{{ courseware_state_dir }}/tools" courseware_tools_dir: "{{ courseware_state_dir }}/tools"
courseware_apps_dir: "{{ courseware_state_dir }}/apps"
courseware_downloads_dir: "{{ courseware_state_dir }}/downloads" courseware_downloads_dir: "{{ courseware_state_dir }}/downloads"
courseware_lab1_dir: "{{ courseware_state_dir }}/lab1" courseware_lab1_dir: "{{ courseware_state_dir }}/lab1"
courseware_lab2_dir: "{{ courseware_state_dir }}/lab2" courseware_lab2_dir: "{{ courseware_state_dir }}/lab2"
@@ -17,6 +16,9 @@ courseware_lab1_models_dir: "{{ courseware_models_dir }}/lab1"
courseware_ollama_models_dir: "{{ courseware_models_dir }}/ollama" courseware_ollama_models_dir: "{{ courseware_models_dir }}/ollama"
courseware_node_runtime_dir: "{{ courseware_tools_dir }}/node-runtime" courseware_node_runtime_dir: "{{ courseware_tools_dir }}/node-runtime"
courseware_node_runtime_bin_dir: "{{ courseware_node_runtime_dir }}/node_modules/node/bin" courseware_node_runtime_bin_dir: "{{ courseware_node_runtime_dir }}/node_modules/node/bin"
courseware_uv_venv_dir: "{{ courseware_tools_dir }}/uv"
courseware_uv_python_install_dir: "{{ courseware_tools_dir }}/uv-python"
courseware_open_webui_python_version: "3.12"
courseware_netron_venv_dir: "{{ courseware_venvs_dir }}/netron" courseware_netron_venv_dir: "{{ courseware_venvs_dir }}/netron"
courseware_wetty_dir: "{{ courseware_tools_dir }}/wetty" courseware_wetty_dir: "{{ courseware_tools_dir }}/wetty"
courseware_promptfoo_dir: "{{ courseware_lab6_dir }}" courseware_promptfoo_dir: "{{ courseware_lab6_dir }}"
@@ -42,7 +44,6 @@ courseware_ollama_min_version: "0.12.11"
courseware_llama_cpp_commit: "51fa458a92d6a3f305f8fd76fc8f702e3e87ddb5" courseware_llama_cpp_commit: "51fa458a92d6a3f305f8fd76fc8f702e3e87ddb5"
courseware_chunkviz_commit: "a891eacafda1f28a12373ad3b00102e68f07c57f" courseware_chunkviz_commit: "a891eacafda1f28a12373ad3b00102e68f07c57f"
courseware_promptfoo_version: "0.119.0" courseware_promptfoo_version: "0.119.0"
courseware_kiln_release_tag: "v0.18.1"
courseware_node_runtime_version: "20.20.2" courseware_node_runtime_version: "20.20.2"
courseware_wetty_spec: "wetty@2.5.0" courseware_wetty_spec: "wetty@2.5.0"
courseware_wetty_base_path: "/wetty" courseware_wetty_base_path: "/wetty"
@@ -71,8 +72,8 @@ courseware_white_rabbit_variants:
quant: "IQ2_M" quant: "IQ2_M"
filename: "WhiteRabbitNeo_WhiteRabbitNeo-V3-7B-IQ2_M.gguf" filename: "WhiteRabbitNeo_WhiteRabbitNeo-V3-7B-IQ2_M.gguf"
courseware_lab2_ollama_models: courseware_lab2_ollama_models:
- label: "Gemma 4 E2B Q2 XL" - label: "Gemma 4 E2B IT Q8"
value: "cajina/gemma4_e2b-q2_k_xl:v01" value: "gemma4:e2b-it-q8_0"
- label: "Gemma 4 E2B Q4" - label: "Gemma 4 E2B Q4"
value: "batiai/gemma4-e2b:q4" value: "batiai/gemma4-e2b:q4"
- label: "Gemma 4 E2B Q6" - label: "Gemma 4 E2B Q6"
-1
View File
@@ -17,5 +17,4 @@
- promptfoo - promptfoo
- { role: ollama_models, tags: ["ollama_models"] } - { role: ollama_models, tags: ["ollama_models"] }
- { role: wiki, tags: ["wiki"] } - { role: wiki, tags: ["wiki"] }
- kiln
- unsloth - unsloth
-1
View File
@@ -13,7 +13,6 @@
- "{{ courseware_models_dir }}" - "{{ courseware_models_dir }}"
- "{{ courseware_datasets_dir }}" - "{{ courseware_datasets_dir }}"
- "{{ courseware_tools_dir }}" - "{{ courseware_tools_dir }}"
- "{{ courseware_apps_dir }}"
- "{{ courseware_downloads_dir }}" - "{{ courseware_downloads_dir }}"
- "{{ courseware_lab1_dir }}" - "{{ courseware_lab1_dir }}"
- "{{ courseware_lab2_dir }}" - "{{ courseware_lab2_dir }}"
-25
View File
@@ -1,25 +0,0 @@
- name: Download Kiln Linux archive
get_url:
url: "https://github.com/Kiln-AI/Kiln/releases/download/{{ courseware_kiln_release_tag }}/Kiln.Linux.x64.zip"
dest: "{{ courseware_downloads_dir }}/Kiln.Linux.x64.zip"
mode: "0644"
- name: Create Kiln Linux directory
file:
path: "{{ courseware_apps_dir }}/kiln"
state: directory
mode: "0755"
- name: Unpack Kiln Linux binary
unarchive:
src: "{{ courseware_downloads_dir }}/Kiln.Linux.x64.zip"
dest: "{{ courseware_apps_dir }}/kiln"
remote_src: true
creates: "{{ courseware_apps_dir }}/kiln/Kiln"
- name: Ensure Kiln Linux binary is executable
file:
path: "{{ courseware_apps_dir }}/kiln/Kiln"
mode: "0755"
state: file
-3
View File
@@ -1,3 +0,0 @@
- name: Install Kiln on Linux
include_tasks: linux.yml
when: ansible_system == "Linux"
+44 -1
View File
@@ -4,15 +4,58 @@
state: directory state: directory
mode: "0755" mode: "0755"
- name: Create Open WebUI virtual environment - name: Create uv helper virtual environment
command: command:
argv: argv:
- "{{ courseware_python_bin }}" - "{{ courseware_python_bin }}"
- -m - -m
- venv - venv
- "{{ courseware_uv_venv_dir }}"
args:
creates: "{{ courseware_uv_venv_dir }}/bin/python"
- name: Install uv helper
command:
argv:
- "{{ courseware_uv_venv_dir }}/bin/python"
- -m
- pip
- install
- --upgrade
- pip
- uv
args:
creates: "{{ courseware_uv_venv_dir }}/bin/uv"
- name: Check Open WebUI virtual environment Python version
command:
argv:
- "{{ courseware_venvs_dir }}/open-webui/bin/python"
- -c
- "import importlib.util, sys; expected = tuple(map(int, '{{ courseware_open_webui_python_version }}'.split('.')[:2])); ok = sys.version_info[:len(expected)] == expected and importlib.util.find_spec('pip') is not None; raise SystemExit(0 if ok else 1)"
register: courseware_open_webui_python_check
changed_when: false
failed_when: false
- name: Remove incompatible Open WebUI virtual environment
file:
path: "{{ courseware_venvs_dir }}/open-webui"
state: absent
when: courseware_open_webui_python_check.rc != 0
- name: Create Open WebUI virtual environment
command:
argv:
- "{{ courseware_uv_venv_dir }}/bin/uv"
- venv
- --seed
- --python
- "{{ courseware_open_webui_python_version }}"
- "{{ courseware_venvs_dir }}/open-webui" - "{{ courseware_venvs_dir }}/open-webui"
args: args:
creates: "{{ courseware_venvs_dir }}/open-webui/bin/python" creates: "{{ courseware_venvs_dir }}/open-webui/bin/python"
environment:
UV_PYTHON_INSTALL_DIR: "{{ courseware_uv_python_install_dir }}"
- name: Upgrade Open WebUI venv tooling - name: Upgrade Open WebUI venv tooling
command: command:
+1
View File
@@ -14,6 +14,7 @@
- pkg-config - pkg-config
- python3 - python3
- python3-pip - python3-pip
- python3-setuptools
- python3-venv - python3-venv
- unzip - unzip
- zstd - zstd
+17 -14
View File
@@ -13,7 +13,7 @@
state: directory state: directory
mode: "0755" mode: "0755"
- name: Configure courseware loopback-only sshd policy - name: Configure courseware sshd policy
become: true become: true
template: template:
src: sshd-courseware-terminal.conf.j2 src: sshd-courseware-terminal.conf.j2
@@ -46,6 +46,15 @@
enabled: true enabled: true
when: ansible_service_mgr == "systemd" when: ansible_service_mgr == "systemd"
- name: Reload sshd when config changed with systemd
become: true
systemd:
name: ssh
state: reloaded
when:
- ansible_service_mgr == "systemd"
- courseware_terminal_sshd_config.changed
- name: Check for running sshd when systemd is unavailable - name: Check for running sshd when systemd is unavailable
become: true become: true
command: pgrep -x sshd command: pgrep -x sshd
@@ -89,19 +98,13 @@
environment: environment:
PATH: "{{ courseware_node_runtime_bin_dir }}:{{ ansible_env.PATH }}" PATH: "{{ courseware_node_runtime_bin_dir }}:{{ ansible_env.PATH }}"
- name: Check loopback sshd listener - name: Wait for sshd to accept local WeTTY connections
become: true wait_for:
command: ss -ltn host: 127.0.0.1
register: courseware_terminal_ss_listeners port: 22
changed_when: false state: started
timeout: 10
- name: Assert sshd is loopback-only msg: "sshd must accept connections on 127.0.0.1:22 for the browser terminal deployment."
assert:
that:
- "'127.0.0.1:22' in courseware_terminal_ss_listeners.stdout"
- "'0.0.0.0:22' not in courseware_terminal_ss_listeners.stdout"
- "'[::]:22' not in courseware_terminal_ss_listeners.stdout"
fail_msg: "sshd must listen only on 127.0.0.1:22 for the browser terminal deployment."
- name: Assert WeTTY binary exists - name: Assert WeTTY binary exists
stat: stat:
@@ -1,6 +1,4 @@
# Managed by Local Courseware Deployment. # Managed by Local Courseware Deployment.
ListenAddress 127.0.0.1
AddressFamily inet
PermitRootLogin no PermitRootLogin no
PasswordAuthentication yes PasswordAuthentication yes
KbdInteractiveAuthentication no KbdInteractiveAuthentication no
-2
View File
@@ -34,5 +34,3 @@ PROMPTFOO_BIN="{{ courseware_tools_dir }}/promptfoo/node_modules/.bin/promptfoo"
WIKI_DIR="{{ courseware_wiki_repo_dir }}" WIKI_DIR="{{ courseware_wiki_repo_dir }}"
WIKI_RUNTIME_CONFIG_PATH="{{ courseware_wiki_runtime_config_path }}" WIKI_RUNTIME_CONFIG_PATH="{{ courseware_wiki_runtime_config_path }}"
LLAMA_CPP_BIN_DIR="{{ courseware_llama_cpp_bin_dir }}" LLAMA_CPP_BIN_DIR="{{ courseware_llama_cpp_bin_dir }}"
KILN_LINUX_BIN="{{ courseware_apps_dir }}/kiln/Kiln"
KILN_LAUNCH_PATH="{{ courseware_apps_dir }}/kiln/Kiln"
+1 -4
View File
@@ -27,7 +27,6 @@ Usage:
./labctl stop [all|service...] ./labctl stop [all|service...]
./labctl status [all|service...] ./labctl status [all|service...]
./labctl urls ./labctl urls
./labctl open kiln
./labctl logs <service> ./labctl logs <service>
EOF EOF
} }
@@ -82,7 +81,6 @@ WARNING: THIS SCRIPT WILL CONFIGURE YOUR ENVIRONMENT WILL THE FOLLOWING SOFTWARE
- Embedding Atlas - Embedding Atlas
- Promptfoo - Promptfoo
- Unsloth Studio - Unsloth Studio
- Kiln Desktop
- Course-specific support assets for lab 1, lab 2, and lab 4 - Course-specific support assets for lab 1, lab 2, and lab 4
- Pre-pulled Gemma 4 E2B Ollama models for Lab 1 and Lab 2 - Pre-pulled Gemma 4 E2B Ollama models for Lab 1 and Lab 2
- Lab 1 confidence support through Gemma 4 E2B Q4 (requires Ollama ${min_ollama}+) - Lab 1 confidence support through Gemma 4 E2B Q4 (requires Ollama ${min_ollama}+)
@@ -107,7 +105,6 @@ WARNING: THIS SCRIPT WILL CONFIGURE YOUR ENVIRONMENT WILL THE FOLLOWING SOFTWARE
- Embedding Atlas - Embedding Atlas
- Promptfoo - Promptfoo
- Unsloth Studio - Unsloth Studio
- Kiln Desktop
- Course-specific support assets for lab 1, lab 2, and lab 4 - Course-specific support assets for lab 1, lab 2, and lab 4
- Pre-pulled Gemma 4 E2B Ollama models for Lab 1 and Lab 2 - Pre-pulled Gemma 4 E2B Ollama models for Lab 1 and Lab 2
- Lab 1 confidence support through Gemma 4 E2B Q4 (requires Ollama ${min_ollama}+) - Lab 1 confidence support through Gemma 4 E2B Q4 (requires Ollama ${min_ollama}+)
@@ -576,7 +573,7 @@ main() {
require_arg "$@" require_arg "$@"
handle_assets_command "$@" handle_assets_command "$@"
;; ;;
start|stop|status|urls|open|logs) start|stop|status|urls|logs)
exec bash "$ROOT_DIR/scripts/service_manager.sh" "$cmd" "$@" exec bash "$ROOT_DIR/scripts/service_manager.sh" "$cmd" "$@"
;; ;;
""|-h|--help|help) ""|-h|--help|help)
-19
View File
@@ -362,21 +362,9 @@ Promptfoo CLI: $PROMPTFOO_BIN
Promptfoo UI: $(service_url promptfoo) Promptfoo UI: $(service_url promptfoo)
Wiki: $(service_url wiki) Wiki: $(service_url wiki)
Lab 3 Terminal: $(service_url wetty) Lab 3 Terminal: $(service_url wetty)
Kiln app: ${KILN_LAUNCH_PATH:-not installed}
EOF EOF
} }
open_kiln() {
if [ -x "$KILN_LINUX_BIN" ]; then
nohup "$KILN_LINUX_BIN" >/dev/null 2>&1 &
echo "started Kiln from $KILN_LINUX_BIN"
return 0
fi
echo "Kiln is not installed." >&2
exit 1
}
show_logs() { show_logs() {
local service=$1 local service=$1
local log_file local log_file
@@ -418,13 +406,6 @@ main() {
urls) urls)
urls urls
;; ;;
open)
if [ "${1:-}" != "kiln" ]; then
echo "Only 'open kiln' is supported." >&2
exit 1
fi
open_kiln
;;
logs) logs)
if [ $# -ne 1 ]; then if [ $# -ne 1 ]; then
echo "Usage: ./labctl logs <service>" >&2 echo "Usage: ./labctl logs <service>" >&2