# Distribution Guide ## Quick Start ```bash docker pull gobha/armature:latest docker run -p 8080:80 \ -e ARMATURE_ADMIN_USERNAME=admin \ -e ARMATURE_ADMIN_PASSWORD=changeme \ gobha/armature: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. A **curated default set** is auto-installed on first boot; additional packages ship in the image and can be opted-in via `BUNDLED_PACKAGES`. #### Default Set (auto-installed) | Package | Type | Description | |---------|------|-------------| | notes | surface | Markdown notes with graph view | | chat | surface | Real-time chat surface | | chat-core | library | Conversations, messages, read cursors | | mermaid-renderer | extension | Diagram rendering | | schedules | surface | Cron task management UI | #### Opt-in (ship in image, require `BUNDLED_PACKAGES` to enable) | Package | Type | Description | |---------|------|-------------| | tasks | full | Kanban/list task manager with webhooks | | workflow-chat | extension | Chat integration for workflow stages | | dashboard | surface | Dashboard surface | | workflow-demo | surface | Interactive walkthrough with diagrams | | bug-report-triage | workflow | Public entry, severity routing, SLA timers | | content-approval | workflow | Multi-party signoff example | | employee-onboarding | workflow | Automated provisioning + manager signoff | | editor | surface | Rich markdown editor | | hello-dashboard | surface | Welcome/getting started surface | | team-activity-log | surface | Team activity feed | | webhook-notifier | workflow | HTTP outbound via connections + Starlark | | csv-table | extension | CSV table renderer | | diff-viewer | extension | Diff visualization | | git-board | surface | Git board interface | | gitea-client | library | Gitea API integration library | | js-sandbox | extension | JavaScript sandbox | | katex-renderer | extension | LaTeX rendering | | regex-tester | extension | Regex testing tool | | icd-test-runner | surface | E2E API test suite | | sdk-test-runner | surface | SDK feature test suite | ### Behavior - **First boot**: Curated default 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 control which packages are installed: ```bash # Install ALL packages (everything in the image) docker run -p 8080:80 \ -e BUNDLED_PACKAGES="*" \ gobha/armature:latest # Install specific packages only docker run -p 8080:80 \ -e BUNDLED_PACKAGES="notes,tasks,schedules" \ gobha/armature:latest ``` Empty (default) installs the curated default set. Use `*` to install all 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: ```bash docker run -p 8080:80 \ -e SKIP_BUNDLED_PACKAGES=true \ gobha/armature:latest ``` ### Custom Bundle Directory Override the default bundled packages location with `BUNDLED_PACKAGES_DIR`: ```bash docker run -p 8080:80 \ -e BUNDLED_PACKAGES_DIR=/custom/packages \ -v /host/packages:/custom/packages \ gobha/armature:latest ``` ## Builder Image The builder image pre-caches Go modules and Node dependencies for faster custom builds. ```bash docker pull gobha/armature-builder:latest ``` ### What It Caches - Go module cache (`go mod download` for 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: ```dockerfile FROM gobha/armature-builder:latest AS builder WORKDIR /app COPY server/ . RUN go build -ldflags="-s -w" -o /bin/armature . ``` ### Building Locally ```bash docker build -f Dockerfile.builder -t armature-builder . ``` ## Custom Build Guide ### Adding Custom Packages 1. Create your package in `packages/your-package/` with a `manifest.json` 2. Build all packages: `cd packages && bash build.sh all` 3. Build the Docker image: `docker build -t my-armature .` 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=true` and install packages manually via the admin UI ### Forking for Custom Builds ```bash git clone https://github.com/gobha/armature.git cd armature # Add/modify packages cp -r my-extension packages/my-extension/ # Build with builder image for faster compilation docker build -t my-armature . ``` ## 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. `/armature`) | | `SKIP_BUNDLED_PACKAGES` | `false` | Disable auto-install of bundled packages | | `BUNDLED_PACKAGES` | (empty = defaults) | `""` curated defaults, `"*"` all, or comma-separated IDs | | `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. ```bash # PostgreSQL (recommended) docker run -p 8080:80 \ -e DATABASE_URL="postgres://user:pass@host:5432/armature?sslmode=require" \ -e JWT_SECRET="$(openssl rand -hex 32)" \ -e ENCRYPTION_KEY="$(openssl rand -hex 32)" \ gobha/armature:latest # SQLite (evaluation only) docker run -p 8080:80 \ -e DB_DRIVER=sqlite \ -v armature-data:/data \ gobha/armature:latest ``` ### Storage Object storage is required for file uploads and package asset extraction. ```bash # PVC (auto-detected if path is writable) docker run -v armature-storage:/data/storage ... # S3-compatible (MinIO, AWS S3, Ceph) docker run \ -e STORAGE_BACKEND=s3 \ -e S3_BUCKET=armature \ -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_DB` env vars (assembled into DSN automatically) - Set liveness probe to `/healthz/live`, readiness probe to `/healthz/ready` - Mount a PVC at `/data/storage` for file storage, or configure S3 - Set `JWT_SECRET` and `ENCRYPTION_KEY` via Kubernetes Secrets