[PATCH 00/16] Replacing mcron jobs by Shepherd timers

  • Open
  • quality assurance status badge
Details
7 participants
  • Luis Guilherme Coelho
  • Ludovic Courtès
  • Maxim Cournoyer
  • Bruno Victal
  • pelzflorian (Florian Pelz)
  • Sergey Trofimov
  • Tomas Volf
Owner
unassigned
Submitted by
Ludovic Courtès
Severity
normal

Debbugs page

Ludovic Courtès wrote 35 hours ago
(address . guix-patches@gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
cover.1742073920.git.ludo@gnu.org
Hello,

This is the last step of the Shepherd 1.0 transition, leading
to the deprecation of mcron, superseded by Shepherd timers.

Thoughts?

Ludo'.

Ludovic Courtès (16):
services: shepherd: Factorize ‘trigger’ action.
services: file-database: Turn into a Shepherd timer.
services: file-database: Exclude /dev by default.
services: package-database: Turn into a Shepherd timer.
services: fstrim: Turn into a Shepherd timer.
services: certbot: Turn into a Shepherd timer.
services: wireguard: Turn monitoring into a Shepherd timer.
tests: Make ‘operating-system-with-console-syslog’ public.
tests: ganeti: Remove unnecessary ‘begin’.
tests: ganeti: Write system log to /dev/console.
tests: ganeti: Increase VM memory size.
services: ganeti: Update to Shepherd 1.0 interface.
services: ganeti: Produce Shepherd timers instead of mcron jobs.
services: virtual-build-machine: Turn GC job into a Shepherd timer.
services: mcron: Deprecate.
DRAFT news: Add entry for mcron deprecation.

doc/guix.texi | 60 +++++++---
etc/news.scm | 13 +++
gnu/home/services/mcron.scm | 7 +-
gnu/services/admin.scm | 68 +++++++----
gnu/services/backup.scm | 6 +-
gnu/services/certbot.scm | 93 ++++++++-------
gnu/services/ganeti.scm | 135 ++++++++++-----------
gnu/services/linux.scm | 50 ++++----
gnu/services/mcron.scm | 7 +-
gnu/services/shepherd.scm | 8 ++
gnu/services/virtualization.scm | 22 +++-
gnu/services/vpn.scm | 201 +++++++++++++++++---------------
gnu/tests.scm | 21 ++++
gnu/tests/ganeti.scm | 120 +++++++++----------
gnu/tests/install.scm | 20 ----
15 files changed, 462 insertions(+), 369 deletions(-)


base-commit: 0c497c87ac47206b3e8c6dfa2e1e9b5f3e452292
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 01/16] services: shepherd: Factorize ‘trigger’ action.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
8849153c52dfe2ceec61a2cdbf3c07cb3363ff7d.1742073920.git.ludo@gnu.org
* gnu/services/shepherd.scm (shepherd-trigger-action): New variable.
* gnu/services/admin.scm (log-cleanup-shepherd-services)
(unattended-upgrade-shepherd-services): Use it.
* gnu/services/backup.scm (restic-backup-job->shepherd-service): Use it.

Change-Id: I834b5b9b61c78f012ee9306df6cf4fd8a93dd6d2
---
gnu/services/admin.scm | 10 ++--------
gnu/services/backup.scm | 6 +-----
gnu/services/shepherd.scm | 8 ++++++++
3 files changed, 11 insertions(+), 13 deletions(-)

