This noweb document constructs a customized Firefox installation:
- I deploy firefox with settings in both
about:config
below and enterprise policies further down. userChrome.css
anduserContent.css
loaded from A Custom Firefox User Chrome- this sucked and fought with firefox sync, didn't hit the security considerations I was hoping for: Extensions are defined below and bundled in to my Nix deployments
{ config, pkgs, ... }:
{
xdg.mimeApps.enable = true;
xdg.mimeApps.defaultApplications = {
"x-scheme-handler/http" = ["firefox.desktop"];
"x-scheme-handler/https" = ["firefox.desktop"];
};
home.sessionVariables = {
GTK_USE_PORTAL = 1; # (ref:gtk-use-portal)
};
programs.firefox = {
enable = true;
package =
<<myFirefox>>;
profiles.default = {
name = "default";
isDefault = true;
settings = {
"svg.context-properties.content.enabled" = true; # (ref:svgContextProperties)
"privacy.trackingprotection.enabled" = true;
"privacy.donottrackheader.enabled" = true;
"privacy.globalprivacycontrol.enabled" = true;
"privacy.globalprivacycontrol.functionality_enabled" = true;
"reader.color_scheme" = "dark";
"mousewheel.default.delta_multiplier_x" = 1000; # horizontal scroll multiplier
# "layout.css.devPixelsPerPx" = # (ref:hidpi)
# "1.5";
# (if config.hardware.video.hidpi.enable == true then
# "1.5"
# else
# "1.0");
"browser.aboutConfig.showWarning" = false;
"browser.sessionstore.warnOnQuit" = true;
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
"toolkit.legacyUserProfileCustomizations.stylesheets" = true; # for userchrome and usercontent
"layout.css.prefers-color-scheme.content-override" = 2; # (ref:content-override)
};
userChrome = builtins.readFile ../files/userChrome.css;
userContent = builtins.readFile ../files/userContent.css;
};
};
}
- (gtk-use-portal) instructs Firefox to use the XDG Desktop Portal, and kde-base includes a Portal allowing Firefox to use e.g. KDE's file select dialogs. Very nice.
- (svgContextProperties) is used by the simple tab groups addon
- (content-override) makes follow GTK dark theme – enumerates values in overrideContentColorScheme (see also StaticPrefList.yaml h/t Snow
- I would love if (hidpi) could be set far up in My NixOS configuration per-host …
NEXT
it would be great if (hidpi) could use config.hardware.video.hidpi.enable
in My NixOS configuration.
Disabling Policies with wrapped Firefox
per the docs, we can distribute a Firefox with enterprise policies enabled; you can enable extensions here, but I enable them in my user profile instead up above.
-unwrapped {
pkgs.wrapFirefox pkgs.firefox# nixExtensions = pkgs.callPackage ./firefox {}; # (ref:extensionsImport)
extraNativeMessagingHosts = [
pkgs.plasma5Packages.plasma-browser-integration
pkgs.browserpass];
cfg = {
enableTridactylNative = true;
};
extraPolicies = {
DisableFirefoxStudies = true;
DisablePocket = true;
DisableTelemetry = true;
FirefoxHome = {
Pocket = false;
Snippets = false;
};
UserMessaging = {
ExtensionRecommendations = false;
SkipOnboarding = true;
};
OfferToSaveLoginsDefault = false;
# Handlers can be set here for org-protocol
# https://github.com/mozilla/policy-templates/blob/master/README.md#Handlers
};
}
A Custom Firefox User Chrome make sure to tangle these when they're changed!
"./firefox_user_chrome.org") (org-babel-tangle-file
Theoretically-Safe Firefox Extensions with Nix
I have this disabled right now ... it's likely easier to just use Firefox Sync for this since the XPIs are just being downloaded
So, Home Manager has the ability to manager a Firefox profile and in doing so, it can side-load extensions which are compiled and managed by Nix. Very nice.
It's recommended in the home-configuration.nix
manpage to pull firefox
addons out of Nix User
Repositories (external: NUR) but i'm not sure
i'm comfortable running NUR as an integrated part of my system, I only
want to use the minimal set of it. So my understanding of NUR's support
for Firefox addons looks like this: addons.json
provide an accessible format for machines to generate a generated-firefox-addons.nix
with a script like this generate-firefox-addons.sh
which also makes a
nixlib/firefox/default.nix
for importing
at (extensionsImport).
nix run -f "https://github.com/nix-community/NUR/archive/master.tar.gz" repos.rycee.firefox-addons-generator \
--arg pkgs 'import <nixpkgs> {}' \
-c nixpkgs-firefox-addons addons.json ./generated.nix
Regularly running shell:pushd nixlib/firefox && ./generate-firefox-addons.sh & is "praxis".
default.nix
looks like:
# Derived from: https://github.com/nix-community/nur-combined/blob/master/repos/ijohanne/pkgs/firefox-plugins/default.nix
{ pkgs ? import <nixpkgs> {} }:
let
buildFirefoxXpiAddon = { pname, url, sha256, meta, ... }: let
newMeta = if meta ? license
then meta
else meta // { license = pkgs.lib.licenses.unfree; };
in
(pkgs.fetchFirefoxAddon { inherit url sha256; name = pname; }) // { meta = newMeta;} ;
generated = pkgs.callPackage ./generated.nix { inherit buildFirefoxXpiAddon; };
in
pkgs.lib.mapAttrsToList(name: value: value)
(pkgs.lib.filterAttrs # (ref:firefox-filterAttrs)
(name: value: (name != "override") &&
(name != "overrideDerivation") &&
(name != "recurseForDerivations"))
(generated))
The most complicated part of this is the map and filter functions in
(firefox-filterAttrs)
above: programs.firefox.extensions
wants a
list, the generated addons
module returns
a set with some overrides attached to it. I just want this to rip 'em
out and map it to a list.
And here's an addons.json
specifying
some of my favorite slugs:
[
{"slug": "awesome-rss"},
{"slug": "better-timing-for-no-race"},
{"slug": "browserpass-ce"},
{"slug": "clearurls"},
{"slug": "darkreader"},
{"slug": "decentraleyes"},
{"slug": "duckduckgo-for-firefox"},
{"slug": "facebook-container"},
{"slug": "https-everywhere"},
{"slug": "laboratory-by-mozilla"},
{"slug": "leechblock-ng"},
{"slug": "multi-account-containers"},
{"slug": "plasma-integration"},
{"slug": "privacy-badger17"},
{"slug": "simple-tab-groups"},
{"slug": "smart-amazon-smile"},
{"slug": "styl-us"},
{"slug": "tab-unload-for-tree-style-tab"},
{"slug": "tampermonkey"},
{"slug": "tree-style-tab"},
{"slug": "twemex-sidebar-for-twitter"},
{"slug": "ublock-origin"},
{"slug": "wallabagger"},
{"slug": "web-scrobbler"},
{"slug": "yet-another-hints-extension"},
{"slug": "youtube-feeds"}
]
This still fetches and repackages the XPIs! I'd like to build these more and more from source … but they won't auto-update to something that'll super-own me for now. See An Undeveloped Thought on Web Extensions and the untenable position of powerful user agents below…
WAITING Add changelogs or git commits for these extensions to Universal Aggregator Software Release Feeds
- State "WAITING" from "NEXT" [2021-05-11 Tue 12:05]
An Undeveloped Thought on Web Extensions and the untenable position of powerful user agents
With regards to the security model of web extensions:
I really don't think the browser extension model is great, but I think user-agents are powerful and powerful user agents are good. There has to be a balance. It's clear that the cloud-services-as-extension model like Grammarly or even AdBlock is ripe for abuse, or change of terms, and the nature of the ecosystem is that when open source developers burn out they can turn around and sell their module to a firm with no trust, and plenty of things to scrutinize.
When subscribing to the changelogs, I see limited authorship information as well as commit patterns: if the module suddenly changes authorship or the commits change from being a very verbose style to only dumping version updates, I need to ask why before it's too late.
The NUR stuff is all based around some automation in that repo which is just managed ad-hoc by a bunch of folks as their personal playgrounds, but I think I can co-opt that and define my own extension set using the same pattern. If I developed that way, this would just be a readme in a forked NUR repo, but here we are, I want to speak through the code, sorry.
By only managing and installing the core open source extensions I
rely on, maybe I can keep myself from getting Super Owned by some extension getting
sold to some amoral surveillance apparatus, while managing the risk of
security issues injected by the relatively lax NUR
security model. The extensions I use largely
don't interact with cloud services or even update very often themselves,
and it's as easy to track the commit feeds or changelog for them in my
News feed
pipeline.