From aa1fde69f427a1ed00c311cd298cef8a2247e2d3 Mon Sep 17 00:00:00 2001 From: convee Date: Sat, 5 Sep 2026 09:05:06 +0800 Subject: [PATCH 1/2] docs: make quickstart handoffs explicit --- Makefile | 5 ++- README.md | 46 ++++++++++++++++---- docs/DEPLOYMENT.md | 14 ++++-- docs/STANDALONE.md | 15 ++++++- scripts/quickstart-kubeadm.sh | 81 ++++++++++++++++++++++++++++++----- tests/test_helm_package.py | 20 ++++++++- website/index.html | 7 ++- 7 files changed, 160 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 7187e37..1d31c00 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ SHELL := /usr/bin/env bash CONTROL_IMAGE ?= site-control:local -.PHONY: help install test test-db test-db-down test-supabase test-oss console homepage-check image chart-lint chart-render benchmark quickstart quickstart-status quickstart-access quickstart-token quickstart-clean standalone-install standalone-smoke standalone-uninstall +.PHONY: help install test test-db test-db-down test-supabase test-oss console homepage-check image chart-lint chart-render benchmark quickstart-doctor quickstart quickstart-status quickstart-access quickstart-token quickstart-clean standalone-install standalone-smoke standalone-uninstall # Generated from the targets themselves rather than kept as a second list. The # hand-written listing this replaces had already lost `help`, and nothing could @@ -79,6 +79,9 @@ chart-render: ## — render the self-contained Helm package benchmark: ## — run the fail-closed deterministic benchmark profile uv run --locked --extra dev python scripts/run-benchmark.py --profile contract +quickstart-doctor: ## — check every host prerequisite and local port before the trial + scripts/quickstart-kubeadm.sh doctor + quickstart: ## — build and prove Site on a disposable kubeadm VM scripts/quickstart-kubeadm.sh up diff --git a/README.md b/README.md index 6d1f48b..0dc419e 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,31 @@ environments, not a public hosting platform — [Known limitations](#known-limit ## See the proof locally -The fastest path is deliberately end to end. With Lima, Docker, `kubectl`, Helm, `uv`, -and Python 3.12+ installed, one command creates a disposable single-node Kubernetes +### Host prerequisites + +The supported source-checkout trial runs on macOS or Linux with hardware virtualization, +outbound HTTPS, and enough capacity for a Lima VM configured with **6 CPUs, 8 GiB RAM, +and a 40 GiB sparse disk**. Install Git, Lima, Docker, `kubectl`, Helm, `curl`, `uv`, +`lsof`, and Python 3.12+. Docker must be running, not merely installed. + +On macOS with Homebrew, the command-line dependencies are: + +```bash +brew install git lima kubectl helm uv python lsof +brew install --cask docker +open -a Docker # wait until Docker reports that it is running +``` + +Linux users should install [Docker Engine](https://docs.docker.com/engine/install/), +[Lima](https://lima-vm.io/docs/installation/), +[`kubectl`](https://kubernetes.io/docs/tasks/tools/), and +[Helm](https://helm.sh/docs/intro/install/) using their distribution's supported path. +Run `make quickstart-doctor` at any time for an explicit dependency, Docker-daemon, Python, +and local-port check. The first uncached run downloads a VM and several container images; +depending on the network it can take 5–25 minutes and needs ports 18090–18098 and 18447. + +The fastest path is deliberately end to end. With the prerequisites above, one command +creates a disposable single-node Kubernetes cluster with `kubeadm`, builds the image from this checkout, installs Site and Prometheus, deploys the included HTML example, and refuses to pass until both server-side HTTP verification and the administrative observability APIs return real evidence: @@ -46,9 +69,10 @@ Site kubeadm quickstart passed observability: available ``` -See the same application, dependency health, verification result, and metrics in the -management console. Keep the first command running; it opens the browser automatically -when possible: +`make quickstart` finishes after it has printed the verified public URL; it does not need +to stay open. To see the same application, dependency health, verification result, and +metrics in the management console, use two terminals. Keep terminal 1 running because it +owns the local console tunnel and opens the browser automatically when possible: ```bash # terminal 1 @@ -58,16 +82,20 @@ make quickstart-access make quickstart-token ``` -Paste the second command's value into **Admin token** and choose **Enter the console**. -The included application is visible immediately under **Applications** as +Paste the second command's value into **管理员 token / Admin token** and choose +**进入控制台 / Enter the console**. Only paste this secret into the local console URL +printed by terminal 1; do not commit or share it. The included application is visible +immediately under **应用 / Applications** as `local/local/hello-site`; its HTTP verification and digests are in **Run details**, and its **Open** action reaches the browser-visible address. CPU/memory samples are under **Monitor → Single application**. Use **Deploy application** to create or update an application from an existing container image; choose **Public** to receive a browser URL, or **Internal** when no public URL should exist. The token remains in a Kubernetes Secret and is never written into this checkout or browser storage. Inspect -the running objects with `make quickstart-status`; remove only the `site-quickstart` Lima -VM and repository-local kubeconfig with `make quickstart-clean`. +the running objects with `make quickstart-status`. Pressing Ctrl-C in terminal 1 only +closes console access; the application and cluster keep running. `make quickstart-clean` +permanently deletes the disposable `site-quickstart` VM, all applications inside it, and +the repository-local kubeconfig; it does not touch another cluster or repository. This trial harness is entirely owned by this repository: it uses Lima's default network, bootstraps Kubernetes directly with kubeadm, and builds the control image locally. No diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 05dde14..c6e10bb 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -64,17 +64,25 @@ workflow, plus a separate `site-values-VERSION.yaml` digest-pinned override and ## Local kubeadm environment -Prerequisites for the complete local trial: Lima, Docker, kubectl, Helm, uv, and -Python 3.12+. The repository creates one disposable VM and bootstraps Kubernetes -with kubeadm; it does not use a shared cluster or another checkout. +Prerequisites for the complete local trial: Lima, a running Docker daemon, kubectl, Helm, +curl, uv, lsof, and Python 3.12+. Run `make quickstart-doctor` for the executable preflight. +The VM allocates 6 CPUs, 8 GiB RAM, and a 40 GiB sparse disk; outbound HTTPS and host +ports 18090–18098 plus 18447 are required. The repository creates one disposable VM and +bootstraps Kubernetes with kubeadm; it does not use a shared cluster or another checkout. ```bash +make quickstart-doctor make quickstart make quickstart-status make quickstart-access +make quickstart-token # run in a second terminal, then log in make quickstart-clean ``` +`make quickstart` exits after verification. `make quickstart-access` must remain running +while the console is in use; Ctrl-C stops only that tunnel. `make quickstart-clean` +permanently removes the disposable VM and all applications stored inside it. + The quickstart uses a single node to minimize first-run time. Production cluster provisioning, upgrades, backup, and disaster recovery are deliberately not implemented in this repository. diff --git a/docs/STANDALONE.md b/docs/STANDALONE.md index f5240ef..6d5f530 100644 --- a/docs/STANDALONE.md +++ b/docs/STANDALONE.md @@ -4,24 +4,35 @@ For a first source-checkout trial, use the disposable kubeadm workflow from the root: ```bash +make quickstart-doctor # checks commands, Docker, Python, and fixed host ports make quickstart make quickstart-access # terminal 1: opens and serves the console -make quickstart-token # terminal 2: paste into the Admin token field +make quickstart-token # terminal 2: paste into 管理员 token / Admin token make quickstart-clean # deletes only the site-quickstart Lima VM and local state ``` +The trial VM is configured for 6 CPUs, 8 GiB RAM, and a 40 GiB sparse disk. It needs +outbound HTTPS while the Ubuntu, Kubernetes, Cilium, and workload images download, plus +host ports 18090–18098 and 18447. A first uncached install may take 5–25 minutes. +`make quickstart` exits after printing the proof. Keep `make quickstart-access` running; +pressing Ctrl-C there closes only the console tunnel, not the cluster. In the default +Chinese UI choose **进入控制台**; in English choose **Enter the console**. + That path creates a single-node Lima VM, installs Kubernetes 1.36 with kubeadm, installs a pinned Cilium release, and builds the control image locally. The Helm release supplies its own local storage provisioner, enables Prometheus, deploys `examples/hello-site`, and gates success on the deployment's HTTP status/body digest, a host-openable public URL with the same body digest, plus the admin metrics and deployment-snapshot APIs. It needs no pre-created Lima network, external image, or other repository. After login, the included -application appears under **Applications** as +application appears under **应用 / Applications** as `local/local/hello-site`, including an **Open** action; use **Monitor → Single application** for its resource samples. **Deploy application** creates or updates from an existing container image: public applications receive a browser URL, while internal applications are explicitly labeled as having no public URL. +`make quickstart-clean` is intentionally destructive only to the disposable trial: it +deletes that VM, every application inside it, and this checkout's local kubeconfig. + The lower-level path installs Site into the Kubernetes context selected by `kubectl`. Review the current context before continuing: diff --git a/scripts/quickstart-kubeadm.sh b/scripts/quickstart-kubeadm.sh index a5bcce0..406b270 100755 --- a/scripts/quickstart-kubeadm.sh +++ b/scripts/quickstart-kubeadm.sh @@ -23,8 +23,9 @@ started_at=$SECONDS usage() { cat <<'EOF' -Usage: scripts/quickstart-kubeadm.sh +Usage: scripts/quickstart-kubeadm.sh +doctor Check every host dependency and fixed local port before installation. up Create one disposable Lima VM, bootstrap Kubernetes with kubeadm, build Site from this checkout, deploy the example, and prove it. status Show the node, Site workloads, example, verification, and monitoring. @@ -32,7 +33,8 @@ access Forward and open the console at http://127.0.0.1:18091/console/. token Print the disposable trial's local admin token for console login. clean Delete only the site-quickstart VM and this checkout's .site-kubeadm state. -Prerequisites: Lima, Docker, kubectl, Helm, curl, uv, and Python 3.12+. +Prerequisites: Lima, a running Docker daemon, kubectl, Helm, curl, uv, lsof, +and Python 3.12+; the VM is configured for 6 CPUs, 8 GiB RAM, and a 40 GiB disk. No other repository, pre-created Lima network, or published Site image is used. EOF } @@ -44,10 +46,67 @@ require_command() { } } +check_prerequisites() { + local command_name missing=() + for command_name in limactl docker kubectl helm curl uv python3 lsof; do + command -v "$command_name" >/dev/null 2>&1 || missing+=("$command_name") + done + if ((${#missing[@]})); then + printf 'quickstart prerequisites are missing: %s\n' "${missing[*]}" >&2 + echo 'Install guide: https://github.com/hullwork/site#host-prerequisites' >&2 + exit 2 + fi + + python3 - <<'PY' || exit 2 +import sys +if sys.version_info < (3, 12): + raise SystemExit( + f"Python 3.12+ is required; found {sys.version.split()[0]}. " + "See https://www.python.org/downloads/" + ) +PY + + if ! docker info >/dev/null 2>&1; then + echo 'Docker is installed, but its daemon is not reachable.' >&2 + echo 'Start Docker Desktop (macOS) or the Docker service (Linux), then rerun make quickstart.' >&2 + exit 2 + fi + + # These are the complete fixed-port contract of the reference VM. Checking + # all of them now avoids a Lima forwarding failure several minutes later. + if ! vm_running; then + local port busy=() + for port in "$api_port" "$console_port" 18090 18092 18093 18094 18095 18096 18097 18098; do + if lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1; then + busy+=("$port") + fi + done + if ((${#busy[@]})); then + printf 'quickstart host ports are already in use: %s\n' "${busy[*]}" >&2 + echo 'Stop the process or older Site trial using those ports, then rerun make quickstart.' >&2 + exit 2 + fi + fi + + cat <<'EOF' +Quickstart doctor passed + commands: available + Python: 3.12 or newer + Docker daemon: reachable + local ports: available or owned by this trial + VM allocation: 6 CPUs, 8 GiB RAM, 40 GiB sparse disk + network: outbound HTTPS is required while Lima, Kubernetes, Cilium, and workload images download +EOF +} + vm_exists() { limactl list --quiet | grep -Fxq "$vm" } +vm_running() { + vm_exists && limactl list "$vm" --format '{{.Status}}' 2>/dev/null | grep -Fxq Running +} + kube() { kubectl --kubeconfig "$kubeconfig" --context "$context" "$@" } @@ -288,10 +347,11 @@ Site kubeadm quickstart passed observability: available Next: - make quickstart-access # http://127.0.0.1:$console_port/console/ - make quickstart-token # paste into the console login form + terminal 1: make quickstart-access # keep it running; opens http://127.0.0.1:$console_port/console/ + terminal 2: make quickstart-token # paste into "管理员 token / Admin token" + choose "进入控制台 / Enter the console" make quickstart-status - make quickstart-clean + make quickstart-clean # permanently deletes this disposable VM and its applications EOF } @@ -333,9 +393,11 @@ $opener First login: 1. In another terminal, run: make quickstart-token - 2. Paste that value into "Admin token", then choose "Enter the console". + 2. Paste that value into "管理员 token / Admin token". + 3. Choose "进入控制台 / Enter the console". -The example application is under "Applications" as local/local/hello-site. +The example application is under "应用 / Applications" as local/local/hello-site. +Its "打开 / Open" action reaches the public URL printed by make quickstart. Press Ctrl-C here to stop console access without stopping the cluster. EOF wait "$pid" || true @@ -360,10 +422,9 @@ clean() { } case "$action" in + doctor) check_prerequisites ;; up) - for command_name in limactl docker kubectl helm curl uv python3 lsof; do - require_command "$command_name" - done + check_prerequisites create_cluster prove_site ;; diff --git a/tests/test_helm_package.py b/tests/test_helm_package.py index 8daf42a..c255810 100644 --- a/tests/test_helm_package.py +++ b/tests/test_helm_package.py @@ -44,7 +44,7 @@ def test_quickstart_lima_template_needs_no_precreated_network(self) -> None: def test_makefile_exposes_the_complete_kubeadm_trial_lifecycle(self) -> None: makefile = (ROOT / "Makefile").read_text(encoding="utf-8") - for target in ("quickstart", "quickstart-status", "quickstart-access", "quickstart-token", "quickstart-clean"): + for target in ("quickstart-doctor", "quickstart", "quickstart-status", "quickstart-access", "quickstart-token", "quickstart-clean"): self.assertRegex(makefile, rf"(?m)^{target}:") script = (ROOT / "scripts" / "quickstart-kubeadm.sh").read_text(encoding="utf-8") self.assertIn('open "$url"', script) @@ -62,6 +62,24 @@ def test_makefile_exposes_the_complete_kubeadm_trial_lifecycle(self) -> None: self.assertIn('deployment/sites-prometheus', script[dependency_wait:restart]) self.assertIn('--timeout=15m', script[dependency_wait:restart]) + def test_quickstart_explains_every_newcomer_handoff(self) -> None: + script = (ROOT / "scripts" / "quickstart-kubeadm.sh").read_text(encoding="utf-8") + self.assertIn("Quickstart doctor passed", script) + self.assertIn("Docker is installed, but its daemon is not reachable", script) + self.assertIn("Python 3.12+ is required", script) + self.assertIn("管理员 token / Admin token", script) + self.assertIn("进入控制台 / Enter the console", script) + self.assertIn("without stopping the cluster", script) + + readme = (ROOT / "README.md").read_text(encoding="utf-8") + for fact in ( + "make quickstart-doctor", + "6 CPUs, 8 GiB RAM", + "5–25 minutes", + "permanently deletes", + ): + self.assertIn(fact, readme) + def test_newcomer_docs_name_kubeadm_and_not_the_kind_tool(self) -> None: docs = "\n".join( (ROOT / path).read_text(encoding="utf-8") diff --git a/website/index.html b/website/index.html index 60399a9..b4d536d 100644 --- a/website/index.html +++ b/website/index.html @@ -144,7 +144,7 @@

