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
This commit is contained in:
bunker-admin 2026-04-16 13:21:44 -06:00
parent d2da13929a
commit 450b5ad4ba
5 changed files with 156 additions and 23 deletions

View File

@ -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 <repo-url> 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/).**

View File

@ -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

View File

@ -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**.
---

View File

@ -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.
---

View File

@ -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