about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/services/torrent
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/torrent')
-rw-r--r--nixpkgs/nixos/modules/services/torrent/deluge.nix68
-rw-r--r--nixpkgs/nixos/modules/services/torrent/flexget.nix100
-rw-r--r--nixpkgs/nixos/modules/services/torrent/opentracker.nix45
-rw-r--r--nixpkgs/nixos/modules/services/torrent/peerflix.nix65
-rw-r--r--nixpkgs/nixos/modules/services/torrent/transmission.nix167
5 files changed, 445 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/torrent/deluge.nix b/nixpkgs/nixos/modules/services/torrent/deluge.nix
new file mode 100644
index 000000000000..84f0437b9411
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/torrent/deluge.nix
@@ -0,0 +1,68 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.deluge;
+  cfg_web = config.services.deluge.web;
+  openFilesLimit = 4096;
+
+in {
+  options = {
+    services = {
+      deluge = {
+        enable = mkEnableOption "Deluge daemon";
+
+        openFilesLimit = mkOption {
+          default = openFilesLimit;
+          example = 8192;
+          description = ''
+            Number of files to allow deluged to open.
+          '';
+        };
+      };
+
+      deluge.web.enable = mkEnableOption "Deluge Web daemon";
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.deluged = {
+      after = [ "network.target" ];
+      description = "Deluge BitTorrent Daemon";
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.deluge ];
+      serviceConfig = {
+        ExecStart = "${pkgs.deluge}/bin/deluged -d";
+        # To prevent "Quit & shutdown daemon" from working; we want systemd to manage it!
+        Restart = "on-success";
+        User = "deluge";
+        Group = "deluge";
+        LimitNOFILE = cfg.openFilesLimit;
+      };
+    };
+
+    systemd.services.delugeweb = mkIf cfg_web.enable {
+      after = [ "network.target" ];
+      description = "Deluge BitTorrent WebUI";
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.deluge ];
+      serviceConfig.ExecStart = "${pkgs.deluge}/bin/deluge --ui web";
+      serviceConfig.User = "deluge";
+      serviceConfig.Group = "deluge";
+    };
+
+    environment.systemPackages = [ pkgs.deluge ];
+
+    users.users.deluge = {
+      group = "deluge";
+      uid = config.ids.uids.deluge;
+      home = "/var/lib/deluge/";
+      createHome = true;
+      description = "Deluge Daemon user";
+    };
+
+    users.groups.deluge.gid = config.ids.gids.deluge;
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/torrent/flexget.nix b/nixpkgs/nixos/modules/services/torrent/flexget.nix
new file mode 100644
index 000000000000..ca63f529a5df
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/torrent/flexget.nix
@@ -0,0 +1,100 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.flexget;
+  pkg = pkgs.flexget;
+  ymlFile = pkgs.writeText "flexget.yml" ''
+    ${cfg.config}
+
+    ${optionalString cfg.systemScheduler "schedules: no"}
+'';
+  configFile = "${toString cfg.homeDir}/flexget.yml";
+in {
+  options = {
+    services.flexget = {
+      enable = mkEnableOption "Run FlexGet Daemon";
+
+      user = mkOption {
+        default = "deluge";
+        example = "some_user";
+        type = types.string;
+        description = "The user under which to run flexget.";
+      };
+
+      homeDir = mkOption {
+        default = "/var/lib/deluge";
+        example = "/home/flexget";
+        type = types.path;
+        description = "Where files live.";
+      };
+
+      interval = mkOption {
+        default = "10m";
+        example = "1h";
+        type = types.string;
+        description = "When to perform a <command>flexget</command> run. See <command>man 7 systemd.time</command> for the format.";
+      };
+
+      systemScheduler = mkOption {
+        default = true;
+        example = "false";
+        type = types.bool;
+        description = "When true, execute the runs via the flexget-runner.timer. If false, you have to specify the settings yourself in the YML file.";
+      };
+
+      config = mkOption {
+        default = "";
+        type = types.lines;
+        description = "The YAML configuration for FlexGet.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkg ];
+
+    systemd.services = {
+      flexget = {
+        description = "FlexGet Daemon";
+        path = [ pkg ];
+        serviceConfig = {
+          User = cfg.user;
+          Environment = "TZ=${config.time.timeZone}";
+          ExecStartPre = "${pkgs.coreutils}/bin/install -m644 ${ymlFile} ${configFile}";
+          ExecStart = "${pkg}/bin/flexget -c ${configFile} daemon start";
+          ExecStop = "${pkg}/bin/flexget -c ${configFile} daemon stop";
+          ExecReload = "${pkg}/bin/flexget -c ${configFile} daemon reload";
+          Restart = "on-failure";
+          PrivateTmp = true;
+          WorkingDirectory = toString cfg.homeDir;
+        };
+        wantedBy = [ "multi-user.target" ];
+      };
+
+      flexget-runner = mkIf cfg.systemScheduler {
+        description = "FlexGet Runner";
+        after = [ "flexget.service" ];
+        wants = [ "flexget.service" ];
+        serviceConfig = {
+          User = cfg.user;
+          ExecStart = "${pkg}/bin/flexget -c ${configFile} execute";
+          PrivateTmp = true;
+          WorkingDirectory = toString cfg.homeDir;
+        };
+      };
+    };
+
+    systemd.timers.flexget-runner = mkIf cfg.systemScheduler {
+      description = "Run FlexGet every ${cfg.interval}";
+      wantedBy = [ "timers.target" ];
+      timerConfig = {
+        OnBootSec = "5m";
+        OnUnitInactiveSec = cfg.interval;
+        Unit = "flexget-runner.service";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/torrent/opentracker.nix b/nixpkgs/nixos/modules/services/torrent/opentracker.nix
new file mode 100644
index 000000000000..74f443381d92
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/torrent/opentracker.nix
@@ -0,0 +1,45 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.opentracker;
+in {
+  options.services.opentracker = {
+    enable = mkEnableOption "opentracker";
+
+    package = mkOption {
+      type = types.package;
+      description = ''
+        opentracker package to use
+      '';
+      default = pkgs.opentracker;
+      defaultText = "pkgs.opentracker";
+    };
+
+    extraOptions = mkOption {
+      type = types.separatedString " ";
+      description = ''
+        Configuration Arguments for opentracker
+        See https://erdgeist.org/arts/software/opentracker/ for all params
+      '';
+      default = "";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    systemd.services.opentracker = {
+      description = "opentracker server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      restartIfChanged = true;
+      serviceConfig = {
+        ExecStart = "${cfg.package}/bin/opentracker ${cfg.extraOptions}";
+        PrivateTmp = true;
+        WorkingDirectory = "/var/empty";
+        # By default opentracker drops all privileges and runs in chroot after starting up as root.
+      };
+    };
+  };
+}
+
diff --git a/nixpkgs/nixos/modules/services/torrent/peerflix.nix b/nixpkgs/nixos/modules/services/torrent/peerflix.nix
new file mode 100644
index 000000000000..a74f65984328
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/torrent/peerflix.nix
@@ -0,0 +1,65 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.peerflix;
+
+  configFile = pkgs.writeText "peerflix-config.json" ''
+    {
+      "connections": 50,
+      "tmp": "${cfg.downloadDir}"
+    }
+  '';
+
+in {
+
+  ###### interface
+
+  options.services.peerflix = {
+    enable = mkOption {
+      description = "Whether to enable peerflix service.";
+      default = false;
+      type = types.bool;
+    };
+
+    stateDir = mkOption {
+      description = "Peerflix state directory.";
+      default = "/var/lib/peerflix";
+      type = types.path;
+    };
+
+    downloadDir = mkOption {
+      description = "Peerflix temporary download directory.";
+      default = "${cfg.stateDir}/torrents";
+      type = types.path;
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    systemd.tmpfiles.rules = [
+      "d '${cfg.stateDir}' - peerflix - - -"
+    ];
+
+    systemd.services.peerflix = {
+      description = "Peerflix Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      environment.HOME = cfg.stateDir;
+
+      preStart = ''
+        mkdir -p "${cfg.stateDir}"/{torrents,.config/peerflix-server}
+        ln -fs "${configFile}" "${cfg.stateDir}/.config/peerflix-server/config.json"
+      '';
+
+      serviceConfig = {
+        ExecStart = "${pkgs.nodePackages.peerflix-server}/bin/peerflix-server";
+        User = "peerflix";
+      };
+    };
+
+    users.users.peerflix.uid = config.ids.uids.peerflix;
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/torrent/transmission.nix b/nixpkgs/nixos/modules/services/torrent/transmission.nix
new file mode 100644
index 000000000000..f544928fb6b1
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/torrent/transmission.nix
@@ -0,0 +1,167 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.transmission;
+  apparmor = config.security.apparmor.enable;
+
+  homeDir = cfg.home;
+  downloadDir = "${homeDir}/Downloads";
+  incompleteDir = "${homeDir}/.incomplete";
+
+  settingsDir = "${homeDir}/.config/transmission-daemon";
+  settingsFile = pkgs.writeText "settings.json" (builtins.toJSON fullSettings);
+
+  # for users in group "transmission" to have access to torrents
+  fullSettings = { umask = 2; download-dir = downloadDir; incomplete-dir = incompleteDir; } // cfg.settings;
+
+  # Directories transmission expects to exist and be ug+rwx.
+  directoriesToManage = [ homeDir settingsDir fullSettings.download-dir fullSettings.incomplete-dir ];
+
+  preStart = pkgs.writeScript "transmission-pre-start" ''
+    #!${pkgs.runtimeShell}
+    set -ex
+    for DIR in ${escapeShellArgs directoriesToManage}; do
+      mkdir -p "$DIR"
+      chmod 770 "$DIR"
+    done
+    cp -f ${settingsFile} ${settingsDir}/settings.json
+  '';
+in
+{
+  options = {
+    services.transmission = {
+      enable = mkOption {
+        type = 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 ${downloadDir} by default and are
+          accessible to users in the "transmission" group.
+        '';
+      };
+
+      settings = mkOption {
+        type = types.attrs;
+        default =
+          {
+            download-dir = downloadDir;
+            incomplete-dir = incompleteDir;
+            incomplete-dir-enabled = true;
+          };
+        example =
+          {
+            download-dir = "/srv/torrents/";
+            incomplete-dir = "/srv/torrents/.incomplete/";
+            incomplete-dir-enabled = true;
+            rpc-whitelist = "127.0.0.1,192.168.*.*";
+          };
+        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://github.com/transmission/transmission/wiki/Editing-Configuration-Files
+          for documentation.
+        '';
+      };
+
+      port = mkOption {
+        type = types.int;
+        default = 9091;
+        description = "TCP port number to run the RPC/web interface.";
+      };
+
+      home = mkOption {
+        type = types.path;
+        default = "/var/lib/transmission";
+        description = ''
+          The directory where transmission will create files.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.transmission = {
+      description = "Transmission BitTorrent Service";
+      after = [ "local-fs.target" "network.target" ] ++ optional apparmor "apparmor.service";
+      requires = mkIf apparmor [ "apparmor.service" ];
+      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 = preStart;
+      serviceConfig.ExecStart = "${pkgs.transmission}/bin/transmission-daemon -f --port ${toString config.services.transmission.port}";
+      serviceConfig.ExecReload = "${pkgs.coreutils}/bin/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.groups.transmission.gid = config.ids.gids.transmission;
+    users.users.transmission = {
+      group = "transmission";
+      uid = config.ids.uids.transmission;
+      description = "Transmission BitTorrent user";
+      home = homeDir;
+      createHome = true;
+    };
+
+    # AppArmor profile
+    security.apparmor.profiles = mkIf apparmor [
+      (pkgs.writeText "apparmor-transmission-daemon" ''
+        #include <tunables/global>
+
+        ${pkgs.transmission}/bin/transmission-daemon {
+          #include <abstractions/base>
+          #include <abstractions/nameservice>
+
+          ${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,
+          ${getLib pkgs.libkrb5}/lib/lib*.so*              mr,
+          ${getLib pkgs.keyutils}/lib/libkeyutils*.so*     mr,
+          ${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so.* mr,
+          ${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so.* mr,
+          ${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so.* mr,
+
+          @{PROC}/sys/kernel/random/uuid   r,
+          @{PROC}/sys/vm/overcommit_memory r,
+
+          ${pkgs.openssl.out}/etc/**                     r,
+          ${pkgs.transmission}/share/transmission/** r,
+
+          owner ${settingsDir}/** rw,
+
+          ${fullSettings.download-dir}/** rw,
+          ${optionalString fullSettings.incomplete-dir-enabled ''
+            ${fullSettings.incomplete-dir}/** rw,
+          ''}
+        }
+      '')
+    ];
+  };
+
+}