Package: guix-patches;
Reported by: paul <goodoldpaul <at> autistici.org>
Date: Mon, 10 Feb 2025 00:06:01 UTC
Severity: normal
Tags: moreinfo
Done: Ludovic Courtès <ludo <at> gnu.org>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 76169 in the body.
You can then email your comments to 76169 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
View this report as an mbox folder, status mbox, maintainer mbox
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Mon, 10 Feb 2025 00:06:01 GMT) Full text and rfc822 format available.paul <goodoldpaul <at> autistici.org>
:guix-patches <at> gnu.org
.
(Mon, 10 Feb 2025 00:06:02 GMT) Full text and rfc822 format available.Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: guix-patches <at> gnu.org Subject: home: Add home-restic-backup service. Date: Mon, 10 Feb 2025 01:04:58 +0100
Hi Guix, I'm sending a patch implementing a Home service for the restic-backup-service-type. This patch depends on https://issues.guix.gnu.org/72803 . Thank you for your work! giacomo
andrew <at> trop.in, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Mon, 10 Feb 2025 00:08:02 GMT) Full text and rfc822 format available.Message #8 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH] home: Add home-restic-backup service. Date: Mon, 10 Feb 2025 01:06:42 +0100
* gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 49 ++++++++++++++++ gnu/home/services/backup.scm | 107 +++++++++++++++++++++++++++++++++++ gnu/local.mk | 1 + 3 files changed, 157 insertions(+) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index 86582fb4785..f8ad6769306 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -462,6 +462,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -46729,6 +46730,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -48275,6 +48277,53 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Home Services + +The @code{(gnu services backup)} module offers services for backing up +file system trees. For now, it provides the @code{restic-backup-service-type}. + +With @code{restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + (service home-restic-backup-service-type + (restic-backup-configuration + (jobs + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-job-configuration}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-job-configuration}. + +It will also install the @command{restic-guix} package to the user's Home +profile. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..421737eef74 --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,107 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu services configuration) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:use-module (srfi srfi-1) + #:export (home-restic-backup-service-type)) + +(define (home-restic-job-log-file job) + (let ((name (restic-backup-job-name job)) + (log-file (restic-backup-job-log-file job))) + (and (maybe-value-set? log-file) log-file))) + +(define (restic-backup-job->home-shepherd-service config) + (let ((schedule (restic-backup-job-schedule config)) + (name (restic-backup-job-name config)) + (files (restic-backup-job-files config)) + (max-duration (restic-backup-job-max-duration config)) + (wait-for-termination? (restic-backup-job-wait-for-termination? config)) + (log-file (home-restic-job-log-file config)) + (requirement (restic-backup-job-requirement config))) + (shepherd-service (provision `(,(string->symbol name))) + (requirement + `(,@requirement)) + (documentation + "Run @code{restic} backed backups on a regular basis.") + (modules '((shepherd service timer) + ;;for %user-log-dir + (shepherd support))) + (start + #~(make-timer-constructor + (if (string? #$schedule) + (cron-string->calendar-event #$schedule) + #$schedule) + (command + (list + "restic-guix" "backup" #$name #$@files)) + #:log-file (if (string? #$log-file) + #$log-file + (string-append %user-log-dir "/restic-backup/" #$name ".log")) + #:wait-for-termination? #$wait-for-termination? + #:max-duration #$(and (maybe-value-set? max-duration) + max-duration))) + (stop + #~(make-timer-destructor)) + (actions (list (shepherd-action + (name 'trigger) + (documentation "Manually trigger a backup, +without waiting for the scheduled time.") + (procedure #~trigger-timer))))))) + +(define (home-restic-backup-activation config) + #~(begin + (use-modules (shepherd support)) + (mkdir-p (string-append %user-log-dir "/restic-backup/")) + (for-each + (lambda (log-file) + (when (string? log-file) + (mkdir-p (dirname log-file)))) + (list #$@(map home-restic-job-log-file + (restic-backup-configuration-jobs config)))))) + +(define home-restic-backup-service-type + (service-type (name 'home-restic-backup) + (extensions + (list + (service-extension home-activation-service-type + home-restic-backup-activation) + (service-extension home-profile-service-type + restic-backup-service-profile) + (service-extension home-shepherd-service-type + (lambda (config) + (map restic-backup-job->home-shepherd-service + (restic-backup-configuration-jobs + config)))))) + (compose concatenate) + (extend + (lambda (config jobs) + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs))))) + (default-value (restic-backup-configuration)) + (description + "This service configures Shepherd timers for running backups +with restic."))) diff --git a/gnu/local.mk b/gnu/local.mk index 117280fc11b..b78c6755f12 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -102,6 +102,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ base-commit: a1fac696c4ef5e20d0412ec22ae6a0d77ea26682 -- 2.48.1
paul <goodoldpaul <at> autistici.org>
to control <at> debbugs.gnu.org
.
(Mon, 10 Feb 2025 00:11:02 GMT) Full text and rfc822 format available.guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Thu, 13 Feb 2025 11:49:01 GMT) Full text and rfc822 format available.Message #13 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Ludovic Courtès <ludo <at> gnu.org> To: Giacomo Leidi <goodoldpaul <at> autistici.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org>, 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Thu, 13 Feb 2025 12:48:02 +0100
Hi, Giacomo Leidi <goodoldpaul <at> autistici.org> skribis: > +(define (restic-backup-job->home-shepherd-service config) > + (let ((schedule (restic-backup-job-schedule config)) > + (name (restic-backup-job-name config)) > + (files (restic-backup-job-files config)) > + (max-duration (restic-backup-job-max-duration config)) > + (wait-for-termination? (restic-backup-job-wait-for-termination? config)) > + (log-file (home-restic-job-log-file config)) > + (requirement (restic-backup-job-requirement config))) > + (shepherd-service (provision `(,(string->symbol name))) > + (requirement > + `(,@requirement)) > + (documentation > + "Run @code{restic} backed backups on a regular basis.") > + (modules '((shepherd service timer) > + ;;for %user-log-dir > + (shepherd support))) > + (start > + #~(make-timer-constructor > + (if (string? #$schedule) > + (cron-string->calendar-event #$schedule) > + #$schedule) Instead of duplicating the whole thing, I’d suggest using ‘for-home?’ as is done for example with ‘home-dicod-service-type’. That way, we end up with a single source that works for both system and home services. Ludo’.
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Thu, 13 Feb 2025 22:38:01 GMT) Full text and rfc822 format available.Message #16 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: Ludovic Courtès <ludo <at> gnu.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org>, 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Thu, 13 Feb 2025 23:37:04 +0100
Hi, It's a good idea, but I was not able to make for-home work with (gnu services configuration) so I changed restic-backup-configuration to a record type from (guix records). It does not impact end user configs in my tests. I'm sending a v2, thank you for your help! giacomo
andrew <at> trop.in, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Thu, 13 Feb 2025 23:02:01 GMT) Full text and rfc822 format available.Message #19 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v2] home: Add home-restic-backup service. Date: Fri, 14 Feb 2025 00:00:36 +0100
* gnu/services/backup.scm (restic-backup-configuration): Reimplement with (guix records); (restic-backup-job-{logfile,command,requirement,modules}): Add new procedures and add support for Guix Home environments; (restic-backup-job->shepherd-service): Add support for Guix Home environments; (restic-backup-service-activation): Drop procedure as now the Shepherd takes care of creating directories for timers logs. * gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 77 +++++++++++++++++++++++ gnu/home/services/backup.scm | 40 ++++++++++++ gnu/local.mk | 1 + gnu/services/backup.scm | 116 ++++++++++++++++++++--------------- 4 files changed, 186 insertions(+), 48 deletions(-) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index cdabe030953..96d400fee8c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -462,6 +462,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -46753,6 +46754,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -48299,6 +48301,81 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Home Services + +The @code{(gnu home services backup)} module offers services for backing up +file system trees. For now, it provides the @code{home-restic-backup-service-type}. + +With @code{home-restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu services backup) ;for 'restic-backup-job' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (simple-service 'backup-jobs + home-restic-backup-service-type + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))) +@end lisp + +In general it is preferrable to extend the @code{home-restic-backup-service-type}, +as shown in the example above. This is because it takes care of wrapping everything +with @code{for-home}, which enables the @code{home-restic-backup-service-type} and +@code{restic-backup-service-type} to share the same codebase. + +For a custom configuration, wrap your @code{restic-backup-configuration} in +@code{for-home}, as in this example: + +@lisp +(use-modules (gnu services) ;for 'for-home' + (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (service home-restic-backup-service-type + (for-home + (restic-backup-configuration + (jobs (list @dots{})))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-backup-job}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-backup-job}. + +It will also install the @command{restic-guix} package to the user's Home +profile. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..658db30246d --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,40 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu services configuration) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:use-module (srfi srfi-1) + #:export (home-restic-backup-service-type)) + +(define home-restic-backup-service-type + (service-type + (inherit (system->home-service-type restic-backup-service-type)) + (extend + (lambda (config jobs) + (for-home + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs)))))) + (default-value (for-home (restic-backup-configuration))))) diff --git a/gnu/local.mk b/gnu/local.mk index fbca6d4ce83..fe7aa9261e7 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -102,6 +102,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index dcbed890e13..60c289d516e 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -28,6 +28,7 @@ (define-module (gnu services backup) #:prefix license:) #:use-module (guix modules) #:use-module (guix packages) + #:use-module (guix records) #:use-module (srfi srfi-1) #:export (restic-backup-job restic-backup-job? @@ -49,7 +50,6 @@ (define-module (gnu services backup) restic-backup-configuration restic-backup-configuration? - restic-backup-configuration-fields restic-backup-configuration-jobs restic-program @@ -57,7 +57,6 @@ (define-module (gnu services backup) restic-guix restic-guix-wrapper-package restic-backup-service-profile - restic-backup-service-activation restic-backup-service-type)) (define (gexp-or-string? value) @@ -132,13 +131,15 @@ (define-configuration/no-serialization restic-backup-job "A list of values that are lowered to strings. These will be passed as command-line arguments to the current @command{restic} invokation.")) -(define list-of-restic-backup-jobs? - (list-of restic-backup-job?)) +(define-record-type* <restic-backup-configuration> + restic-backup-configuration + make-restic-backup-configuration + restic-backup-configuration? + this-restic-backup-configuration -(define-configuration/no-serialization restic-backup-configuration - (jobs - (list-of-restic-backup-jobs '()) - "The list of backup jobs for the current system.")) + (jobs restic-backup-configuration-jobs (default '())) ; list of restic-backup-job + (home-service? restic-backup-configuration-home-service? + (default for-home?) (innate))) (define %restic-guix-supported-actions '("backup" "mount" "prune" "restore" "snapshots" "unlock")) @@ -244,53 +245,79 @@ (define* (restic-guix config #:key (supported-actions (main (command-line))))) -(define (restic-job-log-file job) +(define* (restic-backup-job-log-file job #:key (home-service? #f)) (let ((name (restic-backup-job-name job)) (log-file (restic-backup-job-log-file job))) (if (maybe-value-set? log-file) log-file - (string-append "/var/log/restic-backup/" name ".log")))) + (if home-service? + #~(begin + (use-modules (shepherd support)) + (string-append %user-log-dir "/restic-backup/" #$name ".log")) + (string-append "/var/log/restic-backup/" name ".log"))))) -(define (restic-backup-job->shepherd-service config) +(define* (restic-backup-job-command name files #:key (home-service? #f)) + (if home-service? + #~(list + "restic-guix" "backup" #$name #$@files) + #~(list + (string-append #+bash-minimal "/bin/bash") + "-l" "-c" + (string-append + "restic-guix backup " #$name " " + #$(string-join + (map (lambda (f) (string-append "'" f "'")) + files) + " "))))) + +(define* (restic-backup-job-requirement requirement #:key (home-service? #f)) + (if home-service? + requirement + (append '(user-processes file-systems) requirement))) + +(define* (restic-backup-job-modules #:key (home-service? #f)) + `((shepherd service timer) + ,@(if home-service? + ;;for %user-log-dir + '((shepherd support)) + '()))) + +(define* (restic-backup-job->shepherd-service config #:key (home-service? #f)) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) - (files (string-join - (map (lambda (f) (string-append "'" f "'")) - (restic-backup-job-files config)) - " ")) + (files (restic-backup-job-files config)) (user (restic-backup-job-user config)) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) (wait-for-termination? (restic-backup-job-wait-for-termination? config)) - (log-file (restic-job-log-file config)) - (requirement (restic-backup-job-requirement config))) + (log-file (restic-backup-job-log-file + config #:home-service? home-service?)) + (requirement + (restic-backup-job-requirement + (restic-backup-job-requirement config) + #:home-service? home-service?))) (shepherd-service (provision `(,(string->symbol name))) - (requirement - `(user-processes file-systems ,@requirement)) + (requirement requirement) (documentation "Run @code{restic} backed backups on a regular basis.") - (modules '((shepherd service timer))) + (modules (restic-backup-job-modules + #:home-service? home-service?)) (start #~(make-timer-constructor (if (string? #$schedule) (cron-string->calendar-event #$schedule) #$schedule) (command - (list - ;; We go through bash, instead of executing - ;; restic-guix directly, because the login shell - ;; gives us the correct user environment that some - ;; backends require, such as rclone. - (string-append #+bash-minimal "/bin/bash") - "-l" "-c" - (string-append - "restic-guix backup " #$name " " #$files)) - #:user #$user - #:group #$group - #:environment-variables - (list - (string-append - "HOME=" (passwd:dir (getpwnam #$user))))) + #$(restic-backup-job-command + name files #:home-service? home-service?)) + #$@(if home-service? '() (list #:user user)) + #$@(if home-service? '() (list #:group group)) + #$@(if home-service? '() + (list + #:environment-variables + #~(list + (string-append + "HOME=" (passwd:dir (getpwnam #$user)))))) #:log-file #$log-file #:wait-for-termination? #$wait-for-termination? #:max-duration #$(and (maybe-value-set? max-duration) @@ -329,26 +356,19 @@ (define restic-backup-service-profile (restic-guix-wrapper-package config)) '()))) -(define (restic-backup-service-activation config) - #~(for-each - (lambda (log-file) - (mkdir-p (dirname log-file))) - (list #$@(map restic-job-log-file - (restic-backup-configuration-jobs config))))) - (define restic-backup-service-type (service-type (name 'restic-backup) (extensions (list - (service-extension activation-service-type - restic-backup-service-activation) (service-extension profile-service-type restic-backup-service-profile) (service-extension shepherd-root-service-type - (lambda (config) - (map restic-backup-job->shepherd-service - (restic-backup-configuration-jobs - config)))))) + (match-record-lambda <restic-backup-configuration> + (jobs home-service?) + (map (lambda (job) + (restic-backup-job->shepherd-service + job #:home-service? home-service?)) + jobs))))) (compose concatenate) (extend (lambda (config jobs) base-commit: 3854375d83b8a549513c93fd379af22dc753c1d9 -- 2.48.1
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Thu, 13 Feb 2025 23:27:02 GMT) Full text and rfc822 format available.Message #22 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: Ludovic Courtès <ludo <at> gnu.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org>, 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Fri, 14 Feb 2025 00:26:43 +0100
Hi, I'm sending a v3 with a minor fix for the (command ...) invokation. Thank you for your time, giacomo
andrew <at> trop.in, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Thu, 13 Feb 2025 23:28:01 GMT) Full text and rfc822 format available.Message #25 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v3] home: Add home-restic-backup service. Date: Fri, 14 Feb 2025 00:27:49 +0100
* gnu/services/backup.scm (restic-backup-configuration): Reimplement with (guix records); (restic-backup-job-{logfile,command,requirement,modules}): Add new procedures and add support for Guix Home environments; (restic-backup-job->shepherd-service): Add support for Guix Home environments; (restic-backup-service-activation): Drop procedure as now the Shepherd takes care of creating directories for timers logs. * gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 77 +++++++++++++++++++++++ gnu/home/services/backup.scm | 40 ++++++++++++ gnu/local.mk | 1 + gnu/services/backup.scm | 116 ++++++++++++++++++++--------------- 4 files changed, 186 insertions(+), 48 deletions(-) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index cdabe030953..96d400fee8c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -462,6 +462,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -46753,6 +46754,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -48299,6 +48301,81 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Home Services + +The @code{(gnu home services backup)} module offers services for backing up +file system trees. For now, it provides the @code{home-restic-backup-service-type}. + +With @code{home-restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu services backup) ;for 'restic-backup-job' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (simple-service 'backup-jobs + home-restic-backup-service-type + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))) +@end lisp + +In general it is preferrable to extend the @code{home-restic-backup-service-type}, +as shown in the example above. This is because it takes care of wrapping everything +with @code{for-home}, which enables the @code{home-restic-backup-service-type} and +@code{restic-backup-service-type} to share the same codebase. + +For a custom configuration, wrap your @code{restic-backup-configuration} in +@code{for-home}, as in this example: + +@lisp +(use-modules (gnu services) ;for 'for-home' + (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (service home-restic-backup-service-type + (for-home + (restic-backup-configuration + (jobs (list @dots{})))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-backup-job}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-backup-job}. + +It will also install the @command{restic-guix} package to the user's Home +profile. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..658db30246d --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,40 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu services configuration) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:use-module (srfi srfi-1) + #:export (home-restic-backup-service-type)) + +(define home-restic-backup-service-type + (service-type + (inherit (system->home-service-type restic-backup-service-type)) + (extend + (lambda (config jobs) + (for-home + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs)))))) + (default-value (for-home (restic-backup-configuration))))) diff --git a/gnu/local.mk b/gnu/local.mk index fbca6d4ce83..fe7aa9261e7 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -102,6 +102,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index dcbed890e13..97c12a5a480 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -28,6 +28,7 @@ (define-module (gnu services backup) #:prefix license:) #:use-module (guix modules) #:use-module (guix packages) + #:use-module (guix records) #:use-module (srfi srfi-1) #:export (restic-backup-job restic-backup-job? @@ -49,7 +50,6 @@ (define-module (gnu services backup) restic-backup-configuration restic-backup-configuration? - restic-backup-configuration-fields restic-backup-configuration-jobs restic-program @@ -57,7 +57,6 @@ (define-module (gnu services backup) restic-guix restic-guix-wrapper-package restic-backup-service-profile - restic-backup-service-activation restic-backup-service-type)) (define (gexp-or-string? value) @@ -132,13 +131,15 @@ (define-configuration/no-serialization restic-backup-job "A list of values that are lowered to strings. These will be passed as command-line arguments to the current @command{restic} invokation.")) -(define list-of-restic-backup-jobs? - (list-of restic-backup-job?)) +(define-record-type* <restic-backup-configuration> + restic-backup-configuration + make-restic-backup-configuration + restic-backup-configuration? + this-restic-backup-configuration -(define-configuration/no-serialization restic-backup-configuration - (jobs - (list-of-restic-backup-jobs '()) - "The list of backup jobs for the current system.")) + (jobs restic-backup-configuration-jobs (default '())) ; list of restic-backup-job + (home-service? restic-backup-configuration-home-service? + (default for-home?) (innate))) (define %restic-guix-supported-actions '("backup" "mount" "prune" "restore" "snapshots" "unlock")) @@ -244,53 +245,79 @@ (define* (restic-guix config #:key (supported-actions (main (command-line))))) -(define (restic-job-log-file job) +(define* (restic-backup-job-log-file job #:key (home-service? #f)) (let ((name (restic-backup-job-name job)) (log-file (restic-backup-job-log-file job))) (if (maybe-value-set? log-file) log-file - (string-append "/var/log/restic-backup/" name ".log")))) + (if home-service? + #~(begin + (use-modules (shepherd support)) + (string-append %user-log-dir "/restic-backup/" #$name ".log")) + (string-append "/var/log/restic-backup/" name ".log"))))) -(define (restic-backup-job->shepherd-service config) +(define* (restic-backup-job-command name files #:key (home-service? #f)) + (if home-service? + #~(list + "restic-guix" "backup" #$name #$@files) + #~(list + (string-append #+bash-minimal "/bin/bash") + "-l" "-c" + (string-append + "restic-guix backup " #$name " " + #$(string-join + (map (lambda (f) (string-append "'" f "'")) + files) + " "))))) + +(define* (restic-backup-job-requirement requirement #:key (home-service? #f)) + (if home-service? + requirement + (append '(user-processes file-systems) requirement))) + +(define* (restic-backup-job-modules #:key (home-service? #f)) + `((shepherd service timer) + ,@(if home-service? + ;;for %user-log-dir + '((shepherd support)) + '()))) + +(define* (restic-backup-job->shepherd-service config #:key (home-service? #f)) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) - (files (string-join - (map (lambda (f) (string-append "'" f "'")) - (restic-backup-job-files config)) - " ")) + (files (restic-backup-job-files config)) (user (restic-backup-job-user config)) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) (wait-for-termination? (restic-backup-job-wait-for-termination? config)) - (log-file (restic-job-log-file config)) - (requirement (restic-backup-job-requirement config))) + (log-file (restic-backup-job-log-file + config #:home-service? home-service?)) + (requirement + (restic-backup-job-requirement + (restic-backup-job-requirement config) + #:home-service? home-service?))) (shepherd-service (provision `(,(string->symbol name))) - (requirement - `(user-processes file-systems ,@requirement)) + (requirement requirement) (documentation "Run @code{restic} backed backups on a regular basis.") - (modules '((shepherd service timer))) + (modules (restic-backup-job-modules + #:home-service? home-service?)) (start #~(make-timer-constructor (if (string? #$schedule) (cron-string->calendar-event #$schedule) #$schedule) (command - (list - ;; We go through bash, instead of executing - ;; restic-guix directly, because the login shell - ;; gives us the correct user environment that some - ;; backends require, such as rclone. - (string-append #+bash-minimal "/bin/bash") - "-l" "-c" - (string-append - "restic-guix backup " #$name " " #$files)) - #:user #$user - #:group #$group - #:environment-variables - (list - (string-append - "HOME=" (passwd:dir (getpwnam #$user))))) + #$(restic-backup-job-command + name files #:home-service? home-service?) + #$@(if home-service? '() (list #:user user)) + #$@(if home-service? '() (list #:group group)) + #$@(if home-service? '() + (list + #:environment-variables + #~(list + (string-append + "HOME=" (passwd:dir (getpwnam #$user))))))) #:log-file #$log-file #:wait-for-termination? #$wait-for-termination? #:max-duration #$(and (maybe-value-set? max-duration) @@ -329,26 +356,19 @@ (define restic-backup-service-profile (restic-guix-wrapper-package config)) '()))) -(define (restic-backup-service-activation config) - #~(for-each - (lambda (log-file) - (mkdir-p (dirname log-file))) - (list #$@(map restic-job-log-file - (restic-backup-configuration-jobs config))))) - (define restic-backup-service-type (service-type (name 'restic-backup) (extensions (list - (service-extension activation-service-type - restic-backup-service-activation) (service-extension profile-service-type restic-backup-service-profile) (service-extension shepherd-root-service-type - (lambda (config) - (map restic-backup-job->shepherd-service - (restic-backup-configuration-jobs - config)))))) + (match-record-lambda <restic-backup-configuration> + (jobs home-service?) + (map (lambda (job) + (restic-backup-job->shepherd-service + job #:home-service? home-service?)) + jobs))))) (compose concatenate) (extend (lambda (config jobs) base-commit: 3854375d83b8a549513c93fd379af22dc753c1d9 -- 2.48.1
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Fri, 21 Feb 2025 14:22:02 GMT) Full text and rfc822 format available.Message #28 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Ludovic Courtès <ludo <at> gnu.org> To: paul <goodoldpaul <at> autistici.org> Cc: 76169 <at> debbugs.gnu.org, Andrew Tropin <andrew <at> trop.in>, Tanguy Le Carrour <tanguy <at> bioneland.org>, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Janneke Nieuwenhuizen <janneke <at> gnu.org> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Fri, 21 Feb 2025 15:20:59 +0100
Hi, paul <goodoldpaul <at> autistici.org> skribis: > It's a good idea, but I was not able to make for-home work with (gnu > services configuration) so I changed restic-backup-configuration to a > record type from (guix records). It does not impact end user configs > in my tests. Oh, is it because ‘define-configuration’ does not let you mark fields as “innate”? Ludo’.
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Wed, 26 Feb 2025 23:29:02 GMT) Full text and rfc822 format available.Message #31 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: Ludovic Courtès <ludo <at> gnu.org> Cc: 76169 <at> debbugs.gnu.org, Andrew Tropin <andrew <at> trop.in>, Tanguy Le Carrour <tanguy <at> bioneland.org>, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Janneke Nieuwenhuizen <janneke <at> gnu.org> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Thu, 27 Feb 2025 00:28:22 +0100
[Message part 1 (text/plain, inline)]
Hi Ludo’, On 2/21/25 15:20, Ludovic Courtès wrote: > Hi, > > paul<goodoldpaul <at> autistici.org> skribis: > >> It's a good idea, but I was not able to make for-home work with (gnu >> services configuration) so I changed restic-backup-configuration to a >> record type from (guix records). It does not impact end user configs >> in my tests. > Oh, is it because ‘define-configuration’ does not let you mark fields as > “innate”? I'm not sure, from experimentation (calling pk on the field that had for-home? as a default value) (for-home (oci-configuration is not able to replace for-home? with #t and pk prints #f. I didn't go deep enough to figure out why that is. I can put a comment stating that once for-home will be able to work with (gnu services configuration) the record can be migrated to define-configuration, if you don't find this is a blocking issue . I'm sending a new revision rebased on 72803 rebased on current master. cheers, giacomo
[Message part 2 (text/html, inline)]
andrew <at> trop.in, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Wed, 26 Feb 2025 23:30:02 GMT) Full text and rfc822 format available.Message #34 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v4] home: Add home-restic-backup service. Date: Thu, 27 Feb 2025 00:29:15 +0100
* gnu/services/backup.scm (restic-backup-configuration): Reimplement with (guix records); (restic-backup-job-{logfile,command,requirement,modules}): Add new procedures and add support for Guix Home environments; (restic-backup-job->shepherd-service): Add support for Guix Home environments; (restic-backup-service-activation): Drop procedure as now the Shepherd takes care of creating directories for timers logs. * gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 77 +++++++++++++++++++++++ gnu/home/services/backup.scm | 36 +++++++++++ gnu/local.mk | 1 + gnu/services/backup.scm | 116 ++++++++++++++++++++--------------- 4 files changed, 182 insertions(+), 48 deletions(-) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index 60ed003c82d..b53443ae7cb 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -463,6 +463,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -47245,6 +47246,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -48791,6 +48793,81 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Home Services + +The @code{(gnu home services backup)} module offers services for backing up +file system trees. For now, it provides the @code{home-restic-backup-service-type}. + +With @code{home-restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu services backup) ;for 'restic-backup-job' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (simple-service 'backup-jobs + home-restic-backup-service-type + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))) +@end lisp + +In general it is preferrable to extend the @code{home-restic-backup-service-type}, +as shown in the example above. This is because it takes care of wrapping everything +with @code{for-home}, which enables the @code{home-restic-backup-service-type} and +@code{restic-backup-service-type} to share the same codebase. + +For a custom configuration, wrap your @code{restic-backup-configuration} in +@code{for-home}, as in this example: + +@lisp +(use-modules (gnu services) ;for 'for-home' + (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (service home-restic-backup-service-type + (for-home + (restic-backup-configuration + (jobs (list @dots{})))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-backup-job}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-backup-job}. + +It will also install the @command{restic-guix} package to the user's Home +profile. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..7a30538bc06 --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,36 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:export (home-restic-backup-service-type)) + +(define home-restic-backup-service-type + (service-type + (inherit (system->home-service-type restic-backup-service-type)) + (extend + (lambda (config jobs) + (for-home + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs)))))) + (default-value (for-home (restic-backup-configuration))))) diff --git a/gnu/local.mk b/gnu/local.mk index c8a29bf98b5..678e318f899 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -102,6 +102,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index dc095593432..ae6d9bea82b 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -28,6 +28,7 @@ (define-module (gnu services backup) #:prefix license:) #:use-module (guix modules) #:use-module (guix packages) + #:use-module (guix records) #:use-module (srfi srfi-1) #:export (restic-backup-job restic-backup-job? @@ -49,7 +50,6 @@ (define-module (gnu services backup) restic-backup-configuration restic-backup-configuration? - restic-backup-configuration-fields restic-backup-configuration-jobs restic-program @@ -57,7 +57,6 @@ (define-module (gnu services backup) restic-guix restic-guix-wrapper-package restic-backup-service-profile - restic-backup-service-activation restic-backup-service-type)) (define (gexp-or-string? value) @@ -132,13 +131,15 @@ (define-configuration/no-serialization restic-backup-job "A list of values that are lowered to strings. These will be passed as command-line arguments to the current @command{restic} invocation.")) -(define list-of-restic-backup-jobs? - (list-of restic-backup-job?)) +(define-record-type* <restic-backup-configuration> + restic-backup-configuration + make-restic-backup-configuration + restic-backup-configuration? + this-restic-backup-configuration -(define-configuration/no-serialization restic-backup-configuration - (jobs - (list-of-restic-backup-jobs '()) - "The list of backup jobs for the current system.")) + (jobs restic-backup-configuration-jobs (default '())) ; list of restic-backup-job + (home-service? restic-backup-configuration-home-service? + (default for-home?) (innate))) (define %restic-guix-supported-actions '("backup" "list" "ls" "mount" "prune" "restore" "snapshots" "unlock")) @@ -244,53 +245,79 @@ (define* (restic-guix config #:key (supported-actions (main (command-line))))) -(define (restic-job-log-file job) +(define* (restic-backup-job-log-file job #:key (home-service? #f)) (let ((name (restic-backup-job-name job)) (log-file (restic-backup-job-log-file job))) (if (maybe-value-set? log-file) log-file - (string-append "/var/log/restic-backup/" name ".log")))) + (if home-service? + #~(begin + (use-modules (shepherd support)) + (string-append %user-log-dir "/restic-backup/" #$name ".log")) + (string-append "/var/log/restic-backup/" name ".log"))))) -(define (restic-backup-job->shepherd-service config) +(define* (restic-backup-job-command name files #:key (home-service? #f)) + (if home-service? + #~(list + "restic-guix" "backup" #$name #$@files) + #~(list + (string-append #+bash-minimal "/bin/bash") + "-l" "-c" + (string-append + "restic-guix backup " #$name " " + #$(string-join + (map (lambda (f) (string-append "'" f "'")) + files) + " "))))) + +(define* (restic-backup-job-requirement requirement #:key (home-service? #f)) + (if home-service? + requirement + (append '(user-processes file-systems) requirement))) + +(define* (restic-backup-job-modules #:key (home-service? #f)) + `((shepherd service timer) + ,@(if home-service? + ;;for %user-log-dir + '((shepherd support)) + '()))) + +(define* (restic-backup-job->shepherd-service config #:key (home-service? #f)) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) - (files (string-join - (map (lambda (f) (string-append "'" f "'")) - (restic-backup-job-files config)) - " ")) + (files (restic-backup-job-files config)) (user (restic-backup-job-user config)) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) (wait-for-termination? (restic-backup-job-wait-for-termination? config)) - (log-file (restic-job-log-file config)) - (requirement (restic-backup-job-requirement config))) + (log-file (restic-backup-job-log-file + config #:home-service? home-service?)) + (requirement + (restic-backup-job-requirement + (restic-backup-job-requirement config) + #:home-service? home-service?))) (shepherd-service (provision `(,(string->symbol name))) - (requirement - `(user-processes file-systems ,@requirement)) + (requirement requirement) (documentation "Run @code{restic} backed backups on a regular basis.") - (modules '((shepherd service timer))) + (modules (restic-backup-job-modules + #:home-service? home-service?)) (start #~(make-timer-constructor (if (string? #$schedule) (cron-string->calendar-event #$schedule) #$schedule) (command - (list - ;; We go through bash, instead of executing - ;; restic-guix directly, because the login shell - ;; gives us the correct user environment that some - ;; backends require, such as rclone. - (string-append #+bash-minimal "/bin/bash") - "-l" "-c" - (string-append - "restic-guix backup " #$name " " #$files)) - #:user #$user - #:group #$group - #:environment-variables - (list - (string-append - "HOME=" (passwd:dir (getpwnam #$user))))) + #$(restic-backup-job-command + name files #:home-service? home-service?) + #$@(if home-service? '() (list #:user user)) + #$@(if home-service? '() (list #:group group)) + #$@(if home-service? '() + (list + #:environment-variables + #~(list + (string-append + "HOME=" (passwd:dir (getpwnam #$user))))))) #:log-file #$log-file #:wait-for-termination? #$wait-for-termination? #:max-duration #$(and (maybe-value-set? max-duration) @@ -329,26 +356,19 @@ (define restic-backup-service-profile (restic-guix-wrapper-package config)) '()))) -(define (restic-backup-service-activation config) - #~(for-each - (lambda (log-file) - (mkdir-p (dirname log-file))) - (list #$@(map restic-job-log-file - (restic-backup-configuration-jobs config))))) - (define restic-backup-service-type (service-type (name 'restic-backup) (extensions (list - (service-extension activation-service-type - restic-backup-service-activation) (service-extension profile-service-type restic-backup-service-profile) (service-extension shepherd-root-service-type - (lambda (config) - (map restic-backup-job->shepherd-service - (restic-backup-configuration-jobs - config)))))) + (match-record-lambda <restic-backup-configuration> + (jobs home-service?) + (map (lambda (job) + (restic-backup-job->shepherd-service + job #:home-service? home-service?)) + jobs))))) (compose concatenate) (extend (lambda (config jobs) base-commit: 18d01434cd56e2fce39362745bb8cb355d3356d9 -- 2.48.1
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Wed, 05 Mar 2025 18:43:02 GMT) Full text and rfc822 format available.Message #37 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Ludovic Courtès <ludo <at> gnu.org> To: Giacomo Leidi <goodoldpaul <at> autistici.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org>, 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Wed, 05 Mar 2025 19:42:19 +0100
Hi, Giacomo Leidi <goodoldpaul <at> autistici.org> skribis: > * gnu/services/backup.scm (restic-backup-configuration): Reimplement > with (guix records); > (restic-backup-job-{logfile,command,requirement,modules}): Add new > procedures and add support for Guix Home environments; > (restic-backup-job->shepherd-service): Add support for Guix Home > environments; > (restic-backup-service-activation): Drop procedure as now the Shepherd > takes care of creating directories for timers logs. > * gnu/home/services/backup.scm: New file. > * gnu/local.mk: Add this. > * doc/guix.texi: Document this. > > Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be Overall LGTM. However the patch no longer applies; could you send an updated patch? Minor comments: > +@node Backup Home Services > +@subsection Backup Home Services The node name is good (it has to be unique), but the subsection name could simply be “Backup Services”. > +@lisp > +(use-modules (gnu services backup) ;for 'restic-backup-job' I would suggest #:re-export’ing the commonly needed bits from (gnu home services backup), to reduce the amount of boilerplate needed, similar to what (gnu home services dict) does, for example. > -(define list-of-restic-backup-jobs? > - (list-of restic-backup-job?)) > +(define-record-type* <restic-backup-configuration> You can add a short comment right above to explain, as you proposed, why ‘define-configuration’ is not used. Thanks, Ludo’.
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Wed, 05 Mar 2025 23:28:01 GMT) Full text and rfc822 format available.Message #40 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: Ludovic Courtès <ludo <at> gnu.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org>, 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Thu, 6 Mar 2025 00:27:34 +0100
[Message part 1 (text/plain, inline)]
Hi, On 3/5/25 19:42, Ludovic Courtès wrote: > Overall LGTM. However the patch no longer applies; could you send an > updated patch? I should have addressed all your comments, if you are trying to apply this directly to master it will probably fail as it depends on issue #72803 revision 8. I'm sending a v5 rebased on revision 8 of 72803. thank you for your help, cheers giacomo
[Message part 2 (text/html, inline)]
andrew <at> trop.in, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Wed, 05 Mar 2025 23:29:02 GMT) Full text and rfc822 format available.Message #43 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v5] home: Add home-restic-backup service. Date: Thu, 6 Mar 2025 00:28:03 +0100
* gnu/services/backup.scm (restic-backup-configuration): Reimplement with (guix records); (restic-backup-job-{logfile,command,requirement,modules}): Add new procedures and add support for Guix Home environments; (restic-backup-job->shepherd-service): Add support for Guix Home environments; (restic-backup-service-activation): Drop procedure as now the Shepherd takes care of creating directories for timers logs. * gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 76 ++++++++++++++++++++++ gnu/home/services/backup.scm | 38 +++++++++++ gnu/local.mk | 1 + gnu/services/backup.scm | 119 +++++++++++++++++++++-------------- 4 files changed, 186 insertions(+), 48 deletions(-) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index e4c5c86e91f..9708bd13646 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -463,6 +463,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -47677,6 +47678,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -49223,6 +49225,80 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Services + +The @code{(gnu home services backup)} module offers services for backing up +file system trees. For now, it provides the @code{home-restic-backup-service-type}. + +With @code{home-restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu home services backup) ;for 'restic-backup-job', 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (simple-service 'backup-jobs + home-restic-backup-service-type + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))) +@end lisp + +In general it is preferrable to extend the @code{home-restic-backup-service-type}, +as shown in the example above. This is because it takes care of wrapping everything +with @code{for-home}, which enables the @code{home-restic-backup-service-type} and +@code{restic-backup-service-type} to share the same codebase. + +For a custom configuration, wrap your @code{restic-backup-configuration} in +@code{for-home}, as in this example: + +@lisp +(use-modules (gnu services) ;for 'for-home' + (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (service home-restic-backup-service-type + (for-home + (restic-backup-configuration + (jobs (list @dots{})))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-backup-job}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-backup-job}. + +It will also install the @command{restic-guix} package to the user's Home +profile. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..ac977f835b6 --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,38 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:export (home-restic-backup-service-type) + #:re-export (restic-backup-configuration + restic-backup-job)) + +(define home-restic-backup-service-type + (service-type + (inherit (system->home-service-type restic-backup-service-type)) + (extend + (lambda (config jobs) + (for-home + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs)))))) + (default-value (for-home (restic-backup-configuration))))) diff --git a/gnu/local.mk b/gnu/local.mk index 997b7344fff..ea93dc904de 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -103,6 +103,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index dc095593432..3c092629774 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -28,6 +28,7 @@ (define-module (gnu services backup) #:prefix license:) #:use-module (guix modules) #:use-module (guix packages) + #:use-module (guix records) #:use-module (srfi srfi-1) #:export (restic-backup-job restic-backup-job? @@ -49,7 +50,6 @@ (define-module (gnu services backup) restic-backup-configuration restic-backup-configuration? - restic-backup-configuration-fields restic-backup-configuration-jobs restic-program @@ -57,7 +57,6 @@ (define-module (gnu services backup) restic-guix restic-guix-wrapper-package restic-backup-service-profile - restic-backup-service-activation restic-backup-service-type)) (define (gexp-or-string? value) @@ -132,13 +131,18 @@ (define-configuration/no-serialization restic-backup-job "A list of values that are lowered to strings. These will be passed as command-line arguments to the current @command{restic} invocation.")) -(define list-of-restic-backup-jobs? - (list-of restic-backup-job?)) +;; (for-home (restic-backup-configuration ...)) is not able to replace for-home? with #t, +;; pk prints #f. Once for-home will be able to work with (gnu services configuration) the +;; record can be migrated back to define-configuration. +(define-record-type* <restic-backup-configuration> + restic-backup-configuration + make-restic-backup-configuration + restic-backup-configuration? + this-restic-backup-configuration -(define-configuration/no-serialization restic-backup-configuration - (jobs - (list-of-restic-backup-jobs '()) - "The list of backup jobs for the current system.")) + (jobs restic-backup-configuration-jobs (default '())) ; list of restic-backup-job + (home-service? restic-backup-configuration-home-service? + (default for-home?) (innate))) (define %restic-guix-supported-actions '("backup" "list" "ls" "mount" "prune" "restore" "snapshots" "unlock")) @@ -244,53 +248,79 @@ (define* (restic-guix config #:key (supported-actions (main (command-line))))) -(define (restic-job-log-file job) +(define* (restic-backup-job-log-file job #:key (home-service? #f)) (let ((name (restic-backup-job-name job)) (log-file (restic-backup-job-log-file job))) (if (maybe-value-set? log-file) log-file - (string-append "/var/log/restic-backup/" name ".log")))) + (if home-service? + #~(begin + (use-modules (shepherd support)) + (string-append %user-log-dir "/restic-backup/" #$name ".log")) + (string-append "/var/log/restic-backup/" name ".log"))))) -(define (restic-backup-job->shepherd-service config) +(define* (restic-backup-job-command name files #:key (home-service? #f)) + (if home-service? + #~(list + "restic-guix" "backup" #$name #$@files) + #~(list + (string-append #+bash-minimal "/bin/bash") + "-l" "-c" + (string-append + "restic-guix backup " #$name " " + #$(string-join + (map (lambda (f) (string-append "'" f "'")) + files) + " "))))) + +(define* (restic-backup-job-requirement requirement #:key (home-service? #f)) + (if home-service? + requirement + (append '(user-processes file-systems) requirement))) + +(define* (restic-backup-job-modules #:key (home-service? #f)) + `((shepherd service timer) + ,@(if home-service? + ;;for %user-log-dir + '((shepherd support)) + '()))) + +(define* (restic-backup-job->shepherd-service config #:key (home-service? #f)) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) - (files (string-join - (map (lambda (f) (string-append "'" f "'")) - (restic-backup-job-files config)) - " ")) + (files (restic-backup-job-files config)) (user (restic-backup-job-user config)) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) (wait-for-termination? (restic-backup-job-wait-for-termination? config)) - (log-file (restic-job-log-file config)) - (requirement (restic-backup-job-requirement config))) + (log-file (restic-backup-job-log-file + config #:home-service? home-service?)) + (requirement + (restic-backup-job-requirement + (restic-backup-job-requirement config) + #:home-service? home-service?))) (shepherd-service (provision `(,(string->symbol name))) - (requirement - `(user-processes file-systems ,@requirement)) + (requirement requirement) (documentation "Run @code{restic} backed backups on a regular basis.") - (modules '((shepherd service timer))) + (modules (restic-backup-job-modules + #:home-service? home-service?)) (start #~(make-timer-constructor (if (string? #$schedule) (cron-string->calendar-event #$schedule) #$schedule) (command - (list - ;; We go through bash, instead of executing - ;; restic-guix directly, because the login shell - ;; gives us the correct user environment that some - ;; backends require, such as rclone. - (string-append #+bash-minimal "/bin/bash") - "-l" "-c" - (string-append - "restic-guix backup " #$name " " #$files)) - #:user #$user - #:group #$group - #:environment-variables - (list - (string-append - "HOME=" (passwd:dir (getpwnam #$user))))) + #$(restic-backup-job-command + name files #:home-service? home-service?) + #$@(if home-service? '() (list #:user user)) + #$@(if home-service? '() (list #:group group)) + #$@(if home-service? '() + (list + #:environment-variables + #~(list + (string-append + "HOME=" (passwd:dir (getpwnam #$user))))))) #:log-file #$log-file #:wait-for-termination? #$wait-for-termination? #:max-duration #$(and (maybe-value-set? max-duration) @@ -329,26 +359,19 @@ (define restic-backup-service-profile (restic-guix-wrapper-package config)) '()))) -(define (restic-backup-service-activation config) - #~(for-each - (lambda (log-file) - (mkdir-p (dirname log-file))) - (list #$@(map restic-job-log-file - (restic-backup-configuration-jobs config))))) - (define restic-backup-service-type (service-type (name 'restic-backup) (extensions (list - (service-extension activation-service-type - restic-backup-service-activation) (service-extension profile-service-type restic-backup-service-profile) (service-extension shepherd-root-service-type - (lambda (config) - (map restic-backup-job->shepherd-service - (restic-backup-configuration-jobs - config)))))) + (match-record-lambda <restic-backup-configuration> + (jobs home-service?) + (map (lambda (job) + (restic-backup-job->shepherd-service + job #:home-service? home-service?)) + jobs))))) (compose concatenate) (extend (lambda (config jobs) base-commit: eacc927e82941220e5d4bd1f8737e7edbe5b712f -- 2.48.1
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Sat, 08 Mar 2025 16:43:02 GMT) Full text and rfc822 format available.Message #46 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Ludovic Courtès <ludo <at> gnu.org> To: Giacomo Leidi <goodoldpaul <at> autistici.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org>, 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Sat, 08 Mar 2025 17:42:20 +0100
Giacomo Leidi <goodoldpaul <at> autistici.org> skribis: > * gnu/services/backup.scm (restic-backup-configuration): Reimplement > with (guix records); > (restic-backup-job-{logfile,command,requirement,modules}): Add new > procedures and add support for Guix Home environments; > (restic-backup-job->shepherd-service): Add support for Guix Home > environments; > (restic-backup-service-activation): Drop procedure as now the Shepherd > takes care of creating directories for timers logs. > * gnu/home/services/backup.scm: New file. > * gnu/local.mk: Add this. > * doc/guix.texi: Document this. > > Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be Hi! It LGTM, but it doesn’t apply on top of a8db2cb547f93f915726eae8ebae7646a4361094: --8<---------------cut here---------------start------------->8--- patching file gnu/services/backup.scm Hunk #2 succeeded at 50 with fuzz 1. Hunk #3 FAILED at 57. Hunk #4 succeeded at 131 with fuzz 2 (offset -1 lines). Hunk #5 FAILED at 249. Hunk #6 FAILED at 334. 3 out of 6 hunks FAILED -- saving rejects to file gnu/services/backup.scm.rej --8<---------------cut here---------------end--------------->8--- Ludo’.
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Sat, 08 Mar 2025 17:41:02 GMT) Full text and rfc822 format available.Message #49 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: Ludovic Courtès <ludo <at> gnu.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org>, 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Sat, 8 Mar 2025 18:39:58 +0100
Hi Ludo’, On 3/8/25 17:42, Ludovic Courtès wrote: > Giacomo Leidi <goodoldpaul <at> autistici.org> skribis: > >> * gnu/services/backup.scm (restic-backup-configuration): Reimplement >> with (guix records); >> (restic-backup-job-{logfile,command,requirement,modules}): Add new >> procedures and add support for Guix Home environments; >> (restic-backup-job->shepherd-service): Add support for Guix Home >> environments; >> (restic-backup-service-activation): Drop procedure as now the Shepherd >> takes care of creating directories for timers logs. >> * gnu/home/services/backup.scm: New file. >> * gnu/local.mk: Add this. >> * doc/guix.texi: Document this. >> >> Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be > Hi! It LGTM, but it doesn’t apply on top of > a8db2cb547f93f915726eae8ebae7646a4361094: It is because this patch depends on changes to the restic-guix command from issue #72803 revision 8, I'm sending a rebased patchset (v6) which will apply on top of current master (be49b0f4435cf1d9275cbbc9cac3a84fa4478ff9) but is additionally including changes from #72803. The dependency is due to the additional features introduced by #72803, which are required in the home service to correctly run backups. Please let me know if I can clarify further, thank you for your work! giacomo
ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Sat, 08 Mar 2025 17:42:02 GMT) Full text and rfc822 format available.Message #52 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v6 1/2] services: restic-backup: Add more restic commands to the restic-guix package. Date: Sat, 8 Mar 2025 18:40:23 +0100
This patch refactors the way restic commands can be added to the restic-guix package with a more general approach. This way new subcommands for restic-guix can be added more easily. * gnu/services/backup.scm (restic-backup-job-program): Generalize to restic-program; (restic-guix): allow for multiple actions. * doc/guix.texi: Document it. Change-Id: Ib2b5d74bebc51e35f1ae6e1aa32cedee0da59697 --- doc/guix.texi | 20 +++++- gnu/services/backup.scm | 138 ++++++++++++++++++++++++++-------------- 2 files changed, 108 insertions(+), 50 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 6529865c090..321c312fa83 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -43798,6 +43798,23 @@ Miscellaneous Services sudo herd trigger remote-ftp @end example +The @code{restic-backup-service-type} installs as well @code{restic-guix} +to the system profile, a @code{restic} utility wrapper that allows for easier +interaction with the Guix configured backup jobs. For example the following +could be used to list all the shapshots available on a given job's repository: + +@example +restic-guix snapshots remote-ftp +@end example + +All arguments passed after the job name will be passed to the underlying +@code{restic} command, together with the @code{extra-flags} field from the +@code{restic-backup-job} record: + +@example +restic-guix restore remote-ftp -t `pwd`/restored -i .config/guix/channels.scm latest +@end example + @c %start of fragment @deftp {Data Type} restic-backup-configuration @@ -43871,8 +43888,7 @@ Miscellaneous Services @item @code{extra-flags} (default: @code{'()}) (type: list-of-lowerables) A list of values that are lowered to strings. These will be passed as -command-line arguments to the current job @command{restic backup} -invocation. +command-line arguments to the current @command{restic} invocation. @end table diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index 4d8cf167f04..dc095593432 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -52,11 +52,12 @@ (define-module (gnu services backup) restic-backup-configuration-fields restic-backup-configuration-jobs - restic-backup-job-program - restic-backup-job->mcron-job + restic-program + restic-backup-job->shepherd-service restic-guix restic-guix-wrapper-package restic-backup-service-profile + restic-backup-service-activation restic-backup-service-type)) (define (gexp-or-string? value) @@ -129,7 +130,7 @@ (define-configuration/no-serialization restic-backup-job (extra-flags (list-of-lowerables '()) "A list of values that are lowered to strings. These will be passed as -command-line arguments to the current job @command{restic backup} invocation.")) +command-line arguments to the current @command{restic} invocation.")) (define list-of-restic-backup-jobs? (list-of restic-backup-job?)) @@ -139,71 +140,107 @@ (define-configuration/no-serialization restic-backup-configuration (list-of-restic-backup-jobs '()) "The list of backup jobs for the current system.")) -(define (restic-backup-job-program config) +(define %restic-guix-supported-actions + '("backup" "list" "ls" "mount" "prune" "restore" "snapshots" "unlock")) + +(define (restic-backup-job->kv config) (let ((restic (file-append (restic-backup-job-restic config) "/bin/restic")) + (name + (restic-backup-job-name config)) (repository (restic-backup-job-repository config)) (password-file (restic-backup-job-password-file config)) - (files - (restic-backup-job-files config)) (extra-flags (restic-backup-job-extra-flags config)) - (verbose + (verbose? (if (restic-backup-job-verbose? config) '("--verbose") '()))) - (program-file - "restic-backup-job.scm" - #~(begin - (use-modules (ice-9 popen) - (ice-9 rdelim)) - (setenv "RESTIC_PASSWORD" - (with-input-from-file #$password-file read-line)) + #~(list #$name (list #$restic #$repository #$password-file + (list #$@verbose?) (list #$@extra-flags))))) + +(define (restic-program config) + #~(lambda* (action action-args job-restic repository password-file verbose? extra-flags) + (use-modules (ice-9 format) + (ice-9 popen) + (ice-9 rdelim)) + ;; This can be extended later, i.e. to have a + ;; centrally defined restic package. + ;; See https://issues.guix.gnu.org/71639 + (define restic job-restic) + + (define command + `(,restic ,@verbose? + "-r" ,repository + ,@extra-flags + ,action ,@action-args)) + + (setenv "RESTIC_PASSWORD" + (with-input-from-file password-file read-line)) - (execlp #$restic #$restic #$@verbose - "-r" #$repository - #$@extra-flags - "backup" #$@files))))) + (when (> (length verbose?) 0) + (format #t "Running~{ ~a~}~%" command)) -(define (restic-guix jobs) + (apply execlp `(,restic ,@command)))) + +(define* (restic-guix config #:key (supported-actions + %restic-guix-supported-actions)) (program-file "restic-guix" #~(begin (use-modules (ice-9 match) (srfi srfi-1)) - (define names '#$(map restic-backup-job-name jobs)) - (define programs '#$(map restic-backup-job-program jobs)) - - (define (get-program name) - (define idx - (list-index (lambda (n) (string=? n name)) names)) - (unless idx - (error (string-append "Unknown job name " name "\n\n" - "Possible job names are: " - (string-join names " ")))) - (list-ref programs idx)) + (define jobs + (list + #$@(map restic-backup-job->kv + (restic-backup-configuration-jobs config)))) + (define names (map first jobs)) + (define (get-job key) + (first + (filter-map + (match-lambda + ((k v) + (and (string=? key k) v))) + jobs))) - (define (backup args) - (define name (third args)) - (define program (get-program name)) - (execlp program program)) + (define restic-exec + #$(restic-program config)) (define (validate-args args) - (when (not (>= (length args) 3)) - (error (string-append "Usage: " (basename (car args)) - " backup NAME")))) + (unless (>= (length args) 2) + (error (string-append "Usage: " (basename (first args)) + " ACTION [ARGS]\n\nSupported actions are: " + #$(string-join supported-actions ", ") "."))) + (unless (member (second args) '#$supported-actions) + (error (string-append "Unknown action: " (second args) ". Supported" + "actions are: " + #$(string-join supported-actions ", ") ".")))) + + (define (validate-action-args action args) + (define argc (length args)) + (when (not (>= argc 3)) + (error (string-append "Usage: " (basename (first args)) + " " action " JOB_NAME [ARGS]\n\nPossible job " + "names are: " (string-join names ", ") "."))) + (define job-name (third args)) + (unless (member job-name names) + (error (string-append "Unknown job name: " job-name ". Possible job " + "names are: " (string-join names ", ") "."))) + (let ((job (get-job job-name)) + (action-args + (if (> argc 3) + (take-right args (- argc 3)) + '()))) + (values job action-args))) (define (main args) (validate-args args) (define action (second args)) - (match action - ("backup" - (backup args)) - (_ - (error (string-append "Unknown action: " action))))) + (define-values (job action-args) (validate-action-args action args)) + (apply restic-exec `(,action ,action-args ,@job))) (main (command-line))))) @@ -217,6 +254,10 @@ (define (restic-job-log-file job) (define (restic-backup-job->shepherd-service config) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) + (files (string-join + (map (lambda (f) (string-append "'" f "'")) + (restic-backup-job-files config)) + " ")) (user (restic-backup-job-user config)) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) @@ -242,7 +283,8 @@ (define (restic-backup-job->shepherd-service config) ;; backends require, such as rclone. (string-append #+bash-minimal "/bin/bash") "-l" "-c" - (string-append "restic-guix backup " #$name)) + (string-append + "restic-guix backup " #$name " " #$files)) #:user #$user #:group #$group #:environment-variables @@ -261,11 +303,11 @@ (define (restic-backup-job->shepherd-service config) without waiting for the scheduled time.") (procedure #~trigger-timer))))))) -(define (restic-guix-wrapper-package jobs) +(define (restic-guix-wrapper-package config) (package (name "restic-backup-service-wrapper") (version "0.0.0") - (source (restic-guix jobs)) + (source (restic-guix config)) (build-system copy-build-system) (arguments (list #:install-plan #~'(("./" "/bin")))) @@ -284,10 +326,10 @@ (define restic-backup-service-profile (define jobs (restic-backup-configuration-jobs config)) (if (> (length jobs) 0) (list - (restic-guix-wrapper-package jobs)) + (restic-guix-wrapper-package config)) '()))) -(define (restic-backup-activation config) +(define (restic-backup-service-activation config) #~(for-each (lambda (log-file) (mkdir-p (dirname log-file))) @@ -299,7 +341,7 @@ (define restic-backup-service-type (extensions (list (service-extension activation-service-type - restic-backup-activation) + restic-backup-service-activation) (service-extension profile-service-type restic-backup-service-profile) (service-extension shepherd-root-service-type base-commit: be49b0f4435cf1d9275cbbc9cac3a84fa4478ff9 -- 2.48.1
andrew <at> trop.in, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Sat, 08 Mar 2025 17:42:03 GMT) Full text and rfc822 format available.Message #55 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v6 2/2] home: Add home-restic-backup service. Date: Sat, 8 Mar 2025 18:40:24 +0100
* gnu/services/backup.scm (restic-backup-configuration): Reimplement with (guix records); (restic-backup-job-{logfile,command,requirement,modules}): Add new procedures and add support for Guix Home environments; (restic-backup-job->shepherd-service): Add support for Guix Home environments; (restic-backup-service-activation): Drop procedure as now the Shepherd takes care of creating directories for timers logs. * gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 76 ++++++++++++++++++++++ gnu/home/services/backup.scm | 38 +++++++++++ gnu/local.mk | 1 + gnu/services/backup.scm | 119 +++++++++++++++++++++-------------- 4 files changed, 186 insertions(+), 48 deletions(-) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index 321c312fa83..a56bfdddea7 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -463,6 +463,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -47766,6 +47767,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -49312,6 +49314,80 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Services + +The @code{(gnu home services backup)} module offers services for backing up +file system trees. For now, it provides the @code{home-restic-backup-service-type}. + +With @code{home-restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu home services backup) ;for 'restic-backup-job', 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (simple-service 'backup-jobs + home-restic-backup-service-type + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))) +@end lisp + +In general it is preferrable to extend the @code{home-restic-backup-service-type}, +as shown in the example above. This is because it takes care of wrapping everything +with @code{for-home}, which enables the @code{home-restic-backup-service-type} and +@code{restic-backup-service-type} to share the same codebase. + +For a custom configuration, wrap your @code{restic-backup-configuration} in +@code{for-home}, as in this example: + +@lisp +(use-modules (gnu services) ;for 'for-home' + (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (service home-restic-backup-service-type + (for-home + (restic-backup-configuration + (jobs (list @dots{})))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-backup-job}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-backup-job}. + +It will also install the @command{restic-guix} package to the user's Home +profile. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..ac977f835b6 --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,38 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:export (home-restic-backup-service-type) + #:re-export (restic-backup-configuration + restic-backup-job)) + +(define home-restic-backup-service-type + (service-type + (inherit (system->home-service-type restic-backup-service-type)) + (extend + (lambda (config jobs) + (for-home + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs)))))) + (default-value (for-home (restic-backup-configuration))))) diff --git a/gnu/local.mk b/gnu/local.mk index be1e32571cf..5a0be62b97f 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -103,6 +103,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index dc095593432..3c092629774 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -28,6 +28,7 @@ (define-module (gnu services backup) #:prefix license:) #:use-module (guix modules) #:use-module (guix packages) + #:use-module (guix records) #:use-module (srfi srfi-1) #:export (restic-backup-job restic-backup-job? @@ -49,7 +50,6 @@ (define-module (gnu services backup) restic-backup-configuration restic-backup-configuration? - restic-backup-configuration-fields restic-backup-configuration-jobs restic-program @@ -57,7 +57,6 @@ (define-module (gnu services backup) restic-guix restic-guix-wrapper-package restic-backup-service-profile - restic-backup-service-activation restic-backup-service-type)) (define (gexp-or-string? value) @@ -132,13 +131,18 @@ (define-configuration/no-serialization restic-backup-job "A list of values that are lowered to strings. These will be passed as command-line arguments to the current @command{restic} invocation.")) -(define list-of-restic-backup-jobs? - (list-of restic-backup-job?)) +;; (for-home (restic-backup-configuration ...)) is not able to replace for-home? with #t, +;; pk prints #f. Once for-home will be able to work with (gnu services configuration) the +;; record can be migrated back to define-configuration. +(define-record-type* <restic-backup-configuration> + restic-backup-configuration + make-restic-backup-configuration + restic-backup-configuration? + this-restic-backup-configuration -(define-configuration/no-serialization restic-backup-configuration - (jobs - (list-of-restic-backup-jobs '()) - "The list of backup jobs for the current system.")) + (jobs restic-backup-configuration-jobs (default '())) ; list of restic-backup-job + (home-service? restic-backup-configuration-home-service? + (default for-home?) (innate))) (define %restic-guix-supported-actions '("backup" "list" "ls" "mount" "prune" "restore" "snapshots" "unlock")) @@ -244,53 +248,79 @@ (define* (restic-guix config #:key (supported-actions (main (command-line))))) -(define (restic-job-log-file job) +(define* (restic-backup-job-log-file job #:key (home-service? #f)) (let ((name (restic-backup-job-name job)) (log-file (restic-backup-job-log-file job))) (if (maybe-value-set? log-file) log-file - (string-append "/var/log/restic-backup/" name ".log")))) + (if home-service? + #~(begin + (use-modules (shepherd support)) + (string-append %user-log-dir "/restic-backup/" #$name ".log")) + (string-append "/var/log/restic-backup/" name ".log"))))) -(define (restic-backup-job->shepherd-service config) +(define* (restic-backup-job-command name files #:key (home-service? #f)) + (if home-service? + #~(list + "restic-guix" "backup" #$name #$@files) + #~(list + (string-append #+bash-minimal "/bin/bash") + "-l" "-c" + (string-append + "restic-guix backup " #$name " " + #$(string-join + (map (lambda (f) (string-append "'" f "'")) + files) + " "))))) + +(define* (restic-backup-job-requirement requirement #:key (home-service? #f)) + (if home-service? + requirement + (append '(user-processes file-systems) requirement))) + +(define* (restic-backup-job-modules #:key (home-service? #f)) + `((shepherd service timer) + ,@(if home-service? + ;;for %user-log-dir + '((shepherd support)) + '()))) + +(define* (restic-backup-job->shepherd-service config #:key (home-service? #f)) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) - (files (string-join - (map (lambda (f) (string-append "'" f "'")) - (restic-backup-job-files config)) - " ")) + (files (restic-backup-job-files config)) (user (restic-backup-job-user config)) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) (wait-for-termination? (restic-backup-job-wait-for-termination? config)) - (log-file (restic-job-log-file config)) - (requirement (restic-backup-job-requirement config))) + (log-file (restic-backup-job-log-file + config #:home-service? home-service?)) + (requirement + (restic-backup-job-requirement + (restic-backup-job-requirement config) + #:home-service? home-service?))) (shepherd-service (provision `(,(string->symbol name))) - (requirement - `(user-processes file-systems ,@requirement)) + (requirement requirement) (documentation "Run @code{restic} backed backups on a regular basis.") - (modules '((shepherd service timer))) + (modules (restic-backup-job-modules + #:home-service? home-service?)) (start #~(make-timer-constructor (if (string? #$schedule) (cron-string->calendar-event #$schedule) #$schedule) (command - (list - ;; We go through bash, instead of executing - ;; restic-guix directly, because the login shell - ;; gives us the correct user environment that some - ;; backends require, such as rclone. - (string-append #+bash-minimal "/bin/bash") - "-l" "-c" - (string-append - "restic-guix backup " #$name " " #$files)) - #:user #$user - #:group #$group - #:environment-variables - (list - (string-append - "HOME=" (passwd:dir (getpwnam #$user))))) + #$(restic-backup-job-command + name files #:home-service? home-service?) + #$@(if home-service? '() (list #:user user)) + #$@(if home-service? '() (list #:group group)) + #$@(if home-service? '() + (list + #:environment-variables + #~(list + (string-append + "HOME=" (passwd:dir (getpwnam #$user))))))) #:log-file #$log-file #:wait-for-termination? #$wait-for-termination? #:max-duration #$(and (maybe-value-set? max-duration) @@ -329,26 +359,19 @@ (define restic-backup-service-profile (restic-guix-wrapper-package config)) '()))) -(define (restic-backup-service-activation config) - #~(for-each - (lambda (log-file) - (mkdir-p (dirname log-file))) - (list #$@(map restic-job-log-file - (restic-backup-configuration-jobs config))))) - (define restic-backup-service-type (service-type (name 'restic-backup) (extensions (list - (service-extension activation-service-type - restic-backup-service-activation) (service-extension profile-service-type restic-backup-service-profile) (service-extension shepherd-root-service-type - (lambda (config) - (map restic-backup-job->shepherd-service - (restic-backup-configuration-jobs - config)))))) + (match-record-lambda <restic-backup-configuration> + (jobs home-service?) + (map (lambda (job) + (restic-backup-job->shepherd-service + job #:home-service? home-service?)) + jobs))))) (compose concatenate) (extend (lambda (config jobs) -- 2.48.1
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Tue, 29 Apr 2025 00:22:02 GMT) Full text and rfc822 format available.Message #58 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Ludovic Courtès <ludo <at> gnu.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org>, Tanguy Le Carrour <tanguy <at> bioneland.org>, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in> Subject: Re: bug#76169: home: Add home-restic-backup service. Date: Tue, 29 Apr 2025 02:21:39 +0200
Hi I'm sending a new revision (v7) base on revision 9 of 72803, which drops the restic-guix packge. Thank you for your help, cheers, giacomo
andrew <at> trop.in, hako <at> ultrarare.space, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Tue, 29 Apr 2025 00:24:02 GMT) Full text and rfc822 format available.Message #61 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v7] home: Add home-restic-backup service. Date: Tue, 29 Apr 2025 02:22:58 +0200
* gnu/services/backup.scm (restic-backup-configuration): Reimplement with (guix records); (restic-backup-job-{logfile,command,requirement,modules}): Add new procedures and add support for Guix Home environments; (restic-backup-job->shepherd-service): Add support for Guix Home environments; (restic-backup-service-activation): Drop procedure as now the Shepherd takes care of creating directories for timers logs. * gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 73 ++++++++++++++++++++++++++ gnu/home/services/backup.scm | 38 ++++++++++++++ gnu/local.mk | 1 + gnu/services/backup.scm | 99 ++++++++++++++++++++++-------------- 4 files changed, 173 insertions(+), 38 deletions(-) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index 7b418a40892..84e2c9f0970 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -463,6 +463,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -48677,6 +48678,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -50267,6 +50269,77 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Services + +The @code{(gnu home services backup)} module offers services for backing up +file system trees. For now, it provides the @code{home-restic-backup-service-type}. + +With @code{home-restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu home services backup) ;for 'restic-backup-job', 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (simple-service 'backup-jobs + home-restic-backup-service-type + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))) +@end lisp + +In general it is preferrable to extend the @code{home-restic-backup-service-type}, +as shown in the example above. This is because it takes care of wrapping everything +with @code{for-home}, which enables the @code{home-restic-backup-service-type} and +@code{restic-backup-service-type} to share the same codebase. + +For a custom configuration, wrap your @code{restic-backup-configuration} in +@code{for-home}, as in this example: + +@lisp +(use-modules (gnu services) ;for 'for-home' + (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (service home-restic-backup-service-type + (for-home + (restic-backup-configuration + (jobs (list @dots{})))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-backup-job}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-backup-job}. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..ac977f835b6 --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,38 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:export (home-restic-backup-service-type) + #:re-export (restic-backup-configuration + restic-backup-job)) + +(define home-restic-backup-service-type + (service-type + (inherit (system->home-service-type restic-backup-service-type)) + (extend + (lambda (config jobs) + (for-home + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs)))))) + (default-value (for-home (restic-backup-configuration))))) diff --git a/gnu/local.mk b/gnu/local.mk index cc57222a91b..b57b9fb4fb7 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -103,6 +103,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index 4fff815e168..3cc199a23bd 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -28,6 +28,7 @@ (define-module (gnu services backup) #:prefix license:) #:use-module (guix modules) #:use-module (guix packages) + #:use-module (guix records) #:use-module (srfi srfi-1) #:export (restic-backup-job restic-backup-job? @@ -51,7 +52,6 @@ (define-module (gnu services backup) restic-backup-configuration restic-backup-configuration? - restic-backup-configuration-fields restic-backup-configuration-jobs restic-program @@ -134,13 +134,18 @@ (define-configuration/no-serialization restic-backup-job "A list of values that are lowered to strings. These will be passed as command-line arguments to the current job @command{restic backup} invocation.")) -(define list-of-restic-backup-jobs? - (list-of restic-backup-job?)) +;; (for-home (restic-backup-configuration ...)) is not able to replace for-home? with #t, +;; pk prints #f. Once for-home will be able to work with (gnu services configuration) the +;; record can be migrated back to define-configuration. +(define-record-type* <restic-backup-configuration> + restic-backup-configuration + make-restic-backup-configuration + restic-backup-configuration? + this-restic-backup-configuration -(define-configuration/no-serialization restic-backup-configuration - (jobs - (list-of-restic-backup-jobs '()) - "The list of backup jobs for the current system.")) + (jobs restic-backup-configuration-jobs (default '())) ; list of restic-backup-job + (home-service? restic-backup-configuration-home-service? + (default for-home?) (innate))) (define (lower-restic-backup-job config) (let ((restic @@ -192,31 +197,41 @@ (define (restic-backup config) (apply restic-exec `("backup" ,@job))))) -(define (restic-backup-job-log-file job) +(define* (restic-backup-job-log-file job #:key (home-service? #f)) (let ((name (restic-backup-job-name job)) (log-file (restic-backup-job-log-file job))) (if (maybe-value-set? log-file) log-file - (string-append "/var/log/restic-backup/" name ".log")))) + (if home-service? + #~(string-append %user-log-dir "/restic-backup/" #$name ".log") + (string-append "/var/log/restic-backup/" name ".log"))))) -(define (restic-backup-job-command config) - ;; We go through bash, instead of executing - ;; restic-guix directly, because the login shell - ;; gives us the correct user environment that some - ;; backends require, such as rclone. - #~(list - (string-append #$bash-minimal "/bin/bash") - "-l" "-c" - (string-join (list #$(restic-backup config)) - " "))) +(define* (restic-backup-job-command config #:key (home-service? #f)) + (if home-service? + ;; Home Shepherd sets the right environment, so no + ;; bash is needed + #~(list #$(restic-backup config)) + ;; We go through bash, instead of executing + ;; restic-guix directly, because the login shell + ;; gives us the correct user environment that some + ;; backends require, such as rclone. + #~(list + (string-append #$bash-minimal "/bin/bash") + "-l" "-c" #$(restic-backup config)))) -(define (restic-backup-job-requirement requirement) - (append '(user-processes file-systems) requirement)) +(define* (restic-backup-job-requirement requirement #:key (home-service? #f)) + (if home-service? + requirement + (append '(user-processes file-systems) requirement))) -(define (restic-backup-job-modules) - `((shepherd service timer))) +(define* (restic-backup-job-modules #:key (home-service? #f)) + `((shepherd service timer) + ,@(if home-service? + ;;for %user-log-dir + '((shepherd support)) + '()))) -(define (restic-backup-job->shepherd-service config) +(define* (restic-backup-job->shepherd-service config #:key (home-service? #f)) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) (files (restic-backup-job-files config)) @@ -224,28 +239,34 @@ (define (restic-backup-job->shepherd-service config) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) (wait-for-termination? (restic-backup-job-wait-for-termination? config)) - (log-file (restic-backup-job-log-file config)) + (log-file (restic-backup-job-log-file + config #:home-service? home-service?)) (requirement (restic-backup-job-requirement - (restic-backup-job-requirement config)))) + (restic-backup-job-requirement config) + #:home-service? home-service?))) (shepherd-service (provision `(,(string->symbol name))) (requirement requirement) (documentation "Run restic backed backups on a regular basis.") - (modules (restic-backup-job-modules)) + (modules (restic-backup-job-modules + #:home-service? home-service?)) (start #~(make-timer-constructor (if (string? #$schedule) (cron-string->calendar-event #$schedule) #$schedule) (command - #$(restic-backup-job-command config) - #:user #$user - #:group #$group - #:environment-variables - (list - (string-append - "HOME=" (passwd:dir (getpwnam #$user))))) + #$(restic-backup-job-command + config #:home-service? home-service?) + #$@(if home-service? '() (list #:user user)) + #$@(if home-service? '() (list #:group group)) + #$@(if home-service? '() + (list + #:environment-variables + #~(list + (string-append + "HOME=" (passwd:dir (getpwnam #$user))))))) #:log-file #$log-file #:wait-for-termination? #$wait-for-termination? #:max-duration #$(and (maybe-value-set? max-duration) @@ -263,10 +284,12 @@ (define restic-backup-service-type (extensions (list (service-extension shepherd-root-service-type - (lambda (config) - (map restic-backup-job->shepherd-service - (restic-backup-configuration-jobs - config)))))) + (match-record-lambda <restic-backup-configuration> + (jobs home-service?) + (map (lambda (job) + (restic-backup-job->shepherd-service + job #:home-service? home-service?)) + jobs))))) (compose concatenate) (extend (lambda (config jobs) base-commit: 25dac960ce99c32cf53cdf010351b7355f072fa1 -- 2.49.0
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Tue, 06 May 2025 10:31:04 GMT) Full text and rfc822 format available.Message #64 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Ludovic Courtès <ludo <at> gnu.org> To: Giacomo Leidi <goodoldpaul <at> autistici.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in>, Hilton Chain <hako <at> ultrarare.space>, 76169 <at> debbugs.gnu.org, Janneke Nieuwenhuizen <janneke <at> gnu.org> Subject: Re: [bug#76169] [PATCH v7] home: Add home-restic-backup service. Date: Tue, 06 May 2025 11:50:25 +0200
Hi Giacomo, Giacomo Leidi <goodoldpaul <at> autistici.org> writes: > * gnu/services/backup.scm (restic-backup-configuration): Reimplement > with (guix records); > (restic-backup-job-{logfile,command,requirement,modules}): Add new > procedures and add support for Guix Home environments; > (restic-backup-job->shepherd-service): Add support for Guix Home > environments; > (restic-backup-service-activation): Drop procedure as now the Shepherd > takes care of creating directories for timers logs. > * gnu/home/services/backup.scm: New file. > * gnu/local.mk: Add this. > * doc/guix.texi: Document this. > > Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be This patch doesn’t want to be applied: it’s not applicable on top of eab097c682ed31efd8668f46fce8de8f73b92849. I don’t know, what should we do? :-) Thanks, Ludo’.
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Wed, 07 May 2025 00:29:01 GMT) Full text and rfc822 format available.Message #67 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: Ludovic Courtès <ludo <at> gnu.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Andrew Tropin <andrew <at> trop.in>, Hilton Chain <hako <at> ultrarare.space>, 76169 <at> debbugs.gnu.org, Janneke Nieuwenhuizen <janneke <at> gnu.org> Subject: Re: [bug#76169] [PATCH v7] home: Add home-restic-backup service. Date: Wed, 7 May 2025 02:28:00 +0200
Hi Ludo’ , Next revision (v8) should apply to master (currently is ec95c71c01144fcae1a3d079e0d0aec6087b9d2a). cheers, giacomo
andrew <at> trop.in, gabriel <at> erlikon.ch, hako <at> ultrarare.space, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Wed, 07 May 2025 00:29:02 GMT) Full text and rfc822 format available.Message #70 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v8] home: Add home-restic-backup service. Date: Wed, 7 May 2025 02:28:22 +0200
* gnu/services/backup.scm: Drop mcron obsolete export. (restic-backup-job-program): Generalize to restic-program. (lower-restic-backup-job): New procedure implementing a standard way to lower restic-backup-job records into lists. (restic-program): Implement general way to run restic commands, for example to initialize repositories. (restic-backup-configuration): Reimplement with (guix records). (restic-backup-job-{logfile,command,requirement,modules}): Add new procedures and add support for Guix Home environments. (restic-backup-job->shepherd-service): Add support for Guix Home environments. (restic-backup-service-activation): Drop procedure as now the Shepherd takes care of creating timers log file directories. (restic-backup-service-type): Drop profile and activation services extensions. * gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 82 ++++++++++++++- gnu/home/services/backup.scm | 38 +++++++ gnu/local.mk | 1 + gnu/services/backup.scm | 189 +++++++++++++++++++++++------------ 4 files changed, 245 insertions(+), 65 deletions(-) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index 889eab2ab35..c8d56678e39 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -465,6 +465,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -44788,7 +44789,8 @@ Miscellaneous Services @item @code{log-file} (type: maybe-string) The file system path to the log file for this job. By default the file will have be @file{/var/log/restic-backup/@var{job-name}.log}, where @var{job-name} is the -name defined in the @code{name} field. +name defined in the @code{name} field. For Guix Home services it defaults to +@file{$XDG_STATE_HOME/shepherd/restic-backup/@var{job-name}.log}. @item @code{max-duration} (type: maybe-number) The maximum duration in seconds that a job may last. Past @@ -44815,8 +44817,10 @@ Miscellaneous Services evaluate to @code{calendar-event} records or to strings. Strings must contain Vixie cron date lines. -@item @code{requirement} (default: @code{'()}) (type: list-of-symbols) -The list of Shepherd services that this backup job depends upon. +@item @code{requirement} (type: maybe-list-of-symbols) +The list of Shepherd services that this backup job depends upon. When unset it +defaults to @code{'()}, for Guix Home. Otherwise to +@code{'(user-processes file-systems)}. @item @code{files} (default: @code{'()}) (type: list-of-lowerables) The list of files or directories to be backed up. It must be a list of @@ -48717,6 +48721,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -50307,6 +50312,77 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Services + +The @code{(gnu home services backup)} module offers services for backing up +file system trees. For now, it provides the @code{home-restic-backup-service-type}. + +With @code{home-restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu home services backup) ;for 'restic-backup-job', 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (simple-service 'backup-jobs + home-restic-backup-service-type + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))) +@end lisp + +In general it is preferrable to extend the @code{home-restic-backup-service-type}, +as shown in the example above. This is because it takes care of wrapping everything +with @code{for-home}, which enables the @code{home-restic-backup-service-type} and +@code{restic-backup-service-type} to share the same codebase. + +For a custom configuration, wrap your @code{restic-backup-configuration} in +@code{for-home}, as in this example: + +@lisp +(use-modules (gnu services) ;for 'for-home' + (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (service home-restic-backup-service-type + (for-home + (restic-backup-configuration + (jobs (list @dots{})))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-backup-job}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-backup-job}. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..ac977f835b6 --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,38 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:export (home-restic-backup-service-type) + #:re-export (restic-backup-configuration + restic-backup-job)) + +(define home-restic-backup-service-type + (service-type + (inherit (system->home-service-type restic-backup-service-type)) + (extend + (lambda (config jobs) + (for-home + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs)))))) + (default-value (for-home (restic-backup-configuration))))) diff --git a/gnu/local.mk b/gnu/local.mk index e6ece8cc483..3d4316454a8 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -103,6 +103,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index 6e066bd3d66..06f68302682 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -28,6 +28,7 @@ (define-module (gnu services backup) #:prefix license:) #:use-module (guix modules) #:use-module (guix packages) + #:use-module (guix records) #:use-module (srfi srfi-1) #:export (restic-backup-job restic-backup-job? @@ -47,16 +48,21 @@ (define-module (gnu services backup) restic-backup-job-verbose? restic-backup-job-extra-flags + lower-restic-backup-job + restic-backup-configuration restic-backup-configuration? - restic-backup-configuration-fields restic-backup-configuration-jobs restic-backup-job-program - restic-backup-job->mcron-job + restic-backup-job->shepherd-service restic-guix restic-guix-wrapper-package restic-backup-service-profile + restic-program + restic-job-log-file + restic-backup-job-command + restic-backup-job-modules restic-backup-service-type)) (define (gexp-or-string? value) @@ -75,6 +81,7 @@ (define list-of-symbols? (define-maybe/no-serialization string) (define-maybe/no-serialization number) +(define-maybe/no-serialization symbol) (define-configuration/no-serialization restic-backup-job (restic @@ -90,7 +97,8 @@ (define-configuration/no-serialization restic-backup-job (maybe-string) "The file system path to the log file for this job. By default the file will have be @file{/var/log/restic-backup/@var{job-name}.log}, where @var{job-name} is the -name defined in the @code{name} field.") +name defined in the @code{name} field. For Guix Home services it defaults to +@file{$XDG_STATE_HOME/shepherd/restic-backup/@var{job-name}.log}.") (max-duration (maybe-number) "The maximum duration in seconds that a job may last. Past @@ -117,8 +125,10 @@ (define-configuration/no-serialization restic-backup-job evaluate to @code{calendar-event} records or to strings. Strings must contain Vixie cron date lines.") (requirement - (list-of-symbols '()) - "The list of Shepherd services that this backup job depends upon.") + (maybe-list-of-symbols) + "The list of Shepherd services that this backup job depends upon. When unset it +defaults to @code{'()}, for Guix Home. Otherwise to +@code{'(user-processes file-systems)}.") (files (list-of-lowerables '()) "The list of files or directories to be backed up. It must be a list of @@ -131,15 +141,20 @@ (define-configuration/no-serialization restic-backup-job "A list of values that are lowered to strings. These will be passed as command-line arguments to the current job @command{restic backup} invocation.")) -(define list-of-restic-backup-jobs? - (list-of restic-backup-job?)) +;; (for-home (restic-backup-configuration ...)) is not able to replace for-home? with #t, +;; pk prints #f. Once for-home will be able to work with (gnu services configuration) the +;; record can be migrated back to define-configuration. +(define-record-type* <restic-backup-configuration> + restic-backup-configuration + make-restic-backup-configuration + restic-backup-configuration? + this-restic-backup-configuration -(define-configuration/no-serialization restic-backup-configuration - (jobs - (list-of-restic-backup-jobs '()) - "The list of backup jobs for the current system.")) + (jobs restic-backup-configuration-jobs (default '())) ; list of restic-backup-job + (home-service? restic-backup-configuration-home-service? + (default for-home?) (innate))) -(define (restic-backup-job-program config) +(define (lower-restic-backup-job config) (let ((restic (file-append (restic-backup-job-restic config) "/bin/restic")) (repository @@ -150,22 +165,42 @@ (define (restic-backup-job-program config) (restic-backup-job-files config)) (extra-flags (restic-backup-job-extra-flags config)) - (verbose + (verbose? (if (restic-backup-job-verbose? config) '("--verbose") '()))) - (program-file - "restic-backup-job.scm" - #~(begin - (use-modules (ice-9 popen) - (ice-9 rdelim)) - (setenv "RESTIC_PASSWORD" - (with-input-from-file #$password-file read-line)) - - (execlp #$restic #$restic #$@verbose - "-r" #$repository - #$@extra-flags - "backup" #$@files))))) + #~(list (list #$@files) #$restic #$repository #$password-file + (list #$@verbose?) (list #$@extra-flags)))) + +(define restic-program + #~(lambda (action action-args job-restic repository password-file verbose? extra-flags) + (use-modules (ice-9 format)) + ;; This can be extended later, i.e. to have a + ;; centrally defined restic package. + ;; See https://issues.guix.gnu.org/71639 + (define restic job-restic) + + (define command + `(,restic ,@verbose? + "-r" ,repository + ,@extra-flags + ,action ,@action-args)) + + (setenv "RESTIC_PASSWORD_FILE" password-file) + + (when (> (length verbose?) 0) + (format #t "Running~{ ~a~}~%" command)) + + (apply execlp `(,restic ,@command)))) + +(define (restic-backup-job-program config) + (program-file + "restic-backup" + #~(let ((restic-exec + #$restic-program) + (job #$(lower-restic-backup-job config))) + + (apply restic-exec `("backup" ,@job))))) (define (restic-guix jobs) (program-file @@ -207,55 +242,92 @@ (define (restic-guix jobs) (main (command-line))))) -(define (restic-job-log-file job) +(define* (restic-job-log-file job #:key (home-service? #f)) (let ((name (restic-backup-job-name job)) (log-file (restic-backup-job-log-file job))) (if (maybe-value-set? log-file) log-file - (string-append "/var/log/restic-backup/" name ".log")))) + (if home-service? + #~(begin + (use-modules (shepherd support)) + (string-append %user-log-dir "/restic-backup/" #$name ".log")) + (string-append "/var/log/restic-backup/" name ".log"))))) + +(define* (restic-backup-job-command name files #:key (home-service? #f)) + (if home-service? + #~(list + "restic-guix" "backup" #$name) + ;; We go through bash, instead of executing + ;; restic-guix directly, because the login shell + ;; gives us the correct user environment that some + ;; backends require, such as rclone. + #~(list + (string-append #$bash-minimal "/bin/bash") + "-l" "-c" + (string-append "restic-guix backup " #$name)))) -(define (restic-backup-job->shepherd-service config) +(define (restic-backup-job-modules) + `((shepherd service timer))) + +(define* (restic-job-requirement config #:key (home-service? #f)) + (define maybe-requirement (restic-backup-job-requirement config)) + (if (maybe-value-set? maybe-requirement) + maybe-requirement + (if home-service? + '() + '(user-processes file-systems)))) + +(define* (restic-backup-job-modules #:key (home-service? #f)) + `((shepherd service timer) + ,@(if home-service? + ;;for %user-log-dir + '((shepherd support)) + '()))) + +(define* (restic-backup-job->shepherd-service config #:key (home-service? #f)) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) + (files (restic-backup-job-files config)) (user (restic-backup-job-user config)) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) (wait-for-termination? (restic-backup-job-wait-for-termination? config)) - (log-file (restic-job-log-file config)) - (requirement (restic-backup-job-requirement config))) + (log-file (restic-job-log-file + config #:home-service? home-service?)) + (requirement + (restic-job-requirement config #:home-service? home-service?))) (shepherd-service (provision `(,(string->symbol name))) - (requirement - `(user-processes file-systems ,@requirement)) + (requirement requirement) (documentation - "Run @code{restic} backed backups on a regular basis.") - (modules '((shepherd service timer))) + "Run restic backed backups on a regular basis.") + (modules (restic-backup-job-modules + #:home-service? home-service?)) (start #~(make-timer-constructor (if (string? #$schedule) (cron-string->calendar-event #$schedule) #$schedule) (command - (list - ;; We go through bash, instead of executing - ;; restic-guix directly, because the login shell - ;; gives us the correct user environment that some - ;; backends require, such as rclone. - (string-append #+bash-minimal "/bin/bash") - "-l" "-c" - (string-append "restic-guix backup " #$name)) - #:user #$user - #:group #$group - #:environment-variables - (list - (string-append - "HOME=" (passwd:dir (getpwnam #$user))))) + #$(restic-backup-job-command + name files #:home-service? home-service?) + #$@(if home-service? '() (list #:user user)) + #$@(if home-service? '() (list #:group group)) + #$@(if home-service? '() + (list + #:environment-variables + #~(list + (string-append + "HOME=" (passwd:dir (getpwnam #$user))))))) #:log-file #$log-file #:wait-for-termination? #$wait-for-termination? #:max-duration #$(and (maybe-value-set? max-duration) max-duration))) (stop #~(make-timer-destructor)) - (actions (list shepherd-trigger-action))))) + (actions (list (shepherd-action + (inherit shepherd-trigger-action) + (documentation "Manually trigger a backup, +without waiting for the scheduled time."))))))) (define (restic-guix-wrapper-package jobs) (package @@ -283,26 +355,19 @@ (define restic-backup-service-profile (restic-guix-wrapper-package jobs)) '()))) -(define (restic-backup-activation config) - #~(for-each - (lambda (log-file) - (mkdir-p (dirname log-file))) - (list #$@(map restic-job-log-file - (restic-backup-configuration-jobs config))))) - (define restic-backup-service-type (service-type (name 'restic-backup) (extensions (list - (service-extension activation-service-type - restic-backup-activation) (service-extension profile-service-type restic-backup-service-profile) (service-extension shepherd-root-service-type - (lambda (config) - (map restic-backup-job->shepherd-service - (restic-backup-configuration-jobs - config)))))) + (match-record-lambda <restic-backup-configuration> + (jobs home-service?) + (map (lambda (job) + (restic-backup-job->shepherd-service + job #:home-service? home-service?)) + jobs))))) (compose concatenate) (extend (lambda (config jobs) base-commit: ec95c71c01144fcae1a3d079e0d0aec6087b9d2a -- 2.49.0
guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Mon, 12 May 2025 07:08:02 GMT) Full text and rfc822 format available.Message #73 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Ludovic Courtès <ludo <at> gnu.org> To: Giacomo Leidi <goodoldpaul <at> autistici.org> Cc: 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Gabriel Wicki <gabriel <at> erlikon.ch>, Andrew Tropin <andrew <at> trop.in>, Hilton Chain <hako <at> ultrarare.space>, Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org> Subject: Re: [bug#76169] [PATCH v8] home: Add home-restic-backup service. Date: Mon, 12 May 2025 08:53:38 +0200
Hi, Giacomo Leidi <goodoldpaul <at> autistici.org> writes: > * gnu/services/backup.scm: Drop mcron obsolete export. > (restic-backup-job-program): Generalize to restic-program. > (lower-restic-backup-job): New procedure implementing a standard way to > lower restic-backup-job records into lists. > (restic-program): Implement general way to run restic commands, for > example to initialize repositories. > (restic-backup-configuration): Reimplement > with (guix records). > (restic-backup-job-{logfile,command,requirement,modules}): Add new > procedures and add support for Guix Home environments. > (restic-backup-job->shepherd-service): Add support for Guix Home > environments. > (restic-backup-service-activation): Drop procedure as now the Shepherd > takes care of creating timers log file directories. > (restic-backup-service-type): Drop profile and activation services extensions. > * gnu/home/services/backup.scm: New file. > * gnu/local.mk: Add this. > * doc/guix.texi: Document this. > > Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be We must be getting closer, but… --8<---------------cut here---------------start------------->8--- [ 94%] LOAD gnu/home/services/backup.scm ;;; note: source file ./gnu/services/backup.scm ;;; newer than compiled /home/ludo/src/guix/gnu/services/backup.go ;;; note: source file ./gnu/services/backup.scm ;;; newer than compiled /home/ludo/src/guix/gnu/services/backup.go ice-9/eval.scm:293:34: error: maybe-list-of-symbols?: unbound variable [1;36mhint: [0mDid you forget a `use-modules' form? make[2]: *** [Makefile:7696: make-system-go] Error 1 --8<---------------cut here---------------end--------------->8--- Could you take a look? Ludo’.
Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
to control <at> debbugs.gnu.org
.
(Thu, 15 May 2025 00:40:02 GMT) Full text and rfc822 format available.guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Sat, 17 May 2025 15:10:01 GMT) Full text and rfc822 format available.Message #78 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: paul <goodoldpaul <at> autistici.org> To: Ludovic Courtès <ludo <at> gnu.org> Cc: 76169 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Gabriel Wicki <gabriel <at> erlikon.ch>, Andrew Tropin <andrew <at> trop.in>, Hilton Chain <hako <at> ultrarare.space>, Tanguy Le Carrour <tanguy <at> bioneland.org>, Janneke Nieuwenhuizen <janneke <at> gnu.org> Subject: Re: [bug#76169] home: Add home-restic-backup service. Date: Sat, 17 May 2025 17:09:20 +0200
Sorry I've been copy-pasting code manually and forgot some :/ v9 should build fine. thank you for your help. cheers, giacomo
andrew <at> trop.in, gabriel <at> erlikon.ch, hako <at> ultrarare.space, janneke <at> gnu.org, ludo <at> gnu.org, maxim.cournoyer <at> gmail.com, tanguy <at> bioneland.org, guix-patches <at> gnu.org
:bug#76169
; Package guix-patches
.
(Sat, 17 May 2025 15:11:02 GMT) Full text and rfc822 format available.Message #81 received at 76169 <at> debbugs.gnu.org (full text, mbox):
From: Giacomo Leidi <goodoldpaul <at> autistici.org> To: 76169 <at> debbugs.gnu.org Cc: Giacomo Leidi <goodoldpaul <at> autistici.org> Subject: [PATCH v9] home: Add home-restic-backup service. Date: Sat, 17 May 2025 17:09:54 +0200
* gnu/services/backup.scm: Drop mcron obsolete export. (restic-backup-job-program): Generalize to restic-program. (lower-restic-backup-job): New procedure implementing a standard way to lower restic-backup-job records into lists. (restic-program): Implement general way to run restic commands, for example to initialize repositories. (restic-backup-configuration): Reimplement with (guix records). (restic-backup-job-{logfile,command,requirement,modules}): Add new procedures and add support for Guix Home environments. (restic-backup-job->shepherd-service): Add support for Guix Home environments. (restic-backup-service-activation): Drop procedure as now the Shepherd takes care of creating timers log file directories. (restic-backup-service-type): Drop profile and activation services extensions. * gnu/home/services/backup.scm: New file. * gnu/local.mk: Add this. * doc/guix.texi: Document this. Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be --- doc/guix.texi | 82 ++++++++++++++- gnu/home/services/backup.scm | 38 +++++++ gnu/local.mk | 1 + gnu/services/backup.scm | 187 +++++++++++++++++++++++------------ 4 files changed, 243 insertions(+), 65 deletions(-) create mode 100644 gnu/home/services/backup.scm diff --git a/doc/guix.texi b/doc/guix.texi index 8e73685a216..98a9ed573aa 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -466,6 +466,7 @@ Top * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -44895,7 +44896,8 @@ Miscellaneous Services @item @code{log-file} (type: maybe-string) The file system path to the log file for this job. By default the file will have be @file{/var/log/restic-backup/@var{job-name}.log}, where @var{job-name} is the -name defined in the @code{name} field. +name defined in the @code{name} field. For Guix Home services it defaults to +@file{$XDG_STATE_HOME/shepherd/restic-backup/@var{job-name}.log}. @item @code{max-duration} (type: maybe-number) The maximum duration in seconds that a job may last. Past @@ -44922,8 +44924,10 @@ Miscellaneous Services evaluate to @code{calendar-event} records or to strings. Strings must contain Vixie cron date lines. -@item @code{requirement} (default: @code{'()}) (type: list-of-symbols) -The list of Shepherd services that this backup job depends upon. +@item @code{requirement} (type: maybe-list-of-symbols) +The list of Shepherd services that this backup job depends upon. When unset it +defaults to @code{'()}, for Guix Home. Otherwise to +@code{'(user-processes file-systems)}. @item @code{files} (default: @code{'()}) (type: list-of-lowerables) The list of files or directories to be backed up. It must be a list of @@ -48824,6 +48828,7 @@ Home Services * GPG: GNU Privacy Guard. Setting up GPG and related tools. * Desktop: Desktop Home Services. Services for graphical environments. * Guix: Guix Home Services. Services for Guix. +* Backup: Backup Home Services. Services for backing up User's files. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. * Mail: Mail Home Services. Services for managing mail. @@ -50414,6 +50419,77 @@ Guix Home Services @end lisp @end defvar +@node Backup Home Services +@subsection Backup Services + +The @code{(gnu home services backup)} module offers services for backing up +file system trees. For now, it provides the @code{home-restic-backup-service-type}. + +With @code{home-restic-backup-service-type}, you can periodically back up +directories and files with @uref{https://restic.net/, Restic}, which +supports end-to-end encryption and deduplication. Consider the +following configuration: + +@lisp +(use-modules (gnu home services backup) ;for 'restic-backup-job', 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (simple-service 'backup-jobs + home-restic-backup-service-type + (list (restic-backup-job + (name "remote-ftp") + (repository "rclone:remote-ftp:backup/restic") + (password-file "/home/alice/.restic") + ;; Every day at 23. + (schedule "0 23 * * *") + (files '("/home/alice/.restic" + "/home/alice/.config/rclone" + "/home/alice/Pictures")))))))) +@end lisp + +In general it is preferrable to extend the @code{home-restic-backup-service-type}, +as shown in the example above. This is because it takes care of wrapping everything +with @code{for-home}, which enables the @code{home-restic-backup-service-type} and +@code{restic-backup-service-type} to share the same codebase. + +For a custom configuration, wrap your @code{restic-backup-configuration} in +@code{for-home}, as in this example: + +@lisp +(use-modules (gnu services) ;for 'for-home' + (gnu services backup) ;for 'restic-backup-job' and 'restic-backup-configuration' + (gnu home services backup) ;for 'home-restic-backup-service-type' + (gnu packages sync) ;for 'rclone' + @dots{}) + +(home-environment + + (packages (list rclone ;for use by restic + @dots{})) + (services + (list + @dots{} + (service home-restic-backup-service-type + (for-home + (restic-backup-configuration + (jobs (list @dots{})))))))) +@end lisp + +You can refer to @pxref{Miscellaneous Services, +@code{restic-backup-service-type}} for details about +@code{restic-backup-configuration} and @code{restic-backup-job}. +The only difference is that the @code{home-restic-backup-service-type} +will ignore the @code{user} and @code{group} field of +@code{restic-backup-job}. + @node Fonts Home Services @subsection Fonts Home Services diff --git a/gnu/home/services/backup.scm b/gnu/home/services/backup.scm new file mode 100644 index 00000000000..ac977f835b6 --- /dev/null +++ b/gnu/home/services/backup.scm @@ -0,0 +1,38 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2025 Giacomo Leidi <goodoldpaul <at> autistici.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services backup) + #:use-module (gnu services) + #:use-module (gnu services backup) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:export (home-restic-backup-service-type) + #:re-export (restic-backup-configuration + restic-backup-job)) + +(define home-restic-backup-service-type + (service-type + (inherit (system->home-service-type restic-backup-service-type)) + (extend + (lambda (config jobs) + (for-home + (restic-backup-configuration + (inherit config) + (jobs (append (restic-backup-configuration-jobs config) + jobs)))))) + (default-value (for-home (restic-backup-configuration))))) diff --git a/gnu/local.mk b/gnu/local.mk index dfafe8b8953..7311c33f0f6 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -103,6 +103,7 @@ GNU_SYSTEM_MODULES = \ %D%/home.scm \ %D%/home/services.scm \ %D%/home/services/admin.scm \ + %D%/home/services/backup.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ %D%/home/services/dotfiles.scm \ diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm index 6e066bd3d66..8fdf9ce902f 100644 --- a/gnu/services/backup.scm +++ b/gnu/services/backup.scm @@ -28,6 +28,7 @@ (define-module (gnu services backup) #:prefix license:) #:use-module (guix modules) #:use-module (guix packages) + #:use-module (guix records) #:use-module (srfi srfi-1) #:export (restic-backup-job restic-backup-job? @@ -47,16 +48,21 @@ (define-module (gnu services backup) restic-backup-job-verbose? restic-backup-job-extra-flags + lower-restic-backup-job + restic-backup-configuration restic-backup-configuration? - restic-backup-configuration-fields restic-backup-configuration-jobs restic-backup-job-program - restic-backup-job->mcron-job + restic-backup-job->shepherd-service restic-guix restic-guix-wrapper-package restic-backup-service-profile + restic-program + restic-job-log-file + restic-backup-job-command + restic-backup-job-modules restic-backup-service-type)) (define (gexp-or-string? value) @@ -75,6 +81,8 @@ (define list-of-symbols? (define-maybe/no-serialization string) (define-maybe/no-serialization number) +(define-maybe/no-serialization symbol) +(define-maybe/no-serialization list-of-symbols) (define-configuration/no-serialization restic-backup-job (restic @@ -90,7 +98,8 @@ (define-configuration/no-serialization restic-backup-job (maybe-string) "The file system path to the log file for this job. By default the file will have be @file{/var/log/restic-backup/@var{job-name}.log}, where @var{job-name} is the -name defined in the @code{name} field.") +name defined in the @code{name} field. For Guix Home services it defaults to +@file{$XDG_STATE_HOME/shepherd/restic-backup/@var{job-name}.log}.") (max-duration (maybe-number) "The maximum duration in seconds that a job may last. Past @@ -117,8 +126,10 @@ (define-configuration/no-serialization restic-backup-job evaluate to @code{calendar-event} records or to strings. Strings must contain Vixie cron date lines.") (requirement - (list-of-symbols '()) - "The list of Shepherd services that this backup job depends upon.") + (maybe-list-of-symbols) + "The list of Shepherd services that this backup job depends upon. When unset it +defaults to @code{'()}, for Guix Home. Otherwise to +@code{'(user-processes file-systems)}.") (files (list-of-lowerables '()) "The list of files or directories to be backed up. It must be a list of @@ -131,15 +142,20 @@ (define-configuration/no-serialization restic-backup-job "A list of values that are lowered to strings. These will be passed as command-line arguments to the current job @command{restic backup} invocation.")) -(define list-of-restic-backup-jobs? - (list-of restic-backup-job?)) +;; (for-home (restic-backup-configuration ...)) is not able to replace for-home? with #t, +;; pk prints #f. Once for-home will be able to work with (gnu services configuration) the +;; record can be migrated back to define-configuration. +(define-record-type* <restic-backup-configuration> + restic-backup-configuration + make-restic-backup-configuration + restic-backup-configuration? + this-restic-backup-configuration -(define-configuration/no-serialization restic-backup-configuration - (jobs - (list-of-restic-backup-jobs '()) - "The list of backup jobs for the current system.")) + (jobs restic-backup-configuration-jobs (default '())) ; list of restic-backup-job + (home-service? restic-backup-configuration-home-service? + (default for-home?) (innate))) -(define (restic-backup-job-program config) +(define (lower-restic-backup-job config) (let ((restic (file-append (restic-backup-job-restic config) "/bin/restic")) (repository @@ -150,22 +166,42 @@ (define (restic-backup-job-program config) (restic-backup-job-files config)) (extra-flags (restic-backup-job-extra-flags config)) - (verbose + (verbose? (if (restic-backup-job-verbose? config) '("--verbose") '()))) - (program-file - "restic-backup-job.scm" - #~(begin - (use-modules (ice-9 popen) - (ice-9 rdelim)) - (setenv "RESTIC_PASSWORD" - (with-input-from-file #$password-file read-line)) - - (execlp #$restic #$restic #$@verbose - "-r" #$repository - #$@extra-flags - "backup" #$@files))))) + #~(list (list #$@files) #$restic #$repository #$password-file + (list #$@verbose?) (list #$@extra-flags)))) + +(define restic-program + #~(lambda (action action-args job-restic repository password-file verbose? extra-flags) + (use-modules (ice-9 format)) + ;; This can be extended later, i.e. to have a + ;; centrally defined restic package. + ;; See https://issues.guix.gnu.org/71639 + (define restic job-restic) + + (define command + `(,restic ,@verbose? + "-r" ,repository + ,@extra-flags + ,action ,@action-args)) + + (setenv "RESTIC_PASSWORD_FILE" password-file) + + (when (> (length verbose?) 0) + (format #t "Running~{ ~a~}~%" command)) + + (apply execlp `(,restic ,@command)))) + +(define (restic-backup-job-program config) + (program-file + "restic-backup" + #~(let ((restic-exec + #$restic-program) + (job #$(lower-restic-backup-job config))) + + (apply restic-exec `("backup" ,@job))))) (define (restic-guix jobs) (program-file @@ -207,55 +243,89 @@ (define (restic-guix jobs) (main (command-line))))) -(define (restic-job-log-file job) +(define* (restic-job-log-file job #:key (home-service? #f)) (let ((name (restic-backup-job-name job)) (log-file (restic-backup-job-log-file job))) (if (maybe-value-set? log-file) log-file - (string-append "/var/log/restic-backup/" name ".log")))) + (if home-service? + #~(begin + (use-modules (shepherd support)) + (string-append %user-log-dir "/restic-backup/" #$name ".log")) + (string-append "/var/log/restic-backup/" name ".log"))))) + +(define* (restic-backup-job-command name files #:key (home-service? #f)) + (if home-service? + #~(list + "restic-guix" "backup" #$name) + ;; We go through bash, instead of executing + ;; restic-guix directly, because the login shell + ;; gives us the correct user environment that some + ;; backends require, such as rclone. + #~(list + (string-append #$bash-minimal "/bin/bash") + "-l" "-c" + (string-append "restic-guix backup " #$name)))) -(define (restic-backup-job->shepherd-service config) +(define* (restic-job-requirement config #:key (home-service? #f)) + (define maybe-requirement (restic-backup-job-requirement config)) + (if (maybe-value-set? maybe-requirement) + maybe-requirement + (if home-service? + '() + '(user-processes file-systems)))) + +(define* (restic-backup-job-modules #:key (home-service? #f)) + `((shepherd service timer) + ,@(if home-service? + ;;for %user-log-dir + '((shepherd support)) + '()))) + +(define* (restic-backup-job->shepherd-service config #:key (home-service? #f)) (let ((schedule (restic-backup-job-schedule config)) (name (restic-backup-job-name config)) + (files (restic-backup-job-files config)) (user (restic-backup-job-user config)) (group (restic-backup-job-group config)) (max-duration (restic-backup-job-max-duration config)) (wait-for-termination? (restic-backup-job-wait-for-termination? config)) - (log-file (restic-job-log-file config)) - (requirement (restic-backup-job-requirement config))) + (log-file (restic-job-log-file + config #:home-service? home-service?)) + (requirement + (restic-job-requirement config #:home-service? home-service?))) (shepherd-service (provision `(,(string->symbol name))) - (requirement - `(user-processes file-systems ,@requirement)) + (requirement requirement) (documentation - "Run @code{restic} backed backups on a regular basis.") - (modules '((shepherd service timer))) + "Run restic backed backups on a regular basis.") + (modules (restic-backup-job-modules + #:home-service? home-service?)) (start #~(make-timer-constructor (if (string? #$schedule) (cron-string->calendar-event #$schedule) #$schedule) (command - (list - ;; We go through bash, instead of executing - ;; restic-guix directly, because the login shell - ;; gives us the correct user environment that some - ;; backends require, such as rclone. - (string-append #+bash-minimal "/bin/bash") - "-l" "-c" - (string-append "restic-guix backup " #$name)) - #:user #$user - #:group #$group - #:environment-variables - (list - (string-append - "HOME=" (passwd:dir (getpwnam #$user))))) + #$(restic-backup-job-command + name files #:home-service? home-service?) + #$@(if home-service? '() (list #:user user)) + #$@(if home-service? '() (list #:group group)) + #$@(if home-service? '() + (list + #:environment-variables + #~(list + (string-append + "HOME=" (passwd:dir (getpwnam #$user))))))) #:log-file #$log-file #:wait-for-termination? #$wait-for-termination? #:max-duration #$(and (maybe-value-set? max-duration) max-duration))) (stop #~(make-timer-destructor)) - (actions (list shepherd-trigger-action))))) + (actions (list (shepherd-action + (inherit shepherd-trigger-action) + (documentation "Manually trigger a backup, +without waiting for the scheduled time."))))))) (define (restic-guix-wrapper-package jobs) (package @@ -283,26 +353,19 @@ (define restic-backup-service-profile (restic-guix-wrapper-package jobs)) '()))) -(define (restic-backup-activation config) - #~(for-each - (lambda (log-file) - (mkdir-p (dirname log-file))) - (list #$@(map restic-job-log-file - (restic-backup-configuration-jobs config))))) - (define restic-backup-service-type (service-type (name 'restic-backup) (extensions (list - (service-extension activation-service-type - restic-backup-activation) (service-extension profile-service-type restic-backup-service-profile) (service-extension shepherd-root-service-type - (lambda (config) - (map restic-backup-job->shepherd-service - (restic-backup-configuration-jobs - config)))))) + (match-record-lambda <restic-backup-configuration> + (jobs home-service?) + (map (lambda (job) + (restic-backup-job->shepherd-service + job #:home-service? home-service?)) + jobs))))) (compose concatenate) (extend (lambda (config jobs) base-commit: 9f3d8dbda60bb1dd15d2956c334354947df8b3f5 -- 2.49.0
Ludovic Courtès <ludo <at> gnu.org>
:paul <goodoldpaul <at> autistici.org>
:Message #86 received at 76169-done <at> debbugs.gnu.org (full text, mbox):
From: Ludovic Courtès <ludo <at> gnu.org> To: Giacomo Leidi <goodoldpaul <at> autistici.org> Cc: Tanguy Le Carrour <tanguy <at> bioneland.org>, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Gabriel Wicki <gabriel <at> erlikon.ch>, Andrew Tropin <andrew <at> trop.in>, Hilton Chain <hako <at> ultrarare.space>, 76169-done <at> debbugs.gnu.org, Janneke Nieuwenhuizen <janneke <at> gnu.org> Subject: Re: [bug#76169] [PATCH v9] home: Add home-restic-backup service. Date: Sun, 18 May 2025 22:05:09 +0200
Hello, Giacomo Leidi <goodoldpaul <at> autistici.org> writes: > * gnu/services/backup.scm: Drop mcron obsolete export. > (restic-backup-job-program): Generalize to restic-program. > (lower-restic-backup-job): New procedure implementing a standard way to > lower restic-backup-job records into lists. > (restic-program): Implement general way to run restic commands, for > example to initialize repositories. > (restic-backup-configuration): Reimplement > with (guix records). > (restic-backup-job-{logfile,command,requirement,modules}): Add new > procedures and add support for Guix Home environments. > (restic-backup-job->shepherd-service): Add support for Guix Home > environments. > (restic-backup-service-activation): Drop procedure as now the Shepherd > takes care of creating timers log file directories. > (restic-backup-service-type): Drop profile and activation services extensions. > * gnu/home/services/backup.scm: New file. > * gnu/local.mk: Add this. > * doc/guix.texi: Document this. > > Change-Id: Ied1c0a5756b715fba176a0e42ea154246089e6be Finally applied, thanks!
Debbugs Internal Request <help-debbugs <at> gnu.org>
to internal_control <at> debbugs.gnu.org
.
(Mon, 16 Jun 2025 11:24:11 GMT) Full text and rfc822 format available.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.