services: Add 'unattended-upgrade-service-type'.
* gnu/services/admin.scm (<unattended-upgrade-configuration>): New record type. (%unattended-upgrade-log-file): New variable. (unattended-upgrade-mcron-jobs, unattended-upgrade-log-rotations): New procedures. (unattended-upgrade-service-type): New variable. * doc/guix.texi (Service Reference): Add 'provenance-service-type' anchor. (Unattended Upgrades): New section.
This commit is contained in:
parent
c20e697ea1
commit
79501f26ab
113
doc/guix.texi
113
doc/guix.texi
@ -12926,6 +12926,7 @@ declaration.
|
||||
* Scheduled Job Execution:: The mcron service.
|
||||
* Log Rotation:: The rottlog service.
|
||||
* Networking Services:: Network setup, SSH daemon, etc.
|
||||
* Unattended Upgrades:: Automated system upgrades.
|
||||
* X Window:: Graphical display.
|
||||
* Printing Services:: Local and remote printer support.
|
||||
* Desktop Services:: D-Bus and desktop services.
|
||||
@ -15298,6 +15299,117 @@ Use this to add additional options and manage shared secrets out-of-band.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@node Unattended Upgrades
|
||||
@subsection Unattended Upgrades
|
||||
|
||||
@cindex unattended upgrades
|
||||
@cindex upgrades, unattended
|
||||
Guix provides a service to perform @emph{unattended upgrades}:
|
||||
periodically, the system automatically reconfigures itself from the
|
||||
latest Guix. Guix System has several properties that make unattended
|
||||
upgrades safe:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
upgrades are transactional (either the upgrade succeeds or it fails, but
|
||||
you cannot end up with an ``in-between'' system state);
|
||||
@item
|
||||
the upgrade log is kept---you can view it with @command{guix system
|
||||
list-generations}---and you can roll back to any previous generation,
|
||||
should the upgraded system fail to behave as intended;
|
||||
@item
|
||||
channel code is authenticated so you know you can only run genuine code
|
||||
(@pxref{Channels});
|
||||
@item
|
||||
@command{guix system reconfigure} prevents downgrades, which makes it
|
||||
immune to @dfn{downgrade attacks}.
|
||||
@end itemize
|
||||
|
||||
To set up unattended upgrades, add an instance of
|
||||
@code{unattended-upgrade-service-type} like the one below to the list of
|
||||
your operating system services:
|
||||
|
||||
@lisp
|
||||
(service unattended-upgrade-service-type)
|
||||
@end lisp
|
||||
|
||||
The defaults above set up weekly upgrades: every Sunday at midnight.
|
||||
You do not need to provide the operating system configuration file: it
|
||||
uses @file{/run/current-system/configuration.scm}, which ensures it
|
||||
always uses your latest configuration---@pxref{provenance-service-type},
|
||||
for more information about this file.
|
||||
|
||||
There are several things that can be configured, in particular the
|
||||
periodicity and services (daemons) to be restarted upon completion.
|
||||
When the upgrade is successful, the service takes care of deleting
|
||||
system generations older that some threshold, as per @command{guix
|
||||
system delete-generations}. See the reference below for details.
|
||||
|
||||
To ensure that upgrades are actually happening, you can run
|
||||
@command{guix system describe}. To investigate upgrade failures, visit
|
||||
the unattended upgrade log file (see below).
|
||||
|
||||
@defvr {Scheme Variable} unattended-upgrade-service-type
|
||||
This is the service type for unattended upgrades. It sets up an mcron
|
||||
job (@pxref{Scheduled Job Execution}) that runs @command{guix system
|
||||
reconfigure} from the latest version of the specified channels.
|
||||
|
||||
Its value must be a @code{unattended-upgrade-configuration} record (see
|
||||
below).
|
||||
@end defvr
|
||||
|
||||
@deftp {Data Type} unattended-upgrade-configuration
|
||||
This data type represents the configuration of the unattended upgrade
|
||||
service. The following fields are available:
|
||||
|
||||
@table @asis
|
||||
@item @code{schedule} (default: @code{"30 01 * * 0"})
|
||||
This is the schedule of upgrades, expressed as a gexp containing an
|
||||
mcron job schedule (@pxref{Guile Syntax, mcron job specifications,,
|
||||
mcron, GNU@tie{}mcron}).
|
||||
|
||||
@item @code{channels} (default: @code{#~%default-channels})
|
||||
This gexp specifies the channels to use for the upgrade
|
||||
(@pxref{Channels}). By default, the tip of the official @code{guix}
|
||||
channel is used.
|
||||
|
||||
@item @code{services-to-restart} (default: @code{'(mcron)})
|
||||
This field specifies the Shepherd services to restart when the upgrade
|
||||
completes.
|
||||
|
||||
Those services are restarted right away upon completion, as with
|
||||
@command{herd restart}, which ensures that the latest version is
|
||||
running---remember that by default @command{guix system reconfigure}
|
||||
only restarts services that are not currently running, which is
|
||||
conservative: it minimizes disruption but leaves outdated services
|
||||
running.
|
||||
|
||||
By default, the @code{mcron} service is restarted. This ensures that
|
||||
the latest version of the unattended upgrade job will be used next time.
|
||||
|
||||
@item @code{system-expiration} (default: @code{(* 3 30 24 3600)})
|
||||
This is the expiration time in seconds for system generations. System
|
||||
generations older that this amount of time are deleted with
|
||||
@command{guix system delete-generations} when an upgrade completes.
|
||||
|
||||
@quotation Note
|
||||
The unattended upgrade service does not run the garbage collector. You
|
||||
will probably want to set up your own mcron job to run @command{guix gc}
|
||||
periodically.
|
||||
@end quotation
|
||||
|
||||
@item @code{maximum-duration} (default: @code{3600})
|
||||
Maximum duration in seconds for the upgrade; past that time, the upgrade
|
||||
aborts.
|
||||
|
||||
This is primarily useful to ensure the upgrade does not end up
|
||||
rebuilding or re-downloading ``the world''.
|
||||
|
||||
@item @code{log-file} (default: @code{"/var/log/unattended-upgrade.log"})
|
||||
File where unattended upgrades are logged.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@node X Window
|
||||
@subsection X Window
|
||||
|
||||
@ -29628,6 +29740,7 @@ extend it by passing it lists of packages to add to the system profile.
|
||||
@end defvr
|
||||
|
||||
@cindex provenance tracking, of the operating system
|
||||
@anchor{provenance-service-type}
|
||||
@defvr {Scheme Variable} provenance-service-type
|
||||
This is the type of the service that records @dfn{provenance meta-data}
|
||||
in the system itself. It creates several files under
|
||||
|
@ -1,6 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
|
||||
;;; Copyright © 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
@ -20,10 +20,13 @@
|
||||
|
||||
(define-module (gnu services admin)
|
||||
#:use-module (gnu packages admin)
|
||||
#:use-module (gnu packages certs)
|
||||
#:use-module (gnu packages package-management)
|
||||
#:use-module (gnu services)
|
||||
#:use-module (gnu services mcron)
|
||||
#:use-module (gnu services shepherd)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix modules)
|
||||
#:use-module (guix packages)
|
||||
#:use-module (guix records)
|
||||
#:use-module (srfi srfi-1)
|
||||
@ -41,7 +44,17 @@
|
||||
rottlog-configuration
|
||||
rottlog-configuration?
|
||||
rottlog-service
|
||||
rottlog-service-type))
|
||||
rottlog-service-type
|
||||
|
||||
unattended-upgrade-service-type
|
||||
unattended-upgrade-configuration
|
||||
unattended-upgrade-configuration?
|
||||
unattended-upgrade-configuration-channels
|
||||
unattended-upgrade-configuration-schedule
|
||||
unattended-upgrade-configuration-services-to-restart
|
||||
unattended-upgrade-configuration-system-expiration
|
||||
unattended-upgrade-configuration-maximum-duration
|
||||
unattended-upgrade-configuration-log-file))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
@ -177,4 +190,127 @@ Old log files are removed or compressed according to the configuration.")
|
||||
rotations)))))
|
||||
(default-value (rottlog-configuration))))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Unattended upgrade.
|
||||
;;;
|
||||
|
||||
(define-record-type* <unattended-upgrade-configuration>
|
||||
unattended-upgrade-configuration make-unattended-upgrade-configuration
|
||||
unattended-upgrade-configuration?
|
||||
(schedule unattended-upgrade-configuration-schedule
|
||||
(default "30 01 * * 0"))
|
||||
(channels unattended-upgrade-configuration-channels
|
||||
(default #~%default-channels))
|
||||
(services-to-restart unattended-upgrade-configuration-services-to-restart
|
||||
(default '(mcron)))
|
||||
(system-expiration unattended-upgrade-system-expiration
|
||||
(default (* 3 30 24 3600)))
|
||||
(maximum-duration unattended-upgrade-maximum-duration
|
||||
(default 3600))
|
||||
(log-file unattended-upgrade-configuration-log-file
|
||||
(default %unattended-upgrade-log-file)))
|
||||
|
||||
(define %unattended-upgrade-log-file
|
||||
"/var/log/unattended-upgrade.log")
|
||||
|
||||
(define (unattended-upgrade-mcron-jobs config)
|
||||
(define channels
|
||||
(scheme-file "channels.scm"
|
||||
(unattended-upgrade-configuration-channels config)))
|
||||
|
||||
(define log
|
||||
(unattended-upgrade-configuration-log-file config))
|
||||
|
||||
(define services
|
||||
(unattended-upgrade-configuration-services-to-restart config))
|
||||
|
||||
(define expiration
|
||||
(unattended-upgrade-system-expiration config))
|
||||
|
||||
(define code
|
||||
(with-imported-modules (source-module-closure '((guix build utils)
|
||||
(gnu services herd)))
|
||||
#~(begin
|
||||
(use-modules (guix build utils)
|
||||
(gnu services herd)
|
||||
(srfi srfi-19)
|
||||
(srfi srfi-34))
|
||||
|
||||
(define log
|
||||
(open-file #$log "a0"))
|
||||
|
||||
(define (timestamp)
|
||||
(date->string (time-utc->date (current-time time-utc))
|
||||
"[~4]"))
|
||||
|
||||
(define (alarm-handler . _)
|
||||
(format #t "~a time is up, aborting upgrade~%"
|
||||
(timestamp))
|
||||
(exit 1))
|
||||
|
||||
(define-syntax-rule (with-logging exp ...)
|
||||
(with-output-to-port log
|
||||
(lambda ()
|
||||
(with-error-to-port log
|
||||
(lambda ()
|
||||
exp ...)))))
|
||||
|
||||
;; 'guix time-machine' needs X.509 certificates to authenticate the
|
||||
;; Git host.
|
||||
(setenv "SSL_CERT_DIR"
|
||||
#$(file-append nss-certs "/etc/ssl/certs"))
|
||||
|
||||
;; Make sure the upgrade doesn't take too long.
|
||||
(sigaction SIGALRM alarm-handler)
|
||||
(alarm #$(unattended-upgrade-maximum-duration config))
|
||||
|
||||
(with-logging
|
||||
(format #t "~a starting upgrade...~%" (timestamp))
|
||||
(guard (c ((invoke-error? c)
|
||||
(report-invoke-error c)))
|
||||
(invoke #$(file-append guix "/bin/guix")
|
||||
"time-machine" "-C" #$channels
|
||||
"--" "system" "reconfigure"
|
||||
"/run/current-system/configuration.scm")
|
||||
|
||||
;; 'guix system delete-generations' fails when there's no
|
||||
;; matching generation. Thus, catch 'invoke-error?'.
|
||||
(guard (c ((invoke-error? c)
|
||||
(report-invoke-error c)))
|
||||
(invoke #$(file-append guix "/bin/guix")
|
||||
"system" "delete-generations"
|
||||
#$(string-append (number->string expiration)
|
||||
"s")))
|
||||
|
||||
(format #t "~a restarting services...~%" (timestamp))
|
||||
(for-each restart-service '#$services)
|
||||
|
||||
;; XXX: If 'mcron' has been restarted, perhaps this isn't
|
||||
;; reached.
|
||||
(format #t "~a upgrade complete~%" (timestamp)))))))
|
||||
|
||||
(define upgrade
|
||||
(program-file "unattended-upgrade" code))
|
||||
|
||||
(list #~(job #$(unattended-upgrade-configuration-schedule config)
|
||||
#$upgrade)))
|
||||
|
||||
(define (unattended-upgrade-log-rotations config)
|
||||
(list (log-rotation
|
||||
(files
|
||||
(list (unattended-upgrade-configuration-log-file config))))))
|
||||
|
||||
(define unattended-upgrade-service-type
|
||||
(service-type
|
||||
(name 'unattended-upgrade)
|
||||
(extensions
|
||||
(list (service-extension mcron-service-type
|
||||
unattended-upgrade-mcron-jobs)
|
||||
(service-extension rottlog-service-type
|
||||
unattended-upgrade-log-rotations)))
|
||||
(description
|
||||
"Periodically upgrade the system from the current configuration.")
|
||||
(default-value (unattended-upgrade-configuration))))
|
||||
|
||||
;;; admin.scm ends here
|
||||
|
Loading…
Reference in New Issue
Block a user