Merge remote-tracking branch 'origin/master' into core-updates-frozen
[jackhill/guix/guix.git] / doc / guix-cookbook.texi
index 1342826..88d3b98 100644 (file)
@@ -15,6 +15,9 @@ Copyright @copyright{} 2020 Oleg Pykhalov@*
 Copyright @copyright{} 2020 Matthew Brooks@*
 Copyright @copyright{} 2020 Marcin Karpezo@*
 Copyright @copyright{} 2020 Brice Waegeneire@*
+Copyright @copyright{} 2020 André Batista@*
+Copyright @copyright{} 2020 Christine Lemmer-Webber@*
+Copyright @copyright{} 2021 Joshua Branson@*
 
 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -54,15 +57,19 @@ its API, and related concepts.
 @c TRANSLATORS: You can replace the following paragraph with information on
 @c how to join your own translation team and how to report issues with the
 @c translation.
-If you would like to translate this document in your native language, consider
-joining the @uref{https://translationproject.org/domain/guix-cookbook.html,
-Translation Project}.
+This manual is also available in French (@pxref{Top,,, guix-cookbook.fr,
+Livre de recettes de GNU Guix}) and German (@pxref{Top,,,
+guix-cookbook.de, GNU-Guix-Kochbuch}).  If you would like to translate
+this document in your native language, consider joining
+@uref{https://translate.fedoraproject.org/projects/guix/documentation-cookbook,
+Weblate} (@pxref{Translating Guix,,, guix, GNU Guix reference manual}).
 
 @menu
 * Scheme tutorials::            Meet your new favorite language!
 * Packaging::                   Packaging tutorials
 * System Configuration::        Customizing the GNU System
 * Advanced package management:: Power to the users!
+* Environment management::      Control environment
 
 * Acknowledgments::             Thanks!
 * GNU Free Documentation License::  The license of this document.
@@ -81,8 +88,8 @@ Packaging
 
 System Configuration
 
-* Customizing the Kernel::      Creating and using a custom Linux kernel
-
+* Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY
+* Customizing the Kernel::       Creating and using a custom Linux kernel on Guix System.
 
 @end detailmenu
 @end menu
@@ -109,8 +116,8 @@ Let's get started!
 
 Guix uses the Guile implementation of Scheme.  To start playing with the
 language, install it with @code{guix install guile} and start a
-@uref{https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop,
-REPL} by running @code{guile} from the command line.
+@dfn{REPL}---short for @uref{https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop,
+@dfn{read-eval-print loop}}---by running @code{guile} from the command line.
 
 Alternatively you can also run @code{guix environment --ad-hoc guile -- guile}
 if you'd rather not have Guile installed in your user profile.
@@ -118,15 +125,16 @@ if you'd rather not have Guile installed in your user profile.
 In the following examples, lines show what you would type at the REPL;
 lines starting with ``@result{}'' show evaluation results, while lines
 starting with ``@print{}'' show things that get printed.  @xref{Using Guile
-Interactively,,, guile, GNU Guile Reference Manual}), for more details on the
+Interactively,,, guile, GNU Guile Reference Manual}, for more details on the
 REPL.
 
 @itemize
 @item
 Scheme syntax boils down to a tree of expressions (or @emph{s-expression} in
 Lisp lingo).  An expression can be a literal such as numbers and strings, or a
