1 { config, lib, pkgs, ... }:
6 cfg = config.services.redlib;
8 args = concatStringsSep " " ([
9 "--port ${toString cfg.port}"
10 "--address ${cfg.address}"
15 (mkRenamedOptionModule [ "services" "libreddit" ] [ "services" "redlib" ])
20 enable = mkEnableOption "Private front-end for Reddit";
22 package = mkPackageOption pkgs "redlib" { };
26 example = "127.0.0.1";
28 description = "The address to listen on";
35 description = "The port to listen on";
38 openFirewall = mkOption {
41 description = "Open ports in the firewall for the redlib web interface";
47 config = mkIf cfg.enable {
48 systemd.services.redlib = {
49 description = "Private front-end for Reddit";
50 wantedBy = [ "multi-user.target" ];
51 after = [ "network.target" ];
54 ExecStart = "${lib.getExe cfg.package} ${args}";
55 AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
56 Restart = "on-failure";
59 CapabilityBoundingSet = if (cfg.port < 1024) then [ "CAP_NET_BIND_SERVICE" ] else [ "" ];
61 LockPersonality = true;
62 MemoryDenyWriteExecute = true;
63 PrivateDevices = true;
64 # A private user cannot have process capabilities on the host's user
65 # namespace and thus CAP_NET_BIND_SERVICE has no effect.
66 PrivateUsers = (cfg.port >= 1024);
69 ProtectControlGroups = true;
71 ProtectHostname = true;
72 ProtectKernelLogs = true;
73 ProtectKernelModules = true;
74 ProtectKernelTunables = true;
75 ProtectProc = "invisible";
76 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
77 RestrictNamespaces = true;
78 RestrictRealtime = true;
79 RestrictSUIDSGID = true;
80 SystemCallArchitectures = "native";
81 SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ];
86 networking.firewall = mkIf cfg.openFirewall {
87 allowedTCPPorts = [ cfg.port ];