Files
coder/q5vault/reference/config-paths.md
Antigravity 3478e7b913 coder: let the omp harness drive workspaces over Coders MCP server
Coder ships `coder exp mcp server` and omp is an MCP client, so the two compose
with no custom code. The agent stays on the host where its credentials already
live and reaches into the workspace, rather than shipping secrets into a
container.

- scripts/coder-mcp.sh wraps the server, passing a dedicated `omp-mcp` token via
  `docker exec --env-file` (mode 600 temp file, shredded by an EXIT trap) so the
  token never appears in argv or ps
- allow-list exposes 26 of 32 tools; template mutation is excluded because
  pushing a template is the one real path from a Coder principal to the host
  docker socket
- scripts/coder-token-rotate.sh handles the 168h token lifetime cap: mint,
  verify against the API, then revoke the predecessors
- .omp/mcp.json registers it project-scoped so 26 tools do not load into every
  unrelated omp session

The docker exec must stay in the foreground: backgrounding it makes bash
redirect stdin from /dev/null with job control disabled, and the MCP transport
dies on EOF with "MCP tool load failed ... Transport closed".

Verified: fresh omp session in this directory answered from the tools -
coder_get_authenticated_user returned loca, workspace ws1 running.
2026-08-20 17:46:51 +02:00

11 KiB

title, description, source, reviewed
title description source reviewed
🗂️ Paths, ports, env vars Exhaustive lookup of every file, container, volume, port and CODER_* environment variable in the code.loca.zone deployment, plus the deployed docker-compose.yml verbatim. verified deployment on the loca operator host, 2026-08-19 2026-08-19

🗂️ Paths, ports, env vars

📁 Project files

Path Purpose Owner and notes
/home/loca/dev/coder/ stack root; compose project name coder derives from this directory name loca; run every compose command from here
/home/loca/dev/coder/docker-compose.yml the whole deployment definition: images, pins, ports, env, volumes, memory ceilings loca; edit here, never with docker run flags
/home/loca/dev/coder/.env supplies CODER_PG_PASSWORD to compose interpolation loca, mode 600, git-ignored; contents are never read into or quoted by any document
/home/loca/dev/coder/.mcp-token dedicated Coder token named omp-mcp, consumed by scripts/coder-mcp.sh so the omp harness can call Coder's MCP tools loca, mode 600, git-ignored; 168h maximum lifetime, rotate with scripts/coder-token-rotate.sh
/home/loca/dev/coder/.omp/mcp.json project-scoped MCP registration; mounts the coder server only when omp runs in this directory loca; holds no secret, the token is read by the wrapper
/home/loca/dev/coder/scripts/coder-mcp.sh wraps coder exp mcp server with docker exec --env-file credential passing and a 26-tool allow-list that excludes template mutation loca, mode 755; must run the docker exec in the foreground or the MCP transport dies on EOF
/home/loca/dev/coder/scripts/coder-token-rotate.sh mints a replacement omp-mcp token, verifies it against the API, then revokes the previous ones loca, mode 755; run weekly
/home/loca/dev/coder/scripts/backup-stacks.sh nightly backup driver for both stacks, invoked by stacks-backup.service loca, mode 755; runs as root from the timer, so no sudo inside
/home/loca/dev/coder/.gitignore ignores .env, .admin-credentials, .mcp-token, q5vault/.obsidian/, and terraform working state under templates/ loca; keeps secrets, editor state and tfstate out of version control while the provider lockfile stays committed
/home/loca/dev/coder/config/runtime-version.txt plain-text pin, currently v2.35.3; the human-readable twin of the image tag loca; changes in the same commit as the tag
/home/loca/dev/coder/deploy/code.nginx.conf source of truth for the four nginx server blocks loca; the installed site file is a copy, so edit here first
/home/loca/dev/coder/templates/docker/main.tf pre-validated docker workspace template; one coder_app at subdomain = false, persistent /home/coder volume, no docker socket in the workspace loca; pushed by the operator with coder templates push
/home/loca/dev/coder/templates/docker/.terraform.lock.hcl provider hash lock: coder/coder 2.18.0, kreuzwerker/docker 4.5.0 loca; generated by the provisioner's own terraform (linux_amd64), committed on purpose
/home/loca/dev/coder/templates/docker/README.md operator runbook for the template, incl. cited upstream sources and the validation performed loca
/home/loca/dev/coder/q5vault/ this wiki, the real content vault loca; the wiki grid symlinks into it
/home/loca/dev/coder/quartz.config.coder.yaml Quartz configuration for this wiki: pageTitle Coder SSOT, baseUrl wiki.code.loca.zone, footer links to https://code.loca.zone and https://loca.zone loca; derived from the pwiz config with the same plugin set

