Problems starting wireguard device in user service

Hello all

I’m trying to establish a user service which has to create a wireguard tunnel to get access to company network. The service is created through a derivation of proprietary software using the offical deb-file. The derivation is straight forward:

{
  pkgs,
  ...
}:

pkgs.stdenv.mkDerivation rec {
  pname = "banyan-wireguard-service";
  version = "3.28.0";

  src = pkgs.fetchurl {
    url = "https://www.banyanops.com/app/releases/banyanapp_3.28.0_amd64.deb";
    hash = "sha256-CZQHeagMFYTPsdsF4QkQ8zlvXIO8AyezxCs1yMz9+l4=";
  };

  nativeBuildInputs = [
    pkgs.dpkg
  ];

  installPhase = ''
    mkdir $out
    cp -r . $out
  '';
}

The service registration in my nix-file looks like this:

systemd.user.services.bwgs = {
    enable = true;
    wantedBy = [ "multi-user.target" ];
    unitConfig = {
      Description = "bwgs";
      After = [
        "network.target"
        "network-online.target"
      ];
    };
    serviceConfig = {
      WorkingDirectory = "${banyan-wireguard-service}/opt/Banyan";
      LimitNOFILE = 65536;
      Type = "simple";
      Restart = "on-failure";
      ExecStart = "${banyan-wireguard-service}/opt/Banyan/resources/bin/banyanwgs";
      ExecStopPost = "${banyan-wireguard-service}/opt/Banyan/resources/bin/banyanwgs stop-service";
      StandardOutput = "journal";
      StandardError = "journal";
      LogLevelMax = "debug";
      Nice = 10;
      Environment = [
        "BANYAN_DIR=/var/log/banyan"
        "com_banyanops_app=banyan-platform"
        "com_banyanops_servicename=bwgs"
        "com_banyanops_servicetype=visibility"
      ];
    };
  };

Other relevant lines in my nix-file are the following:

networking.wireguard.enable = true;
networking.firewall.enable = false; # be sure the firewall is not blocking

environment.systemPackages = with pkgs; [
    ...
    wireguard-tools
    ...
  ];

After the service is started the following lines are written to the log:

[2025/12/16 23:11:36 CET] [INFO] (main.StartTunnel:80) BanyanWGS version:3.28.0, StartTunnel interface:wg0 port:8119

[2025/12/16 23:11:36 CET] [INFO] (main.(*excludeDomainStore).RestoreExcDomains:77) config file not present

[2025/12/16 23:11:36 CET] [INFO] (main.(*provider).CreateWg:185) Creating WireGuard device

[2025/12/16 23:11:36 CET] [EROR] (main.createUSWGTun:227) Attempt to create userspace tunnel interface failed, sleep for 5 secs: device name wg0, err operation not permitted

[2025/12/16 23:11:41 CET] [EROR] (main.createUSWGTun:227) Attempt to create userspace tunnel interface failed, sleep for 5 secs: device name wg0, err operation not permitted

[2025/12/16 23:11:46 CET] [EROR] (main.createUSWGTun:227) Attempt to create userspace tunnel interface failed, sleep for 5 secs: device name wg0, err operation not permitted

[2025/12/16 23:11:51 CET] [EROR] (main.createUSWGTun:227) Attempt to create userspace tunnel interface failed, sleep for 5 secs: device name wg0, err operation not permitted

[2025/12/16 23:11:56 CET] [EROR] (main.createUSWGTun:227) Attempt to create userspace tunnel interface failed, sleep for 5 secs: device name wg0, err operation not permitted

[2025/12/16 23:12:01 CET] [INFO] (main.(*provider).lockedCreateWg:239) Tunnel interface creation failed, deviceName wg0, err operation not permitted

[2025/12/16 23:12:01 CET] [EROR] (main.(*provider).CreateWg:189) Failed to create wg0: operation not permitted

My user is member of the following groups:

users
wheel

Does anybody has a hint or knows what’s missing?

Any help is highly appreciated!

cheers,
daprodigy

Prodigy, huh?

Well, I’m no prodigy, but if this service requires wireguard-tools to do its thing, you should try adding wireguard-tools to systemd.user.services.bwgs.path instead of (or in addition to, if you also want those tools for yourself) environment.systemPackages. I don’t know if that’s the actual problem, though.

Thanks for your hint.

Changed the service configuration:

systemd.user.services.bwgs = {
    enable = true;
    path = [ pkgs.wireguard-tools ];
    wantedBy = [ "multi-user.target" ];
    unitConfig = {
      Description = "bwgs";
      After = [
        "network.target"
        "network-online.target"
      ];
    };
    serviceConfig = {
      WorkingDirectory = "${banyan-wireguard-service}/opt/Banyan";
      LimitNOFILE = 65536;
      Type = "simple";
      Restart = "on-failure";
      ExecStart = "${banyan-wireguard-service}/opt/Banyan/resources/bin/banyanwgs";
      ExecStopPost = "${banyan-wireguard-service}/opt/Banyan/resources/bin/banyanwgs stop-service";
      StandardOutput = "journal";
      StandardError = "journal";
      LogLevelMax = "debug";
      Nice = 10;
      Environment = [
        "BANYAN_DIR=/var/log/banyan"
        "com_banyanops_app=banyan-platform"
        "com_banyanops_servicename=bwgs"
        "com_banyanops_servicetype=visibility"
      ];
    };
  };

Resulting service-file:

[Unit]
After=network.target
After=network-online.target
Description=bwgs

