{ config, lib, pkgs, ... }: # Cisco Secure Client (proprietary VPN client, successor to AnyConnect) # # Package: pkgs/cisco-secure-client — fetches the Linux pre-deployment .tgz # from archive.org and extracts the bundled .deb. # # The user can override the source by passing a different package: # work.cisco.package = pkgs.cisco-secure-client.overrideAttrs (_: { # src = /path/to/local/cisco-secure-client-linux64-5.1.17.3394-predeploy-deb-k9.tgz; # }); # # Reference: https://github.com/NixOS/nixpkgs/issues/265443 let cfg = config.work.cisco; in { options.work.cisco = { enable = lib.mkEnableOption "Cisco Secure Client" // { default = false; }; package = lib.mkOption { description = "cisco-secure-client package to use"; type = lib.types.package; default = pkgs.cisco-secure-client; defaultText = "pkgs.cisco-secure-client"; }; }; config = lib.mkIf cfg.enable { environment.systemPackages = with pkgs; [ cfg.package ]; # The vpnagentd binary has /opt/cisco/secureclient/ hardcoded for runtime # config paths (openssl.cnf, ossl-modules/). Create a symlink to the Nix store. systemd.tmpfiles.rules = [ "d /opt 0755 root root -" "L+ /opt/cisco/secureclient - - - - ${cfg.package}/cisco/secureclient" ]; # Load the tun module required by the VPN client boot.kernelModules = ["tun"]; systemd.services.cisco-vpnagentd = { description = "Cisco Secure Client VPN Agent Daemon"; # vpnagentd daemonizes itself; tracked via PID file. after = ["network-online.target" "NetworkManager.service"]; wants = ["network-online.target"]; wantedBy = ["multi-user.target"]; serviceConfig = { Type = "forking"; PIDFile = "/run/vpnagentd.pid"; # Use the wrapper (sets LD_LIBRARY_PATH) — the raw binary was restored # from backup to preserve its embedded Cisco code signature, so it has # no RPATH and needs the env var to find its bundled .so files. ExecStart = "${cfg.package}/bin/vpnagentd"; Restart = "on-failure"; RestartSec = "5"; # Minimal capability set for VPN operation CapabilityBoundingSet = [ "CAP_NET_ADMIN" "CAP_NET_RAW" "CAP_NET_BIND_SERVICE" "CAP_DAC_OVERRIDE" "CAP_SETUID" "CAP_SETGID" "CAP_CHOWN" "CAP_FOWNER" ]; AmbientCapabilities = [ "CAP_NET_ADMIN" "CAP_NET_RAW" "CAP_NET_BIND_SERVICE" "CAP_DAC_OVERRIDE" "CAP_SETUID" "CAP_SETGID" "CAP_CHOWN" "CAP_FOWNER" ]; DeviceAllow = ["/dev/net/tun rw"]; PrivateTmp = true; ProtectSystem = "full"; ProtectHome = false; NoNewPrivileges = false; }; }; }; }