Skip to content

docs(adr): propose CPU, memory and PID limits for the edge container (ADR-022, proposed) - #44

Draft
knittingcode wants to merge 1 commit into
mainfrom
docs/fcrm-adr021-edge-resource-limits
Draft

knittingcode wants to merge 1 commit into
mainfrom
docs/fcrm-adr021-edge-resource-limits

Conversation

@knittingcode

Copy link
Copy Markdown
Owner

Summary

Documentation only. Adds ADR-022 (status: proposed, not implemented, not activated), which proposes CPU, memory and PID limits for the edge container as defence in depth for the availability risk accepted in ADR-021. It also records the missing limits as a deferred hardening item in docs/security/container-vulnerabilities.md.

Motivation and context

ADR-021 (accepted 2026-10-28) states a residual availability risk: if a configuration enabled acme_server or a mutable admin API, a remote client could exhaust the edge's CPU (about 2.2 s CPU per crafted request in the runtime check), and "the edge has no CPU or memory limits, so the API and database on the same host could suffer too". No Compose file on main (1badf76) sets cpus, mem_limit, pids_limit, deploy.resources or ulimits for any service. The security document's lists did not mention this.

The proposal is a separate ADR rather than a new section in ADR-021. That way the accepted ADR-021 text stays unchanged, and the limits remain their own decision, which the owner can accept or reject without touching the exception.

Content

docs/architecture/adr/ADR-022-edge-resource-limits.md:

  • Proposed keys on the edge service in compose.yaml only (inherited by the prod-like, test and HTTPS test overrides): cpus: "1.0", mem_limit: 256m, pids_limit: 256.
  • Rationale, with a table of what has been measured and what has not. Edge usage has not been measured anywhere in the repository, so the values are conservative ceilings: one core bounds the ADR-021 worst case, and the 1 CPU / 512 MB small-instance budget from the FND-010V api benchmark serves as a precedent. Caddy 2.11.7 derives GOMAXPROCS (automaxprocs) and a soft GOMEMLIMIT of 0.9 x the cgroup limit (automemlimit 1.0.0) from the limits. I checked this against cmd/main.go in the module cache.
  • Values must be literals, because the edge guard rejects ${VAR} interpolation outside ports, volume sources and secret files.
  • Alternatives: deploy.resources.limits, memswap_limit, limits on other services, Caddy timeouts and body limits (out of scope), or no limits.
  • Verification an activating change must provide: measure first with docker stats during stack.sh and prodlike.sh, with mem_limit at least 4 x the peak; guard and config --quiet checks stay green; a new hardening_problems assertion on NanoCpus, Memory and PidsLimit with a negative control; no healthcheck or timing regression; the gate stays fail-closed across the edge recreate.
  • Risks: OOM kill (GOMEMLIMIT is soft), configuration reload (not possible today because admin off is set and --watch/--resume are rejected; a future reload would need re-measured headroom), slower tests, not a DoS fix, platform differences.
  • Activation needs an owner decision and a separate PR.

docs/security/container-vulnerabilities.md: one bullet under "Deferred hardening items" that states the current state (no limits) and links to ADR-022.

What is NOT changed

  • No Compose file, script, Dockerfile, Caddyfile, guard or workflow.
  • ADR-021 is unchanged: its decision, acceptance, consequences and review triggers. The ADR-021 sentence "The edge has no CPU or memory limits" stays, because it is still true.
  • security/trivyignore.yaml is unchanged: same entry, scope and expiry (2026-11-30). This PR does not broaden, extend or renew the exception.
  • ADR-020 is not touched.

Testing performed

  • scripts/ci/guard-trivyignore.sh: OK (1 exception follows the policy, checked on 2026-10-29).
  • scripts/ci/guard-tracked-files.sh: OK.
  • No Docker, tests/app/*.sh, bin/devenv or integration tests were run. Nothing in the PR is executable.

Security considerations

None of this is active. The residual risk stated in ADR-021 is unchanged until an activating change is merged.

Owner decisions needed

  1. Accept, amend or reject ADR-022 (the values, service-level keys vs deploy.resources.limits, and whether to set memswap_limit).
  2. If it is accepted, authorise a separate implementation PR with the measurements and the runtime assertion. A Compose change is an ADR-021 review trigger, so that PR also needs the edge review.
  3. Whether the deferred-item bullet in the security document is wanted in this form.

Known limitations

The proposed values are not based on measured edge usage. The ADR makes measurement a precondition for activation.

Add ADR-022 with status proposed: service-level cpus, mem_limit and
pids_limit for the edge in compose.yaml as defence in depth for the
availability risk accepted in ADR-021. The values are conservative
ceilings because edge usage has not been measured; the ADR lists the
measurement, guard, Compose and runtime checks an activating change must
pass, and the risks (OOM kill, reload headroom, slower tests).

Record the missing resource limits as a deferred hardening item in the
container vulnerabilities document. No Compose or executable file
changes; ADR-021 and the trivyignore exception are unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant