Files
werkator/docs/prs/2026-09-03-PR#19-werkdock-config-section.md
16543f038b the sandbox config section is werkdock, not bwrap (#19)
`bwrap` named the mechanism one layer below the tool that actually runs it: since
v1.0.0 Werkator does not invoke bwrap at all, it shells out to the werkdock CLI —
which made `bwrap.werkdock` a key naming its own executor.

The section is `werkdock` now and that key is `werkdock.binary`; BwrapConfig,
BwrapOverrides and BwrapBuildRunner follow the name. A file still writing `bwrap`
is read as before and warned about once per file, in `renameLegacySandbox` on the
raw map of every layer before merging — so nothing downstream knows two names, and
the old name is not a way around the pinning either. Renaming rather than refusing,
because the section lives in the machine configuration of every webspace instance,
which no repository tracks; the hard refusal belongs to the release that sets
ConfigVersions.FORMAT_BROKE_IN, where a file declaring no version can be caught
by name at all.

WERKATOR_SANDBOX in tools/remote follows, and still accepts `bwrap`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #19
2026-09-03 20:41:18 +02:00

6.5 KiB

WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.

The Problem

The build sandbox for hosts without Docker was configured as bwrap, named after the mechanism rather than after the thing Werkator runs. Since step 21 session C (v1.0.0) Werkator does not invoke bwrap at all: it shells out to the werkdock CLI, which assembles the bubblewrap invocation and owns the image store. The name outlived its truth, and the clearest symptom was the key bwrap.werkdock — a section naming its own executor.

It also leaked outward. tools/remote gained a WERKATOR_SANDBOX key in PR#18 whose value had to be bwrap while the very thing it switches on is uploading the werkdock binary, and the question that prompted this PR — "is there also WERKATOR_SANDBOX=werkdock?" — is one nobody would ask about a name that matched.

Non-Goals

  • Refusing the old name. That belongs to the release which sets ConfigVersions.FORMAT_BROKE_IN (plan step 18): only there can a file that declares no version be caught by name at all, and only there is one migration asked of the operator instead of two.
  • Renaming tools/build-bwrap-rootfs.sh or docs/plan/17-bwrap-build-runtime.md. The script really does build a bubblewrap rootfs, and plan documents are historic records.
  • Touching ADR 0008, which decided the runtime and is a snapshot of that decision.

The Scenarios

Feature: the sandbox is named after the tool that runs it

Background

  • builds.<name>.werkdock replaces builds.<name>.bwrap, and werkdock.binary replaces bwrap.werkdock.
  • The pinned set is unchanged in meaning: enabled, rootfs and the binary stay host-pinned, under their new names.

Scenario#19.01: A configuration written for the old name keeps working

So that no installation has to be edited before it can be updated — the section lives in machine configurations that no repository tracks.

  • Given a configuration writing builds.default.bwrap with enabled, rootfs, werkdock and env
  • When the configuration is loaded
  • Then the settings appear as werkdock.enabled, werkdock.rootfs, werkdock.binary and werkdock.env, and the file is named once in a warning
Verified by

Scenario#19.02: The old name is not a way around the pinning

So that a branch cannot escape its sandbox by writing the section a branch is not allowed to write under its previous name.

  • Given a host configuration with werkdock.enabled: true and a rootfs
  • When a branch's committed config sets bwrap.enabled: false with a foreign rootfs
  • Then the sandbox stays enabled and the host's rootfs is used
Verified by

Scenario#19.03: The new name behaves exactly as the old one did

So that the rename is a rename, not a change of behavior.

  • Given configurations using werkdock throughout
  • When builds are dispatched, pinned keys stripped, and both sandboxes enabled at once
  • Then the werkdock runner is selected, the branch cannot override the pinned keys, and enabling docker and werkdock together is rejected naming both
Verified by

The Solution

BwrapConfigWerkdockConfig (field werkdockbinary), BwrapOverridesWerkdockOverrides, BranchConfig.bwrap.werkdock, BwrapBuildRunnerWerkdockBuildRunner, and PINNED_BWRAP_KEYSPINNED_WERKDOCK_KEYS with binary in place of werkdock.

The compatibility lives in exactly one function, ConfigLoader.renameLegacySandbox, applied in loadFile and parseYaml — the two places a raw layer enters — so it runs before merging, before pinning and before binding, and every consumer downstream knows one name. That placement is what makes Scenario#19.02 hold without a second thought: the branch layer is normalised before stripPinned reads it, so the old name cannot smuggle a pinned key past a check that looks for the new one. Where a file writes both sections, the explicit werkdock one wins, because it is the name that is meant. The warning is emitted once per file (warnedSections), like the other section-level warnings, since the config is re-read on every poll cycle.

The version is bumped to 1.2.0 with a release note: the minor, because this changes the configuration schema, and a deployment must be identifiable as the one that introduced it.

Open Questions

  • Should WERKATOR_SANDBOX keep accepting bwrap? It does today, normalised on read and documented as the former name. The env files are local and gitignored, so this alias costs one line and can go whenever the config alias does.

Additional Changes

  • None beyond the rename and its documentation.

Deployment note

The order matters, and only in one direction: deploy v1.2.0 to a host before rewriting its init fragment (.env.<instance>.yml) to the new key names. A fragment carrying werkdock: applied by an older Werkator fails the fragment's strict schema validation — which is the safe outcome, but a failed repo-init nonetheless. The reverse never breaks: v1.2.0 reads every existing bwrap: fragment and machine config as before.

Prerequisite PRs

  • PR#18 introduced WERKATOR_SANDBOX, whose value this PR renames.

Follow-up PRs

  • Plan step 18 (removing the legacy branches section) sets ConfigVersions.FORMAT_BROKE_IN; the bwrap alias should be dropped in the same release, refusing the key by name.