mirror of
https://git.in.rschanz.org/ryan77627/guix.git
synced 2024-12-24 21:38:07 -05:00
services: rsync: Allow configuring several rsync "modules".
Until now the rsync service would export a single module, named "files". This allows users to specify as many modules as they want, in line with rsyncd.conf(5). * gnu/services/rsync.scm (warn-share-field-deprecation): New procedure. (<rsync-configuration>)[modules]: New field. [share-path, share-comment, read-only?, timeout]: Mark as deprecated. (<rsync-module>): New record type. (%default-modules): New variable. (rsync-configuration-modules): New procedure. (rsync-activation): Create the directory of each module. (rsync-config-file): Generate configuration for each module. (rsync-service-type)[description]: New field. * doc/guix.texi (Networking Services): Adjust documentation. Augment example.
This commit is contained in:
parent
9834ff5d32
commit
c9d92409d4
2 changed files with 174 additions and 67 deletions
|
@ -18059,7 +18059,17 @@ The value for this service type is a
|
||||||
@command{rsync-configuration} record as in this example:
|
@command{rsync-configuration} record as in this example:
|
||||||
|
|
||||||
@lisp
|
@lisp
|
||||||
(service rsync-service-type)
|
;; Export two directories over rsync. By default rsync listens on
|
||||||
|
;; all the network interfaces.
|
||||||
|
(service rsync-service-type
|
||||||
|
(rsync-configuration
|
||||||
|
(modules (list (rsync-module
|
||||||
|
(name "music")
|
||||||
|
(file-name "/srv/zik")
|
||||||
|
(read-only? #f))
|
||||||
|
(rsync-module
|
||||||
|
(name "movies")
|
||||||
|
(file-name "/home/charlie/movies"))))))
|
||||||
@end lisp
|
@end lisp
|
||||||
|
|
||||||
See below for details about @code{rsync-configuration}.
|
See below for details about @code{rsync-configuration}.
|
||||||
|
@ -18090,34 +18100,55 @@ Name of the file where @command{rsync} writes its lock file.
|
||||||
@item @code{log-file} (default: @code{"/var/log/rsyncd.log"})
|
@item @code{log-file} (default: @code{"/var/log/rsyncd.log"})
|
||||||
Name of the file where @command{rsync} writes its log file.
|
Name of the file where @command{rsync} writes its log file.
|
||||||
|
|
||||||
@item @code{use-chroot?} (default: @var{#t})
|
@item @code{user} (default: @code{"root"})
|
||||||
Whether to use chroot for @command{rsync} shared directory.
|
|
||||||
|
|
||||||
@item @code{share-path} (default: @file{/srv/rsync})
|
|
||||||
Location of the @command{rsync} shared directory.
|
|
||||||
|
|
||||||
@item @code{share-comment} (default: @code{"Rsync share"})
|
|
||||||
Comment of the @command{rsync} shared directory.
|
|
||||||
|
|
||||||
@item @code{read-only?} (default: @var{#f})
|
|
||||||
Read-write permissions to shared directory.
|
|
||||||
|
|
||||||
@item @code{timeout} (default: @code{300})
|
|
||||||
I/O timeout in seconds.
|
|
||||||
|
|
||||||
@item @code{user} (default: @var{"root"})
|
|
||||||
Owner of the @code{rsync} process.
|
Owner of the @code{rsync} process.
|
||||||
|
|
||||||
@item @code{group} (default: @var{"root"})
|
@item @code{group} (default: @code{"root"})
|
||||||
Group of the @code{rsync} process.
|
Group of the @code{rsync} process.
|
||||||
|
|
||||||
@item @code{uid} (default: @var{"rsyncd"})
|
@item @code{uid} (default: @code{"rsyncd"})
|
||||||
User name or user ID that file transfers to and from that module should take
|
User name or user ID that file transfers to and from that module should take
|
||||||
place as when the daemon was run as @code{root}.
|
place as when the daemon was run as @code{root}.
|
||||||
|
|
||||||
@item @code{gid} (default: @var{"rsyncd"})
|
@item @code{gid} (default: @code{"rsyncd"})
|
||||||
Group name or group ID that will be used when accessing the module.
|
Group name or group ID that will be used when accessing the module.
|
||||||
|
|
||||||
|
@item @code{modules} (default: @code{%default-modules})
|
||||||
|
List of ``modules''---i.e., directories exported over rsync. Each
|
||||||
|
element must be a @code{rsync-module} record, as described below.
|
||||||
|
@end table
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
@deftp {Data Type} rsync-module
|
||||||
|
This is the data type for rsync ``modules''. A module is a directory
|
||||||
|
exported over the rsync protocol. The available fields are as follows:
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
@item @code{name}
|
||||||
|
The module name. This is the name that shows up in URLs. For example,
|
||||||
|
if the module is called @code{music}, the corresponding URL will be
|
||||||
|
@code{rsync://host.example.org/music}.
|
||||||
|
|
||||||
|
@item @code{file-name}
|
||||||
|
Name of the directory being exported.
|
||||||
|
|
||||||
|
@item @code{comment} (default: @code{""})
|
||||||
|
Comment associated with the module. Client user interfaces may display
|
||||||
|
it when they obtain the list of available modules.
|
||||||
|
|
||||||
|
@item @code{read-only?} (default: @code{#t})
|
||||||
|
Whether or not client will be able to upload files. If this is false,
|
||||||
|
the uploads will be authorized if permissions on the daemon side permit
|
||||||
|
it.
|
||||||
|
|
||||||
|
@item @code{chroot?} (default: @code{#t})
|
||||||
|
When this is true, the rsync daemon changes root to the module's
|
||||||
|
directory before starting file transfers with the client. This improves
|
||||||
|
security, but requires rsync to run as root.
|
||||||
|
|
||||||
|
@item @code{timeout} (default: @code{300})
|
||||||
|
Idle time in seconds after which the daemon closes a connection with the
|
||||||
|
client.
|
||||||
@end table
|
@end table
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
;;; GNU Guix --- Functional package management for GNU
|
;;; GNU Guix --- Functional package management for GNU
|
||||||
;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com>
|
;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com>
|
||||||
|
;;; Copyright © 2021 Ludovic Courtès <ludo@gnu.org>
|
||||||
;;;
|
;;;
|
||||||
;;; This file is part of GNU Guix.
|
;;; This file is part of GNU Guix.
|
||||||
;;;
|
;;;
|
||||||
|
@ -25,11 +26,23 @@ (define-module (gnu services rsync)
|
||||||
#:use-module (gnu packages admin)
|
#:use-module (gnu packages admin)
|
||||||
#:use-module (guix records)
|
#:use-module (guix records)
|
||||||
#:use-module (guix gexp)
|
#:use-module (guix gexp)
|
||||||
|
#:use-module (guix diagnostics)
|
||||||
|
#:use-module (guix i18n)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:export (rsync-configuration
|
#:export (rsync-configuration
|
||||||
rsync-configuration?
|
rsync-configuration?
|
||||||
|
rsync-configuration-modules
|
||||||
|
|
||||||
|
rsync-module
|
||||||
|
rsync-module?
|
||||||
|
rsync-module-name
|
||||||
|
rsync-module-file-name
|
||||||
|
rsync-module-comment
|
||||||
|
rsync-module-read-only
|
||||||
|
rsync-module-timeout
|
||||||
|
|
||||||
rsync-service-type))
|
rsync-service-type))
|
||||||
|
|
||||||
;;;; Commentary:
|
;;;; Commentary:
|
||||||
|
@ -39,6 +52,13 @@ (define-module (gnu services rsync)
|
||||||
;;;
|
;;;
|
||||||
;;;; Code:
|
;;;; Code:
|
||||||
|
|
||||||
|
(define-with-syntax-properties (warn-share-field-deprecation (value properties))
|
||||||
|
(unless (unspecified? value)
|
||||||
|
(warning (source-properties->location properties)
|
||||||
|
(G_ "the 'share-path' and 'share-comment' fields is deprecated, \
|
||||||
|
please use 'modules' instead~%")))
|
||||||
|
value)
|
||||||
|
|
||||||
(define-record-type* <rsync-configuration>
|
(define-record-type* <rsync-configuration>
|
||||||
rsync-configuration
|
rsync-configuration
|
||||||
make-rsync-configuration
|
make-rsync-configuration
|
||||||
|
@ -56,15 +76,22 @@ (define-record-type* <rsync-configuration>
|
||||||
(log-file rsync-configuration-log-file ; string
|
(log-file rsync-configuration-log-file ; string
|
||||||
(default "/var/log/rsyncd.log"))
|
(default "/var/log/rsyncd.log"))
|
||||||
(use-chroot? rsync-configuration-use-chroot? ; boolean
|
(use-chroot? rsync-configuration-use-chroot? ; boolean
|
||||||
(default #t))
|
(sanitize warn-share-field-deprecation)
|
||||||
|
(default *unspecified*))
|
||||||
|
(modules rsync-configuration-actual-modules ;list of <rsync-module>
|
||||||
|
(default %default-modules)) ;TODO: eventually remove default
|
||||||
(share-path rsync-configuration-share-path ; string
|
(share-path rsync-configuration-share-path ; string
|
||||||
(default "/srv/rsyncd"))
|
(sanitize warn-share-field-deprecation)
|
||||||
|
(default *unspecified*))
|
||||||
(share-comment rsync-configuration-share-comment ; string
|
(share-comment rsync-configuration-share-comment ; string
|
||||||
(default "Rsync share"))
|
(sanitize warn-share-field-deprecation)
|
||||||
|
(default *unspecified*))
|
||||||
(read-only? rsync-configuration-read-only? ; boolean
|
(read-only? rsync-configuration-read-only? ; boolean
|
||||||
(default #f))
|
(sanitize warn-share-field-deprecation)
|
||||||
|
(default *unspecified*))
|
||||||
(timeout rsync-configuration-timeout ; integer
|
(timeout rsync-configuration-timeout ; integer
|
||||||
(default 300))
|
(sanitize warn-share-field-deprecation)
|
||||||
|
(default *unspecified*))
|
||||||
(user rsync-configuration-user ; string
|
(user rsync-configuration-user ; string
|
||||||
(default "root"))
|
(default "root"))
|
||||||
(group rsync-configuration-group ; string
|
(group rsync-configuration-group ; string
|
||||||
|
@ -74,6 +101,45 @@ (define-record-type* <rsync-configuration>
|
||||||
(gid rsync-configuration-gid ; string
|
(gid rsync-configuration-gid ; string
|
||||||
(default "rsyncd")))
|
(default "rsyncd")))
|
||||||
|
|
||||||
|
;; Rsync "module": a directory exported the rsync protocol.
|
||||||
|
(define-record-type* <rsync-module>
|
||||||
|
rsync-module make-rsync-module
|
||||||
|
rsync-module?
|
||||||
|
(name rsync-module-name) ;string
|
||||||
|
(file-name rsync-module-file-name) ;string
|
||||||
|
(comment rsync-module-comment ;string
|
||||||
|
(default ""))
|
||||||
|
(read-only? rsync-module-read-only? ;boolean
|
||||||
|
(default #t))
|
||||||
|
(chroot? rsync-module-chroot? ;boolean
|
||||||
|
(default #t))
|
||||||
|
(timeout rsync-module-timeout ;integer
|
||||||
|
(default 300)))
|
||||||
|
|
||||||
|
(define %default-modules
|
||||||
|
;; Default modules, provided for backward compatibility.
|
||||||
|
(list (rsync-module (name "files")
|
||||||
|
(file-name "/srv/rsyncd")
|
||||||
|
(comment "Rsync share")
|
||||||
|
(read-only? #f)))) ;yes, that was the default
|
||||||
|
|
||||||
|
(define (rsync-configuration-modules config)
|
||||||
|
(match-record config <rsync-configuration>
|
||||||
|
(modules
|
||||||
|
share-path share-comment use-chroot? read-only? timeout) ;deprecated
|
||||||
|
(if (unspecified? share-path)
|
||||||
|
(rsync-configuration-actual-modules config)
|
||||||
|
(list (rsync-module ;backward compatibility
|
||||||
|
(name "files")
|
||||||
|
(file-name share-path)
|
||||||
|
(comment "Rsync share")
|
||||||
|
(chroot?
|
||||||
|
(if (unspecified? use-chroot?) #t use-chroot?))
|
||||||
|
(read-only?
|
||||||
|
(if (unspecified? read-only?) #f read-only?))
|
||||||
|
(timeout
|
||||||
|
(if (unspecified? timeout) 300 timeout)))))))
|
||||||
|
|
||||||
(define (rsync-account config)
|
(define (rsync-account config)
|
||||||
"Return the user accounts and user groups for CONFIG."
|
"Return the user accounts and user groups for CONFIG."
|
||||||
(let ((rsync-user (if (rsync-configuration-uid config)
|
(let ((rsync-user (if (rsync-configuration-uid config)
|
||||||
|
@ -96,55 +162,62 @@ (define (rsync-activation config)
|
||||||
"Return the activation GEXP for CONFIG."
|
"Return the activation GEXP for CONFIG."
|
||||||
(with-imported-modules '((guix build utils))
|
(with-imported-modules '((guix build utils))
|
||||||
#~(begin
|
#~(begin
|
||||||
(let ((share-directory #$(rsync-configuration-share-path config))
|
(let ((user (getpw (if #$(rsync-configuration-uid config)
|
||||||
(user (getpw (if #$(rsync-configuration-uid config)
|
|
||||||
#$(rsync-configuration-uid config)
|
#$(rsync-configuration-uid config)
|
||||||
#$(rsync-configuration-user config))))
|
#$(rsync-configuration-user config))))
|
||||||
(group (getpw (if #$(rsync-configuration-gid config)
|
(group (getpw (if #$(rsync-configuration-gid config)
|
||||||
#$(rsync-configuration-gid config)
|
#$(rsync-configuration-gid config)
|
||||||
#$(rsync-configuration-group config)))))
|
#$(rsync-configuration-group config)))))
|
||||||
(mkdir-p (dirname #$(rsync-configuration-pid-file config)))
|
(mkdir-p (dirname #$(rsync-configuration-pid-file config)))
|
||||||
(and=> share-directory mkdir-p)
|
(for-each (lambda (directory)
|
||||||
(chown share-directory
|
(mkdir-p directory)
|
||||||
(passwd:uid user)
|
(chown directory (passwd:uid user) (group:gid group)))
|
||||||
(group:gid group))))))
|
'#$(map rsync-module-file-name
|
||||||
|
(rsync-configuration-modules config)))))))
|
||||||
|
|
||||||
(define rsync-config-file
|
(define (rsync-config-file config)
|
||||||
;; Return the rsync configuration file corresponding to CONFIG.
|
;; Return the rsync configuration file corresponding to CONFIG.
|
||||||
(match-lambda
|
(define (module-config module)
|
||||||
(($ <rsync-configuration> package address port-number pid-file lock-file log-file
|
(match-record module <rsync-module>
|
||||||
use-chroot? share-path share-comment read-only?
|
(name file-name comment chroot? read-only? timeout)
|
||||||
timeout user group uid gid)
|
(list "[" name "]\n"
|
||||||
(if (not (string=? user "root"))
|
" path = " file-name "\n"
|
||||||
(cond
|
" use chroot = " (if chroot? "true" "false") "\n"
|
||||||
((<= port-number 1024)
|
" comment = " comment "\n"
|
||||||
(error (string-append "rsync-service: to run on port "
|
" read only = " (if read-only? "true" "false") "\n"
|
||||||
(number->string port-number)
|
" timeout = " (number->string timeout) "\n")))
|
||||||
", user must be root.")))
|
|
||||||
(use-chroot?
|
(define modules
|
||||||
(error (string-append "rsync-service: to run in a chroot"
|
(rsync-configuration-modules config))
|
||||||
", user must be root.")))
|
|
||||||
(uid
|
(match-record config <rsync-configuration>
|
||||||
(error "rsync-service: to use uid, user must be root."))
|
(package address port-number pid-file lock-file log-file
|
||||||
(gid
|
user group uid gid)
|
||||||
(error "rsync-service: to use gid, user must be root."))))
|
(unless (string=? user "root")
|
||||||
(mixed-text-file
|
(cond
|
||||||
"rsync.conf"
|
((<= port-number 1024)
|
||||||
"# Generated by 'rsync-service'.\n\n"
|
(error (string-append "rsync-service: to run on port "
|
||||||
"pid file = " pid-file "\n"
|
(number->string port-number)
|
||||||
"lock file = " lock-file "\n"
|
", user must be root.")))
|
||||||
"log file = " log-file "\n"
|
((find rsync-module-chroot? modules)
|
||||||
(if address (string-append "address = " address "\n") "")
|
(error (string-append "rsync-service: to run in a chroot"
|
||||||
"port = " (number->string port-number) "\n"
|
", user must be root.")))
|
||||||
"use chroot = " (if use-chroot? "true" "false") "\n"
|
(uid
|
||||||
(if uid (string-append "uid = " uid "\n") "")
|
(error "rsync-service: to use uid, user must be root."))
|
||||||
"gid = " (if gid gid "nogroup") "\n" ; no group nobody
|
(gid
|
||||||
"\n"
|
(error "rsync-service: to use gid, user must be root."))))
|
||||||
"[files]\n"
|
|
||||||
"path = " share-path "\n"
|
(apply mixed-text-file "rsync.conf"
|
||||||
"comment = " share-comment "\n"
|
"# Generated by 'rsync-service'.\n\n"
|
||||||
"read only = " (if read-only? "true" "false") "\n"
|
"pid file = " pid-file "\n"
|
||||||
"timeout = " (number->string timeout) "\n"))))
|
"lock file = " lock-file "\n"
|
||||||
|
"log file = " log-file "\n"
|
||||||
|
(if address (string-append "address = " address "\n") "")
|
||||||
|
"port = " (number->string port-number) "\n"
|
||||||
|
(if uid (string-append "uid = " uid "\n") "")
|
||||||
|
"gid = " (if gid gid "nogroup") "\n" ; no group nobody
|
||||||
|
"\n\n"
|
||||||
|
(append-map module-config modules))))
|
||||||
|
|
||||||
(define (rsync-shepherd-service config)
|
(define (rsync-shepherd-service config)
|
||||||
"Return a <shepherd-service> for rsync with CONFIG."
|
"Return a <shepherd-service> for rsync with CONFIG."
|
||||||
|
@ -172,4 +245,7 @@ (define rsync-service-type
|
||||||
(list (service-extension shepherd-root-service-type rsync-shepherd-service)
|
(list (service-extension shepherd-root-service-type rsync-shepherd-service)
|
||||||
(service-extension account-service-type rsync-account)
|
(service-extension account-service-type rsync-account)
|
||||||
(service-extension activation-service-type rsync-activation)))
|
(service-extension activation-service-type rsync-activation)))
|
||||||
(default-value (rsync-configuration))))
|
(default-value (rsync-configuration))
|
||||||
|
(description
|
||||||
|
"Run the rsync file copying tool in daemon mode. This allows remote hosts
|
||||||
|
to keep synchronized copies of the files exported by rsync.")))
|
||||||
|
|
Loading…
Reference in a new issue