summary refs log tree commit diff
path: root/modules/services/torrent/transmission.nix
diff options
context:
space:
mode:
authorBjørn Forsman <bjorn.forsman@gmail.com>2013-03-01 21:12:38 +0100
committerBjørn Forsman <bjorn.forsman@gmail.com>2013-03-08 16:47:09 +0100
commitd89ba0697f960f5a316aad419c88ee525827a0a9 (patch)
tree98e01848b50e1499d27b8ef7b3ed13dbcefd1996 /modules/services/torrent/transmission.nix
parentf1d48aec43947e5dddae8ba02e3133ee8d0d0ff9 (diff)
downloadnixpkgs-d89ba0697f960f5a316aad419c88ee525827a0a9.tar
nixpkgs-d89ba0697f960f5a316aad419c88ee525827a0a9.tar.gz
nixpkgs-d89ba0697f960f5a316aad419c88ee525827a0a9.tar.bz2
nixpkgs-d89ba0697f960f5a316aad419c88ee525827a0a9.tar.lz
nixpkgs-d89ba0697f960f5a316aad419c88ee525827a0a9.tar.xz
nixpkgs-d89ba0697f960f5a316aad419c88ee525827a0a9.tar.zst
nixpkgs-d89ba0697f960f5a316aad419c88ee525827a0a9.zip
Add Transmission BitTorrent service
Enable it with

  services.transmission.enable = true;

and optionally configure it

  services.transmission.settings =
    {
      download-dir = "/srv/torrents/";
      incomplete-dir = "/srv/torrents/.incomplete/";
      incomplete-dir-enabled = true;
      rpc-whitelist = "127.0.0.1,192.168.*.*";
      # for users in group "transmission" to have access to torrents
      umask = 2;
    };

The above settings are written/merged into settings.json each time the
service is about to start.
Diffstat (limited to 'modules/services/torrent/transmission.nix')
-rw-r--r--modules/services/torrent/transmission.nix134
1 files changed, 134 insertions, 0 deletions
diff --git a/modules/services/torrent/transmission.nix b/modules/services/torrent/transmission.nix
new file mode 100644
index 00000000000..c3dc1f80f14
--- /dev/null
+++ b/modules/services/torrent/transmission.nix
@@ -0,0 +1,134 @@
+# NixOS module for Transmission BitTorrent daemon
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.services.transmission;
+  homeDir = "/var/lib/transmission";
+  settingsDir = "${homeDir}/.config/transmission-daemon";
+  settingsFile = "${settingsDir}/settings.json";
+
+  # Strings must be quoted, ints and bools must not (for settings.json).
+  toOption = x:
+    if x == true then "true"
+    else if x == false then "false"
+    else if builtins.isInt x then toString x
+    else toString ''\"${x}\"'';
+
+  # All lines in settings.json end with a ',' (comma), except for the last
+  # line. This is standard JSON. But a comma can also appear *inside* some
+  # fields, notably the "rpc-whitelist" field. This is difficult to handle in
+  # sed so we simply ignore it and say that if you want to change the option at
+  # the last line of settings.json, you have to do it manually. At this time of
+  # writing, the last option is "utp-enable":true.
+  attrsToSedArgs = as:
+    concatStrings (concatLists (mapAttrsToList (name: value:
+      #map (x: '' -e 's=\(\"${name}\":\)[^,]*\(.*\)=\1 ${toOption x}\2=' '') # breaks if comma inside value field
+      map (x: '' -e 's=\(\"${name}\":\).*=\1 ${toOption x},=' '') # always append ',' (breaks last line in settings.json)
+        (if isList value then value else [value]))
+        as));
+
+in
+
+{
+
+  ### configuration
+
+  options = {
+
+    services.transmission = {
+
+      enable = mkOption {
+        type = types.uniq types.bool;
+        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).
+
+          Torrents are downloaded to ${homeDir}/Downloads/ by default and are
+          accessible to users in the "transmission" group.
+        '';
+      };
+
+      settings = mkOption {
+        type = types.attrs;
+        default =
+          {
+            # for users in group "transmission" to have access to torrents
+            umask = 2;
+          }
+        ;
+        example =
+          {
+            download-dir = "/srv/torrents/";
+            incomplete-dir = "/srv/torrents/.incomplete/";
+            incomplete-dir-enabled = true;
+            rpc-whitelist = "127.0.0.1,192.168.*.*";
+            # 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}."
+        '';
+      };
+
+      rpc_port = mkOption {
+        type = types.uniq types.int;
+        default = 9091;
+        description = "TCP port number to run the RPC/web interface.";
+      };
+
+    };
+
+  };
+
+  ### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.transmission = {
+      description = "Transmission BitTorrent Daemon";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      # 1) Only the "transmission" user and group have access to torrents.
+      # 2) Optionally update/force specific fields into the configuration file.
+      serviceConfig.ExecStartPre =
+        if config.services.transmission.settings != {} then ''
+          ${pkgs.stdenv.shell} -c "chmod 770 ${homeDir} && mkdir -p ${settingsDir} && ${pkgs.transmission}/bin/transmission-daemon -d |& sed ${attrsToSedArgs config.services.transmission.settings} > ${settingsFile}.tmp && mv ${settingsFile}.tmp ${settingsFile}"
+        ''
+        else ''
+          ${pkgs.stdenv.shell} -c "chmod 770 ${homeDir}"
+        '';
+      serviceConfig.ExecStart = "${pkgs.transmission}/bin/transmission-daemon -f --port ${toString config.services.transmission.rpc_port}";
+      serviceConfig.ExecReload = "kill -HUP $MAINPID";
+      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 ];
+
+    users.extraUsers.transmission = {
+      group = "transmission";
+      description = "Transmission BitTorrent user";
+      home = homeDir;
+      createHome = true;
+    };
+
+    users.extraGroups.transmission = {};
+
+  };
+
+}