1 { config, lib, pkgs, ... }:
6 cfg = config.services.pppd;
15 enable = mkEnableOption "pppd";
17 package = mkPackageOption pkgs "ppp" { };
21 description = "pppd peers.";
22 type = types.attrsOf (types.submodule (
30 description = "Name of the PPP peer.";
37 description = "Whether to enable this PPP peer.";
40 autostart = mkOption {
44 description = "Whether the PPP session is automatically started at boot time.";
50 description = "pppd configuration for this peer, see the pppd(8) man page.";
59 enabledConfigs = filter (f: f.enable) (attrValues cfg.peers);
62 name = "ppp/peers/${peerCfg.name}";
63 value.text = peerCfg.config;
66 mkSystemd = peerCfg: {
67 name = "pppd-${peerCfg.name}";
69 restartTriggers = [ config.environment.etc."ppp/peers/${peerCfg.name}".source ];
70 before = [ "network.target" ];
71 wants = [ "network.target" ];
72 after = [ "network-pre.target" ];
74 # pppd likes to write directly into /var/run. This is rude
75 # on a modern system, so we use libredirect to transparently
76 # move those files into /run/pppd.
77 LD_PRELOAD = "${pkgs.libredirect}/lib/libredirect.so";
78 NIX_REDIRECTS = "/var/run=/run/pppd";
89 ExecStart = "${getBin cfg.package}/sbin/pppd call ${peerCfg.name} nodetach nolog";
93 AmbientCapabilities = capabilities;
94 CapabilityBoundingSet = capabilities;
95 KeyringMode = "private";
96 LockPersonality = true;
97 MemoryDenyWriteExecute = true;
98 NoNewPrivileges = true;
101 ProtectControlGroups = true;
103 ProtectHostname = true;
104 ProtectKernelModules = true;
105 # pppd can be configured to tweak kernel settings.
106 ProtectKernelTunables = false;
107 ProtectSystem = "strict";
109 RestrictAddressFamilies = [
120 RestrictNamespaces = true;
121 RestrictRealtime = true;
122 RestrictSUIDSGID = true;
123 SecureBits = "no-setuid-fixup-locked noroot-locked";
124 SystemCallFilter = "@system-service";
125 SystemCallArchitectures = "native";
127 # All pppd instances on a system must share a runtime
128 # directory in order for PPP multilink to work correctly. So
129 # we give all instances the same /run/pppd directory to store
132 # For the same reason, we can't set PrivateUsers=true, because
133 # all instances need to run as the same user to access the
134 # multilink database.
135 RuntimeDirectory = "pppd";
136 RuntimeDirectoryPreserve = true;
138 wantedBy = mkIf peerCfg.autostart [ "multi-user.target" ];
142 etcFiles = listToAttrs (map mkEtc enabledConfigs);
143 systemdConfigs = listToAttrs (map mkSystemd enabledConfigs);
146 environment.etc = etcFiles;
147 systemd.services = systemdConfigs;