Ship an example settings policy, and name the variables in .env.example #232

Closed
opened 2026-09-02 18:20:47 +00:00 by jcoffey-dev · 0 comments
Owner

#231 added the settings policy but nothing to copy. The repo already answers this the same way four times over — Caddyfile.example, deploy.example.sh, nginx.example.conf, .env.example — and the new feature was the one configurable thing here with no example beside it.

What's added

settings-policy.example.json at the repo root, with all three sections and the reasoning in the file. Including the part worth being deliberate about: a changes entry overrides a decision a reader has already made, and if you want it to stay put regardless, that is enforced instead.

JSON has no comments, so the commentary is in _-prefixed keys. That is safe because the server reads three names and ignores everything else — and there is a test asserting no comment key ever collides with a real section.

.env.example gains the four variables, commented out, with both forms and the note that the file wins over the inline ones.

A test guarding the example. It checks the shipped file against the rules the parser enforces: unique versions, settings objects, valid JSON, no stray top-level keys. An example that has drifted out of step is worse than no example — somebody copies it, the server refuses to start, and the first experience of the feature is a crash loop.

Immutability, confirmed rather than reasoned about

The question came up, so I ran it against the real image on the deploy host. An immutable container — --read-only --tmpfs /tmp -e IMMUTABLE=1 -e SESSION_FILE= — starts and serves the policy correctly in both forms:

  • with a read-only file mount (-v policy.json:/etc/ihasmail/policy.json:ro), and
  • with the environment variables alone and no mount at all.

The feature costs nothing in immutability. assertImmutable checks two things — SESSION_FILE empty and the install root not writable — and a read-only mount elsewhere touches neither. The only thing this feature writes is the applied-changes stamp, and that goes into the reader's own settings file on Stalwart, like every other setting.

One caveat that predates this and is unchanged by it: assertImmutable probes the install root only, so a policy file mounted read-write somewhere else would not trip it. Nothing previously gave a reason to mount anything; now something does, which is why both the README and the docs say :ro.

npm test (977 web + 126 server — four of those new), npm run build pass.

Merged 2026-09-02 as coffey-labs/ihasmail@0d5975d427

Rebuilt from: git history, session transcript.

#231 added the settings policy but nothing to copy. The repo already answers this the same way four times over — `Caddyfile.example`, `deploy.example.sh`, `nginx.example.conf`, `.env.example` — and the new feature was the one configurable thing here with no example beside it. ## What's added **`settings-policy.example.json`** at the repo root, with all three sections and the reasoning in the file. Including the part worth being deliberate about: a `changes` entry overrides a decision a reader has already made, and if you want it to stay put regardless, that is `enforced` instead. JSON has no comments, so the commentary is in `_`-prefixed keys. That is safe because the server reads three names and ignores everything else — and there is a test asserting no comment key ever collides with a real section. **`.env.example`** gains the four variables, commented out, with both forms and the note that the file wins over the inline ones. **A test guarding the example.** It checks the shipped file against the rules the parser enforces: unique versions, `settings` objects, valid JSON, no stray top-level keys. An example that has drifted out of step is worse than no example — somebody copies it, the server refuses to start, and the first experience of the feature is a crash loop. ## Immutability, confirmed rather than reasoned about The question came up, so I ran it against the real image on the deploy host. An immutable container — `--read-only --tmpfs /tmp -e IMMUTABLE=1 -e SESSION_FILE=` — starts and serves the policy correctly in **both** forms: - with a read-only file mount (`-v policy.json:/etc/ihasmail/policy.json:ro`), and - with the environment variables alone and no mount at all. The feature costs nothing in immutability. `assertImmutable` checks two things — `SESSION_FILE` empty and the install root not writable — and a read-only mount elsewhere touches neither. The only thing this feature writes is the applied-changes stamp, and that goes into the reader's own settings file on Stalwart, like every other setting. One caveat that predates this and is unchanged by it: `assertImmutable` probes the install root only, so a policy file mounted read-*write* somewhere else would not trip it. Nothing previously gave a reason to mount anything; now something does, which is why both the README and the docs say `:ro`. `npm test` (977 web + 126 server — four of those new), `npm run build` pass. **Merged** 2026-09-02 as coffey-labs/ihasmail@0d5975d42756 <sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.