From 72dc508b1e341779b91f67826f170bd43e4d9ff8 Mon Sep 17 00:00:00 2001 From: Alastair Drong Date: Wed, 29 Jul 2026 10:24:34 -0700 Subject: [PATCH 1/3] docs: separate local-dev quickstart from cluster deployment; add auth demo video The Quick Start conflated two audiences: its prerequisites (Docker, k3d) were local-dev tooling, yet it led with a production 'helm install oci://...'. Split them: - 'Quick Start (local development)' is now explicitly the make-dev/k3d path for evaluating and developing SUS itself. - New 'Deploying to Kubernetes' section covers running SUS for real on an existing cluster: prerequisites, Helm install, ingress exposure, first-run setup, and optional Authelia auth (folded in from the old Configuration subsections, which were really deployment concerns). Also add the second promo video (Authelia auth demo) to the Demo section, and fix cross-links (Configuration now points at the deploy subsections). Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 203 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 116 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index 3d1fe33..34380b6 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,23 @@ No coding required. Describe your app in plain language, watch it appear in a li ## Demo -[![Watch the demo](https://img.youtube.com/vi/LAcHn5zU8Vk/maxresdefault.jpg)](https://youtu.be/LAcHn5zU8Vk) +**Build an app, end to end:** + +[![Watch the SUS demo](https://img.youtube.com/vi/LAcHn5zU8Vk/maxresdefault.jpg)](https://youtu.be/LAcHn5zU8Vk) [Watch on YouTube →](https://youtu.be/LAcHn5zU8Vk) +**Multi-user logins (Authelia auth):** + +[![Watch the SUS auth demo](https://img.youtube.com/vi/SNVmmdy6uvQ/maxresdefault.jpg)](https://youtu.be/SNVmmdy6uvQ) + +[Watch on YouTube →](https://youtu.be/SNVmmdy6uvQ) + --- -## Quick Start +## Quick Start (local development) + +This is the fastest way to see SUS running on your own machine and the setup used to **develop SUS itself** — it spins up a throwaway [k3d](https://k3d.io/) cluster, builds the images from source, and deploys the chart. To run SUS for real, see [Deploying to Kubernetes](#deploying-to-kubernetes). ### Prerequisites @@ -28,13 +38,39 @@ No coding required. Describe your app in plain language, watch it appear in a li - [k3d](https://k3d.io/) (`brew install k3d`) - [kubectl](https://kubernetes.io/docs/tasks/tools/) - [Helm](https://helm.sh/docs/intro/install/) + +### Run it locally + +```bash +git clone https://github.com/dev-dull/single-use-software.git +cd single-use-software +make dev # creates a k3d cluster, builds images from source, and deploys the chart +kubectl port-forward -n sus svc/sus-landing 9090:80 +``` + +Open [http://localhost:9090](http://localhost:9090). + +The catalog works out of the box against the public starter pack. To actually **build** an app in a session you'll need an [Anthropic API key](https://console.anthropic.com/settings/keys) (and, to save/publish, a git token) — add them on the `/setup` page. See [Makefile Targets](#makefile-targets) for the individual `build` / `push` / `upgrade` / `teardown` steps. + +--- + +## Deploying to Kubernetes + +Run SUS for real on an existing cluster — a homelab k3s box or a managed cluster (EKS/GKE/AKS). Pre-built images are pulled from GHCR, so you only need the chart. + +### Prerequisites + +- A running Kubernetes cluster and `kubectl` access to it +- [Helm](https://helm.sh/docs/intro/install/) 3+ +- An **ingress controller with WebSocket support** (nginx, Traefik, …) — the build terminal (ttyd) needs WebSocket upgrades +- A DNS name pointing at your ingress (recommended; **required** if you enable [authentication](#authentication-optional)) - An [Anthropic API key](https://console.anthropic.com/settings/keys) ### 1. Fork the starter pack Fork [**sus-starter-pack**](https://github.com/dev-dull/sus-starter-pack) — this is where your apps will be stored. -### 2. Deploy to your cluster +### 2. Install with Helm ```bash helm install sus oci://ghcr.io/dev-dull/charts/sus \ @@ -43,109 +79,37 @@ helm install sus oci://ghcr.io/dev-dull/charts/sus \ That's it — pre-built images are pulled automatically from GHCR. -Then expose SUS via ingress (see [Ingress](#ingress) below) or your preferred method. -
-Building from source +Building and pushing your own images + +To run images you've built yourself (e.g. from a fork), push them to a registry your cluster can pull from and point the chart at them: ```bash git clone https://github.com/dev-dull/single-use-software.git cd single-use-software -make build push +make build push # builds the landing + build-pod images helm install sus ./charts/sus \ --set landing.image.repository=your-registry/sus-landing \ --set landing.image.tag=dev \ + --set buildPod.image.repository=your-registry/sus-build \ + --set buildPod.image.tag=dev \ --set gitRepo.url=https://github.com/you/sus-starter-pack.git ```
-
-Local development with k3d - -For local testing without an existing cluster: - -```bash -make dev # Creates a k3d cluster, builds images, and deploys -kubectl port-forward -n sus svc/sus-landing 9090:80 -``` - -Open [http://localhost:9090](http://localhost:9090) -
- -### 3. Access SUS - -Open SUS through your ingress or load balancer URL. - -### 4. Complete setup - -Click the **Setup** link and configure: - -1. **App Repository** — your forked `sus-starter-pack` URL -2. **Anthropic API Key** — from [console.anthropic.com](https://console.anthropic.com/settings/keys) -3. **Git Access Token** — a [personal access token](https://github.com/settings/tokens/new) with `repo` permissions - -### 5. Build your first app - -Click **+ Create New App**, give it a name and description, and start chatting with Claude. Your app appears in the live preview as you build it. - ---- - -## How It Works - -``` -Browser - | - v -Landing Page Pod (FastAPI, Kubernetes) - |-- Catalog: reads apps from your git repo - |-- Build mode: spins up a build pod with Claude Code + ttyd - |-- Run mode: proxies to build pods or serves static apps from the repo - |-- Setup: API key, git token, repo URL stored as K8s secrets/configmaps - | - v -Build Pods (per-session, on demand) - |-- Claude Code CLI via ttyd (browser terminal) - |-- Auto-runner: detects app files, serves on port 3000 - |-- Git: commits to branch, pushes on save, merges to main on publish - | - v -App Repository (your fork of sus-starter-pack) - |-- {category}/{app-slug}/sus.json + app files - |-- Published apps are merged to main - |-- Saved work-in-progress lives on branches -``` - ---- - -## Configuration - -SUS can be configured two ways: - -| Setting | Setup Page | Helm Value | -|---------|-----------|------------| -| App repo URL | `/setup` | `--set gitRepo.url=...` | -| Anthropic API key | `/setup` | K8s secret `sus-anthropic-api-key` | -| Git access token | `/setup` | K8s secret `sus-git-token` | -| Claude model for build sessions | — | `--set buildPod.claudeModel=opus` (default; aliases like `opus`/`sonnet`/`haiku` track the latest model, a full ID pins one — see note below) | -| Build pod resources | — | `buildPod.resources` in `values.yaml` | -| Landing page resources | — | `landing.resources` in `values.yaml` | - -See [`charts/sus/values.yaml`](charts/sus/values.yaml) for all Helm values. - -**Build-session model:** the default is `opus` (Claude Opus 5) — Anthropic's recommended model for agentic coding, so the best build quality. It costs roughly **2.5× more per token** than `sonnet` and responds a bit slower. If you'd rather trade some build quality for lower cost and faster responses, set `--set buildPod.claudeModel=sonnet` (Claude Sonnet 5). Aliases track the latest model in each family; pass a full ID like `claude-opus-5` to pin a version. - -### Ingress +### 3. Expose it (Ingress) SUS includes an optional Ingress resource. Enable it in your Helm values: ```bash -helm install sus ./charts/sus \ +helm upgrade sus oci://ghcr.io/dev-dull/charts/sus \ + --set gitRepo.url=https://github.com/you/sus-starter-pack.git \ --set ingress.enabled=true \ --set ingress.host=sus.example.com \ --set ingress.className=nginx ``` -**WebSocket support is required.** The build terminal uses WebSockets (ttyd). Your ingress controller must allow WebSocket upgrades. For nginx-ingress, add these annotations: +**WebSocket support is required.** The build terminal uses WebSockets (ttyd), so your ingress controller must allow WebSocket upgrades. For nginx-ingress, add these annotations: ```yaml ingress: @@ -163,12 +127,27 @@ ingress: For Traefik (common in k3s/k3d), WebSocket support is enabled by default — no extra annotations needed. -### Authentication (Authelia) +If you don't run an ingress controller, you can reach SUS another way (e.g. a `LoadBalancer`/`NodePort` service or `kubectl port-forward`), but the build terminal still requires whatever fronts it to pass WebSocket upgrades through. + +### 4. Complete setup + +Open SUS through your ingress (or load balancer) URL, click the **Setup** link, and configure: + +1. **App Repository** — your forked `sus-starter-pack` URL +2. **Anthropic API Key** — from [console.anthropic.com](https://console.anthropic.com/settings/keys) +3. **Git Access Token** — a [personal access token](https://github.com/settings/tokens/new) with `repo` permissions + +### 5. Build your first app + +Click **+ Create New App**, give it a name and description, and start chatting with Claude. Your app appears in the live preview as you build it. + +### Authentication (optional) By default SUS runs single-user with no login. Enabling `auth.enabled` deploys a bundled **Authelia** and switches the landing pod to trusted-header identity so build sessions are attributed to the logged-in user: ```bash -helm upgrade sus ./charts/sus \ +helm upgrade sus oci://ghcr.io/dev-dull/charts/sus \ + --set gitRepo.url=https://github.com/you/sus-starter-pack.git \ --set ingress.enabled=true \ --set ingress.host=sus.example.com \ --set auth.enabled=true \ @@ -238,8 +217,58 @@ Prefer a different provider (tinyauth, oauth2-proxy, Authentik)? The landing app --- +## How It Works + +``` +Browser + | + v +Landing Page Pod (FastAPI, Kubernetes) + |-- Catalog: reads apps from your git repo + |-- Build mode: spins up a build pod with Claude Code + ttyd + |-- Run mode: proxies to build pods or serves static apps from the repo + |-- Setup: API key, git token, repo URL stored as K8s secrets/configmaps + | + v +Build Pods (per-session, on demand) + |-- Claude Code CLI via ttyd (browser terminal) + |-- Auto-runner: detects app files, serves on port 3000 + |-- Git: commits to branch, pushes on save, merges to main on publish + | + v +App Repository (your fork of sus-starter-pack) + |-- {category}/{app-slug}/sus.json + app files + |-- Published apps are merged to main + |-- Saved work-in-progress lives on branches +``` + +--- + +## Configuration + +SUS can be configured two ways: + +| Setting | Setup Page | Helm Value | +|---------|-----------|------------| +| App repo URL | `/setup` | `--set gitRepo.url=...` | +| Anthropic API key | `/setup` | K8s secret `sus-anthropic-api-key` | +| Git access token | `/setup` | K8s secret `sus-git-token` | +| Claude model for build sessions | — | `--set buildPod.claudeModel=opus` (default; aliases like `opus`/`sonnet`/`haiku` track the latest model, a full ID pins one — see note below) | +| Ingress | — | `ingress.*` — see [Expose it (Ingress)](#3-expose-it-ingress) | +| Authentication | — | `auth.*` — see [Authentication (optional)](#authentication-optional) | +| Build pod resources | — | `buildPod.resources` in `values.yaml` | +| Landing page resources | — | `landing.resources` in `values.yaml` | + +See [`charts/sus/values.yaml`](charts/sus/values.yaml) for all Helm values. + +**Build-session model:** the default is `opus` (Claude Opus 5) — Anthropic's recommended model for agentic coding, so the best build quality. It costs roughly **2.5× more per token** than `sonnet` and responds a bit slower. If you'd rather trade some build quality for lower cost and faster responses, set `--set buildPod.claudeModel=sonnet` (Claude Sonnet 5). Aliases track the latest model in each family; pass a full ID like `claude-opus-5` to pin a version. + +--- + ## Makefile Targets +These target the local [k3d](https://k3d.io/) development cluster (see [Quick Start](#quick-start-local-development)): + ``` make dev # Full setup: cluster + build + deploy make build # Build all container images From 2c3478370eae29624e01296edfba831742c063a2 Mon Sep 17 00:00:00 2001 From: Alastair Drong Date: Wed, 29 Jul 2026 10:43:28 -0700 Subject: [PATCH 2/3] =?UTF-8?q?docs:=20address=20review=20=E2=80=94=20fix?= =?UTF-8?q?=20build-your-own-images=20registry=20override,=20port,=20auth?= =?UTF-8?q?=20anchor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the auto-review findings on #97: 1. The 'build your own images' snippet ran 'make build push', but the Makefile hardcodes REGISTRY := localhost:5050 (immediate assignment), so it would build/push to the k3d-local registry while the helm install pointed at your-registry/... -> ImagePullBackOff. Pass the override as a make command-line assignment: 'make build push REGISTRY=your-registry TAG=dev' (verified it resolves your-registry/sus-{landing,build}:dev). 2. 'make dev' echoed a 'port-forward ... 8080:80' hint, but host 8080 is already taken by the k3d loadbalancer (k3d.yaml maps 8080:80), and the README uses 9090. Point the Makefile echo at 9090 so they agree and the hint actually works. 3. Renamed the README auth heading back to 'Authentication (Authelia)' (optional-ness is already clear in the prose) so the existing references in charts/sus/values.yaml and templates/NOTES.txt still resolve; updated the two internal links to match. Co-Authored-By: Claude Opus 4.8 (1M context) --- Makefile | 2 +- README.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 70ce635..128f742 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,7 @@ upgrade: ## Upgrade the Helm release with latest values dev: cluster-up build push deploy ## Full dev setup: cluster + build + deploy @echo "" @echo "SUS is running. Access the landing page:" - @echo " kubectl port-forward -n sus svc/sus-landing 8080:80" + @echo " kubectl port-forward -n sus svc/sus-landing 9090:80" @echo "" teardown: cluster-down ## Tear down everything diff --git a/README.md b/README.md index 34380b6..981cafa 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Run SUS for real on an existing cluster — a homelab k3s box or a managed clust - A running Kubernetes cluster and `kubectl` access to it - [Helm](https://helm.sh/docs/intro/install/) 3+ - An **ingress controller with WebSocket support** (nginx, Traefik, …) — the build terminal (ttyd) needs WebSocket upgrades -- A DNS name pointing at your ingress (recommended; **required** if you enable [authentication](#authentication-optional)) +- A DNS name pointing at your ingress (recommended; **required** if you enable [authentication](#authentication-authelia)) - An [Anthropic API key](https://console.anthropic.com/settings/keys) ### 1. Fork the starter pack @@ -87,7 +87,7 @@ To run images you've built yourself (e.g. from a fork), push them to a registry ```bash git clone https://github.com/dev-dull/single-use-software.git cd single-use-software -make build push # builds the landing + build-pod images +make build push REGISTRY=your-registry TAG=dev # builds + pushes the landing and build-pod images helm install sus ./charts/sus \ --set landing.image.repository=your-registry/sus-landing \ --set landing.image.tag=dev \ @@ -141,7 +141,7 @@ Open SUS through your ingress (or load balancer) URL, click the **Setup** link, Click **+ Create New App**, give it a name and description, and start chatting with Claude. Your app appears in the live preview as you build it. -### Authentication (optional) +### Authentication (Authelia) By default SUS runs single-user with no login. Enabling `auth.enabled` deploys a bundled **Authelia** and switches the landing pod to trusted-header identity so build sessions are attributed to the logged-in user: @@ -255,7 +255,7 @@ SUS can be configured two ways: | Git access token | `/setup` | K8s secret `sus-git-token` | | Claude model for build sessions | — | `--set buildPod.claudeModel=opus` (default; aliases like `opus`/`sonnet`/`haiku` track the latest model, a full ID pins one — see note below) | | Ingress | — | `ingress.*` — see [Expose it (Ingress)](#3-expose-it-ingress) | -| Authentication | — | `auth.*` — see [Authentication (optional)](#authentication-optional) | +| Authentication | — | `auth.*` — see [Authentication (Authelia)](#authentication-authelia) | | Build pod resources | — | `buildPod.resources` in `values.yaml` | | Landing page resources | — | `landing.resources` in `values.yaml` | From 1833aba84c48a462681d7540749b1c83148bec8c Mon Sep 17 00:00:00 2001 From: Alastair Drong Date: Wed, 29 Jul 2026 10:50:32 -0700 Subject: [PATCH 3/3] docs: warn to carry image overrides through later helm upgrades MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the #97 re-review's one non-blocking finding: a reader who builds their own images then follows the Ingress/Authentication 'helm upgrade oci://...' snippets would drop the --set image overrides and revert to the GHCR images — same class as the gitRepo.url footgun. Add a one-line note to the 'build your own images' block. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 981cafa..c15fa56 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,8 @@ helm install sus ./charts/sus \ --set buildPod.image.tag=dev \ --set gitRepo.url=https://github.com/you/sus-starter-pack.git ``` + +If you go this route, carry the `--set landing.image.*` / `--set buildPod.image.*` flags (and `./charts/sus` in place of the `oci://…` URL) through every later `helm upgrade` — including the [Ingress](#3-expose-it-ingress) and [Authentication](#authentication-authelia) examples below — otherwise the upgrade reverts you to the GHCR images. ### 3. Expose it (Ingress)