max / alloy
- Co-Authored-By
- Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8 files changed,
+111 insertions,
-73 deletions
| @@ -75,7 +75,7 @@ | |||
| 75 | 75 | # Package additions — full Alloy stack per docs/STACK.md | |
| 76 | 76 | # | |
| 77 | 77 | # Sources noted per group. Anything absent from both Fedora main and | |
| 78 | - | # Terra is either handled via Flatpak (Rnote, Floorp) or downloaded | |
| 78 | + | # Terra is either handled via Flatpak (Rnote) or downloaded | |
| 79 | 79 | # directly (Nerd Fonts). | |
| 80 | 80 | # ===================================================================== | |
| 81 | 81 | RUN dnf install -y \ | |
| @@ -119,7 +119,9 @@ | |||
| 119 | 119 | adw-gtk3-theme \ | |
| 120 | 120 | # Screenshot capture + region-select (sway has no built-in grab) | |
| 121 | 121 | grim slurp \ | |
| 122 | - | # Flatpak client (Flathub + Floorp/Rnote install at first boot) | |
| 122 | + | # Browser (Gecko default; ungoogled-chromium is opt-in Flatpak per docs/STACK.md) | |
| 123 | + | firefox \ | |
| 124 | + | # Flatpak client (Flathub + Rnote install at first boot) | |
| 123 | 125 | flatpak \ | |
| 124 | 126 | # Font tools | |
| 125 | 127 | unzip fontconfig \ | |
| @@ -167,7 +169,7 @@ | |||
| 167 | 169 | || true | |
| 168 | 170 | ||
| 169 | 171 | # ===================================================================== | |
| 170 | - | # Flathub + Floorp + Rnote — deferred to first boot | |
| 172 | + | # Flathub + Rnote — deferred to first boot | |
| 171 | 173 | # ===================================================================== | |
| 172 | 174 | # bootc prefers /var empty at build time; `flatpak remote-add` and | |
| 173 | 175 | # `flatpak install --system` both write to /var/lib/flatpak, which |
| @@ -73,7 +73,7 @@ | |||
| 73 | 73 | 7. **Branding:** os-release, plymouth splash. | |
| 74 | 74 | 8. **Validation:** `bootc container lint` runs at build. | |
| 75 | 75 | ||
| 76 | - | Fedora Flatpaks (Floorp specifically) are installed system-wide in the image via `flatpak install --system flathub`, with the Flathub remote added first. This trades image size for zero-friction first-boot — user reboots into Alloy, opens Floorp, done. | |
| 76 | + | The base browser (Firefox) ships as an RPM baked into the image — one code path, no first-boot delay, and enterprise policies (`/etc/firefox/policies/policies.json`) take effect immediately. Rnote and any other Flathub-only apps are installed system-wide on first boot via `alloy-flatpak-firstboot.service`, which adds the Flathub remote and pulls the apps — an image-size / first-boot-latency trade Alloy accepts for tools without clean RPM sources. | |
| 77 | 77 | ||
| 78 | 78 | ## Update cadence | |
| 79 | 79 |
| @@ -120,26 +120,31 @@ | |||
| 120 | 120 | ||
| 121 | 121 | ## Browser | |
| 122 | 122 | ||
| 123 | - | **Floorp.** Firefox fork by Ablaze, Gecko-based, ships as Flatpak on Flathub. Picked over baseline Firefox because Floorp exposes materially more visual configurability through its own settings (density, tab layout, workspaces) without needing extensions, and picked over any Chromium fork because Alloy should not reinforce the Chromium monoculture — browser-engine diversity is load-bearing for the web, and Alloy shipping Gecko is a small vote in the right direction. | |
| 123 | + | **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: | |
| 124 | 124 | ||
| 125 | - | Alloy preconfigures Floorp with: | |
| 126 | - | - Helium-style ultra-compact horizontal chrome (thin tab strip, compact address bar, no title bar, no menu bar, no bookmarks bar). | |
| 127 | - | - Alloy light-mode tokens applied via `userChrome.css` — Flatwhite-adjacent warm cream from the same H=80, C=0.012 ramp used everywhere else (see [TOKENS.md](TOKENS.md)). | |
| 128 | - | - Telemetry, Pocket, studies, sponsored tiles, and new-tab feed content off. | |
| 129 | - | - Blank new tab, DuckDuckGo search suggestions off, formfill off (browser is not a password manager). | |
| 130 | - | - No vertical tabs — horizontal only, per firm preference. | |
| 125 | + | - `/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). | |
| 126 | + | - `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. | |
| 127 | + | - `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)). | |
| 131 | 128 | ||
| 132 | - | Config lives at [`usr/share/alloy/floorp/`](../usr/share/alloy/floorp/) — `user.js` for prefs, `chrome/userChrome.css` for chrome overrides, and a README explaining install and verification. | |
| 129 | + | 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. | |
| 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: | |
| 132 | + | ||
| 133 | + | ``` | |
| 134 | + | flatpak install flathub io.github.ungoogled_software.ungoogled_chromium | |
| 135 | + | ``` | |
| 136 | + | ||
| 137 | + | No Alloy config is shipped for it. The point is a working Chromium engine on demand, not a second identity surface. | |
| 133 | 138 | ||
| 134 | 139 | Accepted costs: | |
| 135 | - | - **userChrome.css drifts** across Firefox major versions. Alloy owns the theme; re-verify after each Floorp major release. Bounded work (a few selectors per bump). | |
| 136 | - | - **Floorp release cadence** lags upstream Firefox slightly (ESR-based). Security patches arrive a beat later. Trade accepted for the configurability. | |
| 137 | - | - **Fallback:** if Floorp stalls or drifts weirdly, Alloy falls back to plain Firefox + the same `userChrome.css`. The user-visible difference is smaller than it looks because Alloy owns the visual layer. | |
| 140 | + | - **userChrome.css drifts** across Firefox major versions. Alloy owns the theme; re-verify after each Firefox major release. Bounded work (a few selectors per bump). | |
| 141 | + | - **uBlock Origin pinning** is Alloy's enterprise policy, so Firefox will refuse to let the user disable or uninstall it via the extensions UI. Users who need to disable it can edit `/etc/firefox/policies/policies.json` themselves; Alloy documents the location. | |
| 138 | 142 | ||
| 139 | 143 | Rejected: | |
| 140 | - | - **Chromium and any Chromium fork** (Brave, Vivaldi, Helium, Arc, Zen-if-it-were-Chromium). Alloy doesn't reinforce browser-engine monoculture. | |
| 141 | - | - **LibreWolf.** Stronger privacy defaults but less visual configurability than Floorp; the visual work would still need to happen and LibreWolf isn't friendlier to it. | |
| 142 | - | - **Zen Browser.** Gecko-based and design-forward, but the identity centers vertical tabs and sidebar-forward layout, which conflicts with the horizontal-tabs preference. Revisit only if Zen ships a first-class horizontal mode. | |
| 144 | + | - **Floorp.** Was the previous pick. Rough edges in daily use, ESR-based cadence lags Firefox security patches, fork-specific patches add drift Alloy doesn't own. Upstream Firefox with policies + userChrome.css captures the actual value (visual and behavioral configurability) at less cost. | |
| 145 | + | - **LibreWolf.** Ships uBlock Origin preinstalled — real win — but its hardening (`resistFingerprinting`, letterboxing, cookie clears on close, WebGL off) breaks modern sites. Un-hardening it to pass Alloy's "runs all modern sites" bar erases the reason to choose it over Firefox. | |
| 146 | + | - **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. | |
| 147 | + | - **Chromium as default, Brave, Vivaldi, Arc, Helium.** Alloy doesn't reinforce browser-engine monoculture. Ungoogled-chromium covers the "I need Blink" case without making it the default. | |
| 143 | 148 | ||
| 144 | 149 | ## Shell | |
| 145 | 150 | ||
| @@ -250,7 +255,7 @@ | |||
| 250 | 255 | ||
| 251 | 256 | ### Media keys: **playerctl** | |
| 252 | 257 | ||
| 253 | - | C, MPRIS client. CLI. No config — sway binds media keys directly to `exec playerctl play-pause` and similar. Handles Spotify, mpv, Firefox/Floorp, and any MPRIS-compliant source. | |
| 258 | + | C, MPRIS client. CLI. No config — sway binds media keys directly to `exec playerctl play-pause` and similar. Handles Spotify, mpv, Firefox, and any MPRIS-compliant source. | |
| 254 | 259 | ||
| 255 | 260 | Rejected: playerctld (still a playerctl variant), no serious alternative. | |
| 256 | 261 | ||
| @@ -280,7 +285,7 @@ | |||
| 280 | 285 | ||
| 281 | 286 | Config at [`etc/skel/.config/gtk-3.0/`](../etc/skel/.config/gtk-3.0/) and [`etc/skel/.config/gtk-4.0/`](../etc/skel/.config/gtk-4.0/) with matching `gtk.css` and `settings.ini` per version. | |
| 282 | 287 | ||
| 283 | - | **What this covers:** any GTK 3 or GTK 4 app that consumes libadwaita's named tokens — swayosd (GTK-rendered overlays), Floorp's system dialogs, cosmic-files if GTK-based, etc. | |
| 288 | + | **What this covers:** any GTK 3 or GTK 4 app that consumes libadwaita's named tokens — swayosd (GTK-rendered overlays), Firefox's system dialogs, cosmic-files if GTK-based, etc. | |
| 284 | 289 | ||
| 285 | 290 | **What this doesn't cover:** | |
| 286 | 291 | - Legacy GTK 3 apps with their own token sets (rare — most have migrated). |
| @@ -7,10 +7,13 @@ | |||
| 7 | 7 | # - tailscaled: opt-in only. Enrollment happens via `alloy tail` | |
| 8 | 8 | # (see docs/CONTINUITY.md — Alloy does not phone home | |
| 9 | 9 | # before the user says yes). | |
| 10 | - | # - alloy-flatpak-firstboot: adds flathub and installs Floorp + Rnote | |
| 11 | - | # the first time the machine reaches multi-user with | |
| 12 | - | # network. Kept out of the build so /var stays empty | |
| 13 | - | # at image-build time (bootc lint requirement). | |
| 10 | + | # - alloy-flatpak-firstboot: adds flathub and installs Rnote the first | |
| 11 | + | # time the machine reaches multi-user with network. Kept | |
| 12 | + | # out of the build so /var stays empty at image-build | |
| 13 | + | # time (bootc lint requirement). Firefox is the default | |
| 14 | + | # browser and ships in the base image via dnf, so no | |
| 15 | + | # Flatpak involvement there; ungoogled-chromium is | |
| 16 | + | # user-installed on demand (see docs/STACK.md). | |
| 14 | 17 | # | |
| 15 | 18 | # Format: `enable|disable <unit>`. First match wins; entries without | |
| 16 | 19 | # a match fall through to /usr/lib/systemd/system-preset/ defaults. |
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | [Unit] | |
| 2 | - | Description=Alloy first-boot Flatpak provisioning (Floorp, Rnote) | |
| 2 | + | Description=Alloy first-boot Flatpak provisioning (Rnote) | |
| 3 | 3 | Documentation=file:///usr/share/alloy/README | |
| 4 | 4 | After=network-online.target | |
| 5 | 5 | Wants=network-online.target | |
| @@ -9,7 +9,7 @@ | |||
| 9 | 9 | Type=oneshot | |
| 10 | 10 | RemainAfterExit=yes | |
| 11 | 11 | ExecStart=/usr/bin/flatpak remote-add --system --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo | |
| 12 | - | ExecStart=/usr/bin/flatpak install --system --noninteractive --or-update flathub one.ablaze.floorp com.github.flxzt.rnote | |
| 12 | + | ExecStart=/usr/bin/flatpak install --system --noninteractive --or-update flathub com.github.flxzt.rnote | |
| 13 | 13 | ExecStart=/usr/bin/mkdir -p /var/lib/alloy | |
| 14 | 14 | ExecStart=/usr/bin/touch /var/lib/alloy/flatpak-firstboot.done | |
| 15 | 15 |
| @@ -1,7 +1,11 @@ | |||
| 1 | - | // Alloy Floorp preferences | |
| 1 | + | // Alloy Firefox preferences | |
| 2 | 2 | // | |
| 3 | - | // Loaded on every Floorp startup; overrides values in prefs.js. | |
| 4 | - | // See docs/STACK.md ("Terminal / Browser" section) for context. | |
| 3 | + | // Loaded on every Firefox startup; overrides values in prefs.js. | |
| 4 | + | // See docs/STACK.md ("Browser" section) for context. | |
| 5 | + | // | |
| 6 | + | // Higher-precedence policy kills (telemetry, Pocket, extension pinning, | |
| 7 | + | // password saving, etc.) live in /etc/firefox/policies/policies.json. | |
| 8 | + | // This file covers per-profile UX prefs the policy layer doesn't expose. | |
| 5 | 9 | ||
| 6 | 10 | // ------------------------------------------------------------------- | |
| 7 | 11 | // Enable userChrome.css / userContent.css loading | |
| @@ -27,8 +31,8 @@ | |||
| 27 | 31 | user_pref("browser.tabs.firefox-view-next", false); | |
| 28 | 32 | ||
| 29 | 33 | // Explicitly no vertical tabs. | |
| 30 | - | user_pref("floorp.browser.tabs.verticaltab", false); | |
| 31 | 34 | user_pref("sidebar.verticalTabs", false); | |
| 35 | + | user_pref("sidebar.revamp", false); | |
| 32 | 36 | ||
| 33 | 37 | // ------------------------------------------------------------------- | |
| 34 | 38 | // New tab / home page — blank | |
| @@ -43,45 +47,7 @@ | |||
| 43 | 47 | user_pref("browser.newtabpage.activity-stream.feeds.snippets", false); | |
| 44 | 48 | ||
| 45 | 49 | // ------------------------------------------------------------------- | |
| 46 | - | // Telemetry off | |
| 47 | - | // ------------------------------------------------------------------- | |
| 48 | - | user_pref("toolkit.telemetry.enabled", false); | |
| 49 | - | user_pref("toolkit.telemetry.unified", false); | |
| 50 | - | user_pref("toolkit.telemetry.archive.enabled", false); | |
| 51 | - | user_pref("toolkit.telemetry.newProfilePing.enabled", false); | |
| 52 | - | user_pref("toolkit.telemetry.shutdownPingSender.enabled", false); | |
| 53 | - | user_pref("toolkit.telemetry.updatePing.enabled", false); | |
| 54 | - | user_pref("toolkit.telemetry.bhrPing.enabled", false); | |
| 55 | - | user_pref("toolkit.telemetry.firstShutdownPing.enabled", false); | |
| 56 | - | user_pref("datareporting.healthreport.uploadEnabled", false); | |
| 57 | - | user_pref("datareporting.policy.dataSubmissionEnabled", false); | |
| 58 | - | user_pref("browser.ping-centre.telemetry", false); | |
| 59 | - | user_pref("browser.newtabpage.activity-stream.telemetry", false); | |
| 60 | - | user_pref("browser.newtabpage.activity-stream.feeds.telemetry", false); | |
| 61 | - | ||
| 62 | - | // ------------------------------------------------------------------- | |
| 63 | - | // Studies, experiments, Pocket | |
| 64 | - | // ------------------------------------------------------------------- | |
| 65 | - | user_pref("app.shield.optoutstudies.enabled", false); | |
| 66 | - | user_pref("app.normandy.enabled", false); | |
| 67 | - | user_pref("app.normandy.api_url", ""); | |
| 68 | - | user_pref("extensions.pocket.enabled", false); | |
| 69 | - | user_pref("extensions.pocket.api", ""); | |
| 70 | - | user_pref("extensions.pocket.site", ""); | |
| 71 | - | ||
| 72 | - | // ------------------------------------------------------------------- | |
| 73 | - | // Privacy defaults | |
| 74 | - | // ------------------------------------------------------------------- | |
| 75 | - | user_pref("browser.contentblocking.category", "strict"); | |
| 76 | - | user_pref("privacy.donottrackheader.enabled", true); | |
| 77 | - | user_pref("privacy.globalprivacycontrol.enabled", true); | |
| 78 | - | user_pref("browser.formfill.enable", false); | |
| 79 | - | user_pref("signon.rememberSignons", false); // browser is not a password manager | |
| 80 | - | user_pref("browser.safebrowsing.malware.enabled", true); // keep this on | |
| 81 | - | user_pref("browser.safebrowsing.phishing.enabled", true); | |
| 82 | - | ||
| 83 | - | // ------------------------------------------------------------------- | |
| 84 | - | // Search — DuckDuckGo default | |
| 50 | + | // Search — DuckDuckGo default; suggestions off | |
| 85 | 51 | // ------------------------------------------------------------------- | |
| 86 | 52 | user_pref("browser.search.suggest.enabled", false); | |
| 87 | 53 | user_pref("browser.urlbar.suggest.searches", false); | |
| @@ -90,6 +56,14 @@ | |||
| 90 | 56 | user_pref("browser.urlbar.trending.featureGate", false); | |
| 91 | 57 | user_pref("browser.urlbar.weather.featureGate", false); | |
| 92 | 58 | ||
| 59 | + | // ------------------------------------------------------------------- | |
| 60 | + | // Privacy defaults not covered by enterprise policy | |
| 61 | + | // ------------------------------------------------------------------- | |
| 62 | + | user_pref("browser.contentblocking.category", "strict"); | |
| 63 | + | user_pref("privacy.donottrackheader.enabled", true); | |
| 64 | + | user_pref("privacy.globalprivacycontrol.enabled", true); | |
| 65 | + | user_pref("browser.formfill.enable", false); | |
| 66 | + | ||
| 93 | 67 | // ------------------------------------------------------------------- | |
| 94 | 68 | // Miscellany — reduce noise | |
| 95 | 69 | // ------------------------------------------------------------------- |
| @@ -1,7 +1,7 @@ | |||
| 1 | 1 | /* | |
| 2 | - | * Alloy Floorp chrome — Helium-style ultra-compact horizontal, Flatwhite-adjacent | |
| 2 | + | * Alloy Firefox chrome — Helium-style ultra-compact horizontal, Flatwhite-adjacent | |
| 3 | 3 | * | |
| 4 | - | * Applies Alloy's light-mode tokens (see docs/TOKENS.md) to Floorp's chrome | |
| 4 | + | * Applies Alloy's light-mode tokens (see docs/TOKENS.md) to Firefox's chrome | |
| 5 | 5 | * and slims the tab strip, address bar, and toolbar to their smallest | |
| 6 | 6 | * legible form. No vertical tabs. No bookmarks toolbar. No title/menu bar. | |
| 7 | 7 | * | |
| @@ -43,8 +43,8 @@ | |||
| 43 | 43 | /* Bookmarks toolbar off — keyboard-driven, invoke via Ctrl-B if needed. */ | |
| 44 | 44 | #PersonalToolbar { display: none !important; } | |
| 45 | 45 | ||
| 46 | - | /* Floorp side-service bar off — no vertical UI on the side. */ | |
| 47 | - | #sidebar-box[sidebarcommand="viewFloorpNotebookSidebar"] { display: none !important; } | |
| 46 | + | /* Sidebar off — no vertical UI on the side. */ | |
| 47 | + | #sidebar-box { display: none !important; } | |
| 48 | 48 | #sidebar-splitter[hidden="false"] { display: none !important; } | |
| 49 | 49 | ||
| 50 | 50 | /* ------------------------------------------------------------------- |
| @@ -1,0 +1,54 @@ | |||
| 1 | + | { | |
| 2 | + | "policies": { | |
| 3 | + | "ExtensionSettings": { | |
| 4 | + | "uBlock0@raymondhill.net": { | |
| 5 | + | "installation_mode": "force_installed", | |
| 6 | + | "install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi", | |
| 7 | + | "default_area": "menupanel", | |
| 8 | + | "updates_disabled": false | |
| 9 | + | } | |
| 10 | + | }, | |
| 11 | + | "DisableTelemetry": true, | |
| 12 | + | "DisableFirefoxStudies": true, | |
| 13 | + | "DisablePocket": true, | |
| 14 | + | "DisableFormHistory": true, | |
| 15 | + | "DisableMasterPasswordCreation": true, | |
| 16 | + | "DisableFirefoxAccounts": false, | |
| 17 | + | "PasswordManagerEnabled": false, | |
| 18 | + | "OfferToSaveLogins": false, | |
| 19 | + | "DontCheckDefaultBrowser": true, | |
| 20 | + | "DisableProfileImport": true, | |
| 21 | + | "DisableSetDesktopBackground": true, | |
| 22 | + | "NetworkPrediction": false, | |
| 23 | + | "SearchSuggestEnabled": false, | |
| 24 | + | "PromptForDownloadLocation": false, | |
| 25 | + | "NewTabPage": false, | |
| 26 | + | "FirefoxHome": { | |
| 27 | + | "Search": true, | |
| 28 | + | "TopSites": false, | |
| 29 | + | "SponsoredTopSites": false, | |
| 30 | + | "Highlights": false, | |
| 31 | + | "Pocket": false, | |
| 32 | + | "SponsoredPocket": false, | |
| 33 | + | "Snippets": false, | |
| 34 | + | "Locked": true | |
| 35 | + | }, | |
| 36 | + | "UserMessaging": { | |
| 37 | + | "WhatsNew": false, | |
| 38 | + | "ExtensionRecommendations": false, | |
| 39 | + | "FeatureRecommendations": false, | |
| 40 | + | "UrlbarInterventions": false, | |
| 41 | + | "SkipOnboarding": true, | |
| 42 | + | "MoreFromMozilla": false, | |
| 43 | + | "Locked": true | |
| 44 | + | }, | |
| 45 | + | "OverrideFirstRunPage": "", | |
| 46 | + | "OverridePostUpdatePage": "", | |
| 47 | + | "EnableTrackingProtection": { | |
| 48 | + | "Value": true, | |
| 49 | + | "Locked": false, | |
| 50 | + | "Cryptomining": true, | |
| 51 | + | "Fingerprinting": true | |
| 52 | + | } | |
| 53 | + | } | |
| 54 | + | } |