Files
coder/q5vault/reference/limits.md

6.3 KiB

title, description, source, reviewed
title description source reviewed
🚧 Deliberate limits What this Coder deployment does not enable and what each omission costs: no wildcard access URL, no Authelia gate, no open signup, no external provisioner, and a hard memory pressure gate. verified deployment on the loca operator host, 2026-08-19 2026-08-19

🚧 Deliberate limits

Every entry here is a choice, not an oversight. Each one states the cost, the true blocker, and what it would take to lift it.

🌐 No wildcard access URL

CODER_WILDCARD_ACCESS_URL is unset.

  • the true blocker is TLS issuance, not DNS
    • nested names under the host wildcard do resolve; foo.code.loca.zone and even deep.nested.code.loca.zone answer on this host, as does any nonexistent label under loca.zone
    • each certbot lineage covers only the SANs it was issued for; the code.loca.zone lineage covers code.loca.zone and wiki.code.loca.zone and nothing else
    • a *.code.loca.zone certificate requires DNS-01 validation with DNS-provider API credentials, which are not configured on this host; HTTP-01 via the /var/www/html webroot cannot issue wildcards
    • upstream's own nginx walkthrough confirms the shape: a wildcard certificate is obtained with a DNS plugin and a provider API token, not with webroot validation
  • lost features, exactly:
    • dashboard port forwarding, including the Open Ports panel and port sharing URLs
    • coder_app resources with subdomain = true; upstream states such apps are not accessible when the administrator has not set up wildcards
    • web apps that require an absolute root path, notably Vite, the React dev server, the Next.js dev server, JupyterLab and RStudio per upstream
  • kept features, exactly:
    • path-based coder_app resources at /@<user>/<workspace>.<agent>/apps/<slug>/
    • the dashboard and the web terminal
    • coder port-forward from the CLI
    • SSH port forwarding, including coder ssh -R and anything set up by coder config-ssh
    • Coder Desktop and the IDE remotes (VS Code extension, JetBrains Gateway)
  • documented upgrade path, all of it requiring operator approval:
    • obtain a DNS-01 wildcard certificate for *.code.loca.zone, which means adding DNS-provider API credentials to this host
    • add an nginx server block for server_name *.code.loca.zone proxying to 127.0.0.1:52226
    • set CODER_WILDCARD_ACCESS_URL on the coder service and restart it
    • once wildcards work, upstream advises disabling path-based apps (CODER_DISABLE_PATH_APPS=true), because path apps share the Coder API origin and a malicious workspace could reuse Coder cookies against the API
    • note the RFC 1035 label limit: app, agent, workspace and username together must stay under 63 characters in one hostname label

🔓 No Authelia gate

  • cost: the dashboard is publicly reachable and Coder's own login page is the only thing between the internet and the deployment; there is no second factor at the proxy
  • why the cost is accepted: an auth_request gate would 302 every cookie-less request, which is exactly what the coder CLI, the workspace agents and DERP relay traffic send. A browser-only gate is impossible because the SPA and the agents share /api/v2
  • compensating controls: Coder's own session handling, no open signup, a pinned server image, and a single admin account
  • full argument and the OIDC-via-Authelia upgrade path: operations/auth-model

🚫 No open signup

  • cost: onboarding another person is a manual admin action; there is no self-service registration
  • why: POST /api/v2/users requires authentication, so only an admin can mint accounts, and POST /api/v2/users/first exists solely for the initial Owner
  • consequence to respect: do not create accounts for other people on this deployment. Template Admin is root-equivalent here because of the docker socket, so every additional privileged account widens host exposure
  • if multi-user access is ever wanted, do it through OIDC with Authelia as the provider rather than by handing out passwords

🏗️ No external provisioner

  • cost: template builds run inside the coder container, so a heavy build competes with the control plane for the same 8 GB ceiling, and a build failure shows up in the server log rather than in a separate daemon's log
  • why: an external provisioner needs its own credentialed daemon and a scoped provisioner key; for a single-admin docker-only deployment that is more moving parts than it removes
  • security note carried over from upstream: provisioner daemons hold the credentials that can create compute. Here that credential is the bind-mounted /var/run/docker.sock, which makes the server root-equivalent on the host. Containment list: operations/workspaces

🧠 Memory and swap pressure gate

The measured state of this host on 2026-08-19, before Coder existed:

  • free -m showed 36447 of 60278 MB used
  • swap was 15926 of 16383 MB consumed, that is effectively exhausted
  • roughly ten co-tenant stacks were already running, including zulip, mattermost and eight postgres instances

Containment already in place:

  • mem_limit: 8g on the coder container, so the control plane plus its in-process provisioner cannot exceed 8 GB
  • mem_limit: 2g on the coder-database container
  • postgres publishes no host port, so nothing outside the compose network can drive load into it

The rules, in order:

  • record free -m before bring-up and again after the first workspace build, so the real cost of one workspace is known rather than estimated
  • do not create additional workspaces if available memory drops below about 8 GB
  • workspace containers are siblings on the host daemon and are not covered by the compose mem_limit values, so give every template an explicit resource ceiling
  • if swap is already exhausted, stop and free memory elsewhere before building anything; a build that lands on an exhausted swap will thrash the co-tenant stacks, not just this one

📚 Sources