271 lines
8.7 KiB
Markdown
271 lines
8.7 KiB
Markdown
---
|
|
title: Control Panel (CCP)
|
|
description: Multi-tenant management for provisioning and operating multiple Changemaker Lite instances.
|
|
icon: material/console
|
|
---
|
|
|
|
# Changemaker Control Panel (CCP)
|
|
|
|
The Changemaker Control Panel is a **multi-tenant management layer** for operators who run multiple Changemaker Lite instances from a single server. It provides a web UI to provision, monitor, and maintain a fleet of instances without manual configuration.
|
|
|
|
!!! info "Single instance?"
|
|
If you're running a single Changemaker Lite instance, you don't need CCP. Skip this page and continue with [First Steps](first-steps.md).
|
|
|
|
---
|
|
|
|
## When to Use CCP
|
|
|
|
CCP is designed for:
|
|
|
|
- **Campaign organizations** managing instances for multiple chapters or regions
|
|
- **Hosting providers** offering Changemaker Lite as a managed service
|
|
- **Development teams** spinning up isolated test instances
|
|
|
|
CCP handles the entire instance lifecycle: provisioning, configuration, health monitoring, backups, and upgrades — all from a single dashboard.
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
CCP runs as 4 Docker containers alongside (but independent from) your CML instances:
|
|
|
|
```
|
|
┌──────────────────────────┐
|
|
│ CCP Admin GUI (5100) │ React + Vite + Ant Design
|
|
│ Dark theme, SPA │ Zustand auth store
|
|
└────────────┬─────────────┘
|
|
│
|
|
┌────────────▼─────────────┐
|
|
│ CCP API (5000) │ Express + TypeScript
|
|
│ JWT auth, RBAC │ Prisma ORM → PostgreSQL
|
|
│ Docker socket access │ Winston logger
|
|
└────────────┬─────────────┘
|
|
│
|
|
┌────────┼────────┐
|
|
▼ ▼ ▼
|
|
ccp-postgres ccp-redis Docker Socket
|
|
(port 5480) (port 6399)
|
|
```
|
|
|
|
| Service | Container | Port | Description |
|
|
|---------|-----------|------|-------------|
|
|
| CCP API | `ccp-api` | 5000 | Express API with Docker CLI access |
|
|
| CCP Admin | `ccp-admin` | 5100 | React admin GUI |
|
|
| CCP PostgreSQL | `ccp-postgres` | 5480 | CCP metadata database |
|
|
| CCP Redis | `ccp-redis` | 6399 | Rate limiting, caching |
|
|
|
|
Each managed CML instance gets its own isolated set of containers and PostgreSQL database, with ports allocated from non-overlapping ranges.
|
|
|
|
---
|
|
|
|
## Setup
|
|
|
|
### 1. Run the Setup Script
|
|
|
|
```bash
|
|
cd changemaker-control-panel
|
|
chmod +x setup.sh
|
|
./setup.sh
|
|
```
|
|
|
|
The setup script:
|
|
|
|
- Detects the installation directory and resolves absolute paths
|
|
- Creates `instances/` and `backups/` directories
|
|
- Copies `.env.example` to `.env` if not present
|
|
- Sets `INSTANCES_BASE_PATH`, `BACKUP_STORAGE_PATH`, and `CML_SOURCE_PATH`
|
|
- Generates random secrets for any placeholder values
|
|
|
|
### 2. Review Environment
|
|
|
|
Edit `.env` and verify the key settings:
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `JWT_ACCESS_SECRET` | Auto-generated | JWT signing key |
|
|
| `JWT_REFRESH_SECRET` | Auto-generated | Refresh token signing key |
|
|
| `ENCRYPTION_KEY` | Auto-generated | AES-256 key for instance secrets at rest |
|
|
| `INITIAL_ADMIN_EMAIL` | `admin@example.com` | Bootstrap admin email |
|
|
| `INITIAL_ADMIN_PASSWORD` | `ChangeMe2025!!` | Bootstrap admin password |
|
|
| `INSTANCES_BASE_PATH` | `./instances` | Where instance directories are created |
|
|
| `CML_SOURCE_PATH` | Auto-detected | Path to CML source repo for provisioning |
|
|
| `BACKUP_STORAGE_PATH` | `./backups` | Backup archive storage |
|
|
| `PANGOLIN_API_URL` | — | Pangolin API for tunnel management |
|
|
| `PANGOLIN_API_KEY` | — | Pangolin authentication |
|
|
| `PANGOLIN_ORG_ID` | — | Pangolin organization |
|
|
|
|
### 3. Start CCP
|
|
|
|
```bash
|
|
docker compose up -d
|
|
|
|
# Run database migrations and seed the admin user
|
|
docker compose exec ccp-api npx prisma migrate deploy
|
|
docker compose exec ccp-api npx prisma db seed
|
|
```
|
|
|
|
### 4. Log In
|
|
|
|
Open **http://localhost:5100** and sign in with the admin credentials from `.env`.
|
|
|
|
---
|
|
|
|
## Creating an Instance
|
|
|
|
The Create Instance wizard walks through 5 steps:
|
|
|
|
### Step 1: Basic Information
|
|
|
|
- **Instance name** — human-readable label (e.g., "Edmonton Chapter")
|
|
- **Slug** — URL-safe identifier (e.g., `edmonton`), used for directory names and compose project
|
|
- **Domain** — the domain this instance will serve (e.g., `edmonton.example.org`)
|
|
|
|
### Step 2: Features
|
|
|
|
Toggle which platform features to enable for this instance:
|
|
|
|
- Media Manager
|
|
- Listmonk newsletter sync
|
|
- Payments
|
|
- Rocket.Chat
|
|
- Gancio events
|
|
- Jitsi Meet
|
|
- SMS Campaigns
|
|
|
|
### Step 3: Email
|
|
|
|
Configure SMTP for the instance, or use MailHog for testing.
|
|
|
|
### Step 4: Tunnel
|
|
|
|
Optionally configure Pangolin tunnel credentials for public access.
|
|
|
|
### Step 5: Review
|
|
|
|
Review all settings, then click **Create** to start provisioning.
|
|
|
|
---
|
|
|
|
## Provisioning Flow
|
|
|
|
When you create an instance, CCP runs a **13-step async provisioning process**:
|
|
|
|
| Step | What Happens |
|
|
|------|-------------|
|
|
| 1 | Validate uniqueness (slug + domain) |
|
|
| 2 | Allocate 4 ports from ranges |
|
|
| 3 | Generate 14 secrets (passwords, JWT keys, encryption keys) |
|
|
| 4 | Create Instance record (status: PROVISIONING) |
|
|
| 5 | Create instance directory |
|
|
| 6 | Copy CML source code (rsync, excluding node_modules/.git/.env) |
|
|
| 7 | Decrypt secrets and build template context |
|
|
| 8 | Render 7 config files from Handlebars templates (docker-compose.yml, .env, nginx configs, Pangolin, Prometheus) |
|
|
| 9 | Copy static files (nginx.conf) |
|
|
| 10 | `docker compose pull` (non-fatal if images are cached) |
|
|
| 11 | `docker compose build` |
|
|
| 12 | Start infrastructure (PostgreSQL + Redis), wait for healthy |
|
|
| 13 | Start API (runs migrations + seed), then start all remaining services |
|
|
|
|
The admin GUI polls every 3 seconds during provisioning to show progress. When complete, the instance status changes to **RUNNING**.
|
|
|
|
---
|
|
|
|
## Port Allocation
|
|
|
|
CCP allocates ports from 4 non-overlapping ranges to prevent conflicts between instances:
|
|
|
|
| Range | Start | End | Purpose |
|
|
|-------|-------|-----|---------|
|
|
| API | 14000 | 14999 | Express API server |
|
|
| Admin | 13000 | 13999 | React admin GUI |
|
|
| PostgreSQL | 15400 | 15499 | Database |
|
|
| Nginx | 10000 | 10999 | Reverse proxy |
|
|
|
|
Each new instance receives one port from each range. Ports are tracked in the database and released when instances are deleted.
|
|
|
|
---
|
|
|
|
## Pages Overview
|
|
|
|
### Dashboard
|
|
|
|
At-a-glance fleet status:
|
|
|
|
- Total instances, running, healthy, degraded, stopped, error counts
|
|
- Instance cards with status indicators and quick actions
|
|
|
|
### Instance List
|
|
|
|
Searchable, filterable table of all instances with status, domain, health, and creation date.
|
|
|
|
### Instance Detail
|
|
|
|
5-tab view for each instance:
|
|
|
|
| Tab | Content |
|
|
|-----|---------|
|
|
| **Overview** | Status, domain, ports, features, health summary |
|
|
| **Services** | Per-container status grid with restart and log-view actions |
|
|
| **Logs** | Real-time log viewer with service filter, tail count, and time range |
|
|
| **Backups** | Backup list with create, download, and delete actions |
|
|
| **Tunnel** | Pangolin tunnel status and configuration |
|
|
|
|
### Backups
|
|
|
|
Cross-instance backup management:
|
|
|
|
- All backups in one table with instance filter
|
|
- Stats: total count, total size, last backup time
|
|
- "Backup All Running" bulk action
|
|
- Download and delete individual archives
|
|
|
|
### Audit Log
|
|
|
|
Filterable activity trail with 18 action types:
|
|
|
|
- Instance lifecycle: CREATE, UPDATE, DELETE, START, STOP, RESTART, UPGRADE
|
|
- Backups: CREATE, DELETE
|
|
- Tunnel: PANGOLIN_SETUP, PANGOLIN_SYNC
|
|
- Users: LOGIN, CREATE, UPDATE, DELETE
|
|
- Settings: UPDATE
|
|
|
|
Each entry includes timestamp, user, action, instance, IP address, and details (expandable JSON).
|
|
|
|
### Settings
|
|
|
|
CCP-level configuration:
|
|
|
|
- Port ranges
|
|
- Pangolin credentials
|
|
- Default feature flags for new instances
|
|
- Health check interval
|
|
- Backup retention period
|
|
|
|
---
|
|
|
|
## Roles
|
|
|
|
| Role | Capabilities |
|
|
|------|-------------|
|
|
| **SUPER_ADMIN** | Full access: create/delete instances, manage users, view secrets, delete backups |
|
|
| **OPERATOR** | Manage instances: create, start/stop/restart, backups, health checks |
|
|
| **VIEWER** | Read-only: view instances, logs, health, backups, audit log |
|
|
|
|
---
|
|
|
|
## Security
|
|
|
|
- **JWT authentication** with 15-minute access tokens and 7-day refresh tokens (atomic rotation)
|
|
- **AES-256-GCM encryption** for instance secrets stored in the database
|
|
- **Audit logging** on all operations with IP address capture
|
|
- **Role-based access control** on all API endpoints
|
|
- **Docker socket access** restricted to the CCP API container only
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
- [Services Overview](services.md) — learn about the services CCP provisions for each instance
|
|
- [Updates & Upgrades](upgrades.md) — upgrading CML instances
|
|
- [Deployment](../deployment/index.md) — production setup with tunneling and SSL
|