Skip to content

Installation

Changemaker Lite runs as a set of Docker containers orchestrated by Docker Compose. The config.sh wizard handles all configuration — or you can set things up manually.


Prerequisites

  • Docker 24+ and Docker Compose v2
  • OpenSSL (for secret generation)
  • A Linux server (Ubuntu 22.04+ recommended) or macOS for development
  • At least 2 GB RAM for core services, 4 GB for the full stack
  • A domain name (optional for development, recommended for production)

Quick Start

Clone the repository:

git clone https://gitea.bnkops.com/admin/changemaker.lite
cd changemaker.lite
git checkout v2

Run the configuration wizard:

bash config.sh

Start all services:

docker compose up -d

Open http://localhost:3000 and sign in with the admin credentials you configured. Database migrations and seeding run automatically on first startup.

Change your password

If you used the wizard's generated password, change it immediately from the admin dashboard.


Configuration Wizard (config.sh)

The wizard performs 14 steps to produce a fully configured .env file and prepare the system for startup. Each step is interactive with sensible defaults.

Step 1: Prerequisites Check

Verifies that Docker, Docker Compose v2, and OpenSSL are installed. Exits immediately if any are missing, with links to installation guides.

Step 2: Environment File Setup

  • If no .env exists, copies .env.example as the starting point
  • If .env already exists, offers to back it up (timestamped copy) and create a fresh one, or update values in place

Step 3: Domain Configuration

Prompts for your root domain (default: cmlite.org) and derives 14 environment variables from it:

Variable Example Value
DOMAIN example.org
BASE_DOMAIN https://example.org
GITEA_ROOT_URL https://git.example.org
GITEA_DOMAIN git.example.org
N8N_HOST n8n.example.org
SMTP_FROM noreply@example.org
INITIAL_ADMIN_EMAIL admin@example.org
NC_ADMIN_EMAIL admin@example.org
EXCALIDRAW_WS_URL wss://draw.example.org
LISTMONK_SMTP_FROM Changemaker Lite <noreply@example.org>
HOMEPAGE_VAR_BASE_URL https://example.org
VAULTWARDEN_DOMAIN https://vault.example.org
GANCIO_BASE_URL https://events.example.org
TEST_EMAIL_RECIPIENT admin@example.org

Also updates mkdocs/mkdocs.yml with the new site_url and repo_url, and asks whether this is a production deployment (sets NODE_ENV=production).

Step 4: Admin Credentials

Prompts for the initial super-admin email and password. The password is validated against the security policy:

  • Minimum 12 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one digit
  • Requires password confirmation

Step 5: Secret Generation

Auto-generates 21 unique secrets — no placeholder passwords remain after this step:

Category Count Secrets
JWT & Encryption 3 JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, ENCRYPTION_KEY (64-char hex)
Database 2 V2_POSTGRES_PASSWORD, REDIS_PASSWORD (24-char alphanumeric)
Listmonk 3 LISTMONK_DB_PASSWORD, LISTMONK_WEB_ADMIN_PASSWORD, LISTMONK_API_TOKEN
NocoDB 1 NC_ADMIN_PASSWORD
Gitea 2 GITEA_DB_PASSWD, GITEA_DB_ROOT_PASSWORD
n8n 2 N8N_ENCRYPTION_KEY, N8N_USER_PASSWORD
Monitoring 2 GRAFANA_ADMIN_PASSWORD, GOTIFY_ADMIN_PASSWORD
Vaultwarden 1 VAULTWARDEN_ADMIN_TOKEN (64-char hex)
Rocket.Chat 1 ROCKETCHAT_ADMIN_PASSWORD
Gancio 1 GANCIO_ADMIN_PASSWORD
Jitsi Meet 3 JITSI_APP_SECRET (64-char hex), JITSI_JICOFO_AUTH_PASSWORD, JITSI_JVB_AUTH_PASSWORD

Step 6: Email Configuration

Choose between:

  • MailHog (default) — captures all outgoing emails at http://localhost:8025 for development
  • Production SMTP — configures host, port, user, and password. Optionally shares credentials with Listmonk for newsletter delivery

Step 7: Feature Flags

Enable or disable 9 optional platform features:

Flag Environment Variable What It Enables
Media Manager ENABLE_MEDIA_FEATURES=true Video library, analytics, scheduled publishing
Listmonk Sync LISTMONK_SYNC_ENABLED=true Newsletter subscriber sync from platform participants
Payments ENABLE_PAYMENTS=true Stripe-based products, donations, and plans
Rocket.Chat ENABLE_CHAT=true Team communication platform
Gancio Events GANCIO_SYNC_ENABLED=true Shift-to-event sync with Gancio
Jitsi Meet ENABLE_MEET=true Video conferencing (also prompts for server public IP)
SMS Campaigns ENABLE_SMS=true Termux Android bridge for SMS (also prompts for API URL)
Docs Comments GITEA_COMMENTS_ENABLED=true Gitea-backed page comments on documentation
Bunker Ops BUNKER_OPS_ENABLED=true Fleet metrics push to central server (also prompts for remote write URL)

