@ -1,13 +1,14 @@
# NixOS module for Transmission BitTorrent daemon
{ config , lib , pkgs , . . . }:
with lib ;
let
cfg = config . services . transmission ;
apparmor = config . security . apparmor . enable ;
homeDir = " / v a r / l i b / t r a n s m i s s i o n " ;
downloadDir = " ${ homeDir } / D o w n l o a d s " ;
incompleteDir = " ${ homeDir } / . i n c o m p l e t e " ;
settingsDir = " ${ homeDir } / . c o n f i g / t r a n s m i s s i o n - d a e m o n " ;
settingsFile = " ${ settingsDir } / s e t t i n g s . j s o n " ;
@ -31,16 +32,12 @@ let
( if isList value then value else [ value ] ) )
as ) ) ;
# for users in group "transmission" to have access to torrents
fullSettings = cfg . settings // { umask = 2 ; } ;
in
{
### configuration
options = {
services . transmission = {
enable = mkOption {
type = types . uniq types . bool ;
default = false ;
@ -59,65 +56,48 @@ in
type = types . attrs ;
default =
{
# for users in group "transmission" to have access to torrents
umask = 2 ;
}
;
download-dir = downloadDir ;
incomplete-dir = incompleteDir ;
incomplete-dir-enabled = true ;
} ;
example =
{
download-dir = " / s r v / t o r r e n t s / " ;
incomplete-dir = " / s r v / t o r r e n t s / . i n c o m p l e t e / " ;
incomplete-dir-enabled = true ;
rpc-whitelist = " 1 2 7 . 0 . 0 . 1 , 1 9 2 . 1 6 8 . * . * " ;
# for users in group "transmission" to have access to torrents
umask = 2 ;
}
;
} ;
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 .
See https://trac.transmissionbt.com/wiki/EditConfigFiles for documentation
and/or look at $ { settingsFile } . "
See https://trac.transmissionbt.com/wiki/EditConfigFiles for
documentation and/or look at $ { settingsFile } .
'' ;
} ;
rpc_ port = mkOption {
port = mkOption {
type = types . uniq types . int ;
default = 9091 ;
description = " T C P p o r t n u m b e r t o r u n t h e R P C / w e b i n t e r f a c e . " ;
} ;
apparmor = mkOption {
type = types . uniq types . bool ;
default = true ;
description = " G e n e r a t e a p p a r m o r p r o f i l e f o r t r a n s m i s s i o n - d a e m o n . " ;
} ;
} ;
} ;
### implementation
config = mkIf cfg . enable {
systemd . services . transmission = {
description = " T r a n s m i s s i o n B i t T o r r e n t D a e m o n " ;
after = [ " n e t w o r k . t a r g e t " ] ++ optional ( config . security . apparmor . enable && cfg . apparmor ) " a p p a r m o r . s e r v i c e " ;
requires = mkIf ( config . security . apparmor . enable && cfg . apparmor ) [ " a p p a r m o r . s e r v i c e " ] ;
description = " T r a n s m i s s i o n B i t T o r r e n t S e r v i c e " ;
after = [ " n e t w o r k . t a r g e t " ] ++ optional apparmor " a p p a r m o r . s e r v i c e " ;
requires = mkIf apparmor [ " a p p a r m o r . s e r v i c e " ] ;
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
# 1) Only the "transmission" user and group have access to torrents.
# 2) Optionally update/force specific fields into the configuration file.
serviceConfig . ExecStartPre =
if cfg . settings != { } then ''
$ { pkgs . stdenv . shell } - c " c h m o d 7 7 0 ${ homeDir } & & m k d i r - p ${ settingsDir } & & ${ pkgs . transmission } / b i n / t r a n s m i s s i o n - d a e m o n - d | & s e d ${ attrsToSedArgs cfg . settings } > ${ settingsFile } . t m p & & m v ${ settingsFile } . t m p ${ settingsFile } "
''
else ''
$ { pkgs . stdenv . shell } - c " c h m o d 7 7 0 ${ homeDir } "
'' ;
serviceConfig . ExecStart = " ${ pkgs . transmission } / b i n / t r a n s m i s s i o n - d a e m o n - f - - p o r t ${ toString config . services . transmission . rpc_port } " ;
serviceConfig . ExecStartPre = ''
$ { pkgs . stdenv . shell } - c " c h m o d 7 7 0 ${ homeDir } & & m k d i r - p ${ settingsDir } ${ downloadDir } ${ incompleteDir } & & ${ pkgs . transmission } / b i n / t r a n s m i s s i o n - d a e m o n - d | & s e d ${ attrsToSedArgs fullSettings } > ${ settingsFile } . t m p & & m v ${ settingsFile } . t m p ${ settingsFile } "
'' ;
serviceConfig . ExecStart = " ${ pkgs . transmission } / b i n / t r a n s m i s s i o n - d a e m o n - f - - p o r t ${ toString config . services . transmission . port } " ;
serviceConfig . ExecReload = " ${ pkgs . coreutils } / b i n / k i l l - H U P $ M A I N P I D " ;
serviceConfig . User = " t r a n s m i s s i o n " ;
# NOTE: transmission has an internal umask that also must be set (in settings.json)
@ -127,6 +107,7 @@ in
# It's useful to have transmission in path, e.g. for remote control
environment . systemPackages = [ pkgs . transmission ] ;
users . extraGroups . transmission . gid = config . ids . gids . transmission ;
users . extraUsers . transmission = {
group = " t r a n s m i s s i o n " ;
uid = config . ids . uids . transmission ;
@ -135,10 +116,8 @@ in
createHome = true ;
} ;
users . extraGroups . transmission . gid = config . ids . gids . transmission ;
# AppArmor profile
security . apparmor . profiles = mkIf ( config . security . apparmor . enable && cfg . apparmor ) [
security . apparmor . profiles = mkIf apparmor [
( pkgs . writeText " a p p a r m o r - t r a n s m i s s i o n - d a e m o n " ''
#include <tunables/global>
@ -161,9 +140,9 @@ in
owner $ { settingsDir } /* * r w ,
$ { cfg . s ettings. download-dir } /* * r w ,
$ { optionalString cfg . s ettings. incomplete-dir-enabled ''
$ { cfg . s ettings. incomplete-dir } /* * r w ,
$ { fullS ettings. download-dir } /* * r w ,
$ { optionalString fullS ettings. incomplete-dir-enabled ''
$ { fullS ettings. incomplete-dir } /* * r w ,
'' }
}
'' )