diff options
author | Vladimír Čunát <v@cunat.cz> | 2019-06-05 11:12:34 +0200 |
---|---|---|
committer | Vladimír Čunát <v@cunat.cz> | 2019-06-05 11:12:34 +0200 |
commit | c0ccf42c69845b10c1acd98e93f2d427d429250a (patch) | |
tree | 05571464ace23e44ea411ad150cdf2d926b3f14a /nixos/modules | |
parent | eb7c14fad15e4762a0f54a83decc964b3ae77409 (diff) | |
parent | 576af1718704f9eca5db0983a94edcf8d06caddd (diff) |
Merge branch 'staging-next' into staging
Diffstat (limited to 'nixos/modules')
-rw-r--r-- | nixos/modules/misc/ids.nix | 4 | ||||
-rw-r--r-- | nixos/modules/module-list.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/audio/jack.nix | 275 | ||||
-rw-r--r-- | nixos/modules/services/desktops/geoclue2.nix | 13 | ||||
-rw-r--r-- | nixos/modules/services/networking/btsync.nix | 324 | ||||
-rw-r--r-- | nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix | 50 | ||||
-rw-r--r-- | nixos/modules/services/system/localtime.nix | 8 | ||||
-rw-r--r-- | nixos/modules/services/torrent/deluge.nix | 152 | ||||
-rw-r--r-- | nixos/modules/services/x11/compton.nix | 36 | ||||
-rw-r--r-- | nixos/modules/services/x11/redshift.nix | 8 | ||||
-rw-r--r-- | nixos/modules/system/boot/loader/grub/grub.nix | 1 | ||||
-rw-r--r-- | nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py | 2 |
12 files changed, 523 insertions, 352 deletions
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 5b7fa5d2b98f..f1118f472e44 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -145,7 +145,7 @@ #notbit = 111; # unused aerospike = 111; ngircd = 112; - btsync = 113; + #btsync = 113; # unused minecraft = 114; vault = 115; rippled = 116; @@ -457,7 +457,7 @@ #notbit = 111; # unused aerospike = 111; #ngircd = 112; # unused - btsync = 113; + #btsync = 113; # unused #minecraft = 114; # unused vault = 115; #ripped = 116; # unused diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 5042470802f0..1017d25bf285 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -184,6 +184,7 @@ ./services/amqp/activemq/default.nix ./services/amqp/rabbitmq.nix ./services/audio/alsa.nix + ./services/audio/jack.nix ./services/audio/icecast.nix ./services/audio/liquidsoap.nix ./services/audio/mpd.nix @@ -542,7 +543,6 @@ ./services/networking/autossh.nix ./services/networking/bird.nix ./services/networking/bitlbee.nix - ./services/networking/btsync.nix ./services/networking/charybdis.nix ./services/networking/chrony.nix ./services/networking/cjdns.nix diff --git a/nixos/modules/services/audio/jack.nix b/nixos/modules/services/audio/jack.nix new file mode 100644 index 000000000000..1364abd40447 --- /dev/null +++ b/nixos/modules/services/audio/jack.nix @@ -0,0 +1,275 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.jack; + + pcmPlugin = cfg.jackd.enable && cfg.alsa.enable; + loopback = cfg.jackd.enable && cfg.loopback.enable; + + enable32BitAlsaPlugins = cfg.alsa.support32Bit && pkgs.stdenv.isx86_64 && pkgs.pkgsi686Linux.alsaLib != null; + + umaskNeeded = versionOlder cfg.jackd.package.version "1.9.12"; + bridgeNeeded = versionAtLeast cfg.jackd.package.version "1.9.12"; +in { + options = { + services.jack = { + jackd = { + enable = mkEnableOption '' + JACK Audio Connection Kit. You need to add yourself to the "jackaudio" group + ''; + + package = mkOption { + # until jack1 promiscuous mode is fixed + internal = true; + type = types.package; + default = pkgs.jack2; + defaultText = "pkgs.jack2"; + example = literalExample "pkgs.jack1"; + description = '' + The JACK package to use. + ''; + }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ + "-dalsa" + ]; + example = literalExample '' + [ "-dalsa" "--device" "hw:1" ]; + ''; + description = '' + Specifies startup command line arguments to pass to JACK server. + ''; + }; + + session = mkOption { + type = types.lines; + description = '' + Commands to run after JACK is started. + ''; + }; + + }; + + alsa = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + Route audio to/from generic ALSA-using applications using ALSA JACK PCM plugin. + ''; + }; + + support32Bit = mkOption { + type = types.bool; + default = false; + description = '' + Whether to support sound for 32-bit ALSA applications on 64-bit system. + ''; + }; + }; + + loopback = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Create ALSA loopback device, instead of using PCM plugin. Has broader + application support (things like Steam will work), but may need fine-tuning + for concrete hardware. + ''; + }; + + index = mkOption { + type = types.int; + default = 10; + description = '' + Index of an ALSA loopback device. + ''; + }; + + config = mkOption { + type = types.lines; + description = '' + ALSA config for loopback device. + ''; + }; + + session = mkOption { + type = types.lines; + description = '' + Additional commands to run to setup loopback device. + ''; + }; + }; + + }; + + }; + + config = mkMerge [ + + (mkIf pcmPlugin { + sound.extraConfig = '' + pcm_type.jack { + libs.native = ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_jack.so ; + ${lib.optionalString enable32BitAlsaPlugins + "libs.32Bit = ${pkgs.pkgsi686Linux.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_jack.so ;"} + } + pcm.!default { + @func getenv + vars [ PCM ] + default "plug:jack" + } + ''; + }) + + (mkIf loopback { + boot.kernelModules = [ "snd-aloop" ]; + boot.kernelParams = [ "snd-aloop.index=${toString cfg.loopback.index}" ]; + sound.extraConfig = cfg.loopback.config; + }) + + (mkIf cfg.jackd.enable { + services.jack.jackd.session = '' + ${lib.optionalString bridgeNeeded "${pkgs.a2jmidid}/bin/a2jmidid -e &"} + ''; + # https://alsa.opensrc.org/Jack_and_Loopback_device_as_Alsa-to-Jack_bridge#id06 + services.jack.loopback.config = '' + pcm.loophw00 { + type hw + card ${toString cfg.loopback.index} + device 0 + subdevice 0 + } + pcm.amix { + type dmix + ipc_key 219345 + slave { + pcm loophw00 + } + } + pcm.asoftvol { + type softvol + slave.pcm "amix" + control { name Master } + } + pcm.cloop { + type hw + card ${toString cfg.loopback.index} + device 1 + subdevice 0 + format S32_LE + } + pcm.loophw01 { + type hw + card ${toString cfg.loopback.index} + device 0 + subdevice 1 + } + pcm.ploop { + type hw + card ${toString cfg.loopback.index} + device 1 + subdevice 1 + format S32_LE + } + pcm.aduplex { + type asym + playback.pcm "asoftvol" + capture.pcm "loophw01" + } + pcm.!default { + type plug + slave.pcm aduplex + } + ''; + services.jack.loopback.session = '' + alsa_in -j cloop -dcloop & + alsa_out -j ploop -dploop & + while [ "$(jack_lsp cloop)" == "" ] || [ "$(jack_lsp ploop)" == "" ]; do sleep 1; done + jack_connect cloop:capture_1 system:playback_1 + jack_connect cloop:capture_2 system:playback_2 + jack_connect system:capture_1 ploop:playback_1 + jack_connect system:capture_2 ploop:playback_2 + ''; + + assertions = [ + { + assertion = !(cfg.alsa.enable && cfg.loopback.enable); + message = "For JACK both alsa and loopback options shouldn't be used at the same time."; + } + ]; + + users.users.jackaudio = { + group = "jackaudio"; + extraGroups = [ "audio" ]; + description = "JACK Audio system service user"; + }; + # http://jackaudio.org/faq/linux_rt_config.html + security.pam.loginLimits = [ + { domain = "@jackaudio"; type = "-"; item = "rtprio"; value = "99"; } + { domain = "@jackaudio"; type = "-"; item = "memlock"; value = "unlimited"; } + ]; + users.groups.jackaudio = {}; + + environment = { + systemPackages = [ cfg.jackd.package ]; + etc."alsa/conf.d/50-jack.conf".source = "${pkgs.alsaPlugins}/etc/alsa/conf.d/50-jack.conf"; + variables.JACK_PROMISCUOUS_SERVER = "jackaudio"; + }; + + services.udev.extraRules = '' + ACTION=="add", SUBSYSTEM=="sound", ATTRS{id}!="Loopback", TAG+="systemd", ENV{SYSTEMD_WANTS}="jack.service" + ''; + + systemd.services.jack = { + description = "JACK Audio Connection Kit"; + serviceConfig = { + User = "jackaudio"; + ExecStart = "${cfg.jackd.package}/bin/jackd ${lib.escapeShellArgs cfg.jackd.extraOptions}"; + LimitRTPRIO = 99; + LimitMEMLOCK = "infinity"; + } // optionalAttrs umaskNeeded { + UMask = "007"; + }; + path = [ cfg.jackd.package ]; + environment = { + JACK_PROMISCUOUS_SERVER = "jackaudio"; + JACK_NO_AUDIO_RESERVATION = "1"; + }; + restartIfChanged = false; + }; + systemd.services.jack-session = { + description = "JACK session"; + script = '' + jack_wait -w + ${cfg.jackd.session} + ${lib.optionalString cfg.loopback.enable cfg.loopback.session} + ''; + serviceConfig = { + RemainAfterExit = true; + User = "jackaudio"; + StateDirectory = "jack"; + LimitRTPRIO = 99; + LimitMEMLOCK = "infinity"; + }; + path = [ cfg.jackd.package ]; + environment = { + JACK_PROMISCUOUS_SERVER = "jackaudio"; + HOME = "/var/lib/jack"; + }; + wantedBy = [ "jack.service" ]; + partOf = [ "jack.service" ]; + after = [ "jack.service" ]; + restartIfChanged = false; + }; + }) + + ]; + + meta.maintainers = [ maintainers.gnidorah ]; +} diff --git a/nixos/modules/services/desktops/geoclue2.nix b/nixos/modules/services/desktops/geoclue2.nix index a16dbc04a5f7..040fe157d52d 100644 --- a/nixos/modules/services/desktops/geoclue2.nix +++ b/nixos/modules/services/desktops/geoclue2.nix @@ -188,6 +188,19 @@ in systemd.packages = [ package ]; + users.users.geoclue = { + isSystemUser = true; + home = "/var/lib/geoclue"; + group = "geoclue"; + description = "Geoinformation service"; + }; + + users.groups.geoclue = {}; + + systemd.tmpfiles.rules = [ + "d /var/lib/geoclue 0755 geoclue geoclue" + ]; + # restart geoclue service when the configuration changes systemd.services."geoclue".restartTriggers = [ config.environment.etc."geoclue/geoclue.conf".source diff --git a/nixos/modules/services/networking/btsync.nix b/nixos/modules/services/networking/btsync.nix deleted file mode 100644 index 33e85ef58e6e..000000000000 --- a/nixos/modules/services/networking/btsync.nix +++ /dev/null @@ -1,324 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.services.btsync; - - bittorrentSync = cfg.package; - - listenAddr = cfg.httpListenAddr + ":" + (toString cfg.httpListenPort); - - optionalEmptyStr = b: v: optionalString (b != "") v; - - webUIConfig = optionalString cfg.enableWebUI - '' - "webui": - { - ${optionalEmptyStr cfg.httpLogin "\"login\": \"${cfg.httpLogin}\","} - ${optionalEmptyStr cfg.httpPass "\"password\": \"${cfg.httpPass}\","} - ${optionalEmptyStr cfg.apiKey "\"api_key\": \"${cfg.apiKey}\","} - ${optionalEmptyStr cfg.directoryRoot "\"directory_root\": \"${cfg.directoryRoot}\","} - "listen": "${listenAddr}" - } - ''; - - knownHosts = e: - optionalString (e ? "knownHosts") - (concatStringsSep "," (map (v: "\"${v}\"") e."knownHosts")); - - sharedFoldersRecord = - concatStringsSep "," (map (entry: - let helper = attr: v: - if (entry ? attr) then boolToString entry.attr else boolToString v; - in - '' - { - "secret": "${entry.secret}", - "dir": "${entry.directory}", - - "use_relay_server": ${helper "useRelayServer" true}, - "use_tracker": ${helper "useTracker" true}, - "use_dht": ${helper "useDHT" false}, - - "search_lan": ${helper "searchLAN" true}, - "use_sync_trash": ${helper "useSyncTrash" true}, - - "known_hosts": [${knownHosts entry}] - } - '') cfg.sharedFolders); - - sharedFoldersConfig = optionalString (cfg.sharedFolders != []) - '' - "shared_folders": - [ - ${sharedFoldersRecord} - ] - ''; - - configFile = pkgs.writeText "btsync.config" - '' - { - "device_name": "${cfg.deviceName}", - "storage_path": "${cfg.storagePath}", - "listening_port": ${toString cfg.listeningPort}, - "use_gui": false, - - "check_for_updates": ${boolToString cfg.checkForUpdates}, - "use_upnp": ${boolToString cfg.useUpnp}, - "download_limit": ${toString cfg.downloadLimit}, - "upload_limit": ${toString cfg.uploadLimit}, - "lan_encrypt_data": ${boolToString cfg.encryptLAN}, - - ${webUIConfig} - ${sharedFoldersConfig} - } - ''; -in -{ - options = { - services.btsync = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - If enabled, start the Bittorrent Sync daemon. Once enabled, you can - interact with the service through the Web UI, or configure it in your - NixOS configuration. Enabling the <literal>btsync</literal> service - also installs a systemd user unit which can be used to start - user-specific copies of the daemon. Once installed, you can use - <literal>systemctl --user start btsync</literal> as your user to start - the daemon using the configuration file located at - <literal>$HOME/.config/btsync.conf</literal>. - ''; - }; - - deviceName = mkOption { - type = types.str; - example = "Voltron"; - description = '' - Name of the Bittorrent Sync device. - ''; - }; - - listeningPort = mkOption { - type = types.int; - default = 0; - example = 44444; - description = '' - Listening port. Defaults to 0 which randomizes the port. - ''; - }; - - checkForUpdates = mkOption { - type = types.bool; - default = true; - description = '' - Determines whether to check for updates and alert the user - about them in the UI. - ''; - }; - - useUpnp = mkOption { - type = types.bool; - default = true; - description = '' - Use Universal Plug-n-Play (UPnP) - ''; - }; - - downloadLimit = mkOption { - type = types.int; - default = 0; - example = 1024; - description = '' - Download speed limit. 0 is unlimited (default). - ''; - }; - - uploadLimit = mkOption { - type = types.int; - default = 0; - example = 1024; - description = '' - Upload speed limit. 0 is unlimited (default). - ''; - }; - - httpListenAddr = mkOption { - type = types.str; - default = "0.0.0.0"; - example = "1.2.3.4"; - description = '' - HTTP address to bind to. - ''; - }; - - httpListenPort = mkOption { - type = types.int; - default = 9000; - description = '' - HTTP port to bind on. - ''; - }; - - httpLogin = mkOption { - type = types.str; - example = "allyourbase"; - default = ""; - description = '' - HTTP web login username. - ''; - }; - - httpPass = mkOption { - type = types.str; - example = "arebelongtous"; - default = ""; - description = '' - HTTP web login password. - ''; - }; - - encryptLAN = mkOption { - type = types.bool; - default = true; - description = "Encrypt LAN data."; - }; - - enableWebUI = mkOption { - type = types.bool; - default = false; - description = '' - Enable Web UI for administration. Bound to the specified - <literal>httpListenAddress</literal> and - <literal>httpListenPort</literal>. - ''; - }; - - package = mkOption { - type = types.package; - example = literalExample "pkgs.bittorrentSync20"; - description = '' - Branch of bittorrent sync to use. - ''; - }; - - storagePath = mkOption { - type = types.path; - default = "/var/lib/btsync/"; - description = '' - Where BitTorrent Sync will store it's database files (containing - things like username info and licenses). Generally, you should not - need to ever change this. - ''; - }; - - apiKey = mkOption { - type = types.str; - default = ""; - description = "API key, which enables the developer API."; - }; - - directoryRoot = mkOption { - type = types.str; - default = ""; - example = "/media"; - description = "Default directory to add folders in the web UI."; - }; - - sharedFolders = mkOption { - default = []; - example = - [ { secret = "AHMYFPCQAHBM7LQPFXQ7WV6Y42IGUXJ5Y"; - directory = "/home/user/sync_test"; - useRelayServer = true; - useTracker = true; - useDHT = false; - searchLAN = true; - useSyncTrash = true; - knownHosts = - [ "192.168.1.2:4444" - "192.168.1.3:4444" - ]; - } - ]; - description = '' - Shared folder list. If enabled, web UI must be - disabled. Secrets can be generated using <literal>btsync - --generate-secret</literal>. Note that this secret will be - put inside the Nix store, so it is realistically not very - secret. - - If you would like to be able to modify the contents of this - directories, it is recommended that you make your user a - member of the <literal>btsync</literal> group. - - Directories in this list should be in the - <literal>btsync</literal> group, and that group must have - write access to the directory. It is also recommended that - <literal>chmod g+s</literal> is applied to the directory - so that any sub directories created will also belong to - the <literal>btsync</literal> group. Also, - <literal>setfacl -d -m group:btsync:rwx</literal> and - <literal>setfacl -m group:btsync:rwx</literal> should also - be applied so that the sub directories are writable by - the group. - ''; - }; - }; - }; - - config = mkIf cfg.enable { - assertions = - [ { assertion = cfg.deviceName != ""; - message = "Device name cannot be empty."; - } - { assertion = cfg.enableWebUI -> cfg.sharedFolders == []; - message = "If using shared folders, the web UI cannot be enabled."; - } - { assertion = cfg.apiKey != "" -> cfg.enableWebUI; - message = "If you're using an API key, you must enable the web server."; - } - ]; - - services.btsync.package = mkOptionDefault pkgs.bittorrentSync14; - - users.users.btsync = { - description = "Bittorrent Sync Service user"; - home = cfg.storagePath; - createHome = true; - uid = config.ids.uids.btsync; - group = "btsync"; - }; - - users.groups = [ - { name = "btsync"; - }]; - - systemd.services.btsync = with pkgs; { - description = "Bittorrent Sync Service"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "local-fs.target" ]; - serviceConfig = { - Restart = "on-abort"; - UMask = "0002"; - User = "btsync"; - ExecStart = - "${bittorrentSync}/bin/btsync --nodaemon --config ${configFile}"; - }; - }; - - systemd.user.services.btsync = with pkgs; { - description = "Bittorrent Sync user service"; - after = [ "network.target" "local-fs.target" ]; - serviceConfig = { - Restart = "on-abort"; - ExecStart = - "${bittorrentSync}/bin/btsync --nodaemon --config %h/.config/btsync.conf"; - }; - }; - - environment.systemPackages = [ cfg.package ]; - }; -} diff --git a/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix b/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix index d4f7e95f859f..808cb863a9cf 100644 --- a/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix +++ b/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix @@ -6,7 +6,7 @@ # # git clone https://github.com/strongswan/strongswan.git # cd strongswan -# git diff 5.5.3..5.6.0 src/swanctl/swanctl.opt +# git diff 5.7.2..5.8.0 src/swanctl/swanctl.opt lib: with (import ./param-constructors.nix lib); @@ -227,6 +227,22 @@ in { irrespective of the value of this option (even when set to no). ''; + childless = mkEnumParam [ "allow" "force" "never" ] "allow" '' + Use childless IKE_SA initiation (RFC 6023) for IKEv2. Acceptable values + are <literal>allow</literal> (the default), <literal>force</literal> and + <literal>never</literal>. If set to <literal>allow</literal>, responders + will accept childless IKE_SAs (as indicated via notify in the IKE_SA_INIT + response) while initiators continue to create regular IKE_SAs with the + first CHILD_SA created during IKE_AUTH, unless the IKE_SA is initiated + explicitly without any children (which will fail if the responder does not + support or has disabled this extension). If set to + <literal>force</literal>, only childless initiation is accepted and the + first CHILD_SA is created with a separate CREATE_CHILD_SA exchange + (e.g. to use an independent DH exchange for all CHILD_SAs). Finally, + setting the option to <literal>never</literal> disables support for + childless IKE_SAs as responder. + ''; + send_certreq = mkYesNoParam yes '' Send certificate request payloads to offer trusted root CA certificates to the peer. Certificate requests help the peer to choose an appropriate @@ -350,6 +366,16 @@ in { name from either the pools section or an external pool. ''; + if_id_in = mkStrParam "0" '' + XFRM interface ID set on inbound policies/SA, can be overridden by child + config, see there for details. + ''; + + if_id_out = mkStrParam "0" '' + XFRM interface ID set on outbound policies/SA, can be overridden by child + config, see there for details. + ''; + mediation = mkYesNoParam no '' Whether this connection is a mediation connection, that is, whether this connection is used to mediate other connections using the IKEv2 Mediation @@ -799,7 +825,7 @@ in { Updown script to invoke on CHILD_SA up and down events. ''; - hostaccess = mkYesNoParam yes '' + hostaccess = mkYesNoParam no '' Hostaccess variable to pass to <literal>updown</literal> script. ''; @@ -960,6 +986,26 @@ in { mask requires at least Linux 4.19. ''; + if_id_in = mkStrParam "0" '' + XFRM interface ID set on inbound policies/SA. This allows installing + duplicate policies/SAs and associates them with an interface with the + same ID. The special value <literal>%unique</literal> sets a unique + interface ID on each CHILD_SA instance, beyond that the value + <literal>%unique-dir</literal> assigns a different unique interface ID + for each CHILD_SA direction (in/out). + ''; + + if_id_out = mkStrParam "0" '' + XFRM interface ID set on outbound policies/SA. This allows installing + duplicate policies/SAs and associates them with an interface with the + same ID. The special value <literal>%unique</literal> sets a unique + interface ID on each CHILD_SA instance, beyond that the value + <literal>%unique-dir</literal> assigns a different unique interface ID + for each CHILD_SA direction (in/out). + + The daemon will not install routes for CHILD_SAs that have this option set. + ''; + tfc_padding = mkParamOfType (with lib.types; either int (enum ["mtu"])) 0 '' Pads ESP packets with additional data to have a consistent ESP packet size for improved Traffic Flow Confidentiality. The padding defines the diff --git a/nixos/modules/services/system/localtime.nix b/nixos/modules/services/system/localtime.nix index c7e897c96448..8e9286b94078 100644 --- a/nixos/modules/services/system/localtime.nix +++ b/nixos/modules/services/system/localtime.nix @@ -20,7 +20,13 @@ in { }; config = mkIf cfg.enable { - services.geoclue2.enable = true; + services.geoclue2 = { + enable = true; + appConfig."localtime" = { + isAllowed = true; + isSystem = true; + }; + }; # so polkit will pick up the rules environment.systemPackages = [ pkgs.localtime ]; diff --git a/nixos/modules/services/torrent/deluge.nix b/nixos/modules/services/torrent/deluge.nix index 84f0437b9411..01a5890a7845 100644 --- a/nixos/modules/services/torrent/deluge.nix +++ b/nixos/modules/services/torrent/deluge.nix @@ -5,8 +5,33 @@ 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 = { @@ -15,42 +40,151 @@ in { openFilesLimit = mkOption { default = openFilesLimit; - example = 8192; 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 <option>services.deluge.declarative</option> is set to + <literal>true</literal>. String values must be quoted, integer and + boolean values must not. See + <link xlink:href="https://git.deluge-torrent.org/deluge/tree/deluge/core/preferencesmanager.py#n41"/> + for the availaible options. + ''; + }; + + declarative = mkOption { + type = types.bool; + default = false; + description = '' + Whether to use a declarative deluge configuration. + Only if set to <literal>true</literal>, the options + <option>services.deluge.config</option>, + <option>services.deluge.openFirewall</option> and + <option>services.deluge.authFile</option> will be + applied. + ''; + }; + + openFirewall = mkOption { + default = false; + type = types.bool; + description = '' + Whether to open the firewall for the ports in + <option>services.deluge.config.listen_ports</option>. It only takes effet if + <option>services.deluge.declarative</option> is set to + <literal>true</literal>. + + It does NOT apply to the daemon port nor the web UI port. To access those + ports secuerly check the documentation + <link xlink:href="https://dev.deluge-torrent.org/wiki/UserGuide/ThinClient#CreateSSHTunnel"/> + 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 <option>services.deluge.declarative< |