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 ## Quick Start
### Production (pre-built images)
```bash ```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 curl -fsSL https://gitea.bnkops.com/admin/changemaker.lite/raw/branch/main/scripts/install.sh | bash
cd ~/changemaker.lite # 2. Start services (first pull ~3 min + ~90s stabilization)
docker compose up -d 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 ```bash
git clone <repo-url> changemaker.lite 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`. 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 ## Documentation
**Full documentation is available at [cmlite.org/docs/getting-started](https://cmlite.org/docs/getting-started/).** **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 ## Next Steps
- [Services Overview](services.md) — learn about the services CCP provisions for each instance - [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 } ![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" !!! 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: This script:
1. Checks prerequisites (Docker, Docker Compose, OpenSSL) 1. Checks prerequisites (Docker, Docker Compose, OpenSSL)
2. Downloads the latest release package from Gitea 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. Extracts to `~/changemaker.lite/` 3. Verifies at least 10 GB free disk
4. Launches the configuration wizard (`config.sh`) 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 ### Manual Download
@ -161,6 +163,9 @@ Prompts for the initial super-admin email and password. The password is validate
- At least one **digit** - At least one **digit**
- Requires password confirmation - 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 ### Step 5: Secret Generation
Auto-generates **21 unique secrets** — no placeholder passwords remain after this step: 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 ## 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 ```bash
# Check running containers bash scripts/test-deployment.sh --wait 60
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
``` ```
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. **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) ## 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 - [ ] **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 - [ ] **SMTP credentials** — host, port, username, password from your email provider
- [ ] **Linux server** with Docker 24+ and Docker Compose v2 installed - [ ] **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)* Stripe account for payments
- [ ] *(Optional)* Mapbox or Google Maps API key for geocoding - [ ] *(Optional)* Mapbox or Google Maps API key for geocoding
- [ ] *(Optional)* MaxMind account for geographic analytics - [ ] *(Optional)* MaxMind account for geographic analytics