🌐 Nginx, TLS and the wiki grid

Path Purpose Owner and notes
/etc/nginx/sites-available/code.loca.zone installed copy of deploy/code.nginx.conf; four server blocks (app 443, wiki 443, app 80, wiki 80) root; sudo -n nginx -t before any reload
/etc/nginx/sites-enabled/code.loca.zone symlink activating the site root
/etc/letsencrypt/live/code.loca.zone/ certificate lineage named code.loca.zone, covering code.loca.zone and wiki.code.loca.zone, expiring 2026-11-17; both vhosts read fullchain.pem and privkey.pem here root, certbot-managed; HTTP-01 via /var/www/html webroot
/home/loca/dev/wikis/code/content symlink to /home/loca/dev/coder/q5vault loca; the vault stays in the project, the grid only points at it
/home/loca/dev/wikis/code/quartz.config.yaml symlink to /home/loca/dev/coder/quartz.config.coder.yaml loca
/home/loca/dev/wikis/code/current symlink to the published dist-* directory and the nginx root for the wiki vhost produced by cd /home/loca/dev/wikis && ./build.sh code; absent until the first build runs
/home/loca/dev/services/authelia/config/configuration.yml shared Authelia access rules; default_policy: bypass, and deliberately no rule for code.loca.zone or wiki.code.loca.zone root-adjacent shared service; do not add a rule for this stack, see operations/auth-model

📦 Containers, volumes, network

Object Definition Notes
container coder service coder, image ghcr.io/coder/coder:v2.35.3, restart: unless-stopped, mem_limit: 8g the control plane; also runs the built-in provisioner
container coder-database service database, image postgres:17, restart: unless-stopped, mem_limit: 2g healthcheck pg_isready -U coder -d coder, interval 5s, timeout 5s, 12 retries; publishes no host port
volume coder_pgdata mounted at /var/lib/postgresql/data in coder-database all Coder state: users, templates, template versions, workspaces, Terraform state; survives docker compose down
volume coder_home mounted at /home/coder in coder server-side cache and config root
bind mount /var/run/docker.sock host socket into coder at the same path required by the built-in provisioner; never mounted into a workspace
group_add: "105" host gid of the docker group, added to the coder container user obtained with getent group docker | cut -d: -f3, not guessed
compose network default project network; coder reaches postgres at hostname database port 5432 the only route to the database

Named volumes are declared as coder_pgdata and coder_home; compose creates named volumes prefixed with the project name, so the docker-side names are coder_coder_pgdata and coder_coder_home. Address them through sudo -n docker compose from the project root.

🔌 Ports

Port Bound where Meaning
52226 host 127.0.0.1 only, published as "127.0.0.1:52226:7080" the sole host-visible socket for this stack; nginx proxies to it
7080 inside the coder container, 0.0.0.0:7080 the server's own listener; all interfaces of its own namespace, unreachable from outside the publish spec
5432 inside the coder-database container reachable only over the compose network
443 and 80 host, nginx code.loca.zone and wiki.code.loca.zone vhosts

