Files
dotfiles/modules/desktop/firefox.nix
alexion eca87c74a6 fix(firefox): scale the browser to 1.25x on the high-DPI panel
Left at auto, Firefox reads the panel's 1.5x and inflates its whole
chrome while point-sized apps stay put. Pin devPixelsPerPx a shade under
that so the UI and pages match without dropping to a too-small 1:1.
2026-07-24 14:47:49 -04:00

132 lines
5.2 KiB
Nix

{ config, lib, ... }:
# Firefox as the desktop browser: stock mainline, hardened and de-monetized by policy.
let
cfg = config.modules.desktop.firefox;
user = config.user.name;
# A force-installed extension, keyed at the call site by the add-on's own id.
# Firefox fetches the signed add-on from Mozilla's site and enables it automatically.
forceInstalled = slug: {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/${slug}/latest.xpi";
installation_mode = "force_installed";
};
in
{
options.modules.desktop.firefox.enable = lib.mkEnableOption "Firefox as the desktop browser";
config = lib.mkIf cfg.enable {
home-manager.users.${user} = hm: {
programs.firefox = {
enable = true;
# Enterprise policies: enforced and unchangeable from the browser UI.
policies = {
DisableTelemetry = true;
DisableFirefoxStudies = true;
DisablePocket = true;
OfferToSaveLogins = false;
DontCheckDefaultBrowser = true;
DisableFirefoxAccounts = true;
# Strip the monetized surfaces from the new-tab page.
FirefoxHome = {
SponsoredTopSites = false;
SponsoredPocket = false;
Snippets = false;
};
# An ad and content blocker, the operator's password manager, and a
# video sponsor-skipper. All three are self-contained web extensions.
ExtensionSettings = {
"uBlock0@raymondhill.net" = forceInstalled "ublock-origin";
"78272b6fa58f4a1abaac99321d503a20@proton.me" = forceInstalled "proton-pass";
"sponsorBlocker@ajay.app" = forceInstalled "sponsorblock";
};
};
profiles.default = {
isDefault = true;
# The Nord chrome theme is a declared extension setting, so home-manager
# owns the extension-settings store, overwriting runtime changes to it.
extensions.force = true;
# Stylix's Nord mapping paints the selected address-bar result a
# near-white grey, leaving its light text unreadable. Darken that one
# highlight to the Nord selection grey, from the same scheme.
extensions.settings."FirefoxColor@mozilla.com".settings.theme.colors.popup_highlight =
let
c = hm.config.lib.stylix.colors;
in
lib.mkForce {
r = c."base03-rgb-r";
g = c."base03-rgb-g";
b = c."base03-rgb-b";
};
settings = {
# Scale the UI and page by a fixed factor. Left at auto (-1),
# Firefox reads the panel's 1.5x and inflates its whole chrome on
# this display while point-sized apps stay put; a shade under that
# brings it into line without dropping to true 1:1, which reads too
# small at this DPI.
"layout.css.devPixelsPerPx" = "1.25";
# Auto-enable the sideloaded Firefox Color add-on that carries the
# Nord chrome theme, which Firefox otherwise leaves disabled.
# The functional extensions come through policy and are unaffected.
"extensions.autoDisableScopes" = 0;
# Sponsored surfaces the policies above do not reach.
"browser.urlbar.suggest.quicksuggest.sponsored" = false;
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
};
search = {
# Declaring search overwrites Firefox's own engine list wholesale,
# so engines added later in the UI do not survive a rebuild.
force = true;
default = "ddg";
# The general-purpose commercial engines, hidden to leave a lean
# DuckDuckGo-and-Wikipedia list. They stay reachable through bangs.
# An engine carrying only metaData is treated as a builtin.
engines = {
google.metaData.hidden = true;
bing.metaData.hidden = true;
ebay.metaData.hidden = true;
"amazondotcom-us".metaData.hidden = true;
};
order = [ "ddg" ];
};
};
};
# Nord chrome from the shared Stylix scheme, against the one profile.
# colorTheme recolours the toolbar and tabs, which the target does not do
# on its own, through the Stylix-managed Firefox Color add-on.
stylix.targets.firefox = {
enable = true;
profileNames = [ "default" ];
colorTheme.enable = true;
};
# Links opened from other applications land in Firefox.
xdg.mimeApps = {
enable = true;
defaultApplications = {
"text/html" = "firefox.desktop";
"application/xhtml+xml" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
};
};
# Firefox writes profiles.ini itself on first launch, so home-manager is
# told to own the file rather than fail activation refusing to clobber it.
home.file."${hm.config.programs.firefox.configPath}/profiles.ini".force = true;
};
};
}