Skip to main content

max / alloy_tui

Firefox: wire user.js and userChrome.css to paths Firefox actually reads The previous browser commit shipped user.js and userChrome.css under usr/share/alloy/firefox/, which Firefox never reads. Both files were inert. This commit lands the config at the paths Firefox actually consults, splitting per-profile chrome from system-wide prefs: System-wide default prefs via autoconfig: - usr/lib64/firefox/mozilla.cfg — the previous user.js contents, ported to defaultPref() calls so users can still override. Line 1 is a comment because Firefox unconditionally skips the first line. - usr/lib64/firefox/defaults/pref/autoconfig.js — points Firefox at mozilla.cfg with obscure_value=0 (plain-text config). Per-profile chrome via first-launch profile seed: - etc/skel/.mozilla/firefox/profiles.ini — names a fixed-path profile (alloy.default) so Firefox opens the seeded profile on first launch instead of generating a random-suffix one. - etc/skel/.mozilla/firefox/alloy.default/chrome/userChrome.css — the ultra-compact chrome that was previously stranded at usr/share/alloy/firefox/. mozilla.cfg enables toolkit.legacyUserProfileCustomizations.stylesheets so Firefox actually reads it. usr/share/alloy/firefox/ deleted (both files relocated); the empty parent usr/share/alloy/ also deleted since nothing lives there now. Containerfile config-tree comment and IMAGE.md layout note updated to reflect the new paths. STACK.md#Browser rewritten to describe four config files (each at its live path) instead of three at a never-read one, with links pointing at the real files in the repo. The remaining verification is a QEMU boot: launch Firefox from a fresh /etc/skel spawn and confirm the profile lands at alloy.default/, uBlock Origin auto-installs from the policy, and the compact chrome renders.
Co-Authored-By
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-18 15:37 UTC
Signed with PGP, not checked
Commit: 8917a6eb64b0ed1395436c698f29da6351187a3e
Parent: 5351a12
8 files changed, +124 insertions, -93 deletions
M Containerfile +4 -3
@@ -180,9 +180,10 @@
180 180
181 181 # =====================================================================
182 182 # Config tree — the etc/ and usr/ trees in the repo map 1:1 into
183 - # the image. Per-user defaults live under etc/skel/.config/;
184 - # system-wide config under etc/; Alloy-owned templates under
185 - # usr/share/alloy/. See docs/IMAGE.md for the layout.
183 + # the image. Per-user defaults live under etc/skel/.config/ and
184 + # etc/skel/.mozilla/ (Firefox first-launch profile seed); system-
185 + # wide config under etc/; Firefox autoconfig + mozilla.cfg under
186 + # usr/lib64/firefox/. See docs/IMAGE.md for the layout.
186 187 # =====================================================================
187 188 COPY etc/ /etc/
188 189 COPY usr/ /usr/
M docs/IMAGE.md +1 -1
@@ -68,7 +68,7 @@
68 68 2. **Third-party repos:** Tailscale, any COPRs Alloy depends on for packages not in Fedora main.
69 69 3. **Package additions:** the full Alloy stack from [STACK.md](STACK.md) — compositor, bar, launcher, notifications, terminal, editor, shell, viewers, utilities, continuity daemons, fonts, themes.
70 70 4. **Package removals:** stock Silverblue desktop pieces Alloy replaces (gnome-shell, gdm — the latter gated on the greeter pick).
71 - 5. **Config tree:** the tree at `etc/skel/.config/*` (new-user defaults), `etc/*` (system-wide), and `usr/share/alloy/*` (Alloy-owned templates) in the repo maps 1:1 into the image.
71 + 5. **Config tree:** the tree at `etc/skel/.config/*` and `etc/skel/.mozilla/*` (new-user defaults, including the Firefox first-launch profile seed), `etc/*` (system-wide, including `etc/firefox/policies/policies.json`), and `usr/lib64/firefox/*` (Firefox autoconfig + `mozilla.cfg` default prefs) in the repo maps 1:1 into the image.
72 72 6. **Systemd presets:** which services are enabled by default (syncthing off by default, gammastep off until enrolled, alloy-hinged conditionally on FW12, etc.).
73 73 7. **Branding:** os-release, plymouth splash.
74 74 8. **Validation:** `bootc container lint` runs at build.
M docs/STACK.md +6 -5
@@ -119,13 +119,14 @@
119 119
120 120 ## Browser
121 121
122 - **Firefox (upstream) baked in as the default; ungoogled-chromium available as an opt-in Flatpak.** Alloy's identity work happens at the engine level, not the fork level, so upstream Firefox is the right base — no ESR lag, no fork-specific patch drift, the most-tested Gecko build shipping. Alloy owns the visual and behavioral layer via three files:
122 + **Firefox (upstream) baked in as the default; ungoogled-chromium available as an opt-in Flatpak.** Alloy's identity work happens at the engine level, not the fork level, so upstream Firefox is the right base — no ESR lag, no fork-specific patch drift, the most-tested Gecko build shipping. Alloy owns the visual and behavioral layer via four files, each landing at the path Firefox actually reads:
123 123
124 - - `/etc/firefox/policies/policies.json` — enterprise policy. Pins **uBlock Origin** as a force-installed, update-locked extension. Disables telemetry, Pocket, studies, sponsored tiles, new-tab feed, formfill, and password saving at the policy layer (higher-precedence than user prefs).
125 - - `usr/share/alloy/firefox/user.js` — user-profile prefs. Backs up the policy kills for the settings not exposed to enterprise policy, and configures compact UI density, blank new tab, DuckDuckGo suggestions off, quiet scroll.
126 - - `usr/share/alloy/firefox/userChrome.css` — Helium-style ultra-compact horizontal chrome (thin tab strip, compact address bar, no title bar, no menu bar, no bookmarks bar), using Alloy's light-mode tokens (H=80, C=0.012 ramp from [TOKENS.md](TOKENS.md)).
124 + - [`etc/firefox/policies/policies.json`](../etc/firefox/policies/policies.json) — enterprise policy. Pins **uBlock Origin** as a force-installed, update-locked extension. Disables telemetry, Pocket, studies, sponsored tiles, new-tab feed, formfill, and password saving at the policy layer (higher-precedence than user prefs).
125 + - [`usr/lib64/firefox/mozilla.cfg`](../usr/lib64/firefox/mozilla.cfg) — system-wide default prefs, loaded via Firefox autoconfig. Configures compact UI density, blank new tab, DuckDuckGo suggestions off, quiet scroll, and enables `toolkit.legacyUserProfileCustomizations.stylesheets` so `userChrome.css` gets read. Every entry uses `defaultPref()` so users can still override in `about:config`.
126 + - [`usr/lib64/firefox/defaults/pref/autoconfig.js`](../usr/lib64/firefox/defaults/pref/autoconfig.js) — one-line pointer telling Firefox to load `mozilla.cfg` at startup.
127 + - [`etc/skel/.mozilla/firefox/profiles.ini`](../etc/skel/.mozilla/firefox/profiles.ini) + [`etc/skel/.mozilla/firefox/alloy.default/chrome/userChrome.css`](../etc/skel/.mozilla/firefox/alloy.default/chrome/userChrome.css) — first-launch profile seed. `profiles.ini` names a fixed-path profile (`alloy.default/`) so the pre-seeded `chrome/userChrome.css` (Helium-style ultra-compact horizontal, Alloy light-mode tokens from [TOKENS.md](TOKENS.md)) lands under it. Firefox opens the seeded profile on first launch instead of generating a random-suffix one.
127 128
128 - Runs all modern sites (uBlock Origin blocks ads, never JS). Horizontal tabs only, per firm preference. Config lives at [`usr/share/alloy/firefox/`](../usr/share/alloy/firefox/) and [`etc/firefox/policies/`](../etc/firefox/policies/) with a README explaining install and verification.
129 + Runs all modern sites (uBlock Origin blocks ads, never JS). Horizontal tabs only, per firm preference.
129 130
130 131 **Ungoogled-chromium** is offered as the second-engine escape valve for the rare site that only renders correctly under Blink, and for users who prefer Chromium ergonomics without Google telemetry. Not baked into the ISO. Install path:
131 132
@@ -9,7 +9,7 @@
9 9 * warm cream / papery beige — the Flatwhite family aesthetic — by design.
10 10 *
11 11 * Requires: toolkit.legacyUserProfileCustomizations.stylesheets = true
12 - * (set in user.js).
12 + * (set in usr/lib64/firefox/mozilla.cfg as a system default).
13 13 */
14 14
15 15 :root {
@@ -1,0 +1,9 @@
1 + [General]
2 + StartWithLastProfile=1
3 + Version=2
4 +
5 + [Profile0]
6 + Name=alloy
7 + IsRelative=1
8 + Path=alloy.default
9 + Default=1
@@ -1,0 +1,12 @@
1 + // Alloy Firefox autoconfig pointer.
2 + //
3 + // Tells Firefox to load /usr/lib64/firefox/mozilla.cfg on startup.
4 + // obscure_value = 0 means mozilla.cfg is plain-text (Firefox's byte-
5 + // shift obfuscation is off); we still keep the mandatory first-line
6 + // comment because Firefox skips it unconditionally.
7 + //
8 + // See usr/lib64/firefox/mozilla.cfg for the actual defaults.
9 +
10 + pref("general.config.filename", "mozilla.cfg");
11 + pref("general.config.obscure_value", 0);
12 + pref("general.config.sandbox_enabled", false);
@@ -1,0 +1,91 @@
1 + // Alloy Firefox system defaults
2 + //
3 + // Loaded via /usr/lib64/firefox/defaults/pref/autoconfig.js, which
4 + // points Firefox at this file at startup. Applies system-wide as
5 + // default preferences; users can still override any value in
6 + // about:config or via profile prefs.
7 + //
8 + // Locked prefs (telemetry, Pocket, extension pinning, etc.) live in
9 + // /etc/firefox/policies/policies.json — that layer is stronger than
10 + // this one and its settings cannot be overridden.
11 + //
12 + // IMPORTANT: Line 1 of this file MUST be a comment. Firefox skips
13 + // the first line unconditionally as an anti-tamper heuristic. Do
14 + // not add a `defaultPref` on line 1.
15 +
16 + // -------------------------------------------------------------------
17 + // Enable userChrome.css / userContent.css loading. Alloy ships the
18 + // chrome CSS at ~/.mozilla/firefox/alloy.default/chrome/userChrome.css
19 + // via etc/skel; without this pref Firefox ignores it.
20 + // -------------------------------------------------------------------
21 + defaultPref("toolkit.legacyUserProfileCustomizations.stylesheets", true);
22 +
23 + // -------------------------------------------------------------------
24 + // Force light chrome theme — Alloy Flatwhite-adjacent palette lives
25 + // in userChrome.css. Do not follow system dark mode for browser UI.
26 + // -------------------------------------------------------------------
27 + defaultPref("ui.systemUsesDarkTheme", 0);
28 + defaultPref("browser.theme.toolbar-theme", 1); // 0=dark, 1=light, 2=system
29 + defaultPref("browser.theme.content-theme", 2); // web content follows system
30 +
31 + // -------------------------------------------------------------------
32 + // UI density and layout — Helium-style compact horizontal
33 + // -------------------------------------------------------------------
34 + defaultPref("browser.uidensity", 1); // compact
35 + defaultPref("browser.tabs.tabMinWidth", 60); // slim tabs
36 + defaultPref("browser.tabs.tabmanager.enabled", false); // no dropdown list
37 + defaultPref("browser.bookmarks.toolbar.visibility", "never"); // hide bookmarks bar
38 + defaultPref("browser.tabs.firefox-view", false); // no Firefox View button
39 + defaultPref("browser.tabs.firefox-view-next", false);
40 +
41 + // Explicitly no vertical tabs.
42 + defaultPref("sidebar.verticalTabs", false);
43 + defaultPref("sidebar.revamp", false);
44 +
45 + // -------------------------------------------------------------------
46 + // New tab / home page — blank
47 + // -------------------------------------------------------------------
48 + defaultPref("browser.startup.homepage", "about:blank");
49 + defaultPref("browser.newtabpage.enabled", false);
50 + defaultPref("browser.newtab.url", "about:blank");
51 + defaultPref("browser.newtabpage.activity-stream.showSponsored", false);
52 + defaultPref("browser.newtabpage.activity-stream.showSponsoredTopSites", false);
53 + defaultPref("browser.newtabpage.activity-stream.feeds.topsites", false);
54 + defaultPref("browser.newtabpage.activity-stream.feeds.section.topstories", false);
55 + defaultPref("browser.newtabpage.activity-stream.feeds.snippets", false);
56 +
57 + // -------------------------------------------------------------------
58 + // Search — DuckDuckGo default; suggestions off
59 + // -------------------------------------------------------------------
60 + defaultPref("browser.search.suggest.enabled", false);
61 + defaultPref("browser.urlbar.suggest.searches", false);
62 + defaultPref("browser.urlbar.suggest.quicksuggest.sponsored", false);
63 + defaultPref("browser.urlbar.suggest.quicksuggest.nonsponsored", false);
64 + defaultPref("browser.urlbar.trending.featureGate", false);
65 + defaultPref("browser.urlbar.weather.featureGate", false);
66 +
67 + // -------------------------------------------------------------------
68 + // Privacy defaults not covered by enterprise policy
69 + // -------------------------------------------------------------------
70 + defaultPref("browser.contentblocking.category", "strict");
71 + defaultPref("privacy.donottrackheader.enabled", true);
72 + defaultPref("privacy.globalprivacycontrol.enabled", true);
73 + defaultPref("browser.formfill.enable", false);
74 +
75 + // -------------------------------------------------------------------
76 + // Miscellany — reduce noise
77 + // -------------------------------------------------------------------
78 + defaultPref("browser.aboutConfig.showWarning", false);
79 + defaultPref("browser.warnOnQuitShortcut", false);
80 + defaultPref("browser.tabs.warnOnClose", false);
81 + defaultPref("browser.tabs.warnOnCloseOtherTabs", false);
82 + defaultPref("browser.tabs.warnOnOpen", false);
83 + defaultPref("browser.download.useDownloadDir", true);
84 + defaultPref("browser.download.alwaysOpenPanel", false);
85 +
86 + // Smooth scrolling with sensible values (not the default overshoot).
87 + defaultPref("general.smoothScroll", true);
88 + defaultPref("mousewheel.default.delta_multiplier_y", 100);
89 +
90 + // Prevent accidental font size zoom on Ctrl+scroll.
91 + defaultPref("mousewheel.with_control.action", 0);