Context
The reference project is petrkozorezov/firefox-addons-nix, a broad AMO-to-Nix catalog flake. It fetches Firefox add-on metadata from the Mozilla Add-ons API, generates a Nix-consumable add-on catalog, exposes the catalog through an overlay, and lets Home Manager users install packaged Firefox extensions from pkgs.firefox-addons. The plan here is to create a similar independent project for this repo, but scoped to only the Firefox-family extensions used in this nixos config rather than mirroring the full public AMO catalog.
Important mechanics from that flake:
fetch-addons.py queries the Mozilla Add-ons API, filters public add-ons/current files, extracts slug/version/download URL/hash/GUID, and records metadata such as permissions, host permissions, optional permissions, payment flag, compatibility, categories, tags, EULA/privacy flags, and promoted category.
flake.nix exposes overlays.default.firefox-addons by importing the generated JSON and turning each record into an overridable derivation.
- each add-on derivation fetches the signed AMO XPI and installs it under
share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/${addonId}.xpi.
- the flake has an
allow helper for permission/metadata drift checks so consumers can fail evaluation when a new add-on release changes sensitive metadata unexpectedly.
This issue proposes creating a new repository/flake with the same useful shape, but not forking that project and not generating the full AMO catalog. The new flake should manage only the Firefox-family extensions used by this NixOS config.
Current local consumers
Current profile package lists are built from inputs.dedupe_nur.overlays.default.nur.repos.rycee.firefox-addons
Current extentions configured (ensure that its up to date when implementing):
ublock-origin
raindropio
cookie-autodelete
simplelogin
stylus
tab-stash
languagetool
violentmonkey
web-archives
tridactyl
darkreader
onepassword-password-manager
foxyproxy-standard
wappalyzer
print-edit-we
save-page-we
Design constraint: policy installs are browser-wide
Firefox/Gecko enterprise ExtensionSettings policy is not profile-scoped. If an extension is installed through policy, it applies to every profile in that browser.
That means the new flake should primarily provide package derivations and metadata. This nixos config (repo) should keep deciding profile membership through Home Manager profile package lists:
programs.<browser>.profiles.primary.extensions.packages
programs.<browser>.profiles.work.extensions.packages
programs.<browser>.profiles.ephemeral.extensions.packages
Use policy install entries only for extensions that are intentionally global across all profiles. Do not move profile-specific membership into ExtensionSettings.
Proposed new flake
Create a new repository, for example Bad3r/firefox-extensions-flake, with a curated manifest instead of a full AMO mirror.
Suggested outputs:
overlays.default: exposes pkgs.firefox-extensions.<name>.
packages.${system}: exposes every curated extension package for direct CI/build checks.
lib.buildFirefoxAddon: shared builder compatible with Home Manager extensions.packages.
lib.buildFirefoxAddonFromStore: AMO/signed-XPI builder for normal curated extensions.
lib.buildUblockOriginFromSource: source-build path for uBlock Origin.
- optional
checks.${system}: build every curated extension and verify metadata contracts.
Suggested source layout:
flake.nix
extensions.lock.json # generated AMO metadata for the curated slug list
extensions.toml/json # hand-owned allowlist and expected metadata contract
pkgs/firefox-addon.nix # generic signed-XPI builder
pkgs/ublock-origin.nix # upstream releases packaged uBO derivation
scripts/update-extensions # refresh only curated AMO records
scripts/check-metadata # fail on unexpected permission/host-permission drift
Curated update workflow
The update script should accept an explicit slug list and refresh only those add-ons through the AMO API. It should not page through the whole add-on universe.
For each curated AMO add-on, persist at least:
pname
version
url
hash
addonId
- permissions
- host permissions
- optional permissions
- license
- compatibility
- promoted category
- requires-payment flag
- EULA/privacy flags
The generated package should expose enough metadata for Home Manager and local review:
addonId at top level, because Home Manager uses it to match extension settings.
- metadata/passthru for permissions and host permissions.
- an
allow or equivalent contract checker to catch unexpected metadata changes.
uBlock Origin from source
uBlock Origin should not be fetched from AMO in the new flake. It should be packaged from upstream releases (uBlock/releases).
Source evidence from uBlock Origin repo:
Makefile target firefox builds dist/build/uBlock0.firefox.
tools/pull-assets.sh fetches uBlockOrigin/uAssets master and gh-pages into dist/build/uAssets.
tools/make-firefox.sh all copies common + Firefox platform files, generates metadata with tools/make-firefox-meta.py, and zips dist/build/uBlock0.firefox.xpi.
dist/README.md documents make firefox as the developer build path and notes that stable Firefox normally requires signature handling for XPI installation.
The Nix derivation should make the asset inputs explicit and reproducible. Prefer fixed-output fetches for both uBlock and uAssets.
Migration plan
- Create the new curated extension flake repository.
- Port the small builder pattern from
firefox-addons-nix, but keep the implementation independent rather than forking that repository.
- Add the curated extension manifest from the current profile package lists.
- Implement AMO metadata refresh for only the curated set.
- Implement release
ublock-origin from upstream uBlock.
- Add checks that build all curated packages and fail on unexpected permission/host-permission drift.
- Add the new flake as an input.
- Replace
inputs.dedupe_nur.overlays.default.nur.repos.rycee.firefox-addons usage in Gecko profile code with the new curated flake packages.
- Keep per-profile package membership in Home Manager profile package lists.
- Revisit existing policy install entries and remove any policy install that is only compensating for missing package availability.
- Keep only truly browser-wide policy entries in
ExtensionSettings.
Acceptance criteria
Related work
Context
The reference project is
petrkozorezov/firefox-addons-nix, a broad AMO-to-Nix catalog flake. It fetches Firefox add-on metadata from the Mozilla Add-ons API, generates a Nix-consumable add-on catalog, exposes the catalog through an overlay, and lets Home Manager users install packaged Firefox extensions frompkgs.firefox-addons. The plan here is to create a similar independent project for this repo, but scoped to only the Firefox-family extensions used in this nixos config rather than mirroring the full public AMO catalog.Important mechanics from that flake:
fetch-addons.pyqueries the Mozilla Add-ons API, filters public add-ons/current files, extracts slug/version/download URL/hash/GUID, and records metadata such as permissions, host permissions, optional permissions, payment flag, compatibility, categories, tags, EULA/privacy flags, and promoted category.flake.nixexposesoverlays.default.firefox-addonsby importing the generated JSON and turning each record into an overridable derivation.share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/${addonId}.xpi.allowhelper for permission/metadata drift checks so consumers can fail evaluation when a new add-on release changes sensitive metadata unexpectedly.This issue proposes creating a new repository/flake with the same useful shape, but not forking that project and not generating the full AMO catalog. The new flake should manage only the Firefox-family extensions used by this NixOS config.
Current local consumers
Current profile package lists are built from
inputs.dedupe_nur.overlays.default.nur.repos.rycee.firefox-addonsCurrent extentions configured (ensure that its up to date when implementing):
ublock-originraindropiocookie-autodeletesimpleloginstylustab-stashlanguagetoolviolentmonkeyweb-archivestridactyldarkreaderonepassword-password-managerfoxyproxy-standardwappalyzerprint-edit-wesave-page-weDesign constraint: policy installs are browser-wide
Firefox/Gecko enterprise
ExtensionSettingspolicy is not profile-scoped. If an extension is installed through policy, it applies to every profile in that browser.That means the new flake should primarily provide package derivations and metadata. This nixos config (repo) should keep deciding profile membership through Home Manager profile package lists:
programs.<browser>.profiles.primary.extensions.packagesprograms.<browser>.profiles.work.extensions.packagesprograms.<browser>.profiles.ephemeral.extensions.packagesUse policy install entries only for extensions that are intentionally global across all profiles. Do not move profile-specific membership into
ExtensionSettings.Proposed new flake
Create a new repository, for example
Bad3r/firefox-extensions-flake, with a curated manifest instead of a full AMO mirror.Suggested outputs:
overlays.default: exposespkgs.firefox-extensions.<name>.packages.${system}: exposes every curated extension package for direct CI/build checks.lib.buildFirefoxAddon: shared builder compatible with Home Managerextensions.packages.lib.buildFirefoxAddonFromStore: AMO/signed-XPI builder for normal curated extensions.lib.buildUblockOriginFromSource: source-build path for uBlock Origin.checks.${system}: build every curated extension and verify metadata contracts.Suggested source layout:
Curated update workflow
The update script should accept an explicit slug list and refresh only those add-ons through the AMO API. It should not page through the whole add-on universe.
For each curated AMO add-on, persist at least:
pnameversionurlhashaddonIdThe generated package should expose enough metadata for Home Manager and local review:
addonIdat top level, because Home Manager uses it to match extension settings.allowor equivalent contract checker to catch unexpected metadata changes.uBlock Origin from source
uBlock Origin should not be fetched from AMO in the new flake. It should be packaged from upstream releases (uBlock/releases).
Source evidence from uBlock Origin repo:
Makefiletargetfirefoxbuildsdist/build/uBlock0.firefox.tools/pull-assets.shfetchesuBlockOrigin/uAssetsmasterandgh-pagesintodist/build/uAssets.tools/make-firefox.sh allcopies common + Firefox platform files, generates metadata withtools/make-firefox-meta.py, and zipsdist/build/uBlock0.firefox.xpi.dist/README.mddocumentsmake firefoxas the developer build path and notes that stable Firefox normally requires signature handling for XPI installation.The Nix derivation should make the asset inputs explicit and reproducible. Prefer fixed-output fetches for both uBlock and uAssets.
Migration plan
firefox-addons-nix, but keep the implementation independent rather than forking that repository.ublock-originfrom upstream uBlock.inputs.dedupe_nur.overlays.default.nur.repos.rycee.firefox-addonsusage in Gecko profile code with the new curated flake packages.ExtensionSettings.Acceptance criteria
addonIdand permission metadata suitable for Home Manager profile extension use and local drift checks.profiles.<name>.extensions.packages; policy installs are used only for intentionally browser-wide extensions.Related work