Community-driven Nix Flake for the Zen browser https://zen-browser-flake.nshard.com
  • Nix 98.6%
  • JavaScript 1%
  • Shell 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Luis Quiñones c495e98991
test: wait on observable state instead of fixed sleeps (#400)
Xvfb startups wait for the /tmp/.X11-unix/X99 socket, and browser
shutdowns wait until no zen process is left. sine-mods waits for the
aggregated chrome.css and the probe script pref in prefs.js, then polls
the screenshot until the mod paints. system-certificates waits for each
launch to reach the trusted nginx host. Polls time out after 3 minutes
by passing on the last try, so the existing asserts report the failure.
2026-10-12 19:26:52 -05:00
.github ci: add workflow to bump addon pins (#395) 2026-09-20 14:04:50 -05:00
docs feat(docs): add programs.zen-browser options site (#301) 2026-05-09 16:47:26 -05:00
examples fix(sine): resolve mod entries, seed pref defaults, disable auto-update (#366) 2026-09-20 13:19:13 -05:00
hm-module fix(sine): revalidate mods with If-None-Match instead of refetching (#396) 2026-09-20 15:34:41 -05:00
tests test: wait on observable state instead of fixed sleeps (#400) 2026-10-12 19:26:52 -05:00
tooling feat(docs): add programs.zen-browser options site (#301) 2026-05-09 16:47:26 -05:00
.gitattributes feat(docs): add programs.zen-browser options site (#301) 2026-05-09 16:47:26 -05:00
.gitignore chore: ignore local tooling files (#335) 2026-07-12 09:30:14 -05:00
CONTRIBUTORS.md chore: update contributors list (#101) 2025-08-20 12:56:37 -05:00
default.nix fix(ffmpeg): fix eval on latest nixpkgs via browser.version fake (#387) 2026-08-27 13:05:18 -05:00
flake.lock flake-update: update all inputs (#398) 2026-10-02 16:25:04 +05:00
flake.nix feat(darwin): install upstream .app unmodified by default (#361) 2026-07-27 16:30:36 -05:00
package.nix fix(certificates): register p11-kit trust module as a security device (#365) 2026-08-31 16:33:56 -05:00
sources.json chore(update): twilight @ x86_64 && aarch64 to 1.24t#1791769725 2026-10-12 02:07:01 +00:00
wrangler.jsonc feat(docs): add programs.zen-browser options site (#301) 2026-05-09 16:47:26 -05:00
wrap-zen.nix fix(ffmpeg): fix eval on latest nixpkgs via browser.version fake (#387) 2026-08-27 13:05:18 -05:00

Zen Browser

This is a nix flake for the Zen browser.

Features

A flake for Zen Browser that lets you fine-tune more than other flakes.

Installation

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".

Integration

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 Manager

{
  # 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! :)

With environment.systemPackages or home.packages

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

Start the browser

$ zen-beta # or zen-twilight

Configuration Examples

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)

Home Manager Reference

This module is based on Home Manager's mkFirefoxModule. Refer to the examples above for common patterns.

Core options:

  • enable (boolean): Enable Home Manager config
  • setAsDefaultBrowser (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.

Configuration Layers

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)

Profile Configuration

Profiles support many sub-options. See examples directory for:

Browser State Management

Note

Close Zen browser before home-manager switch if you declare:

  • Any spaces (with or without spacesForce)
  • Any pins (with or without pinsForce)
  • Any containers (with or without containersForce)
  • 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:

  1. Checks if Zen is running via lsof path/to/profile/.parentlock—skips the update with a warning (activation still succeeds) if browser is open
  2. Decompresses zen-sessions.jsonlz4 from LZ4 to JSON
  3. Modifies it with jq to apply your declared config
  4. Recompresses back to LZ4
  5. Restores backup on any failure

Browser 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.

Showcase

Here are some user configurations that showcase different setups using this flake:

1Password

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";
  };
};

Native Messaging

To enable communication between the browser and native applications, you can use the following configuration pattern.

With Home Manager

Check the Home Manager Reference.

With package override

{
  home.packages = [
    (
      inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.system}".default.override {
        nativeMessagingHosts = [pkgs.firefoxpwa];
      }
    )
  ];
}

Troubleshooting

Missing configuration after update

  1. 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.txt

    Then run zen in safe mode once and close it (it will perform the required migrations):

    # or zen-twilight
    zen-beta --safe-mode
    
  2. 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.

The requested URL returned error: 404

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.

Zen not seeing my GPU

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.

1Password constantly requires password

You may want to set policies.DisableAppUpdate = false; in your policies.json file. See #48.

Contributing

Before contributing, please make sure that your code is formatted correctly by running

$ nix fmt

LICENSE

This project is licensed under the MIT License.