2014-04-14 15:26:48 +01:00
|
|
|
{ config, lib, pkgs, ... }:
|
2013-03-01 20:12:38 +00:00
|
|
|
|
2014-04-14 15:26:48 +01:00
|
|
|
with lib;
|
2013-03-01 20:12:38 +00:00
|
|
|
|
|
|
|
let
|
|
|
|
cfg = config.services.transmission;
|
2014-04-15 12:50:39 +01:00
|
|
|
apparmor = config.security.apparmor.enable;
|
|
|
|
|
2017-09-09 21:19:35 +01:00
|
|
|
homeDir = cfg.home;
|
2014-04-15 12:50:39 +01:00
|
|
|
downloadDir = "${homeDir}/Downloads";
|
|
|
|
incompleteDir = "${homeDir}/.incomplete";
|
2015-09-30 19:17:17 +01:00
|
|
|
|
2013-03-01 20:12:38 +00:00
|
|
|
settingsDir = "${homeDir}/.config/transmission-daemon";
|
2015-02-23 17:43:10 +00:00
|
|
|
settingsFile = pkgs.writeText "settings.json" (builtins.toJSON fullSettings);
|
2013-03-01 20:12:38 +00:00
|
|
|
|
2014-04-15 12:50:39 +01:00
|
|
|
# for users in group "transmission" to have access to torrents
|
2016-03-02 18:26:48 +00:00
|
|
|
fullSettings = { umask = 2; download-dir = downloadDir; incomplete-dir = incompleteDir; } // cfg.settings;
|
2018-03-18 16:25:19 +00:00
|
|
|
|
2018-03-18 17:09:42 +00:00
|
|
|
# Directories transmission expects to exist and be ug+rwx.
|
|
|
|
directoriesToManage = [ homeDir settingsDir fullSettings.download-dir fullSettings.incomplete-dir ];
|
|
|
|
|
2018-03-18 16:25:19 +00:00
|
|
|
preStart = pkgs.writeScript "transmission-pre-start" ''
|
|
|
|
#!${pkgs.runtimeShell}
|
|
|
|
set -ex
|
2018-03-18 17:09:42 +00:00
|
|
|
for DIR in ${escapeShellArgs directoriesToManage}; do
|
2018-03-18 16:25:19 +00:00
|
|
|
mkdir -p "$DIR"
|
|
|
|
chmod 770 "$DIR"
|
|
|
|
done
|
|
|
|
cp -f ${settingsFile} ${settingsDir}/settings.json
|
|
|
|
'';
|
2013-03-01 20:12:38 +00:00
|
|
|
in
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
services.transmission = {
|
|
|
|
enable = mkOption {
|
2015-06-15 17:10:26 +01:00
|
|
|
type = types.bool;
|
2013-03-01 20:12:38 +00:00
|
|
|
default = false;
|
|
|
|
description = ''
|
|
|
|
Whether or not to enable the headless Transmission BitTorrent daemon.
|
|
|
|
|
|
|
|
Transmission daemon can be controlled via the RPC interface using
|
|
|
|
transmission-remote or the WebUI (http://localhost:9091/ by default).
|
|
|
|
|
2015-09-30 19:17:17 +01:00
|
|
|
Torrents are downloaded to ${downloadDir} by default and are
|
2013-03-01 20:12:38 +00:00
|
|
|
accessible to users in the "transmission" group.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
settings = mkOption {
|
|
|
|
type = types.attrs;
|
|
|
|
default =
|
|
|
|
{
|
2014-04-15 12:50:39 +01:00
|
|
|
download-dir = downloadDir;
|
|
|
|
incomplete-dir = incompleteDir;
|
|
|
|
incomplete-dir-enabled = true;
|
|
|
|
};
|
2013-03-01 20:12:38 +00:00
|
|
|
example =
|
|
|
|
{
|
|
|
|
download-dir = "/srv/torrents/";
|
|
|
|
incomplete-dir = "/srv/torrents/.incomplete/";
|
|
|
|
incomplete-dir-enabled = true;
|
|
|
|
rpc-whitelist = "127.0.0.1,192.168.*.*";
|
2014-04-15 12:50:39 +01:00
|
|
|
};
|
2013-03-01 20:12:38 +00:00
|
|
|
description = ''
|
|
|
|
Attribute set whos fields overwrites fields in settings.json (each
|
|
|
|
time the service starts). String values must be quoted, integer and
|
|
|
|
boolean values must not.
|
|
|
|
|
2018-04-03 21:32:36 +01:00
|
|
|
See https://github.com/transmission/transmission/wiki/Editing-Configuration-Files
|
|
|
|
for documentation.
|
2013-03-01 20:12:38 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2014-04-15 12:50:39 +01:00
|
|
|
port = mkOption {
|
2015-06-15 17:11:32 +01:00
|
|
|
type = types.int;
|
2013-03-01 20:12:38 +00:00
|
|
|
default = 9091;
|
|
|
|
description = "TCP port number to run the RPC/web interface.";
|
|
|
|
};
|
2017-09-09 21:19:35 +01:00
|
|
|
|
|
|
|
home = mkOption {
|
|
|
|
type = types.path;
|
|
|
|
default = "/var/lib/transmission";
|
|
|
|
description = ''
|
|
|
|
The directory where transmission will create files.
|
|
|
|
'';
|
|
|
|
};
|
2013-03-01 20:12:38 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
systemd.services.transmission = {
|
2014-04-15 12:50:39 +01:00
|
|
|
description = "Transmission BitTorrent Service";
|
2014-11-04 17:28:54 +00:00
|
|
|
after = [ "local-fs.target" "network.target" ] ++ optional apparmor "apparmor.service";
|
2014-04-15 12:50:39 +01:00
|
|
|
requires = mkIf apparmor [ "apparmor.service" ];
|
2013-03-01 20:12:38 +00:00
|
|
|
wantedBy = [ "multi-user.target" ];
|
2013-05-28 18:48:08 +01:00
|
|
|
|
2013-03-01 20:12:38 +00:00
|
|
|
# 1) Only the "transmission" user and group have access to torrents.
|
|
|
|
# 2) Optionally update/force specific fields into the configuration file.
|
2018-03-18 16:25:19 +00:00
|
|
|
serviceConfig.ExecStartPre = preStart;
|
2014-04-15 12:50:39 +01:00
|
|
|
serviceConfig.ExecStart = "${pkgs.transmission}/bin/transmission-daemon -f --port ${toString config.services.transmission.port}";
|
2013-05-11 11:15:32 +01:00
|
|
|
serviceConfig.ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
2013-03-01 20:12:38 +00:00
|
|
|
serviceConfig.User = "transmission";
|
|
|
|
# NOTE: transmission has an internal umask that also must be set (in settings.json)
|
|
|
|
serviceConfig.UMask = "0002";
|
|
|
|
};
|
|
|
|
|
|
|
|
# It's useful to have transmission in path, e.g. for remote control
|
|
|
|
environment.systemPackages = [ pkgs.transmission ];
|
|
|
|
|
2018-06-30 00:58:35 +01:00
|
|
|
users.groups.transmission.gid = config.ids.gids.transmission;
|
|
|
|
users.users.transmission = {
|
2013-03-01 20:12:38 +00:00
|
|
|
group = "transmission";
|
2013-08-23 10:33:24 +01:00
|
|
|
uid = config.ids.uids.transmission;
|
2013-03-01 20:12:38 +00:00
|
|
|
description = "Transmission BitTorrent user";
|
|
|
|
home = homeDir;
|
|
|
|
createHome = true;
|
|
|
|
};
|
|
|
|
|
2013-05-28 18:19:15 +01:00
|
|
|
# AppArmor profile
|
2014-04-15 12:50:39 +01:00
|
|
|
security.apparmor.profiles = mkIf apparmor [
|
2013-05-28 18:19:15 +01:00
|
|
|
(pkgs.writeText "apparmor-transmission-daemon" ''
|
|
|
|
#include <tunables/global>
|
|
|
|
|
|
|
|
${pkgs.transmission}/bin/transmission-daemon {
|
|
|
|
#include <abstractions/base>
|
|
|
|
#include <abstractions/nameservice>
|
|
|
|
|
2016-05-21 11:08:51 +01:00
|
|
|
${getLib pkgs.glibc}/lib/*.so mr,
|
|
|
|
${getLib pkgs.libevent}/lib/libevent*.so* mr,
|
|
|
|
${getLib pkgs.curl}/lib/libcurl*.so* mr,
|
|
|
|
${getLib pkgs.openssl}/lib/libssl*.so* mr,
|
|
|
|
${getLib pkgs.openssl}/lib/libcrypto*.so* mr,
|
|
|
|
${getLib pkgs.zlib}/lib/libz*.so* mr,
|
|
|
|
${getLib pkgs.libssh2}/lib/libssh2*.so* mr,
|
|
|
|
${getLib pkgs.systemd}/lib/libsystemd*.so* mr,
|
|
|
|
${getLib pkgs.xz}/lib/liblzma*.so* mr,
|
|
|
|
${getLib pkgs.libgcrypt}/lib/libgcrypt*.so* mr,
|
|
|
|
${getLib pkgs.libgpgerror}/lib/libgpg-error*.so* mr,
|
|
|
|
${getLib pkgs.nghttp2}/lib/libnghttp2*.so* mr,
|
|
|
|
${getLib pkgs.c-ares}/lib/libcares*.so* mr,
|
|
|
|
${getLib pkgs.libcap}/lib/libcap*.so* mr,
|
|
|
|
${getLib pkgs.attr}/lib/libattr*.so* mr,
|
|
|
|
${getLib pkgs.lz4}/lib/liblz4*.so* mr,
|
2018-04-13 19:50:30 +01:00
|
|
|
${getLib pkgs.libkrb5}/lib/lib*.so* mr,
|
2018-08-29 13:48:59 +01:00
|
|
|
${getLib pkgs.keyutils}/lib/libkeyutils*.so* mr,
|
2013-05-28 18:19:15 +01:00
|
|
|
|
|
|
|
@{PROC}/sys/kernel/random/uuid r,
|
|
|
|
@{PROC}/sys/vm/overcommit_memory r,
|
|
|
|
|
2016-08-23 02:36:49 +01:00
|
|
|
${pkgs.openssl.out}/etc/** r,
|
2013-05-28 18:19:15 +01:00
|
|
|
${pkgs.transmission}/share/transmission/** r,
|
|
|
|
|
|
|
|
owner ${settingsDir}/** rw,
|
|
|
|
|
2014-04-15 12:50:39 +01:00
|
|
|
${fullSettings.download-dir}/** rw,
|
|
|
|
${optionalString fullSettings.incomplete-dir-enabled ''
|
|
|
|
${fullSettings.incomplete-dir}/** rw,
|
2013-05-28 18:19:15 +01:00
|
|
|
''}
|
|
|
|
}
|
|
|
|
'')
|
|
|
|
];
|
2013-03-01 20:12:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|