max / alloy
13 files changed,
+348 insertions,
-120 deletions
| @@ -582,12 +582,17 @@ | |||
| 582 | 582 | # make, which is why these two are ARGs and the theme, terminal, editor | |
| 583 | 583 | # and shell are not. | |
| 584 | 584 | # | |
| 585 | - | # BROWSER is the case docs/STACK.md already names a non-endorsement: | |
| 586 | - | # Alloy argues for helix over vim, and cannot make the equivalent | |
| 587 | - | # argument between Blink and Gecko. `none` is a real answer, not an | |
| 588 | - | # error — someone installing their own from Flathub should not pay for | |
| 589 | - | # one they will remove. | |
| 590 | - | ARG BROWSER=helium | |
| 585 | + | # BROWSER is not the non-endorsement it was until 2026-08-18. Alloy | |
| 586 | + | # picks Firefox and defends it (wiki `alloy-byo-principle`), so this ARG | |
| 587 | + | # is no longer "the choice Alloy declines to make" — it survives because | |
| 588 | + | # `none` is a real answer, not an error: someone installing their own | |
| 589 | + | # from Flathub should not pay for one they will remove. | |
| 590 | + | # | |
| 591 | + | # Alloy still makes no claim that Gecko is the better engine. The claim | |
| 592 | + | # is about the candidate. Firefox is the only browser reachable on an | |
| 593 | + | # image-based system whose defaults Alloy can stand behind, and standing | |
| 594 | + | # behind them costs one file: /etc/firefox/pref/alloy.js. | |
| 595 | + | ARG BROWSER=firefox | |
| 591 | 596 | ||
| 592 | 597 | # LANGS is asked for by name in the rust comment further down: 610 MiB | |
| 593 | 598 | # across 16 packages, "per-image language selection at mint time is the | |
| @@ -692,8 +697,9 @@ | |||
| 692 | 697 | *) echo "unknown PROFILE '$PROFILE'; expected 'client' or 'server'" >&2; exit 1 ;; \ | |
| 693 | 698 | esac; \ | |
| 694 | 699 | case "$BROWSER" in \ | |
| 695 | - | helium|firefox|none) ;; \ | |
| 696 | - | *) echo "unknown BROWSER '$BROWSER'; expected 'helium', 'firefox' or 'none'" >&2; exit 1 ;; \ | |
| 700 | + | firefox|none) ;; \ | |
| 701 | + | helium) echo "BROWSER=helium was removed 2026-08-18: Alloy does not ship a third party's patchset over Chromium's defaults. Use 'firefox' or 'none'." >&2; exit 1 ;; \ | |
| 702 | + | *) echo "unknown BROWSER '$BROWSER'; expected 'firefox' or 'none'" >&2; exit 1 ;; \ | |
| 697 | 703 | esac; \ | |
| 698 | 704 | for lang in $(echo "$LANGS" | tr ',' ' '); do \ | |
| 699 | 705 | case "$lang" in \ | |
| @@ -1313,17 +1319,31 @@ | |||
| 1313 | 1319 | # one thing here a user chooses and a rebuild that changes only the | |
| 1314 | 1320 | # browser should not re-resolve the whole stack. | |
| 1315 | 1321 | # | |
| 1316 | - | # Helium is ungoogled-chromium with the defaults Alloy used to hand-build | |
| 1317 | - | # in fifty Firefox prefs and a policy file, so it ships with no | |
| 1318 | - | # configuration at all: no policy, no pref seed, no chrome CSS. That is | |
| 1319 | - | # the whole reason it is the default. Terra packages it; upstream ships | |
| 1320 | - | # no Flatpak, and the unofficial repackagings are worse provenance than | |
| 1321 | - | # this for the most attack-exposed program on the box. | |
| 1322 | + | # Firefox, picked and defended as of 2026-08-18. Wiki | |
| 1323 | + | # `alloy-byo-principle`, "The browser stops being BYO". | |
| 1322 | 1324 | # | |
| 1323 | - | # Firefox is the Gecko alternative. docs/STACK.md records the browser- | |
| 1324 | - | # engine monoculture argument as overridden rather than withdrawn, and | |
| 1325 | - | # this is the line that makes the alternative real rather than | |
| 1326 | - | # theoretical. | |
| 1325 | + | # It is from Fedora's own repos, which is not incidental: they stay | |
| 1326 | + | # enabled after install, so this is a browser a user can also reach on a | |
| 1327 | + | # machine that chose `none`. That property is now a selection criterion | |
| 1328 | + | # for anything Alloy recommends, and it is what ended the previous | |
| 1329 | + | # ruling. | |
| 1330 | + | # | |
| 1331 | + | # WHAT WAS HERE UNTIL TODAY, and why it is gone. Helium is | |
| 1332 | + | # ungoogled-chromium with the defaults Alloy used to hand-build in fifty | |
| 1333 | + | # Firefox prefs, packaged by Terra as `helium-browser-bin`. It was the | |
| 1334 | + | # default precisely because it needed no configuration. Two things ended | |
| 1335 | + | # it. Terra is disabled post-install (see the repo cleanup layer), so | |
| 1336 | + | # Helium was unreachable on any machine that did not bake it in. And it | |
| 1337 | + | # is a maintained patchset over another vendor's bad defaults, which is | |
| 1338 | + | # not a thing Alloy ships: Helium is doing its best to make a standard | |
| 1339 | + | # approach tolerable, and Alloy is doing its best to improve standard | |
| 1340 | + | # approaches. Anyone who wants it can enable Terra on their own machine | |
| 1341 | + | # and layer it, which is their call and not a shape this image carries. | |
| 1342 | + | # | |
| 1343 | + | # The cost of picking Firefox is that stock Firefox has bad defaults by | |
| 1344 | + | # Alloy's own test, so the pick is paid for in /etc/firefox/pref/alloy.js | |
| 1345 | + | # — anti-features removed, one hidden control restored, nothing about | |
| 1346 | + | # appearance. It arrives with `COPY etc/ /etc/` and is asserted below. | |
| 1327 | 1347 | # | |
| 1328 | 1348 | # The assertion runs on every path including `none`, and that is the | |
| 1329 | 1349 | # point: it proves exactly one browser is installed, or that none is, so | |
| @@ -1332,7 +1352,6 @@ | |||
| 1332 | 1352 | RUN set -eu; \ | |
| 1333 | 1353 | if [ "$PROFILE" = client ]; then \ | |
| 1334 | 1354 | case "$BROWSER" in \ | |
| 1335 | - | helium) dnf install -y helium-browser-bin && dnf clean all ;; \ | |
| 1336 | 1355 | firefox) dnf install -y firefox && dnf clean all ;; \ | |
| 1337 | 1356 | none) echo "no browser in this image, by choice" ;; \ | |
| 1338 | 1357 | esac; \ | |
| @@ -1340,16 +1359,13 @@ | |||
| 1340 | 1359 | echo "no browser: this profile has no session to run one in"; \ | |
| 1341 | 1360 | fi; \ | |
| 1342 | 1361 | installed=""; \ | |
| 1343 | - | for candidate in helium-browser-bin firefox; do \ | |
| 1362 | + | for candidate in firefox helium-browser-bin; do \ | |
| 1344 | 1363 | rpm -q "$candidate" >/dev/null 2>&1 && installed="$installed $candidate"; \ | |
| 1345 | 1364 | done; \ | |
| 1346 | 1365 | installed="$(echo $installed)"; \ | |
| 1347 | 1366 | expected=""; \ | |
| 1348 | 1367 | if [ "$PROFILE" = client ] && [ "$BROWSER" != none ]; then \ | |
| 1349 | - | case "$BROWSER" in \ | |
| 1350 | - | helium) expected="helium-browser-bin" ;; \ | |
| 1351 | - | firefox) expected="firefox" ;; \ | |
| 1352 | - | esac; \ | |
| 1368 | + | expected="firefox"; \ | |
| 1353 | 1369 | fi; \ | |
| 1354 | 1370 | [ "$installed" = "$expected" ] \ | |
| 1355 | 1371 | || { echo "browser mismatch: asked for '${expected:-none}', image has '${installed:-none}'" >&2; exit 1; }; \ | |
| @@ -1702,6 +1718,57 @@ | |||
| 1702 | 1718 | COPY usr/ /usr/ | |
| 1703 | 1719 | COPY --from=rust-build /staged-skel/ / | |
| 1704 | 1720 | ||
| 1721 | + | # ===================================================================== | |
| 1722 | + | # The Firefox configuration is what pays for picking Firefox. | |
| 1723 | + | # ===================================================================== | |
| 1724 | + | # Alloy picks a browser and defends it (wiki `alloy-byo-principle`), and a | |
| 1725 | + | # default has to earn that under rule 3 of `alloy-packaging-policy`. Stock | |
| 1726 | + | # Firefox does not earn it: telemetry, sponsored placements and tracking | |
| 1727 | + | # protection at "standard" all serve someone other than the person running | |
| 1728 | + | # it. /etc/firefox/pref/alloy.js is the payment, and without it this image | |
| 1729 | + | # ships the exact thing docs/STACK.md calls indefensible. | |
| 1730 | + | # | |
| 1731 | + | # Fedora's firefox rpm owns /etc/firefox/pref and /etc is writable on a bootc | |
| 1732 | + | # deployment, so this is one file and no write to /usr. | |
| 1733 | + | # | |
| 1734 | + | # THE THIRD CHECK IS THE INTERESTING ONE. The guard on that file is that it | |
| 1735 | + | # only removes anti-features and restores hidden controls, never sets Alloy's | |
| 1736 | + | # taste. `browser.uidensity` is the named example of the taste it may not | |
| 1737 | + | # set, and `browser.compactmode.show` is the honest version of the same | |
| 1738 | + | # want: put the control back and let the user choose. A guard nobody can | |
| 1739 | + | # enforce is a comment, so it is asserted here instead. If this fails, read | |
| 1740 | + | # the ladder in the wiki note before deleting the check. | |
| 1741 | + | RUN set -eu; \ | |
| 1742 | + | conf=/etc/firefox/pref/alloy.js; \ | |
| 1743 | + | if [ "$PROFILE" = client ]; then \ | |
| 1744 | + | if [ "$BROWSER" = firefox ]; then \ | |
| 1745 | + | test -f "$conf" \ | |
| 1746 | + | || { echo "browser=firefox and $conf is not in the image; the pick is unpaid for and this image ships stock Firefox" >&2; exit 1; }; \ | |
| 1747 | + | grep -q '^pref("browser.ml.enable", false);' "$conf" \ | |
| 1748 | + | || { echo "$conf no longer turns off browser.ml.enable; the AI block was the substantive half of this file" >&2; exit 1; }; \ | |
| 1749 | + | grep -q '^pref("browser.compactmode.show", true);' "$conf" \ | |
| 1750 | + | || { echo "$conf no longer restores the density control; rung 1 of the ladder is the cheapest thing this file does" >&2; exit 1; }; \ | |
| 1751 | + | echo "firefox: $(grep -c '^pref(' "$conf") prefs, anti-features and one restored control"; \ | |
| 1752 | + | else \ | |
| 1753 | + | rpm -q firefox >/dev/null 2>&1 \ | |
| 1754 | + | && { echo "browser=none and firefox is installed anyway; something pulled in a browser nobody chose" >&2; exit 1; }; \ | |
| 1755 | + | echo "firefox: not in this image, by choice; the config file rides along inert"; \ | |
| 1756 | + | fi; \ | |
| 1757 | + | else \ | |
| 1758 | + | rpm -q firefox >/dev/null 2>&1 \ | |
| 1759 | + | && { echo "profile=server carries firefox; the profile split leaked a browser onto an image with no session to run one in" >&2; exit 1; }; \ | |
| 1760 | + | echo "firefox: correctly absent on a profile with no session"; \ | |
| 1761 | + | fi; \ | |
| 1762 | + | if [ -f "$conf" ]; then \ | |
| 1763 | + | if grep -q '^pref("browser.uidensity"' "$conf"; then \ | |
| 1764 | + | echo "$conf sets browser.uidensity; that is rung 3, Alloy's taste in an app it configures only to remove anti-features. Restore the control, do not pick the value." >&2; exit 1; \ | |
| 1765 | + | fi; \ | |
| 1766 | + | if grep -qE '^[[:space:]]*(lockPref|defaultPref)\(' "$conf"; then \ | |
| 1767 | + | echo "$conf locks a pref; every line in it is meant to be a starting position the user can change, and a lock is Alloy hiding a control while objecting to hidden controls" >&2; exit 1; \ | |
| 1768 | + | fi; \ | |
| 1769 | + | echo "firefox config: no taste, no locks"; \ | |
| 1770 | + | fi | |
| 1771 | + | ||
| 1705 | 1772 | # ===================================================================== | |
| 1706 | 1773 | # The cursor theme skel names has to be the one the prune kept. | |
| 1707 | 1774 | # ===================================================================== |
| @@ -32,11 +32,11 @@ | |||
| 32 | 32 | ||
| 33 | 33 | ### The categories, from what the image ships | |
| 34 | 34 | ||
| 35 | - | Counted 2026-08-06 against the built image rather than invented: `/usr/share/applications` holds 17 desktop entries, of which 7 are not `NoDisplay`. That is the whole visible surface Alloy itself installs. | |
| 35 | + | Counted 2026-08-06 against the built image rather than invented (the browser row is Firefox since 2026-08-18; it was Helium when this was counted, and the entry count is unchanged either way): `/usr/share/applications` holds 17 desktop entries, of which 7 are not `NoDisplay`. That is the whole visible surface Alloy itself installs. | |
| 36 | 36 | ||
| 37 | 37 | | Category | What ships in it | XDG category a third-party app would declare | | |
| 38 | 38 | |---|---|---| | |
| 39 | - | | Browser | helium | `WebBrowser` | | |
| 39 | + | | Browser | firefox | `WebBrowser` | | |
| 40 | 40 | | Console | shop (no desktop entry; it is the terminal) | `TerminalEmulator` | | |
| 41 | 41 | | Editor | helix | `TextEditor` | | |
| 42 | 42 | | File manager | yazi | `FileManager` | |
| @@ -108,7 +108,7 @@ | |||
| 108 | 108 | ||
| 109 | 109 | **A package added here gets a line in `crates/alloy/credits.toml`.** The installer's last screen names the projects Alloy ships and their licenses, off a hand-curated manifest rather than a generated closure, so nothing adds itself. The manifest is embedded in the console binary with `include_str!`, which means the page cannot go missing on installer media or a read-only deployment and also means a manifest edit needs a rebuild. Its own header says which license to record: for anything packaged out of Rust or Go, Fedora's `%{LICENSE}` is the whole vendored closure rather than the project's own terms, so read upstream's LICENSE for those and use `rpm -q --qf '%{LICENSE}'` only for the C packages. | |
| 110 | 110 | ||
| 111 | - | The browser ships as an RPM baked into the image: one code path, no first-boot delay, and no first-run network dependency. Alloy ships no configuration for it at all, which is why it is the browser Alloy ships (see [STACK.md](STACK.md#browser)). The `flatpak` client is included so users can pull Flathub-only apps on demand post-install; no Flatpaks are provisioned at build or first-boot time. | |
| 111 | + | The browser ships as an RPM baked into the image: one code path, no first-boot delay, and no first-run network dependency. It is Firefox, from Fedora's own repos, and it carries exactly one file of Alloy configuration (`/etc/firefox/pref/alloy.js`, anti-features removed and one hidden control restored; see [STACK.md](STACK.md#browser)). The `flatpak` client is included so users can pull Flathub-only apps on demand post-install; no Flatpaks are provisioned at build or first-boot time. | |
| 112 | 112 | ||
| 113 | 113 | ## Size | |
| 114 | 114 | ||
| @@ -120,6 +120,12 @@ | |||
| 120 | 120 | The default became `LANGS=rust` later the same day, which takes the language layer down | |
| 121 | 121 | with it; the numbers are left as measured rather than adjusted on paper. | |
| 122 | 122 | ||
| 123 | + | The same applies to the browser, and more sharply. `BROWSER=helium` was removed on | |
| 124 | + | 2026-08-18 and Firefox is the only answer now, so the browser layer below is a | |
| 125 | + | measurement of a build this tree can no longer produce. It is left as measured for the | |
| 126 | + | same reason: an adjusted number is a guess wearing a measurement's clothes. Re-measure | |
| 127 | + | the browser layer on the next full build. | |
| 128 | + | ||
| 123 | 129 | Two sizes, and they answer different questions. **Image size** is the sum of the layers: | |
| 124 | 130 | what a registry stores and what `bootc upgrade` moves. **Deployed size** is the final | |
| 125 | 131 | filesystem: what the disk holds and what the ISO squashes. A file written in one layer | |
| @@ -133,7 +139,7 @@ | |||
| 133 | 139 | |------|-------|---------------------| | |
| 134 | 140 | | 1.44 GB | sway, `xdg-desktop-portal{,-gtk,-wlr}`, the session | The product. This is the desktop. | | |
| 135 | 141 | | 778 MB | `LANGS=rust,go` | As measured. Go is 230 MB of this layer, and 356 MB by exclusive closure once the packages only it pulls in are counted; that gap is the two questions the measurements answer, not a disagreement. Go left the default on 2026-08-17, so a stock image builds this layer at `LANGS=rust`. Argued at `ARG LANGS`. | | |
| 136 | - | | 674 MB | `helium-browser-bin` | The product, and the one stack pick Alloy declines to make. | | |
| 142 | + | | 674 MB | `helium-browser-bin` | The product. Superseded: this is Helium, removed 2026-08-18, and Firefox's layer is unmeasured. | | |
| 137 | 143 | | 663 MB | Base package list | The stack, per [STACK.md](STACK.md). | | |
| 138 | 144 | | 170 MB | initramfs + `rpmostree-unpackaged-content` | Bootable image. | | |
| 139 | 145 | | 147 MB | cups + cups-filters | Printing, client profile only; the server profile presets it off. | |
| @@ -188,36 +188,50 @@ | |||
| 188 | 188 | ||
| 189 | 189 | ## Browser | |
| 190 | 190 | ||
| 191 | - | **Helium baked into the image as the default, unconfigured.** Helium is ungoogled-chromium with the behavior Alloy used to hand-build on top of Firefox already set upstream: ads, trackers, cookie banners and third-party cookies blocked by default, fingerprinting tampered with, no analytics, and no network request at all on first launch. Alloy ships no policy file, no preference seed, no chrome CSS and no extension pin for it. Shipping nothing is the reason it is the default, not an omission next to it. The packaging rules this follows are in the wiki note `alloy-packaging-policy`; the short form is that an app earns a recommendation by not needing configuration, which is the same test that picked helix over a configured vim. | |
| 191 | + | **Firefox baked into the image as the default, with one file of configuration.** Ruled 2026-08-18. Firefox is a pick Alloy defends, not a shrug: it is the only browser reachable on an image-based system whose defaults Alloy can stand behind, and standing behind them costs `/etc/firefox/pref/alloy.js` and nothing else. No policy file, no autoconfig, no `profiles.ini`, no `userChrome.css`. The wiki note is `alloy-byo-principle`. | |
| 192 | 192 | ||
| 193 | - | The package is `helium-browser-bin` from Terra, the repo Alloy already enables for satty, currently 0.14.9.1. Helium's own code is GPL-3.0; what it imports from ungoogled-chromium keeps its BSD-3-Clause terms. Nothing in Alloy links either, so this sits on the same aggregation footing as Distrobox, greetd and tuigreet, which are GPL-3.0-only in the image already. | |
| 193 | + | Reachability is the load-bearing word. Firefox comes from Fedora's own repos, and those stay enabled after install, so a machine that chose `BROWSER=none` is one `rpm-ostree install firefox` from the browser the image would have carried. That property is now a selection criterion for anything Alloy recommends: **a candidate needs support for image-based systems, stated or inherent.** | |
| 194 | 194 | ||
| 195 | - | **What Alloy used to ship here, and no longer does.** Five files went with this change: an enterprise policy pinning uBlock Origin and disabling telemetry, Pocket, studies, sponsored tiles and password saving; a `mozilla.cfg` of around fifty default prefs; the autoconfig pointer that loaded it; a `profiles.ini` naming a fixed-path profile; and roughly two hundred lines of `userChrome.css`. That CSS described its own purpose in its header as "Helium-style ultra-compact horizontal". It was emulating a browser that is packaged, so the emulation had no reason to exist. The fifty prefs were not only cosmetic, and dropping them on a browser with bad defaults would be indefensible. It was affordable while Helium was the only recommendation, because Helium already behaves that way. | |
| 195 | + | ### What the configuration does, and what it may never do | |
| 196 | 196 | ||
| 197 | - | **Ruled 2026-08-17: the two recommended browsers are stock Firefox and Helium**, and stock Firefox does not behave that way. It arrives with telemetry on, sponsored shortcuts on the new tab page, Pocket integration, and Enhanced Tracking Protection at "standard" rather than "strict", which is most of what the deleted `mozilla.cfg` was setting. Alloy still ships it no configuration, and the estate does not come back. | |
| 197 | + | Three rungs, in order, and a lower one needs an argument for why the one above it did not work: | |
| 198 | 198 | ||
| 199 | - | What changes is that honest description stops being a courtesy and becomes the obligation. Whatever offers the choice states what each browser does out of the box, so a user picking Gecko knows what they are picking rather than discovering it. | |
| 199 | + | 1. **Restore a control the vendor hid.** `browser.compactmode.show` ships false, which hides the density control in Customize. Alloy sets it true and stops there. The user is one visible click from compact and Alloy has not said which density is right. | |
| 200 | + | 2. **Remove an anti-feature.** The test is who the default serves. Telemetry serves the vendor, sponsored placements serve advertisers, tracking protection at "standard" serves the ad industry, and the AI block (`browser.ml.*`, `browser.tabs.groups.smart.*`) ships on, downloads models, and was never opted into. | |
| 201 | + | 3. **Set a value to Alloy's preference.** Forbidden here. `browser.uidensity` is the named example and the Containerfile asserts it is absent. | |
| 200 | 202 | ||
| 201 | - | **And it is offered a fix rather than left with the defaults.** Ruled the same day, as the pattern for every bring-your-own role and not a browser exception: where a candidate has bad defaults, offer both a modified configuration and stock. Bad meaning bad, not aesthetic, and the test is who the default serves. Telemetry serves the vendor, sponsored shortcuts serve advertisers, Pocket serves a content business, tracking protection at standard serves the ad industry. Tab layout and density serve the user fine and Alloy has no business touching them on a browser it declined to pick. | |
| 203 | + | Every line is a `pref`, never a `lockPref`: these are starting positions the user can change in Settings. A locked pref would be Alloy hiding a control while objecting to hidden controls, which is the argument in wiki `irreducible-complexity-principle`. | |
| 202 | 204 | ||
| 203 | - | So the estate does not come back, and this is the line that keeps that true: **the modified configuration only removes anti-features and never adds Alloy's taste.** Two hundred lines of `userChrome.css` were the other half of what was deleted and they stay deleted. A diff with a single line about appearance in it has gone too far. The configuration also enumerates what it changes before it runs, because an opaque "Alloy configuration" is a black box the user cannot judge, which would defeat the describing it exists to improve on. | |
| 205 | + | ### What Alloy used to ship here, and still does not | |
| 204 | 206 | ||
| 205 | - | This does not weaken the rule that an app earns a recommendation by not needing configuration. **That rule is a test for what Alloy picks as a default, not a bar on what it will offer as a bring-your-own candidate.** The test for a candidate is provenance and an accurate account of its behaviour. Otherwise the rule would force Alloy to either configure a browser it declined to pick or refuse to name the second engine at all, and both defeat the point of declining. | |
| 207 | + | Five files went in the 2026-07-30 change: an enterprise policy pinning uBlock Origin; a `mozilla.cfg` of around fifty prefs; the autoconfig pointer that loaded it; a `profiles.ini` naming a fixed-path profile; and roughly two hundred lines of `userChrome.css`. **The estate does not come back.** What returns is the substantive fraction of those fifty prefs, the ones answering to the who-does-this-serve test, in one enumerated file. The `userChrome.css` half stays dead: a diff to the pref file with a single line about appearance in it has gone too far. | |
| 206 | 208 | ||
| 207 | - | **This is a non-endorsement, not a pick.** Alloy is not claiming Blink is the better engine, and the monoculture argument that previously rejected Chromium as the default is recorded as overridden rather than withdrawn. Reinforcing one engine's dominance is a real cost and Alloy is paying it. What it lost to is the theming rule: the previous answer was "ship Gecko and fix it", and Alloy no longer fixes browsers. **Firefox remains one line in the Containerfile** for anyone who wants Gecko, which is what a builder-not-artifact distribution means by a choice, and it would ship with no Alloy configuration on it either. | |
| 209 | + | One correction to the older account, measured on Firefox 153: **Pocket is gone from Firefox entirely.** Mozilla shut the service down, and there is no `extensions.pocket` pref left to set. It was on the list from the 2026-07-30 estate and would now be a dead line. | |
| 208 | 210 | ||
| 209 | - | **What still reaches the browser** is system appearance, through the portal and the toolkit rather than through per-app files: `org.freedesktop.appearance` `color-scheme` for light and dark, the GTK theme for system dialogs, the cursor theme, and the font stack including the Noto coverage packages. That is the whole of it. Anything past what a well-behaved app reads from the system is now the user's to set in the browser's own settings. | |
| 211 | + | ### Helium, and why it is not here | |
| 212 | + | ||
| 213 | + | Helium is ungoogled-chromium with the behaviour Alloy used to hand-build already set upstream, packaged by Terra as `helium-browser-bin`. It was the default from 2026-07-30 and one of two recommendations from 2026-08-17. It is now gone from the image and from the builder, for two reasons that arrived a day apart. | |
| 214 | + | ||
| 215 | + | **It was unreachable.** Terra is disabled after install, because leaving it enabled breaks bootc-image-builder's installer depsolve, and `rpm-ostree install --enablerepo` works only in a container build. So a machine that chose no browser could not add Helium by any supported route, which broke the floor the whole bring-your-own arrangement rested on. | |
| 216 | + | ||
| 217 | + | **And it is someone else's workaround.** Helium is a maintained patchset over another vendor's bad defaults. Shipping it as Alloy's answer adopts that mitigation as Alloy's position, and the reasoning that ended it is worth keeping in one line: Helium is doing its best to make a standard approach tolerable, and Alloy is doing its best to improve standard approaches. Anyone who wants it can enable Terra on a machine they own and layer it. That is their call, and not a shape this image carries. | |
| 218 | + | ||
| 219 | + | ### This is a pick, and it is still not an engine claim | |
| 220 | + | ||
| 221 | + | Alloy does not claim Gecko beats Blink. The monoculture argument that once rejected Chromium as a default is recorded as overridden rather than withdrawn, and the engine question is exactly as unarguable as it was on 2026-07-30. What changed is that the question stopped being the deciding one. Applying the reachability criterion left Fedora's stock `chromium` as the only Blink candidate, which is the un-mitigated defaults Helium exists to fix, so there was no second candidate to defend. A role with one defensible candidate gets a pick. | |
| 222 | + | ||
| 223 | + | **What still reaches the browser** is system appearance, through the portal and the toolkit rather than through per-app files: `org.freedesktop.appearance` `color-scheme` for light and dark, the GTK theme for system dialogs, the cursor theme, and the font stack including the Noto coverage packages. That is the whole of it. Anything past what a well-behaved app reads from the system is the user's to set in the browser's own settings. | |
| 210 | 224 | ||
| 211 | 225 | Accepted costs: | |
| 212 | - | - **The day/night switch reaching the browser is unverified.** The deleted `mozilla.cfg` set `ui.systemUsesDarkTheme = 0`, so Alloy was deliberately fighting the portal and the portal path has never been observed working here. If it turns out not to drive Helium, that is recorded as a defect in the appearance propagation and fixed there. Per-app chrome CSS does not come back for it. | |
| 213 | - | - **No blocker is pinned.** Helium's blocking is a browser feature rather than a forced extension, which also means a user who disables it has disabled it, with nothing in the image arguing. | |
| 214 | - | - **`-bin` provenance, and a pre-1.0 version.** Terra repackages an upstream binary rather than building from source, and this is the most attack-exposed program in the image. Helium is also at 0.14.x, which is young for the piece of the system that faces the whole internet. It is still better provenance than the alternatives: Helium has no official Flatpak and upstream refuses to make one, holding that Chromium cannot be packaged as a Flatpak without breaking its internal sandbox, so every Flatpak of it is an unofficial community repackaging. | |
| 215 | - | - **Updates come with the image.** A browser inside the image moves when the image is rebuilt rather than on its own channel. `alloy update` shows what is booted, what is staged, and how to roll back; reporting how far behind the image's packages have fallen, with the browser called out rather than buried in a bulk count, is filed work and not yet shipped. | |
| 226 | + | - **The day/night switch reaching the browser is unverified.** The deleted `mozilla.cfg` set `ui.systemUsesDarkTheme = 0`, so Alloy was deliberately fighting the portal, and the portal path has never been observed working here. If it turns out not to drive Firefox, that is a defect in the appearance propagation and is fixed there. Per-app chrome CSS does not come back for it. | |
| 227 | + | - **No blocker is pinned.** Strict tracking protection is Firefox's own feature rather than a forced extension, so a user who turns it down has turned it down, with nothing in the image arguing. | |
| 228 | + | - **A pref file is a maintenance surface.** Mozilla renames prefs, and a pref that no longer exists fails silently. The file records that its names were read out of Firefox 153.0's `omni.ja` on 2026-08-18 rather than remembered, and re-measuring is part of taking a Fedora major. | |
| 229 | + | - **Updates come with the image.** A browser inside the image moves when the image is rebuilt rather than on its own channel. `alloy update` shows what is booted, what is staged, and how to roll back. | |
| 216 | 230 | ||
| 217 | 231 | Rejected: | |
| 218 | - | - **Firefox as the default.** Was the previous pick, and upstream Gecko remains the right Gecko. It loses on rule 3 alone: keeping it as the default meant keeping the five files, and every one of them was Alloy configuring an application. | |
| 219 | - | - **Ungoogled-chromium.** Helium is built on it, so these were never two options, and it is packaged for neither Fedora nor Terra. Compiling it in the image costs hours of build time and roughly 100 GB of scratch space for a subset of what the prebuilt package already provides. | |
| 220 | - | - **Helium as a Flatpak.** See the provenance note above. | |
| 232 | + | - **Helium.** See above. Unreachable after install, and a patchset over another project's defaults. | |
| 233 | + | - **Ungoogled-chromium.** Packaged for neither Fedora nor Terra. Compiling it in the image costs hours of build time and roughly 100 GB of scratch space. | |
| 234 | + | - **Stock `chromium` from Fedora.** Reachable, and it is the un-mitigated defaults. Recommending it unconfigured endorses defaults Alloy rejects; configuring it rebuilds the estate on a browser Alloy has no other reason to carry. | |
| 221 | 235 | - **LibreWolf.** Ships uBlock Origin preinstalled, but its hardening (`resistFingerprinting`, letterboxing, cookie clears on close, WebGL off) breaks modern sites. Un-hardening it to pass the "runs all modern sites" bar erases the reason to choose it. | |
| 222 | 236 | - **Zen Browser.** Gecko-based and design-forward, but its identity centers vertical tabs and sidebar-forward layout. Revisit only if Zen ships a first-class horizontal mode as a supported configuration. | |
| 223 | 237 | - **Brave, Vivaldi, Arc.** Each arrives with a business model attached to the browser, which is the class of default Alloy is least willing to hand a user. |
| @@ -275,16 +275,16 @@ | |||
| 275 | 275 | license = "MIT" | |
| 276 | 276 | url = "https://github.com/Byron/dua-cli" | |
| 277 | 277 | ||
| 278 | + | [[section.project]] | |
| 279 | + | name = "Firefox" | |
| 280 | + | license = "MPL-2.0" | |
| 281 | + | url = "https://www.mozilla.org/firefox" | |
| 282 | + | ||
| 278 | 283 | [[section.project]] | |
| 279 | 284 | name = "Git" | |
| 280 | 285 | license = "GPL-2.0-only" | |
| 281 | 286 | url = "https://git-scm.com" | |
| 282 | 287 | ||
| 283 | - | [[section.project]] | |
| 284 | - | name = "Helium" | |
| 285 | - | license = "GPL-3.0-only AND BSD-3-Clause" | |
| 286 | - | url = "https://helium.computer" | |
| 287 | - | ||
| 288 | 288 | [[section.project]] | |
| 289 | 289 | name = "jq" | |
| 290 | 290 | license = "MIT" |
| @@ -91,20 +91,31 @@ | |||
| 91 | 91 | ||
| 92 | 92 | ## The browser | |
| 93 | 93 | ||
| 94 | - | Helium ships in the image as the default browser, unconfigured. It is | |
| 95 | - | ungoogled-chromium with ad blocking, tracker blocking, cookie-banner handling | |
| 96 | - | and anti-fingerprinting already on upstream, and it makes no network request on | |
| 97 | - | first launch. | |
| 94 | + | Firefox ships in the image as the default browser. It comes from Fedora's own | |
| 95 | + | repositories, which matters more than it sounds: those stay enabled after you | |
| 96 | + | install, so a machine built with no browser at all is one `rpm-ostree install | |
| 97 | + | firefox` away from this one. | |
| 98 | 98 | ||
| 99 | - | Alloy ships no policy file, no preference seed, no chrome CSS and no pinned | |
| 100 | - | extension for it. That is why it is the default: an app earns a recommendation | |
| 101 | - | here by not needing to be configured. Anything past what a well-behaved app | |
| 102 | - | reads from the system (light or dark, the GTK theme for dialogs, the cursor, | |
| 103 | - | the fonts) is yours to set in the browser's own settings. | |
| 99 | + | Alloy changes exactly one file, `/etc/firefox/pref/alloy.js`, and it is worth | |
| 100 | + | knowing what is in it because the rule it follows is short. Alloy turns off | |
| 101 | + | things that serve somebody other than you: telemetry, sponsored placements on | |
| 102 | + | the new tab page and in the address bar, and the AI features, which arrive | |
| 103 | + | switched on and download models nobody asked for. It sets tracking protection | |
| 104 | + | to strict. It also turns on one thing, `browser.compactmode.show`, which puts | |
| 105 | + | the density control back in Customize where Mozilla hides it. | |
| 104 | 106 | ||
| 105 | - | Firefox is one line in the Containerfile if you want Gecko, and would ship with | |
| 106 | - | no Alloy configuration on it either. | |
| 107 | + | That last one is the pattern rather than an exception. Alloy would rather hand | |
| 108 | + | you back a control than pick the value for you, so it does not set the density | |
| 109 | + | itself: compact is one click away in Customize and the choice stays yours. | |
| 107 | 110 | ||
| 108 | - | Two honest notes. The browser is packaged from an upstream binary rather than | |
| 109 | - | built from source, and it is pre-1.0. And because it lives in the image, it | |
| 110 | - | updates when you rebuild the image and not before (chapter 8). | |
| 111 | + | Nothing in that file is locked. Every line is a starting position you can | |
| 112 | + | change in Settings, and if you disagree with all of it, changing all of it is | |
| 113 | + | supported. There is no policy file, no autoconfig, and no chrome CSS. Anything | |
| 114 | + | past what a well-behaved app reads from the system (light or dark, the GTK | |
| 115 | + | theme for dialogs, the cursor, the fonts) is yours to set in the browser's own | |
| 116 | + | settings. | |
| 117 | + | ||
| 118 | + | Two honest notes. Because the browser lives in the image, it updates when you | |
| 119 | + | rebuild the image and not before (chapter 8). And Mozilla renames preferences | |
| 120 | + | between releases, so a line in that file can quietly stop applying; the file | |
| 121 | + | records which Firefox version its names were read from. |
| @@ -33,12 +33,11 @@ | |||
| 33 | 33 | # | |
| 34 | 34 | # It also fixes a smaller thing that worked by luck. The vendor mimeapps.list | |
| 35 | 35 | # ships from shared-mime-info and names `org.mozilla.firefox.desktop`, which | |
| 36 | - | # this image does not contain under any BROWSER value: Helium is | |
| 37 | - | # helium.desktop and Fedora's Firefox rpm is firefox.desktop, while that id | |
| 38 | - | # belongs to the Flatpak. It resolved correctly anyway, by falling through to | |
| 39 | - | # mimeinfo.cache where exactly one candidate declared the scheme. One browser | |
| 40 | - | # is not a thing to rely on when the point of the exercise is that the user | |
| 41 | - | # brings their own. | |
| 36 | + | # this image does not contain under any BROWSER value: Fedora's Firefox rpm is | |
| 37 | + | # firefox.desktop, while that id belongs to the Flatpak. It resolved correctly | |
| 38 | + | # anyway, by falling through to mimeinfo.cache where exactly one candidate | |
| 39 | + | # declared the scheme. One browser is not a thing to rely on: a `BROWSER=none` | |
| 40 | + | # image has none, and a user's own Flatpak is a second. | |
| 42 | 41 | ||
| 43 | 42 | set -eu | |
| 44 | 43 | ||
| @@ -125,7 +124,13 @@ | |||
| 125 | 124 | # telling someone to run a command that is not there is the same silent | |
| 126 | 125 | # failure this script was written to remove, one level up. When that verb | |
| 127 | 126 | # ships it replaces the flatpak line here. | |
| 127 | + | # | |
| 128 | + | # The layering route is named because it works: Firefox is in Fedora's own | |
| 129 | + | # repos, and those stay enabled after install. That is the whole reason it is | |
| 130 | + | # Alloy's pick (wiki `alloy-byo-principle`), so a machine that chose `none` is | |
| 131 | + | # one command from the browser the image would have carried. | |
| 128 | 132 | printf 'No browser is installed, so this link cannot be opened: %s\n' "$url" >&2 | |
| 129 | - | say "Install one with: flatpak install fedora org.mozilla.firefox | |
| 130 | - | Or rebuild the image with BROWSER=helium to bake one in." | |
| 133 | + | say "Install one with: rpm-ostree install firefox | |
| 134 | + | Or, sandboxed: flatpak install fedora org.mozilla.firefox | |
| 135 | + | Or rebuild the image with BROWSER=firefox to bake one in." | |
| 131 | 136 | exit 3 |
| @@ -378,7 +378,7 @@ | |||
| 378 | 378 | Ok(vec![ | |
| 379 | 379 | Stream { | |
| 380 | 380 | index: 100, | |
| 381 | - | app: "Helium".into(), | |
| 381 | + | app: "firefox".into(), | |
| 382 | 382 | direction: Direction::Output, | |
| 383 | 383 | device_index: 1, | |
| 384 | 384 | volume: 100, |