Files
dev/configs/nixos/modules/services/copyparty/default.nix

137 lines
3.8 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
cfg = config.modules.services.copyparty; # NOLINT(let_order)
port = 3923;
serviceGroup = "storage";
serviceStateDir = "/var/lib/copyparty";
serviceUser = "copyparty";
in
{
options.modules.services.copyparty = {
enable = lib.mkEnableOption "Copyparty";
passwordFile = lib.mkOption {
type = lib.types.str;
description = "Sets the runtime file that contains the Copyparty account password.";
};
volumes = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
path = lib.mkOption {
type = lib.types.externalPath;
description = "Sets the filesystem path served by this volume.";
};
access = lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
default = { };
example = {
A = [ "alexion" ];
};
description = "Maps Copyparty permission strings to account names.";
};
readOnly = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Serves this volume read-only.";
};
flags = lib.mkOption {
type = lib.types.attrs;
default = { };
example = {
dthumb = true;
};
description = "Sets Copyparty volume flags.";
};
};
}
);
default = { };
description = "Defines Copyparty volumes by URL path.";
};
reverseProxy = {
enable = lib.mkEnableOption "reverse-proxy trust settings for Copyparty";
trustedSources = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Lists proxy sources that can set Copyparty's forwarded client IP header.";
};
};
};
config = lib.mkMerge [
{
registry."stable-uid".${config.networking.hostName}.copyparty = 20002;
}
(lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.volumes != { };
message = "modules.services.copyparty.volumes must declare at least one served volume.";
}
{
assertion = !cfg.reverseProxy.enable || cfg.reverseProxy.trustedSources != [ ];
message = "modules.services.copyparty.reverseProxy.trustedSources must name at least one trusted proxy source when reverse-proxy support is enabled.";
}
];
services.copyparty = {
enable = true;
group = serviceGroup;
package = pkgs.copyparty-min;
stateDir = serviceStateDir;
user = serviceUser;
settings = {
i = "0.0.0.0";
usernames = true;
"http-only" = true;
"no-crt" = true;
"no-thumb" = true;
"no-snap" = true;
"no-rescan" = true;
"ses-db" = "${serviceStateDir}/sessions.db";
"chpw-db" = "${serviceStateDir}/chpw.json";
"shr-db" = "${serviceStateDir}/shares.db";
}
// lib.optionalAttrs cfg.reverseProxy.enable {
rproxy = 1;
"xff-hdr" = "x-forwarded-for";
};
accounts.${config.user.name}.passwordFile = cfg.passwordFile;
globalExtraConfig = lib.optionalString cfg.reverseProxy.enable (
lib.concatMapStringsSep "\n" (source: "xff-src: ${source}") cfg.reverseProxy.trustedSources
);
volumes = lib.mapAttrs (_urlPath: volume: {
inherit (volume)
access
flags
path
readOnly
;
}) cfg.volumes;
};
users.users.${serviceUser}.uid =
config.registry."stable-uid".${config.networking.hostName}.copyparty;
networking.firewall.allowedTCPPorts = [ port ];
})
];
}