breeze/flake.nix

226 lines
6.9 KiB
Nix

{
description = "breeze file server";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
crane.url = "github:ipetkov/crane";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
crane,
flake-utils,
...
}:
flake-utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
craneLib = crane.mkLib pkgs;
# Common arguments can be set here to avoid repeating them later
# Note: changes here will rebuild all dependency crates
commonArgs = {
src = craneLib.cleanCargoSource ./.;
strictDeps = true;
buildInputs =
[
pkgs.openssl
]
++ pkgs.lib.optionals pkgs.stdenv.isDarwin [
# Additional darwin specific inputs can be set here
pkgs.libiconv
];
};
breeze = craneLib.buildPackage (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 {
checks = {
inherit breeze;
};
packages.default = breeze;
apps.default = flake-utils.lib.mkApp {
drv = breeze;
};
devShells.default = craneLib.devShell {
# Inherit inputs from checks.
checks = self.checks.${system};
# Additional dev-shell environment variables can be set directly
# MY_CUSTOM_DEVELOPMENT_VAR = "something else";
# Extra inputs can be added here; cargo and rustc are provided by default.
packages = with pkgs; [
alejandra
rewrk
];
};
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 = "Any supplementary groups for `breeze` to run under";
};
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).
'';
};
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.
'';
};
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"
];
};
};
};
};
});
}