Skip to content

Latest commit

 

History

History
104 lines (81 loc) · 4.41 KB

File metadata and controls

104 lines (81 loc) · 4.41 KB

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.

How the proxy works

The browser issues every Honcho call same-origin to /api/* and names the real upstream per request in an X-Honcho-Upstream header (sourced from the active instance's base URL). nginx strips /api, forwards to that upstream server-side, and returns the response. Because the browser→nginx hop is same-origin, no CORS applies; the nginx→Honcho hop is server-side, where CORS is irrelevant. The frontend stays the source of truth for which instance to talk to, so the multi-instance switcher and the Fleet view keep working.

Compose: dev vs prod profiles

One docker-compose.yml with two profiles; the shared config (env, ports, extra_hosts) is defined once via a YAML anchor:

  • dev profilebuild: ., runs your local source (make up).
  • prod profile — pulls the published image (ghcr.io/offendingcommit/openconcho-web:latest, pull_policy: always) (make prod).
make up      # build from source + run                → http://localhost:8080
make prod    # pull ghcr…:latest instead of building
make down    # stop + remove (either profile)
make clean   # down + drop the locally built image

make up expands to docker compose --profile dev up -d --build and make prod to docker compose --profile prod up -d. A bare docker compose up (no profile) starts nothing — use the make targets or pass --profile. Set env inline or via a .env file:

OPENCONCHO_DEFAULT_HONCHO_URL=https://honcho.example.net make prod

The published image is multi-arch (amd64 + arm64); the first publish creates a private GHCR package — make it public for unauthenticated pulls.

Add it to an existing Honcho Compose stack

Drop the openconcho service into the project that runs your Honcho api, pointing the seed at the api service (nginx resolves it on the compose network):

services:
  openconcho:
    image: ghcr.io/offendingcommit/openconcho-web:latest
    environment:
      OPENCONCHO_DEFAULT_HONCHO_URL: http://api:8000
    ports:
      - "127.0.0.1:8080:8080"
    depends_on:
      api:
        condition: service_healthy
    restart: unless-stopped

OPENCONCHO_DEFAULT_HONCHO_URL seeds the UI's first instance with an absolute URL. The browser sends that URL in the X-Honcho-Upstream header; nginx (on the compose network) forwards to it — no browser CORS, and the API token never leaves the origin.

Standalone (no compose)

docker run --rm -p 8080:8080 -e OPENCONCHO_DEFAULT_HONCHO_URL=http://host.docker.internal:8000 \
  ghcr.io/offendingcommit/openconcho-web:latest
# → http://localhost:8080  ·  GET /healthz returns "ok"

Runtime knobs (no rebuild needed):

Env Default Meaning
OPENCONCHO_DEFAULT_HONCHO_URL (empty) Absolute URL seeding the first instance; empty = configure in Settings
OPENCONCHO_UPSTREAM_ALLOWLIST (empty) Optional SSRF guard: comma-separated host globs (e.g. honcho.example.net,*.honcho.dev). Empty = forward anywhere

Hardened run adds --read-only --cap-drop ALL --security-opt no-new-privileges with --tmpfs /tmp --tmpfs /var/cache/nginx. Note: the entrypoint writes config.js and the allowlist map at start, which a read-only root blocks — under --read-only either bind-mount those paths or leave the env empty and configure the URL in Settings.

SSRF: when to set the allowlist

The header-driven proxy forwards to whatever upstream the client names. With the default 127.0.0.1:8080 binding only your own machine can reach nginx, so leaving the allowlist open is fine. Before exposing the proxy (e.g. behind a tunnel), set OPENCONCHO_UPSTREAM_ALLOWLIST to the host globs you trust — non-matching upstreams are rejected with 403 and an X-Honcho-Proxy-Reject: allowlist header.

CORS, the short version

The desktop app routes HTTP through Rust (reqwest) and bypasses browser CORS; the web build solves it with the same-origin /api proxy above — nothing to configure on Honcho. The proxy makes a Honcho-side CORSMiddleware unnecessary regardless of which instance you point at.