Step 8: Tunnel Configuration (Pangolin)

Optionally configures Pangolin tunnel credentials for secure public access:

  • PANGOLIN_API_URL — API endpoint (default: https://api.bnkserve.org/v1)
  • PANGOLIN_API_KEY — Authentication key
  • PANGOLIN_ORG_ID — Organization identifier

Complete tunnel setup is done from the admin GUI at Settings > Tunnel after services are running.

Step 9: CORS Origins

Automatically calculates allowed origins from your domain:

http://app.DOMAIN,https://app.DOMAIN,http://DOMAIN,https://DOMAIN,http://localhost:3000,http://localhost,http://localhost:4003

Step 10: Nginx Config Generation

Renders all .conf.template files in nginx/conf.d/ by substituting ${DOMAIN} with your configured domain. This produces the nginx configuration files that handle subdomain routing.

Step 11: Homepage Services YAML

Generates configs/homepage/services.yaml with 27 service entries (both production and local development URLs) for the Homepage service dashboard.

Step 12: Container Directory Permissions

Creates and sets permissions (775) on 12 directories needed by containers:

Directory Purpose
configs/code-server/.config Code Server configuration
configs/code-server/.local Code Server local data
mkdocs/.cache MkDocs build cache
mkdocs/site MkDocs built site output
assets/uploads Listmonk uploads
assets/images Shared images
assets/icons Homepage icons
media/local/inbox Media upload inbox
media/local/thumbnails Video thumbnails
media/public Public media files
local-files n8n local files
data NAR import data

Step 13: Upgrade Watcher (Optional)

Installs a systemd path watcher that enables the admin GUI's "Check for Updates" and "Start Upgrade" buttons. This step requires sudo and is optional — you can install it later or use the CLI upgrade script directly.

The watcher installs two systemd units:

  • changemaker-upgrade.path — watches for data/upgrade/trigger.json
  • changemaker-upgrade.service — runs scripts/upgrade-watcher.sh when triggered

Step 14: Summary & Next Steps

Displays a configuration summary showing all choices made, then prints startup commands.


What Gets Modified

After the wizard completes, the following files have been created or modified:

File Action
.env Created (or updated) with all configuration values
mkdocs/mkdocs.yml Updated site_url and repo_url with domain
nginx/conf.d/*.conf Generated from .conf.template files
configs/homepage/services.yaml Generated with all service URLs
12 directories Created with container-friendly permissions
systemd units (optional) Installed to /etc/systemd/system/

Manual Setup (Alternative)

If you prefer to configure by hand instead of using the wizard:

cp .env.example .env

At minimum, set these required secrets:

# Generate cryptographic secrets
V2_POSTGRES_PASSWORD=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | head -c 24)
REDIS_PASSWORD=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | head -c 24)
JWT_ACCESS_SECRET=$(openssl rand -hex 32)
JWT_REFRESH_SECRET=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)

Set your admin credentials (password must meet the 12+ char complexity requirement):

INITIAL_ADMIN_EMAIL=admin@yourdomain.org
INITIAL_ADMIN_PASSWORD=YourStrongPassword1

Then configure optional sections:

  • Domain: Set DOMAIN and all derived variables (see Step 3 table above)
  • SMTP: Set SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, EMAIL_TEST_MODE=false
  • Feature flags: Enable features as needed (see Step 7 table above)
  • Tunnel: Set PANGOLIN_API_URL, PANGOLIN_API_KEY, PANGOLIN_ORG_ID

See Environment Variables for every available option.


Full Stack Startup

After configuration, start the entire platform:

docker compose up -d

That's it. Docker handles the startup order automatically:

  1. PostgreSQL and Redis start first (with healthchecks)
  2. API waits for both to be healthy, then auto-runs database migrations and seeding
  3. Admin GUI waits for the API
  4. Nginx, media, communication, and all other services start in parallel
  5. Init containers (nocodb-init, listmonk-init, etc.) run once and exit

Watch the startup progress:

docker compose logs -f api --tail 20

Once you see Starting server on port 4000, open http://localhost:3000 and log in.

Include Monitoring

The monitoring stack (Prometheus, Grafana, Alertmanager) uses a Docker Compose profile and isn't included by default:

docker compose --profile monitoring up -d

Start Only Core Services

If you prefer a minimal startup (lower resource usage):

docker compose up -d v2-postgres redis api admin nginx

Manual migrations

The API container runs migrations and seeding automatically on startup via its entrypoint script. You only need to run them manually if you're developing locally without Docker:

cd api && npx prisma migrate deploy && npx prisma db seed

See Services Overview for the complete service catalog.


Verifying Installation

After starting services, verify everything is healthy:

# 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

You should see the API return {"status":"ok"} and all started containers in a "running" state.


Next Steps