Small surface. Hard boundaries.
Ridiculous leverage
-
Kubeadm-first quickstart

One command.
A real cluster.
A live URL.

The repository-owned trial creates a disposable Lima VM, bootstraps Kubernetes with kubeadm, installs Cilium and Site, deploys the included app, and refuses to pass without measured HTTP proof.

Lima · Docker · kubectl · Helm · uv · Python 3.12+
+
Kubeadm-first quickstart

One command.
A real cluster.
A live URL.

The repository-owned trial creates a disposable Lima VM, bootstraps Kubernetes with kubeadm, installs Cilium and Site, deploys the included app, and refuses to pass without measured HTTP proof.

Git · Lima · running Docker · kubectl · Helm · uv · Python 3.12+
6 CPU · 8 GiB RAM · 40 GiB sparse disk · outbound HTTPS
site — zsh
$ git clone https://github.com/hullwork/site.git
@@ -155,7 +155,10 @@ 

Small surface. Hard boundaries.
Ridiculous leverage phase: Running HTTP verification: 200 public URL: http://127.0.0.1:18090 - public URL body: matches verification digest

+ public URL body: matches verification digest + +$ make quickstart-access # keep terminal 1 open +$ make quickstart-token # run in terminal 2
kubeadm cluster readyproof, not promises
From 808bc41f4182b6d35cae7a13589cdaaacd644b0c Mon Sep 17 00:00:00 2001 From: convee Date: Sat, 5 Sep 2026 09:08:40 +0800 Subject: [PATCH 2/2] docs: keep test count current --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0dc419e..e17db5e 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ git clone https://github.com/hullwork/site.git cd site uv sync --locked --extra dev make test-db # starts a throwaway PostgreSQL on 127.0.0.1:55439 -make test # 1030 tests +make test # 1031 tests make test-db-down ```