# Deployment Modes — Welcome Screen + Wizard Fast-Path **Status:** Implemented and operational. Architectural reference. Welcome-screen mode selector and `min`-mode fast-path shipped in Phase 0. **Owner:** chrisfu **Audience:** Jr/mid engineer onboarding to knoe.dev. Familiarity with Tk/tkinter helps but is not required. --- ## 1. Context The knoe-db installer (`./install.sh` / `./knoe.sh install`, driven by the Tk UI in `knoe/ui/screens/`) supports four ways to deploy the platform. Different audiences, different hardware, but **the same architecture underneath**. Earlier installer revisions assumed the engineer already knew which mode they wanted, presented a welcome screen that was a wall of text, and shipped a sidebar tab strip (`k3d` / `k3s` / `k8s`) that didn't reliably refresh state across screens. Phase 0 replaced all of that with a first-screen mode selector that teaches the engineer what each mode *is* before asking them to choose, and added a `min`-mode fast-path that skips wizard screens irrelevant to a single-container deployment. ### The four modes | Mode | What it is | Who it's for | Required tools | | --- | --- | --- | --- | | **min** | A single `knoe-db` container under `containerd` — no Kubernetes, no Docker. The Spring Boot app runs locally on the host. | Engineers running a Spring app on a laptop and wanting a CNPG-compatible Postgres without a full cluster. | Homebrew, 1Password | | **k3d** | A Docker-based local k3s cluster. Full CNPG + optional Supabase / ArgoCD / Gitea / GitLab. | Local development with the full platform. | Docker, Homebrew, 1Password | | **k3s** | A multi-node k3s cluster on real hardware. Full Kerberos auth stack, Garage S3, monitoring. Mirrors the GKE shape. | Homelab contributors with their own hardware (e.g. a 3-node Pi cluster). | k3sup, Homebrew, 1Password | | **gke** | The production dual-cluster on Google Cloud (`knoe-dev-0` + `knoe-dev-cnpg-0` in `us-west3`). | Production. | gcloud, kubectl, 1Password | The architectural commitment matters: **all four modes are scaled-down mirrors of the GKE shape.** Not parallel implementations of the same idea, not divergent forks — the same components composed at different scales. CNPG runs in all four. The Spring Boot `authority` service runs in all four. `knoe.user` lives in the same schema in all four. The only thing that changes is what platform the components run on and which optional services are enabled. ### Mode → cluster_env mapping | `cluster_env` | `KNOE_MODE` | Target | | --- | --- | --- | | `dev` | `k3d` | Local K3d cluster | | `service` | `k3s` | On-prem K3s cluster | | `prod` | `k8s` (alias `gke`) | GKE (or other cloud) | | `min` | `min` | Local containerd (no Kubernetes) | The conversion lives in `knoe/core/env.py` (`_deployment_mode_from_env()`). ### Config file mapping `knoe/knoe_conf.py` maps environments to config files under `conf/`: | Mode | Config file | | --- | --- | | `min` | `conf/min.cfg` | | `k3d` (`dev`) | `conf/k3d.cfg` | | `k3s` (`service`) | `conf/k3s.cfg` | | `gke` (`prod`) | `conf/gke.cfg` | Config is layered: env-specific file overrides base. `KNOE_CONF` env var or `conf/service/` subdirs point to the active config. --- ## 2. How it's wired — file map | Component | Location | What's there | | --- | --- | --- | | Welcome screen with mode selector | `knoe/ui/screens/welcome.py` | `WelcomeScreenMixin._render_welcome_page()` renders the four mode cards. Click handler updates `deployment_mode` and `cluster_env`, redraws card borders, re-evaluates the Next gate. | | Sidebar nav | `knoe/ui/screens/navigation.py` | `_create_sidebar_nav()` no longer renders the old `k3d/k3s/k8s` tab strip — the welcome card selector replaces it. `_set_deployment_mode` is still called from the welcome handler. | | Mode/state initialization | `knoe/ui/screens/__init__.py` | `nav_items` list, `deployment_mode = tk.StringVar(...)`, `cluster_env = tk.StringVar(...)`. | | Wizard transitions | `knoe/ui/screens/navigation.py` `on_next` / `on_prev` | Min-mode fast-path skips screens that don't apply (network scan, cluster init, Kerberos, ArgoCD, Supabase, common services). | | Update-footer Next-button gate | `knoe/ui/screens/navigation.py` `update_footer` | Welcome screen disables Next until a mode is selected. | | Min-mode bootstrap | `etc/init_min.sh` | Idempotent: ensures Homebrew + containerd, pulls and runs the `knoe-db` container locally, runs schema bootstrap, prints connection info. Invoked from `init_scripts` step in min mode. | | Min-mode config | `conf/min.cfg` | Modeled on `conf/k3d.cfg`. Just what `init_min.sh` needs. | | Min-mode lifecycle | `knoe.sh` (`start` / `stop` / `restart` subcommands) | Manages the local containerd `knoe-db` instance for users who don't want to run the wizard every time. | --- ## 3. UI layout — welcome screen ``` ┌──────────────────────────────────────────────────────────────────┐ │ │ │ knoe.dev │ │ infrastructure.auto() │ │ │ │ Welcome │ │ ─────── │ │ Knoe.DB sets up a production-grade PostgreSQL cluster with │ │ Kerberos authentication. Pick the mode that matches your │ │ hardware — we'll walk you through every step. │ │ │ │ ┌────────────┬────────────┬────────────┬────────────┐ │ │ │ min │ k3d │ k3s │ gke │ │ │ │ Just a │ Local │ Homelab │ Production│ │ │ │ Database │ Cluster │ │ │ │ │ │ One knoe-db│ k3s-in- │ Multi-node │ Dual GKE │ │ │ │ container │ Docker │ k3s on real│ clusters on│ │ │ │ via │ cluster on │ hardware. │ Google │ │ │ │ containerd.│ your Mac. │ Full │ Cloud. │ │ │ │ No K8s. │ Full CNPG │ Kerberos │ CNPG + │ │ │ │ Perfect for│ database — │ auth stack,│ GCS backups│ │ │ │ a Spring │ add │ Garage S3, │ + Workload │ │ │ │ app on your│ Supabase, │ monitoring.│ Identity. │ │ │ │ laptop. │ ArgoCD, │ │ │ │ │ │ │ Gitea, or │ │ │ │ │ │ │ GitLab. │ │ │ │ │ │ Homebrew + │ Docker + │ k3sup + │ gcloud + │ │ │ │ 1Password │ Homebrew + │ Homebrew + │ 1Password │ │ │ │ │ 1Password │ 1Password │ │ │ │ └────────────┴────────────┴────────────┴────────────┘ │ │ │ │ You'll need: Docker · Homebrew · 1Password │ │ │ │ [ Next → ] │ └──────────────────────────────────────────────────────────────────┘ ``` Behavior: - The four cards are clickable. - The selected card gets a colored border in the mode's accent color (`_MODE_COLORS`: `min` purple, `k3d` blue, `k3s` green, `gke` orange). - The "You'll need:" line below the cards updates to reflect the selected mode's tools. - The Next button is **disabled** until a mode is selected. - Selecting a card also sets `cluster_env` via the mode-to-cluster_env map. - On Next, mode is persisted to `knoe_cfg_data["Global"]["DEPLOYMENT_MODE"]`. --- ## 4. Wizard transitions — `min`-mode fast-path ### Default flow (k3d / k3s / gke) ``` welcome → network_scan → env_setup → init_cluster → cluster_nodes → init_password → init_scripts → kerberos_config → knoe_users → argocd_config → gitops_config → supabase_config → common_services → … → security ``` ### Min-mode flow ``` welcome → dependencies → environment → init_password → init_scripts → security ``` Skipped in min: `network_scan`, `init_cluster`, `cluster_nodes`, `kerberos_config`, `knoe_users`, `argocd_config`, `gitops_config`, `supabase_config`, `common_services`. None of them apply when there's no Kubernetes cluster and no Kerberos KDC. `init_scripts` invokes `etc/init_min.sh` instead of the cluster-mode init scripts. The fast-path is implemented as a `_min_mode_next` dictionary in `knoe/ui/screens/navigation.py` consulted from `on_next` / `on_prev`. The override is only active when `_is_min_mode()` returns true. --- ## 5. Verification Run after any change touching the wizard or mode logic. 1. `./install.sh` opens. The welcome screen shows four mode cards. The sidebar has **no** k3d/k3s/k8s tab strip. 2. With no mode selected, the Next button is disabled. 3. Click the **min** card. Next becomes enabled. Click Next. - The wizard skips the network-scan screen. - It skips `init_cluster` and `cluster_nodes`. - It skips `kerberos_config`, `knoe_users`, `argocd_config`, `gitops_config`, `supabase_config`, `common_services`. - It runs `init_min.sh` at the `init_scripts` step. - It lands on the `security` screen. - Going back through `on_prev` walks the same trimmed sequence in reverse without hitting any skipped screens. 4. Click the **k3d** card on a fresh run. The wizard follows the existing k3d flow exactly as before. 5. `python3 -c "from knoe.ui.screens import KnoeInstaller"` — no import errors. 6. After completing min mode, `nerdctl ps` shows the `knoe-db` container running locally and `psql "${printed_conn_string}" -c '\dt knoe.*'` lists the `knoe.user` table. 7. `./knoe.sh stop` and `./knoe.sh start` cleanly stop/restart the local containerd instance. --- ## 6. Out of scope - A `min`-mode equivalent of the full Kerberos auth stack. Min is "just a database". Auth in min is a follow-up. - Migrating an existing `k3d` deployment to `min` (or any other mode-to-mode migration). Each mode is an independent target. - A unified package format that produces all four mode-specific installers from one `pyinstaller` build. The current per-mode build is fine. - Letting one wizard run install *multiple* modes (e.g. set up `k3d` and `gke` from the same session). One mode per run. --- ## 7. Glossary **k3s** — A lightweight Kubernetes distribution by Rancher Labs. Single binary, runs comfortably on a Raspberry Pi. The same project, two delivery shapes: `k3d` is k3s wrapped in Docker; bare k3s is k3s on actual hardware. **k3d** — A wrapper that runs k3s clusters inside Docker containers. Useful for local dev because it gives you a "real" Kubernetes cluster without having to provision VMs. **GKE (Google Kubernetes Engine)** — Google Cloud's managed Kubernetes. We use Standard for `knoe-dev-0` and `knoe-dev-cnpg-0`. See `CLAUDE.md` for cluster topology. **containerd** — A container runtime. Speaks the OCI image and runtime specs. Both Docker and Kubernetes use containerd under the hood. In `min` mode we talk to it directly via `nerdctl`, skipping Docker entirely. **nerdctl** — A Docker-CLI-compatible client for `containerd`. If you know `docker run`, you know `nerdctl run`. **CNPG (CloudNativePG)** — The Postgres operator we use for `knoe-db`. See `CLAUDE.md` for which cluster runs it in production. **`cluster_env`** — A label the installer carries internally that picks which `conf/*.cfg` file to read and which downstream config branches to take. Maps from `deployment_mode` per the table in §1. Don't reuse this name for new variables — it's already overloaded enough. **Tk / tkinter** — Python's standard GUI toolkit. The installer is built on it. Canvas-based rendering means we draw text and shapes directly rather than using Tk's widget hierarchy for the welcome screen. **Wizard / pid** — The installer is a multi-screen wizard. Each screen has a "page id" (`pid`) — `welcome`, `network_scan`, `init_cluster`, etc. `nav_items` is the ordered list; `on_next` / `on_prev` decide transitions based on the current `pid` and the user's state.