-compound which is a parenthesized list of compounds and literals.  @code{#t}
-and @code{#f} stand for the Booleans ``true'' and ``false'', respectively.
+compound which is a parenthesized list of compounds and literals.  @code{#true}
+and @code{#false} (abbreviated @code{#t} and @code{#f}) stand for the
+Booleans ``true'' and ``false'', respectively.
 
 Examples of valid expressions:
 
@@ -246,8 +254,10 @@ definitions.
 @end lisp
 
 @item
-The keyword syntax is @code{#:}; it is used to create unique identifiers.
-@pxref{Keywords,,, guile, GNU Guile Reference Manual}.
+@dfn{Keywords} are typically used to identify the named parameters of a
+procedure.  They are prefixed by @code{#:} (hash, colon) followed by
+alphanumeric characters: @code{#:like-this}.
+@xref{Keywords,,, guile, GNU Guile Reference Manual}.
 
 @item
 The percentage @code{%} is typically used for read-only global variables in
@@ -583,7 +593,7 @@ packages.
 Guix makes it possible to streamline the process by adding as many ``package
 declaration directories'' as you want.
 
-Create a directory, say @file{~./guix-packages} and add it to the @samp{GUIX_PACKAGE_PATH}
+Create a directory, say @file{~/guix-packages} and add it to the @samp{GUIX_PACKAGE_PATH}
 environment variable:
 
 @example
@@ -785,14 +795,12 @@ another, more sophisticated package (slightly modified from the source):
                   "17pjvprmdrx4h6bb1hhc98w9qi6ki7yl57f090n9kbhswxqfs7s3"))
                 (patches (search-patches "libgit2-mtime-0.patch"))
                 (modules '((guix build utils)))
-                (snippet '(begin
-                            ;; Remove bundled software.
-                            (delete-file-recursively "deps")
-                            #t))))
+                ;; Remove bundled software.
+                (snippet '(delete-file-recursively "deps"))))
       (build-system cmake-build-system)
       (outputs '("out" "debug"))
       (arguments
-       `(#:tests? #t                            ; Run the test suite (this is the default)
+       `(#:tests? #true                         ; Run the test suite (this is the default)
          #:configure-flags '("-DUSE_SHA1DC=ON") ; SHA-1 collision detection
          #:phases
          (modify-phases %standard-phases
@@ -802,23 +810,19 @@ another, more sophisticated package (slightly modified from the source):
                  (("#!/bin/sh") (string-append "#!" (which "sh"))))
                (substitute* "tests/clar/fs.h"
                  (("/bin/cp") (which "cp"))
-                 (("/bin/rm") (which "rm")))
-               #t))
+                 (("/bin/rm") (which "rm")))))
            ;; Run checks more verbosely.
            (replace 'check
              (lambda _ (invoke "./libgit2_clar" "-v" "-Q")))
            (add-after 'unpack 'make-files-writable-for-tests
-               (lambda _ (for-each make-file-writable (find-files "." ".*")))))))
+             (lambda _ (for-each make-file-writable (find-files "." ".*")))))))
       (inputs
-       `(("libssh2" ,libssh2)
-         ("http-parser" ,http-parser)
-         ("python" ,python-wrapper)))
+       (list libssh2 http-parser python-wrapper))
       (native-inputs
-       `(("pkg-config" ,pkg-config)))
+       (list pkg-config))
       (propagated-inputs
        ;; These two libraries are in 'Requires.private' in libgit2.pc.
-       `(("openssl" ,openssl)
-         ("zlib" ,zlib)))
+       (list openssl zlib))
       (home-page "https://libgit2.github.com/")
       (synopsis "Library providing Git core methods")
       (description
@@ -843,12 +847,32 @@ tags, so if the @code{version} is tagged, then it can be used directly.  Sometim
 the tag is prefixed with a @code{v}, in which case you'd use @code{(commit (string-append
 "v" version))}.
 
-To ensure that the source code from the Git repository is stored in a unique
-directory with a readable name we use @code{(file-name (git-file-name name
+To ensure that the source code from the Git repository is stored in a
+directory with a descriptive name, we use @code{(file-name (git-file-name name
 version))}.
 
-Note that there is also a @code{git-version} procedure that can be used to derive the
-version when packaging programs for a specific commit.
+The @code{git-version} procedure can be used to derive the
+version when packaging programs for a specific commit, following the
+Guix contributor guidelines (@pxref{Version Numbers,,, guix, GNU Guix
+Reference Manual}).
+
+How does one obtain the @code{sha256} hash that's in there, you ask?  By
+invoking @command{guix hash} on a checkout of the desired commit, along
+these lines:
+
+@example
+git clone https://github.com/libgit2/libgit2/
+cd libgit2
+git checkout v0.26.6
+guix hash -rx .
+@end example
+
+@command{guix hash -rx} computes a SHA256 hash over the whole directory,
+excluding the @file{.git} sub-directory (@pxref{Invoking guix hash,,,
+guix, GNU Guix Reference Manual}).
+
+In the future, @command{guix download} will hopefully be able to do
+these steps for you, just like it does for regular downloads.
 
 @subsubsection Snippets
 
@@ -862,22 +886,6 @@ Snippets might need additional Guile modules which can be imported from the
 
 @subsubsection Inputs
 
-First, a syntactic comment: See the quasi-quote / comma syntax?
-
-@lisp
-    (native-inputs
-     `(("pkg-config" ,pkg-config)))
-@end lisp
-
-is equivalent to
-
-@lisp
-    (native-inputs
-     (list (list "pkg-config" pkg-config)))
-@end lisp
-
-You'll mostly see the former because it's shorter.
-
 There are 3 different input types.  In short:
 
 @table @asis
