NixOS packaging for Portmaster — the free and open-source application firewall by Safing.
This flake builds Portmaster v2.1.7 from source (Go core + Rust/Tauri desktop + Angular UI) and provides a NixOS module with full systemd integration and security hardening.
| Project | safing/portmaster |
| License | AGPL-3.0 |
| Tracked | GitHub releases |
For long-form references beyond the README sections below, see:
docs/ARCHITECTURE.md— directory layout, component boundaries (Go core / Tauri desktop / Angular UI), NixOS-specific patches cataloguedocs/BUILD.md— operator commands: dev shell, formatters, hooks, tests, update contract, troubleshootingdocs/OPTIONS.md— fullservices.portmaster.*option referencedocs/upstream-issue-draft.md— draft of the upstream issue for nixpkgs upstreaming
| Component | Technology | Description |
|---|---|---|
portmaster-core |
Go | Firewall engine — DNS resolver, network filter, threat intelligence |
portmaster (desktop) |
Rust / Tauri | Native desktop app with system tray integration |
portmaster-ui |
Angular | Web UI served by the core at 127.0.0.1:817 |
Add as a flake input:
{
inputs.portmaster = {
url = "github:Daaboulex/portmaster-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
}Then add the overlay:
nixpkgs.overlays = [ inputs.portmaster.overlays.default ];Import the NixOS module:
imports = [ inputs.portmaster.nixosModules.default ];# flake.nix
inputs.portmaster = {
url = "github:daaboulex/portmaster-nix";
inputs.nixpkgs.follows = "nixpkgs";
};nixpkgs.overlays = [
inputs.portmaster.overlays.default
];imports = [
inputs.portmaster.nixosModules.default
];services.portmaster = {
enable = true;
notifier.enable = true; # System tray icon (autostart on login)
# autostart = true; # Start service on boot (default: true)
# settings.devmode = true; # Web UI at 127.0.0.1:817 (default: true)
# extraArgs = [ "--verbose" ];
};| Option | Type | Default | Description |
|---|---|---|---|
services.portmaster.enable |
bool | false |
Enable Portmaster firewall service |
services.portmaster.package |
package | pkgs.portmaster |
Portmaster package to use |
services.portmaster.autostart |
bool | true |
Start service on boot. When false, the service is installed but must be started manually with sudo systemctl start portmaster |
services.portmaster.notifier.enable |
bool | false |
XDG autostart for the system tray icon. Only launches if the service is active |
services.portmaster.notifier.delay |
int | 3 |
Seconds to wait before launching the tray icon (lets the desktop system tray initialize) |
services.portmaster.settings |
attrs | {} |
Freeform settings passed to portmaster-core |
services.portmaster.settings.devmode |
bool | true |
Enable web UI at 127.0.0.1:817 |
services.portmaster.extraArgs |
list of str | [] |
Extra CLI arguments for portmaster-core |
- System service:
portmaster.service— runsportmaster-coreas root with proper capabilities and systemd hardening - Desktop app:
portmasterbinary with.desktopfile — launch from your application menu - System tray: Optional XDG autostart entry (via
notifier.enable) — starts in background/tray-only mode, checks that the service is running before launching - Web UI: Available at
http://127.0.0.1:817whendevmodeis enabled - Data directory:
/var/lib/portmaster/— managed viasystemd-tmpfiles - Kernel module:
netfilter_queue— loaded automatically for packet filtering
When autostart = false, Portmaster doesn't start on boot but is still fully installed:
sudo systemctl start portmaster # Start the firewall
sudo systemctl stop portmaster # Stop the firewall
sudo systemctl status portmaster # Check statusThe notifier tray icon (if enabled) will silently skip launching when the service isn't running — no "Connection refused" popup.
On NixOS, every system rebuild generates new Nix store hashes, changing all binary paths. Without intervention, Portmaster treats each rebuild as a new application and creates a fresh profile — losing all per-app firewall rules.
This package includes a nix_linux.go tag handler (following the same pattern as the upstream Flatpak handler) that creates a stable nix-pkg tag from the derivation name and binary name. Profiles match on this tag instead of the volatile store path, so per-app rules persist across rebuilds.
The Tauri desktop app hardcodes FHS paths (/usr/bin/systemctl, /usr/bin/pkexec) that don't exist on NixOS. This package patches them at build time:
| Upstream path | NixOS path | Purpose |
|---|---|---|
/sbin/systemctl et al. |
${systemd}/bin/systemctl |
Service status detection |
/usr/bin/pkexec |
/run/wrappers/bin/pkexec |
Polkit privilege elevation (SUID wrapper) |
/usr/bin/gksudo |
/run/wrappers/bin/gksudo |
Fallback privilege elevation |
Without these patches, the desktop app cannot detect whether portmaster.service is running, and the "Start Service" button in the splash screen doesn't work.
x86_64-linux and aarch64-linux. The upstream Go and Rust code is architecture-independent, and both architectures have been verified to build.
If you previously used the v1 packaging (binary fetch + self-update approach):
- Stop the old service:
sudo systemctl stop portmaster-core - Back up your config:
sudo cp -r /opt/safing/portmaster/config /tmp/portmaster-config-backup - Rebuild with the new flake (this creates
/var/lib/portmaster/) - Optionally restore config:
sudo cp -r /tmp/portmaster-config-backup/* /var/lib/portmaster/config/ - Clean up old data:
sudo rm -rf /opt/safing/portmaster
Note: v2 databases are not backward-compatible with v1. Threat intelligence and DNS cache will be re-downloaded automatically.
- Safing GmbH — Portmaster developers
- NixOS/nixpkgs#264454 by WitteShadovv — earlier v1 packaging effort that informed this from-source build approach
git clone https://github.com/Daaboulex/portmaster-nix
cd portmaster-nix
nix develop # enter dev shell, installs pre-commit hooks
nix fmt # format flake + module + package
nix flake check --no-build # eval check
nix build .#portmaster-core # Go core only
nix build .#portmaster-ui # Angular static bundle
nix build .#portmaster # composed Tauri desktop + core + UI
./result/bin/portmaster --versionCI runs the same chain twice weekly via .github/workflows/update.yml. See docs/BUILD.md for the full operator reference (update contract, troubleshooting, manual service control).
See docs/OPTIONS.md for the full options reference.
The Nix packaging code is MIT licensed. Upstream Portmaster is AGPL-3.0 by Safing GmbH.
Maintained as part of the Daaboulex NixOS ecosystem.