1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
(define-module (tw services restic)
#:use-module (gnu)
#:use-module ((gnu packages admin)
#:select (shadow))
#:use-module (gnu services)
#:use-module (gnu services configuration)
#:use-module (gnu services shepherd)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (tw packages restic)
#:export (restic-server-service-type
restic-server-configuration))
(define-maybe/no-serialization integer)
(define-maybe/no-serialization string)
;; TODO: implement --tls, --tls-cert and --tls-key, maybe using certbot-service-type?
(define-configuration/no-serialization restic-server-configuration
(repository-path (string "/var/lib/restic") "The directory containing
restic's repositories and @code{.htpasswd} file, unless otherwise configured
using @code{htpasswd-file}.")
(restic-server (package restic-rest-server) "The restic REST server package to use.")
(bind-address (string ":8000") "The listen address (including port) to bind to.")
(htpasswd-file (maybe-string #f) "Location of @code{.htpasswd} file
(default: @code{REPOSITORY-PATH/.htpasswd}).")
(auth? (boolean #t) "Whether to authenticate users at all (using .htpasswd).")
(verify-upload? (boolean #t) "Whether to verify the integrity of uploaded
data. @emph{Do not disable} unless the restic server is to be run on a very
low-power device.")
(append-only? (boolean #f) "Whether to run the restic server in append-only mode.")
(max-repository-size (maybe-integer %unset-value) "Maximum repository size
in bytes, if any.")
(private-repos-only? (boolean #f) "Whether to let users only access their
private restic repos.")
(prometheus? (boolean #f) "Whether to serve Prometheus metrics.")
(prometheus-auth? (boolean #t) "Whether to require authentication as the
@code{metrics} user to access the Prometheus /metrics endpoint."))
(define (restic-server-arguments config)
"Turn CONFIG into a list of arguments to the restic-rest-server executable."
`("--path" ,(restic-server-configuration-repository-path config)
"--log" "/var/log/restic-server.log"
"--listen" ,(restic-server-configuration-bind-address config)
,@(if (restic-server-configuration-append-only? config) '("--append-only") '())
,@(let ((max-size (restic-server-configuration-max-repository-size config)))
(if (integer? max-size) `("--max-size" ,max-size) '()))
,@(if (restic-server-configuration-private-repos-only? config) '("--private-repos") '())
,@(if (restic-server-configuration-prometheus? config) '("--prometheus") '())
,@(if (restic-server-configuration-prometheus-auth? config) '() '("--prometheus-no-auth"))))
(define (restic-server-service config)
"Create a `shepherd-service' for the restic REST server from CONFIG."
(list (shepherd-service
(provision '(restic-server))
(requirement '(networking))
(documentation "Run the Restic REST server to serve backup repositories via HTTP.")
(start #~(make-forkexec-constructor
(list #$(file-append (restic-server-configuration-restic-server config)
"/bin/restic-rest-server")
#$@(restic-server-arguments config))
#:user "restic" #:group "restic"))
(stop #~(make-kill-destructor)))))
(define (restic-server-accounts config)
"Create user accounts and groups for the restic REST server defined in CONFIG."
(list (user-account
(name "restic")
(group "restic")
(comment "Restic server user")
(system? #t)
(home-directory (restic-server-configuration-repository-path config))
(shell (file-append shadow "/sbin/nologin")))
(user-group
(name "restic")
(system? #t))))
(define restic-server-service-type
(service-type
(name 'restic-server)
(extensions
(list (service-extension shepherd-root-service-type restic-server-service)
(service-extension account-service-type restic-server-accounts)))
(description
"Restic REST server, running as a service user instead of root.")))
|