@@ -911,6 +919,24 @@ It also matters when a substitute is available, in which case only the @emph{inp
 and @emph{propagated inputs} will be fetched: the @emph{native inputs} are not required to
 install a package from a substitute.
 
+@quotation Note
+You may see here and there snippets where package inputs are written
+quite differently, like so:
+
+@lisp
+;; The "old style" for inputs.
+(inputs
+ `(("libssh2" ,libssh2)
+   ("http-parser" ,http-parser)
+   ("python" ,python-wrapper)))
+@end lisp
+
+This is the ``old style'', where each input in the list is explicitly
+given a label (a string).  It is still supported but we recommend using
+the style above instead.  @xref{package Reference,,, guix, GNU Guix
+Reference Manual}, for more info.
+@end quotation
+
 @subsubsection Outputs
 
 Just like how a package can have multiple inputs, it can also produce multiple
@@ -1006,7 +1032,7 @@ If you want to know more about what happens during those phases, consult the
 associated procedures.
 
 For instance, as of this writing the definition of @code{unpack} for the GNU build
-system is
+system is:
 
 @lisp
 (define* (unpack #:key source #:allow-other-keys)
@@ -1021,13 +1047,13 @@ working directory."
         ;; Preserve timestamps (set to the Epoch) on the copied tree so that
         ;; things work deterministically.
         (copy-recursively source "."
-                          #:keep-mtime? #t))
+                          #:keep-mtime? #true))
       (begin
         (if (string-suffix? ".zip" source)
             (invoke "unzip" source)
             (invoke "tar" "xvf" source))
         (chdir (first-subdirectory "."))))
-  #t)
+  #true)
 @end lisp
 
 Note the @code{chdir} call: it changes the working directory to where the source was
@@ -1043,16 +1069,16 @@ the following forms:
 
 @itemize
 @item
-@code{(add-before PHASE NEW-PHASE PROCEDURE)}: Run @code{PROCEDURE} named @code{NEW-PHASE} before @code{PHASE}.
+@code{(add-before @var{phase} @var{new-phase} @var{procedure})}: Run @var{procedure} named @var{new-phase} before @var{phase}.
 @item
-@code{(add-after PHASE NEW-PHASE PROCEDURE)}: Same, but afterwards.
+@code{(add-after @var{phase} @var{new-phase} @var{procedure})}: Same, but afterwards.
 @item
-@code{(replace PHASE PROCEDURE)}.
+@code{(replace @var{phase} @var{procedure})}.
 @item
-@code{(delete PHASE)}.
+@code{(delete @var{phase})}.
 @end itemize
 
-The @code{PROCEDURE} supports the keyword arguments @code{inputs} and @code{outputs}.  Each
+The @var{procedure} supports the keyword arguments @code{inputs} and @code{outputs}.  Each
 input (whether @emph{native}, @emph{propagated} or not) and output directory is referenced
 by their name in those variables.  Thus @code{(assoc-ref outputs "out")} is the store
 directory of the main output of the package.  A phase procedure may look like
@@ -1060,16 +1086,16 @@ this:
 
 @lisp
 (lambda* (#:key inputs outputs #:allow-other-keys)
-  (let (((bash-directory (assoc-ref inputs "bash"))
-         (output-directory (assoc-ref outputs "out"))
-         (doc-directory (assoc-ref outputs "doc"))
-  ; ...
-  #t)
+  (let ((bash-directory (assoc-ref inputs "bash"))
+        (output-directory (assoc-ref outputs "out"))
+        (doc-directory (assoc-ref outputs "doc")))
+    ;; ...
+    #true))
 @end lisp
 
-The procedure must return @code{#t} on success.  It's brittle to rely on the return
+The procedure must return @code{#true} on success.  It's brittle to rely on the return
 value of the last expression used to tweak the phase because there is no
-guarantee it would be a @code{#t}.  Hence the trailing @code{#t} to ensure the right value
+guarantee it would be a @code{#true}.  Hence the trailing @code{#true} to ensure the right value
 is returned on success.
 
 @subsubsection Code staging
@@ -1095,7 +1121,7 @@ Some of those functions can be found in
 @samp{$GUIX_CHECKOUT/guix/guix/build/utils.scm}.  Most of them mirror the behaviour
 of the traditional Unix system commands:
 
-@table @asis
+@table @code
 @item which
 Like the @samp{which} system command.
 @item find-files
@@ -1119,6 +1145,9 @@ then restore the previous working directory.
 A ``@command{sed}-like'' function.
 @end table
 
+@xref{Build Utilities,,, guix, GNU Guix Reference Manual}, for more
+information on these utilities.
+
 @subsubsection Module prefix
 
 The license in our last example needs a prefix: this is because of how the
@@ -1267,7 +1296,7 @@ version or compilation options.
 @subsection Getting help
 
 Sadly, some applications can be tough to package.  Sometimes they need a patch to
-work with the non-standard filesystem hierarchy enforced by the store.
+work with the non-standard file system hierarchy enforced by the store.
 Sometimes the tests won't run properly.  (They can be skipped but this is not
 recommended.)  Other times the resulting package won't be reproducible.
 
@@ -1323,13 +1352,62 @@ chapter is to demonstrate some advanced configuration concepts.
 reference.
 
 @menu
+* Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY
 * Customizing the Kernel::       Creating and using a custom Linux kernel on Guix System.
+* Guix System Image API::        Customizing images to target specific platforms.
 * Connecting to Wireguard VPN::  Connecting to a Wireguard VPN.
 * Customizing a Window Manager:: Handle customization of a Window manager on Guix System.
+* Running Guix on a Linode Server:: Running Guix on a Linode Server
 * Setting up a bind mount:: Setting up a bind mount in the file-systems definition.
 * Getting substitutes from Tor:: Configuring Guix daemon to get substitutes through Tor.
+* Setting up NGINX with Lua:: Configuring NGINX web-server to load Lua modules.
 @end menu
 
+@node Auto-Login to a Specific TTY
+@section Auto-Login to a Specific TTY
+
+While the Guix manual explains auto-login one user to @emph{all} TTYs (
+@pxref{auto-login to TTY,,, guix, GNU Guix Reference Manual}), some
+might prefer a situation, in which one user is logged into one TTY with
+the other TTYs either configured to login different users or no one at
+all.  Note that one can auto-login one user to any TTY, but it is
+usually advisable to avoid @code{tty1}, which, by default, is used to
+log warnings and errors.
+
+Here is how one might set up auto login for one user to one tty:
+
+@lisp
+(define (auto-login-to-tty config tty user)
+  (if (string=? tty (mingetty-configuration-tty config))
+        (mingetty-configuration
+         (inherit config)
+         (auto-login user))
+        config))
+
+(define %my-services
+  (modify-services %base-services
+    ;; @dots{}
+    (mingetty-service-type config =>
+                           (auto-login-to-tty
+                            config "tty3" "alice"))))
+
+(operating-system
+  ;; @dots{}
+  (services %my-services))
+@end lisp
+
+One could also @code{compose} (@pxref{Higher-Order Functions,,, guile,
+The Guile Reference Manual}) @code{auto-login-to-tty} to login multiple
+users to multiple ttys.
+
+Finally, here is a note of caution.  Setting up auto login to a TTY,
+means that anyone can turn on your computer and run commands as your
+regular user.
+However, if you have an encrypted root partition, and thus already need
+to enter a passphrase when the system boots, auto-login might be a
+convenient option.
+
+
 @node Customizing the Kernel
 @section Customizing the Kernel
 
@@ -1360,8 +1438,8 @@ creates a package.
                            #:key
                            ;; A function that takes an arch and a variant.
                            ;; See kernel-config for an example.
-                           (extra-version #f)
-                           (configuration-file #f)
+                           (extra-version #false)
+                           (configuration-file #false)
                            (defconfig "defconfig")
                            (extra-options %default-extra-linux-options)
                            (patches (list %boot-logo-patch)))
@@ -1404,7 +1482,7 @@ the @code{make-linux-libre} package definition:
       (begin
         (copy-file config ".config")
         (chmod ".config" #o666))
-      (invoke "make" ,defconfig))
+      (invoke "make" ,defconfig)))
 @end lisp
 
 Below is a sample kernel package.  The @code{linux-libre} package is nothing
@@ -1435,7 +1513,7 @@ it:
 @lisp
 (define %default-extra-linux-options
   `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html
-   ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #t)
+   ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #true)
    ;; Modules required for initrd:
    ("CONFIG_NET_9P" . m)
    ("CONFIG_NET_9P_VIRTIO" . m)
@@ -1452,9 +1530,9 @@ it:
   (string-join (map (match-lambda
                       ((option . 'm)
                        (string-append option "=m"))
-                      ((option . #t)
+                      ((option . #true)
                        (string-append option "=y"))
-                      ((option . #f)
+                      ((option . #false)
                        (string-append option "=n")))
                     options)
                "\n"))
@@ -1470,7 +1548,7 @@ And in the custom configure script from the `make-linux-libre` package:
   (display extra-configuration port)
   (close-port port))
 
-(invoke "make" "oldconfig"))))
+(invoke "make" "oldconfig")
 @end lisp
 
 So by not providing a configuration-file the @file{.config} starts blank, and
@@ -1480,7 +1558,7 @@ custom kernel:
 @lisp
 (define %macbook41-full-config
   (append %macbook41-config-options
-          %filesystems
+          %file-systems
           %efi-support
           %emulation
           (@@@@ (gnu packages linux) %default-extra-linux-options)))
@@ -1496,8 +1574,8 @@ custom kernel:
                       #:extra-options %macbook41-config-options))
 @end lisp
 
-In the above example @code{%filesystems} is a collection of flags enabling
-different filesystem support, @code{%efi-support} enables EFI support and
+In the above example @code{%file-systems} is a collection of flags enabling
+different file system support, @code{%efi-support} enables EFI support and
 @code{%emulation} enables a x86_64-linux machine to act in 32-bit mode also.
 @code{%default-extra-linux-options} are the ones quoted above, which had to be
 added in since they were replaced in the @code{extra-options} keyword.
@@ -1561,7 +1639,7 @@ The second way to setup the kernel configuration makes more use of Guix's
 features and allows you to share configuration segments between different
 kernels.  For example, all machines using EFI to boot have a number of EFI
 configuration flags that they need.  It is likely that all the kernels will
-share a list of filesystems to support.  By using variables it is easier to
+share a list of file systems to support.  By using variables it is easier to
 see at a glance what features are enabled and to make sure you don't have
 features in one kernel but missing in another.
 
@@ -1570,6 +1648,217 @@ likely that you'll need to modify the initrd on a machine using a custom
 kernel, since certain modules which are expected to be built may not be
 available for inclusion into the initrd.
 
+@node Guix System Image API
+@section Guix System Image API
+
+Historically, Guix System is centered around an @code{operating-system}
+structure.  This structure contains various fields ranging from the
+bootloader and kernel declaration to the services to install.
+
+Depending on the target machine, that can go from a standard
+@code{x86_64} machine to a small ARM single board computer such as the
+Pine64, the image constraints can vary a lot.  The hardware
+manufacturers will impose different image formats with various partition
+sizes and offsets.
+
+To create images suitable for all those machines, a new abstraction is
+necessary: that's the goal of the @code{image} record.  This record
+contains all the required information to be transformed into a
+standalone image, that can be directly booted on any target machine.
+
+@lisp
+(define-record-type* <image>
+  image make-image
+  image?
+  (name               image-name ;symbol
+                      (default #f))
+  (format             image-format) ;symbol
+  (target             image-target
+                      (default #f))
+  (size               image-size  ;size in bytes as integer
+                      (default 'guess))
+  (operating-system   image-operating-system  ;<operating-system>
+                      (default #f))
+  (partitions         image-partitions ;list of <partition>
+                      (default '()))
+  (compression?       image-compression? ;boolean
+                      (default #t))
+  (volatile-root?     image-volatile-root? ;boolean
+                      (default #t))
+  (substitutable?     image-substitutable? ;boolean
+                      (default #t)))
+@end lisp
+
+This record contains the operating-system to instantiate. The
+@code{format} field defines the image type and can be @code{efi-raw},
+@code{qcow2} or @code{iso9660} for instance. In the future, it could be
+extended to @code{docker} or other image types.
+
+A new directory in the Guix sources is dedicated to images definition. For now
+there are four files:
+
+@itemize @bullet
+@item @file{gnu/system/images/hurd.scm}
+@item @file{gnu/system/images/pine64.scm}
+@item @file{gnu/system/images/novena.scm}
+@item @file{gnu/system/images/pinebook-pro.scm}
+@end itemize
+
+Let's have a look to @file{pine64.scm}. It contains the
+@code{pine64-barebones-os} variable which is a minimal definition of an
+operating-system dedicated to the @b{Pine A64 LTS} board.
+
+@lisp
+(define pine64-barebones-os
+  (operating-system
+   (host-name "vignemale")
+   (timezone "Europe/Paris")
+   (locale "en_US.utf8")
+   (bootloader (bootloader-configuration
+                (bootloader u-boot-pine64-lts-bootloader)
+                (targets '("/dev/vda"))))
+   (initrd-modules '())
+   (kernel linux-libre-arm64-generic)
+   (file-systems (cons (file-system
+                        (device (file-system-label "my-root"))
+                        (mount-point "/")
+                        (type "ext4"))
+                       %base-file-systems))
+   (services (cons (service agetty-service-type
+                            (agetty-configuration
+                             (extra-options '("-L")) ; no carrier detect
+                             (baud-rate "115200")
+                             (term "vt100")
+                             (tty "ttyS0")))
+                   %base-services))))
+@end lisp
+
+The @code{kernel} and @code{bootloader} fields are pointing to packages
+dedicated to this board.
+
+Right below, the @code{pine64-image-type} variable is also defined.
+
+@lisp
+(define pine64-image-type
+  (image-type
+   (name 'pine64-raw)
+   (constructor (cut image-with-os arm64-disk-image <>))))
+@end lisp
+
+It's using a record we haven't talked about yet, the @code{image-type} record,
+defined this way:
+
+@lisp
+(define-record-type* <image-type>
+  image-type make-image-type
+  image-type?
+  (name           image-type-name) ;symbol
+  (constructor    image-type-constructor)) ;<operating-system> -> <image>
+@end lisp
+
+The main purpose of this record is to associate a name to a procedure
+transforming an @code{operating-system} to an image.  To understand why
+it is necessary, let's have a look to the command producing an image
+from an @code{operating-system} configuration file:
+
+@example
+guix system image my-os.scm
+@end example
+
+This command expects an @code{operating-system} configuration but how
+should we indicate that we want an image targeting a Pine64 board?  We
+need to provide an extra information, the @code{image-type}, by passing
+the @code{--image-type} or @code{-t} flag, this way:
+
+@example
+guix system image --image-type=pine64-raw my-os.scm
+@end example
+
+This @code{image-type} parameter points to the @code{pine64-image-type}
+defined above. Hence, the @code{operating-system} declared in
+@code{my-os.scm} will be applied the @code{(cut image-with-os
+arm64-disk-image <>)} procedure to turn it into an image.
+
+The resulting image looks like:
+
+@lisp
+(image
+ (format 'disk-image)
+ (target "aarch64-linux-gnu")
+ (operating-system my-os)
+ (partitions
+  (list (partition
+         (inherit root-partition)
+         (offset root-offset)))))
+@end lisp
+
+which is the aggregation of the @code{operating-system} defined in
+ @code{my-os.scm} to the @code{arm64-disk-image} record.
+
+But enough Scheme madness. What does this image API bring to the Guix user?
+
+One can run:
+
+@example
+mathieu@@cervin:~$ guix system --list-image-types
+The available image types are:
+
+   - pinebook-pro-raw
+   - pine64-raw
+   - novena-raw
+   - hurd-raw
+   - hurd-qcow2
+   - qcow2
+   - uncompressed-iso9660
+   - efi-raw
+   - arm64-raw
+   - arm32-raw
+   - iso9660
+@end example
+
+and by writing an @code{operating-system} file based on
+@code{pine64-barebones-os}, you can customize your image to your
+preferences in a file (@file{my-pine-os.scm}) like this:
+
+@lisp
+(use-modules (gnu services linux)
+             (gnu system images pine64))
+
+(let ((base-os pine64-barebones-os))
+  (operating-system
+    (inherit base-os)
+    (timezone "America/Indiana/Indianapolis")
+    (services
+     (cons
+      (service earlyoom-service-type
+               (earlyoom-configuration
+                (prefer-regexp "icecat|chromium")))
+      (operating-system-user-services base-os)))))
+@end lisp
+
+run:
+
+@example
+guix system image --image-type=pine64-raw my-pine-os.scm
+@end example
+
+or,
+
+@example
+guix system image --image-type=hurd-raw my-hurd-os.scm
+@end example
+
+to get an image that can be written directly to a hard drive and booted
+from.
+
+Without changing anything to @code{my-hurd-os.scm}, calling:
+
+@example
+guix system image --image-type=hurd-qcow2 my-hurd-os.scm
+@end example
+
+will instead produce a Hurd QEMU image.
+
 @node Connecting to Wireguard VPN
 @section Connecting to Wireguard VPN
 
@@ -1738,6 +2027,249 @@ your screen but not suspend it, it's a good idea to notify xss-lock about this s
 confusion occurs. This can be done by executing @code{xset s activate} immediately
 before you execute slock.
 
+@node Running Guix on a Linode Server
+@section Running Guix on a Linode Server
+@cindex linode, Linode
+
+To run Guix on a server hosted by @uref{https://www.linode.com, Linode},
+start with a recommended Debian server.  We recommend using the default
+distro as a way to bootstrap Guix. Create your SSH keys.
+
+@example
+ssh-keygen
+@end example
+
+Be sure to add your SSH key for easy login to the remote server.
+This is trivially done via Linode's graphical interface for adding
+SSH keys.  Go to your profile and click add SSH Key.
+Copy into it the output of:
+
+@example
+cat ~/.ssh/<username>_rsa.pub
+@end example
+
+Power the Linode down.
+
+In the Linode's Storage tab, resize the Debian disk to be smaller.
+30 GB free space is recommended.  Then click "Add a disk", and fill
+out the form with the following:
+
+@itemize @bullet
+@item
+Label: "Guix"
+
+@item
+Filesystem: ext4
+
+@item
+Set it to the remaining size
+@end itemize
+
+In the Configurations tab, press "Edit" on the default Debian profile.
+Under "Block Device Assignment" click "Add a Device". It should be
+@file{/dev/sdc} and you can select the "Guix" disk. Save Changes.
+
+Now "Add a Configuration", with the following:
+@itemize @bullet
+@item
+Label: Guix
+
+@item
+Kernel:GRUB 2 (it's at the bottom!  This step is @b{IMPORTANT!})
+
+@item
+Block device assignment:
+
+@item
+@file{/dev/sda}: Guix
+
+@item
+@file{/dev/sdb}: swap
+
+@item
+Root device: @file{/dev/sda}
+
+@item
+Turn off all the filesystem/boot helpers
+@end itemize
+
+Now power it back up, booting with the Debian configuration.  Once it's
+running, ssh to your server via @code{ssh
+root@@@var{<your-server-IP-here>}}. (You can find your server IP address in
+your Linode Summary section.) Now you can run the "install guix from
+@pxref{Binary Installation,,, guix, GNU Guix}" steps:
+
+@example
+sudo apt-get install gpg
+wget https://sv.gnu.org/people/viewgpg.php?user_id=15145 -qO - | gpg --import -
+wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
+chmod +x guix-install.sh
+./guix-install.sh
+guix pull
+@end example
+
+Now it's time to write out a config for the server.  The key information
+is below. Save the resulting file as @file{guix-config.scm}.
+
+@lisp
+(use-modules (gnu)
+             (guix modules))
+(use-service-modules networking
+                     ssh)
+(use-package-modules admin
+                     certs
+                     package-management
+                     ssh
+                     tls)
+
+(operating-system
+  (host-name "my-server")
+  (timezone "America/New_York")
+  (locale "en_US.UTF-8")
+  ;; This goofy code will generate the grub.cfg
+  ;; without installing the grub bootloader on disk.
+  (bootloader (bootloader-configuration
+               (bootloader
+                (bootloader
+                 (inherit grub-bootloader)
+                 (installer #~(const #true))))))
+  (file-systems (cons (file-system
+                        (device "/dev/sda")
+                        (mount-point "/")
+                        (type "ext4"))
+                      %base-file-systems))
+
+
+  (swap-devices (list "/dev/sdb"))
+
+
+  (initrd-modules (cons "virtio_scsi"    ; Needed to find the disk
+                        %base-initrd-modules))
+
+  (users (cons (user-account
+                (name "janedoe")
+                (group "users")
+                ;; Adding the account to the "wheel" group
+                ;; makes it a sudoer.
+                (supplementary-groups '("wheel"))
+                (home-directory "/home/janedoe"))
+               %base-user-accounts))
+
+  (packages (cons* nss-certs            ;for HTTPS access
+                   openssh-sans-x
+                   %base-packages))
+
+  (services (cons*
+             (service dhcp-client-service-type)
+             (service openssh-service-type
+                      (openssh-configuration
+                       (openssh openssh-sans-x)
+                       (password-authentication? #false)
+                       (authorized-keys
+                        `(("janedoe" ,(local-file "janedoe_rsa.pub"))
+                          ("root" ,(local-file "janedoe_rsa.pub"))))))
+             %base-services)))
+@end lisp
+
+Replace the following fields in the above configuration:
+@lisp
+(host-name "my-server")       ; replace with your server name
+; if you chose a linode server outside the U.S., then
+; use tzselect to find a correct timezone string
+(timezone "America/New_York") ; if needed replace timezone
+(name "janedoe")              ; replace with your username
+("janedoe" ,(local-file "janedoe_rsa.pub")) ; replace with your ssh key
+("root" ,(local-file "janedoe_rsa.pub")) ; replace with your ssh key
+@end lisp
+
+The last line in the above example lets you log into the server as root
+and set the initial root password (see the note at the end of this
+recipe about root login).  After you have done this, you may
+delete that line from your configuration and reconfigure to prevent root
+login.
+
+Copy your ssh public key (eg: @file{~/.ssh/id_rsa.pub}) as
+@file{@var{<your-username-here>}_rsa.pub} and put
+@file{guix-config.scm} in the same directory.  In a new terminal run
+these commands.
+
+@example
+sftp root@@<remote server ip address>
+put /path/to/files/<username>_rsa.pub .
+put /path/to/files/guix-config.scm .
+@end example
+
+In your first terminal, mount the guix drive:
+
+@example
+mkdir /mnt/guix
+mount /dev/sdc /mnt/guix
+@end example
+
+Due to the way we set up the bootloader section of the guix-config.scm,
+only the grub configuration file will be installed.  So, we need to copy
+over some of the other GRUB stuff already installed on the Debian system:
+
+@example
+mkdir -p /mnt/guix/boot/grub
+cp -r /boot/grub/* /mnt/guix/boot/grub/
+@end example
+
+Now initialize the Guix installation:
+
+@example
+guix system init guix-config.scm /mnt/guix
+@end example
+
+Ok, power it down!
+Now from the Linode console, select boot and select "Guix".
+
+Once it boots, you should be able to log in via SSH!  (The server config
+will have changed though.)  You may encounter an error like:
+
+@example
+$ ssh root@@<server ip address>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
+Someone could be eavesdropping on you right now (man-in-the-middle attack)!
+It is also possible that a host key has just been changed.
+The fingerprint for the ECDSA key sent by the remote host is
+SHA256:0B+wp33w57AnKQuHCvQP0+ZdKaqYrI/kyU7CfVbS7R4.
+Please contact your system administrator.
+Add correct host key in /home/joshua/.ssh/known_hosts to get rid of this message.
+Offending ECDSA key in /home/joshua/.ssh/known_hosts:3
+ECDSA host key for 198.58.98.76 has changed and you have requested strict checking.
+Host key verification failed.
+@end example
+
+Either delete @file{~/.ssh/known_hosts} file, or delete the offending line
+starting with your server IP address.
+
+Be sure to set your password and root's password.
+
+@example
+ssh root@@<remote ip address>
+passwd  ; for the root password
+passwd <username> ; for the user password
+@end example
+
+You may not be able to run the above commands at this point.  If you
+have issues remotely logging into your linode box via SSH, then you may
+still need to set your root and user password initially by clicking on
+the ``Launch Console'' option in your linode.  Choose the ``Glish''
+instead of ``Weblish''.  Now you should be able to ssh into the machine.
+
+Hooray!  At this point you can shut down the server, delete the
+Debian disk, and resize the Guix to the rest of the size.
+Congratulations!
+
+By the way, if you save it as a disk image right at this point, you'll
+have an easy time spinning up new Guix images!  You may need to
+down-size the Guix image to 6144MB, to save it as an image.  Then you
+can resize it again to the max size.
+
 @node Setting up a bind mount
 @section Setting up a bind mount
 
@@ -1799,10 +2331,16 @@ HTTP/HTTPS will get proxied; FTP, Git protocol, SSH, etc connections
 will still go through the clearnet.  Again, this configuration isn't
 foolproof some of your traffic won't get routed by Tor at all.  Use it
 at your own risk.
+
+Also note that the procedure described here applies only to package
+substitution. When you update your guix distribution with
+@command{guix pull}, you still need to use @command{torsocks} if
+you want to route the connection to guix's git repository servers
+through Tor.
 @end quotation
 
 Guix's substitute server is available as a Onion service, if you want
-to use it to get your substitutes from Tor configure your system as
+to use it to get your substitutes through Tor configure your system as
 follow:
 
 @lisp
@@ -1843,6 +2381,63 @@ sudo herd set-http-proxy guix-daemon http://localhost:9250
 guix build --substitute-urls=https://bp7o7ckwlewr4slm.onion …
 @end example
 
+@node Setting up NGINX with Lua
+@section Setting up NGINX with Lua
+@cindex nginx, lua, openresty, resty
+
+NGINX could be extended with Lua scripts.
+
+Guix provides NGINX service with ability to load Lua module and specific
+Lua packages, and reply to requests by evaluating Lua scripts.
+
+The following example demonstrates system definition with configuration
+to evaluate @file{index.lua} Lua script on HTTP request to
+@uref{http://localhost/hello} endpoint:
+
+@example
+local shell = require "resty.shell"
+
+local stdin = ""
+local timeout = 1000  -- ms
+local max_size = 4096  -- byte
+
+local ok, stdout, stderr, reason, status =
+   shell.run([[/run/current-system/profile/bin/ls /tmp]], stdin, timeout, max_size)
+
+ngx.say(stdout)
+@end example
+
+@lisp
+(use-modules (gnu))
+(use-service-modules #;… web)
+(use-package-modules #;… lua)
+(operating-system
+  ;; …
+  (services
+   ;; …
+   (service nginx-service-type
+            (nginx-configuration
+             (modules
+              (list
+               (file-append nginx-lua-module "/etc/nginx/modules/ngx_http_lua_module.so")))
+             (lua-package-path (list lua-resty-core
+                                     lua-resty-lrucache
+                                     lua-resty-signal
+                                     lua-tablepool
+                                     lua-resty-shell))
+             (lua-package-cpath (list lua-resty-signal))
+             (server-blocks
+              (list (nginx-server-configuration
+                     (server-name '("localhost"))
+                     (listen '("80"))
+                     (root "/etc")
+                     (locations (list
+                                 (nginx-location-configuration
+                                  (uri "/hello")
+                                  (body (list #~(format #f "content_by_lua_file ~s;"
+                                                        #$(local-file "index.lua"))))))))))))))
+@end lisp
+
 @c *********************************************************************
 @node Advanced package management
 @chapter Advanced package management
@@ -1911,7 +2506,7 @@ section on @ref{Reproducible profiles}.
 
 @item
 Easier upgrades and maintenance: Multiple profiles make it easy to keep
-package listings at hand and make upgrades completely friction-less.
+package listings at hand and make upgrades completely frictionless.
 @end itemize
 
 Concretely, here follows some typical profiles:
@@ -2241,6 +2836,130 @@ mkdir -p "$GUIX_EXTRA_PROFILES/my-project"
 It's safe to delete the Guix channel profile you've just installed with the
 channel specification, the project profile does not depend on it.
 
+@c *********************************************************************
+@node Environment management
+@chapter Environment management
+
+Guix provides multiple tools to manage environment.  This chapter
+demonstrate such utilities.
+
+@menu
+* Guix environment via direnv:: Setup Guix environment with direnv
+@end menu
+
+@node Guix environment via direnv
+@section Guix environment via direnv
+
+Guix provides a @samp{direnv} package, which could extend shell after
+directory change.  This tool could be used to prepare a pure Guix
+environment.
+
+The following example provides a shell function for @file{~/.direnvrc}
+file, which could be used from Guix Git repository in
+@file{~/src/guix/.envrc} file to setup a build environment similar to
+described in @pxref{Building from Git,,, guix, GNU Guix Reference
+Manual}.
+
+Create a @file{~/.direnvrc} with a Bash code:
+
+@example
+# Thanks <https://github.com/direnv/direnv/issues/73#issuecomment-152284914>
+export_function()
+@{
+  local name=$1
+  local alias_dir=$PWD/.direnv/aliases
+  mkdir -p "$alias_dir"
+  PATH_add "$alias_dir"
+  local target="$alias_dir/$name"
+  if declare -f "$name" >/dev/null; then
+    echo "#!$SHELL" > "$target"
+    declare -f "$name" >> "$target" 2>/dev/null
+    # Notice that we add shell variables to the function trigger.
+    echo "$name \$*" >> "$target"
+    chmod +x "$target"
+  fi
+@}
+
+use_guix()
+@{
+    # Set GitHub token.
+    export GUIX_GITHUB_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+    # Unset 'GUIX_PACKAGE_PATH'.
+    export GUIX_PACKAGE_PATH=""
+
+    # Recreate a garbage collector root.
+    gcroots="$HOME/.config/guix/gcroots"
+    mkdir -p "$gcroots"
+    gcroot="$gcroots/guix"
+    if [ -L "$gcroot" ]
+    then
+        rm -v "$gcroot"
+    fi
+
+    # Miscellaneous packages.
+    PACKAGES_MAINTENANCE=(
+        direnv
+        git
+        git:send-email
+        git-cal
+        gnupg
+        guile-colorized
+        guile-readline
+        less
+        ncurses
+        openssh
+        xdot
+    )
+
+    # Environment packages.
+    PACKAGES=(help2man guile-sqlite3 guile-gcrypt)
+
+    # Thanks <https://lists.gnu.org/archive/html/guix-devel/2016-09/msg00859.html>
+    eval "$(guix environment --search-paths --root="$gcroot" --pure guix --ad-hoc $@{PACKAGES[@@]@} $@{PACKAGES_MAINTENANCE[@@]@} "$@@")"
+
+    # Predefine configure flags.
+    configure()
+    @{
+        ./configure --localstatedir=/var --prefix=
+    @}
+    export_function configure
+
+    # Run make and optionally build something.
+    build()
+    @{
+        make -j 2
+        if [ $# -gt 0 ]
+        then
+            ./pre-inst-env guix build "$@@"
+        fi
+    @}
+    export_function build
+
+    # Predefine push Git command.
+    push()
+    @{
+        git push --set-upstream origin
+    @}
+    export_function push
+
+    clear                        # Clean up the screen.
+    git-cal --author='Your Name' # Show contributions calendar.
+
+    # Show commands help.
+    echo "
+build          build a package or just a project if no argument provided
+configure      run ./configure with predefined parameters
+push           push to upstream Git repository
+"
+@}
+@end example
+
+Every project containing @file{.envrc} with a string @code{use guix}
+will have predefined environment variables and procedures.
+
+Run @command{direnv allow} to setup the environment for the first time.
+
 @c *********************************************************************
 @node Acknowledgments
 @chapter Acknowledgments