173 lines
6.1 KiB
Nix
173 lines
6.1 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
let
|
|
cfg = config.services.aria2;
|
|
|
|
homeDir = "/var/lib/aria2";
|
|
defaultRpcListenPort = 6800;
|
|
defaultDir = "${homeDir}/Downloads";
|
|
|
|
portRangesToString = ranges: lib.concatStringsSep "," (map
|
|
(x:
|
|
if x.from == x.to
|
|
then builtins.toString x.from
|
|
else builtins.toString x.from + "-" + builtins.toString x.to
|
|
)
|
|
ranges);
|
|
|
|
customToKeyValue = lib.generators.toKeyValue {
|
|
mkKeyValue = lib.generators.mkKeyValueDefault
|
|
{
|
|
mkValueString = v:
|
|
if builtins.isList v then portRangesToString v
|
|
else lib.generators.mkValueStringDefault { } v;
|
|
} "=";
|
|
};
|
|
in
|
|
{
|
|
imports = [
|
|
(lib.mkRemovedOptionModule [ "services" "aria2" "rpcSecret" ] "Use services.aria2.rpcSecretFile instead")
|
|
(lib.mkRemovedOptionModule [ "services" "aria2" "extraArguments" ] "Use services.aria2.settings instead")
|
|
(lib.mkRenamedOptionModule [ "services" "aria2" "downloadDir" ] [ "services" "aria2" "settings" "dir" ])
|
|
(lib.mkRenamedOptionModule [ "services" "aria2" "listenPortRange" ] [ "services" "aria2" "settings" "listen-port" ])
|
|
(lib.mkRenamedOptionModule [ "services" "aria2" "rpcListenPort" ] [ "services" "aria2" "settings" "rpc-listen-port" ])
|
|
];
|
|
|
|
options = {
|
|
services.aria2 = {
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether or not to enable the headless Aria2 daemon service.
|
|
|
|
Aria2 daemon can be controlled via the RPC interface using one of many
|
|
WebUIs (http://localhost:${toString defaultRpcListenPort}/ by default).
|
|
|
|
Targets are downloaded to `${defaultDir}` by default and are
|
|
accessible to users in the `aria2` group.
|
|
'';
|
|
};
|
|
openPorts = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Open listen and RPC ports found in `settings.listen-port` and
|
|
`settings.rpc-listen-port` options in the firewall.
|
|
'';
|
|
};
|
|
rpcSecretFile = lib.mkOption {
|
|
type = lib.types.path;
|
|
example = "/run/secrets/aria2-rpc-token.txt";
|
|
description = ''
|
|
A file containing the RPC secret authorization token.
|
|
Read https://aria2.github.io/manual/en/html/aria2c.html#rpc-auth to know how this option value is used.
|
|
'';
|
|
};
|
|
settings = lib.mkOption {
|
|
description = ''
|
|
Generates the `aria2.conf` file. Refer to [the documentation][0] for
|
|
all possible settings.
|
|
|
|
[0]: https://aria2.github.io/manual/en/html/aria2c.html#synopsis
|
|
'';
|
|
default = { };
|
|
type = lib.types.submodule {
|
|
freeformType = with lib.types; attrsOf (oneOf [ bool int float singleLineStr ]);
|
|
options = {
|
|
save-session = lib.mkOption {
|
|
type = lib.types.singleLineStr;
|
|
default = "${homeDir}/aria2.session";
|
|
description = "Save error/unfinished downloads to FILE on exit.";
|
|
};
|
|
dir = lib.mkOption {
|
|
type = lib.types.singleLineStr;
|
|
default = defaultDir;
|
|
description = "Directory to store downloaded files.";
|
|
};
|
|
conf-path = lib.mkOption {
|
|
type = lib.types.singleLineStr;
|
|
default = "${homeDir}/aria2.conf";
|
|
description = "Configuration file path.";
|
|
};
|
|
enable-rpc = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Enable JSON-RPC/XML-RPC server.";
|
|
};
|
|
listen-port = lib.mkOption {
|
|
type = with lib.types; listOf (attrsOf port);
|
|
default = [{ from = 6881; to = 6999; }];
|
|
description = "Set UDP listening port range used by DHT(IPv4, IPv6) and UDP tracker.";
|
|
};
|
|
rpc-listen-port = lib.mkOption {
|
|
type = lib.types.port;
|
|
default = defaultRpcListenPort;
|
|
description = "Specify a port number for JSON-RPC/XML-RPC server to listen to. Possible Values: 1024-65535";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
assertions = [
|
|
{
|
|
assertion = cfg.settings.enable-rpc;
|
|
message = "RPC has to be enabled, the default module option takes care of that.";
|
|
}
|
|
{
|
|
assertion = !(cfg.settings ? rpc-secret);
|
|
message = "Set the RPC secret through services.aria2.rpcSecretFile so it will not end up in the world-readable nix store.";
|
|
}
|
|
];
|
|
|
|
# Need to open ports for proper functioning
|
|
networking.firewall = lib.mkIf cfg.openPorts {
|
|
allowedUDPPortRanges = config.services.aria2.settings.listen-port;
|
|
allowedTCPPorts = [ config.services.aria2.settings.rpc-listen-port ];
|
|
};
|
|
|
|
users.users.aria2 = {
|
|
group = "aria2";
|
|
uid = config.ids.uids.aria2;
|
|
description = "aria2 user";
|
|
home = homeDir;
|
|
createHome = false;
|
|
};
|
|
|
|
users.groups.aria2.gid = config.ids.gids.aria2;
|
|
|
|
systemd.tmpfiles.rules = [
|
|
"d '${homeDir}' 0770 aria2 aria2 - -"
|
|
"d '${config.services.aria2.settings.dir}' 0770 aria2 aria2 - -"
|
|
];
|
|
|
|
systemd.services.aria2 = {
|
|
description = "aria2 Service";
|
|
after = [ "network.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
preStart = ''
|
|
if [[ ! -e "${cfg.settings.save-session}" ]]
|
|
then
|
|
touch "${cfg.settings.save-session}"
|
|
fi
|
|
cp -f "${pkgs.writeText "aria2.conf" (customToKeyValue cfg.settings)}" "${cfg.settings.conf-path}"
|
|
chmod +w "${cfg.settings.conf-path}"
|
|
echo "rpc-secret=$(cat "$CREDENTIALS_DIRECTORY/rpcSecretFile")" >> "${cfg.settings.conf-path}"
|
|
'';
|
|
|
|
serviceConfig = {
|
|
Restart = "on-abort";
|
|
ExecStart = "${pkgs.aria2}/bin/aria2c --conf-path=${cfg.settings.conf-path}";
|
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
|
User = "aria2";
|
|
Group = "aria2";
|
|
LoadCredential = "rpcSecretFile:${cfg.rpcSecretFile}";
|
|
};
|
|
};
|
|
};
|
|
|
|
meta.maintainers = [ lib.maintainers.timhae ];
|
|
}
|