Skip to content

feat: one-command install wizard (curl | bash → ordo init)#123

Merged
AlienWalker1995 merged 3 commits into
mainfrom
feat/install-wizard
Jul 26, 2026
Merged

feat: one-command install wizard (curl | bash → ordo init)#123
AlienWalker1995 merged 3 commits into
mainfrom
feat/install-wizard

Conversation

@AlienWalker1995

Copy link
Copy Markdown
Owner

What

Adds the missing first-time-install experience: a single curl-able bootstrap that launches a comprehensive interactive wizard taking a fresh operator from nothing to a running stack.

curl -fsSL https://raw.githubusercontent.com/AlienWalker1995/Ordo-AI-Stack/main/install.sh | sh

Wizard decision flow

Step Auto-detected Prompted Generated
Hardware hardware.detect().summary() (accept or pin later)
Model catalog.best_fit(hw) recommendation override by tier / id / auto
Capabilities hardware-gated auto default which optional groups (image-video, rag, voice, automation, search, monitoring — chat always on) explicit plugins: list when customized
Access tailscale ip -4 (if present) CADDY_TAILNET_HOSTNAME, CADDY_BIND (tailnet-IP vs 0.0.0.0); offers tailscale cert CADDY_TAILNET_DOMAIN derived from host
Google SSO OAuth client id/secret + email allowlist → auth/oauth2-proxy/emails.txt
Secrets required KEY set derived from render() external: HF_TOKEN, TS_AUTHKEY, GITHUB_PERSONAL_ACCESS_TOKEN, OAUTH2_PROXY_CLIENT_ID/SECRET (skippable) internal: LITELLM_MASTER_KEY, OPS_CONTROLLER_TOKEN, MCP_GATEWAY_TOKEN, OAUTH2_PROXY_COOKIE_SECRET (valid 32-byte b64), SEARXNG_SECRET, N8N_API_KEY

Writes <out>/ordo.yaml (source) + <out>/secrets.env (chmod 600, gitignored, never committed).

ordo init post-wizard offers (interactive only, each y/N)

  1. ordo render --source <out>/ordo.yaml --out <out>
  2. ordo fetch
  3. bring-up: cd <out> && COMPOSE_PROFILES=<selected> docker compose -p ordo --env-file .env --env-file secrets.env up -d, then prints https://<host>:8444/.

Safety

  • --yes / non-interactive writes config only — never renders, never brings the stack up.
  • Live-tree overwrite guard: ordo init refuses to clobber an existing <out>/ordo.yaml or secrets.env without --force.
  • setup kept as an alias of init.

What's auto vs prompted vs generated

  • Auto: hardware, best-fit model, capability set (hardware-gated), required-secret key set (from render() — no hardcoded drift).
  • Prompted: model override, capability customization, tailnet host/bind, Google OAuth id/secret + allowlist, external tokens.
  • Generated: the six internal shared secrets.

Validation

  • ordo init --yes --out $TMP/wiz → valid ordo.yaml + secrets.env (11 keys, 6 generated non-empty, 5 external blank); ordo render from the temp source succeeds (ctx consistency OK).
  • sh -n install.sh clean.
  • ruff check . clean; pytest tests/ = 564 passed, 4 skipped.
  • Live out/ never written (mtimes pre-session); live source still renders to a temp dir.

Not fully automated (guided instead)

  • Google OAuth client creation — cannot be automated (requires a human in the Google Cloud console). The wizard prints the exact console URL + the callback URI (https://<host>/oauth2/callback) and collects the resulting id/secret.
  • tailscale cert — offered only when tailscale is on PATH; otherwise it prints the manual command.

🤖 Generated with Claude Code

Hermes Bot and others added 3 commits July 26, 2026 10:31
Add a real first-time-install path: a curl-able install.sh bootstrap that
checks prereqs, clones, installs the ordo CLI into a venv, and launches a
comprehensive interactive wizard that takes a fresh operator from nothing to a
running stack.

- ordo/wizard.py: rewritten. Detect hardware -> confirm best-fit model ->
  toggle capability groups (image-video/rag/voice/automation/search/monitoring,
  chat always on) -> tailnet hostname + Caddy bind -> Google SSO (client
  id/secret + email allowlist) -> secrets. Internal secrets auto-generated
  (LITELLM_MASTER_KEY/OPS_CONTROLLER_TOKEN/MCP_GATEWAY_TOKEN/cookie/SEARXNG/n8n);
  external ones (Google/HF/Tailscale/GitHub) prompted + skippable. Writes
  <out>/ordo.yaml + <out>/secrets.env (chmod 600) and the oauth2-proxy
  allowlist. Pure logic (build_source / plugins_from_capabilities /
  resolve_secrets) kept testable; secret KEY set is data-driven from render().
- ordo/cli.py: add `ordo init` (setup kept as alias). Live-tree overwrite guard;
  post-wizard render/fetch/up offers (each y/N); prints dashboard URL. Under
  --yes/non-interactive it only writes config, never brings up.
- install.sh: POSIX sh bootstrap with the curl one-liner, prereq checks
  (git/docker/compose/python3.11+, nvidia-smi warn), idempotent clone + venv.
- tests: new answers-schema + capability/secret-mapping coverage; headless
  write->render round-trip.
- README: leads with the curl one-liner + what the wizard asks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Read prompts from /dev/tty (both the install-dir ask() and the wizard's
own stdin) instead of the script's stdin. Under `curl … | sh` stdin is the
piped script, not a terminal, so the previous `[ -t 0 ]` check fell through
to non-interactive `ordo init --yes` (config-only) — the exact opposite of
the one-curl-drives-the-whole-wizard goal. /dev/tty still reaches the real
console, so a piped install is now fully interactive; genuinely headless
runs (no /dev/tty, e.g. CI) still degrade to --yes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both docs opened with config-as-render philosophy (and the operator guide
with a 30-item build log) before ever saying how to install. Restructure so
the one-curl install and the interactive `ordo init` wizard are the lead:
the wizard's six steps (hardware/model/capabilities/access/SSO/secrets) are
now the centerpiece, with the manual render path kept below as the alt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@AlienWalker1995
AlienWalker1995 merged commit 958e28e into main Jul 26, 2026
3 checks passed
@AlienWalker1995
AlienWalker1995 deleted the feat/install-wizard branch July 26, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant