Hi! Commit 033adfe in Guix adds the (gnu system) Guile module, which is a first stab at providing a declarative system configuration mechanism. This is inspired by NixOS, and is also probably familiar to users of Puppet or Chef. Currently it’s only used to build a QEMU image, but in the not-too-distant future it will be used to build installer images, and actual system images. Below is the doc I’ve written to describe the spirit of that approach, and part of its implementation. Comments welcome! Ludo’. 6.6 System Configuration ======================== _This section documents work-in-progress. As such it may be incomplete, outdated, or open to discussions. Please discuss it on ._ The GNU system supports a consistent whole-system configuration mechanism. By that we mean that all aspects of the global system configuration—such as the available system services, timezone and locale settings, user accounts—are configured in a single place. Such a "system configuration" can be "instantiated"—i.e., effected. This section describes this mechanism. First we focus on the system administrator’s viewpoint—explaining how the system is configured and instantiated. Then we show how this mechanism can be extended, for instance to support new system services. * Menu: * Using the Configuration System:: Customizing your GNU system. * Defining Services:: Adding new service definitions. 6.6.1 Using the Configuration System ------------------------------------ The operating system is configured by filling in an ‘operating-system’ structure, as defined by the ‘(gnu system)’ module. A simple setup, with the default system services, the default Linux-Libre kernel, initial RAM disk, and boot loader looks like this: (use-modules (gnu system) (gnu system shadow) ; for 'user-account' (gnu system service) ; for 'lsh-service' (gnu packages base) ; Coreutils, grep, etc. (gnu packages bash) ; Bash (gnu packages system) ; dmd, Inetutils (gnu packages zile) ; Zile (gnu packages less) ; less (gnu packages guile) ; Guile (gnu packages linux)) ; procps, psmisc (define %komputilo (operating-system (host-name "komputilo") (timezone "Europe/Paris") (locale "fr_FR.UTF-8") (users (list (user-account (name "alice") (password "") (uid 1000) (gid 100) (comment "Bob's sister") (home-directory "/home/alice")))) (packages (list coreutils bash guile-2.0 guix dmd inetutils findutils grep sed procps psmisc zile less)) (services (cons (lsh-service #:port 2222 #:allow-root-login? #t) %standard-services)))) This example should be self-describing. The ‘packages’ field lists packages provides by the various ‘(gnu packages ...)’ modules above; these are the packages that will be globally visible on the system, for all user accounts, in addition to the per-user profiles (*note Invoking guix package::). The ‘services’ field lists "system services" to be made available when the system starts. The %STANDARD-SERVICES list, from the ‘(gnu system)’ module, provides the basic services one would expect from a GNU system: a login service (mingetty) on each tty, syslogd, libc’s name service cache daemon (nscd), etc. The ‘operating-system’ declaration above specifies that, in addition to those services, we want the ‘lshd’ secure shell daemon listening on port 2222, and allowing remote ‘root’ logins (*note (lsh)Invoking lshd::). Under the hood, ‘lsh-service’ arranges so that ‘lshd’ is started with the right command-line options, possibly with supporting configuration files generated as needed (*note Defining Services::). Assuming the above snippet is stored in the ‘my-system-config.scm’ file, the (yet unwritten!) ‘guix system --boot my-system-config.scm’ command instantiates that configuration, and makes it the default GRUB boot entry. The normal way to change the system’s configuration is by updating this file and re-running the ‘guix system’ command. At the Scheme level, the bulk of an ‘operating-system’ declaration is instantiated with the following monadic procedure (*note The Store Monad::): -- Monadic Procedure: operating-system-derivation os Return a derivation that builds OS, an ‘operating-system’ object (*note Derivations::). The output of the derivation is a single directory that refers to all the packages, configuration files, and other supporting files needed to instantiate OS. One of the advantages of putting all the system configuration under the control of Guix is that it makes it possible to roll-back to a previous system instantiation, should anything go wrong with the new one. Another one is that it makes it easy to replicate the very same configuration across different machines, or at different points in time, without having to resort to additional administration tools layered on top of the system’s own tools. 6.6.2 Defining Services ----------------------- The ‘(gnu system dmd)’ module defines several procedures that allow users to declare the operating system’s services (*note Using the Configuration System::). These procedures are _monadic procedures_—i.e., procedures that return a monadic value in the store monad (*note The Store Monad::). Examples of such procedures include: ‘mingetty-service’ return the definition of a service that runs ‘mingetty’ to offer a login service on the given console tty; ‘nscd-service’ return a definition for libc’s name service cache daemon (nscd); ‘guix-service’ return a definition for a service that runs ‘guix-daemon’ (*note Invoking guix-daemon::). The monadic value returned by those procedures is a "service definition"—a structure as returned by the ‘service’ form. Service definitions specifies the inputs the service depends on, and an expression to start and stop the service. Behind the scenes, service definitions are “translated” into the form suitable for the configuration file of dmd, the init system (*note (dmd)Services::). As an example, here is what the ‘nscd-service’ procedure looks like: (define (nscd-service) (mlet %store-monad ((nscd (package-file glibc "sbin/nscd"))) (return (service (documentation "Run libc's name service cache daemon.") (provision '(nscd)) (start `(make-forkexec-constructor ,nscd "-f" "/dev/null" "--foreground")) (stop `(make-kill-destructor)) (respawn? #f) (inputs `(("glibc" ,glibc))))))) The ‘inputs’ field specifies that this service depends on the GLIBC package—the package that contains the ‘nscd’ program. The ‘start’ and ‘stop’ fields are expressions that make use of dmd’s facilities to start and stop processes (*note (dmd)Service De- and Constructors::). The ‘provision’ field specifies the name under which this service is known to dmd, and ‘documentation’ specifies on-line documentation. Thus, the commands ‘deco start ncsd’, ‘deco stop nscd’, and ‘deco doc nscd’ will do what you would expect (*note (dmd)Invoking deco::).