diff --git a/flake.lock b/flake.lock index abc937c..3b94618 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -35,11 +35,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725534445, - "narHash": "sha256-Yd0FK9SkWy+ZPuNqUgmVPXokxDgMJoGuNpMEtkfcf84=", + "lastModified": 1726871744, + "narHash": "sha256-V5LpfdHyQkUF7RfOaDPrZDP+oqz88lTJrMT1+stXNwo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9bb1e7571aadf31ddb4af77fc64b2d59580f9a39", + "rev": "a1d92660c6b3b7c26fb883500a80ea9d33321be2", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index d92f2cd..11c1afb 100644 --- a/flake.nix +++ b/flake.nix @@ -7,15 +7,14 @@ flake-utils.url = "github:numtide/flake-utils"; }; - outputs = - { self - , nixpkgs - , crane - , flake-utils - , ... - }: - flake-utils.lib.eachDefaultSystem (system: - let + outputs = { + self, + nixpkgs, + crane, + flake-utils, + ... + }: + flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; craneLib = crane.mkLib pkgs; @@ -38,14 +37,13 @@ breeze = craneLib.buildPackage (commonArgs // { - cargoArtifacts = craneLib.buildDepsOnly commonArgs; + cargoArtifacts = craneLib.buildDepsOnly commonArgs; - # Additional environment variables or build phases/hooks can be set - # here *without* rebuilding all dependency crates - # MY_CUSTOM_VAR = "some value"; - }); - in - { + # Additional environment variables or build phases/hooks can be set + # here *without* rebuilding all dependency crates + # MY_CUSTOM_VAR = "some value"; + }); + in { checks = { inherit breeze; }; @@ -70,123 +68,158 @@ ]; }; - nixosModules.breeze = - { config - , pkgs - , lib - , ... - }: - with lib; let - cfg = config.services.breeze; - settingsFormat = pkgs.formats.toml { }; - in - { - options = { - services.breeze = { - enable = mkEnableOption "breeze file server"; + nixosModules.breeze = { + config, + pkgs, + lib, + ... + }: + with lib; let + cfg = config.services.breeze; + settingsFormat = pkgs.formats.toml {}; + in { + options = { + services.breeze = { + enable = mkEnableOption "breeze file server"; - package = mkOption { - type = types.package; - default = breeze; - description = "Package for `breeze` to use"; - }; - - user = mkOption { - type = types.str; - default = "breeze"; - description = "User that `breeze` will run under"; - }; - - group = mkOption { - type = types.str; - default = "breeze"; - description = "Group that `breeze` will run under"; - }; - - extraGroups = mkOption { - type = types.listOf types.str; - default = [ ]; - description = "Supplementary groups"; - }; - - settings = mkOption { - type = settingsFormat.type; - default = { }; - description = '' - The *.toml configuration to run `breeze` with. - There is no formal documentation, but there is an example in the [readme](https://git.min.rip/min/breeze/src/branch/main/README.md). - ''; - }; - }; - }; - - config = mkIf cfg.enable { - users.users.${cfg.user} = { - isSystemUser = true; - inherit (cfg) group; + package = mkOption { + type = types.package; + default = breeze; + description = "Package for `breeze` to use"; }; - users.groups.${cfg.group} = { }; + user = mkOption { + type = types.str; + default = "breeze"; + description = "User that `breeze` will run under"; + }; - systemd.services.breeze = { - description = "breeze file server"; - after = [ "local-fs.target" "network.target" ]; - wantedBy = [ "multi-user.target" ]; + group = mkOption { + type = types.str; + default = "breeze"; + description = "Group that `breeze` will run under"; + }; - serviceConfig = rec { - User = cfg.user; - Group = cfg.group; - DynamicUser = false; # we write files, so don't do that - SupplementaryGroups = cfg.extraGroups; - StateDirectory = "breeze"; - CacheDirectory = "breeze"; - ExecStart = escapeShellArgs [ - "${cfg.package}/bin/breeze" - "--config" - (settingsFormat.generate "breeze.toml" cfg.settings) - ]; - Restart = "on-failure"; + extraGroups = mkOption { + type = types.listOf types.str; + default = []; + description = "Any supplementary groups for `breeze` to run under"; + }; - # Security Options # + settings = mkOption { + type = settingsFormat.type; + default = {}; + description = '' + The *.toml configuration to run `breeze` with. + There is no formal documentation, but there is an example in the [readme](https://git.min.rip/min/breeze/src/branch/main/README.md). + ''; + }; - NoNewPrivileges = true; # implied by DynamicUser - RemoveIPC = true; # implied by DynamicUser + configDir = mkOption { + type = types.path; + default = "/etc/breeze"; + description = '' + The directory on disk to store the `breeze` config file in. + This does not load pre-existing config files, it only defines where the generated config is saved. + ''; + }; - AmbientCapabilities = ""; - CapabilityBoundingSet = ""; - - DeviceAllow = ""; - - LockPersonality = true; - - PrivateTmp = true; # implied by DynamicUser - PrivateDevices = true; - PrivateUsers = true; - - ProtectClock = true; - ProtectControlGroups = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - - RestrictNamespaces = true; - RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; - RestrictRealtime = true; - RestrictSUIDSGID = true; # implied by DynamicUser - - SystemCallArchitectures = "native"; - SystemCallErrorNumber = "EPERM"; - SystemCallFilter = [ - "@system-service" - "~@keyring" - "~@memlock" - "~@privileged" - "~@setuid" - ]; - }; + uploadKeyFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + File to load the `engine.upload_key` from, if desired. + This is useful for loading it from a secret management system. + ''; }; }; }; + + config = mkIf cfg.enable { + users.users.${cfg.user} = { + isSystemUser = true; + inherit (cfg) group; + }; + + users.groups.${cfg.group} = {}; + + systemd.tmpfiles.rules = [ + "d '${cfg.configDir}' 0750 ${cfg.user} ${cfg.group} - -" + ]; + + services.breeze.settings = mkMerge [ + (mkIf (cfg.uploadKeyFile != null) {engine.upload_key = "@UPLOAD_KEY@";}) + ]; + + systemd.services.breeze = let + cfgFile = "${cfg.configDir}/breeze.toml"; + in { + description = "breeze file server"; + after = ["local-fs.target" "network.target"]; + wantedBy = ["multi-user.target"]; + + preStart = + '' + install -m 660 ${settingsFormat.generate "breeze.toml" cfg.settings} ${cfgFile} + '' + + lib.optionalString (cfg.uploadKeyFile != null) '' + ${pkgs.replace-secret}/bin/replace-secret '@UPLOAD_KEY@' "${cfg.uploadKeyFile}" ${cfgFile} + ''; + + serviceConfig = rec { + User = cfg.user; + Group = cfg.group; + DynamicUser = false; # we write files, so don't do that + SupplementaryGroups = cfg.extraGroups; + StateDirectory = "breeze"; + CacheDirectory = "breeze"; + ExecStart = escapeShellArgs [ + "${cfg.package}/bin/breeze" + "--config" + cfgFile + ]; + Restart = "on-failure"; + + # Security Options # + + NoNewPrivileges = true; # implied by DynamicUser + RemoveIPC = true; # implied by DynamicUser + + AmbientCapabilities = ""; + CapabilityBoundingSet = ""; + + DeviceAllow = ""; + + LockPersonality = true; + + PrivateTmp = true; # implied by DynamicUser + PrivateDevices = true; + PrivateUsers = true; + + ProtectClock = true; + ProtectControlGroups = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + + RestrictNamespaces = true; + RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"]; + RestrictRealtime = true; + RestrictSUIDSGID = true; # implied by DynamicUser + + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = [ + "@system-service" + "~@keyring" + "~@memlock" + "~@privileged" + "~@setuid" + ]; + }; + }; + }; + }; }); } diff --git a/nix/module.nix b/nix/module.nix deleted file mode 100644 index 249d697..0000000 --- a/nix/module.nix +++ /dev/null @@ -1,113 +0,0 @@ -{ config -, pkgs -, lib -, ... -}: -with lib; let - cfg = config.services.breeze; - settingsFormat = pkgs.formats.toml { }; -in -{ - options = { - services.breeze = { - enable = mkEnableOption "breeze file server"; - - package = mkPackageOption self.packages.${system} "breeze"; - - user = mkOption { - type = types.str; - default = "breeze"; - description = "User that `breeze` will run under"; - }; - - group = mkOption { - type = types.str; - default = "breeze"; - description = "Group that `breeze` will run under"; - }; - - extraGroups = mkOption { - type = types.listOf types.str; - default = [ ]; - description = "Supplementary groups"; - }; - - settings = mkOption { - type = settingsFormat.type; - default = { }; - description = '' - The *.toml configuration to run `breeze` with. - There is no formal documentation, but there is an example in the [readme](https://git.min.rip/min/breeze/src/branch/main/README.md). - ''; - }; - }; - }; - - config = mkIf cfg.enable { - users.users.${cfg.user} = { - isSystemUser = true; - inherit (cfg) group; - }; - - users.groups.${cfg.group} = { }; - - systemd.services.breeze = { - description = "breeze file server"; - after = [ "local-fs.target" "network.target" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = rec { - User = cfg.user; - Group = cfg.group; - DynamicUser = false; # we write files, so don't do that - SupplementaryGroups = cfg.extraGroups; - StateDirectory = "breeze"; - CacheDirectory = "breeze"; - ExecStart = escapeShellArgs [ - "${cfg.package}/bin/breeze" - "--config" - (settingsFormat.generate "breeze.toml" cfg.settings) - ]; - Restart = "on-failure"; - - # Security Options # - - NoNewPrivileges = true; # implied by DynamicUser - RemoveIPC = true; # implied by DynamicUser - - AmbientCapabilities = ""; - CapabilityBoundingSet = ""; - - DeviceAllow = ""; - - LockPersonality = true; - - PrivateTmp = true; # implied by DynamicUser - PrivateDevices = true; - PrivateUsers = true; - - ProtectClock = true; - ProtectControlGroups = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - - RestrictNamespaces = true; - RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; - RestrictRealtime = true; - RestrictSUIDSGID = true; # implied by DynamicUser - - SystemCallArchitectures = "native"; - SystemCallErrorNumber = "EPERM"; - SystemCallFilter = [ - "@system-service" - "~@keyring" - "~@memlock" - "~@privileged" - "~@setuid" - ]; - }; - }; - }; -}