MVP Shipment: Self-hosted distribution, packaging, release process #56

Open
opened 2026-04-11 14:37:03 +02:00 by claude · 0 comments
Owner

MVP Shipment Readiness — Self-Hosted Cameleer

Context

Ship Cameleer as a self-hosted product to first paying customers. Target audience: technically proficient Docker users on their own infrastructure. They get the cameleer3-server (observability product) directly — NOT the SaaS vendor plane. No Logto, no multi-tenant layer. The server's LicenseInfo.open() default already gives unlimited features with no license token, so no license infrastructure needed for MVP.

The codebase is feature-complete. The gaps are entirely in distribution, packaging, naming, documentation, and release process.


Product Definition (Self-Hosted)

What the customer deploys (5 services):

Service Image Purpose
Server ghcr.io/cameleer-io/server:1 Observability backend (port 8081)
Dashboard ghcr.io/cameleer-io/dashboard:1 React SPA (nginx)
PostgreSQL postgres:16-alpine RBAC, config, runtime mgmt
ClickHouse clickhouse/clickhouse-server:24 Traces, metrics, logs, stats
Traefik traefik:v3 Reverse proxy + routing for deployed apps

Plus ghcr.io/cameleer-io/runtime:1 (auto-pulled when customer deploys Camel apps).

What they do NOT get: cameleer-saas, Logto, logto-bootstrap, vendor-seed, multi-tenant provisioning.


Gap Analysis

P0 — Ship Blockers

# Gap Current State Impact
1 No public image registry All images on private gitea.siegeln.net/cameleer/ Customer cannot pull any image
2 No self-hosted docker-compose Only SaaS compose (includes Logto, vendor plane) and server dev compose (just PG) No way to stand up the product
3 Runtime base image uses local name application.yml:46cameleer-runtime-base:latest (bare name, no registry) App deployment fails — Docker can't pull
4 No .env.example for self-hosted SaaS .env.example is outdated and SaaS-specific Customer has no config template
5 ClickHouse has no auth clickhouse-users.xml: default user, no password, ::0/0 Any container on network can access all data
6 Default admin password is admin application.yml:72CAMELEER_UI_PASSWORD:admin Insecure out-of-box

P1 — Important for Trust

# Gap Current State Impact
7 No versioning/release process Server 1.0-SNAPSHOT, no git tags, CI tags :latest and :$SHA only Customer can't pin versions or track changes
8 Confusing image names cameleer3-server (internal "3"), cameleer3-server-ui (verbose) Unprofessional, confusing
9 No Prometheus /metrics Actuator exposes only health DevOps teams can't monitor Cameleer itself
10 No customer documentation Only developer-facing HOWTO.md and CLAUDE.md Customer can't self-serve
11 No health checks in compose Server has /api/v1/health but no HEALTHCHECK in compose Docker doesn't know service readiness
12 No install script Manual setup only Poor first-run experience

P2 — Polish (post-MVP)

# Gap Notes
13 No _FILE suffix for secrets Industry pattern for Docker secrets/K8s
14 No upgrade guide docker compose pull && up -d works but undocumented
15 No uninstall docs Three-tier cleanup should be documented
16 No in-app version display No way to check running version from UI
17 No update notification No way for customer to know new version exists

Naming Convention

Public Image Names (GHCR)

Internal Name Public Name Rationale
cameleer3-server ghcr.io/cameleer-io/server Drop "3", org prefix says "cameleer"
cameleer3-server-ui ghcr.io/cameleer-io/dashboard Customer sees a dashboard, not "server-ui"
cameleer-runtime-base ghcr.io/cameleer-io/runtime Short, clear

GitHub org: cameleer-io (GitHub doesn't allow dots in org names; cameleer.io domain → cameleer-io org).

Image Tagging Strategy

Tag Meaning Example
1.0.0 Exact release ghcr.io/cameleer-io/server:1.0.0
1.0 Latest patch of 1.0.x Auto-updated on each 1.0.x release
1 Latest minor of 1.x Recommended for .env — gets patches + features
latest Latest stable Not recommended for production

Docker Compose Naming (self-hosted)

Resource Name Notes
Project name cameleer Top-level name: cameleer
Containers cameleer-server, cameleer-dashboard, cameleer-db, cameleer-clickhouse, cameleer-proxy Explicit container_name:
Volumes cameleer-db-data, cameleer-ch-data, cameleer-jars, cameleer-certs With name:
Networks cameleer (internal), cameleer-routing (Traefik ↔ deployed apps) With name:

Implementation Plan

Phase 1: Registry & Release Pipeline

Goal: Images pullable from public GHCR with semantic versioning.

Tasks:

  1. Create GitHub org cameleer-io, enable GHCR packages
  2. Create GitHub PAT with write:packages scope, add as GHCR_TOKEN secret in Gitea CI
  3. Add .gitea/workflows/release.yml to cameleer3-server repo:
    • Trigger: push: tags: ['v*']
    • Build server JAR + UI (same steps as existing CI)
    • Build 3 Docker images: server, dashboard, runtime
    • Push to GHCR with SemVer multi-tag (1.0.0, 1.0, 1, latest)
    • Also push to Gitea registry (internal use)
    • Create Gitea release with auto-generated notes
  4. Update pom.xml version from 1.0-SNAPSHOT to 1.0.0
  5. Tag v1.0.0, verify GHCR images are public and pullable without auth

Critical files:

  • cameleer3-server/.gitea/workflows/release.yml (new)
  • cameleer3-server/pom.xml (version bump)

Note on runtime-base: Currently built in cameleer-saas CI (docker/runtime-base/Dockerfile). The release workflow needs to also build this image. Either move the Dockerfile to the server repo, or add a GHCR push step to the SaaS CI's release workflow.

Phase 2: Self-Hosted Distribution Repo

Goal: Customer can clone one repo and have everything needed.

Tasks:

  1. Create cameleer-io/self-hosted repo on GitHub (public)
  2. Write docker-compose.yml with 5 services + proper health checks:
    • proxy (Traefik v3): ports 80/443, Docker socket, TLS certs
    • server (ghcr.io/cameleer-io/server:1): Docker socket, JAR volume, connects to both networks
    • dashboard (ghcr.io/cameleer-io/dashboard:1): nginx proxies /api/ to server
    • db (postgres:16-alpine): health check via pg_isready
    • clickhouse (clickhouse/clickhouse-server:24): health check via clickhouse-client
  3. Write .env.example with <10 required vars:
    CAMELEER_ADMIN_PASSWORD=     # (generated by install.sh)
    CAMELEER_JWT_SECRET=         # (generated by install.sh)
    CAMELEER_AUTH_TOKEN=         # Bootstrap token for agent registration
    POSTGRES_PASSWORD=           # (generated by install.sh)
    CLICKHOUSE_PASSWORD=         # (generated by install.sh)
    CAMELEER_HOST=localhost      # Public hostname
    CAMELEER_VERSION=1           # Image tag
    
  4. Write config files:
    • config/traefik.yml — simplified (no Logto routing, no admin-console port)
    • config/traefik-dynamic.yml — TLS default cert, root redirect to dashboard
    • config/clickhouse-users.xml — with password auth from env var
    • config/clickhouse-init.sqlCREATE DATABASE IF NOT EXISTS cameleer;
  5. Write install.sh:
    • Validate: Docker >= 24, Compose >= 2.20, 4GB RAM, ports 80/443 free
    • Generate secrets: JWT, PG password, CH password, auth token, admin password
    • Generate self-signed TLS cert (or accept CERT_FILE/KEY_FILE)
    • docker compose pull (including runtime image pre-pull)
    • docker compose up -d
    • Wait for health, print URL + credentials

Key compose design:

  • Server: CAMELEER_RUNTIME_BASE_IMAGE=ghcr.io/cameleer-io/runtime:${CAMELEER_VERSION:-1}
  • Server: CAMELEER_DOCKER_NETWORK=cameleer-routing
  • Server: CAMELEER_ROUTING_DOMAIN=${CAMELEER_HOST:-localhost}
  • Server: CAMELEER_SERVER_URL=http://cameleer-server:8081
  • Server gets Docker socket + cameleer-jars volume
  • Dashboard nginx proxies /api/ to http://server:8081/api/

Phase 3: Server Hardening for Self-Hosted

Goal: Fix P0 security gaps and runtime image config.

Tasks in cameleer3-server repo:

  1. Change runtime base image default in application.yml:46: cameleer-runtime-base:latestghcr.io/cameleer-io/runtime:latest
  2. Add Prometheus metrics:
    • Add micrometer-registry-prometheus to cameleer3-server-app/pom.xml
    • Change application.yml:104: include: healthinclude: health,prometheus
  3. ClickHouse auth and admin password already configurable via env vars — no code changes needed

Phase 4: Documentation

Tasks (in cameleer-io/self-hosted repo):

  1. README.md — Quick Start (prerequisites, one-command install, first login)
  2. docs/configuration.md — Every env var with description, default, example
  3. docs/architecture.md — Component diagram, data flow, network topology
  4. docs/instrumenting-your-app.md — Add agent JAR to a Camel app
  5. docs/upgrade.md — Standard upgrade, backup, rollback
  6. docs/troubleshooting.md — Top 10 issues
  7. docs/oidc.md — Optional OIDC setup (Keycloak, Azure AD, Okta)

Phase 5: cameleer.io Domain Setup

  1. get.cameleer.io — curl install script redirect
  2. docs.cameleer.io — Documentation site
  3. releases.cameleer.io/latest — Version check endpoint

Release Process

First Release (v1.0.0)

  1. Freeze main, update pom.xml: 1.0-SNAPSHOT1.0.0
  2. Tag v1.0.0 → triggers release CI → GHCR + Gitea
  3. Create self-hosted repo with CAMELEER_VERSION=1 default
  4. Test full flow: fresh machine → ./install.sh → login → deploy app

Version Numbering

  • Start at 1.0.0 (mature product — 9 Flyway migrations, full ClickHouse schema, 300+ flows)
  • Patch (1.0.x): bug fixes, security
  • Minor (1.x.0): new features
  • Major (x.0.0): breaking changes

Customer Experience

1. git clone https://github.com/cameleer-io/self-hosted.git cameleer
2. cd cameleer && ./install.sh
3. ~60s later: "Cameleer is running at https://localhost"
4. Login with admin / (generated password)
5. Add agent to Camel app → first traces appear

Upgrade: docker compose pull && docker compose up -d

Uninstall:

docker compose down              # Stop (preserve data)
docker compose down -v           # Stop + delete all data
docker compose down -v --rmi all # Full cleanup

Verification Checklist

  • Fresh install: clean Docker host → ./install.sh → all 5 services healthy → login works
  • Agent connection: deploy Camel app with agent → traces in dashboard
  • App deployment: upload JAR → runtime container starts → app accessible via Traefik
  • Upgrade: v1.0.0 → v1.0.1 → data preserved
  • Uninstall: docker compose down -v → no orphaned resources
  • Security: ClickHouse requires password, admin password not admin after install

Critical Files

Repo File Change
cameleer3-server .gitea/workflows/release.yml New — tag-triggered release to GHCR
cameleer3-server pom.xml Version 1.0-SNAPSHOT1.0.0
cameleer3-server application.yml:46 Runtime base image → ghcr.io/cameleer-io/runtime:latest
cameleer3-server application.yml:103-104 Add prometheus to actuator endpoints
cameleer3-server cameleer3-server-app/pom.xml Add micrometer-registry-prometheus
cameleer-io/self-hosted docker-compose.yml New — 5-service self-hosted compose
cameleer-io/self-hosted .env.example New — documented config template
cameleer-io/self-hosted install.sh New — guided install script
cameleer-io/self-hosted config/* New — Traefik, ClickHouse config
cameleer-io/self-hosted README.md + docs/* New — customer documentation

Registry Alternatives (for future reference)

If GHCR is later undesirable, evaluated alternatives:

Option How Pros Cons
Gitea public packages Enable public visibility on gitea.siegeln.net container packages Zero new infra, already works gitea.siegeln.net URL less professional (fixable with CNAME registry.cameleer.io)
Gitea + customer tokens Keep packages private, issue read-only pull tokens per customer Full access control, revocable Extra onboarding step, token management
Image tarballs docker save to .tar.gz, attach to Gitea releases Works offline/air-gapped, no auth No layer caching, larger downloads (~200-300MB)

Industry Research Summary

Patterns observed from GitLab, Sentry, Plausible, Mattermost, n8n, PostHog:

  • Registry: GHCR trending (Plausible, Logto use it). Docker Hub has 10 pulls/hr anon limit since Apr 2025.
  • Distribution: Dedicated self-hosted repo pattern (Sentry getsentry/self-hosted, Plausible plausible/hosting, Mattermost mattermost/docker).
  • Install: Git clone + install script (Sentry) or Docker Compose template (Plausible, Mattermost). Target <5min to running.
  • Upgrade: Universal pattern: docker compose pull && up -d with auto-migration on startup.
  • Config: <10 required env vars. .env.example with comments. Support _FILE suffix for secrets.
  • Health: Docker HEALTHCHECK + /health endpoint + optional /metrics for Prometheus.
  • Versioning: SemVer. Multi-tag (1.0.0, 1.0, 1, latest). Tag-triggered CI.
  • Docs: Quick Start (most important page), Config Reference, Architecture, Upgrade Guide, Troubleshooting.
  • Licensing: Env var (LICENSE_KEY) most common. LicenseInfo.open() pattern matches n8n/Mattermost CE approach.
  • Uninstall: Document commands, never provide scripts. Three tiers (stop, stop+data, full).
# MVP Shipment Readiness — Self-Hosted Cameleer ## Context Ship Cameleer as a self-hosted product to first paying customers. Target audience: technically proficient Docker users on their own infrastructure. They get the **cameleer3-server** (observability product) directly — NOT the SaaS vendor plane. No Logto, no multi-tenant layer. The server's `LicenseInfo.open()` default already gives unlimited features with no license token, so no license infrastructure needed for MVP. The codebase is feature-complete. The gaps are entirely in **distribution, packaging, naming, documentation, and release process**. --- ## Product Definition (Self-Hosted) **What the customer deploys (5 services):** | Service | Image | Purpose | |---------|-------|---------| | Server | `ghcr.io/cameleer-io/server:1` | Observability backend (port 8081) | | Dashboard | `ghcr.io/cameleer-io/dashboard:1` | React SPA (nginx) | | PostgreSQL | `postgres:16-alpine` | RBAC, config, runtime mgmt | | ClickHouse | `clickhouse/clickhouse-server:24` | Traces, metrics, logs, stats | | Traefik | `traefik:v3` | Reverse proxy + routing for deployed apps | Plus `ghcr.io/cameleer-io/runtime:1` (auto-pulled when customer deploys Camel apps). **What they do NOT get:** cameleer-saas, Logto, logto-bootstrap, vendor-seed, multi-tenant provisioning. --- ## Gap Analysis ### P0 — Ship Blockers | # | Gap | Current State | Impact | |---|-----|--------------|--------| | 1 | **No public image registry** | All images on private `gitea.siegeln.net/cameleer/` | Customer cannot pull any image | | 2 | **No self-hosted docker-compose** | Only SaaS compose (includes Logto, vendor plane) and server dev compose (just PG) | No way to stand up the product | | 3 | **Runtime base image uses local name** | `application.yml:46` → `cameleer-runtime-base:latest` (bare name, no registry) | App deployment fails — Docker can't pull | | 4 | **No `.env.example` for self-hosted** | SaaS `.env.example` is outdated and SaaS-specific | Customer has no config template | | 5 | **ClickHouse has no auth** | `clickhouse-users.xml`: default user, no password, `::0/0` | Any container on network can access all data | | 6 | **Default admin password is `admin`** | `application.yml:72` → `CAMELEER_UI_PASSWORD:admin` | Insecure out-of-box | ### P1 — Important for Trust | # | Gap | Current State | Impact | |---|-----|--------------|--------| | 7 | **No versioning/release process** | Server `1.0-SNAPSHOT`, no git tags, CI tags `:latest` and `:$SHA` only | Customer can't pin versions or track changes | | 8 | **Confusing image names** | `cameleer3-server` (internal "3"), `cameleer3-server-ui` (verbose) | Unprofessional, confusing | | 9 | **No Prometheus `/metrics`** | Actuator exposes only `health` | DevOps teams can't monitor Cameleer itself | | 10 | **No customer documentation** | Only developer-facing HOWTO.md and CLAUDE.md | Customer can't self-serve | | 11 | **No health checks in compose** | Server has `/api/v1/health` but no HEALTHCHECK in compose | Docker doesn't know service readiness | | 12 | **No install script** | Manual setup only | Poor first-run experience | ### P2 — Polish (post-MVP) | # | Gap | Notes | |---|-----|-------| | 13 | No `_FILE` suffix for secrets | Industry pattern for Docker secrets/K8s | | 14 | No upgrade guide | `docker compose pull && up -d` works but undocumented | | 15 | No uninstall docs | Three-tier cleanup should be documented | | 16 | No in-app version display | No way to check running version from UI | | 17 | No update notification | No way for customer to know new version exists | --- ## Naming Convention ### Public Image Names (GHCR) | Internal Name | Public Name | Rationale | |--------------|-------------|-----------| | `cameleer3-server` | `ghcr.io/cameleer-io/server` | Drop "3", org prefix says "cameleer" | | `cameleer3-server-ui` | `ghcr.io/cameleer-io/dashboard` | Customer sees a dashboard, not "server-ui" | | `cameleer-runtime-base` | `ghcr.io/cameleer-io/runtime` | Short, clear | **GitHub org:** `cameleer-io` (GitHub doesn't allow dots in org names; `cameleer.io` domain → `cameleer-io` org). ### Image Tagging Strategy | Tag | Meaning | Example | |-----|---------|---------| | `1.0.0` | Exact release | `ghcr.io/cameleer-io/server:1.0.0` | | `1.0` | Latest patch of 1.0.x | Auto-updated on each 1.0.x release | | `1` | Latest minor of 1.x | Recommended for `.env` — gets patches + features | | `latest` | Latest stable | Not recommended for production | ### Docker Compose Naming (self-hosted) | Resource | Name | Notes | |----------|------|-------| | Project name | `cameleer` | Top-level `name: cameleer` | | Containers | `cameleer-server`, `cameleer-dashboard`, `cameleer-db`, `cameleer-clickhouse`, `cameleer-proxy` | Explicit `container_name:` | | Volumes | `cameleer-db-data`, `cameleer-ch-data`, `cameleer-jars`, `cameleer-certs` | With `name:` | | Networks | `cameleer` (internal), `cameleer-routing` (Traefik ↔ deployed apps) | With `name:` | --- ## Implementation Plan ### Phase 1: Registry & Release Pipeline **Goal:** Images pullable from public GHCR with semantic versioning. **Tasks:** 1. Create GitHub org `cameleer-io`, enable GHCR packages 2. Create GitHub PAT with `write:packages` scope, add as `GHCR_TOKEN` secret in Gitea CI 3. Add `.gitea/workflows/release.yml` to `cameleer3-server` repo: - Trigger: `push: tags: ['v*']` - Build server JAR + UI (same steps as existing CI) - Build 3 Docker images: `server`, `dashboard`, `runtime` - Push to GHCR with SemVer multi-tag (`1.0.0`, `1.0`, `1`, `latest`) - Also push to Gitea registry (internal use) - Create Gitea release with auto-generated notes 4. Update `pom.xml` version from `1.0-SNAPSHOT` to `1.0.0` 5. Tag `v1.0.0`, verify GHCR images are public and pullable without auth **Critical files:** - `cameleer3-server/.gitea/workflows/release.yml` (new) - `cameleer3-server/pom.xml` (version bump) **Note on runtime-base:** Currently built in cameleer-saas CI (`docker/runtime-base/Dockerfile`). The release workflow needs to also build this image. Either move the Dockerfile to the server repo, or add a GHCR push step to the SaaS CI's release workflow. ### Phase 2: Self-Hosted Distribution Repo **Goal:** Customer can clone one repo and have everything needed. **Tasks:** 1. Create `cameleer-io/self-hosted` repo on GitHub (public) 2. Write `docker-compose.yml` with 5 services + proper health checks: - `proxy` (Traefik v3): ports 80/443, Docker socket, TLS certs - `server` (ghcr.io/cameleer-io/server:1): Docker socket, JAR volume, connects to both networks - `dashboard` (ghcr.io/cameleer-io/dashboard:1): nginx proxies `/api/` to server - `db` (postgres:16-alpine): health check via `pg_isready` - `clickhouse` (clickhouse/clickhouse-server:24): health check via `clickhouse-client` 3. Write `.env.example` with <10 required vars: ``` CAMELEER_ADMIN_PASSWORD= # (generated by install.sh) CAMELEER_JWT_SECRET= # (generated by install.sh) CAMELEER_AUTH_TOKEN= # Bootstrap token for agent registration POSTGRES_PASSWORD= # (generated by install.sh) CLICKHOUSE_PASSWORD= # (generated by install.sh) CAMELEER_HOST=localhost # Public hostname CAMELEER_VERSION=1 # Image tag ``` 4. Write config files: - `config/traefik.yml` — simplified (no Logto routing, no admin-console port) - `config/traefik-dynamic.yml` — TLS default cert, root redirect to dashboard - `config/clickhouse-users.xml` — with password auth from env var - `config/clickhouse-init.sql` — `CREATE DATABASE IF NOT EXISTS cameleer;` 5. Write `install.sh`: - Validate: Docker >= 24, Compose >= 2.20, 4GB RAM, ports 80/443 free - Generate secrets: JWT, PG password, CH password, auth token, admin password - Generate self-signed TLS cert (or accept CERT_FILE/KEY_FILE) - `docker compose pull` (including runtime image pre-pull) - `docker compose up -d` - Wait for health, print URL + credentials **Key compose design:** - Server: `CAMELEER_RUNTIME_BASE_IMAGE=ghcr.io/cameleer-io/runtime:${CAMELEER_VERSION:-1}` - Server: `CAMELEER_DOCKER_NETWORK=cameleer-routing` - Server: `CAMELEER_ROUTING_DOMAIN=${CAMELEER_HOST:-localhost}` - Server: `CAMELEER_SERVER_URL=http://cameleer-server:8081` - Server gets Docker socket + `cameleer-jars` volume - Dashboard nginx proxies `/api/` to `http://server:8081/api/` ### Phase 3: Server Hardening for Self-Hosted **Goal:** Fix P0 security gaps and runtime image config. **Tasks in cameleer3-server repo:** 1. Change runtime base image default in `application.yml:46`: `cameleer-runtime-base:latest` → `ghcr.io/cameleer-io/runtime:latest` 2. Add Prometheus metrics: - Add `micrometer-registry-prometheus` to `cameleer3-server-app/pom.xml` - Change `application.yml:104`: `include: health` → `include: health,prometheus` 3. ClickHouse auth and admin password already configurable via env vars — no code changes needed ### Phase 4: Documentation **Tasks (in `cameleer-io/self-hosted` repo):** 1. `README.md` — Quick Start (prerequisites, one-command install, first login) 2. `docs/configuration.md` — Every env var with description, default, example 3. `docs/architecture.md` — Component diagram, data flow, network topology 4. `docs/instrumenting-your-app.md` — Add agent JAR to a Camel app 5. `docs/upgrade.md` — Standard upgrade, backup, rollback 6. `docs/troubleshooting.md` — Top 10 issues 7. `docs/oidc.md` — Optional OIDC setup (Keycloak, Azure AD, Okta) ### Phase 5: cameleer.io Domain Setup 1. `get.cameleer.io` — curl install script redirect 2. `docs.cameleer.io` — Documentation site 3. `releases.cameleer.io/latest` — Version check endpoint --- ## Release Process ### First Release (v1.0.0) 1. Freeze `main`, update `pom.xml`: `1.0-SNAPSHOT` → `1.0.0` 2. Tag `v1.0.0` → triggers release CI → GHCR + Gitea 3. Create self-hosted repo with `CAMELEER_VERSION=1` default 4. Test full flow: fresh machine → `./install.sh` → login → deploy app ### Version Numbering - Start at **1.0.0** (mature product — 9 Flyway migrations, full ClickHouse schema, 300+ flows) - Patch (1.0.x): bug fixes, security - Minor (1.x.0): new features - Major (x.0.0): breaking changes --- ## Customer Experience ``` 1. git clone https://github.com/cameleer-io/self-hosted.git cameleer 2. cd cameleer && ./install.sh 3. ~60s later: "Cameleer is running at https://localhost" 4. Login with admin / (generated password) 5. Add agent to Camel app → first traces appear ``` **Upgrade:** `docker compose pull && docker compose up -d` **Uninstall:** ``` docker compose down # Stop (preserve data) docker compose down -v # Stop + delete all data docker compose down -v --rmi all # Full cleanup ``` --- ## Verification Checklist - [ ] Fresh install: clean Docker host → `./install.sh` → all 5 services healthy → login works - [ ] Agent connection: deploy Camel app with agent → traces in dashboard - [ ] App deployment: upload JAR → runtime container starts → app accessible via Traefik - [ ] Upgrade: v1.0.0 → v1.0.1 → data preserved - [ ] Uninstall: `docker compose down -v` → no orphaned resources - [ ] Security: ClickHouse requires password, admin password not `admin` after install --- ## Critical Files | Repo | File | Change | |------|------|--------| | cameleer3-server | `.gitea/workflows/release.yml` | **New** — tag-triggered release to GHCR | | cameleer3-server | `pom.xml` | Version `1.0-SNAPSHOT` → `1.0.0` | | cameleer3-server | `application.yml:46` | Runtime base image → `ghcr.io/cameleer-io/runtime:latest` | | cameleer3-server | `application.yml:103-104` | Add `prometheus` to actuator endpoints | | cameleer3-server | `cameleer3-server-app/pom.xml` | Add `micrometer-registry-prometheus` | | cameleer-io/self-hosted | `docker-compose.yml` | **New** — 5-service self-hosted compose | | cameleer-io/self-hosted | `.env.example` | **New** — documented config template | | cameleer-io/self-hosted | `install.sh` | **New** — guided install script | | cameleer-io/self-hosted | `config/*` | **New** — Traefik, ClickHouse config | | cameleer-io/self-hosted | `README.md` + `docs/*` | **New** — customer documentation | --- ## Registry Alternatives (for future reference) If GHCR is later undesirable, evaluated alternatives: | Option | How | Pros | Cons | |--------|-----|------|------| | **Gitea public packages** | Enable public visibility on `gitea.siegeln.net` container packages | Zero new infra, already works | `gitea.siegeln.net` URL less professional (fixable with CNAME `registry.cameleer.io`) | | **Gitea + customer tokens** | Keep packages private, issue read-only pull tokens per customer | Full access control, revocable | Extra onboarding step, token management | | **Image tarballs** | `docker save` to .tar.gz, attach to Gitea releases | Works offline/air-gapped, no auth | No layer caching, larger downloads (~200-300MB) | --- ## Industry Research Summary Patterns observed from GitLab, Sentry, Plausible, Mattermost, n8n, PostHog: - **Registry:** GHCR trending (Plausible, Logto use it). Docker Hub has 10 pulls/hr anon limit since Apr 2025. - **Distribution:** Dedicated self-hosted repo pattern (Sentry `getsentry/self-hosted`, Plausible `plausible/hosting`, Mattermost `mattermost/docker`). - **Install:** Git clone + install script (Sentry) or Docker Compose template (Plausible, Mattermost). Target <5min to running. - **Upgrade:** Universal pattern: `docker compose pull && up -d` with auto-migration on startup. - **Config:** <10 required env vars. `.env.example` with comments. Support `_FILE` suffix for secrets. - **Health:** Docker HEALTHCHECK + `/health` endpoint + optional `/metrics` for Prometheus. - **Versioning:** SemVer. Multi-tag (`1.0.0`, `1.0`, `1`, `latest`). Tag-triggered CI. - **Docs:** Quick Start (most important page), Config Reference, Architecture, Upgrade Guide, Troubleshooting. - **Licensing:** Env var (`LICENSE_KEY`) most common. `LicenseInfo.open()` pattern matches n8n/Mattermost CE approach. - **Uninstall:** Document commands, never provide scripts. Three tiers (stop, stop+data, full).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cameleer/cameleer-saas#56