diff options
| author | Simon South <simon@simonsouth.net> | 2020-12-05 10:27:55 -0500 |
|---|---|---|
| committer | 宋文武 <iyzsong@member.fsf.org> | 2021-02-12 15:11:36 +0800 |
| commit | db6b9d2f4bc59511904e8c1412d0257675c46095 (patch) | |
| tree | bb14d07667f3ae3065cb48b30a64ce8c5059ed44 | |
| parent | 8458d8db70885b350285e8b1490734349135e51e (diff) | |
services: Add transmission-daemon service.
* 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.
Signed-off-by: 宋文武 <iyzsong@member.fsf.org>
| -rw-r--r-- | Makefile.am | 1 | ||||
| -rw-r--r-- | doc/guix.texi | 799 | ||||
| -rw-r--r-- | gnu/local.mk | 1 | ||||
| -rw-r--r-- | gnu/services/file-sharing.scm | 804 | ||||
| -rw-r--r-- | po/packages/POTFILES.in | 1 | ||||
| -rw-r--r-- | tests/services/file-sharing.scm | 59 |
6 files changed, 1665 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 798808bde6d..52537fb53d7 100644 --- a/Makefile.am +++ b/Makefile.am | |||
| @@ -475,6 +475,7 @@ SCM_TESTS = \ | |||
| 475 | tests/scripts.scm \ | 475 | tests/scripts.scm \ |
| 476 | tests/search-paths.scm \ | 476 | tests/search-paths.scm \ |
| 477 | tests/services.scm \ | 477 | tests/services.scm \ |
| 478 | tests/services/file-sharing.scm \ | ||
| 478 | tests/services/linux.scm \ | 479 | tests/services/linux.scm \ |
| 479 | tests/sets.scm \ | 480 | tests/sets.scm \ |
| 480 | tests/size.scm \ | 481 | tests/size.scm \ |
diff --git a/doc/guix.texi b/doc/guix.texi index 8944f5129da..aba8a6b575f 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -14716,6 +14716,7 @@ declaration. | |||
| 14716 | * Mail Services:: IMAP, POP3, SMTP, and all that. | 14716 | * Mail Services:: IMAP, POP3, SMTP, and all that. |
| 14717 | * Messaging Services:: Messaging services. | 14717 | * Messaging Services:: Messaging services. |
| 14718 | * Telephony Services:: Telephony services. | 14718 | * Telephony Services:: Telephony services. |
| 14719 | * File-Sharing Services:: File-sharing services. | ||
| 14719 | * Monitoring Services:: Monitoring services. | 14720 | * Monitoring Services:: Monitoring services. |
| 14720 | * Kerberos Services:: Kerberos services. | 14721 | * Kerberos Services:: Kerberos services. |
| 14721 | * LDAP Services:: LDAP services. | 14722 | * LDAP Services:: LDAP services. |
| @@ -22287,6 +22288,804 @@ If it is set your server will be linked by this host name instead. | |||
| 22287 | 22288 | ||
| 22288 | 22289 | ||
| 22289 | 22290 | ||
| 22291 | @node File-Sharing Services | ||
| 22292 | @subsection File-Sharing Services | ||
| 22293 | |||
| 22294 | The @code{(gnu services file-sharing)} module provides services that | ||
| 22295 | assist with transferring files over peer-to-peer file-sharing networks. | ||
| 22296 | |||
| 22297 | @subsubheading Transmission Daemon Service | ||
| 22298 | |||
| 22299 | @uref{https://transmissionbt.com/, Transmission} is a flexible | ||
| 22300 | BitTorrent client that offers a variety of graphical and command-line | ||
| 22301 | interfaces. A @code{transmission-daemon-service-type} service provides | ||
| 22302 | Transmission's headless variant, @command{transmission-daemon}, as a | ||
| 22303 | system service, allowing users to share files via BitTorrent even when | ||
| 22304 | they are not logged in. | ||
| 22305 | |||
| 22306 | @deffn {Scheme Variable} transmission-daemon-service-type | ||
| 22307 | The service type for the Transmission Daemon BitTorrent client. Its | ||
| 22308 | value must be a @code{transmission-daemon-configuration} object as in | ||
| 22309 | this example: | ||
| 22310 | |||
| 22311 | @lisp | ||
| 22312 | (service transmission-daemon-service-type | ||
| 22313 | (transmission-daemon-configuration | ||
| 22314 | ;; Restrict access to the RPC ("control") interface | ||
| 22315 | (rpc-authentication-required? #t) | ||
| 22316 | (rpc-username "transmission") | ||
| 22317 | (rpc-password | ||
| 22318 | (transmission-password-hash | ||
| 22319 | "transmission" ; desired password | ||
| 22320 | "uKd1uMs9")) ; arbitrary salt value | ||
| 22321 | |||
| 22322 | ;; Accept requests from this and other hosts on the | ||
| 22323 | ;; local network | ||
| 22324 | (rpc-whitelist-enabled? #t) | ||
| 22325 | (rpc-whitelist '("::1" "127.0.0.1" "192.168.0.*")) | ||
| 22326 | |||
| 22327 | ;; Limit bandwidth use during work hours | ||
| 22328 | (alt-speed-down (* 1024 2)) ; 2 MB/s | ||
| 22329 | (alt-speed-up 512) ; 512 kB/s | ||
| 22330 | |||
| 22331 | (alt-speed-time-enabled? #t) | ||
| 22332 | (alt-speed-time-day 'weekdays) | ||
| 22333 | (alt-speed-time-begin | ||
| 22334 | (+ (* 60 8) 30)) ; 8:30 am | ||
| 22335 | (alt-speed-time-end | ||
| 22336 | (+ (* 60 (+ 12 5)) 30)))) ; 5:30 pm | ||
| 22337 | @end lisp | ||
| 22338 | @end deffn | ||
| 22339 | |||
| 22340 | Once the service is started, users can interact with the daemon through | ||
| 22341 | its Web interface (at @code{http://localhost:9091/}) or by using the | ||
| 22342 | @command{transmission-remote} command-line tool, available in the | ||
| 22343 | @code{transmission} package. (Emacs users may want to also consider the | ||
| 22344 | @code{emacs-transmission} package.) Both communicate with the daemon | ||
| 22345 | through its remote procedure call (RPC) interface, which by default is | ||
| 22346 | available to all users on the system; you may wish to change this by | ||
| 22347 | assigning values to the @code{rpc-authentication-required?}, | ||
| 22348 | @code{rpc-username} and @code{rpc-password} settings, as shown in the | ||
| 22349 | example above and documented further below. | ||
| 22350 | |||
| 22351 | The value for @code{rpc-password} must be a password hash of the type | ||
| 22352 | generated and used by Transmission clients. This can be copied verbatim | ||
| 22353 | from an existing @file{settings.json} file, if another Transmission | ||
| 22354 | client is already being used. Otherwise, the | ||
| 22355 | @code{transmission-password-hash} and @code{transmission-random-salt} | ||
| 22356 | procedures provided by this module can be used to obtain a suitable hash | ||
| 22357 | value. | ||
| 22358 | |||
| 22359 | @deffn {Scheme Procedure} transmission-password-hash @var{password} @var{salt} | ||
| 22360 | Returns a string containing the result of hashing @var{password} | ||
| 22361 | together with @var{salt}, in the format recognized by Transmission | ||
| 22362 | clients for their @code{rpc-password} configuration setting. | ||
| 22363 | |||
| 22364 | @var{salt} must be an eight-character string. The | ||
| 22365 | @code{transmission-random-salt} procedure can be used to generate a | ||
| 22366 | suitable salt value at random. | ||
| 22367 | @end deffn | ||
| 22368 | |||
| 22369 | @deffn {Scheme Procedure} transmission-random-salt | ||
| 22370 | Returns a string containing a random, eight-character salt value of the | ||
| 22371 | type generated and used by Transmission clients, suitable for passing to | ||
| 22372 | the @code{transmission-password-hash} procedure. | ||
| 22373 | @end deffn | ||
| 22374 | |||
| 22375 | These procedures are accessible from within a Guile REPL started with | ||
| 22376 | the @command{guix repl} command (@pxref {Invoking guix repl}). This is | ||
| 22377 | useful for obtaining a random salt value to provide as the second | ||
| 22378 | parameter to `transmission-password-hash`, as in this example session: | ||
| 22379 | |||
| 22380 | @example | ||
| 22381 | $ guix repl | ||
| 22382 | scheme@@(guix-user)> ,use (gnu services file-sharing) | ||
| 22383 | scheme@@(guix-user)> (transmission-random-salt) | ||
| 22384 | $1 = "uKd1uMs9" | ||
| 22385 | @end example | ||
| 22386 | |||
| 22387 | Alternatively, a complete password hash can generated in a single step: | ||
| 22388 | |||
| 22389 | @example | ||
| 22390 | scheme@@(guix-user)> (transmission-password-hash "transmission" | ||
| 22391 | (transmission-random-salt)) | ||
| 22392 | $2 = "@{c8bbc6d1740cd8dc819a6e25563b67812c1c19c9VtFPfdsX" | ||
| 22393 | @end example | ||
| 22394 | |||
| 22395 | The resulting string can be used as-is for the value of | ||
| 22396 | @code{rpc-password}, allowing the password to be kept hidden even in the | ||
| 22397 | operating-system configuration. | ||
| 22398 | |||
| 22399 | Torrent files downloaded by the daemon are directly accessible only to | ||
| 22400 | users in the ``transmission'' user group, who receive read-only access | ||
| 22401 | to the directory specified by the @code{download-dir} configuration | ||
| 22402 | setting (and also the directory specified by @code{incomplete-dir}, if | ||
| 22403 | @code{incomplete-dir-enabled?} is @code{#t}). Downloaded files can be | ||
| 22404 | moved to another directory or deleted altogether using | ||
| 22405 | @command{transmission-remote} with its @code{--move} and | ||
| 22406 | @code{--remove-and-delete} options. | ||
| 22407 | |||
| 22408 | If the @code{watch-dir-enabled?} setting is set to @code{#t}, users in | ||
| 22409 | the ``transmission'' group are able also to place @file{.torrent} files | ||
| 22410 | in the directory specified by @code{watch-dir} to have the corresponding | ||
| 22411 | torrents added by the daemon. (The @code{trash-original-torrent-files?} | ||
| 22412 | setting controls whether the daemon deletes these files after processing | ||
| 22413 | them.) | ||
| 22414 | |||
| 22415 | Some of the daemon's configuration settings can be changed temporarily | ||
| 22416 | by @command{transmission-remote} and similar tools. To undo these | ||
| 22417 | changes, use the service's @code{reload} action to have the daemon | ||
| 22418 | reload its settings from disk: | ||
| 22419 | |||
| 22420 | @example | ||
| 22421 | # herd reload transmission-daemon | ||
| 22422 | @end example | ||
| 22423 | |||
| 22424 | The full set of available configuration settings is defined by the | ||
| 22425 | @code{transmission-daemon-configuration} data type. | ||
| 22426 | |||
| 22427 | @deftp {Data Type} transmission-daemon-configuration | ||
| 22428 | The data type representing configuration settings for Transmission | ||
| 22429 | Daemon. These correspond directly to the settings recognized by | ||
| 22430 | Transmission clients in their @file{settings.json} file. | ||
| 22431 | @end deftp | ||
| 22432 | |||
| 22433 | @c The following documentation was initially generated by | ||
| 22434 | @c (generate-transmission-daemon-documentation) in (gnu services | ||
| 22435 | @c file-sharing). Manually maintained documentation is better, so we | ||
| 22436 | @c shouldn't hesitate to edit below as needed. However if the change | ||
| 22437 | @c you want to make to this documentation can be done in an automated | ||
| 22438 | @c way, it's probably easier to change (generate-documentation) than to | ||
| 22439 | @c make it below and have to deal with the churn as Transmission Daemon | ||
| 22440 | @c updates. | ||
| 22441 | |||
| 22442 | @c %start of fragment | ||
| 22443 | |||
| 22444 | Available @code{transmission-daemon-configuration} fields are: | ||
| 22445 | |||
| 22446 | @deftypevr {@code{transmission-daemon-configuration} parameter} package transmission | ||
| 22447 | The Transmission package to use. | ||
| 22448 | |||
| 22449 | @end deftypevr | ||
| 22450 | |||
| 22451 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer stop-wait-period | ||
| 22452 | The period, in seconds, to wait when stopping the service for | ||
| 22453 | @command{transmission-daemon} to exit before killing its process. This | ||
| 22454 | allows the daemon time to complete its housekeeping and send a final | ||
| 22455 | update to trackers as it shuts down. On slow hosts, or hosts with a | ||
| 22456 | slow network connection, this value may need to be increased. | ||
| 22457 | |||
| 22458 | Defaults to @samp{10}. | ||
| 22459 | |||
| 22460 | @end deftypevr | ||
| 22461 | |||
| 22462 | @deftypevr {@code{transmission-daemon-configuration} parameter} string download-dir | ||
| 22463 | The directory to which torrent files are downloaded. | ||
| 22464 | |||
| 22465 | Defaults to @samp{"/var/lib/transmission-daemon/downloads"}. | ||
| 22466 | |||
| 22467 | @end deftypevr | ||
| 22468 | |||
| 22469 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean incomplete-dir-enabled? | ||
| 22470 | If @code{#t}, files will be held in @code{incomplete-dir} while their | ||
| 22471 | torrent is being downloaded, then moved to @code{download-dir} once the | ||
| 22472 | torrent is complete. Otherwise, files for all torrents (including those | ||
| 22473 | still being downloaded) will be placed in @code{download-dir}. | ||
| 22474 | |||
| 22475 | Defaults to @samp{#f}. | ||
| 22476 | |||
| 22477 | @end deftypevr | ||
| 22478 | |||
| 22479 | @deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string incomplete-dir | ||
| 22480 | The directory in which files from incompletely downloaded torrents will | ||
| 22481 | be held when @code{incomplete-dir-enabled?} is @code{#t}. | ||
| 22482 | |||
| 22483 | Defaults to @samp{disabled}. | ||
| 22484 | |||
| 22485 | @end deftypevr | ||
| 22486 | |||
| 22487 | @deftypevr {@code{transmission-daemon-configuration} parameter} umask umask | ||
| 22488 | The file mode creation mask used for downloaded files. (See the | ||
| 22489 | @command{umask} man page for more information.) | ||
| 22490 | |||
| 22491 | Defaults to @samp{18}. | ||
| 22492 | |||
| 22493 | @end deftypevr | ||
| 22494 | |||
| 22495 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean rename-partial-files? | ||
| 22496 | When @code{#t}, ``.part'' is appended to the name of partially | ||
| 22497 | downloaded files. | ||
| 22498 | |||
| 22499 | Defaults to @samp{#t}. | ||
| 22500 | |||
| 22501 | @end deftypevr | ||
| 22502 | |||
| 22503 | @deftypevr {@code{transmission-daemon-configuration} parameter} preallocation-mode preallocation | ||
| 22504 | The mode by which space should be preallocated for downloaded files, one | ||
| 22505 | of @code{none}, @code{fast} (or @code{sparse}) and @code{full}. | ||
| 22506 | Specifying @code{full} will minimize disk fragmentation at a cost to | ||
| 22507 | file-creation speed. | ||
| 22508 | |||
| 22509 | Defaults to @samp{fast}. | ||
| 22510 | |||
| 22511 | @end deftypevr | ||
| 22512 | |||
| 22513 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean watch-dir-enabled? | ||
| 22514 | If @code{#t}, the directory specified by @code{watch-dir} will be | ||
| 22515 | watched for new @file{.torrent} files and the torrents they describe | ||
| 22516 | added automatically (and the original files removed, if | ||
| 22517 | @code{trash-original-torrent-files?} is @code{#t}). | ||
| 22518 | |||
| 22519 | Defaults to @samp{#f}. | ||
| 22520 | |||
| 22521 | @end deftypevr | ||
| 22522 | |||
| 22523 | @deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string watch-dir | ||
| 22524 | The directory to be watched for @file{.torrent} files indicating new | ||
| 22525 | torrents to be added, when @code{watch-dir-enabled} is @code{#t}. | ||
| 22526 | |||
| 22527 | Defaults to @samp{disabled}. | ||
| 22528 | |||
| 22529 | @end deftypevr | ||
| 22530 | |||
| 22531 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean trash-original-torrent-files? | ||
| 22532 | When @code{#t}, @file{.torrent} files will be deleted from the watch | ||
| 22533 | directory once their torrent has been added (see | ||
| 22534 | @code{watch-directory-enabled?}). | ||
| 22535 | |||
| 22536 | Defaults to @samp{#f}. | ||
| 22537 | |||
| 22538 | @end deftypevr | ||
| 22539 | |||
| 22540 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean speed-limit-down-enabled? | ||
| 22541 | When @code{#t}, the daemon's download speed will be limited to the rate | ||
| 22542 | specified by @code{speed-limit-down}. | ||
| 22543 | |||
| 22544 | Defaults to @samp{#f}. | ||
| 22545 | |||
| 22546 | @end deftypevr | ||
| 22547 | |||
| 22548 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer speed-limit-down | ||
| 22549 | The default global-maximum download speed, in kilobytes per second. | ||
| 22550 | |||
| 22551 | Defaults to @samp{100}. | ||
| 22552 | |||
| 22553 | @end deftypevr | ||
| 22554 | |||
| 22555 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean speed-limit-up-enabled? | ||
| 22556 | When @code{#t}, the daemon's upload speed will be limited to the rate | ||
| 22557 | specified by @code{speed-limit-up}. | ||
| 22558 | |||
| 22559 | Defaults to @samp{#f}. | ||
| 22560 | |||
| 22561 | @end deftypevr | ||
| 22562 | |||
| 22563 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer speed-limit-up | ||
| 22564 | The default global-maximum upload speed, in kilobytes per second. | ||
| 22565 | |||
| 22566 | Defaults to @samp{100}. | ||
| 22567 | |||
| 22568 | @end deftypevr | ||
| 22569 | |||
| 22570 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean alt-speed-enabled? | ||
| 22571 | When @code{#t}, the alternate speed limits @code{alt-speed-down} and | ||
| 22572 | @code{alt-speed-up} are used (in place of @code{speed-limit-down} and | ||
| 22573 | @code{speed-limit-up}, if they are enabled) to constrain the daemon's | ||
| 22574 | bandwidth usage. This can be scheduled to occur automatically at | ||
| 22575 | certain times during the week; see @code{alt-speed-time-enabled?}. | ||
| 22576 | |||
| 22577 | Defaults to @samp{#f}. | ||
| 22578 | |||
| 22579 | @end deftypevr | ||
| 22580 | |||
| 22581 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-down | ||
| 22582 | The alternate global-maximum download speed, in kilobytes per second. | ||
| 22583 | |||
| 22584 | Defaults to @samp{50}. | ||
| 22585 | |||
| 22586 | @end deftypevr | ||
| 22587 | |||
| 22588 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-up | ||
| 22589 | The alternate global-maximum upload speed, in kilobytes per second. | ||
| 22590 | |||
| 22591 | Defaults to @samp{50}. | ||
| 22592 | |||
| 22593 | @end deftypevr | ||
| 22594 | |||
| 22595 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean alt-speed-time-enabled? | ||
| 22596 | When @code{#t}, the alternate speed limits @code{alt-speed-down} and | ||
| 22597 | @code{alt-speed-up} will be enabled automatically during the periods | ||
| 22598 | specified by @code{alt-speed-time-day}, @code{alt-speed-time-begin} and | ||
| 22599 | @code{alt-time-speed-end}. | ||
| 22600 | |||
| 22601 | Defaults to @samp{#f}. | ||
| 22602 | |||
| 22603 | @end deftypevr | ||
| 22604 | |||
| 22605 | @deftypevr {@code{transmission-daemon-configuration} parameter} day-list alt-speed-time-day | ||
| 22606 | The days of the week on which the alternate-speed schedule should be | ||
| 22607 | used, specified either as a list of days (@code{sunday}, @code{monday}, | ||
| 22608 | and so on) or using one of the symbols @code{weekdays}, @code{weekends} | ||
| 22609 | or @code{all}. | ||
| 22610 | |||
| 22611 | Defaults to @samp{all}. | ||
| 22612 | |||
| 22613 | @end deftypevr | ||
| 22614 | |||
| 22615 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-time-begin | ||
| 22616 | The time of day at which to enable the alternate speed limits, expressed | ||
| 22617 | as a number of minutes since midnight. | ||
| 22618 | |||
| 22619 | Defaults to @samp{540}. | ||
| 22620 | |||
| 22621 | @end deftypevr | ||
| 22622 | |||
| 22623 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer alt-speed-time-end | ||
| 22624 | The time of day at which to disable the alternate speed limits, | ||
| 22625 | expressed as a number of minutes since midnight. | ||
| 22626 | |||
| 22627 | Defaults to @samp{1020}. | ||
| 22628 | |||
| 22629 | @end deftypevr | ||
| 22630 | |||
| 22631 | @deftypevr {@code{transmission-daemon-configuration} parameter} string bind-address-ipv4 | ||
| 22632 | The IP address at which to listen for peer connections, or ``0.0.0.0'' | ||
| 22633 | to listen at all available IP addresses. | ||
| 22634 | |||
| 22635 | Defaults to @samp{"0.0.0.0"}. | ||
| 22636 | |||
| 22637 | @end deftypevr | ||
| 22638 | |||
| 22639 | @deftypevr {@code{transmission-daemon-configuration} parameter} string bind-address-ipv6 | ||
| 22640 | The IPv6 address at which to listen for peer connections, or ``::'' to | ||
| 22641 | listen at all available IPv6 addresses. | ||
| 22642 | |||
| 22643 | Defaults to @samp{"::"}. | ||
| 22644 | |||
| 22645 | @end deftypevr | ||
| 22646 | |||
| 22647 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean peer-port-random-on-start? | ||
| 22648 | If @code{#t}, when the daemon starts it will select a port at random on | ||
| 22649 | which to listen for peer connections, from the range specified | ||
| 22650 | (inclusively) by @code{peer-port-random-low} and | ||
| 22651 | @code{peer-port-random-high}. Otherwise, it listens on the port | ||
| 22652 | specified by @code{peer-port}. | ||
| 22653 | |||
| 22654 | Defaults to @samp{#f}. | ||
| 22655 | |||
| 22656 | @end deftypevr | ||
| 22657 | |||
| 22658 | @deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port-random-low | ||
| 22659 | The lowest selectable port number when @code{peer-port-random-on-start?} | ||
| 22660 | is @code{#t}. | ||
| 22661 | |||
| 22662 | Defaults to @samp{49152}. | ||
| 22663 | |||
| 22664 | @end deftypevr | ||
| 22665 | |||
| 22666 | @deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port-random-high | ||
| 22667 | The highest selectable port number when @code{peer-port-random-on-start} | ||
| 22668 | is @code{#t}. | ||
| 22669 | |||
| 22670 | Defaults to @samp{65535}. | ||
| 22671 | |||
| 22672 | @end deftypevr | ||
| 22673 | |||
| 22674 | @deftypevr {@code{transmission-daemon-configuration} parameter} port-number peer-port | ||
| 22675 | The port on which to listen for peer connections when | ||
| 22676 | @code{peer-port-random-on-start?} is @code{#f}. | ||
| 22677 | |||
| 22678 | Defaults to @samp{51413}. | ||
| 22679 | |||
| 22680 | @end deftypevr | ||
| 22681 | |||
| 22682 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean port-forwarding-enabled? | ||
| 22683 | If @code{#t}, the daemon will attempt to configure port-forwarding on an | ||
| 22684 | upstream gateway automatically using @acronym{UPnP} and | ||
| 22685 | @acronym{NAT-PMP}. | ||
| 22686 | |||
| 22687 | Defaults to @samp{#t}. | ||
| 22688 | |||
| 22689 | @end deftypevr | ||
| 22690 | |||
| 22691 | @deftypevr {@code{transmission-daemon-configuration} parameter} encryption-mode encryption | ||
| 22692 | The encryption preference for peer connections, one of | ||
| 22693 | @code{prefer-unencrypted-connections}, | ||
| 22694 | @code{prefer-encrypted-connections} or | ||
| 22695 | @code{require-encrypted-connections}. | ||
| 22696 | |||
| 22697 | Defaults to @samp{prefer-encrypted-connections}. | ||
| 22698 | |||
| 22699 | @end deftypevr | ||
| 22700 | |||
| 22701 | @deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string peer-congestion-algorithm | ||
| 22702 | The TCP congestion-control algorithm to use for peer connections, | ||
| 22703 | specified using a string recognized by the operating system in calls to | ||
| 22704 | @code{setsockopt} (or set to @code{disabled}, in which case the | ||
| 22705 | operating-system default is used). | ||
| 22706 | |||
| 22707 | Note that on GNU/Linux systems, the kernel must be configured to allow | ||
| 22708 | processes to use a congestion-control algorithm not in the default set; | ||
| 22709 | otherwise, it will deny these requests with ``Operation not permitted''. | ||
| 22710 | To see which algorithms are available on your system and which are | ||
| 22711 | currently permitted for use, look at the contents of the files | ||
| 22712 | @file{tcp_available_congestion_control} and | ||
| 22713 | @file{tcp_allowed_congestion_control} in the @file{/proc/sys/net/ipv4} | ||
| 22714 | directory. | ||
| 22715 | |||
| 22716 | As an example, to have Transmission Daemon use | ||
| 22717 | @uref{http://www-ece.rice.edu/networks/TCP-LP/,the TCP Low Priority | ||
| 22718 | congestion-control algorithm}, you'll need to modify your kernel | ||
| 22719 | configuration to build in support for the algorithm, then update your | ||
| 22720 | operating-system configuration to allow its use by adding a | ||
| 22721 | @code{sysctl-service-type} service (or updating the existing one's | ||
| 22722 | configuration) with lines like the following: | ||
| 22723 | |||
| 22724 | @lisp | ||
| 22725 | (service sysctl-service-type | ||
| 22726 | (sysctl-configuration | ||
| 22727 | (settings | ||
| 22728 | ("net.ipv4.tcp_allowed_congestion_control" . | ||
| 22729 | "reno cubic lp")))) | ||
| 22730 | @end lisp | ||
| 22731 | |||
| 22732 | The Transmission Daemon configuration can then be updated with | ||
| 22733 | |||
| 22734 | @lisp | ||
| 22735 | (peer-congestion-algorithm "lp") | ||
| 22736 | @end lisp | ||
| 22737 | |||
| 22738 | and the system reconfigured to have the changes take effect. | ||
| 22739 | |||
| 22740 | Defaults to @samp{disabled}. | ||
| 22741 | |||
| 22742 | @end deftypevr | ||
| 22743 | |||
| 22744 | @deftypevr {@code{transmission-daemon-configuration} parameter} tcp-type-of-service peer-socket-tos | ||
| 22745 | The type of service to request in outgoing @acronym{TCP} packets, one of | ||
| 22746 | @code{default}, @code{low-cost}, @code{throughput}, @code{low-delay} and | ||
| 22747 | @code{reliability}. | ||
| 22748 | |||
| 22749 | Defaults to @samp{default}. | ||
| 22750 | |||
| 22751 | @end deftypevr | ||
| 22752 | |||
| 22753 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-limit-global | ||
| 22754 | The global limit on the number of connected peers. | ||
| 22755 | |||
| 22756 | Defaults to @samp{200}. | ||
| 22757 | |||
| 22758 | @end deftypevr | ||
| 22759 | |||
| 22760 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-limit-per-torrent | ||
| 22761 | The per-torrent limit on the number of connected peers. | ||
| 22762 | |||
| 22763 | Defaults to @samp{50}. | ||
| 22764 | |||
| 22765 | @end deftypevr | ||
| 22766 | |||
| 22767 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer upload-slots-per-torrent | ||
| 22768 | The maximum number of peers to which the daemon will upload data | ||
| 22769 | simultaneously for each torrent. | ||
| 22770 | |||
| 22771 | Defaults to @samp{14}. | ||
| 22772 | |||
| 22773 | @end deftypevr | ||
| 22774 | |||
| 22775 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer peer-id-ttl-hours | ||
| 22776 | The maximum lifespan, in hours, of the peer ID associated with each | ||
| 22777 | public torrent before it is regenerated. | ||
| 22778 | |||
| 22779 | Defaults to @samp{6}. | ||
| 22780 | |||
| 22781 | @end deftypevr | ||
| 22782 | |||
| 22783 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean blocklist-enabled? | ||
| 22784 | When @code{#t}, the daemon will ignore peers mentioned in the blocklist | ||
| 22785 | it has most recently downloaded from @code{blocklist-url}. | ||
| 22786 | |||
| 22787 | Defaults to @samp{#f}. | ||
| 22788 | |||
| 22789 | @end deftypevr | ||
| 22790 | |||
| 22791 | @deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string blocklist-url | ||
| 22792 | The URL of a peer blocklist (in @acronym{P2P}-plaintext or eMule | ||
| 22793 | @file{.dat} format) to be periodically downloaded and applied when | ||
| 22794 | @code{blocklist-enabled?} is @code{#t}. | ||
| 22795 | |||
| 22796 | Defaults to @samp{disabled}. | ||
| 22797 | |||
| 22798 | @end deftypevr | ||
| 22799 | |||
| 22800 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean download-queue-enabled? | ||
| 22801 | If @code{#t}, the daemon will be limited to downloading at most | ||
| 22802 | @code{download-queue-size} non-stalled torrents simultaneously. | ||
| 22803 | |||
| 22804 | Defaults to @samp{#t}. | ||
| 22805 | |||
| 22806 | @end deftypevr | ||
| 22807 | |||
| 22808 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer download-queue-size | ||
| 22809 | The size of the daemon's download queue, which limits the number of | ||
| 22810 | non-stalled torrents it will download at any one time when | ||
| 22811 | @code{download-queue-enabled?} is @code{#t}. | ||
| 22812 | |||
| 22813 | Defaults to @samp{5}. | ||
| 22814 | |||
| 22815 | @end deftypevr | ||
| 22816 | |||
| 22817 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean seed-queue-enabled? | ||
| 22818 | If @code{#t}, the daemon will be limited to seeding at most | ||
| 22819 | @code{seed-queue-size} non-stalled torrents simultaneously. | ||
| 22820 | |||
| 22821 | Defaults to @samp{#f}. | ||
| 22822 | |||
| 22823 | @end deftypevr | ||
| 22824 | |||
| 22825 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer seed-queue-size | ||
| 22826 | The size of the daemon's seed queue, which limits the number of | ||
| 22827 | non-stalled torrents it will seed at any one time when | ||
| 22828 | @code{seed-queue-enabled?} is @code{#t}. | ||
| 22829 | |||
| 22830 | Defaults to @samp{10}. | ||
| 22831 | |||
| 22832 | @end deftypevr | ||
| 22833 | |||
| 22834 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean queue-stalled-enabled? | ||
| 22835 | When @code{#t}, the daemon will consider torrents for which it has not | ||
| 22836 | shared data in the past @code{queue-stalled-minutes} minutes to be | ||
| 22837 | stalled and not count them against its @code{download-queue-size} and | ||
| 22838 | @code{seed-queue-size} limits. | ||
| 22839 | |||
| 22840 | Defaults to @samp{#t}. | ||
| 22841 | |||
| 22842 | @end deftypevr | ||
| 22843 | |||
| 22844 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer queue-stalled-minutes | ||
| 22845 | The maximum period, in minutes, a torrent may be idle before it is | ||
| 22846 | considered to be stalled, when @code{queue-stalled-enabled?} is | ||
| 22847 | @code{#t}. | ||
| 22848 | |||
| 22849 | Defaults to @samp{30}. | ||
| 22850 | |||
| 22851 | @end deftypevr | ||
| 22852 | |||
| 22853 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean ratio-limit-enabled? | ||
| 22854 | When @code{#t}, a torrent being seeded will automatically be paused once | ||
| 22855 | it reaches the ratio specified by @code{ratio-limit}. | ||
| 22856 | |||
| 22857 | Defaults to @samp{#f}. | ||
| 22858 | |||
| 22859 | @end deftypevr | ||
| 22860 | |||
| 22861 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-rational ratio-limit | ||
| 22862 | The ratio at which a torrent being seeded will be paused, when | ||
| 22863 | @code{ratio-limit-enabled?} is @code{#t}. | ||
| 22864 | |||
| 22865 | Defaults to @samp{2.0}. | ||
| 22866 | |||
| 22867 | @end deftypevr | ||
| 22868 | |||
| 22869 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean idle-seeding-limit-enabled? | ||
| 22870 | When @code{#t}, a torrent being seeded will automatically be paused once | ||
| 22871 | it has been idle for @code{idle-seeding-limit} minutes. | ||
| 22872 | |||
| 22873 | Defaults to @samp{#f}. | ||
| 22874 | |||
| 22875 | @end deftypevr | ||
| 22876 | |||
| 22877 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer idle-seeding-limit | ||
| 22878 | The maximum period, in minutes, a torrent being seeded may be idle | ||
| 22879 | before it is paused, when @code{idle-seeding-limit-enabled?} is | ||
| 22880 | @code{#t}. | ||
| 22881 | |||
| 22882 | Defaults to @samp{30}. | ||
| 22883 | |||
| 22884 | @end deftypevr | ||
| 22885 | |||
| 22886 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean dht-enabled? | ||
| 22887 | Enable @uref{http://bittorrent.org/beps/bep_0005.html,the distributed | ||
| 22888 | hash table (@acronym{DHT}) protocol}, which supports the use of | ||
| 22889 | trackerless torrents. | ||
| 22890 | |||
| 22891 | Defaults to @samp{#t}. | ||
| 22892 | |||
| 22893 | @end deftypevr | ||
| 22894 | |||
| 22895 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean lpd-enabled? | ||
| 22896 | Enable @uref{https://en.wikipedia.org/wiki/Local_Peer_Discovery,local | ||
| 22897 | peer discovery} (@acronym{LPD}), which allows the discovery of peers on | ||
| 22898 | the local network and may reduce the amount of data sent over the public | ||
| 22899 | Internet. | ||
| 22900 | |||
| 22901 | Defaults to @samp{#f}. | ||
| 22902 | |||
| 22903 | @end deftypevr | ||
| 22904 | |||
| 22905 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean pex-enabled? | ||
| 22906 | Enable @uref{https://en.wikipedia.org/wiki/Peer_exchange,peer exchange} | ||
| 22907 | (@acronym{PEX}), which reduces the daemon's reliance on external | ||
| 22908 | trackers and may improve its performance. | ||
| 22909 | |||
| 22910 | Defaults to @samp{#t}. | ||
| 22911 | |||
| 22912 | @end deftypevr | ||
| 22913 | |||
| 22914 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean utp-enabled? | ||
| 22915 | Enable @uref{http://bittorrent.org/beps/bep_0029.html,the micro | ||
| 22916 | transport protocol} (@acronym{uTP}), which aims to reduce the impact of | ||
| 22917 | BitTorrent traffic on other users of the local network while maintaining | ||
| 22918 | full utilization of the available bandwidth. | ||
| 22919 | |||
| 22920 | Defaults to @samp{#t}. | ||
| 22921 | |||
| 22922 | @end deftypevr | ||
| 22923 | |||
| 22924 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean rpc-enabled? | ||
| 22925 | If @code{#t}, enable the remote procedure call (@acronym{RPC}) | ||
| 22926 | interface, which allows remote control of the daemon via its Web | ||
| 22927 | interface, the @command{transmission-remote} command-line client, and | ||
| 22928 | similar tools. | ||
| 22929 | |||
| 22930 | Defaults to @samp{#t}. | ||
| 22931 | |||
| 22932 | @end deftypevr | ||
| 22933 | |||
| 22934 | @deftypevr {@code{transmission-daemon-configuration} parameter} string rpc-bind-address | ||
| 22935 | The IP address at which to listen for @acronym{RPC} connections, or | ||
| 22936 | ``0.0.0.0'' to listen at all available IP addresses. | ||
| 22937 | |||
| 22938 | Defaults to @samp{"0.0.0.0"}. | ||
| 22939 | |||
| 22940 | @end deftypevr | ||
| 22941 | |||
| 22942 | @deftypevr {@code{transmission-daemon-configuration} parameter} port-number rpc-port | ||
| 22943 | The port on which to listen for @acronym{RPC} connections. | ||
| 22944 | |||
| 22945 | Defaults to @samp{9091}. | ||
| 22946 | |||
| 22947 | @end deftypevr | ||
| 22948 | |||
| 22949 | @deftypevr {@code{transmission-daemon-configuration} parameter} string rpc-url | ||
| 22950 | The path prefix to use in the @acronym{RPC}-endpoint @acronym{URL}. | ||
| 22951 | |||
| 22952 | Defaults to @samp{"/transmission/"}. | ||
| 22953 | |||
| 22954 | @end deftypevr | ||
| 22955 | |||
| 22956 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean rpc-authentication-required? | ||
| 22957 | When @code{#t}, clients must authenticate (see @code{rpc-username} and | ||
| 22958 | @code{rpc-password}) when using the @acronym{RPC} interface. Note this | ||
| 22959 | has the side effect of disabling host-name whitelisting (see | ||
| 22960 | @code{rpc-host-whitelist-enabled?}. | ||
| 22961 | |||
| 22962 | Defaults to @samp{#f}. | ||
| 22963 | |||
| 22964 | @end deftypevr | ||
| 22965 | |||
| 22966 | @deftypevr {@code{transmission-daemon-configuration} parameter} maybe-string rpc-username | ||
| 22967 | The username required by clients to access the @acronym{RPC} interface | ||
| 22968 | when @code{rpc-authentication-required?} is @code{#t}. | ||
| 22969 | |||
| 22970 | Defaults to @samp{disabled}. | ||
| 22971 | |||
| 22972 | @end deftypevr | ||
| 22973 | |||
| 22974 | @deftypevr {@code{transmission-daemon-configuration} parameter} maybe-transmission-password-hash rpc-password | ||
| 22975 | The password required by clients to access the @acronym{RPC} interface | ||
| 22976 | when @code{rpc-authentication-required?} is @code{#t}. This must be | ||
| 22977 | specified using a password hash in the format recognized by Transmission | ||
| 22978 | clients, either copied from an existing @file{settings.json} file or | ||
| 22979 | generated using the @code{transmission-password-hash} procedure. | ||
| 22980 | |||
| 22981 | Defaults to @samp{disabled}. | ||
| 22982 | |||
| 22983 | @end deftypevr | ||
| 22984 | |||
| 22985 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean rpc-whitelist-enabled? | ||
| 22986 | When @code{#t}, @acronym{RPC} requests will be accepted only when they | ||
| 22987 | originate from an address specified in @code{rpc-whitelist}. | ||
| 22988 | |||
| 22989 | Defaults to @samp{#t}. | ||
| 22990 | |||
| 22991 | @end deftypevr | ||
| 22992 | |||
| 22993 | @deftypevr {@code{transmission-daemon-configuration} parameter} string-list rpc-whitelist | ||
| 22994 | The list of IP and IPv6 addresses from which @acronym{RPC} requests will | ||
| 22995 | be accepted when @code{rpc-whitelist-enabled?} is @code{#t}. Wildcards | ||
| 22996 | may be specified using @samp{*}. | ||
| 22997 | |||
| 22998 | Defaults to @samp{("127.0.0.1" "::1")}. | ||
| 22999 | |||
| 23000 | @end deftypevr | ||
| 23001 | |||
| 23002 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean rpc-host-whitelist-enabled? | ||
| 23003 | When @code{#t}, @acronym{RPC} requests will be accepted only when they | ||
| 23004 | are addressed to a host named in @code{rpc-host-whitelist}. Note that | ||
| 23005 | requests to ``localhost'' or ``localhost.'', or to a numeric address, | ||
| 23006 | are always accepted regardless of these settings. | ||
| 23007 | |||
| 23008 | Note also this functionality is disabled when | ||
| 23009 | @code{rpc-authentication-required?} is @code{#t}. | ||
| 23010 | |||
| 23011 | Defaults to @samp{#t}. | ||
| 23012 | |||
| 23013 | @end deftypevr | ||
| 23014 | |||
| 23015 | @deftypevr {@code{transmission-daemon-configuration} parameter} string-list rpc-host-whitelist | ||
| 23016 | The list of host names recognized by the @acronym{RPC} server when | ||
| 23017 | @code{rpc-host-whitelist-enabled?} is @code{#t}. | ||
| 23018 | |||
| 23019 | Defaults to @samp{()}. | ||
| 23020 | |||
| 23021 | @end deftypevr | ||
| 23022 | |||
| 23023 | @deftypevr {@code{transmission-daemon-configuration} parameter} message-level message-level | ||
| 23024 | The minimum severity level of messages to be logged (to | ||
| 23025 | @file{/var/log/transmission.log}) by the daemon, one of @code{none} (no | ||
| 23026 | logging), @code{error}, @code{info} and @code{debug}. | ||
| 23027 | |||
| 23028 | Defaults to @samp{info}. | ||
| 23029 | |||
| 23030 | @end deftypevr | ||
| 23031 | |||
| 23032 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean start-added-torrents? | ||
| 23033 | When @code{#t}, torrents are started as soon as they are added; | ||
| 23034 | otherwise, they are added in ``paused'' state. | ||
| 23035 | |||
| 23036 | Defaults to @samp{#t}. | ||
| 23037 | |||
| 23038 | @end deftypevr | ||
| 23039 | |||
| 23040 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean script-torrent-done-enabled? | ||
| 23041 | When @code{#t}, the script specified by | ||
| 23042 | @code{script-torrent-done-filename} will be invoked each time a torrent | ||
| 23043 | completes. | ||
| 23044 | |||
| 23045 | Defaults to @samp{#f}. | ||
| 23046 | |||
| 23047 | @end deftypevr | ||
| 23048 | |||
| 23049 | @deftypevr {@code{transmission-daemon-configuration} parameter} maybe-file-object script-torrent-done-filename | ||
| 23050 | A file name or file-like object specifying a script to run each time a | ||
| 23051 | torrent completes, when @code{script-torrent-done-enabled?} is | ||
| 23052 | @code{#t}. | ||
| 23053 | |||
| 23054 | Defaults to @samp{disabled}. | ||
| 23055 | |||
| 23056 | @end deftypevr | ||
| 23057 | |||
| 23058 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean scrape-paused-torrents-enabled? | ||
| 23059 | When @code{#t}, the daemon will scrape trackers for a torrent even when | ||
| 23060 | the torrent is paused. | ||
| 23061 | |||
| 23062 | Defaults to @samp{#t}. | ||
| 23063 | |||
| 23064 | @end deftypevr | ||
| 23065 | |||
| 23066 | @deftypevr {@code{transmission-daemon-configuration} parameter} non-negative-integer cache-size-mb | ||
| 23067 | The amount of memory, in megabytes, to allocate for the daemon's | ||
| 23068 | in-memory cache. A larger value may increase performance by reducing | ||
| 23069 | the frequency of disk I/O. | ||
| 23070 | |||
| 23071 | Defaults to @samp{4}. | ||
| 23072 | |||
| 23073 | @end deftypevr | ||
| 23074 | |||
| 23075 | @deftypevr {@code{transmission-daemon-configuration} parameter} boolean prefetch-enabled? | ||
| 23076 | When @code{#t}, the daemon will try to improve I/O performance by | ||
| 23077 | hinting to the operating system which data is likely to be read next | ||
| 23078 | from disk to satisfy requests from peers. | ||
| 23079 | |||
| 23080 | Defaults to @samp{#t}. | ||
| 23081 | |||
| 23082 | @end deftypevr | ||
| 23083 | |||
| 23084 | |||
| 23085 | @c %end of fragment | ||
| 23086 | |||
| 23087 | |||
| 23088 | |||
| 22290 | @node Monitoring Services | 23089 | @node Monitoring Services |
| 22291 | @subsection Monitoring Services | 23090 | @subsection Monitoring Services |
| 22292 | 23091 | ||
diff --git a/gnu/local.mk b/gnu/local.mk index d098c04308c..0625c6c5ebf 100644 --- a/gnu/local.mk +++ b/gnu/local.mk | |||
| @@ -605,6 +605,7 @@ GNU_SYSTEM_MODULES = \ | |||
| 605 | %D%/services/dns.scm \ | 605 | %D%/services/dns.scm \ |
| 606 | %D%/services/docker.scm \ | 606 | %D%/services/docker.scm \ |
| 607 | %D%/services/authentication.scm \ | 607 | %D%/services/authentication.scm \ |
| 608 | %D%/services/file-sharing.scm \ | ||
| 608 | %D%/services/games.scm \ | 609 | %D%/services/games.scm \ |
| 609 | %D%/services/ganeti.scm \ | 610 | %D%/services/ganeti.scm \ |
| 610 | %D%/services/getmail.scm \ | 611 | %D%/services/getmail.scm \ |
diff --git a/gnu/services/file-sharing.scm b/gnu/services/file-sharing.scm new file mode 100644 index 00000000000..72cd6478d64 --- /dev/null +++ b/gnu/services/file-sharing.scm | |||
| @@ -0,0 +1,804 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2020 Simon South <simon@simonsouth.net> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (gnu services file-sharing) | ||
| 20 | #:use-module (gcrypt base16) | ||
| 21 | #:use-module (gcrypt hash) | ||
| 22 | #:use-module (gcrypt random) | ||
| 23 | #:use-module (gnu services) | ||
| 24 | #:use-module (gnu services admin) | ||
| 25 | #:use-module (gnu services configuration) | ||
| 26 | #:use-module (gnu services shepherd) | ||
| 27 | #:use-module (gnu packages admin) | ||
| 28 | #:use-module (gnu packages bittorrent) | ||
| 29 | #:use-module (gnu packages gnupg) | ||
| 30 | #:use-module (gnu packages guile) | ||
| 31 | #:use-module (gnu system shadow) | ||
| 32 | #:use-module (guix diagnostics) | ||
| 33 | #:use-module (guix gexp) | ||
| 34 | #:use-module (guix i18n) | ||
| 35 | #:use-module (guix modules) | ||
| 36 | #:use-module (guix packages) | ||
| 37 | #:use-module (guix records) | ||
| 38 | #:use-module (ice-9 format) | ||
| 39 | #:use-module (ice-9 match) | ||
| 40 | #:use-module (rnrs bytevectors) | ||
| 41 | #:use-module (srfi srfi-1) | ||
| 42 | #:use-module (srfi srfi-34) | ||
| 43 | #:use-module (srfi srfi-35) | ||
| 44 | #:export (transmission-daemon-configuration | ||
| 45 | transmission-daemon-service-type | ||
| 46 | transmission-password-hash | ||
| 47 | transmission-random-salt)) | ||
| 48 | |||
| 49 | ;;; | ||
| 50 | ;;; Transmission Daemon. | ||
| 51 | ;;; | ||
| 52 | |||
| 53 | (define %transmission-daemon-user "transmission") | ||
| 54 | (define %transmission-daemon-group "transmission") | ||
| 55 | |||
| 56 | (define %transmission-daemon-configuration-directory | ||
| 57 | "/var/lib/transmission-daemon") | ||
| 58 | (define %transmission-daemon-log-file | ||
| 59 | "/var/log/transmission.log") | ||
| 60 | |||
| 61 | (define %transmission-salt-length 8) | ||
| 62 | |||
| 63 | (define (transmission-password-hash password salt) | ||
| 64 | "Returns a string containing the result of hashing @var{password} together | ||
| 65 | with @var{salt}, in the format recognized by Transmission clients for their | ||
| 66 | @code{rpc-password} configuration setting. | ||
| 67 | |||
| 68 | @var{salt} must be an eight-character string. The | ||
| 69 | @code{transmission-random-salt} procedure can be used to generate a suitable | ||
| 70 | salt value at random." | ||
| 71 | (if (not (and (string? salt) | ||
| 72 | (eq? (string-length salt) %transmission-salt-length))) | ||
| 73 | (raise (formatted-message | ||
| 74 | (G_ "salt value must be a string of ~d characters") | ||
| 75 | %transmission-salt-length)) | ||
| 76 | (string-append "{" | ||
| 77 | (bytevector->base16-string | ||
| 78 | (sha1 (string->utf8 (string-append password salt)))) | ||
| 79 | salt))) | ||
| 80 | |||
| 81 | (define (transmission-random-salt) | ||
| 82 | "Returns a string containing a random, eight-character salt value of the | ||
| 83 | type generated and used by Transmission clients, suitable for passing to the | ||
| 84 | @code{transmission-password-hash} procedure." | ||
| 85 | ;; This implementation matches a portion of Transmission's tr_ssha1 | ||
| 86 | ;; function. See libtransmission/crypto-utils.c in the Transmission source | ||
| 87 | ;; distribution. | ||
| 88 | (let ((salter (string-append "0123456789" | ||
| 89 | "abcdefghijklmnopqrstuvwxyz" | ||
| 90 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
| 91 | "./"))) | ||
| 92 | (list->string | ||
| 93 | (map (lambda (u8) | ||
| 94 | (string-ref salter (modulo u8 (string-length salter)))) | ||
| 95 | (bytevector->u8-list | ||
| 96 | (gen-random-bv %transmission-salt-length %gcry-strong-random)))))) | ||
| 97 | |||
| 98 | (define (uglify-field-name field-name) | ||
| 99 | (string-delete #\? (symbol->string field-name))) | ||
| 100 | |||
| 101 | (define (serialize-field field-name val) | ||
| 102 | ;; "Serialize" each configuration field as a G-expression containing a | ||
| 103 | ;; name-value pair, the collection of which will subsequently be serialized | ||
| 104 | ;; to disk as a JSON object. | ||
| 105 | #~(#$(uglify-field-name field-name) . #$val)) | ||
| 106 | |||
| 107 | (define serialize-boolean serialize-field) | ||
| 108 | (define serialize-integer serialize-field) | ||
| 109 | (define serialize-rational serialize-field) | ||
| 110 | |||
| 111 | (define serialize-string serialize-field) | ||
| 112 | (define-maybe string) | ||
| 113 | ;; Override the definition of "serialize-maybe-string", as we need to output a | ||
| 114 | ;; name-value pair for the JSON builder. | ||
| 115 | (set! serialize-maybe-string | ||
| 116 | (lambda (field-name val) | ||
| 117 | (serialize-string field-name | ||
| 118 | (if (and (symbol? val) | ||
| 119 | (eq? val 'disabled)) | ||
| 120 | "" | ||
| 121 | val)))) | ||
| 122 | |||
| 123 | (define (string-list? val) | ||
| 124 | (and (list? val) | ||
| 125 | (and-map (lambda (x) | ||
| 126 | (and (string? x) | ||
| 127 | (not (string-index x #\,)))) | ||
| 128 | val))) | ||
| 129 | (define (serialize-string-list field-name val) | ||
| 130 | (serialize-field field-name (string-join val ","))) | ||
| 131 | |||
| 132 | (define days | ||
| 133 | '((sunday . #b0000001) | ||
| 134 | (monday . #b0000010) | ||
| 135 | (tuesday . #b0000100) | ||
| 136 | (wednesday . #b0001000) | ||
| 137 | (thursday . #b0010000) | ||
| 138 | (friday . #b0100000) | ||
| 139 | (saturday . #b1000000))) | ||
| 140 | (define day-lists | ||
| 141 | (list (cons 'weekdays '(monday tuesday wednesday thursday friday)) | ||
| 142 | (cons 'weekends '(saturday sunday)) | ||
| 143 | (cons 'all (map car days)))) | ||
| 144 | (define (day-list? val) | ||
| 145 | (or (and (symbol? val) | ||
| 146 | (assq val day-lists)) | ||
| 147 | (and (list? val) | ||
| 148 | (and-map (lambda (x) | ||
| 149 | (and (symbol? x) | ||
| 150 | (assq x days))) | ||
| 151 | val)))) | ||
| 152 | (define (serialize-day-list field-name val) | ||
| 153 | (serialize-integer field-name | ||
| 154 | (reduce logior | ||
| 155 | #b0000000 | ||
| 156 | (map (lambda (day) | ||
| 157 | (assq-ref days day)) | ||
| 158 | (if (symbol? val) | ||
| 159 | (assq-ref day-lists val) | ||
| 160 | val))))) | ||
| 161 | |||
| 162 | (define encryption-modes | ||
| 163 | '((prefer-unencrypted-connections . 0) | ||
| 164 | (prefer-encrypted-connections . 1) | ||
| 165 | (require-encrypted-connections . 2))) | ||
| 166 | (define (encryption-mode? val) | ||
| 167 | (and (symbol? val) | ||
| 168 | (assq val encryption-modes))) | ||
| 169 | (define (serialize-encryption-mode field-name val) | ||
| 170 | (serialize-integer field-name (assq-ref encryption-modes val))) | ||
| 171 | |||
| 172 | (define serialize-file-like serialize-field) | ||
| 173 | |||
| 174 | (define (file-object? val) | ||
| 175 | (or (string? val) | ||
| 176 | (file-like? val))) | ||
| 177 | (define (serialize-file-object field-name val) | ||
| 178 | (if (file-like? val) | ||
| 179 | (serialize-file-like field-name val) | ||
| 180 | (serialize-string field-name val))) | ||
| 181 | (define-maybe file-object) | ||
| 182 | (set! serialize-maybe-file-object | ||
| 183 | (lambda (field-name val) | ||
| 184 | (if (and (symbol? val) | ||
| 185 | (eq? val 'disabled)) | ||
| 186 | (serialize-string field-name "") | ||
| 187 | (serialize-file-object field-name val)))) | ||
| 188 | |||
| 189 | (define (file-object-list? val) | ||
| 190 | (and (list? val) | ||
| 191 | (and-map file-object? val))) | ||
| 192 | (define serialize-file-object-list serialize-field) | ||
| 193 | |||
| 194 | (define message-levels | ||
| 195 | '((none . 0) | ||
| 196 | (error . 1) | ||
| 197 | (info . 2) | ||
| 198 | (debug . 3))) | ||
| 199 | (define (message-level? val) | ||
| 200 | (and (symbol? val) | ||
| 201 | (assq val message-levels))) | ||
| 202 | (define (serialize-message-level field-name val) | ||
| 203 | (serialize-integer field-name (assq-ref message-levels val))) | ||
| 204 | |||
| 205 | (define (non-negative-integer? val) | ||
| 206 | (and (integer? val) | ||
| 207 | (not (negative? val)))) | ||
| 208 | (define serialize-non-negative-integer serialize-integer) | ||
| 209 | |||
| 210 | (define (non-negative-rational? val) | ||
| 211 | (and (rational? val) | ||
| 212 | (not (negative? val)))) | ||
| 213 | (define serialize-non-negative-rational serialize-rational) | ||
| 214 | |||
| 215 | (define (port-number? val) | ||
| 216 | (and (integer? val) | ||
| 217 | (>= val 1) | ||
| 218 | (<= val 65535))) | ||
| 219 | (define serialize-port-number serialize-integer) | ||
| 220 | |||
| 221 | (define preallocation-modes | ||
| 222 | '((none . 0) | ||
| 223 | (fast . 1) | ||
| 224 | (sparse . 1) | ||
| 225 | (full . 2))) | ||
| 226 | (define (preallocation-mode? val) | ||
| 227 | (and (symbol? val) | ||
| 228 | (assq val preallocation-modes))) | ||
| 229 | (define (serialize-preallocation-mode field-name val) | ||
| 230 | (serialize-integer field-name (assq-ref preallocation-modes val))) | ||
| 231 | |||
| 232 | (define tcp-types-of-service | ||
| 233 | '((default . "default") | ||
| 234 | (low-cost . "lowcost") | ||
| 235 | (throughput . "throughput") | ||
| 236 | (low-delay . "lowdelay") | ||
| 237 | (reliability . "reliability"))) | ||
| 238 | (define (tcp-type-of-service? val) | ||
| 239 | (and (symbol? val) | ||
| 240 | (assq val tcp-types-of-service))) | ||
| 241 | (define (serialize-tcp-type-of-service field-name val) | ||
| 242 | (serialize-string field-name (assq-ref tcp-types-of-service val))) | ||
| 243 | |||
| 244 | (define (transmission-password-hash? val) | ||
| 245 | (and (string? val) | ||
| 246 | (= (string-length val) 49) | ||
| 247 | (eqv? (string-ref val 0) #\{) | ||
| 248 | (string-every char-set:hex-digit val 1 41))) | ||
| 249 | (define serialize-transmission-password-hash serialize-string) | ||
| 250 | (define-maybe transmission-password-hash) | ||
| 251 | (set! serialize-maybe-transmission-password-hash serialize-maybe-string) | ||
| 252 | |||
| 253 | (define (umask? val) | ||
| 254 | (and (integer? val) | ||
| 255 | (>= val #o000) | ||
| 256 | (<= val #o777))) | ||
| 257 | (define serialize-umask serialize-integer) ; must use decimal representation | ||
| 258 | |||
| 259 | (define-configuration transmission-daemon-configuration | ||
| 260 | ;; Settings internal to this service definition. | ||
| 261 | (transmission | ||
| 262 | (package transmission) | ||
| 263 | "The Transmission package to use.") | ||
| 264 | (stop-wait-period | ||
| 265 | (non-negative-integer 10) | ||
| 266 | "The period, in seconds, to wait when stopping the service for | ||
| 267 | @command{transmission-daemon} to exit before killing its process. This allows | ||
| 268 | the daemon time to complete its housekeeping and send a final update to | ||
| 269 | trackers as it shuts down. On slow hosts, or hosts with a slow network | ||
| 270 | connection, this value may need to be increased.") | ||
| 271 | |||
| 272 | ;; Files and directories. | ||
| 273 | (download-dir | ||
| 274 | (string (string-append %transmission-daemon-configuration-directory | ||
| 275 | "/downloads")) | ||
| 276 | "The directory to which torrent files are downloaded.") | ||
| 277 | (incomplete-dir-enabled? | ||
| 278 | (boolean #f) | ||
| 279 | "If @code{#t}, files will be held in @code{incomplete-dir} while their | ||
| 280 | torrent is being downloaded, then moved to @code{download-dir} once the | ||
| 281 | torrent is complete. Otherwise, files for all torrents (including those still | ||
| 282 | being downloaded) will be placed in @code{download-dir}.") | ||
| 283 | (incomplete-dir | ||
| 284 | (maybe-string 'disabled) | ||
| 285 | "The directory in which files from incompletely downloaded torrents will be | ||
| 286 | held when @code{incomplete-dir-enabled?} is @code{#t}.") | ||
| 287 | (umask | ||
| 288 | (umask #o022) | ||
| 289 | "The file mode creation mask used for downloaded files. (See the | ||
| 290 | @command{umask} man page for more information.)") | ||
| 291 | (rename-partial-files? | ||
| 292 | (boolean #t) | ||
| 293 | "When @code{#t}, ``.part'' is appended to the name of partially downloaded | ||
| 294 | files.") | ||
| 295 | (preallocation | ||
| 296 | (preallocation-mode 'fast) | ||
| 297 | "The mode by which space should be preallocated for downloaded files, one | ||
| 298 | of @code{none}, @code{fast} (or @code{sparse}) and @code{full}. Specifying | ||
| 299 | @code{full} will minimize disk fragmentation at a cost to file-creation | ||
| 300 | speed.") | ||
| 301 | (watch-dir-enabled? | ||
| 302 | (boolean #f) | ||
| 303 | "If @code{#t}, the directory specified by @code{watch-dir} will be watched | ||
| 304 | for new @file{.torrent} files and the torrents they describe added | ||
| 305 | automatically (and the original files removed, if | ||
| 306 | @code{trash-original-torrent-files?} is @code{#t}).") | ||
| 307 | (watch-dir | ||
| 308 | (maybe-string 'disabled) | ||
| 309 | "The directory to be watched for @file{.torrent} files indicating new | ||
| 310 | torrents to be added, when @code{watch-dir-enabled} is @code{#t}.") | ||
| 311 | (trash-original-torrent-files? | ||
| 312 | (boolean #f) | ||
| 313 | "When @code{#t}, @file{.torrent} files will be deleted from the watch | ||
| 314 | directory once their torrent has been added (see | ||
| 315 | @code{watch-directory-enabled?}).") | ||
| 316 | |||
| 317 | ;; Bandwidth limits. | ||
| 318 | (speed-limit-down-enabled? | ||
| 319 | (boolean #f) | ||
| 320 | "When @code{#t}, the daemon's download speed will be limited to the rate | ||
| 321 | specified by @code{speed-limit-down}.") | ||
| 322 | (speed-limit-down | ||
| 323 | (non-negative-integer 100) | ||
| 324 | "The default global-maximum download speed, in kilobytes per second.") | ||
| 325 | (speed-limit-up-enabled? | ||
| 326 | (boolean #f) | ||
| 327 | "When @code{#t}, the daemon's upload speed will be limited to the rate | ||
| 328 | specified by @code{speed-limit-up}.") | ||
| 329 | (speed-limit-up | ||
| 330 | (non-negative-integer 100) | ||
| 331 | "The default global-maximum upload speed, in kilobytes per second.") | ||
| 332 | (alt-speed-enabled? | ||
| 333 | (boolean #f) | ||
| 334 | "When @code{#t}, the alternate speed limits @code{alt-speed-down} and | ||
| 335 | @code{alt-speed-up} are used (in place of @code{speed-limit-down} and | ||
| 336 | @code{speed-limit-up}, if they are enabled) to constrain the daemon's | ||
| 337 | bandwidth usage. This can be scheduled to occur automatically at certain | ||
| 338 | times during the week; see @code{alt-speed-time-enabled?}.") | ||
| 339 | (alt-speed-down | ||
| 340 | (non-negative-integer 50) | ||
| 341 | "The alternate global-maximum download speed, in kilobytes per second.") | ||
| 342 | (alt-speed-up | ||
| 343 | (non-negative-integer 50) | ||
| 344 | "The alternate global-maximum upload speed, in kilobytes per second.") | ||
| 345 | |||
| 346 | ;; Bandwidth-limit scheduling. | ||
| 347 | (alt-speed-time-enabled? | ||
| 348 | (boolean #f) | ||
| 349 | "When @code{#t}, the alternate speed limits @code{alt-speed-down} and | ||
| 350 | @code{alt-speed-up} will be enabled automatically during the periods specified | ||
| 351 | by @code{alt-speed-time-day}, @code{alt-speed-time-begin} and | ||
| 352 | @code{alt-time-speed-end}.") | ||
| 353 | (alt-speed-time-day | ||
| 354 | (day-list 'all) | ||
| 355 | "The days of the week on which the alternate-speed schedule should be used, | ||
| 356 | specified either as a list of days (@code{sunday}, @code{monday}, and so on) | ||
| 357 | or using one of the symbols @code{weekdays}, @code{weekends} or @code{all}.") | ||
| 358 | (alt-speed-time-begin | ||
| 359 | (non-negative-integer 540) | ||
| 360 | "The time of day at which to enable the alternate speed limits, | ||
| 361 | expressed as a number of minutes since midnight.") | ||
| 362 | (alt-speed-time-end | ||
| 363 | (non-negative-integer 1020) | ||
| 364 | "The time of day at which to disable the alternate speed limits, | ||
| 365 | expressed as a number of minutes since midnight.") | ||
| 366 | |||
| 367 | ;; Peer networking. | ||
| 368 | (bind-address-ipv4 | ||
| 369 | (string "0.0.0.0") | ||
| 370 | "The IP address at which to listen for peer connections, or ``0.0.0.0'' to | ||
| 371 | listen at all available IP addresses.") | ||
| 372 | (bind-address-ipv6 | ||
| 373 | (string "::") | ||
| 374 | "The IPv6 address at which to listen for peer connections, or ``::'' to | ||
| 375 | listen at all available IPv6 addresses.") | ||
| 376 | (peer-port-random-on-start? | ||
| 377 | (boolean #f) | ||
| 378 | "If @code{#t}, when the daemon starts it will select a port at random on | ||
| 379 | which to listen for peer connections, from the range specified (inclusively) | ||
| 380 | by @code{peer-port-random-low} and @code{peer-port-random-high}. Otherwise, | ||
| 381 | it listens on the port specified by @code{peer-port}.") | ||
| 382 | (peer-port-random-low | ||
| 383 | (port-number 49152) | ||
| 384 | "The lowest selectable port number when @code{peer-port-random-on-start?} | ||
| 385 | is @code{#t}.") | ||
| 386 | (peer-port-random-high | ||
| 387 | (port-number 65535) | ||
| 388 | "The highest selectable port number when @code{peer-port-random-on-start} | ||
| 389 | is @code{#t}.") | ||
| 390 | (peer-port | ||
| 391 | (port-number 51413) | ||
| 392 | "The port on which to listen for peer connections when | ||
| 393 | @code{peer-port-random-on-start?} is @code{#f}.") | ||
| 394 | (port-forwarding-enabled? | ||
| 395 | (boolean #t) | ||
| 396 | "If @code{#t}, the daemon will attempt to configure port-forwarding on an | ||
| 397 | upstream gateway automatically using @acronym{UPnP} and @acronym{NAT-PMP}.") | ||
| 398 | (encryption | ||
| 399 | (encryption-mode 'prefer-encrypted-connections) | ||
| 400 | "The encryption preference for peer connections, one of | ||
| 401 | @code{prefer-unencrypted-connections}, @code{prefer-encrypted-connections} or | ||
| 402 | @code{require-encrypted-connections}.") | ||
| 403 | (peer-congestion-algorithm | ||
| 404 | (maybe-string 'disabled) | ||
| 405 | "The TCP congestion-control algorithm to use for peer connections, | ||
| 406 | specified using a string recognized by the operating system in calls to | ||
| 407 | @code{setsockopt} (or set to @code{disabled}, in which case the | ||
| 408 | operating-system default is used). | ||
| 409 | |||
| 410 | Note that on GNU/Linux systems, the kernel must be configured to allow | ||
| 411 | processes to use a congestion-control algorithm not in the default set; | ||
| 412 | otherwise, it will deny these requests with ``Operation not permitted''. To | ||
| 413 | see which algorithms are available on your system and which are currently | ||
| 414 | permitted for use, look at the contents of the files | ||
| 415 | @file{tcp_available_congestion_control} and | ||
| 416 | @file{tcp_allowed_congestion_control} in the @file{/proc/sys/net/ipv4} | ||
| 417 | directory. | ||
| 418 | |||
| 419 | As an example, to have Transmission Daemon use | ||
| 420 | @uref{http://www-ece.rice.edu/networks/TCP-LP/, the TCP Low Priority | ||
| 421 | congestion-control algorithm}, you'll need to modify your kernel configuration | ||
| 422 | to build in support for the algorithm, then update your operating-system | ||
| 423 | configuration to allow its use by adding a @code{sysctl-service-type} | ||
| 424 | service (or updating the existing one's configuration) with lines like the | ||
| 425 | following: | ||
| 426 | |||
| 427 | @lisp | ||
| 428 | (service sysctl-service-type | ||
| 429 | (sysctl-configuration | ||
| 430 | (settings | ||
| 431 | (\"net.ipv4.tcp_allowed_congestion_control\" . | ||
| 432 | \"reno cubic lp\")))) | ||
| 433 | @end lisp | ||
| 434 | |||
| 435 | The Transmission Daemon configuration can then be updated with | ||
| 436 | |||
| 437 | @lisp | ||
| 438 | (peer-congestion-algorithm \"lp\") | ||
| 439 | @end lisp | ||
| 440 | |||
| 441 | and the system reconfigured to have the changes take effect.") | ||
| 442 | (peer-socket-tos | ||
| 443 | (tcp-type-of-service 'default) | ||
| 444 | "The type of service to request in outgoing @acronym{TCP} packets, | ||
| 445 | one of @code{default}, @code{low-cost}, @code{throughput}, @code{low-delay} | ||
| 446 | and @code{reliability}.") | ||
| 447 | (peer-limit-global | ||
| 448 | (non-negative-integer 200) | ||
| 449 | "The global limit on the number of connected peers.") | ||
| 450 | (peer-limit-per-torrent | ||
| 451 | (non-negative-integer 50) | ||
| 452 | "The per-torrent limit on the number of connected peers.") | ||
| 453 | (upload-slots-per-torrent | ||
| 454 | (non-negative-integer 14) | ||
| 455 | "The maximum number of peers to which the daemon will upload data | ||
| 456 | simultaneously for each torrent.") | ||
| 457 | (peer-id-ttl-hours | ||
| 458 | (non-negative-integer 6) | ||
| 459 | "The maximum lifespan, in hours, of the peer ID associated with each public | ||
| 460 | torrent before it is regenerated.") | ||
| 461 | |||
| 462 | ;; Peer blocklists. | ||
| 463 | (blocklist-enabled? | ||
| 464 | (boolean #f) | ||
| 465 | "When @code{#t}, the daemon will ignore peers mentioned in the blocklist it | ||
| 466 | has most recently downloaded from @code{blocklist-url}.") | ||
| 467 | (blocklist-url | ||
| 468 | (maybe-string 'disabled) | ||
| 469 | "The URL of a peer blocklist (in @acronym{P2P}-plaintext or eMule | ||
| 470 | @file{.dat} format) to be periodically downloaded and applied when | ||
| 471 | @code{blocklist-enabled?} is @code{#t}.") | ||
| 472 | |||
| 473 | ;; Queueing. | ||
| 474 | (download-queue-enabled? | ||
| 475 | (boolean #t) | ||
| 476 | "If @code{#t}, the daemon will be limited to downloading at most | ||
| 477 | @code{download-queue-size} non-stalled torrents simultaneously.") | ||
| 478 | (download-queue-size | ||
| 479 | (non-negative-integer 5) | ||
| 480 | "The size of the daemon's download queue, which limits the number of | ||
| 481 | non-stalled torrents it will download at any one time when | ||
| 482 | @code{download-queue-enabled?} is @code{#t}.") | ||
| 483 | (seed-queue-enabled? | ||
| 484 | (boolean #f) | ||
| 485 | "If @code{#t}, the daemon will be limited to seeding at most | ||
| 486 | @code{seed-queue-size} non-stalled torrents simultaneously.") | ||
| 487 | (seed-queue-size | ||
| 488 | (non-negative-integer 10) | ||
| 489 | "The size of the daemon's seed queue, which limits the number of | ||
| 490 | non-stalled torrents it will seed at any one time when | ||
| 491 | @code{seed-queue-enabled?} is @code{#t}.") | ||
| 492 | (queue-stalled-enabled? | ||
| 493 | (boolean #t) | ||
| 494 | "When @code{#t}, the daemon will consider torrents for which it has not | ||
| 495 | shared data in the past @code{queue-stalled-minutes} minutes to be stalled and | ||
| 496 | not count them against its @code{download-queue-size} and | ||
| 497 | @code{seed-queue-size} limits.") | ||
| 498 | (queue-stalled-minutes | ||
| 499 | (non-negative-integer 30) | ||
| 500 | "The maximum period, in minutes, a torrent may be idle before it is | ||
| 501 | considered to be stalled, when @code{queue-stalled-enabled?} is @code{#t}.") | ||
| 502 | |||
| 503 | ;; Seeding limits. | ||
| 504 | (ratio-limit-enabled? | ||
| 505 | (boolean #f) | ||
| 506 | "When @code{#t}, a torrent being seeded will automatically be paused once | ||
| 507 | it reaches the ratio specified by @code{ratio-limit}.") | ||
| 508 | (ratio-limit | ||
| 509 | (non-negative-rational 2.0) | ||
| 510 | "The ratio at which a torrent being seeded will be paused, when | ||
| 511 | @code{ratio-limit-enabled?} is @code{#t}.") | ||
| 512 | (idle-seeding-limit-enabled? | ||
| 513 | (boolean #f) | ||
| 514 | "When @code{#t}, a torrent being seeded will automatically be paused once | ||
| 515 | it has been idle for @code{idle-seeding-limit} minutes.") | ||
| 516 | (idle-seeding-limit | ||
| 517 | (non-negative-integer 30) | ||
| 518 | "The maximum period, in minutes, a torrent being seeded may be idle before | ||
| 519 | it is paused, when @code{idle-seeding-limit-enabled?} is @code{#t}.") | ||
| 520 | |||
| 521 | ;; BitTorrent extensions. | ||
| 522 | (dht-enabled? | ||
| 523 | (boolean #t) | ||
| 524 | "Enable @uref{http://bittorrent.org/beps/bep_0005.html, the distributed | ||
| 525 | hash table (@acronym{DHT}) protocol}, which supports the use of trackerless | ||
| 526 | torrents.") | ||
| 527 | (lpd-enabled? | ||
| 528 | (boolean #f) | ||
| 529 | "Enable @url{https://en.wikipedia.org/wiki/Local_Peer_Discovery, local peer | ||
| 530 | discovery} (@acronym{LPD}), which allows the discovery of peers on the local | ||
| 531 | network and may reduce the amount of data sent over the public Internet.") | ||
| 532 | (pex-enabled? | ||
| 533 | (boolean #t) | ||
| 534 | "Enable @url{https://en.wikipedia.org/wiki/Peer_exchange, peer | ||
| 535 | exchange} (@acronym{PEX}), which reduces the daemon's reliance on external | ||
| 536 | trackers and may improve its performance.") | ||
| 537 | (utp-enabled? | ||
| 538 | (boolean #t) | ||
| 539 | "Enable @url{http://bittorrent.org/beps/bep_0029.html, the micro transport | ||
| 540 | protocol} (@acronym{uTP}), which aims to reduce the impact of BitTorrent | ||
| 541 | traffic on other users of the local network while maintaining full utilization | ||
| 542 | of the available bandwidth.") | ||
| 543 | |||
| 544 | ;; Remote procedure call (RPC) interface. | ||
| 545 | (rpc-enabled? | ||
| 546 | (boolean #t) | ||
| 547 | "If @code{#t}, enable the remote procedure call (@acronym{RPC}) interface, | ||
| 548 | which allows remote control of the daemon via its Web interface, the | ||
| 549 | @command{transmission-remote} command-line client, and similar tools.") | ||
| 550 | (rpc-bind-address | ||
| 551 | (string "0.0.0.0") | ||
| 552 | "The IP address at which to listen for @acronym{RPC} connections, or | ||
| 553 | ``0.0.0.0'' to listen at all available IP addresses.") | ||
| 554 | (rpc-port | ||
| 555 | (port-number 9091) | ||
| 556 | "The port on which to listen for @acronym{RPC} connections.") | ||
| 557 | (rpc-url | ||
| 558 | (string "/transmission/") | ||
| 559 | "The path prefix to use in the @acronym{RPC}-endpoint @acronym{URL}.") | ||
| 560 | (rpc-authentication-required? | ||
| 561 | (boolean #f) | ||
| 562 | "When @code{#t}, clients must authenticate (see @code{rpc-username} and | ||
| 563 | @code{rpc-password}) when using the @acronym{RPC} interface. Note this has | ||
| 564 | the side effect of disabling host-name whitelisting (see | ||
| 565 | @code{rpc-host-whitelist-enabled?}.") | ||
| 566 | (rpc-username | ||
| 567 | (maybe-string 'disabled) | ||
| 568 | "The username required by clients to access the @acronym{RPC} interface | ||
| 569 | when @code{rpc-authentication-required?} is @code{#t}.") | ||
| 570 | (rpc-password | ||
| 571 | (maybe-transmission-password-hash 'disabled) | ||
| 572 | "The password required by clients to access the @acronym{RPC} interface | ||
| 573 | when @code{rpc-authentication-required?} is @code{#t}. This must be specified | ||
| 574 | using a password hash in the format recognized by Transmission clients, either | ||
| 575 | copied from an existing @file{settings.json} file or generated using the | ||
| 576 | @code{transmission-password-hash} procedure.") | ||
| 577 | (rpc-whitelist-enabled? | ||
| 578 | (boolean #t) | ||
| 579 | "When @code{#t}, @acronym{RPC} requests will be accepted only when they | ||
| 580 | originate from an address specified in @code{rpc-whitelist}.") | ||
| 581 | (rpc-whitelist | ||
| 582 | (string-list '("127.0.0.1" "::1")) | ||
| 583 | "The list of IP and IPv6 addresses from which @acronym{RPC} requests will | ||
| 584 | be accepted when @code{rpc-whitelist-enabled?} is @code{#t}. Wildcards may be | ||
| 585 | specified using @samp{*}.") | ||
| 586 | (rpc-host-whitelist-enabled? | ||
| 587 | (boolean #t) | ||
| 588 | "When @code{#t}, @acronym{RPC} requests will be accepted only when they are | ||
| 589 | addressed to a host named in @code{rpc-host-whitelist}. Note that requests to | ||
| 590 | ``localhost'' or ``localhost.'', or to a numeric address, are always accepted | ||
| 591 | regardless of these settings. | ||
| 592 | |||
| 593 | Note also this functionality is disabled when | ||
| 594 | @code{rpc-authentication-required?} is @code{#t}.") | ||
| 595 | (rpc-host-whitelist | ||
| 596 | (string-list '()) | ||
| 597 | "The list of host names recognized by the @acronym{RPC} server when | ||
| 598 | @code{rpc-host-whitelist-enabled?} is @code{#t}.") | ||
| 599 | |||
| 600 | ;; Miscellaneous. | ||
| 601 | (message-level | ||
| 602 | (message-level 'info) | ||
| 603 | "The minimum severity level of messages to be logged (to | ||
| 604 | @file{/var/log/transmission.log}) by the daemon, one of @code{none} (no | ||
| 605 | logging), @code{error}, @code{info} and @code{debug}.") | ||
| 606 | (start-added-torrents? | ||
| 607 | (boolean #t) | ||
| 608 | "When @code{#t}, torrents are started as soon as they are added; otherwise, | ||
| 609 | they are added in ``paused'' state.") | ||
| 610 | (script-torrent-done-enabled? | ||
| 611 | (boolean #f) | ||
| 612 | "When @code{#t}, the script specified by | ||
| 613 | @code{script-torrent-done-filename} will be invoked each time a torrent | ||
| 614 | completes.") | ||
| 615 | (script-torrent-done-filename | ||
| 616 | (maybe-file-object 'disabled) | ||
| 617 | "A file name or file-like object specifying a script to run each time a | ||
| 618 | torrent completes, when @code{script-torrent-done-enabled?} is @code{#t}.") | ||
| 619 | (scrape-paused-torrents-enabled? | ||
| 620 | (boolean #t) | ||
| 621 | "When @code{#t}, the daemon will scrape trackers for a torrent even when | ||
| 622 | the torrent is paused.") | ||
| 623 | (cache-size-mb | ||
| 624 | (non-negative-integer 4) | ||
| 625 | "The amount of memory, in megabytes, to allocate for the daemon's in-memory | ||
| 626 | cache. A larger value may increase performance by reducing the frequency of | ||
| 627 | disk I/O.") | ||
| 628 | (prefetch-enabled? | ||
| 629 | (boolean #t) | ||
| 630 | "When @code{#t}, the daemon will try to improve I/O performance by hinting | ||
| 631 | to the operating system which data is likely to be read next from disk to | ||
| 632 | satisfy requests from peers.")) | ||
| 633 | |||
| 634 | (define (transmission-daemon-shepherd-service config) | ||
| 635 | "Return a <shepherd-service> for Transmission Daemon with CONFIG." | ||
| 636 | (let ((transmission | ||
| 637 | (transmission-daemon-configuration-transmission config)) | ||
| 638 | (stop-wait-period | ||
| 639 | (transmission-daemon-configuration-stop-wait-period config))) | ||
| 640 | (list | ||
| 641 | (shepherd-service | ||
| 642 | (provision '(transmission-daemon transmission bittorrent)) | ||
| 643 | (requirement '(networking)) | ||
| 644 | (documentation "Share files using the BitTorrent protocol.") | ||
| 645 | (start #~(make-forkexec-constructor | ||
| 646 | '(#$(file-append transmission "/bin/transmission-daemon") | ||
| 647 | "--config-dir" | ||
| 648 | #$%transmission-daemon-configuration-directory | ||
| 649 | "--foreground") | ||
| 650 | #:user #$%transmission-daemon-user | ||
| 651 | #:group #$%transmission-daemon-group | ||
| 652 | #:directory #$%transmission-daemon-configuration-directory | ||
| 653 | #:log-file #$%transmission-daemon-log-file | ||
| 654 | #:environment-variables | ||
| 655 | '("CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt"))) | ||
| 656 | (stop #~(lambda (pid) | ||
| 657 | (kill pid SIGTERM) | ||
| 658 | |||
| 659 | ;; Transmission Daemon normally needs some time to shut down, | ||
| 660 | ;; as it will complete some housekeeping and send a final | ||
| 661 | ;; update to trackers before it exits. | ||
| 662 | ;; | ||
| 663 | ;; Wait a reasonable period for it to stop before continuing. | ||
| 664 | ;; If we don't do this, restarting the service can fail as the | ||
| 665 | ;; new daemon process finds the old one still running and | ||
| 666 | ;; attached to the port used for peer connections. | ||
| 667 | (let wait-before-killing ((period #$stop-wait-period)) | ||
| 668 | (if (zero? (car (waitpid pid WNOHANG))) | ||
| 669 | (if (positive? period) | ||
| 670 | (begin | ||
| 671 | (sleep 1) | ||
| 672 | (wait-before-killing (- period 1))) | ||
| 673 | (begin | ||
| 674 | (format #t | ||
| 675 | #$(G_ "Wait period expired; killing \ | ||
| 676 | transmission-daemon (pid ~a).~%") | ||
| 677 | pid) | ||
| 678 | (display #$(G_ "(If you see this message \ | ||
| 679 | regularly, you may need to increase the value | ||
| 680 | of 'stop-wait-period' in the service configuration.)\n")) | ||
| 681 | (kill pid SIGKILL))))) | ||
| 682 | #f)) | ||
| 683 | (actions | ||
| 684 | (list | ||
| 685 | (shepherd-action | ||
| 686 | (name 'reload) | ||
| 687 | (documentation "Reload the settings file from disk.") | ||
| 688 | (procedure #~(lambda (pid) | ||
| 689 | (if pid | ||
| 690 | (begin | ||
| 691 | (kill pid SIGHUP) | ||
| 692 | (display #$(G_ "Service transmission-daemon has \ | ||
| 693 | been asked to reload its settings file."))) | ||
| 694 | (display #$(G_ "Service transmission-daemon is not \ | ||
| 695 | running.")))))))))))) | ||
| 696 | |||
| 697 | (define %transmission-daemon-accounts | ||
| 698 | (list (user-group | ||
| 699 | (name %transmission-daemon-group) | ||
| 700 | (system? #t)) | ||
| 701 | (user-account | ||
| 702 | (name %transmission-daemon-user) | ||
| 703 | (group %transmission-daemon-group) | ||
| 704 | (comment "Transmission Daemon service account") | ||
| 705 | (home-directory %transmission-daemon-configuration-directory) | ||
| 706 | (shell (file-append shadow "/sbin/nologin")) | ||
| 707 | (system? #t)))) | ||
| 708 | |||
| 709 | (define %transmission-daemon-log-rotations | ||
| 710 | (list (log-rotation | ||
| 711 | (files (list %transmission-daemon-log-file))))) | ||
| 712 | |||
| 713 | (define (transmission-daemon-computed-settings-file config) | ||
| 714 | "Return a @code{computed-file} object that, when unquoted in a G-expression, | ||
| 715 | produces a Transmission settings file (@file{settings.json}) matching CONFIG." | ||
| 716 | (let ((settings | ||
| 717 | ;; "Serialize" the configuration settings as a list of G-expressions | ||
| 718 | ;; containing a name-value pair, which will ultimately be sorted and | ||
| 719 | ;; serialized to the settings file as a JSON object. | ||
| 720 | (map | ||
| 721 | (lambda (field) | ||
| 722 | ((configuration-field-serializer field) | ||
| 723 | (configuration-field-name field) | ||
| 724 | ((configuration-field-getter field) config))) | ||
| 725 | (filter | ||
| 726 | (lambda (field) | ||
| 727 | ;; Omit configuration fields that are used only internally by | ||
| 728 | ;; this service definition. | ||
| 729 | (not (memq (configuration-field-name field) | ||
| 730 | '(transmission stop-wait-period)))) | ||
| 731 | transmission-daemon-configuration-fields)))) | ||
| 732 | (computed-file | ||
| 733 | "settings.json" | ||
| 734 | (with-extensions (list guile-gcrypt guile-json-4) | ||
| 735 | (with-imported-modules (source-module-closure '((json builder))) | ||
| 736 | #~(begin | ||
| 737 | (use-modules (json builder)) | ||
| 738 | |||
| 739 | (with-output-to-file #$output | ||
| 740 | (lambda () | ||
| 741 | (scm->json (sort-list '(#$@settings) | ||
| 742 | (lambda (x y) | ||
| 743 | (string<=? (car x) (car y)))) | ||
| 744 | #:pretty #t))))))))) | ||
| 745 | |||
| 746 | (define (transmission-daemon-activation config) | ||
| 747 | "Return the Transmission Daemon activation GEXP for CONFIG." | ||
| 748 | (let ((config-dir %transmission-daemon-configuration-directory) | ||
| 749 | (incomplete-dir-enabled | ||
| 750 | (transmission-daemon-configuration-incomplete-dir-enabled? config)) | ||
| 751 | (incomplete-dir | ||
| 752 | (transmission-daemon-configuration-incomplete-dir config)) | ||
| 753 | (watch-dir-enabled | ||
| 754 | (transmission-daemon-configuration-watch-dir-enabled? config)) | ||
| 755 | (watch-dir | ||
| 756 | (transmission-daemon-configuration-watch-dir config))) | ||
| 757 | (with-imported-modules (source-module-closure '((guix build utils))) | ||
| 758 | #~(begin | ||
| 759 | (use-modules (guix build utils)) | ||
| 760 | |||
| 761 | (let ((owner (getpwnam #$%transmission-daemon-user))) | ||
| 762 | (define (mkdir-p/perms directory perms) | ||
| 763 | (mkdir-p directory) | ||
| 764 | (chown directory (passwd:uid owner) (passwd:gid owner)) | ||
| 765 | (chmod directory perms)) | ||
| 766 | |||
| 767 | ;; Create the directories Transmission Daemon is configured to use | ||
| 768 | ;; and assign them suitable permissions. | ||
| 769 | (for-each (lambda (directory-specification) | ||
| 770 | (apply mkdir-p/perms directory-specification)) | ||
| 771 | '(#$@(append | ||
| 772 | `((,config-dir #o750)) | ||
| 773 | (if incomplete-dir-enabled | ||
| 774 | `((,incomplete-dir #o750)) | ||
| 775 | '()) | ||
| 776 | (if watch-dir-enabled | ||
| 777 | `((,watch-dir #o770)) | ||
| 778 | '()))))) | ||
| 779 | |||
| 780 | ;; Generate and activate the daemon's settings file, settings.json. | ||
| 781 | (activate-special-files | ||
| 782 | '((#$(string-append config-dir "/settings.json") | ||
| 783 | #$(transmission-daemon-computed-settings-file config)))))))) | ||
| 784 | |||
| 785 | (define transmission-daemon-service-type | ||
| 786 | (service-type | ||
| 787 | (name 'transmission) | ||
| 788 | (extensions | ||
| 789 | (list (service-extension shepherd-root-service-type | ||
| 790 | transmission-daemon-shepherd-service) | ||
| 791 | (service-extension account-service-type | ||
| 792 | (const %transmission-daemon-accounts)) | ||
| 793 | (service-extension rottlog-service-type | ||
| 794 | (const %transmission-daemon-log-rotations)) | ||
| 795 | (service-extension activation-service-type | ||
| 796 | transmission-daemon-activation))) | ||
| 797 | (default-value (transmission-daemon-configuration)) | ||
| 798 | (description "Share files using the BitTorrent protocol."))) | ||
| 799 | |||
| 800 | (define (generate-transmission-daemon-documentation) | ||
| 801 | (generate-documentation | ||
| 802 | `((transmission-daemon-configuration | ||
| 803 | ,transmission-daemon-configuration-fields)) | ||
| 804 | 'transmission-daemon-configuration)) | ||
diff --git a/po/packages/POTFILES.in b/po/packages/POTFILES.in index 9a178edfa63..398f9adfdfc 100644 --- a/po/packages/POTFILES.in +++ b/po/packages/POTFILES.in | |||
| @@ -59,5 +59,6 @@ gnu/packages/wordnet.scm | |||
| 59 | gnu/packages/xiph.scm | 59 | gnu/packages/xiph.scm |
| 60 | gnu/services/base.scm | 60 | gnu/services/base.scm |
| 61 | gnu/services/certbot.scm | 61 | gnu/services/certbot.scm |
| 62 | gnu/services/file-sharing.scm | ||
| 62 | gnu/services/networking.scm | 63 | gnu/services/networking.scm |
| 63 | gnu/services/version-control.scm | 64 | gnu/services/version-control.scm |
diff --git a/tests/services/file-sharing.scm b/tests/services/file-sharing.scm new file mode 100644 index 00000000000..27bec57325f --- /dev/null +++ b/tests/services/file-sharing.scm | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2020 Simon South <simon@simonsouth.net> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (tests services file-sharing) | ||
| 20 | #:use-module (gnu services file-sharing) | ||
| 21 | #:use-module (srfi srfi-64)) | ||
| 22 | |||
| 23 | ;;; Tests for the (gnu services file-sharing) module. | ||
| 24 | |||
| 25 | (test-begin "file-sharing") | ||
| 26 | |||
| 27 | |||
| 28 | ;;; | ||
| 29 | ;;; Transmission Daemon. | ||
| 30 | ;;; | ||
| 31 | |||
| 32 | (define %transmission-salt-length 8) | ||
| 33 | |||
| 34 | (define (valid-transmission-salt? salt) | ||
| 35 | (and (string? salt) | ||
| 36 | (eqv? (string-length salt) %transmission-salt-length))) | ||
| 37 | |||
| 38 | (test-assert "transmission-random-salt" | ||
| 39 | (valid-transmission-salt? (transmission-random-salt))) | ||
| 40 | |||
| 41 | (test-equal "transmission-password-hash, typical values" | ||
| 42 | "{ef6fba106cdef3aac64d1410090cae353cbecde53ceVVQO2" | ||
| 43 | (transmission-password-hash "transmission" "3ceVVQO2")) | ||
| 44 | |||
| 45 | (test-equal "transmission-password-hash, empty password" | ||
| 46 | "{820f816515d8969d058d07a1de018650619ee7ffCp.I5SWg" | ||
| 47 | (transmission-password-hash "" "Cp.I5SWg")) | ||
| 48 | |||
| 49 | (test-error "transmission-password-hash, salt value too short" | ||
| 50 | (transmission-password-hash | ||
| 51 | "transmission" | ||
| 52 | (make-string (- %transmission-salt-length 1) #\a))) | ||
| 53 | |||
| 54 | (test-error "transmission-password-hash, salt value too long" | ||
| 55 | (transmission-password-hash | ||
| 56 | "transmission" | ||
| 57 | (make-string (+ %transmission-salt-length 1) #\a))) | ||
| 58 | |||
| 59 | (test-end "file-sharing") | ||
