nixos/deluge: add authFile, config & port options
This commit is contained in:
parent
474566bccb
commit
2fa256bd55
@ -5,8 +5,33 @@ with lib;
|
|||||||
let
|
let
|
||||||
cfg = config.services.deluge;
|
cfg = config.services.deluge;
|
||||||
cfg_web = config.services.deluge.web;
|
cfg_web = config.services.deluge.web;
|
||||||
openFilesLimit = 4096;
|
|
||||||
|
|
||||||
|
openFilesLimit = 4096;
|
||||||
|
listenPortsDefault = [ 6881 6889 ];
|
||||||
|
|
||||||
|
listToRange = x: { from = elemAt x 0; to = elemAt x 1; };
|
||||||
|
|
||||||
|
configDir = "${cfg.dataDir}/.config/deluge";
|
||||||
|
configFile = pkgs.writeText "core.conf" (builtins.toJSON cfg.config);
|
||||||
|
declarativeLockFile = "${configDir}/.declarative";
|
||||||
|
|
||||||
|
preStart = if cfg.declarative then ''
|
||||||
|
if [ -e ${declarativeLockFile} ]; then
|
||||||
|
# Was declarative before, no need to back up anything
|
||||||
|
ln -sf ${configFile} ${configDir}/core.conf
|
||||||
|
ln -sf ${cfg.authFile} ${configDir}/auth
|
||||||
|
else
|
||||||
|
# Declarative for the first time, backup stateful files
|
||||||
|
ln -sb --suffix=.stateful ${configFile} ${configDir}/core.conf
|
||||||
|
ln -sb --suffix=.stateful ${cfg.authFile} ${configDir}/auth
|
||||||
|
echo "Autogenerated file that signifies that this server configuration is managed declaratively by NixOS" \
|
||||||
|
> ${declarativeLockFile}
|
||||||
|
fi
|
||||||
|
'' else ''
|
||||||
|
if [ -e ${declarativeLockFile} ]; then
|
||||||
|
rm ${declarativeLockFile}
|
||||||
|
fi
|
||||||
|
'';
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
services = {
|
services = {
|
||||||
@ -15,42 +40,151 @@ in {
|
|||||||
|
|
||||||
openFilesLimit = mkOption {
|
openFilesLimit = mkOption {
|
||||||
default = openFilesLimit;
|
default = openFilesLimit;
|
||||||
example = 8192;
|
|
||||||
description = ''
|
description = ''
|
||||||
Number of files to allow deluged to open.
|
Number of files to allow deluged to open.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
download_location = "/srv/torrents/";
|
||||||
|
max_upload_speed = "1000.0";
|
||||||
|
share_ratio_limit = "2.0";
|
||||||
|
allow_remote = true;
|
||||||
|
daemon_port = 58846;
|
||||||
|
listen_ports = [ ${toString listenPortsDefault} ];
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Deluge core configuration for the core.conf file. Only has an effect
|
||||||
|
when <option>services.deluge.declarative</option> is set to
|
||||||
|
<literal>true</literal>. String values must be quoted, integer and
|
||||||
|
boolean values must not. See
|
||||||
|
<link xlink:href="https://git.deluge-torrent.org/deluge/tree/deluge/core/preferencesmanager.py#n41"/>
|
||||||
|
for the availaible options.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
declarative = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to use a declarative deluge configuration.
|
||||||
|
Only if set to <literal>true</literal>, the options
|
||||||
|
<option>services.deluge.config</option>,
|
||||||
|
<option>services.deluge.openFirewall</option> and
|
||||||
|
<option>services.deluge.authFile</option> will be
|
||||||
|
applied.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Whether to open the firewall for the ports in
|
||||||
|
<option>services.deluge.config.listen_ports</option>. It only takes effet if
|
||||||
|
<option>services.deluge.declarative</option> is set to
|
||||||
|
<literal>true</literal>.
|
||||||
|
|
||||||
|
It does NOT apply to the daemon port nor the web UI port. To access those
|
||||||
|
ports secuerly check the documentation
|
||||||
|
<link xlink:href="https://dev.deluge-torrent.org/wiki/UserGuide/ThinClient#CreateSSHTunnel"/>
|
||||||
|
or use a VPN or configure certificates for deluge.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dataDir = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/var/lib/deluge";
|
||||||
|
description = ''
|
||||||
|
The directory where deluge will create files.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
authFile = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
example = "/run/keys/deluge-auth";
|
||||||
|
description = ''
|
||||||
|
The file managing the authentication for deluge, the format of this
|
||||||
|
file is straightforward, each line contains a
|
||||||
|
username:password:level tuple in plaintext. It only has an effect
|
||||||
|
when <option>services.deluge.declarative</option> is set to
|
||||||
|
<literal>true</literal>.
|
||||||
|
See <link xlink:href="https://dev.deluge-torrent.org/wiki/UserGuide/Authentication"/> for
|
||||||
|
more informations.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
deluge.web.enable = mkEnableOption "Deluge Web daemon";
|
deluge.web = {
|
||||||
|
enable = mkEnableOption "Deluge Web daemon";
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 8112;
|
||||||
|
description = ''
|
||||||
|
Deluge web UI port.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [ "d '${configDir}' 0770 deluge deluge" ]
|
||||||
|
++ optional (cfg.config ? "download_location")
|
||||||
|
"d '${cfg.config.download_location}' 0770 deluge deluge"
|
||||||
|
++ optional (cfg.config ? "torrentfiles_location")
|
||||||
|
"d '${cfg.config.torrentfiles_location}' 0770 deluge deluge"
|
||||||
|
++ optional (cfg.config ? "move_completed_path")
|
||||||
|
"d '${cfg.config.move_completed_path}' 0770 deluge deluge";
|
||||||
|
|
||||||
systemd.services.deluged = {
|
systemd.services.deluged = {
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
description = "Deluge BitTorrent Daemon";
|
description = "Deluge BitTorrent Daemon";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
path = [ pkgs.deluge ];
|
path = [ pkgs.deluge ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.deluge}/bin/deluged -d";
|
ExecStart = ''
|
||||||
# To prevent "Quit & shutdown daemon" from working; we want systemd to manage it!
|
${pkgs.deluge}/bin/deluged \
|
||||||
|
--do-not-daemonize \
|
||||||
|
--config ${configDir}
|
||||||
|
'';
|
||||||
|
# To prevent "Quit & shutdown daemon" from working; we want systemd to
|
||||||
|
# manage it!
|
||||||
Restart = "on-success";
|
Restart = "on-success";
|
||||||
User = "deluge";
|
User = "deluge";
|
||||||
Group = "deluge";
|
Group = "deluge";
|
||||||
|
UMask = "0002";
|
||||||
LimitNOFILE = cfg.openFilesLimit;
|
LimitNOFILE = cfg.openFilesLimit;
|
||||||
};
|
};
|
||||||
|
preStart = preStart;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.delugeweb = mkIf cfg_web.enable {
|
systemd.services.delugeweb = mkIf cfg_web.enable {
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" "deluged.service"];
|
||||||
|
requires = [ "deluged.service" ];
|
||||||
description = "Deluge BitTorrent WebUI";
|
description = "Deluge BitTorrent WebUI";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
path = [ pkgs.deluge ];
|
path = [ pkgs.deluge ];
|
||||||
serviceConfig.ExecStart = "${pkgs.deluge}/bin/deluge --ui web";
|
serviceConfig = {
|
||||||
serviceConfig.User = "deluge";
|
ExecStart = ''
|
||||||
serviceConfig.Group = "deluge";
|
${pkgs.deluge}/bin/deluge-web \
|
||||||
|
--config ${configDir} \
|
||||||
|
--port ${toString cfg.web.port}
|
||||||
|
'';
|
||||||
|
User = "deluge";
|
||||||
|
Group = "deluge";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall = mkIf (cfg.declarative && cfg.openFirewall && !(cfg.config.random_port or true)) {
|
||||||
|
allowedTCPPortRanges = singleton (listToRange (cfg.config.listen_ports or listenPortsDefault));
|
||||||
|
allowedUDPPortRanges = singleton (listToRange (cfg.config.listen_ports or listenPortsDefault));
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.deluge ];
|
environment.systemPackages = [ pkgs.deluge ];
|
||||||
@ -58,7 +192,7 @@ in {
|
|||||||
users.users.deluge = {
|
users.users.deluge = {
|
||||||
group = "deluge";
|
group = "deluge";
|
||||||
uid = config.ids.uids.deluge;
|
uid = config.ids.uids.deluge;
|
||||||
home = "/var/lib/deluge/";
|
home = cfg.dataDir;
|
||||||
createHome = true;
|
createHome = true;
|
||||||
description = "Deluge Daemon user";
|
description = "Deluge Daemon user";
|
||||||
};
|
};
|
||||||
|
@ -5,25 +5,56 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||||||
};
|
};
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
server =
|
simple = {
|
||||||
|
services.deluge = {
|
||||||
|
enable = true;
|
||||||
|
web.enable = true;
|
||||||
|
};
|
||||||
|
networking.firewall.allowedTCPPorts = [ 8112 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
declarative =
|
||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{ services.deluge = {
|
{
|
||||||
|
services.deluge = {
|
||||||
enable = true;
|
enable = true;
|
||||||
web.enable = true;
|
openFirewall = true;
|
||||||
|
declarative = true;
|
||||||
|
config = {
|
||||||
|
allow_remote = true;
|
||||||
|
download_location = "/var/lib/deluge/my-download";
|
||||||
|
daemon_port = 58846;
|
||||||
|
listen_ports = [ 6881 6889 ];
|
||||||
|
};
|
||||||
|
web = {
|
||||||
|
enable = true;
|
||||||
|
port = 3142;
|
||||||
|
};
|
||||||
|
authFile = pkgs.writeText "deluge-auth" ''
|
||||||
|
localclient:a7bef72a890:10
|
||||||
|
andrew:password:10
|
||||||
|
user3:anotherpass:5
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
networking.firewall.allowedTCPPorts = [ 8112 ];
|
environment.systemPackages = [ pkgs.deluge ];
|
||||||
};
|
};
|
||||||
|
|
||||||
client = { };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
startAll;
|
startAll;
|
||||||
|
|
||||||
$server->waitForUnit("deluged");
|
$simple->waitForUnit("deluged");
|
||||||
$server->waitForUnit("delugeweb");
|
$simple->waitForUnit("delugeweb");
|
||||||
$client->waitForUnit("network.target");
|
$simple->waitForOpenPort("8112");
|
||||||
$client->waitUntilSucceeds("curl --fail http://server:8112");
|
$declarative->waitForUnit("network.target");
|
||||||
|
$declarative->waitUntilSucceeds("curl --fail http://simple:8112");
|
||||||
|
|
||||||
|
$declarative->waitForUnit("deluged");
|
||||||
|
$declarative->waitForUnit("delugeweb");
|
||||||
|
$declarative->waitUntilSucceeds("curl --fail http://declarative:3142");
|
||||||
|
$declarative->succeed("deluge-console 'help' | grep -q 'rm - Remove a torrent'");
|
||||||
|
$declarative->succeed("deluge-console 'connect 127.0.0.1:58846 andrew password; help' | grep -q 'rm - Remove a torrent'");
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user