Community-driven Nix Flake for the Zen browser
See the codeThis is a nix flake for the Zen browser.
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 switch
Check 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."${pkgs.stdenv.hostPlatform.system}".default # beta
inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.system}".beta
inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.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."${pkgs.stdenv.hostPlatform.system}".twilight-official
# you can even override the package policies
inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.system}".default.override {
extraPolicies = {
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-twilight
See 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, managed storage config |
| 04b-extensions-rycee.nix | Firefox addons via rycee.nix, ext storage |
| 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, folders, space-scoped pins |
| 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.) |
| 15-joined-tabs.nix | Joined tabs configuration |
| 16-environment-variables | Environment variables (themes, etc.) |
| 17-live-folders | Live folders (Issues, etc) |
| 18-space-routing | Space routing |
| 19-extension-buttons | Extension buttons pinned to the toolbar |
| 20-sine-mods | Sine mods (Linux only) |
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.darwinDefaultsIdfirst. 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:
[!NOTE] 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- Any
extensionButtons
If you only declare simple options like policies/extensions/bookmarks, rebuilding while Zen is open is ok.
Spaces, pins, and containers are stored in zen-sessions.jsonlz4 (Mozilla LZ4 compressed JSON). The activation script:
lsof path/to/profile/.parentlock—skips the update with a warning (activation still succeeds) if browser is openBrowser must be closed because the file is locked in memory while Zen runs. With pinsForce = true, pinsForceAction (default demote) selects whether undeclared pinned or essential tabs are removed or demoted to normal tabs; with pinsForce = false, no changes are made to pins.
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."${pkgs.stdenv.hostPlatform.system}".default.override {
nativeMessagingHosts = [pkgs.firefoxpwa];
}
)
];
}
The release 1.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.txtThen 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 fmt
This project is licensed under the MIT License.
(top 24 of 43)
297 followers · starred May 2026
156 followers · starred May 2026
181 followers · starred Jul 2026
70 followers · starred May 2025
Community-driven Nix Flake for the Zen browser
See the codeThis is a nix flake for the Zen browser.
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 switch
Check 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."${pkgs.stdenv.hostPlatform.system}".default # beta
inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.system}".beta
inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.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."${pkgs.stdenv.hostPlatform.system}".twilight-official
# you can even override the package policies
inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.system}".default.override {
extraPolicies = {
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-twilight
See 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, managed storage config |
| 04b-extensions-rycee.nix | Firefox addons via rycee.nix, ext storage |
| 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, folders, space-scoped pins |
| 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.) |
| 15-joined-tabs.nix | Joined tabs configuration |
| 16-environment-variables | Environment variables (themes, etc.) |
| 17-live-folders | Live folders (Issues, etc) |
| 18-space-routing | Space routing |
| 19-extension-buttons | Extension buttons pinned to the toolbar |
| 20-sine-mods | Sine mods (Linux only) |
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.darwinDefaultsIdfirst. 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:
[!NOTE] 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- Any
extensionButtons
If you only declare simple options like policies/extensions/bookmarks, rebuilding while Zen is open is ok.
Spaces, pins, and containers are stored in zen-sessions.jsonlz4 (Mozilla LZ4 compressed JSON). The activation script:
lsof path/to/profile/.parentlock—skips the update with a warning (activation still succeeds) if browser is openBrowser must be closed because the file is locked in memory while Zen runs. With pinsForce = true, pinsForceAction (default demote) selects whether undeclared pinned or essential tabs are removed or demoted to normal tabs; with pinsForce = false, no changes are made to pins.
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."${pkgs.stdenv.hostPlatform.system}".default.override {
nativeMessagingHosts = [pkgs.firefoxpwa];
}
)
];
}
The release 1.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.txtThen 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 fmt
This project is licensed under the MIT License.
(top 24 of 43)
297 followers · starred May 2026
156 followers · starred May 2026
181 followers · starred Jul 2026
70 followers · starred May 2025