fix(pkgs): one chromium, not two — and what that is actually worth
All checks were successful
Check / eval (push) Successful in 3m32s

BACKLOG #121. nixpkgs' chromium wrapper with enableWideVine = true (what the
template ships, for DRM) runs the `-wv` copy but links its share/* from the
PLAIN unwrapped build. A symlink is a store reference, so a second 687 MiB
chromium rode along for a directory of .desktop files nothing executes.
overlays.default now points those symlinks at the copy we already run; the
template needs no change, since lib.nix, the repo pkgs and nixosModules all
apply the overlay.

Checked first, because it decided whether the item was possible at all:
whether the `-wv` copy references the plain build. It is `cp -a` of it, so it
plausibly would have — and then no wrapper change could have dropped the
duplicate. It does not. Also verified rather than assumed: `.override
{ enableWideVine = true; }` composes with the overlay's overrideAttrs (the
order usually matters), so the template's existing line picks the fix up
untouched; the wrapper still execs the -wv build with WidevineCdm present; and
share/{applications,icons,man} match stock with the .desktop byte-identical.

I claimed this was "687 MiB off every install". It is not, and measuring the
artifact instead of the closure is what corrected it:

    nominal closure          -687 MiB  (9.38 -> 8.71 GiB)
    ISO image                -8 KiB    of 8.078 GiB
    installed disk           ~-19 MiB
    cache-install download   -195 MiB

Two dedupes that closure arithmetic cannot see. mksquashfs detects duplicate
files, so the ISO had already stored the near-identical blocks once. And
auto-optimise-store (on by default here) hardlinks identical files: the two
paths share inodes — verified by stat, and du counts 639 MiB for the pair
against ~620 for one. The only thing that cannot dedupe is the wire, where the
extra path is its own 195 MiB NAR.

So this is a DOWNLOAD fix — precisely what #120's netinstall cares about — and
close to a no-op for the offline ISO that is the default today. Whether that
justifies coupling an overlay to nixpkgs wrapper internals is Bernardo's call;
it is guarded and no-ops if upstream moves, but it is his to weigh. Worth an
upstream patch regardless: the wrapper should take its desktop entry from the
variant it wraps.

The guard is the load-bearing part, because the failure mode is a SILENT no-op
that no build complains about: checks.chromium-single-closure asserts exactly
one full unwrapped chromium in the template closure, and was proved to fail by
neutering the overlay — it reports "found 2", names both paths, and warns off
the tempting "fix" of dropping enableWideVine, which silently removes DRM.

The rule this establishes, now recorded in ROADMAP and on #120 (whose entire
size table is closure arithmetic): closure size is not disk size and is not
image size. Measure the artifact.

V2: flake check, chromium-single-closure, live-baseline-apps, template-sot,
option-docs, state-bridges all pass. Three ISOs built from one tree for the
numbers above.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 17:26:24 +01:00
parent 00b1e10fc3
commit 0b464af3e5
4 changed files with 194 additions and 34 deletions

View File

@@ -404,6 +404,59 @@ Design/decision records and a running log of shipped work (items marked
decision rather than a drive-by. Proved to fail: dropping snapshot makes it
name the missing entry. **V3 pending** — that the apps *launch* needs real
hardware (HARDWARE-QUEUE, Acer M5-481T).
- ✓ **One chromium, not two (#121):** found by measuring #103's ISO delta
rather than by anything failing — nothing *was* failing, which is the point.
nixpkgs' chromium wrapper, with `enableWideVine = true` (what the template
ships, for Netflix/Spotify DRM), runs the `-wv` copy but links its
`share/*` from the **plain** unwrapped build:
`for f in '${chromium.browser}'/share/*; do ln -s …`. A symlink is a store
reference, so a whole second **687 MiB** chromium rode along for a directory
of `.desktop` files nothing executes — on **every installed machine**, not
just the ISO, for as long as chromium has been the default browser.
**What made a fix possible** (checked first, since it decides everything):
the `-wv` copy is `cp -a` of the browser and is **self-contained** — it does
*not* reference the plain build. Had it done so, no wrapper change could
drop the duplicate. Its `share/` is byte-identical, `.desktop` included, so
`overlays.default` moves the symlink source to the copy we already run.
Both paths are read back out of the wrapper's own `buildCommand`, so the
overlay knows nothing of nixpkgs internals beyond two strings; if upstream
restructures either, the match returns null and the fix **no-ops** rather
than breaking a build. With `enableWideVine = false` the paths are equal and
the substitution is identity. DRM payload verified still present in the build
the wrapper execs; `share/` byte-identical to stock.
**What it actually saves — and the lesson, which is worth more than the fix**
(the first pass at this claimed "687 MiB on every install"; measuring the
*artifact* instead of the closure killed that):
| Metric | Saving |
|---|---|
| Nominal closure (`nix path-info -S`) | 687 MiB (9.38 → 8.71 GiB) |
| **ISO image** | **~0 — 8 KiB of 8.078 GiB** |
| **Installed disk** | **~19 MiB** |
| **Download, cache-based install** | **195 MiB** |
The duplicate was nearly free everywhere it was already stored, because two
mechanisms dedupe it and closure arithmetic sees neither: **mksquashfs
detects duplicate files**, so the ISO had stored those blocks once (the `-wv`
copy is `cp -a` of the plain build — near-identical by construction); and
**`nix.settings.auto-optimise-store` is on** (`modules/nixos/default.nix`),
which hardlinks identical files, so the pair costs 639 MiB of disk against
~620 MiB for one — verified by inode, not inferred. The one place dedup
cannot help is the wire: a binary-cache install fetches the extra path as its
own NAR, **195 MiB compressed** (`cache.nixos.org` `downloadSize`). So this
is a *download* fix, which is exactly what #120's netinstall cares about, and
a no-op for the offline ISO that is the default today.
**Rule this establishes: closure size is not disk size and is not image size.
Measure the artifact.** #120's size table is closure arithmetic and inherits
this caveat.
**The guard is load-bearing**, because a silent no-op is this fix's failure
mode and nothing about it breaks a build: `checks.chromium-single-closure`
asserts the *invariant* (exactly one full unwrapped chromium in the template
closure — plain or `-wv`, never both), not the mechanism, and was proved to
fail by neutering the overlay: it reports "found 2", names both paths, and
says not to "fix" it by dropping `enableWideVine`, which would silently
remove DRM. Worth an upstream nixpkgs patch (the wrapper should take its
desktop entry from the variant it wraps); the overlay is the local stopgap.
- ✓ **Plymouth logo contrast:** the shipped art was a fixed navy that
vanished on dark bases. `modules/nixos/plymouth.nix` now recolors every
element from the palette at build time (flat fill, alpha kept):