added ability to specify user and group.

This commit is contained in:
Gabe Venberg 2025-04-22 21:49:20 +02:00
parent 15e200caa2
commit 5520fe611b

View file

@ -51,12 +51,11 @@ with lib; let
${concatStringsSep "\n" (mapAttrsToList mkVolume cfg.volumes)} ${concatStringsSep "\n" (mapAttrsToList mkVolume cfg.volumes)}
''; '';
name = "copyparty";
cfg = config.services.copyparty; cfg = config.services.copyparty;
configFile = pkgs.writeText "${name}.conf" configStr; configFile = pkgs.writeText "copyparty.conf" configStr;
runtimeConfigPath = "/run/${name}/${name}.conf"; runtimeConfigPath = "/run/copyparty/copyparty.conf";
home = "/var/lib/${name}"; stateDir = "/var/lib/copyparty";
defaultShareDir = "${home}/data"; defaultShareDir = "${stateDir}/data";
in { in {
options.services.copyparty = { options.services.copyparty = {
enable = mkEnableOption "web-based file manager"; enable = mkEnableOption "web-based file manager";
@ -70,6 +69,26 @@ in {
''; '';
}; };
user = mkOption {
type = types.str;
default = "copyparty";
description = ''
The user that copyparty will run under.
If changed from default, you are responsible for making sure the user exists.
'';
};
group = mkOption {
type = types.str;
default = "copyparty";
description = ''
The group that copyparty will run under.
If changed from default, you are responsible for making sure the user exists.
'';
};
openFilesLimit = mkOption { openFilesLimit = mkOption {
default = 4096; default = 4096;
type = types.either types.int types.str; type = types.either types.int types.str;
@ -81,6 +100,7 @@ in {
description = '' description = ''
Global settings to apply. Global settings to apply.
Directly maps to values in the [global] section of the copyparty config. Directly maps to values in the [global] section of the copyparty config.
Cannot set "c" or "hist", those are set by this module.
See `${getExe cfg.package} --help` for more details. See `${getExe cfg.package} --help` for more details.
''; '';
default = { default = {
@ -213,7 +233,7 @@ in {
environment = { environment = {
PYTHONUNBUFFERED = "true"; PYTHONUNBUFFERED = "true";
XDG_CONFIG_HOME = "${home}/.config"; XDG_CONFIG_HOME = "home";
}; };
preStart = let preStart = let
@ -229,17 +249,16 @@ in {
serviceConfig = { serviceConfig = {
Type = "simple"; Type = "simple";
ExecStart = "${getExe cfg.package} -c ${runtimeConfigPath}"; ExecStart = "${getExe cfg.package} -c ${runtimeConfigPath} --hist ${stateDir}";
# Hardening options # Hardening options
User = "copyparty"; User = cfg.user;
Group = "copyparty"; Group = cfg.group;
RuntimeDirectory = name; RuntimeDirectory = ["copyparty"];
RuntimeDirectoryMode = "0700"; RuntimeDirectoryMode = "0700";
StateDirectory = [name "${name}/data" "${name}/.config"]; StateDirectory = ["copyparty"];
StateDirectoryMode = "0700"; StateDirectoryMode = "0700";
WorkingDirectory = home; WorkingDirectory = stateDir;
TemporaryFileSystem = "/:ro";
BindReadOnlyPaths = BindReadOnlyPaths =
[ [
"/nix/store" "/nix/store"
@ -249,10 +268,9 @@ in {
"-/etc/localtime" "-/etc/localtime"
] ]
++ (mapAttrsToList (k: v: "-${v.passwordFile}") cfg.accounts); ++ (mapAttrsToList (k: v: "-${v.passwordFile}") cfg.accounts);
BindPaths = [home] ++ (mapAttrsToList (k: v: v.path) cfg.volumes); BindPaths = [stateDir] ++ (mapAttrsToList (k: v: v.path) cfg.volumes);
# Would re-mount paths ignored by temporary root ProtectSystem = "strict";
#ProtectSystem = "strict"; ProtectHome = "tmpfs";
ProtectHome = true;
PrivateTmp = true; PrivateTmp = true;
PrivateDevices = true; PrivateDevices = true;
ProtectKernelTunables = true; ProtectKernelTunables = true;
@ -272,14 +290,16 @@ in {
NoNewPrivileges = true; NoNewPrivileges = true;
LockPersonality = true; LockPersonality = true;
RestrictRealtime = true; RestrictRealtime = true;
MemoryDenyWriteExecute = true;
# RestrictAddressFamilies = "none";
}; };
}; };
users.groups.copyparty = {}; users.groups.copyparty = lib.mkIf (cfg.user == "copyparty" && cfg.group == "copyparty") {};
users.users.copyparty = { users.users.copyparty = lib.mkIf (cfg.user == "copyparty" && cfg.group == "copyparty") {
description = "Service user for copyparty"; description = "Service user for copyparty";
group = "copyparty"; group = "copyparty";
home = home; home = stateDir;
isSystemUser = true; isSystemUser = true;
}; };
}; };