Skip to content

security(docker): run Go services without root with safe volume-permission migration #339

Open

Description

@dborup

Context

Identified by a static comparison on 2026-10-07 against dborup/CoreScope master 6444294d938083f6d935d0445c27bc6a7bbf360e. This is follow-up work for evaluation and implementation, not a claim of an observed production incident. Recheck current master before implementation. No deployment is authorized by this issue alone.

Upstream reference: Kpa-clawbot fork, PR 2125 (reference only; intentionally not linked to avoid upstream notifications)

Benefit and existing coverage

The current Go Supervisor configurations run under root without per-service user overrides. Dropping privileges limits the impact of a compromised service. This observation concerns repository container definitions, not a verification of the currently deployed processes.

Required work / acceptance criteria

  • Run corescope-server and corescope-ingestor as non-root in all supported Go container variants.
  • Define UID/GID behavior for existing bind mounts, named volumes and configured host IDs.
  • Test new and existing root-owned databases, WAL/SHM files, config, logs and required writable paths.
  • Avoid unnecessary recursive ownership changes and broad writable application directories; document startup cost and host-volume side effects.
  • Preserve Mosquitto/Caddy behavior, including our existing broker PUID/PGID handling.
  • Test read-only config mounts and geo-filter save behavior, with clear failures for unsupported arrangements.
  • Provide migration and rollback instructions; retain backups and do not modify production permissions during development.

Upstream's entrypoint is a reference, not a drop-in migration plan.

Activity

  1. dborup commented on Oct 13, 2026

    @dborup
    OwnerAuthor

    Opt-in non-root mode merged in #404. It is off by default, so existing installs are unchanged. This issue stays open until the staging rehearsal (checklist in #404) is done and the owner decides about production.

  2. added a commit that references this issue on Oct 13, 2026
  3. dborup commented on Oct 14, 2026

    @dborup
    OwnerAuthor

    Staging rehearsal (v0.2.4-rc2, 2026-10-14): non-root mode ran for about 2 h on real data with UID/GID 10001. Server and ingestor ran as the dedicated user, ingest was normal, and there were 0 permission/readonly/SQLITE_BUSY errors and write_errors=0. A second restart reported ownership: 0 of 4. The rollback drill passed: with the mode off, everything ran as root immediately; restore-owners restored the recorded owners and modes exactly and removed .corescope-nonroot; the next start was clean. Still to test: the geo-filter save returning 409 in on-mode (needs the admin key). The production decision is pending.

  4. dborup commented on Oct 14, 2026

    @dborup
    OwnerAuthor

    Geo-filter check done on staging (2026-10-14): with non-root mode on, "Save to server" in the customizer showed "geo filter not saved: config.json is read-only for the server (read-only mount, or CORESCOPE_RUN_AS_NONROOT is on)…". The server logged [geofilter] save failed: … CORESCOPE_RUN_AS_NONROOT is on, and config.json was unchanged (mtime not touched). A second rollback with restore-owners was clean again. Every item on the #404 staging checklist has now passed; the production decision is pending.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions