Files
openconcho/docs/docker.md
Offending Commit 282ba1b76c feat(docker): full self-hosted Compose support
Make the web image drop-in for a Honcho docker-compose stack:
- nginx reverse-proxies /v3 and /health to $HONCHO_UPSTREAM (variable +
  Docker resolver so it starts even before the upstream resolves), giving
  the SPA a same-origin path to Honcho with no browser CORS.
- Runtime config: an entrypoint writes config.js from
  OPENCONCHO_DEFAULT_HONCHO_URL, so one prebuilt image targets any backend
  ("same-origin" | absolute URL | empty). SPA seeds a first-run default
  instance from it (additive; no-op in dev/desktop).
- docker-compose.yml example service + GHCR multi-arch publish workflow on
  release.
- nginx.conf -> envsubst template; docs rewritten.

Closes #21. Closes #31.
2026-05-28 16:06:03 -05:00

2.7 KiB

Running OpenConcho in Docker

The @openconcho/web SPA ships as a container: a two-stage build (Node + pnpm builds the static bundle, then nginx-unprivileged serves it on port 8080 as a non-root user) that also reverse-proxies the Honcho API under its own origin, so the browser never makes a cross-origin request.

Honcho's self-hosting path is Docker Compose. Drop the openconcho service from docker-compose.yml into the project that runs your Honcho api:

services:
  openconcho:
    image: ghcr.io/offendingcommit/openconcho-web:latest
    environment:
      HONCHO_UPSTREAM: http://api:8000        # nginx proxies /v3 + /health here
      OPENCONCHO_DEFAULT_HONCHO_URL: same-origin
    ports:
      - "127.0.0.1:8080:8080"
    depends_on:
      api:
        condition: service_healthy
    restart: unless-stopped

OPENCONCHO_DEFAULT_HONCHO_URL: same-origin makes the UI default its Honcho base URL to its own origin, so API calls go through the proxy → no browser CORS, and the API token never leaves the origin. The published image is multi-arch (amd64 + arm64); the first publish creates a private GHCR package — make it public if you want unauthenticated pulls.

Standalone

docker build -t openconcho-web .
docker run --rm -p 8080:8080 -e HONCHO_UPSTREAM=http://host.docker.internal:8000 openconcho-web
# → http://localhost:8080  ·  GET /healthz returns "ok"

Runtime knobs (no rebuild needed):

Env Default Meaning
HONCHO_UPSTREAM http://api:8000 Where nginx proxies /v3 and /health
OPENCONCHO_DEFAULT_HONCHO_URL same-origin SPA's default base URL — same-origin, an absolute URL, or empty (configure in Settings)

Hardened run adds --read-only --cap-drop ALL --security-opt no-new-privileges with --tmpfs /tmp --tmpfs /var/cache/nginx. Note: the runtime config writes config.js into the web root at start, which a read-only root blocks — under --read-only either bind-mount config.js or leave OPENCONCHO_DEFAULT_HONCHO_URL empty and set the URL in Settings.

CORS, the short version

The desktop app routes HTTP through Rust and bypasses browser CORS; the web build doesn't. The Compose setup above solves CORS via the same-origin proxy — nothing to configure on Honcho. If instead you point the UI at a different origin (absolute OPENCONCHO_DEFAULT_HONCHO_URL or a URL typed in Settings), allow that origin in Honcho's FastAPI CORSMiddleware:

app.add_middleware(CORSMiddleware, allow_origins=["https://your-ui-origin"],
                   allow_methods=["*"], allow_headers=["*"])