From 450b5ad4ba27774c9289d0993ae7c478c3a32ce5 Mon Sep 17 00:00:00 2001 From: bunker-admin Date: Thu, 16 Apr 2026 13:21:44 -0600 Subject: [PATCH] docs: sync getting-started + README with install UX improvements Updates the user-facing docs to match the install flow after the friction fixes landed: README.md Quick Start block now reflects reality: install.sh host-port check, test-deployment.sh verify step, password file location, and the useful-tools block (validate-env, test-deployment, pangolin-teardown, ccp-deregister). mkdocs prerequisites.md New warning block under Linux Server covering the cockpit-on-9090 class of port collisions, pointing at the installer's ss-based preflight and validate-env.sh for manual checks. Checklist gains a host-port line. mkdocs installation.md "What install.sh does" now enumerates the new port check and disk check. Configuration Wizard Step 4 notes the data/admin-credentials.txt persistence for auto-generated passwords. "Verifying Installation" rewritten around test-deployment.sh. New "Clean reset before reinstall" block with the teardown sequence. mkdocs first-steps.md Log In step tells users where to find the generated password when they ran config.sh -y without --admin-password. mkdocs control-panel.md New "Registering an Existing Install (Phone-Home)" section covering invite code, --ccp-* flags, approval, rate-limit + backoff behaviour, and the ccp-deregister.sh teardown path with the slug-conflict rationale. Bunker Admin --- README.md | 24 +++++- .../docs/getting-started/control-panel.md | 77 +++++++++++++++++++ .../docs/docs/getting-started/first-steps.md | 11 ++- .../docs/docs/getting-started/installation.md | 57 ++++++++++---- .../docs/getting-started/prerequisites.md | 10 ++- 5 files changed, 156 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 9a9020ed..957e89ee 100644 --- a/README.md +++ b/README.md @@ -103,15 +103,22 @@ Send SMS campaigns via an Android bridge, sync subscribers to Listmonk for newsl ## Quick Start +### Production (pre-built images) + ```bash -# One-command install (downloads pre-built images, runs config wizard) +# 1. One-command install: checks host ports, downloads tarball, runs config wizard curl -fsSL https://gitea.bnkops.com/admin/changemaker.lite/raw/branch/main/scripts/install.sh | bash -cd ~/changemaker.lite -docker compose up -d +# 2. Start services (first pull ~3 min + ~90s stabilization) +cd ~/changemaker.lite && docker compose up -d + +# 3. Verify the install +bash scripts/test-deployment.sh --wait 60 ``` -Or clone and build from source: +The installer checks your host's port availability before extracting — no more half-started stacks from cockpit on `:9090` or other surprises. The generated admin password is printed to stdout **and** saved to `data/admin-credentials.txt` (mode 0600). See [Prerequisites](https://cmlite.org/docs/getting-started/prerequisites/) for what you need lined up first. + +### Development (source) ```bash git clone changemaker.lite @@ -127,6 +134,15 @@ docker compose exec api npx prisma db seed Then open **http://localhost:3000** and log in with the admin credentials from your `.env`. +### Useful tools + +```bash +bash scripts/validate-env.sh # re-check .env + host ports +bash scripts/test-deployment.sh # full deployment health sweep +bash scripts/pangolin-teardown.sh # wipe tunnel org before reinstall (dry-run by default) +bash scripts/ccp-deregister.sh # deregister from Changemaker Control Panel (dry-run by default) +``` + ## Documentation **Full documentation is available at [cmlite.org/docs/getting-started](https://cmlite.org/docs/getting-started/).** diff --git a/mkdocs/docs/docs/getting-started/control-panel.md b/mkdocs/docs/docs/getting-started/control-panel.md index ac8468cc..f9c445a3 100644 --- a/mkdocs/docs/docs/getting-started/control-panel.md +++ b/mkdocs/docs/docs/getting-started/control-panel.md @@ -271,6 +271,83 @@ CCP-level configuration: --- +## Registering an Existing Install (Phone-Home) + +Instead of provisioning from scratch, CCP can adopt a Changemaker Lite install that already runs elsewhere. The target host's `ccp-agent` container phones home with an invite code, you approve the registration in CCP, and CCP issues an mTLS cert bundle for ongoing management. + +### 1. Generate an invite code in CCP + +```bash +curl -s -X POST $CCP_URL/api/invite-codes \ + -H "Authorization: Bearer $ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"expiryHours":48}' +``` + +The response contains a `code` like `KNZH-B6WW`. Invite codes are single-use and expire. + +### 2. Install the target with `--ccp-*` flags + +On the host that will be registered: + +```bash +bash config.sh -y --enable-all \ + --domain yourdomain.org \ + --admin-password 'StrongPassword1' \ + --ccp-url https://ccp.example.com \ + --ccp-invite-code KNZH-B6WW \ + --ccp-agent-url https://100.90.78.47:7443 \ + # ... tunnel, SMTP, and other flags +``` + +All three CCP flags are required together. The wizard: + +- Sets `ENABLE_CCP_AGENT=true` in `.env` +- Appends `ccp-agent` to `COMPOSE_PROFILES` (without clobbering `monitoring`) +- On `docker compose up -d`, the `ccp-agent` container starts and phones home + +### 3. Approve in CCP + +```bash +# List pending registrations +curl -s $CCP_URL/api/agents/registrations -H "Authorization: Bearer $ADMIN_TOKEN" + +# Approve one +curl -s -X POST $CCP_URL/api/agents/registrations/$REG_ID/approve \ + -H "Authorization: Bearer $ADMIN_TOKEN" -d '{}' +``` + +On approval, CCP issues a mTLS cert bundle. The agent picks it up on its next poll, writes certs to disk, and restarts into mTLS mode. The instance then shows as `RUNNING` in CCP with live container status via `docker compose ps` proxied through the agent. + +!!! info "Approval SLA and rate limits" + The agent polls `/api/agents/poll` every 30s while waiting. The endpoint accepts up to 180 polls per 15 minutes (one every ~5s upper bound), so the agent comfortably handles human-paced approval times. If the agent does hit HTTP 429, it backs off exponentially (30s → 60s → 120s → 300s cap) and resets on the next successful poll — no manual restart required. + +### 4. Deregister on teardown + +When you wipe the target host (`docker compose down -v` + `sudo rm -rf`), also deregister the instance from CCP. Otherwise the stale Instance row blocks re-registration of the same slug, and CCP will return HTTP 409 `SLUG_CONFLICT` on the next approval. + +```bash +# From the target host (or anywhere with network access to CCP): +bash scripts/ccp-deregister.sh \ + --ccp-url https://ccp.example.com \ + --token $ADMIN_TOKEN \ + --yes +``` + +Defaults: matches by `CCP_AGENT_URL` from `.env`. Use `--slug` or `--instance-id` for explicit targeting. Dry-run by default. + +The teardown sequence for a registered instance is therefore: + +```bash +cd ~/changemaker.lite +bash scripts/ccp-deregister.sh --token $ADMIN_TOKEN --yes # CCP-side +bash scripts/pangolin-teardown.sh --yes # Pangolin-side +docker compose --profile monitoring down -v --remove-orphans # Docker +sudo rm -rf ~/changemaker.lite # Filesystem +``` + +--- + ## Next Steps - [Services Overview](services.md) — learn about the services CCP provisions for each instance diff --git a/mkdocs/docs/docs/getting-started/first-steps.md b/mkdocs/docs/docs/getting-started/first-steps.md index d02dfdf9..33b5788c 100644 --- a/mkdocs/docs/docs/getting-started/first-steps.md +++ b/mkdocs/docs/docs/getting-started/first-steps.md @@ -26,8 +26,17 @@ Open the admin panel at `http://localhost:3000` (or `app.DOMAIN` in production) ![Login Page](../../assets/images/screenshots/getting-started/login.png){ loading=lazy } +!!! info "Where's the password if I let the wizard generate one?" + If you ran `config.sh -y` without `--admin-password`, the generated password was printed once to stdout **and** saved to `data/admin-credentials.txt` (mode 0600). Retrieve it with: + + ```bash + cat ~/changemaker.lite/data/admin-credentials.txt + ``` + + Delete the file once you've saved the password elsewhere (e.g. in Vaultwarden). + !!! warning "Change your password" - If you used the wizard's generated password, change it immediately from **Settings > Organization**. + Whatever password you're logging in with first, change it immediately from **Settings > Organization**. --- diff --git a/mkdocs/docs/docs/getting-started/installation.md b/mkdocs/docs/docs/getting-started/installation.md index bcebdb30..b360d34e 100644 --- a/mkdocs/docs/docs/getting-started/installation.md +++ b/mkdocs/docs/docs/getting-started/installation.md @@ -80,11 +80,13 @@ curl -fsSL https://gitea.bnkops.com/admin/changemaker.lite/raw/branch/main/scrip This script: 1. Checks prerequisites (Docker, Docker Compose, OpenSSL) -2. Downloads the latest release package from Gitea -3. Extracts to `~/changemaker.lite/` -4. Launches the configuration wizard (`config.sh`) +2. **Checks host port availability** — aborts early if any of the ~14 required ports (3000, 4000, 9090, 3030, etc.) are already in use. Prints culprit-specific hints (e.g. cockpit.socket on :9090) +3. Verifies at least 10 GB free disk +4. Downloads the latest release package from Gitea +5. Extracts to `~/changemaker.lite/` +6. Launches the configuration wizard (`config.sh`) -After the wizard completes, start everything with `docker compose up -d`. +After the wizard completes, start everything with `docker compose up -d`, then verify with `bash scripts/test-deployment.sh --wait 60`. ### Manual Download @@ -161,6 +163,9 @@ Prompts for the initial super-admin email and password. The password is validate - At least one **digit** - Requires password confirmation +!!! info "Non-interactive password" + If you run with `-y` and omit `--admin-password`, the wizard generates a strong password and **also writes it to `data/admin-credentials.txt` with mode 0600**. Delete the file after saving the password elsewhere. Explicit `--admin-password` is never persisted to disk by `config.sh`. + ### Step 5: Secret Generation Auto-generates **21 unique secrets** — no placeholder passwords remain after this step: @@ -370,23 +375,41 @@ See [Services Overview](services.md) for the complete service catalog. ## Verifying Installation -After starting services, verify everything is healthy: +Changemaker Lite ships a one-shot deployment verifier. Run it after `docker compose up -d`: ```bash -# Check running containers -docker compose ps - -# API health check -curl -s http://localhost:4000/api/health | python3 -m json.tool - -# View API logs -docker compose logs api --tail 20 - -# Check for containers in restart loops -docker compose ps | grep -i restarting +bash scripts/test-deployment.sh --wait 60 ``` -You should see the API return `{"status":"ok"}` and all started containers in a "running" state. +`--wait 60` gives services time to pass their healthchecks on a cold start (first-run image pulls take ~3 min and health stabilization ~90s — brief unhealthy states during this window are expected). The script checks: + +- All containers running with healthy healthchecks +- API `/api/health` returns `"healthy"` with database + Redis OK +- Admin and media API endpoints respond +- (If `--domain yourdomain.org` passed) tunnel subdomains return 200/302/403 + +Any failure is printed with the failing component. If everything passes, your install is ready. + +### Manual checks + +```bash +docker compose ps # container status +curl -s http://localhost:4000/api/health | python3 -m json.tool # API health +docker compose logs api --tail 20 # API startup logs +bash scripts/validate-env.sh # re-check .env + host ports +``` + +### Clean reset before reinstall + +If you need to wipe and start over: + +```bash +docker compose --profile monitoring down -v --remove-orphans +bash scripts/pangolin-teardown.sh --yes # wipes the tunnel org (dry-run by default) +sudo rm -rf ~/changemaker.lite +``` + +For CCP-registered instances, also run `bash scripts/ccp-deregister.sh --yes` before removing the project directory — otherwise the CCP retains a stale Instance row that blocks re-registration of the same slug. --- diff --git a/mkdocs/docs/docs/getting-started/prerequisites.md b/mkdocs/docs/docs/getting-started/prerequisites.md index f81ea866..8ccbf333 100644 --- a/mkdocs/docs/docs/getting-started/prerequisites.md +++ b/mkdocs/docs/docs/getting-started/prerequisites.md @@ -101,6 +101,13 @@ Changemaker Lite runs on any Linux server with Docker. Minimum specs: **Options:** A VPS from DigitalOcean, Hetzner, Linode, or a spare machine on your network. If using a tunnel (Pangolin), the server doesn't need a public IP. +!!! warning "Watch out for host-level services on our ports" + Changemaker Lite binds ~14 host ports including `9090` (Prometheus), `3000` (admin), `4000` (API), `3030` (Gitea), and `8091` (NocoDB). If another service on your host already uses any of these, `docker compose up -d` will partially succeed and leave the stack in a broken state. + + **Common culprit:** `cockpit.socket` — Ubuntu Server's web admin UI — binds `:9090` by default. Disable it with `sudo systemctl disable --now cockpit.socket` before installing, or reconfigure cockpit to a different port. + + The installer runs `ss -Htln` against the required ports before downloading the tarball and aborts with specific remediation hints if any are bound. You can also run the check manually after install with `bash scripts/validate-env.sh`. + --- ## Optional (Enhance Your Deployment) @@ -144,7 +151,8 @@ Use this checklist to make sure you're ready: - [ ] **Tunnel or public IP** — Pangolin credentials (API key + Org ID), or server with public IP + SSL - [ ] **SMTP credentials** — host, port, username, password from your email provider - [ ] **Linux server** with Docker 24+ and Docker Compose v2 installed -- [ ] **OpenSSL** installed (for generating secrets during setup) +- [ ] **OpenSSL** + **ss** (from `iproute2`) installed (for secret generation + host port check) +- [ ] **Host ports free** — if cockpit is enabled, `sudo systemctl disable --now cockpit.socket` - [ ] *(Optional)* Stripe account for payments - [ ] *(Optional)* Mapbox or Google Maps API key for geocoding - [ ] *(Optional)* MaxMind account for geographic analytics