Bundled packages auto-install on first boot for zero-config first run. Builder image for faster custom builds. Per-environment allowlists for K8s/Helm (dev=all, test=all, prod=skip). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6.5 KiB
Distribution Guide
Quick Start
docker pull ghcr.io/switchboard-core/switchboard-core:latest
docker run -p 8080:80 \
-e SWITCHBOARD_ADMIN_USERNAME=admin \
-e SWITCHBOARD_ADMIN_PASSWORD=changeme \
ghcr.io/switchboard-core/switchboard-core:latest
On first run, bundled packages are automatically installed — workflows, surfaces, and extensions are ready to use immediately.
Bundled Packages
The production Docker image ships with pre-built packages that are auto-installed on first boot:
| Package | Type | Description |
|---|---|---|
| bug-report-triage | workflow | Public entry, severity routing, SLA timers |
| content-approval | workflow | Multi-party signoff example |
| employee-onboarding | workflow | Automated provisioning + manager signoff |
| webhook-notifier | workflow | HTTP outbound via connections + Starlark |
| workflow-demo | surface | Interactive walkthrough with diagrams |
| hello-dashboard | surface | Welcome/getting started surface |
| schedules | surface | Cron task management UI |
| tasks | full | Kanban/list task manager with webhooks |
| team-activity-log | surface | Team activity feed |
| gitea-client | library | Gitea API integration library |
| icd-test-runner | surface | E2E API test suite |
| sdk-test-runner | surface | SDK feature test suite |
Behavior
- First boot: All bundled packages are installed and enabled automatically.
- Subsequent boots: No-op — already-installed packages are skipped.
- Admin uninstalls a package: It stays uninstalled. Bundled packages are never force-reinstalled.
- To re-install: Delete the package from the database, then restart the container.
Selecting Packages (Allowlist)
Set BUNDLED_PACKAGES to a comma-separated list of package IDs to install only a subset:
# K8s / Helm — install only core surfaces, no demo/test packages
docker run -p 8080:80 \
-e BUNDLED_PACKAGES="tasks,schedules,hello-dashboard" \
ghcr.io/switchboard-core/switchboard-core:latest
Empty (default) means install all bundled packages. This is useful for Helm charts where different environments need different packages.
Disabling Auto-Install
Set SKIP_BUNDLED_PACKAGES=true to prevent bundled packages from being installed:
docker run -p 8080:80 \
-e SKIP_BUNDLED_PACKAGES=true \
ghcr.io/switchboard-core/switchboard-core:latest
Custom Bundle Directory
Override the default bundled packages location with BUNDLED_PACKAGES_DIR:
docker run -p 8080:80 \
-e BUNDLED_PACKAGES_DIR=/custom/packages \
-v /host/packages:/custom/packages \
ghcr.io/switchboard-core/switchboard-core:latest
Builder Image
The builder image pre-caches Go modules and Node dependencies for faster custom builds.
docker pull ghcr.io/switchboard-core/builder:latest
What It Caches
- Go module cache (
go mod downloadfor all server dependencies) - Node modules for the CM6 editor bundle
- Vendor library tarballs (marked, DOMPurify, mermaid, KaTeX)
- Build tools (zip, Node.js runtime)
Using in Custom Builds
Reference the builder image as a base stage in your Dockerfile:
FROM ghcr.io/switchboard-core/builder:latest AS builder
WORKDIR /app
COPY server/ .
RUN go build -ldflags="-s -w" -o /bin/switchboard .
Building Locally
docker build -f Dockerfile.builder -t switchboard-builder .
Custom Build Guide
Adding Custom Packages
- Create your package in
packages/your-package/with amanifest.json - Build all packages:
cd packages && bash build.sh all - Build the Docker image:
docker build -t my-switchboard .
The Dockerfile automatically builds all packages in the packages/ directory and bundles them into the production image.
Removing Bundled Packages
To exclude specific packages from the bundle, either:
- Remove them from
packages/before building - Set
SKIP_BUNDLED_PACKAGES=trueand install packages manually via the admin UI
Forking for Custom Builds
git clone https://github.com/switchboard-core/switchboard-core.git
cd switchboard-core
# Add/modify packages
cp -r my-extension packages/my-extension/
# Build with builder image for faster compilation
docker build -t my-switchboard .
Production Deployment
Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
Backend API port |
DB_DRIVER |
(auto) | postgres or sqlite |
DATABASE_URL |
PostgreSQL connection string | |
JWT_SECRET |
dev-secret-change-me |
Must change in production |
ENCRYPTION_KEY |
AES-256 key for credential encryption | |
AUTH_MODE |
builtin |
builtin, mtls, or oidc |
STORAGE_BACKEND |
(auto) | pvc or s3 |
STORAGE_PATH |
/data/storage |
PVC mount point |
BASE_PATH |
URL prefix (e.g. /switchboard) |
|
SKIP_BUNDLED_PACKAGES |
false |
Disable auto-install of bundled packages |
BUNDLED_PACKAGES |
(empty = all) | Comma-separated allowlist of package IDs to install |
BUNDLED_PACKAGES_DIR |
/app/bundled-packages |
Override bundled packages location |
LOG_FORMAT |
text |
text or json |
LOG_LEVEL |
info |
debug, info, warn, error |
Database
PostgreSQL is recommended for production. SQLite is suitable for single-instance evaluation.
# PostgreSQL (recommended)
docker run -p 8080:80 \
-e DATABASE_URL="postgres://user:pass@host:5432/switchboard?sslmode=require" \
-e JWT_SECRET="$(openssl rand -hex 32)" \
-e ENCRYPTION_KEY="$(openssl rand -hex 32)" \
ghcr.io/switchboard-core/switchboard-core:latest
# SQLite (evaluation only)
docker run -p 8080:80 \
-e DB_DRIVER=sqlite \
-v switchboard-data:/data \
ghcr.io/switchboard-core/switchboard-core:latest
Storage
Object storage is required for file uploads and package asset extraction.
# PVC (auto-detected if path is writable)
docker run -v switchboard-storage:/data/storage ...
# S3-compatible (MinIO, AWS S3, Ceph)
docker run \
-e STORAGE_BACKEND=s3 \
-e S3_BUCKET=switchboard \
-e S3_ENDPOINT=https://minio.corp:9000 \
-e S3_ACCESS_KEY=... \
-e S3_SECRET_KEY=... \
-e S3_FORCE_PATH_STYLE=true \
...
Kubernetes
See the k8s/ directory for example manifests. Key considerations:
- Use
POSTGRES_HOST,POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_DBenv vars (assembled into DSN automatically) - Set liveness probe to
/healthz/live, readiness probe to/healthz/ready - Mount a PVC at
/data/storagefor file storage, or configure S3 - Set
JWT_SECRETandENCRYPTION_KEYvia Kubernetes Secrets