diff --git a/nix/module.nix b/nix/module.nix index 1428e0d..0dc4c5e 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -5,7 +5,7 @@ self: { pkgs, ... }: let - inherit (builtins) toJSON baseNameOf toString; + inherit (builtins) toJSON toString; inherit (lib.modules) mkIf; inherit (lib.options) mkOption mkEnableOption literalExpression; inherit (lib.types) package str port int listOf enum bool attrsOf path; @@ -30,6 +30,13 @@ self: { config_dir = "${cfg.stateDir}/conf"; cache_dir = cfg.cacheDir; }); + + # Check if we need privileged port capability + portMatch = builtins.match ".*:([0-9]+)" cfg.listenAddress; + needsPrivilegedPort = + portMatch + != null + && builtins.fromJSON (builtins.head portMatch) < 1024; in { ###### interface options = { @@ -39,7 +46,7 @@ in { package = mkOption { type = package; default = self.packages.${pkgs.stdenv.system}.eris; - defaultText = literalExpression "pkgs.eris"; + defaultText = literalExpression "self.packages.\${pkgs.stdenv.system}.eris"; description = "The Eris package to use."; }; @@ -154,7 +161,7 @@ in { dataDir = mkOption { # This derives from stateDir by default to keep persistent data together type = path; - default = "${cfg.stateDir}/data"; + default = "/var/lib/eris/data"; description = "Directory containing `corpora` and `scripts` subdirectories."; }; @@ -180,7 +187,7 @@ in { An attribute set where keys are Lua script filenames (e.g., "`my_script.lua`") and values are paths to the script files. These will be placed in {path}`''${cfg.dataDir}/scripts`. ''; - example = lib.literalExpression '' + example = literalExpression '' { "custom_tokens.lua" = ./custom_tokens.lua; } @@ -225,7 +232,7 @@ in { type ipv4_addr; flags interval; comment "Managed by Eris NixOS module"; } - chain input { + chain INPUT { ${lib.optionalString cfg.nftablesDropRule '' ip saddr @eris_blacklist counter drop comment "Drop traffic from Eris blacklist"; ''} @@ -281,13 +288,13 @@ in { # Explicitly allow writes to state/cache/data dirs ReadWritePaths = [ - cfg.stateDir - cfg.cacheDir - cfg.dataDir + "${cfg.stateDir}" + "${cfg.cacheDir}" + "${cfg.dataDir}" ]; # Allow reads from config file path - ReadOnlyPaths = [erisConfigFile]; + ReadOnlyPaths = ["${erisConfigFile}"]; # Explicitly deny access to sensitive paths InaccessiblePaths = [ @@ -308,16 +315,15 @@ in { # Network access control RestrictAddressFamilies = ["AF_INET" "AF_INET6"]; # Allow only standard IP protocols - CapabilityBoundingSet = ["CAP_NET_BIND_SERVICE"]; # Allow binding to ports < 1024 if needed - AmbientCapabilities = ["CAP_NET_BIND_SERVICE"]; + + # Only add NET_BIND_SERVICE capability if needed (port < 1024) + CapabilityBoundingSet = optionals needsPrivilegedPort "CAP_NET_BIND_SERVICE"; + AmbientCapabilities = optionals needsPrivilegedPort "CAP_NET_BIND_SERVICE"; # System call filtering (adjust based on Eris's needs) # Start with a reasonable baseline for network services SystemCallFilter = ["@system-service" "@network-io" "@file-system"]; - # TODO: Consider adding more specific filters or removing groups if issues arise - # e.g., SystemCallArchitectures=native. This probably will not be enough - # Other hardening RestrictNamespaces = true; # Prevent creation of new namespaces LockPersonality = true; # Lock down legacy personality settings @@ -327,8 +333,8 @@ in { RestrictSUIDSGID = true; # Ignore SUID/SGID bits on execution # Directories managed by systemd - StateDirectory = baseNameOf cfg.stateDir; # e.g., "eris" - CacheDirectory = baseNameOf cfg.cacheDir; # e.g., "eris" + StateDirectory = "eris"; + CacheDirectory = "eris"; StateDirectoryMode = "0750"; CacheDirectoryMode = "0750"; @@ -362,16 +368,17 @@ in { # Systemd creates StateDirectory and CacheDirectory, but we need subdirs mkdir -p ${cfg.stateDir}/conf ${cfg.dataDir} ${corporaDir} ${scriptsDir} - # Ensure ownership is correct for all relevant dirs managed by systemd or created here - ${chownCmd} /var/lib/${baseNameOf cfg.stateDir} \ - /var/cache/${baseNameOf cfg.cacheDir} \ + # Wee need to be able to read and write to all relevant directories. + ${chownCmd} ${cfg.stateDir} \ + ${cfg.cacheDir} \ ${cfg.stateDir}/conf \ ${cfg.dataDir} \ ${corporaDir} \ ${scriptsDir} - # Copy declarative files - ${toString copyCorporaCmds} - ${toString copyLuaScriptCmds} + + # Copy configurationn files + ${lib.optionalString (cfg.corpora != {}) (toString copyCorporaCmds)} + ${lib.optionalString (cfg.luaScripts != {}) (toString copyLuaScriptCmds)} ''; }; };