at 23.11-pre 3.1 kB view raw
1{ config, lib, pkgs, ... }: 2let 3 inherit (lib) types; 4 cfg = config.services.croc; 5 rootDir = "/run/croc"; 6in 7{ 8 options.services.croc = { 9 enable = lib.mkEnableOption (lib.mdDoc "croc relay"); 10 ports = lib.mkOption { 11 type = with types; listOf port; 12 default = [9009 9010 9011 9012 9013]; 13 description = lib.mdDoc "Ports of the relay."; 14 }; 15 pass = lib.mkOption { 16 type = with types; either path str; 17 default = "pass123"; 18 description = lib.mdDoc "Password or passwordfile for the relay."; 19 }; 20 openFirewall = lib.mkEnableOption (lib.mdDoc "opening of the peer port(s) in the firewall"); 21 debug = lib.mkEnableOption (lib.mdDoc "debug logs"); 22 }; 23 24 config = lib.mkIf cfg.enable { 25 systemd.services.croc = { 26 after = [ "network.target" ]; 27 wantedBy = [ "multi-user.target" ]; 28 serviceConfig = { 29 ExecStart = "${pkgs.croc}/bin/croc --pass '${cfg.pass}' ${lib.optionalString cfg.debug "--debug"} relay --ports ${lib.concatMapStringsSep "," toString cfg.ports}"; 30 # The following options are only for optimizing: 31 # systemd-analyze security croc 32 AmbientCapabilities = ""; 33 CapabilityBoundingSet = ""; 34 DynamicUser = true; 35 # ProtectClock= adds DeviceAllow=char-rtc r 36 DeviceAllow = ""; 37 LockPersonality = true; 38 MemoryDenyWriteExecute = true; 39 MountAPIVFS = true; 40 NoNewPrivileges = true; 41 PrivateDevices = true; 42 PrivateMounts = true; 43 PrivateNetwork = lib.mkDefault false; 44 PrivateTmp = true; 45 PrivateUsers = true; 46 ProcSubset = "pid"; 47 ProtectClock = true; 48 ProtectControlGroups = true; 49 ProtectHome = true; 50 ProtectHostname = true; 51 ProtectKernelLogs = true; 52 ProtectKernelModules = true; 53 ProtectKernelTunables = true; 54 ProtectProc = "invisible"; 55 ProtectSystem = "strict"; 56 RemoveIPC = true; 57 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; 58 RestrictNamespaces = true; 59 RestrictRealtime = true; 60 RestrictSUIDSGID = true; 61 RootDirectory = rootDir; 62 # Avoid mounting rootDir in the own rootDir of ExecStart='s mount namespace. 63 InaccessiblePaths = [ "-+${rootDir}" ]; 64 BindReadOnlyPaths = [ 65 builtins.storeDir 66 ] ++ lib.optional (types.path.check cfg.pass) cfg.pass; 67 # This is for BindReadOnlyPaths= 68 # to allow traversal of directories they create in RootDirectory=. 69 UMask = "0066"; 70 # Create rootDir in the host's mount namespace. 71 RuntimeDirectory = [(baseNameOf rootDir)]; 72 RuntimeDirectoryMode = "700"; 73 SystemCallFilter = [ 74 "@system-service" 75 "~@aio" "~@keyring" "~@memlock" "~@privileged" "~@setuid" "~@sync" "~@timer" 76 ]; 77 SystemCallArchitectures = "native"; 78 SystemCallErrorNumber = "EPERM"; 79 }; 80 }; 81 82 networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall cfg.ports; 83 }; 84 85 meta.maintainers = with lib.maintainers; [ hax404 julm ]; 86}