This is a nix flake for the Zen browser.
- Linux and macOS support
- Available for x86_64 and aarch64
- Support for twilight and beta
- Policies can be modified via Home Manager and unwrapped package override
- Fast & Automatic updates via GitHub Actions
- Browser update checks are disabled by default
- The default twilight version is reliable and reproducible
- Declarative [Work]Spaces (including themes, icons, containers)
- Declarative keyboard shortcuts with version protection
- Declarative mods installation from Zen theme store
A flake for Zen Browser that lets you fine-tune more than other flakes.
Just add it to your NixOS flake.nix or home-manager:
inputs = {
zen-browser = {
url = "github:0xc000022070/zen-browser-flake";
inputs = {
# IMPORTANT: To ensure compatibility with the latest Firefox version, use nixpkgs-unstable.
nixpkgs.follows = "nixpkgs";
home-manager.follows = "home-manager";
};
};
# ...
}Note
Beta Branch: To keep the flake input only sync with beta updates, use
inputs.zen-browser.url = "github:0xc000022070/zen-browser-flake/beta".
Important
Use the twilight package to guarantee reproducibility, the artifacts of that package are re-uploaded to this repository. However, if you don't agree with that and want to use the official artifacts, use twilight-official.
{
# home.nix
imports = [
inputs.zen-browser.homeModules.beta
# or inputs.zen-browser.homeModules.twilight
# or inputs.zen-browser.homeModules.twilight-official
];
programs.zen-browser = {
enable = true;
setAsDefaultBrowser = true;
};
}Then build your Home Manager configuration
$ home-manager switchCheck the Home Manager Reference and my rice here! :)
To integrate Zen Browser into your NixOS/Home Manager configuration, add the
following to your environment.systemPackages or home.packages:
# options are: 'x86_64-linux', 'aarch64-linux' and 'aarch64-darwin'
inputs.zen-browser.packages."${system}".default # beta
inputs.zen-browser.packages."${system}".beta
inputs.zen-browser.packages."${system}".twilight
# IMPORTANT: this package relies on the twilight release artifacts from the
# official zen repo and those artifacts are always replaced, causing hash mismatch
inputs.zen-browser.packages."${system}".twilight-official
# you can even override the package policies
inputs.zen-browser.packages."${system}".default.override {
policies = {
DisableAppUpdate = true;
DisableTelemetry = true;
# more and more
};
}Afterwards you can just build your configuration
$ sudo nixos-rebuild switch # or home-manager switch$ zen-beta # or zen-twilightSee the examples/ directory for standalone configuration examples:
| Example | Description |
|---|---|
| 01-basic-home-manager.nix | Minimal Home Manager setup |
| 02-policies-configuration.nix | System policies (policies.json) |
| 02a-policies-preferences.nix | Locked preferences (policies.Preferences) |
| 02b-settings-preferences.nix | User settings (profiles.*.settings) |
| 03-policies-package-override.nix | Package-level policy override |
| 04-extensions.nix | Firefox addons |
| 04b-extensions-rycee.nix | Firefox addons via rycee.nix |
| 05-mods-installation.nix | Zen theme store mods |
| 06-search-engines.nix | Custom search engines |
| 07-bookmarks.nix | Bookmark organization |
| 08-containers.nix | Multi-container setup |
| 09-spaces-themes.nix | Spaces with themes |
| 10-pinned-tabs.nix | Pinned tabs and folders |
| 11-keyboard-shortcuts.nix | Keyboard shortcut overrides |
| 12-userchrome-css.nix | userChrome CSS customization |
| 13-complete-setup.nix | Full real-world configuration |
| 14-native-messaging.nix | Native messaging hosts (1Password, etc.) |
This module is based on Home Manager's mkFirefoxModule. Refer to the examples above for common patterns.
Core options:
enable(boolean): Enable Home Manager configsetAsDefaultBrowser(boolean): Set Zen as default for URLs and file types
Important
macOS users need to configure programs.zen-browser.darwinDefaultsId first.
See home-manager options.
Three distinct configuration layers, stored differently:
| Layer | File | Storage | User Can Override |
|---|---|---|---|
| System Policies | 02-policies-configuration.nix | policies.json | No (enforced) |
| Locked Preferences | 02a-policies-preferences.nix | policies.json | No (enforced) |
| User Settings | 02b-settings-preferences.nix | prefs.js | Yes (defaults) |
Profiles support many sub-options. See examples directory for:
- Extensions: 04-extensions.nix, 04b-extensions-unfree.nix (rycee's NUR)
- Mods: 05-mods-installation.nix (Zen theme store)
- Search: 06-search-engines.nix (custom search shortcuts)
- Bookmarks: 07-bookmarks.nix
- Containers: 08-containers.nix
- Spaces: 09-spaces-themes.nix with custom gradient themes
- Pinned Tabs: 10-pinned-tabs.nix with folder grouping
- Keyboard Shortcuts: 11-keyboard-shortcuts.nix
- userChrome.css: 12-userchrome-css.nix
[!CRITICAL] Close Zen browser before
home-manager switchif you declare:
- Any
spaces(with or withoutspacesForce)- Any
pins(with or withoutpinsForce)- Any
containers(with or withoutcontainersForce)- Any
keyboardShortcuts
If you only declare simple options like policies/extensions/bookmarks, rebuilding while Zen is open is ok, and closure won't be required.
Spaces, pins, and containers are stored in zen-sessions.jsonlz4 (Mozilla LZ4 compressed JSON). The activation script:
- Checks if Zen is running via
pgrep "zen"—exits with error if browser is open - Decompresses zen-sessions.jsonlz4 from LZ4 to JSON
- Modifies it with jq to apply your declared config
- Recompresses back to LZ4
- Restores backup on any failure
Browser must be closed because the file is locked in memory while Zen runs. The *Force options just control whether undeclared items are deleted—the state modification happens either way.
Here are some user configurations that showcase different setups using this flake:
Zen has to be manually added to the list of browsers that 1Password will
communicate with. See this wiki article
for more information. To enable 1Password integration, you need to add the
browser identifier to the file /etc/1password/custom_allowed_browsers.
environment.etc = {
"1password/custom_allowed_browsers" = {
text = ''
.zen-wrapped
''; # or just "zen" if you use unwrapped package
mode = "0755";
};
};To enable communication between the browser and native applications, you can use the following configuration pattern.
Check the Home Manager Reference.
{
home.packages = [
(
inputs.zen-browser.packages."${system}".default.override {
nativeMessagingHosts = [pkgs.firefoxpwa];
}
)
];
}-
The release 18.18.6b changed the configuration location. Please move your configuration from ~/.zen to ~/.config/zen and restart the browser
mkdir -p ~/.config/zen mv ~/.zen/* ~/.config/zen/ rmdir ~/.zen
Then change every occurrence of ".zen" to ".config/zen" in:
.config/zen/<profile_name>/extensions.json.config/zen/<profile_name>/pkcs11.txt.config/zen/<profile_name>/chrome_debugger_profile/pkcs11.txt
Then run zen in safe mode once and close it (it will perform the required migrations):
# or zen-twilight zen-beta --safe-mode -
Please check that you're using the wrapped version of the package. The -unwrapped variants should not be used directly. Instead, they should be wrapped with wrapFirefox or custom wrappers.
Alternatively, you can review this discussion in the official Zen Browser repository.
This usually happens when the Zen team deletes a beta release from the official repository. They do this to keep only stable artifacts available. See #105 and #112 for further context.
You can either revert your nix input update or wait until CI refreshes sources.json.
Make sure that you update your flake.lock as to sync up nixpkgs version. Or make
zen follow your system nixpkgs by using inputs.nixpkgs.follows = "nixpkgs"
(assuming your nixpkgs input is named nixpkgs).
Check No WebGL context for details.
You may want to set policies.DisableAppUpdate = false; in your policies.json
file. See #48.
Before contributing, please make sure that your code is formatted correctly by running
$ nix fmtThis project is licensed under the MIT License.