{ config, lib, pkgs, ... }: with lib; let cfg = config.services.deluge; cfg_web = config.services.deluge.web; 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 { options = { services = { deluge = { enable = mkEnableOption "Deluge daemon"; openFilesLimit = mkOption { default = openFilesLimit; description = '' 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 is set to true. String values must be quoted, integer and boolean values must not. See for the availaible options. ''; }; declarative = mkOption { type = types.bool; default = false; description = '' Whether to use a declarative deluge configuration. Only if set to true, the options , and will be applied. ''; }; openFirewall = mkOption { default = false; type = types.bool; description = '' Whether to open the firewall for the ports in . It only takes effet if is set to true. It does NOT apply to the daemon port nor the web UI port. To access those ports secuerly check the documentation 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 is set to true. See for more informations. ''; }; }; deluge.web = { enable = mkEnableOption "Deluge Web daemon"; port = mkOption { type = types.port; default = 8112; description = '' Deluge web UI port. ''; }; }; }; }; 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 = { after = [ "network.target" ]; description = "Deluge BitTorrent Daemon"; wantedBy = [ "multi-user.target" ]; path = [ pkgs.deluge ]; serviceConfig = { ExecStart = '' ${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"; User = "deluge"; Group = "deluge"; UMask = "0002"; LimitNOFILE = cfg.openFilesLimit; }; preStart = preStart; }; systemd.services.delugeweb = mkIf cfg_web.enable { after = [ "network.target" "deluged.service"]; requires = [ "deluged.service" ]; description = "Deluge BitTorrent WebUI"; wantedBy = [ "multi-user.target" ]; path = [ pkgs.deluge ]; serviceConfig = { ExecStart = '' ${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 ]; users.users.deluge = { group = "deluge"; uid = config.ids.uids.deluge; home = cfg.dataDir; createHome = true; description = "Deluge Daemon user"; }; users.groups.deluge.gid = config.ids.gids.deluge; }; }