Toggle diff (73 lines)
diff --git a/gnu/services/admin.scm b/gnu/services/admin.scm
index 2a11a4f4f1..726ca5f918 100644
--- a/gnu/services/admin.scm
+++ b/gnu/services/admin.scm
@@ -404,10 +404,7 @@ (define (log-cleanup-shepherd-services configuration)
schedule)
(command '(#$program))))
(stop #~(make-timer-destructor))
- (actions (list (shepherd-action
- (name 'trigger)
- (documentation "Trigger log cleanup.")
- (procedure #~trigger-timer))))
+ (actions (list shepherd-trigger-action))
(documentation "Periodically delete old log files."))))))
(define log-cleanup-service-type
@@ -671,10 +668,7 @@ (define (unattended-upgrade-shepherd-services config)
;; again.
#:wait-for-termination? #t))
(stop #~(make-timer-destructor))
- (actions (list (shepherd-action
- (name 'trigger)
- (documentation "Trigger unattended system upgrade.")
- (procedure #~trigger-timer)))))))
+ (actions (list shepherd-trigger-action)))))
(define unattended-upgrade-service-type
(service-type
diff --git a/gnu/services/backup.scm b/gnu/services/backup.scm
index 4d8cf167f0..6e066bd3d6 100644
--- a/gnu/services/backup.scm
+++ b/gnu/services/backup.scm
@@ -255,11 +255,7 @@ (define (restic-backup-job->shepherd-service config)
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)))))))
+ (actions (list shepherd-trigger-action)))))
(define (restic-guix-wrapper-package jobs)
(package
diff --git a/gnu/services/shepherd.scm b/gnu/services/shepherd.scm
index 65c49b9c59..e7e414b920 100644
--- a/gnu/services/shepherd.scm
+++ b/gnu/services/shepherd.scm
@@ -72,6 +72,7 @@ (define-module (gnu services shepherd)
shepherd-action-procedure
shepherd-configuration-action
+ shepherd-trigger-action
%default-modules
@@ -404,6 +405,13 @@ (define (shepherd-configuration-action file)
(format #t "~a~%" #$file)
#$file))))
+(define shepherd-trigger-action
+ ;; Action to trigger a timer.
+ (shepherd-action
+ (name 'trigger)
+ (documentation "Trigger immediate execution of this timer.")
+ (procedure #~trigger-timer)))
+
(define (shepherd-configuration-file services shepherd)
"Return the shepherd configuration file for SERVICES. SHEPHERD is used
as shepherd package."
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 02/16] services: file-database: Turn into a Shepherd timer.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
7e1843fdb5c8d0ebe4f3002ea7beb041f0622f5a.1742073920.git.ludo@gnu.org
* gnu/services/admin.scm (file-database-mcron-jobs): Rename to…
(file-database-shepherd-services): … this. Return a list of Shepherd
services.
(file-database-service-type): Adjust accordingly.
* doc/guix.texi (File Search Services): Update documentation of
‘schedule’.

Change-Id: I5734c629b113e54057694d2ec480abd26b7815db
---
doc/guix.texi | 5 +++--
gnu/services/admin.scm | 22 ++++++++++++++++++----
2 files changed, 21 insertions(+), 6 deletions(-)

Toggle diff (62 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index d109877a32..ae7b08ad23 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -27152,8 +27152,9 @@ File Search Services
is taken.
@item @code{schedule} (default: @code{%default-file-database-update-schedule})
-String or G-exp denoting an mcron schedule for the periodic
-@command{updatedb} job (@pxref{Guile Syntax,,, mcron, GNU@tie{}mcron}).
+This is the schedule of database updates, expressed as a string in
+traditional cron syntax or as a gexp evaluating to a Shepherd calendar
+event (@pxref{Timers,,, shepherd, The GNU Shepherd Manual}).
@item @code{excluded-directories} (default @code{%default-file-database-excluded-directories})
List of regular expressions of directories to ignore when building the
diff --git a/gnu/services/admin.scm b/gnu/services/admin.scm
index 726ca5f918..5f5b76ffbb 100644
--- a/gnu/services/admin.scm
+++ b/gnu/services/admin.scm
@@ -462,7 +462,7 @@ (define-configuration/no-serialization file-database-configuration
guix locate}). This list is passed to the @option{--prunepaths} option of
@command{updatedb} (@pxref{Invoking updatedb,,, find, GNU@tie{}Findutils})."))
-(define (file-database-mcron-jobs configuration)
+(define (file-database-shepherd-services configuration)
(match-record configuration <file-database-configuration>
(package schedule excluded-directories)
(let ((updatedb (program-file
@@ -481,13 +481,27 @@ (define (file-database-mcron-jobs configuration)
#$(string-append "--prunepaths="
(string-join
excluded-directories)))))))
- (list #~(job #$schedule #$updatedb)))))
+ (list (shepherd-service
+ (provision '(file-database-update))
+ (requirement '(user-processes))
+ (modules '((shepherd service timer)))
+ (start #~(make-timer-constructor
+ #$(if (string? schedule)
+ #~(cron-string->calendar-event #$schedule)
+ schedule)
+ (command '(#$updatedb))
+ #:wait-for-termination? #t))
+ (stop #~(make-timer-destructor))
+ (documentation
+ "Periodically update the system-wide file database that can be
+queried by the 'locate' command.")
+ (actions (list shepherd-trigger-action)))))))
(define file-database-service-type
(service-type
(name 'file-database)
- (extensions (list (service-extension mcron-service-type
- file-database-mcron-jobs)))
+ (extensions (list (service-extension shepherd-root-service-type
+ file-database-shepherd-services)))
(description
"Periodically update the file database used by the @command{locate} command,
which lets you search for files by name. The database is created by running
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 03/16] services: file-database: Exclude /dev by default.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
198fd0abf3a0d64f44b1fae7eae99b721fb8d38f.1742073920.git.ludo@gnu.org
* gnu/services/admin.scm (%default-file-database-excluded-directories):
Add “/dev’.

Change-Id: I06af6621cd363e140a6fc49e1cee97d15b365b89
---
gnu/services/admin.scm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

Toggle diff (15 lines)
diff --git a/gnu/services/admin.scm b/gnu/services/admin.scm
index 5f5b76ffbb..b73accc4af 100644
--- a/gnu/services/admin.scm
+++ b/gnu/services/admin.scm
@@ -430,7 +430,7 @@ (define %default-file-database-excluded-directories
;; Regexps of directories excluded from the 'locate' database.
(list (%store-prefix)
"/tmp" "/var/tmp" "/var/cache" ".*/\\.cache"
- "/run/udev"))
+ "/run/udev" "/dev"))
(define (string-or-gexp? obj)
(or (string? obj) (gexp? obj)))
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 04/16] services: package-database: Turn into a Shepherd timer.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
1344bace2389f90a2aa26834ab4b0528e55e2c30.1742073920.git.ludo@gnu.org
* gnu/services/admin.scm (package-database-mcron-jobs): Rename to…
(package-database-shepherd-services): … this. Return a shepherd
service.
(package-database-service-type): Update accordingly.
* doc/guix.texi (File Search Services): Update documentation of the
‘schedule’ field.

Change-Id: Id7b4c5cff95a7117dca7d95af37db7389bb5ca92
---
doc/guix.texi | 7 ++++---
gnu/services/admin.scm | 34 ++++++++++++++++++++++++----------
2 files changed, 28 insertions(+), 13 deletions(-)

Toggle diff (72 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index ae7b08ad23..e45e8a9979 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -27194,9 +27194,10 @@ File Search Services
The Guix package to use.
@item @code{schedule} (default: @code{%default-package-database-update-schedule})
-String or G-exp denoting an mcron schedule for the periodic
-@command{guix locate --update} job (@pxref{Guile Syntax,,, mcron,
-GNU@tie{}mcron}).
+This is the schedule of the periodic @command{guix locate --update} job,
+expressed as a string in traditional cron syntax or as a gexp evaluating
+to a Shepherd calendar event (@pxref{Timers,,, shepherd, The GNU
+Shepherd Manual}).
@item @code{method} (default: @code{'store})
Indexing method for @command{guix locate}. The default value,
diff --git a/gnu/services/admin.scm b/gnu/services/admin.scm
index b73accc4af..e473794043 100644
--- a/gnu/services/admin.scm
+++ b/gnu/services/admin.scm
@@ -529,23 +529,37 @@ (define-configuration/no-serialization package-database-configuration
"G-exp denoting the channels to use when updating the database
(@pxref{Channels})."))
-(define (package-database-mcron-jobs configuration)
+(define (package-database-shepherd-services configuration)
(match-record configuration <package-database-configuration>
(package schedule method channels)
(let ((channels (scheme-file "channels.scm" channels)))
- (list #~(job #$schedule
- ;; XXX: The whole thing's running as "root" just because it
- ;; needs write access to /var/cache/guix/locate.
- (string-append #$(file-append package "/bin/guix")
- " time-machine -C " #$channels
- " -- locate --update --method="
- #$(symbol->string method)))))))
+ (list (shepherd-service
+ (provision '(package-database-update))
+ (requirement '(user-processes guix-daemon))
+ (modules '((shepherd service timer)))
+ ;; XXX: The whole thing's running as "root" just because it needs
+ ;; write access to /var/cache/guix/locate.
+ (start #~(make-timer-constructor
+ #$(if (string? schedule)
+ #~(cron-string->calendar-event #$schedule)
+ schedule)
+ (command '(#$(file-append package "/bin/guix")
+ "time-machine" "-C" #$channels
+ "--" "locate" "--update"
+ #$(string-append
+ "--method=" (symbol->string method))))
+ #:wait-for-termination? #t))
+ (stop #~(make-timer-destructor))
+ (documentation
+ "Periodically update the system-wide package database that can
+be queried by the 'guix locate' command.")
+ (actions (list shepherd-trigger-action)))))))
(define package-database-service-type
(service-type
(name 'package-database)
- (extensions (list (service-extension mcron-service-type
- package-database-mcron-jobs)))
+ (extensions (list (service-extension shepherd-root-service-type
+ package-database-shepherd-services)))
(description
"Periodically update the package database used by the @code{guix locate} command,
which lets you search for packages that provide a given file.")
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 05/16] services: fstrim: Turn into a Shepherd timer.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
3fa51ca5c51d0cd271420d7387202770541f6078.1742073920.git.ludo@gnu.org
* gnu/services/linux.scm (mcron-time?): Remove.
(shepherd-calendar-event?): New procedure.
(fstrim-configuration)[schedule]: Change type to
‘shepherd-calendar-event’ and update docstring.
(fstrim-mcron-job): Rename to…
(fstrim-shepherd-services): … this. Return a list of Shepherd services.
(fstrim-service-type): Adjust accordingly.
* doc/guix.texi (Linux Services): Update.

Change-Id: I9a7433cb15a1f4600470a915769d612e6e644dd8
---
doc/guix.texi | 16 +++++++++-----
gnu/services/linux.scm | 50 +++++++++++++++++++++++-------------------
2 files changed, 37 insertions(+), 29 deletions(-)

Toggle diff (132 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index e45e8a9979..da1c4adc0c 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -42019,6 +42019,7 @@ Linux Services
@end defvar
@c %start of fragment
+
@deftp {Data Type} fstrim-configuration
Available @code{fstrim-configuration} fields are:
@@ -42026,13 +42027,13 @@ Linux Services
@item @code{package} (default: @code{util-linux}) (type: file-like)
The package providing the @command{fstrim} command.
-@item @code{schedule} (default: @code{"0 0 * * 0"}) (type: mcron-time)
-Schedule for launching @command{fstrim}. This can be a procedure, a
-list or a string. For additional information, see @ref{Guile
-Syntax,,Job specification,mcron,the mcron manual}. By default this is
-set to run weekly on Sunday at 00:00.
+@item @code{schedule} (default: @code{"0 0 * * 0"}) (type: shepherd-calendar-event)
+Schedule for launching @command{fstrim}, expressed as a string in
+traditional cron syntax or as a gexp evaluating to a Shepherd calendar
+event (@pxref{Timers,,, shepherd,The GNU Shepherd Manual}). By default
+this is set to run weekly on Sunday at 00:00.
-@item @code{listed-in} (default: @code{'("/etc/fstab" "/proc/self/mountinfo")}) (type: maybe-list-of-strings)
+@item @code{listed-in} (default: @code{("/etc/fstab" "/proc/self/mountinfo")}) (type: maybe-list-of-strings)
List of files in fstab or kernel mountinfo format. All missing or empty
files are silently ignored. The evaluation of the list @emph{stops}
after the first non-empty file. File systems with
@@ -42049,7 +42050,10 @@ Linux Services
more information).
@end table
+
@end deftp
+
+
@c %end of fragment
@cindex modprobe
diff --git a/gnu/services/linux.scm b/gnu/services/linux.scm
index b22dbeefa0..d7aee1b82e 100644
--- a/gnu/services/linux.scm
+++ b/gnu/services/linux.scm
@@ -34,7 +34,6 @@ (define-module (gnu services linux)
#:use-module (gnu services admin)
#:use-module (gnu services base)
#:use-module (gnu services configuration)
- #:use-module (gnu services mcron)
#:use-module (gnu services shepherd)
#:use-module (gnu packages linux)
#:use-module (srfi srfi-1)
@@ -196,8 +195,8 @@ (define earlyoom-service-type
;;; fstrim
;;;
-(define (mcron-time? x)
- (or (procedure? x) (string? x) (list? x)))
+(define (shepherd-calendar-event? x)
+ (or (string? x) (gexp? x)))
(define-maybe list-of-strings (prefix fstrim-))
@@ -216,11 +215,11 @@ (define-configuration fstrim-configuration
"The package providing the @command{fstrim} command."
empty-serializer)
(schedule
- (mcron-time "0 0 * * 0")
- "Schedule for launching @command{fstrim}. This can be a procedure, a list
-or a string. For additional information, see @ref{Guile Syntax,,
-Job specification, mcron, the mcron manual}. By default this is set to run
-weekly on Sunday at 00:00."
+ (shepherd-calendar-event "0 0 * * 0")
+ "Schedule for launching @command{fstrim}, expressed as a string in
+traditional cron syntax or as a gexp evaluating to a Shepherd calendar
+event (@pxref{Timers,,, shepherd, The GNU Shepherd Manual}). By default this
+is set to run weekly on Sunday at 00:00."
empty-serializer)
;; The following are fstrim-related options.
(listed-in
@@ -251,26 +250,31 @@ (define (serialize-fstrim-configuration config)
rcons
fstrim-configuration-fields))
-(define (fstrim-mcron-job config)
- (match-record config <fstrim-configuration> (package schedule)
- #~(job
- ;; Note: The “if” below is to ensure that
- ;; lists are ungexp'd correctly since @var{schedule}
- ;; can be either a procedure, a string or a list.
- #$(if (list? schedule)
- #~'(#$@schedule)
- schedule)
- (lambda ()
- (system* #$(file-append package "/sbin/fstrim")
- #$@(serialize-fstrim-configuration config)))
- "fstrim")))
+(define (fstrim-shepherd-services config)
+ (match-record config <fstrim-configuration>
+ (package schedule)
+ (list (shepherd-service
+ (provision '(fstrim))
+ (requirement '(user-processes))
+ (modules '((shepherd service timer)))
+ (start #~(make-timer-constructor
+ #$(if (string? schedule)
+ #~(cron-string->calendar-event #$schedule)
+ schedule)
+ (command
+ (list #$(file-append package "/sbin/fstrim")
+ #$@(serialize-fstrim-configuration config)))
+ #:wait-for-termination? #t))
+ (stop #~(make-timer-destructor))
+ (documentation "Periodically run the 'fstrim' command.")
+ (actions (list shepherd-trigger-action))))))
(define fstrim-service-type
(service-type
(name 'fstrim)
(extensions
- (list (service-extension mcron-service-type
- (compose list fstrim-mcron-job))))
+ (list (service-extension shepherd-root-service-type
+ fstrim-shepherd-services)))
(description "Discard unused blocks from file systems.")
(default-value (fstrim-configuration))))
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 06/16] services: certbot: Turn into a Shepherd timer.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
52a1dd45cb6686b3d13f8b143a0d8bcbf2b6aaab.1742073920.git.ludo@gnu.org
* gnu/services/certbot.scm (certbot-renewal-jobs): Rename to…
(certbot-renewal-shepherd-services): … this. Return a list of Shepherd
services, including ‘renew-certbot-certificates’, formally defined…
(certbot-renewal-one-shot): … here. Remove.
(certbot-service-type): Adjust accordingly.

Change-Id: I25ad9fc1277f4f6f948ab5fce7c6626f22591d10
---
gnu/services/certbot.scm | 93 +++++++++++++++++++++-------------------
1 file changed, 50 insertions(+), 43 deletions(-)

Toggle diff (122 lines)
diff --git a/gnu/services/certbot.scm b/gnu/services/certbot.scm
index b276c49e0f..d6c7d175ff 100644
--- a/gnu/services/certbot.scm
+++ b/gnu/services/certbot.scm
@@ -27,7 +27,6 @@ (define-module (gnu services certbot)
#:use-module (gnu services)
#:use-module (gnu services base)
#:use-module (gnu services shepherd)
- #:use-module (gnu services mcron)
#:use-module (gnu services web)
#:use-module (gnu system shadow)
#:use-module (gnu packages tls)
@@ -220,46 +219,56 @@ (define certbot-command
'#$commands)
(exit script-code))))))))
-(define (certbot-renewal-jobs config)
- (list
- ;; Attempt to renew the certificates twice per day, at a random minute
- ;; within the hour. See https://eff-certbot.readthedocs.io/.
- #~(job '(next-minute-from (next-hour '(0 12)) (list (random 60)))
- #$(certbot-command config))))
+(define (certbot-renewal-shepherd-services config)
+ (list (shepherd-service
+ (provision '(certbot-certificate-renewal))
+ (requirement '(user-processes nginx))
+ (modules '((shepherd service timer)))
+ (start #~(make-timer-constructor
+ ;; Attempt to renew the certificates twice per day. See
+ ;; https://eff-certbot.readthedocs.io/.
+ (calendar-event #:minutes '(22) #:hours '(0 12))
+ (command '(#$(certbot-command config)))
+ #:wait-for-termination? #t))
+ (stop #~(make-timer-destructor))
+ (documentation "Periodically run the 'certbot' command to renew X.509
+certificates.")
+ (actions
+ (list shepherd-trigger-action
+ (shepherd-configuration-action (certbot-command config)))))
-(define (certbot-renewal-one-shot config)
- (list
- ;; Renew certificates when the system first starts. This is a one-shot
- ;; service, because the mcron configuration will take care of running this
- ;; periodically. This is most useful the very first time the system starts,
- ;; to overwrite our self-signed certificates as soon as possible without
- ;; user intervention.
- (shepherd-service
- (provision '(renew-certbot-certificates))
- (requirement '(nginx))
- (one-shot? #t)
- (start #~(lambda _
- ;; This needs the network, but there's no reliable way to know
- ;; if the network is up other than trying. If we fail due to a
- ;; connection error we retry a number of times in the hope that
- ;; the network comes up soon.
- (let loop ((attempt 0))
- (let ((code (status:exit-val
- (system* #$(certbot-command config)))))
- (cond
- ((and (= code 2) ; Exit code 2 means connection error
- (< attempt 12)) ; Arbitrarily chosen max attempts
- (sleep 10) ; Arbitrarily chosen retry delay
- (loop (1+ attempt)))
- ((zero? code)
- ;; Success!
- #t)
- (else
- ;; Failure.
- #f))))))
- (auto-start? #t)
- (documentation "Call certbot to renew certificates.")
- (actions (list (shepherd-configuration-action (certbot-command config)))))))
+ ;; Renew certificates when the system first starts. This is a one-shot
+ ;; service, because the timer above takes care of running this
+ ;; periodically. This is most useful the very first time the system
+ ;; starts, to overwrite our self-signed certificates as soon as
+ ;; possible without user intervention.
+ (shepherd-service
+ (provision '(renew-certbot-certificates))
+ (requirement '(user-processes nginx))
+ (one-shot? #t)
+ (start #~(lambda _
+ ;; This needs the network, but there's no reliable way to know
+ ;; if the network is up other than trying. If we fail due to a
+ ;; connection error we retry a number of times in the hope that
+ ;; the network comes up soon.
+ (let loop ((attempt 0))
+ (let ((code (status:exit-val
+ (system* #$(certbot-command config)))))
+ (cond
+ ((and (= code 2) ; Exit code 2 means connection error
+ (< attempt 12)) ; Arbitrarily chosen max attempts
+ (sleep 10) ; Arbitrarily chosen retry delay
+ (loop (1+ attempt)))
+ ((zero? code)
+ ;; Success!
+ #t)
+ (else
+ ;; Failure.
+ #f))))))
+ (auto-start? #t)
+ (documentation "Run 'certbot' to renew certificates at boot time.")
+ (actions
+ (list (shepherd-configuration-action (certbot-command config)))))))
(define (generate-certificate-gexp certbot-cert-directory rsa-key-size)
(match-lambda
@@ -354,10 +363,8 @@ (define certbot-service-type
(compose list certbot-configuration-package))
(service-extension activation-service-type
certbot-activation)
- (service-extension mcron-service-type
- certbot-renewal-jobs)
(service-extension shepherd-root-service-type
- certbot-renewal-one-shot)))
+ certbot-renewal-shepherd-services)))
(compose concatenate)
(extend (lambda (config additional-certificates)
(certbot-configuration
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 07/16] services: wireguard: Turn monitoring into a Shepherd timer.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
c8c1a15f77ffa40cec9fbb1fb735e26c2be2971f.1742073920.git.ludo@gnu.org
* gnu/services/vpn.scm (<wireguard-configuration>)[schedule]: Change
default value.
(wireguard-monitoring-program): New procedure, with code taken from…
(wireguard-monitoring-jobs): … here. Remove.
(wireguard-shepherd-services): New procedure, with code taken from…
(wireguard-shepherd-service): … here. Remove.
* doc/guix.texi (VPN Services): Update.

Change-Id: I6851ddf1eb9480bdc9e6c6c6b88958ab2e6225d7
---
doc/guix.texi | 7 +-
gnu/services/vpn.scm | 201 ++++++++++++++++++++++---------------------
2 files changed, 109 insertions(+), 99 deletions(-)

Toggle diff (270 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index da1c4adc0c..7f3a7ca82a 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -35654,9 +35654,10 @@ VPN Services
name. Set this to @code{#t} if one or more endpoints use host names
provided by a dynamic DNS service to keep the sessions alive.
-@item @code{monitor-ips-interval} (default: @code{'(next-minute (range 0 60 5))})
-The time interval at which the IP monitoring job should run, provided as
-an mcron time specification (@pxref{Guile Syntax,,,mcron}).
+@item @code{monitor-ips-interval} (default: @code{"*/5 * * * *"})
+This is the monitoring schedule, expressed as a string in traditional
+cron syntax or as a gexp evaluating to a Shepherd calendar event
+(@pxref{Timers,,, shepherd, The GNU Shepherd Manual}).
@item @code{private-key} (default: @code{"/etc/wireguard/private.key"})
The private key file for the interface. It is automatically generated
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index 478a0d543e..e788ebef2e 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -34,7 +34,6 @@ (define-module (gnu services vpn)
#:use-module (gnu services)
#:use-module (gnu services configuration)
#:use-module (gnu services dbus)
- #:use-module (gnu services mcron)
#:use-module (gnu services shepherd)
#:use-module (gnu system shadow)
#:use-module (gnu packages admin)
@@ -43,6 +42,7 @@ (define-module (gnu services vpn)
#:use-module (guix packages)
#:use-module (guix records)
#:use-module (guix gexp)
+ #:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module (guix deprecation)
#:use-module (srfi srfi-1)
@@ -756,7 +756,7 @@ (define-record-type* <wireguard-configuration>
(monitor-ips? wireguard-configuration-monitor-ips? ;boolean
(default #f))
(monitor-ips-interval wireguard-configuration-monitor-ips-interval
- (default '(next-minute (range 0 60 5)))) ;string | list
+ (default "*/5 * * * *")) ;string | list
(pre-up wireguard-configuration-pre-up ;list of strings
(default '()))
(post-up wireguard-configuration-post-up ;list of strings
@@ -916,117 +916,126 @@ (define (endpoint-host-names peers)
'()
peers)))
-(define (wireguard-shepherd-service config)
+(define (wireguard-monitoring-program config)
(match-record config <wireguard-configuration>
- (wireguard interface)
+ (interface monitor-ips-interval peers)
+ (let ((host-names (endpoint-host-names peers)))
+ (when (null? host-names)
+ (warning (G_ "'monitor-ips?' is #t but no host name to monitor~%")))
+
+ ;; Loosely based on WireGuard's own 'reresolve-dns.sh' shell script
+ ;; (see: https://raw.githubusercontent.com/WireGuard/wireguard-tools/
+ ;; master/contrib/reresolve-dns/reresolve-dns.sh).
+ (program-file
+ (format #f "wireguard-~a-monitoring" interface)
+ (with-imported-modules (source-module-closure
+ '((gnu services herd)
+ (guix build utils)))
+ #~(begin
+ (use-modules (gnu services herd)
+ (guix build utils)
+ (ice-9 popen)
+ (ice-9 match)
+ (ice-9 textual-ports)
+ (srfi srfi-1)
+ (srfi srfi-26))
+
+ (define (resolve-host name)
+ "Return the IP address resolved from NAME."
+ (let* ((ai (car (getaddrinfo name)))
+ (sa (addrinfo:addr ai)))
+ (inet-ntop (sockaddr:fam sa)
+ (sockaddr:addr sa))))
+
+ (define wg #$(file-append wireguard-tools "/bin/wg"))
+
+ #$(procedure-source strip-port/maybe)
+
+ (define service-name
+ '#$(wireguard-service-name interface))
+
+ (when (live-service-running
+ (current-service service-name))
+ (let* ((pipe (open-pipe* OPEN_READ wg "show"
+ #$interface "endpoints"))
+ (lines (string-split (get-string-all pipe)
+ #\newline))
+ ;; IPS is an association list mapping
+ ;; public keys to IP addresses.
+ (ips (map (match-lambda
+ ((public-key ip)
+ (cons public-key
+ (strip-port/maybe ip))))
+ (map (cut string-split <> #\tab)
+ (remove string-null?
+ lines)))))
+ (close-pipe pipe)
+ (for-each
+ (match-lambda
+ ((key . host-name)
+ (let ((resolved-ip (resolve-host
+ (strip-port/maybe
+ host-name)))
+ (current-ip (assoc-ref ips key)))
+ (unless (string=? resolved-ip current-ip)
+ (format #t "resetting `~a' peer \
+endpoint to `~a' due to stale IP (`~a' instead of `~a')~%"
+ key host-name
+ current-ip resolved-ip)
+ (invoke wg "set" #$interface "peer" key
+ "endpoint" host-name)))))
+ '#$host-names)))))))))
+
+(define (wireguard-shepherd-services config)
+ (match-record config <wireguard-configuration>
+ (wireguard interface monitor-ips? monitor-ips-interval)
(let ((wg-quick (file-append wireguard "/bin/wg-quick"))
(auto-start? (wireguard-configuration-auto-start? config))
- (config (wireguard-configuration-file config)))
- (list (shepherd-service
- (requirement '(networking))
+ (config-file (wireguard-configuration-file config)))
+ (define monitoring-service
+ (and monitor-ips?
+ (shepherd-service
+ (provision (list (symbol-append
+ (wireguard-service-name interface)
+ '-monitoring)))
+ (requirement (list 'user-processes
+ (wireguard-service-name interface)))
+ (modules '((shepherd service timer)))
+ (start #~(make-timer-constructor
+ #$(if (string? monitor-ips-interval)
+ #~(cron-string->calendar-event
+ #$monitor-ips-interval)
+ monitor-ips-interval)
+ (command '(#$(wireguard-monitoring-program config)))
+ #:wait-for-termination? #t))
+ (stop #~(make-timer-destructor))
+ (documentation "Monitor the Wireguard VPN tunnel.")
+ (actions (list shepherd-trigger-action)))))
+
+ (cons (shepherd-service
+ (requirement '(networking user-processes))
(provision (list (wireguard-service-name interface)))
(start #~(lambda _
- (invoke #$wg-quick "up" #$config)))
+ (invoke #$wg-quick "up" #$config-file)))
(stop #~(lambda _
- (invoke #$wg-quick "down" #$config)
+ (invoke #$wg-quick "down" #$config-file)
#f)) ;stopped!
- (actions (list (shepherd-configuration-action config)))
+ (actions (list (shepherd-configuration-action config-file)))
(auto-start? auto-start?)
- (documentation "Run the Wireguard VPN tunnel"))))))
-
-(define (wireguard-monitoring-jobs config)
- ;; Loosely based on WireGuard's own 'reresolve-dns.sh' shell script (see:
- ;; https://raw.githubusercontent.com/WireGuard/wireguard-tools/
- ;; master/contrib/reresolve-dns/reresolve-dns.sh).
- (match-record config <wireguard-configuration>
- (interface monitor-ips? monitor-ips-interval peers)
- (let ((host-names (endpoint-host-names peers)))
- (if monitor-ips?
- (if (null? host-names)
- (begin
- (warn "monitor-ips? is #t but no host name to monitor")
- '())
- ;; The mcron monitor job may be a string or a list; ungexp strips
- ;; one quote level, which must be added back when a list is
- ;; provided.
- (list
- #~(job
- (if (string? #$monitor-ips-interval)
- #$monitor-ips-interval
- '#$monitor-ips-interval)
- #$(program-file
- (format #f "wireguard-~a-monitoring" interface)
- (with-imported-modules (source-module-closure
- '((gnu services herd)
- (guix build utils)))
- #~(begin
- (use-modules (gnu services herd)
- (guix build utils)
- (ice-9 popen)
- (ice-9 match)
- (ice-9 textual-ports)
- (srfi srfi-1)
- (srfi srfi-26))
-
- (define (resolve-host name)
- "Return the IP address resolved from NAME."
- (let* ((ai (car (getaddrinfo name)))
- (sa (addrinfo:addr ai)))
- (inet-ntop (sockaddr:fam sa)
- (sockaddr:addr sa))))
-
- (define wg #$(file-append wireguard-tools "/bin/wg"))
-
- #$(procedure-source strip-port/maybe)
-
- (define service-name '#$(wireguard-service-name
- interface))
-
- (when (live-service-running
- (current-service service-name))
- (let* ((pipe (open-pipe* OPEN_READ wg "show"
- #$interface "endpoints"))
- (lines (string-split (get-string-all pipe)
- #\newline))
- ;; IPS is an association list mapping
- ;; public keys to IP addresses.
- (ips (map (match-lambda
- ((public-key ip)
- (cons public-key
- (strip-port/maybe ip))))
- (map (cut string-split <> #\tab)
- (remove string-null?
- lines)))))
- (close-pipe pipe)
- (for-each
- (match-lambda
- ((key . host-name)
- (let ((resolved-ip (resolve-host
- (strip-port/maybe
- host-name)))
- (current-ip (assoc-ref ips key)))
- (unless (string=? resolved-ip current-ip)
- (format #t "resetting `~a' peer \
-endpoint to `~a' due to stale IP (`~a' instead of `~a')~%"
- key host-name
- current-ip resolved-ip)
- (invoke wg "set" #$interface "peer" key
- "endpoint" host-name)))))
- '#$host-names)))))))))
- '())))) ;monitor-ips? is #f
+ (documentation "Run the Wireguard VPN tunnel"))
+ (or (and=> monitoring-service list)
+ '())))))
(define wireguard-service-type
(service-type
(name 'wireguard)
(extensions
(list (service-extension shepherd-root-service-type
- wireguard-shepherd-service)
+ wireguard-shepherd-services)
(service-extension activation-service-type
wireguard-activation)
(service-extension profile-service-type
(compose list
- wireguard-configuration-wireguard))
- (service-extension mcron-service-type
- wireguard-monitoring-jobs)))
+ wireguard-configuration-wireguard))))
(description "Set up Wireguard @acronym{VPN, Virtual Private Network}
tunnels.")))
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 08/16] tests: Make ‘operating-system -with-console-syslog’ public.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
18ee01c05e82b666726f3709cad6fabafff9ae98.1742073920.git.ludo@gnu.org
* gnu/tests/install.scm (operating-system-with-console-syslog): Move to…
* gnu/tests.scm (operating-system-with-console-syslog): … here. New
procedure.

Change-Id: I015e24525140365d09f22127d366107fdc9ca902
---
gnu/tests.scm | 21 +++++++++++++++++++++
gnu/tests/install.scm | 20 --------------------
2 files changed, 21 insertions(+), 20 deletions(-)

Toggle diff (72 lines)
diff --git a/gnu/tests.scm b/gnu/tests.scm
index 84298de448..abb7076208 100644
--- a/gnu/tests.scm
+++ b/gnu/tests.scm
@@ -53,6 +53,7 @@ (define-module (gnu tests)
%simple-os
simple-operating-system
+ operating-system-with-console-syslog
system-test
system-test?
@@ -268,6 +269,26 @@ (define-syntax-rule (simple-operating-system user-services ...)
(services (cons* user-services ... %base-services))))
+(define (operating-system-with-console-syslog os)
+ "Return OS with a system log service that writes to /dev/console."
+ (operating-system
+ (inherit os)
+ (services
+ (modify-services (operating-system-user-services os)
+ (shepherd-system-log-service-type
+ config
+ =>
+ (system-log-configuration
+ (inherit config)
+ (message-destination
+ #~(lambda (message)
+ (let ((destinations ((default-message-destination-procedure)
+ message)))
+ (if (<= (system-log-message-priority message)
+ (system-log-priority info))
+ (cons "/dev/console" destinations)
+ destinations))))))))))
+
;;;
;;; Tests.
diff --git a/gnu/tests/install.scm b/gnu/tests/install.scm
index a837637b18..8293296339 100644
--- a/gnu/tests/install.scm
+++ b/gnu/tests/install.scm
@@ -1784,26 +1784,6 @@ (define %test-xfs-root-os
;;; Installation through the graphical interface.
;;;
-(define (operating-system-with-console-syslog os)
- "Return OS with a syslog service that writes to /dev/console."
- (operating-system
- (inherit os)
- (services
- (modify-services (operating-system-user-services os)
- (shepherd-system-log-service-type
- config
- =>
- (system-log-configuration
- (inherit config)
- (message-destination
- #~(lambda (message)
- (let ((destinations ((default-message-destination-procedure)
- message)))
- (if (<= (system-log-message-priority message)
- (system-log-priority info))
- (cons "/dev/console" destinations)
- destinations))))))))))
-
(define %root-password "foo")
(define* (gui-test-program marionette
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 10/16] tests: ganeti: Write system log to /dev/console.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
20e0f3fd05f4ec2a2b62cd25c050b72ac98dba38.1742073920.git.ludo@gnu.org
* gnu/tests/ganeti.scm (%ganeti-os): Wrap in
‘operating-system-with-console-syslog’.

Change-Id: Ie86ad640ad6a7c154f5768ac4250acdd0e8940af
---
gnu/tests/ganeti.scm | 87 ++++++++++++++++++++++----------------------
1 file changed, 44 insertions(+), 43 deletions(-)

Toggle diff (105 lines)
diff --git a/gnu/tests/ganeti.scm b/gnu/tests/ganeti.scm
index ce55c8e04f..42ed58d977 100644
--- a/gnu/tests/ganeti.scm
+++ b/gnu/tests/ganeti.scm
@@ -33,54 +33,55 @@ (define-module (gnu tests ganeti)
#:export (%test-ganeti-kvm %test-ganeti-lxc))
(define %ganeti-os
- (operating-system
- (host-name "gnt1")
- (timezone "Etc/UTC")
- (locale "en_US.UTF-8")
+ (operating-system-with-console-syslog
+ (operating-system
+ (host-name "gnt1")
+ (timezone "Etc/UTC")
+ (locale "en_US.UTF-8")
- (bootloader (bootloader-configuration
- (bootloader grub-bootloader)
- (targets '("/dev/vda"))))
- (file-systems (cons (file-system
- (device (file-system-label "my-root"))
- (mount-point "/")
- (type "ext4"))
- %base-file-systems))
- (firmware '())
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (targets '("/dev/vda"))))
+ (file-systems (cons (file-system
+ (device (file-system-label "my-root"))
+ (mount-point "/")
+ (type "ext4"))
+ %base-file-systems))
+ (firmware '())
- (packages (append (list ganeti-instance-debootstrap ganeti-instance-guix)
- %base-packages))
+ (packages (append (list ganeti-instance-debootstrap ganeti-instance-guix)
+ %base-packages))
- ;; The hosts file must contain a nonlocal IP for host-name.
- (essential-services
- (modify-services (operating-system-default-essential-services this-operating-system)
- (hosts-service-type config => (list
- (host "127.0.0.1" "localhost")
- (host "::1" "localhost")))))
- (services
- (append (list (service static-networking-service-type
- (list %qemu-static-networking))
- (service openssh-service-type
- (openssh-configuration
- (permit-root-login 'prohibit-password)))
+ ;; The hosts file must contain a nonlocal IP for host-name.
+ (essential-services
+ (modify-services (operating-system-default-essential-services this-operating-system)
+ (hosts-service-type config => (list
+ (host "127.0.0.1" "localhost")
+ (host "::1" "localhost")))))
+ (services
+ (append (list (service static-networking-service-type
+ (list %qemu-static-networking))
+ (service openssh-service-type
+ (openssh-configuration
+ (permit-root-login 'prohibit-password)))
- ;; In addition, the cluster name must resolve to an IP address that
- ;; is not currently provisioned.
- (simple-service 'ganeti-host-entries hosts-service-type
- (list
- (host "10.0.2.15" "gnt1.example.com" '("gnt1"))
- (host "192.168.254.254" "ganeti.example.com")))
+ ;; In addition, the cluster name must resolve to an IP address that
+ ;; is not currently provisioned.
+ (simple-service 'ganeti-host-entries hosts-service-type
+ (list
+ (host "10.0.2.15" "gnt1.example.com" '("gnt1"))
+ (host "192.168.254.254" "ganeti.example.com")))
- (service ganeti-service-type
- (ganeti-configuration
- (file-storage-paths '("/srv/ganeti/file-storage"))
- (rapi-configuration
- (ganeti-rapi-configuration
- ;; Disable TLS so we can test the RAPI without
- ;; pulling in GnuTLS.
- (ssl? #f)))
- (os %default-ganeti-os))))
- %base-services))))
+ (service ganeti-service-type
+ (ganeti-configuration
+ (file-storage-paths '("/srv/ganeti/file-storage"))
+ (rapi-configuration
+ (ganeti-rapi-configuration
+ ;; Disable TLS so we can test the RAPI without
+ ;; pulling in GnuTLS.
+ (ssl? #f)))
+ (os %default-ganeti-os))))
+ %base-services)))))
(define* (run-ganeti-test hypervisor #:key
(master-netdev "eth0")
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 11/16] tests: ganeti: Increase VM memory size.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
56f9dea90aa68cb053ae44d598b92c47144b973f.1742073920.git.ludo@gnu.org
* gnu/tests/ganeti.scm (run-ganeti-test): Pass ‘-m 1024’ to
‘make-marionette’.

Change-Id: I82c8a0eb37c16079f1affe793afc0d8a773c62c8
---
gnu/tests/ganeti.scm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

Toggle diff (15 lines)
diff --git a/gnu/tests/ganeti.scm b/gnu/tests/ganeti.scm
index 42ed58d977..140950776e 100644
--- a/gnu/tests/ganeti.scm
+++ b/gnu/tests/ganeti.scm
@@ -117,7 +117,7 @@ (define* (run-ganeti-test hypervisor #:key
(gnu build marionette))
(define marionette
- (make-marionette (list #$vm)))
+ (make-marionette (list #$vm "-m" "1024")))
(test-runner-current (system-test-runner #$output))
(test-begin "ganeti")
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 12/16] services: ganeti: Update to Shepherd 1.0 interface.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
8719086cc46a85760d78bf1515b2b0684462bcb9.1742073920.git.ludo@gnu.org
* gnu/services/ganeti.scm (shepherd-wconfd-force-start-action)[procedure]:
Use ‘enable-service’ and ‘perform-service-action’ instead of ‘action’,
which was deprecated in 0.10.x and replaced in 1.0.

Change-Id: I2ba7d973b95f17f6ce093185fec7b246cf427be9
---
gnu/services/ganeti.scm | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)

Toggle diff (34 lines)
diff --git a/gnu/services/ganeti.scm b/gnu/services/ganeti.scm
index ee72946c88..f905ab8395 100644
--- a/gnu/services/ganeti.scm
+++ b/gnu/services/ganeti.scm
@@ -329,18 +329,17 @@ (define shepherd-wconfd-force-start-action
"Forcefully start wconfd even on non-master nodes (dangerous!).")
(procedure #~(lambda _
(format #t "Forcefully starting the wconfd daemon...~%")
- (action 'ganeti-wconfd 'enable)
- (dynamic-wind
- (lambda ()
- (false-if-exception
- (call-with-output-file #$%wconfd-force-node-hint
- (lambda (port)
- (const #t)))))
- (lambda ()
- (action 'ganeti-wconfd 'restart))
+ (enable-service (lookup-service 'ganeti-wconfd))
+ (call-with-output-file #$%wconfd-force-node-hint
+ (const #t))
+ (catch #t
(lambda ()
+ (perform-service-action (lookup-service 'ganeti-wconfd)
+ 'restart)
+ (delete-file #$%wconfd-force-node-hint))
+ (lambda _
(delete-file #$%wconfd-force-node-hint)))
- #t))))
+ #t))))
(define ganeti-wconfd-service
(match-lambda
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 14/16] services: virtual-build-machine: Turn GC job into a Shepherd timer.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
134eeae955e072d41a212d5b0a41c43fed4edd4b.1742073920.git.ludo@gnu.org
* gnu/services/virtualization.scm (gc-service-type): New variable.
(%virtual-build-machine-operating-system): Use instead of extending
‘mcron-service-type’.

Change-Id: I56d7f9293f582269e5a34d91bf4f3edddfa844e0
---
gnu/services/virtualization.scm | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)

Toggle diff (49 lines)
diff --git a/gnu/services/virtualization.scm b/gnu/services/virtualization.scm
index 796b9bf86f..171915d62d 100644
--- a/gnu/services/virtualization.scm
+++ b/gnu/services/virtualization.scm
@@ -40,7 +40,6 @@ (define-module (gnu services virtualization)
#:use-module (gnu services base)
#:use-module (gnu services configuration)
#:use-module (gnu services dbus)
- #:use-module (gnu services mcron)
#:use-module (gnu services shepherd)
#:use-module (gnu services ssh)
#:use-module (gnu services)
@@ -1304,6 +1303,23 @@ (define %system-log-message-destination
(else
'("/dev/console")))))
+(define gc-service-type ;TODO: Factorize.
+ (shepherd-service-type
+ 'garbage-collection
+ (lambda _
+ (shepherd-service
+ (provision '(gc))
+ (requirement '(user-processes guix-daemon))
+ (start #~(make-timer-constructor
+ (calendar-event #:minutes '(12))
+ (command
+ '("/run/current-system/profile/bin/guix" "gc" "-F2G"))
+ #:wait-for-termination? #t))
+ (stop #~(make-timer-constructor))
+ (actions (list shepherd-trigger-action))))
+ #t
+ (description "Periodically collect garbage.")))
+
(define %virtual-build-machine-operating-system
(operating-system
(host-name "build-machine")
@@ -1336,9 +1352,7 @@ (define %virtual-build-machine-operating-system
(openssh openssh-sans-x)))
;; Run GC once per hour.
- (simple-service 'perdiodic-gc mcron-service-type
- (list #~(job "12 * * * *"
- "guix gc -F 2G")))
+ (service gc-service-type)
(modify-services %base-services
;; By default, the secret service introduces a
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 09/16] tests: ganeti: Remove unnecessary ‘begin’.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
05bc1b0ed65b4456d6e563373deb485e15d7c22d.1742073920.git.ludo@gnu.org
* gnu/tests/ganeti.scm (run-ganeti-test): Remove ‘begin’ where
unnecessary.

Change-Id: I3a36fffdc797c9187b5ffa406f7a06985f18d29c
---
gnu/tests/ganeti.scm | 31 ++++++++++++-------------------
1 file changed, 12 insertions(+), 19 deletions(-)

Toggle diff (81 lines)
diff --git a/gnu/tests/ganeti.scm b/gnu/tests/ganeti.scm
index 29eb354044..ce55c8e04f 100644
--- a/gnu/tests/ganeti.scm
+++ b/gnu/tests/ganeti.scm
@@ -154,9 +154,8 @@ (define* (run-ganeti-test hypervisor #:key
(test-eq "watcher pause"
0
(marionette-eval
- '(begin
- (system* #$(file-append ganeti "/sbin/gnt-cluster")
- "watcher" "pause" "1h"))
+ '(system* #$(file-append ganeti "/sbin/gnt-cluster")
+ "watcher" "pause" "1h")
marionette))
(test-assert "force-start wconfd"
@@ -174,8 +173,7 @@ (define* (run-ganeti-test hypervisor #:key
(test-eq "gnt-cluster verify 1"
0
(marionette-eval
- '(begin
- (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
+ '(system* #$(file-append ganeti "/sbin/gnt-cluster") "verify")
marionette))
;; Try stopping and starting daemons with daemon-util like
@@ -183,33 +181,29 @@ (define* (run-ganeti-test hypervisor #:key
(test-eq "daemon-util stop-all"
0
(marionette-eval
- '(begin
- (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
- "stop-all"))
+ '(system* #$(file-append ganeti "/lib/ganeti/daemon-util")
+ "stop-all")
marionette))
(test-eq "daemon-util start-all"
0
(marionette-eval
- '(begin
- (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
- "start-all"))
+ '(system* #$(file-append ganeti "/lib/ganeti/daemon-util")
+ "start-all")
marionette))
;; Check that the cluster is still healthy after the daemon restarts.
(test-eq "gnt-cluster verify 2"
0
(marionette-eval
- '(begin
- (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
+ '(system* #$(file-append ganeti "/sbin/gnt-cluster") "verify")
marionette))
(test-eq "watcher continue"
0
(marionette-eval
- '(begin
- (system* #$(file-append ganeti "/sbin/gnt-cluster")
- "watcher" "continue"))
+ '(system* #$(file-append ganeti "/sbin/gnt-cluster")
+ "watcher" "continue")
marionette))
;; Try accessing the RAPI.
@@ -244,9 +238,8 @@ (define* (run-ganeti-test hypervisor #:key
(test-eq "gnt-cluster destroy"
0
(marionette-eval
- '(begin
- (system* #$(file-append ganeti "/sbin/gnt-cluster")
- "destroy" "--yes-do-it"))
+ '(system* #$(file-append ganeti "/sbin/gnt-cluster")
+ "destroy" "--yes-do-it")
marionette))
(test-end))))
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 13/16] services: ganeti: Produce Shepherd timers instead of mcron jobs.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
062c86dcff350447488f600a445202a35915ad10.1742073920.git.ludo@gnu.org
* gnu/services/ganeti.scm (<ganeti-watcher-configuration>)[schedule]:
Change default value to a cron string.
(ganeti-timer): New procedure.
(ganeti-watcher-jobs): Rename to…
(ganeti-watcher-service): … this. Return Shepherd services.
(ganeti-watcher-service-type)[extensions]: Adjust accordingly.
(ganeti-cleaner-jobs): Rename to…
(ganeti-cleaner-service): … this. Return Shepherd services.
(ganeti-cleaner-service-type)[extensions]: Adjust accordingly.
(ganeti-shepherd-services): Include the watcher and cleaner services.
(ganeti-mcron-jobs): Remove.
(ganeti-service-type)[extensions]: Adjust accordingly.
* doc/guix.texi (Virtualization Services): Update ‘schedule’
documentation.

Change-Id: Id209a3c50271203dc7190c4c6d0c0ffdf6c10875
---
doc/guix.texi | 7 ++-
gnu/services/ganeti.scm | 116 +++++++++++++++++++---------------------
2 files changed, 59 insertions(+), 64 deletions(-)

Toggle diff (213 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 7f3a7ca82a..35999db9b0 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -39775,8 +39775,11 @@ Virtualization Services
@item @code{ganeti} (default: @code{ganeti})
The @code{ganeti} package to use for this service.
-@item @code{schedule} (default: @code{'(next-second-from (next-minute (range 0 60 5)))})
-How often to run the script. The default is every five minutes.
+@item @code{schedule} (default: @code{"*/5 * * * *"})
+When to run the script, expressed either as a string in traditional cron
+syntax or as a gexp representing a Shepherd calendar event
+(@pxref{Timers,,, shepherd, The GNU Shepherd Manual}). The default is
+every five minutes.
@item @code{rapi-ip} (default: @code{#f})
This option needs to be specified only if the RAPI daemon is configured to use
diff --git a/gnu/services/ganeti.scm b/gnu/services/ganeti.scm
index f905ab8395..9cab6c110a 100644
--- a/gnu/services/ganeti.scm
+++ b/gnu/services/ganeti.scm
@@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020, 2022 Marius Bakke <marius@gnu.org>
+;;; Copyright © 2025 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -19,14 +20,11 @@
(define-module (gnu services ganeti)
#:use-module (gnu packages virtualization)
#:use-module (gnu services)
- #:use-module (gnu services mcron)
#:use-module (gnu services shepherd)
#:use-module (guix gexp)
#:use-module (guix records)
-
#:use-module (srfi srfi-1)
#:use-module (ice-9 match)
-
#:export (ganeti-noded-configuration
ganeti-noded-configuration?
ganeti-noded-configuration-ganeti
@@ -644,9 +642,8 @@ (define-record-type* <ganeti-watcher-configuration>
(ganeti ganeti-watcher-configuration-ganeti ;file-like
(default ganeti))
(schedule ganeti-watcher-configuration-schedule ;list | string
- (default '(next-second-from
- ;; Run every five minutes.
- (next-minute (range 0 60 5)))))
+ ;; Run every 5 minutes.
+ (default "*/5 * * * *"))
(rapi-ip ganeti-watcher-configuration-rapi-ip ;#f | string
(default #f))
(job-age ganeti-watcher-configuration-job-age ;integer
@@ -660,36 +657,47 @@ (define ganeti-watcher-command
(match-lambda
(($ <ganeti-watcher-configuration> ganeti _ rapi-ip job-age verify-disks?
debug?)
- #~(lambda ()
- (system* #$(file-append ganeti "/sbin/ganeti-watcher")
- #$@(if rapi-ip
- #~((string-append "--rapi-ip=" #$rapi-ip))
- #~())
- #$(string-append "--job-age=" (number->string job-age))
- #$@(if verify-disks?
- #~()
- #~("--no-verify-disks"))
- #$@(if debug?
- #~("--debug")
- #~()))))))
+ #~(#$(file-append ganeti "/sbin/ganeti-watcher")
+ #$@(if rapi-ip
+ #~((string-append "--rapi-ip=" #$rapi-ip))
+ #~())
+ #$(string-append "--job-age=" (number->string job-age))
+ #$@(if verify-disks?
+ #~()
+ #~("--no-verify-disks"))
+ #$@(if debug?
+ #~("--debug")
+ #~())))))
-(define (ganeti-watcher-jobs config)
+(define (ganeti-timer name schedule command)
+ "Return a Shepherd timer providing NAME and running COMMAND, a list-valued
+gexp."
+ (shepherd-service
+ (provision (list name))
+ (requirement '(user-processes))
+ (modules '((shepherd service timer)))
+ (start #~(make-timer-constructor
+ #$(if (string? schedule)
+ #~(cron-string->calendar-event #$schedule)
+ schedule)
+ (command '(#$@command))
+ #:wait-for-termination? #t))
+ (stop #~(make-timer-destructor))
+ (documentation "Periodically run a Ganeti maintenance job.")
+ (actions (list shepherd-trigger-action))))
+
+(define (ganeti-watcher-service config)
(match config
(($ <ganeti-watcher-configuration> _ schedule)
- (list
- #~(job #$@(match schedule
- ((? string?)
- #~(#$schedule))
- ((? list?)
- #~('#$schedule)))
- #$(ganeti-watcher-command config)
- "ganeti-watcher")))))
+ (list (ganeti-timer 'ganeti-watcher
+ schedule
+ (ganeti-watcher-command config))))))
(define ganeti-watcher-service-type
(service-type (name 'ganeti-watcher)
(extensions
- (list (service-extension mcron-service-type
- ganeti-watcher-jobs)))
+ (list (service-extension shepherd-root-service-type
+ ganeti-watcher-service)))
(default-value (ganeti-watcher-configuration))
(description
"@command{ganeti-watcher} is a periodically run script that
@@ -714,34 +722,23 @@ (define-record-type* <ganeti-cleaner-configuration>
;; Run the node cleaner at 02:45 every day.
(default "45 2 * * *")))
-(define ganeti-cleaner-jobs
+(define ganeti-cleaner-service
(match-lambda
(($ <ganeti-cleaner-configuration> ganeti master-schedule node-schedule)
- (list
- #~(job #$@(match master-schedule
- ((? string?)
- #~(#$master-schedule))
- ((? list?)
- #~('#$master-schedule)))
- (lambda ()
- (system* #$(file-append ganeti "/sbin/ganeti-cleaner")
- "master"))
- "ganeti master cleaner")
- #~(job #$@(match node-schedule
- ((? string?)
- #~(#$node-schedule))
- ((? list?)
- #~('#$node-schedule)))
- (lambda ()
- (system* #$(file-append ganeti "/sbin/ganeti-cleaner")
- "node"))
- "ganeti node cleaner")))))
+ (list (ganeti-timer 'ganeti-master-cleaner
+ master-schedule
+ #~(#$(file-append ganeti "/sbin/ganeti-cleaner")
+ "master"))
+ (ganeti-timer 'ganeti-node-cleaner
+ node-schedule
+ #~(#$(file-append ganeti "/sbin/ganeti-cleaner")
+ "node"))))))
(define ganeti-cleaner-service-type
(service-type (name 'ganeti-cleaner)
(extensions
- (list (service-extension mcron-service-type
- ganeti-cleaner-jobs)))
+ (list (service-extension shepherd-root-service-type
+ ganeti-cleaner-service)))
(default-value (ganeti-cleaner-configuration))
(description
"@command{ganeti-cleaner} is a script that removes old files
@@ -804,7 +801,8 @@ (define (ganeti-activation config)
(define ganeti-shepherd-services
(match-lambda
- (($ <ganeti-configuration> _ noded confd wconfd luxid rapi kvmd mond metad)
+ (($ <ganeti-configuration> _ noded confd wconfd luxid rapi kvmd mond metad
+ watcher cleaner)
(append (ganeti-noded-service noded)
(ganeti-confd-service confd)
(ganeti-wconfd-service wconfd)
@@ -812,13 +810,9 @@ (define ganeti-shepherd-services
(ganeti-rapi-service rapi)
(ganeti-kvmd-service kvmd)
(ganeti-mond-service mond)
- (ganeti-metad-service metad)))))
-
-(define ganeti-mcron-jobs
- (match-lambda
- (($ <ganeti-configuration> _ _ _ _ _ _ _ _ _ watcher cleaner)
- (append (ganeti-watcher-jobs watcher)
- (ganeti-cleaner-jobs cleaner)))))
+ (ganeti-metad-service metad)
+ (ganeti-watcher-service watcher)
+ (ganeti-cleaner-service cleaner)))))
(define-record-type* <ganeti-os>
ganeti-os make-ganeti-os ganeti-os?
@@ -1122,9 +1116,7 @@ (define ganeti-service-type
(service-extension etc-service-type
ganeti-etc-service)
(service-extension profile-service-type
- (compose list ganeti-configuration-ganeti))
- (service-extension mcron-service-type
- ganeti-mcron-jobs)))
+ (compose list ganeti-configuration-ganeti))))
(default-value (ganeti-configuration (os %default-ganeti-os)))
(description
"Ganeti is a family of services that are designed to run
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 16/16] DRAFT news: Add entry for mcron deprecation.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
218d5ad8274680771591e5d940dcc7b7e7c0aafd.1742073920.git.ludo@gnu.org
* etc/news.scm: Add entry.

Change-Id: I7e096a8f137e20487f5dac5fca4ae5b05754f5cd
---
etc/news.scm | 13 +++++++++++++
1 file changed, 13 insertions(+)

Toggle diff (26 lines)
diff --git a/etc/news.scm b/etc/news.scm
index 8e37bc8bec..368bdb567a 100644
--- a/etc/news.scm
+++ b/etc/news.scm
@@ -37,6 +37,19 @@
(channel-news
(version 0)
+ (entry (commit "XXX")
+ (title
+ (en "Scheduled job execution with mcron superseded by Shepherd
+timers"))
+ (body
+ (en "On Guix System and Guix Home, scheduled job execution with the
+mcron package is deprecated; @code{mcron-service-type} and
+@code{home-mcron-service-type} are slated for removal after 2026-04-01.
+
+As a replacement for mcron jobs, you can use Shepherd timers---a feature that
+appeared in version 1.0 of the Shepherd. Run @command{info \"(guix) Scheduled
+Job Execution\"} for more information on how to transition.")))
+
(entry (commit "41e62cb10c3049610dc854f1d3e9b91aebd73aed")
(title
(en "Removable devices now mount under @file{/run/media/$USER} instead of @file{/media}")
--
2.48.1
Ludovic Courtès wrote 35 hours ago
[PATCH 15/16] services: mcron: Deprecate.
(address . 77041@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
9c83cf458fc508990a834cecac3f9d8cbd74df87.1742073920.git.ludo@gnu.org
* gnu/services/mcron.scm (mcron-service-type): Mark as deprecated.
* gnu/home/services/mcron.scm (home-mcron-service-type): Likewise.
* doc/guix.texi (Scheduled Job Execution): Document it.
(Mcron Home Service): Likewise.

Change-Id: I0329bf1ef5026d6b7d392a5807f0600ff28c3006
---
doc/guix.texi | 18 ++++++++++++++++++
gnu/home/services/mcron.scm | 7 +++++--
gnu/services/mcron.scm | 7 +++++--
3 files changed, 28 insertions(+), 4 deletions(-)

Toggle diff (100 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 35999db9b0..19342c22a3 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -20851,6 +20851,18 @@ Scheduled Job Execution
@cindex cron
@cindex mcron
@cindex scheduling jobs
+@quotation Deprecation Warning
+This section describes the mcron service, which is deprecated and slated
+for removal after 2026-04-01.
+
+The Shepherd supports running jobs periodically by defining services as
+@dfn{timers}. @xref{Shepherd Services} for information on defining
+Shepherd services in Guix, and @ref{Timers,,, shepherd, The GNU Shepherd
+Manual} for information on Shepherd timers.
+
+Please use the Shepherd instead mcron.
+@end quotation
+
The @code{(gnu services mcron)} module provides an interface to
GNU@tie{}mcron, a daemon to run jobs at scheduled times (@pxref{Top,,,
mcron, GNU@tie{}mcron}). GNU@tie{}mcron is similar to the traditional
@@ -48514,6 +48526,12 @@ Mcron Home Service
@cindex mcron
@cindex scheduling jobs
+@quotation Deprecation Warning
+The @code{home-mcron-service-type} described below is superseded by
+Shepherd timers and slated for removal after 2026-04-01.
+@xref{Scheduled Job Execution}, for more information.
+@end quotation
+
The @code{(gnu home services mcron)} module provides an interface to
GNU@tie{}mcron, a daemon to run jobs at scheduled times (@pxref{Top,,,
mcron, GNU@tie{}mcron}). The information about system's mcron is
diff --git a/gnu/home/services/mcron.scm b/gnu/home/services/mcron.scm
index 23be44ba07..57b92da2eb 100644
--- a/gnu/home/services/mcron.scm
+++ b/gnu/home/services/mcron.scm
@@ -2,7 +2,7 @@
;;; Copyright © 2021, 2023 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
-;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2023, 2025 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -20,6 +20,7 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services mcron)
+ #:use-module (guix deprecation)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (gnu services mcron) ;for the service mapping
@@ -53,7 +54,9 @@ (define-syntax-rule (home-mcron-configuration fields ...)
;; Macro provided for backward compatibility.
(for-home (mcron-configuration fields ...)))
-(define home-mcron-service-type
+;; TODO: Deprecated; remove sometime after 2026-04-01.
+(define-deprecated home-mcron-service-type
+ home-shepherd-service-type
(service-type
(inherit (system->home-service-type mcron-service-type))
(default-value (for-home (mcron-configuration)))))
diff --git a/gnu/services/mcron.scm b/gnu/services/mcron.scm
index 0e0d07d252..0bb0ae7450 100644
--- a/gnu/services/mcron.scm
+++ b/gnu/services/mcron.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2016-2020, 2023 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016-2020, 2023, 2025 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
;;;
@@ -22,6 +22,7 @@ (define-module (gnu services mcron)
#:use-module (gnu services)
#:use-module (gnu services shepherd)
#:use-module (gnu packages guile-xyz)
+ #:use-module (guix deprecation)
#:use-module (guix records)
#:use-module (guix gexp)
#:use-module (srfi srfi-1)
@@ -194,7 +195,9 @@ (define (mcron-shepherd-services config)
(actions
(list (shepherd-schedule-action mcron files)))))))))
-(define mcron-service-type
+;; TODO: Deprecated; remove sometime after 2026-04-01.
+(define-deprecated mcron-service-type
+ shepherd-root-service-type
(service-type (name 'mcron)
(description
"Run the mcron job scheduling daemon.")
--
2.48.1
pelzflorian (Florian Pelz) wrote 23 hours ago
Re: [bug#77041] [PATCH 16/16] DRAFT news: Add entry for mcron deprecation.
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 77041@debbugs.gnu.org)
87y0x5jp99.fsf@pelzflorian.de
Thank you Ludo for not only transitioning Guix but also for
cleanups/refactoring here in this patch series. Looks good to me mostly
but have not tested nor carefully checked the Scheme code.

For fstrim doc/guix.texi,
(type: shepherd-calendar-event) in the documentation might be better
expressed as “type: Shepherd calendar event”, as there is no
shepherd-calendar-event.

For fstrim, you also removed the quoting ' of lists:
-@item @code{listed-in} (default: @code{'("/etc/fstab" "/proc/self/mountinfo")}) (type: maybe-list-of-strings)
+@item @code{listed-in} (default: @code{("/etc/fstab" "/proc/self/mountinfo")}) (type: maybe-list-of-strings)

I still prefer quoting, as users need the quote in their configuration
files.

For [PATCH 15/16] services: mcron: Deprecate.
I spot one typo / missing “instead of” in doc/guix.texi:
+Please use the Shepherd instead mcron.

Could you add the following German translation:
(entry (commit "XXX") (title (en "Scheduled job execution with mcron superseded by Shepherd timers") (de "Geplante Auftragsausführung mit mcron abgelöst durch Shepherd-Timer")) (body (en "On Guix System and Guix Home, scheduled job execution with the mcron package is deprecated; @code{mcron-service-type} and @code{home-mcron-service-type} are slated for removal after 2026-04-01. As a replacement for mcron jobs, you can use Shepherd timers---a feature that appeared in version 1.0 of the Shepherd. Run @command{info \"(guix) Scheduled Job Execution\"} for more information on how to transition.") (de "Auf Guix System und Guix Home gilt geplante Auftragsausführung mit dem mcron-Paket als veraltet. Es ist vorgesehen, @code{mcron-service-type} und @code{home-mcron-service-type} nach dem 01.04.2026 zu entfernen. Als Ersatz für mcron-Aufträge können Sie auf Shepherd-Timer umsteigen – diese Funktion ist seit Shepherds Version 1.0 verfügbar. Führen Sie @command{info \"(guix.de) Geplante Auftragsausführung\"} aus, um weitere Informationen zum Umstieg zu bekommen.")))
Regards,
Florian
Maxim Cournoyer wrote 21 hours ago
Re: [bug#77041] [PATCH 15/16] services: mcron: Deprecate.
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Tanguy Le Carrour)(address . tanguy@bioneland.org)(name . Janneke Nieuwenhuizen)(address . janneke@gnu.org)(address . 77041@debbugs.gnu.org)(name . Andrew Tropin)(address . andrew@trop.in)
87iko919hf.fsf@gmail.com
Hi,

Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (5 lines)
> * gnu/services/mcron.scm (mcron-service-type): Mark as deprecated.
> * gnu/home/services/mcron.scm (home-mcron-service-type): Likewise.
> * doc/guix.texi (Scheduled Job Execution): Document it.
> (Mcron Home Service): Likewise.

While I think some documentation to mention that Shepherd timers can be
used instead of mcron for most cases, I do not see this as a reason to
deprecate nor remove the mcron service itself, just like we do not
remove system services when new, perhaps more modern alternatives get
added.

--
Thanks,
Maxim
Maxim Cournoyer wrote 21 hours ago
Re: [bug#77041] [PATCH 16/16] DRAFT news: Add entry for mcron deprecation.
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 77041@debbugs.gnu.org)(name . Florian Pelz)(address . pelzflorian@pelzflorian.de)
87a59l18gy.fsf@gmail.com
Hi Ludovic,

Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (29 lines)
> * etc/news.scm: Add entry.
>
> Change-Id: I7e096a8f137e20487f5dac5fca4ae5b05754f5cd
> ---
> etc/news.scm | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/etc/news.scm b/etc/news.scm
> index 8e37bc8bec..368bdb567a 100644
> --- a/etc/news.scm
> +++ b/etc/news.scm
> @@ -37,6 +37,19 @@
> (channel-news
> (version 0)
>
> + (entry (commit "XXX")
> + (title
> + (en "Scheduled job execution with mcron superseded by Shepherd
> +timers"))
> + (body
> + (en "On Guix System and Guix Home, scheduled job execution with the
> +mcron package is deprecated; @code{mcron-service-type} and
> +@code{home-mcron-service-type} are slated for removal after 2026-04-01.
> +
> +As a replacement for mcron jobs, you can use Shepherd timers---a feature that
> +appeared in version 1.0 of the Shepherd. Run @command{info \"(guix) Scheduled
> +Job Execution\"} for more information on how to transition.")))
> +

I'd turn this into a soft-deprecation: document Shepherd timers as the
preferred alternative to use in most scenarios such as when authoring
Guix System or home services,, but leave otherwise leave the
mcron-service-type and home-mcron-service-type services be.

--
Thanks,
Maxim
Maxim Cournoyer wrote 21 hours ago
Re: [bug#77041] [PATCH 00/16] Replacing mcron jobs by Shepherd timers
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 77041@debbugs.gnu.org)(name . Florian Pelz)(address . pelzflorian@pelzflorian.de)
875xk918ei.fsf@gmail.com
Hi,

Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (7 lines)
> Hello,
>
> This is the last step of the Shepherd 1.0 transition, leading
> to the deprecation of mcron, superseded by Shepherd timers.
>
> Thoughts?

Like Florian, I've read the diffs only, haven't applied nor built nor
test, but it looks reasonable to me, except the hard deprecation and
removal, which is unnecessary.

With the hard deprecation turned into a soft deprecation, it'd LGTM.

Reviewed-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>

--
Thanks,
Maxim
Luis Guilherme Coelho wrote 20 hours ago
Re: [bug#77041] [PATCH 15/16] services: mcron: Deprecate.
(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 77041@debbugs.gnu.org)(name . Andrew Tropin)(address . andrew@trop.in)(name . Tanguy Le Carrour)(address . tanguy@bioneland.org)(name . Janneke Nieuwenhuizen)(address . janneke@gnu.org)
D8HPV5FYPXTM.4XD3QWPNVVSE@disroot.org
Toggle quote (6 lines)
> While I think some documentation to mention that Shepherd timers can be
> used instead of mcron for most cases, I do not see this as a reason to
> deprecate nor remove the mcron service itself, just like we do not
> remove system services when new, perhaps more modern alternatives get
> added.

+1 on this.

Also, in the current state, while timers can be used in most places a
mcron service would be used normally, defining timer services is
somewhat more verbose. For example, defining an alarm service with mcron
is as simple as (1):

(simple-service 'home-alarm-service
home-mcron-service-type
(home-mcron-configuration
(jobs (list #~(job "0 6 * * *"
"mpv --shuffle ~/media/music")))))

While doing it with shepherd would be something like (2):

(simple-service 'home-alarm-service
home-shepherd-service-type
(list (shepherd-service
(provision '(alarm))
(modules '((shepherd service timer)))
(start #~(make-timer-constructor
(calendar-event #:hours '(6)
#:minutes '(0))
(command '("mpv" "--shuffle" "~/media/music"))))
(stop #~(make-timer-destructor))
(actions (list shepherd-trigger-action)))))

I guess we could make it more succint by defining a
`home-shepherd-timer-service-type` (this name is already in use, but I
don't know a better one) for these timers services to extend, as I do
here:


With these definitions, the alarm service could be written, using
shepherd timers as (3):

(simple-service 'home-alarm-service
home-shepherd-timer-service-type
(list (shepherd-timer
(name 'alarm)
(event #~(calendar-event #:hours '(6)
#:minutes '(0)))
(action #~(command '("mpv" "--shuffle" "~/media/music"))))))

Which is only two lines longer than (1), while (2) is six lines longer.
I think the various services that provide shepherd timers would also
benefit from these definitions.

WDYT?

PS. I've sent this mail before but by mistake it was sent only to
Maxim, please disregard.
Tomas Volf wrote 18 hours ago
(name . Luis Guilherme Coelho via Guix-patches via)(address . guix-patches@gnu.org)(name . Luis Guilherme Coelho)(address . lgcoelho@disroot.org)(name . Tanguy Le Carrour)(address . tanguy@bioneland.org)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)(name . Ludovic Cour tès)(address . ludo@gnu.org)(name . Andrew Tropin)(address . andrew@trop.in)(address . 77041@debbugs.gnu.org)(name . Janneke Nieuwenhuizen)(address . janneke@gnu.org)
87senduim2.fsf@wolfsden.cz
Luis Guilherme Coelho via Guix-patches via <guix-patches@gnu.org>
writes:

Toggle quote (18 lines)
>> While I think some documentation to mention that Shepherd timers can be
>> used instead of mcron for most cases, I do not see this as a reason to
>> deprecate nor remove the mcron service itself, just like we do not
>> remove system services when new, perhaps more modern alternatives get
>> added.
>
> +1 on this.
>
> Also, in the current state, while timers can be used in most places a
> mcron service would be used normally, defining timer services is
> somewhat more verbose.
>
> [..]
>
> Which is only two lines longer than (1), while (2) is six lines longer.
> I think the various services that provide shepherd timers would also
> benefit from these definitions.

In my own configuration I went as far as:

Toggle snippet (7 lines)
(services
(cron-timer 'cron-btrfs-scrub-raid
"0 4 1,15 * *"
(script/btrfs-scrub "/raid"))
...)

And it even sends emails with the output, as crons should.

I am not saying Guix proper needs to go as far as I did, but I agree
that currently defining Shepherd timers is bit too verbose.

Tomas

--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
Tomas Volf wrote 18 hours ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Tanguy Le Carrour)(address . tanguy@bioneland.org)(name . Janneke Nieuwenhuizen)(address . janneke@gnu.org)(address . 77041@debbugs.gnu.org)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)(name . Andrew Tropin)(address . andrew@trop.in)
87o6y1uiee.fsf@wolfsden.cz
Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (7 lines)
> +@quotation Deprecation Warning
> +The @code{home-mcron-service-type} described below is superseded by
> +Shepherd timers and slated for removal after 2026-04-01.
> +@xref{Scheduled Job Execution}, for more information.
> +@end quotation
> +

Currently timers lack the ability to send email with the cron output,
something mcron can do. Is that something you plan to address before
removing the mcron-service-type?

(Albeit saying "no" would probably be justified, the email sending was
broken for a long time and no one noticed, so I am unsure whether people
actually use it.)

Tomas

--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
Ludovic Courtès wrote 16 hours ago
Re: [bug#77041] [PATCH 16/16] DRAFT news: Add entry for mcron deprecation.
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 77041@debbugs.gnu.org)
87o6y0oq7h.fsf@gnu.org
Hi Florian,

"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> skribis:

Toggle quote (4 lines)
> Thank you Ludo for not only transitioning Guix but also for
> cleanups/refactoring here in this patch series. Looks good to me mostly
> but have not tested nor carefully checked the Scheme code.

Thanks!

Toggle quote (9 lines)
> For fstrim doc/guix.texi,
> (type: shepherd-calendar-event) in the documentation might be better
> expressed as “type: Shepherd calendar event”, as there is no
> shepherd-calendar-event.
>
> For fstrim, you also removed the quoting ' of lists:
> -@item @code{listed-in} (default: @code{'("/etc/fstab" "/proc/self/mountinfo")}) (type: maybe-list-of-strings)
> +@item @code{listed-in} (default: @code{("/etc/fstab" "/proc/self/mountinfo")}) (type: maybe-list-of-strings)

This was generated by:

(configuration->documentation 'fstrim-configuration)

I was surprised also by the lack of quote but I suspected this had been
discussed before and implemented in ‘define-configuration’. If not, we
should report a bug for that.

I took note of the other issues you reported and will fix them for v2.

Ludo’.
Ludovic Courtès wrote 16 hours ago
Re: [bug#77041] [PATCH 15/16] services: mcron: Deprecate.
(name . Luis Guilherme Coelho)(address . lgcoelho@disroot.org)(name . Tanguy Le Carrour)(address . tanguy@bioneland.org)(name . Janneke Nieuwenhuizen)(address . janneke@gnu.org)(address . 77041@debbugs.gnu.org)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)(name . Andrew Tropin)(address . andrew@trop.in)
87cyegoptf.fsf@gnu.org
Hello,

"Luis Guilherme Coelho" <lgcoelho@disroot.org> skribis:

Toggle quote (8 lines)
>> While I think some documentation to mention that Shepherd timers can be
>> used instead of mcron for most cases, I do not see this as a reason to
>> deprecate nor remove the mcron service itself, just like we do not
>> remove system services when new, perhaps more modern alternatives get
>> added.
>
> +1 on this.

To be honest, I also wondered about deprecation: I do value internal
consistency (I think services provided by Guix itself should all use the
same tool), but I think it’s OK if people want to keep using mcron.

So yes, some sort of “soft deprecation” as Maxim wrote sounds
reasonable to me.

Thoughts?

Toggle quote (5 lines)
> Also, in the current state, while timers can be used in most places a
> mcron service would be used normally, defining timer services is
> somewhat more verbose. For example, defining an alarm service with mcron
> is as simple as (1):

[...]

Toggle quote (7 lines)
> I guess we could make it more succint by defining a
> `home-shepherd-timer-service-type` (this name is already in use, but I
> don't know a better one) for these timers services to extend, as I do
> here:
>
> https://codeberg.org/anemofilia/radix/src/branch/main/radix/services/shepherd.scm

Yes, I was going to suggest something like this.

Could something similar to the ‘ganeti-timer’ procedure introduced in
this patch series?

(define (ganeti-timer name schedule command)
"Return a Shepherd timer providing NAME and running COMMAND, a list-valued
gexp."
(shepherd-service
(provision (list name))
(requirement '(user-processes))
(modules '((shepherd service timer)))
(start #~(make-timer-constructor
#$(if (string? schedule)
#~(cron-string->calendar-event #$schedule)
schedule)
(command '(#$@command))
#:wait-for-termination? #t))
(stop #~(make-timer-destructor))
(documentation "Periodically run a Ganeti maintenance job.")
(actions (list shepherd-trigger-action))))

Or maybe something higher-level that would extend
‘shepherd-root-service-type’?

Perhaps this should be done independently of this patch series though.

Thanks,
Ludo’.
Ludovic Courtès wrote 16 hours ago
(name . Tomas Volf)(address . ~@wolfsden.cz)(address . 77041@debbugs.gnu.org)(name . Andrew Tropin)(address . andrew@trop.in)(name . Tanguy Le Carrour)(address . tanguy@bioneland.org)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)(name . Janneke Nieuwenhuizen)(address . janneke@gnu.org)
87zfhknb58.fsf@gnu.org
Tomas Volf <~@wolfsden.cz> skribis:

Toggle quote (12 lines)
> Ludovic Courtès <ludo@gnu.org> writes:
>
>> +@quotation Deprecation Warning
>> +The @code{home-mcron-service-type} described below is superseded by
>> +Shepherd timers and slated for removal after 2026-04-01.
>> +@xref{Scheduled Job Execution}, for more information.
>> +@end quotation
>> +
>
> Currently timers lack the ability to send email with the cron output,
> something mcron can do. Is that something you plan to address

No. :-)

I think it’s more convenient, more flexible, and safer to implement as a
higher-level mechanism, like you did in your personal services IIRC.

WDYT?

Ludo’.
Tomas Volf wrote 12 hours ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 77041@debbugs.gnu.org)(name . Andrew Tropin)(address . andrew@trop.in)(name . Tanguy Le Carrour)(address . tanguy@bioneland.org)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)(name . Janneke Nieuwenhuizen)(address . janneke@gnu.org)
875xk8vfcr.fsf@wolfsden.cz
Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (21 lines)
> Tomas Volf <~@wolfsden.cz> skribis:
>
>> Ludovic Courtès <ludo@gnu.org> writes:
>>
>>> +@quotation Deprecation Warning
>>> +The @code{home-mcron-service-type} described below is superseded by
>>> +Shepherd timers and slated for removal after 2026-04-01.
>>> +@xref{Scheduled Job Execution}, for more information.
>>> +@end quotation
>>> +
>>
>> Currently timers lack the ability to send email with the cron output,
>> something mcron can do. Is that something you plan to address
>
> No. :-)
>
> I think it’s more convenient, more flexible, and safer to implement as a
> higher-level mechanism, like you did in your personal services IIRC.
>
> WDYT?

Yeah, I think that is a reasonable approach. ^_^

Tomas

--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
-----BEGIN PGP SIGNATURE-----

iQJCBAEBCgAsFiEEt4NJs4wUfTYpiGikL7/ufbZ/wakFAmfXQYQOHH5Ad29sZnNk
ZW4uY3oACgkQL7/ufbZ/wakEeA//Q6lWn+QRI4viy3GuSILTKN8xqrXsVIn+Ls1b
fOmcs3DaXE2CGxMNomap4l0jG2gXP8sfLAKpieVYZdIdF/ktrRC19vwF5MDEQ6Vt
RSyVJRqbqHx5fjNymOdWJmSR6mjMaI1meVM6YsUa+Oa5IJf0g2YZZQDTstVok/5E
ptYHqPvXrzLMcXWBnKN3pnzAJ9q85bmMzgVMeyom3au/kUHDM2TrNw1UOYq0w914
L06NPf9y6pEDw4B0vXEAehM/HKAcQTF3oE1uOonyEYY4STiY2MOszfljFYWcDI6d
VThz3yGwKRgaFwK0s+cynyOpLKvf8QZP7BUr3yhOMCancBiHvLqt1/NwMTOawN8+
gdB6kYQ6V/CacPu2VX6q9qCy8axI4yjUR1VDsRP0ah5WCxFpxv2iKZsY8GDJ/dgU
nXi6WBGor1MwxynyIwt21DqVSpTe0d5PLJzLaykIyeKGWKQkewQNWpCCtR4LtBmB
8WE4QJ5T1MYzLYpJzpr/9kyf7rQLMJ0kyRYJ+SZgT5z6YlYDP5Ut6JF9ctkO6t4B
iQ+OYzbtvRUoZqayrGlw9i8pLrW/H4WRBS9lSVOwP+VkfSn1AqL78yYpXKeM0/ai
5GBGgVdOx6SkAYtFlV4T9/9/lA2aM3VoYZpKb6dhmD0uXYBHG6wD1AhjC0XM/7/W
LH1nZk8=
=fmgp
-----END PGP SIGNATURE-----

Bruno Victal wrote 5 hours ago
Re: [bug#77041] [PATCH 16/16] DRAFT news: Add entry for mcron deprecation.
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 77041@debbugs.gnu.org)
2e961821-d36b-4737-8894-b9b95d9fde77@makinata.eu
Hi Ludo’,

On 2025-03-16 17:11, Ludovic Courtès wrote:
Toggle quote (14 lines)
> "pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> skribis:
>>
>> For fstrim, you also removed the quoting ' of lists:
>> -@item @code{listed-in} (default: @code{'("/etc/fstab" "/proc/self/mountinfo")}) (type: maybe-list-of-strings)
>> +@item @code{listed-in} (default: @code{("/etc/fstab" "/proc/self/mountinfo")}) (type: maybe-list-of-strings)
>
> This was generated by:
>
> (configuration->documentation 'fstrim-configuration)
>
> I was surprised also by the lack of quote but I suspected this had been
> discussed before and implemented in ‘define-configuration’. If not, we
> should report a bug for that.

You didn't do anything wrong, this is a current bug/limitation of
configuration->documentation, I added those quotes manually when I
generated the documentation for that service.

--
Cheers,
Bruno.
Sergey Trofimov wrote 39 minutes ago
Re: [bug#77041] [PATCH 00/16] Replacing mcron jobs by Shepherd timers
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 77041@debbugs.gnu.org)(name . Florian Pelz)(address . pelzflorian@pelzflorian.de)
87tt7sxe79.fsf@sarg.org.ru
Hi Ludovic,

Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (8 lines)
> Hello,
>
> This is the last step of the Shepherd 1.0 transition, leading
> to the deprecation of mcron, superseded by Shepherd timers.
>
> Thoughts?
>

Chiming in unrelated to the proposed changes. Neither mcron nor shepherd
timers work correctly on machines that spend time asleep (e.g. laptops).
It makes backup / fstrim / log rotation schedules unreliable and
therefore forces the user to look for alternatives. I currently use
?
Your comment

Commenting via the web interface is currently disabled.

To comment on this conversation send an email to 77041@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 77041
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch
You may also tag this issue. See list of standard tags. For example, to set the confirmed and easy tags
mumi command -t +confirmed -t +easy
Or, remove the moreinfo tag and set the help tag
mumi command -t -moreinfo -t +help