Compare commits

...

2 Commits

Author SHA1 Message Date
minish 1fc0ecad20
bump version 2024-09-08 18:42:43 -04:00
minish 85369049a5
add nixos module 2024-09-08 18:36:44 -04:00
5 changed files with 259 additions and 19 deletions

2
Cargo.lock generated
View File

@ -228,7 +228,7 @@ checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]] [[package]]
name = "breeze" name = "breeze"
version = "0.2.4" version = "0.2.5"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"argh", "argh",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "breeze" name = "breeze"
version = "0.2.4" version = "0.2.5"
edition = "2021" edition = "2021"
[dependencies] [dependencies]

View File

@ -84,6 +84,11 @@ motd = "my image host, currently hosting %uplcount% files"
# cached anyways. # cached anyways.
max_temp_lifetime = 43200 max_temp_lifetime = 43200
# OPTIONAL - the maximum length (in bytes) a file being uploaded may be.
# A word of warning about this: the error shown to ShareX users who
# hit the limit is *not* very clear. ("connection closed" or similar)
max_upload_len = 2_147_483_648
# The maximum length (in bytes) an image file may be before the server # The maximum length (in bytes) an image file may be before the server
# will skip removing its EXIF data. # will skip removing its EXIF data.
# The performance impact of breeze's EXIF data removal is not # The performance impact of breeze's EXIF data removal is not
@ -108,7 +113,7 @@ upload_lifetime = 1800
scan_freq = 60 scan_freq = 60
# How much memory (in bytes) the cache is allowed to consume. # How much memory (in bytes) the cache is allowed to consume.
mem_capacity = 4_294_967_295 mem_capacity = 4_294_967_296
[http] [http]
# The address that the HTTP server will listen on. (ip:port) # The address that the HTTP server will listen on. (ip:port)

154
flake.nix
View File

@ -7,14 +7,15 @@
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
}; };
outputs = { outputs =
self, { self
nixpkgs, , nixpkgs
crane, , crane
flake-utils, , flake-utils
... , ...
}: }:
flake-utils.lib.eachDefaultSystem (system: let flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
craneLib = crane.mkLib pkgs; craneLib = crane.mkLib pkgs;
@ -37,13 +38,14 @@
breeze = craneLib.buildPackage (commonArgs breeze = craneLib.buildPackage (commonArgs
// { // {
cargoArtifacts = craneLib.buildDepsOnly commonArgs; cargoArtifacts = craneLib.buildDepsOnly commonArgs;
# Additional environment variables or build phases/hooks can be set # Additional environment variables or build phases/hooks can be set
# here *without* rebuilding all dependency crates # here *without* rebuilding all dependency crates
# MY_CUSTOM_VAR = "some value"; # MY_CUSTOM_VAR = "some value";
}); });
in { in
{
checks = { checks = {
inherit breeze; inherit breeze;
}; };
@ -62,9 +64,129 @@
# MY_CUSTOM_DEVELOPMENT_VAR = "something else"; # MY_CUSTOM_DEVELOPMENT_VAR = "something else";
# Extra inputs can be added here; cargo and rustc are provided by default. # Extra inputs can be added here; cargo and rustc are provided by default.
packages = [ packages = with pkgs; [
pkgs.rewrk 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 = "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"
];
};
};
};
};
}); });
} }

113
nix/module.nix Normal file
View File

@ -0,0 +1,113 @@
{ 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"
];
};
};
};
}