Registry context: 52222 pwiz, 52223 reserved for pwiz, 52224 cdsr (code-server), 52226 code (Coder). All loca.zone application backends bind loopback inside 51000-53000. Ad-hoc dev servers started from an IDE or workspace terminal must avoid every registered port; check with ss -ltn first.

⚙️ Environment variables actually set

Variable Value Why
CODER_HTTP_ADDRESS 0.0.0.0:7080 binds all interfaces of the container namespace so the host publish can reach it; a container-local loopback bind would be unreachable
CODER_ACCESS_URL https://code.loca.zone the external URL that users and workspace agents use; upstream requires it whenever the built-in tunnel is not used, and it must not be localhost
CODER_PG_CONNECTION_URL postgresql://coder:${CODER_PG_PASSWORD}@database:5432/coder?sslmode=disable external-database mode against the private postgres container; sslmode=disable is acceptable only because the traffic never leaves the compose network
CODER_TELEMETRY_ENABLE "false" no usage data leaves the host; confirmed by telemetry false in /api/v2/buildinfo
POSTGRES_USER coder database role
POSTGRES_PASSWORD ${CODER_PG_PASSWORD} interpolated from .env; the literal value is never documented
POSTGRES_DB coder database name

Deliberately unset: CODER_WILDCARD_ACCESS_URL (see reference/limits), CODER_TLS_ENABLE and friends (nginx terminates TLS), every CODER_OIDC_* variable (see operations/auth-model), and CODER_DISABLE_PATH_APPS (path-based apps are the only app routing available without a wildcard).

📄 Deployed docker-compose.yml

The password appears only as the ${CODER_PG_PASSWORD} placeholder, exactly as it does on disk.

services:
  database:
    image: postgres:17
    container_name: coder-database
    restart: unless-stopped
    environment:
      POSTGRES_USER: coder
      POSTGRES_PASSWORD: ${CODER_PG_PASSWORD}
      POSTGRES_DB: coder
    volumes:
      - coder_pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U coder -d coder"]
      interval: 5s
      timeout: 5s
      retries: 12
    mem_limit: 2g

  coder:
    image: ghcr.io/coder/coder:v2.35.3
    container_name: coder
    restart: unless-stopped
    depends_on:
      database:
        condition: service_healthy
    ports:
      - "127.0.0.1:52226:7080"
    environment:
      CODER_HTTP_ADDRESS: 0.0.0.0:7080
      CODER_ACCESS_URL: https://code.loca.zone
      CODER_PG_CONNECTION_URL: postgresql://coder:${CODER_PG_PASSWORD}@database:5432/coder?sslmode=disable
      CODER_TELEMETRY_ENABLE: "false"
      # No CODER_WILDCARD_ACCESS_URL. Nested names such as foo.code.loca.zone
      # DO resolve via the *.loca.zone wildcard; the actual blocker is TLS
      # issuance: this lineage covers only code.loca.zone and
      # wiki.code.loca.zone, and a *.code.loca.zone certificate needs DNS-01
      # validation with DNS-provider credentials that are not configured here.
      # Path-based workspace apps and `coder port-forward` are used instead.
    group_add:
      # host gid of /var/run/docker.sock; required so the built-in provisioner
      # can build docker-template workspaces.
      - "105"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - coder_home:/home/coder
    mem_limit: 8g

volumes:
  coder_pgdata:
  coder_home:

🔗 Endpoints worth bookmarking

URL Purpose
http://127.0.0.1:52226/healthz loopback liveness, returns OK
http://127.0.0.1:52226/api/v2/buildinfo running version, advertised dashboard URL, telemetry flag
http://127.0.0.1:52226/api/v2/users/first 200, the initial Owner exists; 404 only on a never-bootstrapped deployment
https://code.loca.zone/ dashboard, no auth redirect
https://code.loca.zone/@<user>/<workspace>.<agent>/apps/<slug>/ path-based workspace app
https://code.loca.zone/@<user>/<workspace>.<agent>/terminal web terminal
https://wiki.code.loca.zone/ this wiki, public

📚 Sources