at 25.11-pre 3.1 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.frp; 9 settingsFormat = pkgs.formats.toml { }; 10 configFile = settingsFormat.generate "frp.toml" cfg.settings; 11 isClient = (cfg.role == "client"); 12 isServer = (cfg.role == "server"); 13in 14{ 15 options = { 16 services.frp = { 17 enable = lib.mkEnableOption "frp"; 18 19 package = lib.mkPackageOption pkgs "frp" { }; 20 21 role = lib.mkOption { 22 type = lib.types.enum [ 23 "server" 24 "client" 25 ]; 26 description = '' 27 The frp consists of `client` and `server`. The server is usually 28 deployed on the machine with a public IP address, and 29 the client is usually deployed on the machine 30 where the Intranet service to be penetrated resides. 31 ''; 32 }; 33 34 settings = lib.mkOption { 35 type = settingsFormat.type; 36 default = { }; 37 description = '' 38 Frp configuration, for configuration options 39 see the example of [client](https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml) 40 or [server](https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml) on github. 41 ''; 42 example = { 43 serverAddr = "x.x.x.x"; 44 serverPort = 7000; 45 }; 46 }; 47 }; 48 }; 49 50 config = 51 let 52 serviceCapability = lib.optionals isServer [ "CAP_NET_BIND_SERVICE" ]; 53 executableFile = if isClient then "frpc" else "frps"; 54 in 55 lib.mkIf cfg.enable { 56 systemd.services = { 57 frp = { 58 wants = lib.optionals isClient [ "network-online.target" ]; 59 after = if isClient then [ "network-online.target" ] else [ "network.target" ]; 60 wantedBy = [ "multi-user.target" ]; 61 description = "A fast reverse proxy frp ${cfg.role}"; 62 serviceConfig = { 63 Type = "simple"; 64 Restart = "on-failure"; 65 RestartSec = 15; 66 ExecStart = "${cfg.package}/bin/${executableFile} --strict_config -c ${configFile}"; 67 StateDirectoryMode = lib.optionalString isServer "0700"; 68 DynamicUser = true; 69 # Hardening 70 UMask = lib.optionalString isServer "0007"; 71 CapabilityBoundingSet = serviceCapability; 72 AmbientCapabilities = serviceCapability; 73 PrivateDevices = true; 74 ProtectHostname = true; 75 ProtectClock = true; 76 ProtectKernelTunables = true; 77 ProtectKernelModules = true; 78 ProtectKernelLogs = true; 79 ProtectControlGroups = true; 80 RestrictAddressFamilies = [ 81 "AF_INET" 82 "AF_INET6" 83 ] ++ lib.optionals isClient [ "AF_UNIX" ]; 84 LockPersonality = true; 85 MemoryDenyWriteExecute = true; 86 RestrictRealtime = true; 87 RestrictSUIDSGID = true; 88 PrivateMounts = true; 89 SystemCallArchitectures = "native"; 90 SystemCallFilter = [ "@system-service" ]; 91 }; 92 }; 93 }; 94 }; 95 96 meta.maintainers = with lib.maintainers; [ zaldnoay ]; 97}