[Service]
Environment="LOCALE_ARCHIVE=/nix/store/9vmxdn26pggj3glazmb68vhcf4smflvz-glibc-locales-2.40-66/lib/locale/locale-archive"
Environment="PATH=/nix/store/9s7agi8digrq7c86670yq3rl64xv9pls-wireguard-tools-1.0.20250521/bin:/nix/store/imad8dvhp77h0pjbckp6wvmnyhp8dpgg-coreutils-9.8/bin:/nix/store/av4xw9f56xlx5pgv862wabfif6m1yc0a-findutils-4.10.0/bin:/nix/store/x3zjxxz8m4ki88axp0gn8q8m6bldybba-gnugrep-3.12/bin:/nix/store/drc7kang929jaza6cy9zdx10s4gw1z5p-gnused-4.9/bin:/nix/store/zf8qy81dsw1vqwgh9p9n2h40s1k0g2l1-systemd-258.2/bin:/nix/store/9s7agi8digrq7c86670yq3rl64xv9pls-wireguard-tools-1.0.20250521/sbin:/nix/store/imad8dvhp77h0pjbckp6wvmnyhp8dpgg-coreutils-9.8/sbin:/nix/store/av4xw9f56xlx5pgv862wabfif6m1yc0a-findutils-4.10.0/sbin:/nix/store/x3zjxxz8m4ki88axp0gn8q8m6bldybba-gnugrep-3.12/sbin:/nix/store/drc7kang929jaza6cy9zdx10s4gw1z5p-gnused-4.9/sbin:/nix/store/zf8qy81dsw1vqwgh9p9n2h40s1k0g2l1-systemd-258.2/sbin"
Environment="TZDIR=/nix/store/xaa75rd44q62nc9mrbvym9d1m6gy0fj8-tzdata-2025b/share/zoneinfo"
Environment=BANYAN_DIR=/var/log/banyan
Environment=com_banyanops_app=banyan-platform
Environment=com_banyanops_servicename=bwgs
Environment=com_banyanops_servicetype=visibility
ExecStart=/nix/store/l3g9d4bfrmg7v2kb4gablxwg2lr9h63m-banyan-wireguard-service-3.28.0/opt/Banyan/resources/bin/banyanwgs
ExecStopPost=/nix/store/l3g9d4bfrmg7v2kb4gablxwg2lr9h63m-banyan-wireguard-service-3.28.0/opt/Banyan/resources/bin/banyanwgs stop-service
LimitNOFILE=65536
LogLevelMax=debug
Nice=10
Restart=on-failure
StandardError=journal
StandardOutput=journal
Type=simple
WorkingDirectory=/nix/store/l3g9d4bfrmg7v2kb4gablxwg2lr9h63m-banyan-wireguard-service-3.28.0/opt/Banyan

[Install]
WantedBy=multi-user.target

Still get the error:

[2025/12/17 21:17:34 CET] [EROR] (main.createUSWGTun:227) Attempt to create userspace tunnel interface failed, sleep for 5 secs: device name wg0, err operation not permitted

Turns out this service has to be started as system-service. By bad …

Added sudo and wireguard-tools to the services path and added the wireguard kernel module.

Now, the service tries to bring up wg0 and fails with the following lines in the log:

[2025/12/20 10:52:18 CET] [INFO] (main.DelTunnelsFromSavedConfig:578) Deleting any lingering configs using config file, some errors might be seen as some configs are removed by OS when the application exits
[2025/12/20 10:52:18 CET] [INFO] (main.DelTunnelsFromSavedConfig:583) The bwgsconfig file is not present, skipping deletion
[2025/12/20 10:52:18 CET] [INFO] (main.StartTunnel:80) BanyanWGS version:3.28.0, StartTunnel interface:wg0 port:8119
[2025/12/20 10:52:18 CET] [INFO] (main.(*excludeDomainStore).RestoreExcDomains:77) config file not present
[2025/12/20 10:52:18 CET] [INFO] (main.(*provider).CreateWg:185) Creating WireGuard device
[2025/12/20 10:52:18 CET] [EROR] (main.(*provider).CreateWg:195) Failed to bring UP wg0: exit status 1
[2025/12/20 10:52:18 CET] [EROR] (main.StartTunnel:96) Creation of tunnel interface: wg0 failed, err: exit status 1
[2025/12/20 10:52:18 CET] [EROR] (main.main:249) exit status 1
[2025/12/20 10:52:18 CET] [INFO] (main.DelTunnelsFromSavedConfig:578) Deleting any lingering configs using config file, some errors might be seen as some configs are removed by OS when the application exits
[2025/12/20 10:52:18 CET] [INFO] (main.DelTunnelsFromSavedConfig:583) The bwgsconfig file is not present, skipping deletion
[2025/12/20 10:52:18 CET] [INFO] (main.deleteInterfaceAPISock:258) Deleted lingering WireGuard API sock file from previous run, file: /var/run/wireguard/wg0.sock:

I installed a debian 13 system in a vm and installed the deb-package to compare the configs and logs. The service is executing command ip as sudo to bring up wg0. In journalctl the absolute path to ip is printed out as command.

Dec 20 10:50:16 debian13 (anyanwgs)[2916]: bwgs.service: Executing: /opt/Banyan/resources/bin/banyanwgs
Dec 20 10:50:16 debian13 sudo[2939]:     root : PWD=/opt/Banyan ; USER=root ; COMMAND=/usr/sbin/ip link set dev wg0 up
Dec 20 10:50:16 debian13 sudo[2939]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
Dec 20 10:50:16 debian13 sudo[2939]: pam_unix(sudo:session): session closed for user root

Does this mean, that the execution of the command in the service is hardcoded to /usr/sbin/ip? If yes, this is certainly a problem in NixOS.

Is there a way to redirect a hardcoded command to a /nix/store path?