diff --git a/flake.nix b/flake.nix index a0cf9d9..d1dcf8b 100644 --- a/flake.nix +++ b/flake.nix @@ -5,7 +5,6 @@ naersk.url = "github:nix-community/naersk"; naersk.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = { self, @@ -20,7 +19,8 @@ "aarch64-darwin" ]; forAllSystems = nixpkgs.lib.genAttrs supportedSystems; - cargo-toml = builtins.fromTOML (builtins.readFile ./Cargo.toml); + cargoConfig = builtins.fromTOML (builtins.readFile ./Cargo.toml); + pkgName = cargoConfig.package.name; in { packages = forAllSystems ( @@ -40,41 +40,43 @@ { default = app; docker = pkgs.dockerTools.streamLayeredImage { - name = "localhost/${cargo-toml.package.name}"; + name = "localhost/${pkgName}"; tag = "latest"; contents = [ app pkgs.bash ]; - config.Cmd = [ "${app}/bin/${cargo-toml.package.name}" ]; + config.Cmd = [ "${app}/bin/${pkgName}" ]; }; } ); nixosModules.default = - { config, lib, ... }: + { + config, + pkgs, + lib, + ... + }: let - cfg = config.crashkeys.services.audsite; + cfg = config.crashkeys.services.${pkgName}; in { options = { - crashkeys.services.audsite = { - enable = lib.mkEnableOption "Enables the crashkeys.dev web server"; - system = lib.mkOption { - type = lib.types.enum supportedSystems; - example = "x86_64-linux"; - description = "The architecture of the system for which to run the web server."; - }; + crashkeys.services.${pkgName} = { + enable = lib.mkEnableOption "Enables the crashkeys.dev web server."; package = lib.mkOption { type = lib.types.package; - default = self.packages.${cfg.system}.default; + default = self.packages.${pkgs.system}.default; description = "The Nix package corresponding to the web server to run."; }; public_url = lib.mkOption { type = lib.types.str; - default = "https://crashkeys.dev"; example = "https://crashkeys.dev"; - description = "The base public URL the site will be available at."; + description = '' + The base public URL the site will be available at. + Note that this value is only used to generate OpenGraph tags. + ''; }; address = lib.mkOption { type = lib.types.str; @@ -90,36 +92,70 @@ }; }; }; - config = lib.mkIf cfg.enable { - systemd.services."crashkeys.audsite" = { - wantedBy = [ "multi-user.target" ]; - serviceConfig = - let - pkg = cfg.package; - in - { - Restart = "on-failure"; - ExecStart = "${pkg}/bin/${cargo-toml.package.name}"; - DynamicUser = "yes"; - WorkingDirectory = "${pkg}"; - RuntimeDirectory = "crashkeys.audsite"; - RuntimeDirectoryMode = "0755"; - StateDirectory = "crashkeys.audsite"; - StateDirectoryMode = "0700"; - CacheDirectory = "crashkeys.audsite"; - CacheDirectoryMode = "0750"; - BindReadOnlyPaths = [ - "${pkg}" - "/nix/store" - ]; - Environment = [ - "ROCKET_ADDRESS=${cfg.address}" - "ROCKET_PORT=${builtins.toString cfg.port}" - "ROCKET_PUBLIC_URL=${cfg.public_url}" - ]; - }; + config = + let + # The generated systemd service unit's name + serviceName = "crashkeys.${pkgName}"; + in + lib.mkIf cfg.enable { + systemd.services."${serviceName}" = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = + let + pkg = cfg.package; + in + { + Restart = "on-failure"; + ExecStart = "${pkg}/bin/${pkgName}"; + DynamicUser = "yes"; + + # The package includes the web server's static assets, + # so we must run it at its output directory in the Nix store + WorkingDirectory = "${pkg}"; + RuntimeDirectory = "${serviceName}"; + RuntimeDirectoryMode = "0755"; + StateDirectory = "${serviceName}"; + StateDirectoryMode = "0700"; + CacheDirectory = "${serviceName}"; + CacheDirectoryMode = "0750"; + BindReadOnlyPaths = [ + "${pkg}" + ]; + Environment = [ + "ROCKET_ADDRESS=${cfg.address}" + "ROCKET_PORT=${builtins.toString cfg.port}" + "ROCKET_PUBLIC_URL=${cfg.public_url}" + ]; + + NoNewPrivileges = true; + PrivateDevices = true; + ProtectClock = true; + CapabilityBoundingSet = ""; # Clear all capabilities + RestrictSUIDSGID = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + ProtectKernelModules = true; + PrivateMounts = true; + RestrictNamespaces = true; + ProtectHostname = true; + + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; + ProtectSystem = "full"; + ProtectProc = "noaccess"; + ProcSubset = "pid"; + PrivateUsers = true; + PrivateTmp = true; + ProtectKernelTunables = true; + LockPersonality = true; + RestrictRealtime = true; + MemoryDenyWriteExecute = true; + }; + }; }; - }; }; # For `nix develop` (optional, can be skipped):