[PATCH 0/1] services: Add Transmission Daemon

  • Done
  • quality assurance status badge
Details
3 participants
  • ???
  • Ludovic Courtès
  • Simon South
Owner
unassigned
Submitted by
Simon South
Severity
normal
S
S
Simon South wrote on 4 Nov 2020 13:37
(address . guix-patches@gnu.org)(address . simon@simonsouth.net)
cover.1604429058.git.simon@simonsouth.net
This patch adds a service type for Transmission Daemon, the headless variant
of the Transmission BitTorrent client (https://transmissionbt.com/).Running
the client as a service this way makes it possible to share files over
BitTorrent continuously without requiring a user be logged in.

I've tried to make this as complete as possible but am especially interested
in geting feedback as this is my first attempt at creating a service
definition. A few things to point out:

- I've placed the code in a new "(gnu services file-sharing)" module and the
documentation in a new "File-Sharing Services" section of the manual, only
because these names seemed the most natural to me. ("Peer-to-peer" would be
too broad a categorization, I think, while "BitTorrent" too narrow.)

- The module exports two procedures, "transmission-password-hash" and
"transmission-random-salt", that together are my solution to the problem of
assigning a value to the daemon's "rpc-password" configuration setting.

Transmission clients seem to expect the user to supply a password in
plaintext in their "settings.json" file. At startup, the client generates a
random, eight-character salt value; hashes it and the password together; and
writes the result back to the settings file, after which the password
remains obscured. This obviously violates the functional nature of Guix, as
we don't expect services to be rewriting their own configuration files and
the use of a random salt value makes the process non-repeatable anyway.

I've documented in the manual how a user can use these two procedures to
create a suitable value for "rpc-password" that remains stable across system
reconfigurations, but perhaps you know of a better (or more conventional)
approach.

- I've added a custom "stop" procedure to the Shepherd service that gives the
daemon time to shut down before eventually killing its process. This is
necessary since the daemon performs some housekeeping and sends a final
update to BitTorrent trackers before it exits, which can take several
seconds or more; without this code, restarting the service usually fails as
the new daemon process finds the old one is still running and attached to
the port used for peer connections.

Again, the approach I've used to handle this seems reasonable to me but
perhaps you know of something better.

--
Simon South
simon@simonsouth.net


Simon South (1):
services: Add transmission-daemon service.

doc/guix.texi | 799 +++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
gnu/services/file-sharing.scm | 806 ++++++++++++++++++++++++++++++++++
3 files changed, 1606 insertions(+)
create mode 100644 gnu/services/file-sharing.scm

--
2.28.0
S
S
Simon South wrote on 4 Nov 2020 13:40
[PATCH 1/1] services: Add transmission-daemon service.
(address . 44435@debbugs.gnu.org)(address . simon@simonsouth.net)
7630c2a18eded24bbfc66d45b353a9faab400d93.1604429058.git.simon@simonsouth.net
* gnu/services/file-sharing.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
* doc/guix.texi (File-Sharing Services): New section.
---
doc/guix.texi | 799 +++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
gnu/services/file-sharing.scm | 806 ++++++++++++++++++++++++++++++++++
3 files changed, 1606 insertions(+)
create mode 100644 gnu/services/file-sharing.scm

Toggle diff (520 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index b7f1bc1f00..dcf57e16e3 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -14364,6 +14364,7 @@ declaration.
* Mail Services:: IMAP, POP3, SMTP, and all that.
* Messaging Services:: Messaging services.
* Telephony Services:: Telephony services.
+* File-Sharing Services:: File-sharing services.
* Monitoring Services:: Monitoring services.
* Kerberos Services:: Kerberos services.
* LDAP Services:: LDAP services.
@@ -21592,6 +21593,804 @@ If it is set your server will be linked by this host name instead.
+@node File-Sharing Services
+@subsection File-Sharing Services
+
+The @code{(gnu services file-sharing)} module provides services that
+assist with transferring files over peer-to-peer file-sharing networks.
+
+@subsubheading Transmission Daemon Service
+
+@uref{https://transmissionbt.com/, Transmission} is a flexible
+BitTorrent client that offers a variety of graphical and command-line
+interfaces. A @code{transmission-daemon-service-type} service provides
+Transmission's headless variant, @command{transmission-daemon}, as a
+system service, allowing users to share files via BitTorrent even when
+they are not logged in.
+
+@deffn {Scheme Variable} transmission-daemon-service-type
+The service type for the Transmission Daemon BitTorrent client. Its
+value must be a @code{transmission-daemon-configuration} object as in
+this example:
+
+@lisp
+(service transmission-daemon-service-type
+ (transmission-daemon-configuration
+ ;; Restrict access to the RPC ("control") interface
+ (rpc-authentication-required? #t)
+ (rpc-username "transmission")
+ (rpc-password
+ (transmission-password-hash
+ "transmission" ; desired password
+ "uKd1uMs9")) ; arbitrary salt value
+
+ ;; Accept requests from this and other hosts on the
+ ;; local network
+ (rpc-whitelist-enabled? #t)
+ (rpc-whitelist '("::1" "127.0.0.1" "192.168.0.*"))
+
+ ;; Limit bandwidth use during work hours
+ (alt-speed-down (* 1024 2)) ; 2 MB/s
+ (alt-speed-up 512) ; 512 kB/s
+
+ (alt-speed-time-enabled? #t)
+ (alt-speed-time-day 'weekdays)
+ (alt-speed-time-begin
+ (+ (* 60 8) 30)) ; 8:30 am
+ (alt-speed-time-end
+ (+ (* 60 (+ 12 5)) 30)))) ; 5:30 pm
+@end lisp
+@end deffn
+
+Once the service is started, users can interact with the daemon through
+its Web interface (at @code{http://localhost:9091/}) or by using the
+@command{transmission-remote} command-line tool, available in the
+@code{transmission} package. (Emacs users may want to also consider the
+@code{emacs-transmission} package.) Both communicate with the daemon
+through its remote procedure call (RPC) interface, which by default is
+available to all users on the system; you may wish to change this by
+assigning values to the @code{rpc-authentication-required?},
+@code{rpc-username} and @code{rpc-password} settings, as shown in the
+example above and documented further below.
+
+The value for @code{rpc-password} must be a password hash of the type
+generated and used by Transmission clients. This can be copied verbatim
+from an existing @file{settings.json} file, if another Transmission
+client is already being used. Otherwise, the
+@code{transmission-password-hash} and @code{transmission-random-salt}
+procedures provided by this module can be used to obtain a suitable hash
+value.
+
+@deffn {Scheme Procedure} transmission-password-hash @var{password} @var{salt}
+Returns a string containing the result of hashing @var{password}
+together with @var{salt}, in the format recognized by Transmission
+clients for their @code{rpc-password} configuration setting.
+
+@var{salt} must be an eight-character string. The
+@code{transmission-random-salt} procedure can be used to generate a
+suitable salt value at random.
+@end deffn
+
+@deffn {Scheme Procedure} transmission-random-salt
+Returns a string containing a random, eight-character salt value of the
+type generated and used by Transmission clients, suitable for passing to
+the @code{transmission-password-hash} procedure.
+@end deffn
+
+These procedures are accessible from within a Guile REPL started with
+the @command{guix repl} command (@pxref {Invoking guix repl}). This is
+useful for obtaining a random salt value to provide as the second
+parameter to `transmission-password-hash`, as in this example session:
+
+@example
+$ guix repl
+scheme@@(guix-user)> ,use (gnu services file-sharing)
+scheme@@(guix-user)> (transmission-random-salt)
+$1 = "uKd1uMs9"
+@end example
+
+Alternatively, a complete password hash can generated in a single step:
+
+@example
+scheme@@(guix-user)> (transmission-password-hash "transmission"
+(transmission-random-salt))
+$2 = "@{c8bbc6d1740cd8dc819a6e25563b67812c1c19c9VtFPfdsX"
+@end example
+
+The resulting string can be used as-is for the value of
+@code{rpc-password}, allowing the password to be kept hidden even in the
+operating-system configuration.
+
+Torrent files downloaded by the daemon are directly accessible only to
+users in the ``transmission'' user group, who receive read-only access
+to the directory specified by the @code{download-dir} configuration
+setting (and also the directory specified by @code{incomplete-dir}, if
+@code{incomplete-dir-enabled?} is @code{#t}). Downloaded files can be
+moved to another directory or deleted altogether using
+@command{transmission-remote} with its @code{--move} and
+@code{--remove-and-delete} options.
+
+If the @code{watch-dir-enabled?} setting is set to @code{#t}, users in
+the ``transmission'' group are able also to place @file{.torrent} files
+in the directory specified by @code{watch-dir} to have the corresponding
+torrents added by the daemon. (The @code{trash-original-torrent-files?}
+setting controls whether the daemon deletes these files after processing
+them.)
+
+Some of the daemon's configuration settings can be changed temporarily
+by @command{transmission-remote} and similar tools. To undo these
+changes, use the service's @code{reload} action to have the daemon
+reload its settings from disk:
+
+@example
+# herd reload transmission-daemon
+@end example
+
+The full set of available configuration settings is defined by the
+@code{transmission-daemon-configuration} data type.
+
+@deftp {Data Type} transmission-daemon-configuration
+The data type representing configuration settings for Transmission
+Daemon. These correspond directly to the settings recognized by
+Transmission clients in their @file{settings.json} file.
+@end deftp
+
+@c The following documentation was initially generated by
+@c (generate-transmission-daemon-documentation) in (gnu services
+@c file-sharing). Manually maintained documentation is better, so we
+@c shouldn't hesitate to edit below as needed. However if the change
+@c you want to make to this documentation can be done in an automated
+@c way, it's probably easier to change (generate-documentation) than to
+@c make it below and have to deal with the churn as Transmission Daemon
+@c updates.
+
+@c %start of fragment
+
+Available @code{transmission-daemon-configuration} fields are:
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} package transmission
+The Transmission package to use.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer stop-wait-period
+The period, in seconds, to wait when stopping the service for
+@command{transmission-daemon} to exit before killing its process. This
+allows the daemon time to complete its housekeeping and send a final
+update to trackers as it shuts down. On slow hosts, or hosts with a
+slow network connection, this value may need to be increased.
+
+Defaults to @samp{10}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string download-dir
+The directory to which torrent files are downloaded.
+
+Defaults to @samp{"/var/lib/transmission-daemon/downloads"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean incomplete-dir-enabled?
+If @code{#t}, files will be held in @code{incomplete-dir} while their
+torrent is being downloaded, then moved to @code{download-dir} once the
+torrent is complete. Otherwise, files for all torrents (including those
+still being downloaded) will be placed in @code{download-dir}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string incomplete-dir
+The directory in which files from incompletely downloaded torrents will
+be held when @code{incomplete-dir-enabled?} is @code{#t}.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} umask umask
+The file mode creation mask used for downloaded files. (See the
+@command{umask} man page for more information.)
+
+Defaults to @samp{18}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean rename-partial-files?
+When @code{#t}, ``.part'' is appended to the name of partially
+downloaded files.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} preallocation-mode preallocation
+The mode by which space should be preallocated for downloaded files, one
+of @code{none}, @code{fast} (or @code{sparse}) and @code{full}.
+Specifying @code{full} will minimize disk fragmentation at a cost to
+file-creation speed.
+
+Defaults to @samp{fast}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean watch-dir-enabled?
+If @code{#t}, the directory specified by @code{watch-dir} will be
+watched for new @file{.torrent} files and the torrents they describe
+added automatically (and the original files removed, if
+@code{trash-original-torrent-files?} is @code{#t}).
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string watch-dir
+The directory to be watched for @file{.torrent} files indicating new
+torrents to be added, when @code{watch-dir-enabled} is @code{#t}.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean trash-original-torrent-files?
+When @code{#t}, @file{.torrent} files will be deleted from the watch
+directory once their torrent has been added (see
+@code{watch-directory-enabled?}).
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean speed-limit-down-enabled?
+When @code{#t}, the daemon's download speed will be limited to the rate
+specified by @code{speed-limit-down}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer speed-limit-down
+The default global-maximum download speed, in kilobytes per second.
+
+Defaults to @samp{100}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean speed-limit-up-enabled?
+When @code{#t}, the daemon's upload speed will be limited to the rate
+specified by @code{speed-limit-up}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer speed-limit-up
+The default global-maximum upload speed, in kilobytes per second.
+
+Defaults to @samp{100}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean alt-speed-enabled?
+When @code{#t}, the alternate speed limits @code{alt-speed-down} and
+@code{alt-speed-up} are used (in place of @code{speed-limit-down} and
+@code{speed-limit-up}, if they are enabled) to constrain the daemon's
+bandwidth usage. This can be scheduled to occur automatically at
+certain times during the week; see @code{alt-speed-time-enabled?}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-down
+The alternate global-maximum download speed, in kilobytes per second.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-up
+The alternate global-maximum upload speed, in kilobytes per second.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean alt-speed-time-enabled?
+When @code{#t}, the alternate speed limits @code{alt-speed-down} and
+@code{alt-speed-up} will be enabled automatically during the periods
+specified by @code{alt-speed-time-day}, @code{alt-speed-time-begin} and
+@code{alt-time-speed-end}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} day-list alt-speed-time-day
+The days of the week on which the alternate-speed schedule should be
+used, specified either as a list of days (@code{sunday}, @code{monday},
+and so on) or using one of the symbols @code{weekdays}, @code{weekends}
+or @code{all}.
+
+Defaults to @samp{all}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-time-begin
+The time of day at which to enable the alternate speed limits, expressed
+as a number of minutes since midnight.
+
+Defaults to @samp{540}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-time-end
+The time of day at which to disable the alternate speed limits,
+expressed as a number of minutes since midnight.
+
+Defaults to @samp{1020}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string bind-address-ipv4
+The IP address at which to listen for peer connections, or ``0.0.0.0''
+to listen at all available IP addresses.
+
+Defaults to @samp{"0.0.0.0"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string bind-address-ipv6
+The IPv6 address at which to listen for peer connections, or ``::'' to
+listen at all available IPv6 addresses.
+
+Defaults to @samp{"::"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean peer-port-random-on-start?
+If @code{#t}, when the daemon starts it will select a port at random on
+which to listen for peer connections, from the range specified
+(inclusively) by @code{peer-port-random-low} and
+@code{peer-port-random-high}. Otherwise, it listens on the port
+specified by @code{peer-port}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port-random-low
+The lowest selectable port number when @code{peer-port-random-on-start?}
+is @code{#t}.
+
+Defaults to @samp{49152}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port-random-high
+The highest selectable port number when @code{peer-port-random-on-start}
+is @code{#t}.
+
+Defaults to @samp{65535}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port
+The port on which to listen for peer connections when
+@code{peer-port-random-on-start?} is @code{#f}.
+
+Defaults to @samp{51413}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean port-forwarding-enabled?
+If @code{#t}, the daemon will attempt to configure port-forwarding on an
+upstream gateway automatically using @acronym{UPnP} and
+@acronym{NAT-PMP}.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} encryption-mode encryption
+The encryption preference for peer connections, one of
+@code{prefer-unencrypted-connections},
+@code{prefer-encrypted-connections} or
+@code{require-encrypted-connections}.
+
+Defaults to @samp{prefer-encrypted-connections}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string peer-congestion-algorithm
+The TCP congestion-control algorithm to use for peer connections,
+specified using a string recognized by the operating system in calls to
+@code{setsockopt} (or set to @code{disabled}, in which case the
+operating-system default is used).
+
+Note that on GNU/Linux systems, the kernel must be configured to allow
+processes to use a congestion-control algorithm not in the default set;
+otherwise, it will deny these requests with ``Operation not permitted''.
+To see which algorithms are available on your system and which are
+currently permitted for use, look at the contents of the files
+@file{tcp_available_congestion_control} and
+@file{tcp_allowed_congestion_control} in the @file{/proc/sys/net/ipv4}
+directory.
+
+As an example, to have Transmission Daemon use
+@uref{http://www-ece.rice.edu/networks/TCP-LP/,the TCP Low Priority
+congestion-control algorithm}, you'll need to modify your kernel
+configuration to build in support for the algorithm, then update your
+operating-system configuration to allow its use by adding a
+@code{sysctl-service-type} service (or updating the existing one's
+configuration) with lines like the following:
+
+@lisp
+(service sysctl-service-type
+ (sysctl-configuration
+ (settings
+ ("net.ipv4.tcp_allowed_congestion_control" .
+ "reno cubic lp"))))
+@end lisp
+
+The Transmission Daemon configuration can then be updated with
+
+@lisp
+(peer-congestion-algorithm "lp")
+@end lisp
+
+and the system reconfigured to have the changes take effect.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} tcp-type-of-service peer-socket-tos
+The type of service to request in outgoing @acronym{TCP} packets, one of
+@code{default}, @code{low-cost}, @code{throughput}, @code{low-delay} and
+@code{reliability}.
+
+Defaults to @samp{default}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-limit-global
+The global limit on the number of connected peers.
+
+Defaults to @samp{200}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-limit-per-torrent
+The per-torrent limit on the number of connected peers.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer upload-slots-per-torrent
+The maximum number of peers to which the daemon will upload data
+simultaneously for each torrent.
+
+Defaults to @samp{14}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-id-ttl-hours
+The maximum lifespan, in hours, of the peer ID associated with each
+public torrent before it is regenerated.
+
+Defaults to @samp{6}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean blocklist-enabled?
+When @code{#t}, the daemon will ignore peers mentioned in the blocklist
+it has most recently downloaded from @code{blocklist-url}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string blocklist-url
+The URL of a peer blocklist (in @acronym{P2P}-plaintext or eMule
+@file{.dat} format) to be periodically downloaded and applied when
+@code{bloc
This message was truncated. Download the full message here.
S
S
Simon South wrote on 7 Nov 2020 15:12
(address . 44435@debbugs.gnu.org)
87mtzt5k83.fsf@simonsouth.net
Simon South <simon@simonsouth.net> writes:
Toggle quote (4 lines)
> +(define (transmission-daemon-activation config)
> + "Return the Transmission Daemon activation GEXP for CONFIG."
> + (let ((owner (getpwnam %transmission-daemon-user))

This call to "getpwnam" should be executed on the build side, not the
host side.

Also, since Ludovic's commit ca465a9c8454, configuring a system that
uses this service type issues

gnu/services/file-sharing.scm:736:9: warning: importing module (guix config) from the host

which I assume is a problem.

I'm working on an update that addresses these things.

--
Simon South
simon@simonsouth.net
S
S
Simon South wrote on 8 Nov 2020 19:06
[PATCH v2 0/1] services: Add Transmission Daemon
(address . 44435@debbugs.gnu.org)(address . simon@simonsouth.net)
cover.1604858392.git.simon@simonsouth.net
Here's an updated version of the patch that

- Fixes the "importing module from host" warning by removing an unnecessary
import of (guix gexp) in transmission-daemon-computed-settings-file; and

- Moves the execution of getpwnam in transmission-daemon-activation from the
host side to the build side, where it belongs.

Everything else is unchanged.

For convenience, here's my original cover letter:

This patch adds a service type for Transmission Daemon, the headless variant
of the Transmission BitTorrent client (https://transmissionbt.com/).Running
the client as a service this way makes it possible to share files over
BitTorrent continuously without requiring a user be logged in.

I've tried to make this as complete as possible but am especially interested
in geting feedback as this is my first attempt at creating a service
definition. A few things to point out:

- I've placed the code in a new "(gnu services file-sharing)" module and the
documentation in a new "File-Sharing Services" section of the manual, only
because these names seemed the most natural to me. ("Peer-to-peer" would be
too broad a categorization, I think, while "BitTorrent" too narrow.)

- The module exports two procedures, "transmission-password-hash" and
"transmission-random-salt", that together are my solution to the problem of
assigning a value to the daemon's "rpc-password" configuration setting.

Transmission clients seem to expect the user to supply a password in
plaintext in their "settings.json" file. At startup, the client generates a
random, eight-character salt value; hashes it and the password together; and
writes the result back to the settings file, after which the password
remains obscured. This obviously violates the functional nature of Guix, as
we don't expect services to be rewriting their own configuration files and
the use of a random salt value makes the process non-repeatable anyway.

I've documented in the manual how a user can use these two procedures to
create a suitable value for "rpc-password" that remains stable across system
reconfigurations, but perhaps you know of a better (or more conventional)
approach.

- I've added a custom "stop" procedure to the Shepherd service that gives the
daemon time to shut down before eventually killing its process. This is
necessary since the daemon performs some housekeeping and sends a final
update to BitTorrent trackers before it exits, which can take several
seconds or more; without this code, restarting the service usually fails as
the new daemon process finds the old one is still running and attached to
the port used for peer connections.

Again, the approach I've used to handle this seems reasonable to me but
perhaps you know of something better.

--
Simon South
simon@simonsouth.net


Simon South (1):
services: Add transmission-daemon service.

doc/guix.texi | 799 +++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
gnu/services/file-sharing.scm | 803 ++++++++++++++++++++++++++++++++++
3 files changed, 1603 insertions(+)
create mode 100644 gnu/services/file-sharing.scm

--
2.29.2
S
S
Simon South wrote on 8 Nov 2020 19:06
[PATCH v2 1/1] services: Add transmission-daemon service.
(address . 44435@debbugs.gnu.org)(address . simon@simonsouth.net)
74ae4b17fccb96f6c03c21123c4ea8c824893c61.1604858392.git.simon@simonsouth.net
* gnu/services/file-sharing.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
* doc/guix.texi (File-Sharing Services): New section.
---
doc/guix.texi | 799 +++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
gnu/services/file-sharing.scm | 803 ++++++++++++++++++++++++++++++++++
3 files changed, 1603 insertions(+)
create mode 100644 gnu/services/file-sharing.scm

Toggle diff (520 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 217ed7a8a8..fe1c097653 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -14365,6 +14365,7 @@ declaration.
* Mail Services:: IMAP, POP3, SMTP, and all that.
* Messaging Services:: Messaging services.
* Telephony Services:: Telephony services.
+* File-Sharing Services:: File-sharing services.
* Monitoring Services:: Monitoring services.
* Kerberos Services:: Kerberos services.
* LDAP Services:: LDAP services.
@@ -21688,6 +21689,804 @@ If it is set your server will be linked by this host name instead.
+@node File-Sharing Services
+@subsection File-Sharing Services
+
+The @code{(gnu services file-sharing)} module provides services that
+assist with transferring files over peer-to-peer file-sharing networks.
+
+@subsubheading Transmission Daemon Service
+
+@uref{https://transmissionbt.com/, Transmission} is a flexible
+BitTorrent client that offers a variety of graphical and command-line
+interfaces. A @code{transmission-daemon-service-type} service provides
+Transmission's headless variant, @command{transmission-daemon}, as a
+system service, allowing users to share files via BitTorrent even when
+they are not logged in.
+
+@deffn {Scheme Variable} transmission-daemon-service-type
+The service type for the Transmission Daemon BitTorrent client. Its
+value must be a @code{transmission-daemon-configuration} object as in
+this example:
+
+@lisp
+(service transmission-daemon-service-type
+ (transmission-daemon-configuration
+ ;; Restrict access to the RPC ("control") interface
+ (rpc-authentication-required? #t)
+ (rpc-username "transmission")
+ (rpc-password
+ (transmission-password-hash
+ "transmission" ; desired password
+ "uKd1uMs9")) ; arbitrary salt value
+
+ ;; Accept requests from this and other hosts on the
+ ;; local network
+ (rpc-whitelist-enabled? #t)
+ (rpc-whitelist '("::1" "127.0.0.1" "192.168.0.*"))
+
+ ;; Limit bandwidth use during work hours
+ (alt-speed-down (* 1024 2)) ; 2 MB/s
+ (alt-speed-up 512) ; 512 kB/s
+
+ (alt-speed-time-enabled? #t)
+ (alt-speed-time-day 'weekdays)
+ (alt-speed-time-begin
+ (+ (* 60 8) 30)) ; 8:30 am
+ (alt-speed-time-end
+ (+ (* 60 (+ 12 5)) 30)))) ; 5:30 pm
+@end lisp
+@end deffn
+
+Once the service is started, users can interact with the daemon through
+its Web interface (at @code{http://localhost:9091/}) or by using the
+@command{transmission-remote} command-line tool, available in the
+@code{transmission} package. (Emacs users may want to also consider the
+@code{emacs-transmission} package.) Both communicate with the daemon
+through its remote procedure call (RPC) interface, which by default is
+available to all users on the system; you may wish to change this by
+assigning values to the @code{rpc-authentication-required?},
+@code{rpc-username} and @code{rpc-password} settings, as shown in the
+example above and documented further below.
+
+The value for @code{rpc-password} must be a password hash of the type
+generated and used by Transmission clients. This can be copied verbatim
+from an existing @file{settings.json} file, if another Transmission
+client is already being used. Otherwise, the
+@code{transmission-password-hash} and @code{transmission-random-salt}
+procedures provided by this module can be used to obtain a suitable hash
+value.
+
+@deffn {Scheme Procedure} transmission-password-hash @var{password} @var{salt}
+Returns a string containing the result of hashing @var{password}
+together with @var{salt}, in the format recognized by Transmission
+clients for their @code{rpc-password} configuration setting.
+
+@var{salt} must be an eight-character string. The
+@code{transmission-random-salt} procedure can be used to generate a
+suitable salt value at random.
+@end deffn
+
+@deffn {Scheme Procedure} transmission-random-salt
+Returns a string containing a random, eight-character salt value of the
+type generated and used by Transmission clients, suitable for passing to
+the @code{transmission-password-hash} procedure.
+@end deffn
+
+These procedures are accessible from within a Guile REPL started with
+the @command{guix repl} command (@pxref {Invoking guix repl}). This is
+useful for obtaining a random salt value to provide as the second
+parameter to `transmission-password-hash`, as in this example session:
+
+@example
+$ guix repl
+scheme@@(guix-user)> ,use (gnu services file-sharing)
+scheme@@(guix-user)> (transmission-random-salt)
+$1 = "uKd1uMs9"
+@end example
+
+Alternatively, a complete password hash can generated in a single step:
+
+@example
+scheme@@(guix-user)> (transmission-password-hash "transmission"
+(transmission-random-salt))
+$2 = "@{c8bbc6d1740cd8dc819a6e25563b67812c1c19c9VtFPfdsX"
+@end example
+
+The resulting string can be used as-is for the value of
+@code{rpc-password}, allowing the password to be kept hidden even in the
+operating-system configuration.
+
+Torrent files downloaded by the daemon are directly accessible only to
+users in the ``transmission'' user group, who receive read-only access
+to the directory specified by the @code{download-dir} configuration
+setting (and also the directory specified by @code{incomplete-dir}, if
+@code{incomplete-dir-enabled?} is @code{#t}). Downloaded files can be
+moved to another directory or deleted altogether using
+@command{transmission-remote} with its @code{--move} and
+@code{--remove-and-delete} options.
+
+If the @code{watch-dir-enabled?} setting is set to @code{#t}, users in
+the ``transmission'' group are able also to place @file{.torrent} files
+in the directory specified by @code{watch-dir} to have the corresponding
+torrents added by the daemon. (The @code{trash-original-torrent-files?}
+setting controls whether the daemon deletes these files after processing
+them.)
+
+Some of the daemon's configuration settings can be changed temporarily
+by @command{transmission-remote} and similar tools. To undo these
+changes, use the service's @code{reload} action to have the daemon
+reload its settings from disk:
+
+@example
+# herd reload transmission-daemon
+@end example
+
+The full set of available configuration settings is defined by the
+@code{transmission-daemon-configuration} data type.
+
+@deftp {Data Type} transmission-daemon-configuration
+The data type representing configuration settings for Transmission
+Daemon. These correspond directly to the settings recognized by
+Transmission clients in their @file{settings.json} file.
+@end deftp
+
+@c The following documentation was initially generated by
+@c (generate-transmission-daemon-documentation) in (gnu services
+@c file-sharing). Manually maintained documentation is better, so we
+@c shouldn't hesitate to edit below as needed. However if the change
+@c you want to make to this documentation can be done in an automated
+@c way, it's probably easier to change (generate-documentation) than to
+@c make it below and have to deal with the churn as Transmission Daemon
+@c updates.
+
+@c %start of fragment
+
+Available @code{transmission-daemon-configuration} fields are:
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} package transmission
+The Transmission package to use.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer stop-wait-period
+The period, in seconds, to wait when stopping the service for
+@command{transmission-daemon} to exit before killing its process. This
+allows the daemon time to complete its housekeeping and send a final
+update to trackers as it shuts down. On slow hosts, or hosts with a
+slow network connection, this value may need to be increased.
+
+Defaults to @samp{10}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string download-dir
+The directory to which torrent files are downloaded.
+
+Defaults to @samp{"/var/lib/transmission-daemon/downloads"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean incomplete-dir-enabled?
+If @code{#t}, files will be held in @code{incomplete-dir} while their
+torrent is being downloaded, then moved to @code{download-dir} once the
+torrent is complete. Otherwise, files for all torrents (including those
+still being downloaded) will be placed in @code{download-dir}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string incomplete-dir
+The directory in which files from incompletely downloaded torrents will
+be held when @code{incomplete-dir-enabled?} is @code{#t}.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} umask umask
+The file mode creation mask used for downloaded files. (See the
+@command{umask} man page for more information.)
+
+Defaults to @samp{18}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean rename-partial-files?
+When @code{#t}, ``.part'' is appended to the name of partially
+downloaded files.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} preallocation-mode preallocation
+The mode by which space should be preallocated for downloaded files, one
+of @code{none}, @code{fast} (or @code{sparse}) and @code{full}.
+Specifying @code{full} will minimize disk fragmentation at a cost to
+file-creation speed.
+
+Defaults to @samp{fast}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean watch-dir-enabled?
+If @code{#t}, the directory specified by @code{watch-dir} will be
+watched for new @file{.torrent} files and the torrents they describe
+added automatically (and the original files removed, if
+@code{trash-original-torrent-files?} is @code{#t}).
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string watch-dir
+The directory to be watched for @file{.torrent} files indicating new
+torrents to be added, when @code{watch-dir-enabled} is @code{#t}.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean trash-original-torrent-files?
+When @code{#t}, @file{.torrent} files will be deleted from the watch
+directory once their torrent has been added (see
+@code{watch-directory-enabled?}).
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean speed-limit-down-enabled?
+When @code{#t}, the daemon's download speed will be limited to the rate
+specified by @code{speed-limit-down}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer speed-limit-down
+The default global-maximum download speed, in kilobytes per second.
+
+Defaults to @samp{100}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean speed-limit-up-enabled?
+When @code{#t}, the daemon's upload speed will be limited to the rate
+specified by @code{speed-limit-up}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer speed-limit-up
+The default global-maximum upload speed, in kilobytes per second.
+
+Defaults to @samp{100}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean alt-speed-enabled?
+When @code{#t}, the alternate speed limits @code{alt-speed-down} and
+@code{alt-speed-up} are used (in place of @code{speed-limit-down} and
+@code{speed-limit-up}, if they are enabled) to constrain the daemon's
+bandwidth usage. This can be scheduled to occur automatically at
+certain times during the week; see @code{alt-speed-time-enabled?}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-down
+The alternate global-maximum download speed, in kilobytes per second.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-up
+The alternate global-maximum upload speed, in kilobytes per second.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean alt-speed-time-enabled?
+When @code{#t}, the alternate speed limits @code{alt-speed-down} and
+@code{alt-speed-up} will be enabled automatically during the periods
+specified by @code{alt-speed-time-day}, @code{alt-speed-time-begin} and
+@code{alt-time-speed-end}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} day-list alt-speed-time-day
+The days of the week on which the alternate-speed schedule should be
+used, specified either as a list of days (@code{sunday}, @code{monday},
+and so on) or using one of the symbols @code{weekdays}, @code{weekends}
+or @code{all}.
+
+Defaults to @samp{all}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-time-begin
+The time of day at which to enable the alternate speed limits, expressed
+as a number of minutes since midnight.
+
+Defaults to @samp{540}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-time-end
+The time of day at which to disable the alternate speed limits,
+expressed as a number of minutes since midnight.
+
+Defaults to @samp{1020}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string bind-address-ipv4
+The IP address at which to listen for peer connections, or ``0.0.0.0''
+to listen at all available IP addresses.
+
+Defaults to @samp{"0.0.0.0"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string bind-address-ipv6
+The IPv6 address at which to listen for peer connections, or ``::'' to
+listen at all available IPv6 addresses.
+
+Defaults to @samp{"::"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean peer-port-random-on-start?
+If @code{#t}, when the daemon starts it will select a port at random on
+which to listen for peer connections, from the range specified
+(inclusively) by @code{peer-port-random-low} and
+@code{peer-port-random-high}. Otherwise, it listens on the port
+specified by @code{peer-port}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port-random-low
+The lowest selectable port number when @code{peer-port-random-on-start?}
+is @code{#t}.
+
+Defaults to @samp{49152}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port-random-high
+The highest selectable port number when @code{peer-port-random-on-start}
+is @code{#t}.
+
+Defaults to @samp{65535}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port
+The port on which to listen for peer connections when
+@code{peer-port-random-on-start?} is @code{#f}.
+
+Defaults to @samp{51413}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean port-forwarding-enabled?
+If @code{#t}, the daemon will attempt to configure port-forwarding on an
+upstream gateway automatically using @acronym{UPnP} and
+@acronym{NAT-PMP}.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} encryption-mode encryption
+The encryption preference for peer connections, one of
+@code{prefer-unencrypted-connections},
+@code{prefer-encrypted-connections} or
+@code{require-encrypted-connections}.
+
+Defaults to @samp{prefer-encrypted-connections}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string peer-congestion-algorithm
+The TCP congestion-control algorithm to use for peer connections,
+specified using a string recognized by the operating system in calls to
+@code{setsockopt} (or set to @code{disabled}, in which case the
+operating-system default is used).
+
+Note that on GNU/Linux systems, the kernel must be configured to allow
+processes to use a congestion-control algorithm not in the default set;
+otherwise, it will deny these requests with ``Operation not permitted''.
+To see which algorithms are available on your system and which are
+currently permitted for use, look at the contents of the files
+@file{tcp_available_congestion_control} and
+@file{tcp_allowed_congestion_control} in the @file{/proc/sys/net/ipv4}
+directory.
+
+As an example, to have Transmission Daemon use
+@uref{http://www-ece.rice.edu/networks/TCP-LP/,the TCP Low Priority
+congestion-control algorithm}, you'll need to modify your kernel
+configuration to build in support for the algorithm, then update your
+operating-system configuration to allow its use by adding a
+@code{sysctl-service-type} service (or updating the existing one's
+configuration) with lines like the following:
+
+@lisp
+(service sysctl-service-type
+ (sysctl-configuration
+ (settings
+ ("net.ipv4.tcp_allowed_congestion_control" .
+ "reno cubic lp"))))
+@end lisp
+
+The Transmission Daemon configuration can then be updated with
+
+@lisp
+(peer-congestion-algorithm "lp")
+@end lisp
+
+and the system reconfigured to have the changes take effect.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} tcp-type-of-service peer-socket-tos
+The type of service to request in outgoing @acronym{TCP} packets, one of
+@code{default}, @code{low-cost}, @code{throughput}, @code{low-delay} and
+@code{reliability}.
+
+Defaults to @samp{default}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-limit-global
+The global limit on the number of connected peers.
+
+Defaults to @samp{200}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-limit-per-torrent
+The per-torrent limit on the number of connected peers.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer upload-slots-per-torrent
+The maximum number of peers to which the daemon will upload data
+simultaneously for each torrent.
+
+Defaults to @samp{14}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-id-ttl-hours
+The maximum lifespan, in hours, of the peer ID associated with each
+public torrent before it is regenerated.
+
+Defaults to @samp{6}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean blocklist-enabled?
+When @code{#t}, the daemon will ignore peers mentioned in the blocklist
+it has most recently downloaded from @code{blocklist-url}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string blocklist-url
+The URL of a peer blocklist (in @acronym{P2P}-plaintext or eMule
+@file{.dat} format) to be periodically downloaded and applied when
+@code{bloc
This message was truncated. Download the full message here.
L
L
Ludovic Courtès wrote on 18 Nov 2020 23:39
Re: [bug#44435] [PATCH v2 0/1] services: Add Transmission Daemon
(name . Simon South)(address . simon@simonsouth.net)(address . 44435@debbugs.gnu.org)
87sg96i92y.fsf@gnu.org
Hi Simon,

Simon South <simon@simonsouth.net> skribis:

Toggle quote (5 lines)
> Here's an updated version of the patch that
>
> - Fixes the "importing module from host" warning by removing an unnecessary
> import of (guix gexp) in transmission-daemon-computed-settings-file; and

Good. :-)

Toggle quote (5 lines)
> - I've placed the code in a new "(gnu services file-sharing)" module and the
> documentation in a new "File-Sharing Services" section of the manual, only
> because these names seemed the most natural to me. ("Peer-to-peer" would be
> too broad a categorization, I think, while "BitTorrent" too narrow.)

Sounds good to me.

Toggle quote (17 lines)
> - The module exports two procedures, "transmission-password-hash" and
> "transmission-random-salt", that together are my solution to the problem of
> assigning a value to the daemon's "rpc-password" configuration setting.
>
> Transmission clients seem to expect the user to supply a password in
> plaintext in their "settings.json" file. At startup, the client generates a
> random, eight-character salt value; hashes it and the password together; and
> writes the result back to the settings file, after which the password
> remains obscured. This obviously violates the functional nature of Guix, as
> we don't expect services to be rewriting their own configuration files and
> the use of a random salt value makes the process non-repeatable anyway.
>
> I've documented in the manual how a user can use these two procedures to
> create a suitable value for "rpc-password" that remains stable across system
> reconfigurations, but perhaps you know of a better (or more conventional)
> approach.

Looks like a good idea. At worst we’ll have to keep it in sync with
what future versions of Transmission do, but I guess it’s unlikely to
change often.

Toggle quote (8 lines)
> - I've added a custom "stop" procedure to the Shepherd service that gives the
> daemon time to shut down before eventually killing its process. This is
> necessary since the daemon performs some housekeeping and sends a final
> update to BitTorrent trackers before it exits, which can take several
> seconds or more; without this code, restarting the service usually fails as
> the new daemon process finds the old one is still running and attached to
> the port used for peer connections.

OK.

Toggle quote (10 lines)
> +@node File-Sharing Services
> +@subsection File-Sharing Services
> +
> +The @code{(gnu services file-sharing)} module provides services that
> +assist with transferring files over peer-to-peer file-sharing networks.
> +
> +@subsubheading Transmission Daemon Service
> +
> +@uref{https://transmissionbt.com/, Transmission} is a flexible

Great that you took the time to write good documentation with examples!

Toggle quote (14 lines)
> +(define (transmission-password-hash password salt)
> + "Returns a string containing the result of hashing @var{password} together
> +with @var{salt}, in the format recognized by Transmission clients for their
> +@code{rpc-password} configuration setting.
> +
> +@var{salt} must be an eight-character string. The
> +@code{transmission-random-salt} procedure can be used to generate a suitable
> +salt value at random."
> + (if (not (eq? (string-length salt) %transmission-salt-length))
> + (throw 'out-of-range
> + (format #f
> + "salt value must be ~d characters in length"
> + %transmission-salt-length))

I’d recommend using (srfi srfi-34), (srfi srfi-35), (guix i18n), and
(guix diagnostics) and write it like so:

(raise (condition (formatted-message
(G_ "salt value …") …)))

Then you can also add this file to po/packages/POTFILE.in for
translation.

Toggle quote (5 lines)
> + (let ((password-digest (call-with-input-string
> + (string-append password salt)
> + (lambda (port)
> + (port-hash (hash-algorithm sha1) port)))))

More concise:

(sha1 (string->utf8 (string-append password salt)))

Toggle quote (26 lines)
> + (stop #~(lambda (pid)
> + (kill pid SIGTERM)
> +
> + ;; Transmission Daemon normally needs some time to shut down,
> + ;; as it will complete some housekeeping and send a final
> + ;; update to trackers before it exits.
> + ;;
> + ;; Wait a reasonable period for it to stop before continuing.
> + ;; If we don't do this, restarting the service can fail as the
> + ;; new daemon process finds the old one still running and
> + ;; attached to the port used for peer connections.
> + (let wait-before-killing ((period #$stop-wait-period))
> + (if (zero? (car (waitpid pid WNOHANG)))
> + (if (positive? period)
> + (begin
> + (sleep 1)
> + (wait-before-killing (- period 1)))
> + (begin
> + (format #t
> + "Wait period expired; killing \
> +transmission-daemon (pid ~a).~%"
> + pid)
> + (display "(If you see this message regularly, you \
> +may need to increase the value
> +of 'stop-wait-period' in the service configuration.)\n")
> + kill pid SIGKILL))))
^
Missing parens.

Ideally this SIGTERM-then-SIGKILL dance would be done by shepherd
itself. Future work!


I’m not familiar with Transmission so I can’t really comment on the
other things, but overall it LGTM apart from the details above.

Could you send an updated patch?

It would be nice to have a minimal system test to ensure at least
Transmission starts and is fine with the generated config file; we can
leave that to another patch though, if you prefer.

Thanks!

Ludo’.
S
S
Simon South wrote on 19 Nov 2020 01:35
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 44435@debbugs.gnu.org)
87mtzerxod.fsf@simonsouth.net
Ludovic Courtès <ludo@gnu.org> writes:
Toggle quote (2 lines)
> Could you send an updated patch?

Absolutely. Thanks for the review and the feedback.

Toggle quote (4 lines)
> It would be nice to have a minimal system test to ensure at least
> Transmission starts and is fine with the generated config file; we can
> leave that to another patch though, if you prefer.

Nah; I can probably get that done fairly quickly, and then perhaps
everything can be committed together.

I'll follow up soon.

--
Simon South
simon@simonsouth.net
S
S
Simon South wrote on 5 Dec 2020 16:27
[PATCH v3 0/1] services: Add Transmission Daemon
(address . 44435@debbugs.gnu.org)(name . Simon South)(address . simon@simonsouth.net)
cover.1607175147.git.simon@simonsouth.net
Here's a new version of this patch that incorporates feedback[0] from Ludovic:

- transmission-password-hash now signals an error in a more conventional
manner, by raise'ing a &formatted-message condition, and uses Guile-GCrypt's
"sha1" shorthand procedure along with string->utf8 for a more compact
implementation.

- A missing pair of parentheses in transmission-daemon-shepherd-service has
been restored.

- User-facing strings have been wrapped with "G_" and the file added to
po/packages/POTFILES.in to permit internationalization. (I've done this for
every string, not just the one in transmission-password-hash.)

I've also added a small test suite that exercises the password-related
procedures exported by the service module, using values captured from
transmission-daemon itself. I've placed the file in tests/services, though
it's not clear this is the right location; tests/networking.scm also pertains
to a service, for instance. I can re-submit with the file relocated if need
be.

Finally, despite my earlier bravado[1] I've held off adding any system tests,
only because I now realize getting the system test suite running on the
machines I have available is going to be a project in and of itself. I do
intend to add these at a later date.



For convenience, here's my original cover letter:

This patch adds a service type for Transmission Daemon, the headless variant
of the Transmission BitTorrent client (https://transmissionbt.com/).Running
the client as a service this way makes it possible to share files over
BitTorrent continuously without requiring a user be logged in.

I've tried to make this as complete as possible but am especially interested
in geting feedback as this is my first attempt at creating a service
definition. A few things to point out:

- I've placed the code in a new "(gnu services file-sharing)" module and the
documentation in a new "File-Sharing Services" section of the manual, only
because these names seemed the most natural to me. ("Peer-to-peer" would be
too broad a categorization, I think, while "BitTorrent" too narrow.)

- The module exports two procedures, "transmission-password-hash" and
"transmission-random-salt", that together are my solution to the problem of
assigning a value to the daemon's "rpc-password" configuration setting.

Transmission clients seem to expect the user to supply a password in
plaintext in their "settings.json" file. At startup, the client generates a
random, eight-character salt value; hashes it and the password together; and
writes the result back to the settings file, after which the password
remains obscured. This obviously violates the functional nature of Guix, as
we don't expect services to be rewriting their own configuration files and
the use of a random salt value makes the process non-repeatable anyway.

I've documented in the manual how a user can use these two procedures to
create a suitable value for "rpc-password" that remains stable across system
reconfigurations, but perhaps you know of a better (or more conventional)
approach.

- I've added a custom "stop" procedure to the Shepherd service that gives the
daemon time to shut down before eventually killing its process. This is
necessary since the daemon performs some housekeeping and sends a final
update to BitTorrent trackers before it exits, which can take several
seconds or more; without this code, restarting the service usually fails as
the new daemon process finds the old one is still running and attached to
the port used for peer connections.

Again, the approach I've used to handle this seems reasonable to me but
perhaps you know of something better.

--
Simon South
simon@simonsouth.net


Simon South (1):
services: Add transmission-daemon service.

Makefile.am | 1 +
doc/guix.texi | 799 +++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
gnu/services/file-sharing.scm | 804 ++++++++++++++++++++++++++++++++
po/packages/POTFILES.in | 1 +
tests/services/file-sharing.scm | 59 +++
6 files changed, 1665 insertions(+)
create mode 100644 gnu/services/file-sharing.scm
create mode 100644 tests/services/file-sharing.scm

--
2.29.2
S
S
Simon South wrote on 5 Dec 2020 16:27
[PATCH v3 1/1] services: Add transmission-daemon service.
(address . 44435@debbugs.gnu.org)(name . Simon South)(address . simon@simonsouth.net)
ea67c278710ed993559e3f13093688fd240f7b37.1607175147.git.simon@simonsouth.net
* gnu/services/file-sharing.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
* po/packages/POTFILES.in: Add it.
* tests/services/file-sharing.scm: New file.
* Makefile.am (SCM_TESTS): Add it.
* doc/guix.texi (File-Sharing Services): New section.
---
Makefile.am | 1 +
doc/guix.texi | 799 +++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
gnu/services/file-sharing.scm | 804 ++++++++++++++++++++++++++++++++
po/packages/POTFILES.in | 1 +
tests/services/file-sharing.scm | 59 +++
6 files changed, 1665 insertions(+)
create mode 100644 gnu/services/file-sharing.scm
create mode 100644 tests/services/file-sharing.scm

Toggle diff (514 lines)
diff --git a/Makefile.am b/Makefile.am
index 1a3ca227a4..a50540601d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -469,6 +469,7 @@ SCM_TESTS = \
tests/scripts.scm \
tests/search-paths.scm \
tests/services.scm \
+ tests/services/file-sharing.scm \
tests/services/linux.scm \
tests/sets.scm \
tests/size.scm \
diff --git a/doc/guix.texi b/doc/guix.texi
index a5c9779c86..57a2ad9ac7 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -14504,6 +14504,7 @@ declaration.
* Mail Services:: IMAP, POP3, SMTP, and all that.
* Messaging Services:: Messaging services.
* Telephony Services:: Telephony services.
+* File-Sharing Services:: File-sharing services.
* Monitoring Services:: Monitoring services.
* Kerberos Services:: Kerberos services.
* LDAP Services:: LDAP services.
@@ -21858,6 +21859,804 @@ If it is set your server will be linked by this host name instead.
+@node File-Sharing Services
+@subsection File-Sharing Services
+
+The @code{(gnu services file-sharing)} module provides services that
+assist with transferring files over peer-to-peer file-sharing networks.
+
+@subsubheading Transmission Daemon Service
+
+@uref{https://transmissionbt.com/, Transmission} is a flexible
+BitTorrent client that offers a variety of graphical and command-line
+interfaces. A @code{transmission-daemon-service-type} service provides
+Transmission's headless variant, @command{transmission-daemon}, as a
+system service, allowing users to share files via BitTorrent even when
+they are not logged in.
+
+@deffn {Scheme Variable} transmission-daemon-service-type
+The service type for the Transmission Daemon BitTorrent client. Its
+value must be a @code{transmission-daemon-configuration} object as in
+this example:
+
+@lisp
+(service transmission-daemon-service-type
+ (transmission-daemon-configuration
+ ;; Restrict access to the RPC ("control") interface
+ (rpc-authentication-required? #t)
+ (rpc-username "transmission")
+ (rpc-password
+ (transmission-password-hash
+ "transmission" ; desired password
+ "uKd1uMs9")) ; arbitrary salt value
+
+ ;; Accept requests from this and other hosts on the
+ ;; local network
+ (rpc-whitelist-enabled? #t)
+ (rpc-whitelist '("::1" "127.0.0.1" "192.168.0.*"))
+
+ ;; Limit bandwidth use during work hours
+ (alt-speed-down (* 1024 2)) ; 2 MB/s
+ (alt-speed-up 512) ; 512 kB/s
+
+ (alt-speed-time-enabled? #t)
+ (alt-speed-time-day 'weekdays)
+ (alt-speed-time-begin
+ (+ (* 60 8) 30)) ; 8:30 am
+ (alt-speed-time-end
+ (+ (* 60 (+ 12 5)) 30)))) ; 5:30 pm
+@end lisp
+@end deffn
+
+Once the service is started, users can interact with the daemon through
+its Web interface (at @code{http://localhost:9091/}) or by using the
+@command{transmission-remote} command-line tool, available in the
+@code{transmission} package. (Emacs users may want to also consider the
+@code{emacs-transmission} package.) Both communicate with the daemon
+through its remote procedure call (RPC) interface, which by default is
+available to all users on the system; you may wish to change this by
+assigning values to the @code{rpc-authentication-required?},
+@code{rpc-username} and @code{rpc-password} settings, as shown in the
+example above and documented further below.
+
+The value for @code{rpc-password} must be a password hash of the type
+generated and used by Transmission clients. This can be copied verbatim
+from an existing @file{settings.json} file, if another Transmission
+client is already being used. Otherwise, the
+@code{transmission-password-hash} and @code{transmission-random-salt}
+procedures provided by this module can be used to obtain a suitable hash
+value.
+
+@deffn {Scheme Procedure} transmission-password-hash @var{password} @var{salt}
+Returns a string containing the result of hashing @var{password}
+together with @var{salt}, in the format recognized by Transmission
+clients for their @code{rpc-password} configuration setting.
+
+@var{salt} must be an eight-character string. The
+@code{transmission-random-salt} procedure can be used to generate a
+suitable salt value at random.
+@end deffn
+
+@deffn {Scheme Procedure} transmission-random-salt
+Returns a string containing a random, eight-character salt value of the
+type generated and used by Transmission clients, suitable for passing to
+the @code{transmission-password-hash} procedure.
+@end deffn
+
+These procedures are accessible from within a Guile REPL started with
+the @command{guix repl} command (@pxref {Invoking guix repl}). This is
+useful for obtaining a random salt value to provide as the second
+parameter to `transmission-password-hash`, as in this example session:
+
+@example
+$ guix repl
+scheme@@(guix-user)> ,use (gnu services file-sharing)
+scheme@@(guix-user)> (transmission-random-salt)
+$1 = "uKd1uMs9"
+@end example
+
+Alternatively, a complete password hash can generated in a single step:
+
+@example
+scheme@@(guix-user)> (transmission-password-hash "transmission"
+(transmission-random-salt))
+$2 = "@{c8bbc6d1740cd8dc819a6e25563b67812c1c19c9VtFPfdsX"
+@end example
+
+The resulting string can be used as-is for the value of
+@code{rpc-password}, allowing the password to be kept hidden even in the
+operating-system configuration.
+
+Torrent files downloaded by the daemon are directly accessible only to
+users in the ``transmission'' user group, who receive read-only access
+to the directory specified by the @code{download-dir} configuration
+setting (and also the directory specified by @code{incomplete-dir}, if
+@code{incomplete-dir-enabled?} is @code{#t}). Downloaded files can be
+moved to another directory or deleted altogether using
+@command{transmission-remote} with its @code{--move} and
+@code{--remove-and-delete} options.
+
+If the @code{watch-dir-enabled?} setting is set to @code{#t}, users in
+the ``transmission'' group are able also to place @file{.torrent} files
+in the directory specified by @code{watch-dir} to have the corresponding
+torrents added by the daemon. (The @code{trash-original-torrent-files?}
+setting controls whether the daemon deletes these files after processing
+them.)
+
+Some of the daemon's configuration settings can be changed temporarily
+by @command{transmission-remote} and similar tools. To undo these
+changes, use the service's @code{reload} action to have the daemon
+reload its settings from disk:
+
+@example
+# herd reload transmission-daemon
+@end example
+
+The full set of available configuration settings is defined by the
+@code{transmission-daemon-configuration} data type.
+
+@deftp {Data Type} transmission-daemon-configuration
+The data type representing configuration settings for Transmission
+Daemon. These correspond directly to the settings recognized by
+Transmission clients in their @file{settings.json} file.
+@end deftp
+
+@c The following documentation was initially generated by
+@c (generate-transmission-daemon-documentation) in (gnu services
+@c file-sharing). Manually maintained documentation is better, so we
+@c shouldn't hesitate to edit below as needed. However if the change
+@c you want to make to this documentation can be done in an automated
+@c way, it's probably easier to change (generate-documentation) than to
+@c make it below and have to deal with the churn as Transmission Daemon
+@c updates.
+
+@c %start of fragment
+
+Available @code{transmission-daemon-configuration} fields are:
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} package transmission
+The Transmission package to use.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer stop-wait-period
+The period, in seconds, to wait when stopping the service for
+@command{transmission-daemon} to exit before killing its process. This
+allows the daemon time to complete its housekeeping and send a final
+update to trackers as it shuts down. On slow hosts, or hosts with a
+slow network connection, this value may need to be increased.
+
+Defaults to @samp{10}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string download-dir
+The directory to which torrent files are downloaded.
+
+Defaults to @samp{"/var/lib/transmission-daemon/downloads"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean incomplete-dir-enabled?
+If @code{#t}, files will be held in @code{incomplete-dir} while their
+torrent is being downloaded, then moved to @code{download-dir} once the
+torrent is complete. Otherwise, files for all torrents (including those
+still being downloaded) will be placed in @code{download-dir}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string incomplete-dir
+The directory in which files from incompletely downloaded torrents will
+be held when @code{incomplete-dir-enabled?} is @code{#t}.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} umask umask
+The file mode creation mask used for downloaded files. (See the
+@command{umask} man page for more information.)
+
+Defaults to @samp{18}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean rename-partial-files?
+When @code{#t}, ``.part'' is appended to the name of partially
+downloaded files.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} preallocation-mode preallocation
+The mode by which space should be preallocated for downloaded files, one
+of @code{none}, @code{fast} (or @code{sparse}) and @code{full}.
+Specifying @code{full} will minimize disk fragmentation at a cost to
+file-creation speed.
+
+Defaults to @samp{fast}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean watch-dir-enabled?
+If @code{#t}, the directory specified by @code{watch-dir} will be
+watched for new @file{.torrent} files and the torrents they describe
+added automatically (and the original files removed, if
+@code{trash-original-torrent-files?} is @code{#t}).
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string watch-dir
+The directory to be watched for @file{.torrent} files indicating new
+torrents to be added, when @code{watch-dir-enabled} is @code{#t}.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean trash-original-torrent-files?
+When @code{#t}, @file{.torrent} files will be deleted from the watch
+directory once their torrent has been added (see
+@code{watch-directory-enabled?}).
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean speed-limit-down-enabled?
+When @code{#t}, the daemon's download speed will be limited to the rate
+specified by @code{speed-limit-down}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer speed-limit-down
+The default global-maximum download speed, in kilobytes per second.
+
+Defaults to @samp{100}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean speed-limit-up-enabled?
+When @code{#t}, the daemon's upload speed will be limited to the rate
+specified by @code{speed-limit-up}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer speed-limit-up
+The default global-maximum upload speed, in kilobytes per second.
+
+Defaults to @samp{100}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean alt-speed-enabled?
+When @code{#t}, the alternate speed limits @code{alt-speed-down} and
+@code{alt-speed-up} are used (in place of @code{speed-limit-down} and
+@code{speed-limit-up}, if they are enabled) to constrain the daemon's
+bandwidth usage. This can be scheduled to occur automatically at
+certain times during the week; see @code{alt-speed-time-enabled?}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-down
+The alternate global-maximum download speed, in kilobytes per second.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-up
+The alternate global-maximum upload speed, in kilobytes per second.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean alt-speed-time-enabled?
+When @code{#t}, the alternate speed limits @code{alt-speed-down} and
+@code{alt-speed-up} will be enabled automatically during the periods
+specified by @code{alt-speed-time-day}, @code{alt-speed-time-begin} and
+@code{alt-time-speed-end}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} day-list alt-speed-time-day
+The days of the week on which the alternate-speed schedule should be
+used, specified either as a list of days (@code{sunday}, @code{monday},
+and so on) or using one of the symbols @code{weekdays}, @code{weekends}
+or @code{all}.
+
+Defaults to @samp{all}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-time-begin
+The time of day at which to enable the alternate speed limits, expressed
+as a number of minutes since midnight.
+
+Defaults to @samp{540}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-time-end
+The time of day at which to disable the alternate speed limits,
+expressed as a number of minutes since midnight.
+
+Defaults to @samp{1020}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string bind-address-ipv4
+The IP address at which to listen for peer connections, or ``0.0.0.0''
+to listen at all available IP addresses.
+
+Defaults to @samp{"0.0.0.0"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} string bind-address-ipv6
+The IPv6 address at which to listen for peer connections, or ``::'' to
+listen at all available IPv6 addresses.
+
+Defaults to @samp{"::"}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean peer-port-random-on-start?
+If @code{#t}, when the daemon starts it will select a port at random on
+which to listen for peer connections, from the range specified
+(inclusively) by @code{peer-port-random-low} and
+@code{peer-port-random-high}. Otherwise, it listens on the port
+specified by @code{peer-port}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port-random-low
+The lowest selectable port number when @code{peer-port-random-on-start?}
+is @code{#t}.
+
+Defaults to @samp{49152}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port-random-high
+The highest selectable port number when @code{peer-port-random-on-start}
+is @code{#t}.
+
+Defaults to @samp{65535}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port
+The port on which to listen for peer connections when
+@code{peer-port-random-on-start?} is @code{#f}.
+
+Defaults to @samp{51413}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} boolean port-forwarding-enabled?
+If @code{#t}, the daemon will attempt to configure port-forwarding on an
+upstream gateway automatically using @acronym{UPnP} and
+@acronym{NAT-PMP}.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} encryption-mode encryption
+The encryption preference for peer connections, one of
+@code{prefer-unencrypted-connections},
+@code{prefer-encrypted-connections} or
+@code{require-encrypted-connections}.
+
+Defaults to @samp{prefer-encrypted-connections}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string peer-congestion-algorithm
+The TCP congestion-control algorithm to use for peer connections,
+specified using a string recognized by the operating system in calls to
+@code{setsockopt} (or set to @code{disabled}, in which case the
+operating-system default is used).
+
+Note that on GNU/Linux systems, the kernel must be configured to allow
+processes to use a congestion-control algorithm not in the default set;
+otherwise, it will deny these requests with ``Operation not permitted''.
+To see which algorithms are available on your system and which are
+currently permitted for use, look at the contents of the files
+@file{tcp_available_congestion_control} and
+@file{tcp_allowed_congestion_control} in the @file{/proc/sys/net/ipv4}
+directory.
+
+As an example, to have Transmission Daemon use
+@uref{http://www-ece.rice.edu/networks/TCP-LP/,the TCP Low Priority
+congestion-control algorithm}, you'll need to modify your kernel
+configuration to build in support for the algorithm, then update your
+operating-system configuration to allow its use by adding a
+@code{sysctl-service-type} service (or updating the existing one's
+configuration) with lines like the following:
+
+@lisp
+(service sysctl-service-type
+ (sysctl-configuration
+ (settings
+ ("net.ipv4.tcp_allowed_congestion_control" .
+ "reno cubic lp"))))
+@end lisp
+
+The Transmission Daemon configuration can then be updated with
+
+@lisp
+(peer-congestion-algorithm "lp")
+@end lisp
+
+and the system reconfigured to have the changes take effect.
+
+Defaults to @samp{disabled}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} tcp-type-of-service peer-socket-tos
+The type of service to request in outgoing @acronym{TCP} packets, one of
+@code{default}, @code{low-cost}, @code{throughput}, @code{low-delay} and
+@code{reliability}.
+
+Defaults to @samp{default}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-limit-global
+The global limit on the number of connected peers.
+
+Defaults to @samp{200}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-limit-per-torrent
+The per-torrent limit on the number of connected peers.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer upload-slots-per-torrent
+The maximum number of peers to which the daemon will upload data
+simultaneously for each torrent.
+
+Defaults to @samp{14}.
+
+@end deftypevr
+
+@deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-id-ttl-hours
+The maximum lifespan,
This message was truncated. Download the full message here.
?
Re: [bug#44435] [PATCH v3 0/1] services: Add Transmission Daemon
(name . Simon South)(address . simon@simonsouth.net)(address . 44435-done@debbugs.gnu.org)
OSZP286MB0664D2F03DA0593A4F7EFF19A38B9@OSZP286MB0664.JPNP286.PROD.OUTLOOK.COM
Simon South <simon@simonsouth.net> writes:

Toggle quote (3 lines)
> Here's a new version of this patch that incorporates feedback[0] from Ludovic:
> [...]

I configure my system with this and test a torrent download.

Pushed, thank you for this patch and ludo for the review!
Closed
?