summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiacomo Leidi <goodoldpaul@autistici.org>2025-01-19 23:04:00 +0100
committerLudovic Courtès <ludo@gnu.org>2025-01-25 00:04:27 +0100
commit35c6ae6e58f1cfd397602d12c4f4e70d37f0eb90 (patch)
treefd6e79d4783af33baf9e78c6ae9b3a36df8961ec
parent44d12f9663ca363134636588279ef70decd1d551 (diff)
services: restic-backup: Implement as a Shepherd timer.
This patch implements restic backup with Shepherd services. It is supposed not to break any existing setup. * gnu/services/backup.scm (restic-backup-job): Add Shepherd configuration options; (restic-backup-job->mcron-job): Replace with...; (restic-job-log-file): New procedure; (restic-backup-job->shepherd-service): New procedure; (restic-backup-activation): New procedure; (restic-backup-service-type): Replace mcron with Shepherd extension and add activation extension hook. * doc/guix.texi: Document it. Change-Id: I66de3b6a1cb6177f9e4ee0c2acf3013ecbcdd338 Signed-off-by: Ludovic Courtès <ludo@gnu.org>
-rw-r--r--doc/guix.texi39
-rw-r--r--gnu/services/backup.scm122
2 files changed, 131 insertions, 30 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index b1463387f3a..9a53bdcd374 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -111,7 +111,7 @@ Copyright @copyright{} 2022 (@*
111Copyright @copyright{} 2022 John Kehayias@* 111Copyright @copyright{} 2022 John Kehayias@*
112Copyright @copyright{} 2022⁠–⁠2023 Bruno Victal@* 112Copyright @copyright{} 2022⁠–⁠2023 Bruno Victal@*
113Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@* 113Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@*
114Copyright @copyright{} 2023-2024 Giacomo Leidi@* 114Copyright @copyright{} 2023-2025 Giacomo Leidi@*
115Copyright @copyright{} 2022 Antero Mejr@* 115Copyright @copyright{} 2022 Antero Mejr@*
116Copyright @copyright{} 2023 Karl Hallsby@* 116Copyright @copyright{} 2023 Karl Hallsby@*
117Copyright @copyright{} 2023 Nathaniel Nicandro@* 117Copyright @copyright{} 2023 Nathaniel Nicandro@*
@@ -42710,19 +42710,16 @@ following configuration:
42710 "/etc/guix/signing-key.sec")))))))))) 42710 "/etc/guix/signing-key.sec"))))))))))
42711@end lisp 42711@end lisp
42712 42712
42713Each @code{restic-backup-job} translates to an mcron job which sets the 42713Each @code{restic-backup-job} translates to a Shepherd timer which sets the
42714@env{RESTIC_PASSWORD} environment variable by reading the first line of 42714@env{RESTIC_PASSWORD} environment variable by reading the first line of
42715@code{password-file} and runs @command{restic backup}, creating backups 42715@code{password-file} and runs @command{restic backup}, creating backups
42716using rclone of all the files listed in the @code{files} field. 42716using rclone of all the files listed in the @code{files} field.
42717 42717
42718The @code{restic-backup-service-type} installs as well @code{restic-guix} 42718The @code{restic-backup-service-type} provides the ability to instantaneously
42719to the system profile, a @code{restic} utility wrapper that allows for easier 42719trigger a backup with the @code{trigger} Shepherd action:
42720interaction with the Guix configured backup jobs. For example the following
42721could be used to instantaneusly trigger a backup for the above shown
42722configuration, without waiting for the scheduled job:
42723 42720
42724@example 42721@example
42725restic-guix backup remote-ftp 42722sudo herd trigger remote-ftp
42726@end example 42723@end example
42727 42724
42728@c %start of fragment 42725@c %start of fragment
@@ -42753,6 +42750,23 @@ The restic package to be used for the current job.
42753@item @code{user} (default: @code{"root"}) (type: string) 42750@item @code{user} (default: @code{"root"}) (type: string)
42754The user used for running the current job. 42751The user used for running the current job.
42755 42752
42753@item @code{group} (default: @code{"root"}) (type: string)
42754The group used for running the current job.
42755
42756@item @code{log-file} (type: maybe-string)
42757The file system path to the log file for this job. By default the file will
42758have be @file{/var/log/restic-backup/@var{job-name}.log}, where @var{job-name} is the
42759name defined in the @code{name} field.
42760
42761@item @code{max-duration} (type: maybe-number)
42762The maximum duration in seconds that a job may last. Past
42763@code{max-duration} seconds, the job is forcefully terminated.
42764
42765@item @code{wait-for-termination?} (default: @code{#f}) (type: boolean)
42766Wait until the job has finished before considering executing it again;
42767otherwise, perform it strictly on every occurrence of event, at the risk of
42768having multiple instances running concurrently.
42769
42756@item @code{repository} (type: string) 42770@item @code{repository} (type: string)
42757The restic repository target of this job. 42771The restic repository target of this job.
42758 42772
@@ -42765,9 +42779,12 @@ that will be used to set the @env{RESTIC_PASSWORD} environment variable
42765for the current job. 42779for the current job.
42766 42780
42767@item @code{schedule} (type: gexp-or-string) 42781@item @code{schedule} (type: gexp-or-string)
42768A string or a gexp that will be passed as time specification in the 42782A string or a gexp representing the frequency of the backup. Gexp must
42769mcron job specification (@pxref{Syntax, mcron job specifications,, 42783evaluate to @code{calendar-event} records or to strings. Strings must contain
42770mcron,GNU@tie{}mcron}). 42784Vixie cron date lines.
42785
42786@item @code{requirement} (default: @code{'()}) (type: list-of-symbols)
42787The list of Shepherd services that this backup job depends upon.
42771 42788
42772@item @code{files} (default: @code{'()}) (type: list-of-lowerables) 42789@item @code{files} (default: @code{'()}) (type: list-of-lowerables)
42773The list of files or directories to be backed up. It must be a list of 42790The list of files or directories to be backed up. It must be a list of
diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm
index 555e9fc9590..99a79ff5fbe 100644
--- a/gnu/services/backup.scm
+++ b/gnu/services/backup.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2024 Giacomo Leidi <goodoldpaul@autistici.org> 2;;; Copyright © 2024, 2025 Giacomo Leidi <goodoldpaul@autistici.org>
3;;; 3;;;
4;;; This file is part of GNU Guix. 4;;; This file is part of GNU Guix.
5;;; 5;;;
@@ -18,9 +18,10 @@
18 18
19(define-module (gnu services backup) 19(define-module (gnu services backup)
20 #:use-module (gnu packages backup) 20 #:use-module (gnu packages backup)
21 #:use-module (gnu packages bash)
21 #:use-module (gnu services) 22 #:use-module (gnu services)
22 #:use-module (gnu services configuration) 23 #:use-module (gnu services configuration)
23 #:use-module (gnu services mcron) 24 #:use-module (gnu services shepherd)
24 #:use-module (guix build-system copy) 25 #:use-module (guix build-system copy)
25 #:use-module (guix gexp) 26 #:use-module (guix gexp)
26 #:use-module ((guix licenses) 27 #:use-module ((guix licenses)
@@ -33,11 +34,16 @@
33 restic-backup-job-fields 34 restic-backup-job-fields
34 restic-backup-job-restic 35 restic-backup-job-restic
35 restic-backup-job-user 36 restic-backup-job-user
37 restic-backup-job-group
38 restic-backup-job-log-file
39 restic-backup-job-max-duration
40 restic-backup-job-wait-for-termination?
36 restic-backup-job-name 41 restic-backup-job-name
37 restic-backup-job-repository 42 restic-backup-job-repository
38 restic-backup-job-password-file 43 restic-backup-job-password-file
39 restic-backup-job-schedule 44 restic-backup-job-schedule
40 restic-backup-job-files 45 restic-backup-job-files
46 restic-backup-job-requirement
41 restic-backup-job-verbose? 47 restic-backup-job-verbose?
42 restic-backup-job-extra-flags 48 restic-backup-job-extra-flags
43 49
@@ -64,6 +70,12 @@
64(define list-of-lowerables? 70(define list-of-lowerables?
65 (list-of lowerable?)) 71 (list-of lowerable?))
66 72
73(define list-of-symbols?
74 (list-of symbol?))
75
76(define-maybe/no-serialization string)
77(define-maybe/no-serialization number)
78
67(define-configuration/no-serialization restic-backup-job 79(define-configuration/no-serialization restic-backup-job
68 (restic 80 (restic
69 (package restic) 81 (package restic)
@@ -71,6 +83,23 @@
71 (user 83 (user
72 (string "root") 84 (string "root")
73 "The user used for running the current job.") 85 "The user used for running the current job.")
86 (group
87 (string "root")
88 "The group used for running the current job.")
89 (log-file
90 (maybe-string)
91 "The file system path to the log file for this job. By default the file will
92have be @file{/var/log/restic-backup/@var{job-name}.log}, where @var{job-name} is the
93name defined in the @code{name} field.")
94 (max-duration
95 (maybe-number)
96 "The maximum duration in seconds that a job may last. Past
97@code{max-duration} seconds, the job is forcefully terminated.")
98 (wait-for-termination?
99 (boolean #f)
100 "Wait until the job has finished before considering executing it again;
101otherwise, perform it strictly on every occurrence of event, at the risk of
102having multiple instances running concurrently.")
74 (name 103 (name
75 (string) 104 (string)
76 "A string denoting a name for this job.") 105 "A string denoting a name for this job.")
@@ -84,9 +113,12 @@ will be used to set the @code{RESTIC_PASSWORD} environment variable for the
84current job.") 113current job.")
85 (schedule 114 (schedule
86 (gexp-or-string) 115 (gexp-or-string)
87 "A string or a gexp that will be passed as time specification in the mcron 116 "A string or a gexp representing the frequency of the backup. Gexp must
88job specification (@pxref{Syntax, mcron job specifications,, mcron, 117evaluate to @code{calendar-event} records or to strings. Strings must contain
89GNU@tie{}mcron}).") 118Vixie cron date lines.")
119 (requirement
120 (list-of-symbols '())
121 "The list of Shepherd services that this backup job depends upon.")
90 (files 122 (files
91 (list-of-lowerables '()) 123 (list-of-lowerables '())
92 "The list of files or directories to be backed up. It must be a list of 124 "The list of files or directories to be backed up. It must be a list of
@@ -175,16 +207,59 @@ command-line arguments to the current job @command{restic backup} invokation."))
175 207
176 (main (command-line))))) 208 (main (command-line)))))
177 209
178(define (restic-backup-job->mcron-job config) 210(define (restic-job-log-file job)
179 (let ((user 211 (let ((name (restic-backup-job-name job))
180 (restic-backup-job-user config)) 212 (log-file (restic-backup-job-log-file job)))
181 (schedule 213 (if (maybe-value-set? log-file)
182 (restic-backup-job-schedule config)) 214 log-file
183 (name 215 (string-append "/var/log/restic-backup/" name ".log"))))
184 (restic-backup-job-name config))) 216
185 #~(job #$schedule 217(define (restic-backup-job->shepherd-service config)
186 #$(string-append "restic-guix backup " name) 218 (let ((schedule (restic-backup-job-schedule config))
187 #:user #$user))) 219 (name (restic-backup-job-name config))
220 (user (restic-backup-job-user config))
221 (group (restic-backup-job-group config))
222 (max-duration (restic-backup-job-max-duration config))
223 (wait-for-termination? (restic-backup-job-wait-for-termination? config))
224 (log-file (restic-job-log-file config))
225 (requirement (restic-backup-job-requirement config)))
226 (shepherd-service (provision `(,(string->symbol name)))
227 (requirement
228 `(user-processes file-systems ,@requirement))
229 (documentation
230 "Run @code{restic} backed backups on a regular basis.")
231 (modules '((shepherd service timer)))
232 (start
233 #~(make-timer-constructor
234 (if (string? #$schedule)
235 (cron-string->calendar-event #$schedule)
236 #$schedule)
237 (command
238 (list
239 ;; We go through bash, instead of executing
240 ;; restic-guix directly, because the login shell
241 ;; gives us the correct user environment that some
242 ;; backends require, such as rclone.
243 (string-append #+bash-minimal "/bin/bash")
244 "-l" "-c"
245 (string-append "restic-guix backup " #$name))
246 #:user #$user
247 #:group #$group
248 #:environment-variables
249 (list
250 (string-append
251 "HOME=" (passwd:dir (getpwnam #$user)))))
252 #:log-file #$log-file
253 #:wait-for-termination? #$wait-for-termination?
254 #:max-duration #$(and (maybe-value-set? max-duration)
255 max-duration)))
256 (stop
257 #~(make-timer-destructor))
258 (actions (list (shepherd-action
259 (name 'trigger)
260 (documentation "Manually trigger a backup,
261without waiting for the scheduled time.")
262 (procedure #~trigger-timer)))))))
188 263
189(define (restic-guix-wrapper-package jobs) 264(define (restic-guix-wrapper-package jobs)
190 (package 265 (package
@@ -212,15 +287,24 @@ without waiting for the scheduled job to run.")
212 (restic-guix-wrapper-package jobs)) 287 (restic-guix-wrapper-package jobs))
213 '()))) 288 '())))
214 289
290(define (restic-backup-activation config)
291 #~(for-each
292 (lambda (log-file)
293 (mkdir-p (dirname log-file)))
294 (list #$@(map restic-job-log-file
295 (restic-backup-configuration-jobs config)))))
296
215(define restic-backup-service-type 297(define restic-backup-service-type
216 (service-type (name 'restic-backup) 298 (service-type (name 'restic-backup)
217 (extensions 299 (extensions
218 (list 300 (list
301 (service-extension activation-service-type
302 restic-backup-activation)
219 (service-extension profile-service-type 303 (service-extension profile-service-type
220 restic-backup-service-profile) 304 restic-backup-service-profile)
221 (service-extension mcron-service-type 305 (service-extension shepherd-root-service-type
222 (lambda (config) 306 (lambda (config)
223 (map restic-backup-job->mcron-job 307 (map restic-backup-job->shepherd-service
224 (restic-backup-configuration-jobs 308 (restic-backup-configuration-jobs
225 config)))))) 309 config))))))
226 (compose concatenate) 310 (compose concatenate)
@@ -232,5 +316,5 @@ without waiting for the scheduled job to run.")
232 jobs))))) 316 jobs)))))
233 (default-value (restic-backup-configuration)) 317 (default-value (restic-backup-configuration))
234 (description 318 (description
235 "This service configures @code{mcron} jobs for running backups 319 "This service configures Shepherd timers for running backups
236with @code{restic}."))) 320with restic.")))