summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore31
-rw-r--r--Makefile.am3
-rwxr-xr-xbootstrap12
-rw-r--r--doc/guix-cookbook.texi821
-rw-r--r--doc/local.mk9
-rw-r--r--po/doc/local.mk33
6 files changed, 890 insertions, 19 deletions
diff --git a/.gitignore b/.gitignore
index 93d2ec9801..38cde42fca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,22 +29,23 @@
 /doc/*.1
 /doc/.dirstamp
 /doc/contributing.*.texi
-/doc/guix.*.aux
-/doc/guix.*.cp
-/doc/guix.*.cps
-/doc/guix.*.fn
-/doc/guix.*.fns
-/doc/guix.*.html
-/doc/guix.*.info
-/doc/guix.*.info-[0-9]
-/doc/guix.*.ky
-/doc/guix.*.pg
-/doc/guix.*.toc
-/doc/guix.*.t2p
-/doc/guix.*.tp
-/doc/guix.*.vr
-/doc/guix.*.vrs
+/doc/guix*.aux
+/doc/guix*.cp
+/doc/guix*.cps
+/doc/guix*.fn
+/doc/guix*.fns
+/doc/guix*.html
+/doc/guix*.info
+/doc/guix*.info-[0-9]
+/doc/guix*.ky
+/doc/guix*.pg
+/doc/guix*.toc
+/doc/guix*.t2p
+/doc/guix*.tp
+/doc/guix*.vr
+/doc/guix*.vrs
 /doc/guix.*.texi
+/doc/guix-cookbook.*.texi
 /doc/guix.aux
 /doc/guix.cp
 /doc/guix.cps
diff --git a/Makefile.am b/Makefile.am
index 7e3b5c1070..93d18d7df6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -814,7 +814,8 @@ assert-no-store-file-names:
 	$(AM_V_at)if grep -r --exclude=*.texi --exclude=*.info			\
 	     --exclude=*.info-[0-9] --exclude=*.dot				\
 	     --exclude=*.eps --exclude-dir=bootstrap				\
-		 --exclude=guix-manual.pot --exclude=guix-manual.*.po		\
+	     --exclude=guix-manual.pot --exclude=guix-manual.*.po		\
+	     --exclude=guix-cookbook.pot --exclude=guix-cookbook.*.po		\
 	     --exclude=guix-prettify.el						\
 	     --exclude=ChangeLog*						\
 	     -E "$(storedir)/[a-z0-9]{32}-" $(distdir) ;			\
diff --git a/bootstrap b/bootstrap
index c0b5af7677..c9e7a084a1 100755
--- a/bootstrap
+++ b/bootstrap
@@ -4,7 +4,7 @@
 set -e -x
 
 # Generate stubs for translations.
-langs=`find po/doc -type f -name '*.po' \
+langs=`find po/doc -type f -name 'guix-manual*.po' \
         | sed -e 's,guix-manual\.,,' \
         | xargs -n 1 -I{} basename {} .po`
 for lang in ${langs}; do
@@ -15,5 +15,15 @@ for lang in ${langs}; do
 	touch "po/doc/guix-manual.${lang}.po"
     fi
 done
+langs=`find po/doc -type f -name 'guix-cookbook*.po' \
+        | sed -e 's,guix-manual\.,,' \
+        | xargs -n 1 -I{} basename {} .po`
+for lang in ${langs}; do
+    if [ ! -e "doc/guix-cookbook.${lang}.texi" ]; then
+	echo "@setfilename guix-cookbook.${lang}.info" > "doc/guix-cookbook.${lang}.texi"
+	# Ensure .po file is newer.
+	touch "po/doc/guix-cookbook.${lang}.po"
+    fi
+done
 
 exec autoreconf -vfi
diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi
new file mode 100644
index 0000000000..66f94a0fe7
--- /dev/null
+++ b/doc/guix-cookbook.texi
@@ -0,0 +1,821 @@
+\input texinfo
+@c -*-texinfo-*-
+
+@c %**start of header
+@setfilename guix-cookbook.info
+@documentencoding UTF-8
+@settitle GNU Guix Cookbook
+@c %**end of header
+
+@copying
+Copyright @copyright{} 2019 Ricardo Wurmus@*
+Copyright @copyright{} 2019 Efraim Flashner@*
+Copyright @copyright{} 2019 Pierre Neidhardt@*
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
+copy of the license is included in the section entitled ``GNU Free
+Documentation License''.
+@end copying
+
+@dircategory System administration
+@direntry
+* Guix cookbook: (guix-cookbook).    Tutorials and examples for GNU Guix.
+@end direntry
+
+@titlepage
+@title GNU Guix Cookbook
+@subtitle Tutorials and examples for using the GNU Guix Functional Package Manager
+@author The GNU Guix Developers
+
+@page
+@vskip 0pt plus 1filll
+
+@insertcopying
+@end titlepage
+
+@contents
+
+@c *********************************************************************
+@node Top
+@top GNU Guix Cookbook
+
+This document presents tutorials and detailed examples for GNU@tie{}Guix, a
+functional package management tool written for the GNU system.  Please
+@pxref{Top,,, guix, GNU Guix reference manual} for details about the system,
+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}.
+
+@menu
+* Scheme tutorials::            Meet your new favorite language!
+* Packaging::                   Packaging tutorials
+* System Configuration::        Customizing the GNU System
+
+* Acknowledgments::             Thanks!
+* GNU Free Documentation License::  The license of this document.
+* Concept Index::               Concepts.
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Scheme tutorials
+
+* A Scheme Crash Course::       Learn the basics of Scheme
+
+Packaging
+
+* Packaging Tutorial::          Let's add a package to Guix!
+
+System Configuration
+
+* Customizing the Kernel::      Creating and using a custom Linux kernel
+
+
+@end detailmenu
+@end menu
+
+@c *********************************************************************
+@node Scheme tutorials
+@chapter Scheme tutorials
+
+GNU@tie{}Guix is written in the general purpose programming language Scheme,
+and many of its features can be accessed and manipulated programmatically.
+You can use Scheme to generate package definitions, to modify them, to build
+them, to deploy whole operating systems, etc.
+
+Knowing the basics of how to program in Scheme will unlock many of the
+advanced features Guix provides --- and you don't even need to be an
+experienced programmer to use them!
+
+Let's get started!
+
+@node A Scheme Crash Course
+@section A Scheme Crash Course
+
+@cindex Scheme, crash course
+
+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.
+
+Alternatively you can also run @code{guix environment --ad-hoc guile -- guile}
+if you'd rather not have Guile installed in your user profile.
+
+In the following examples we use the @code{>} symbol to denote the REPL
+prompt, that is, the line reserved for user input.  @xref{Using Guile
+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.
+
+Examples of valid expressions:
+
+@example scheme
+> "Hello World!"
+"Hello World!"
+> 17
+17
+> (display (string-append "Hello " "Guix" "\n"))
+"Hello Guix!"
+@end example
+
+@item
+This last example is a function call nested in another function call.  When a
+parenthesized expression is evaluated, the first term is the function and the
+rest are the arguments passed to the function.  Every function returns the
+last evaluated expression as its return value.
+
+@item
+Anonymous functions are declared with the @code{lambda} term:
+
+@example scheme
+> (lambda (x) (* x x))
+#<procedure 120e348 at <unknown port>:24:0 (x)>
+@end example
+
+The above procedure returns the square of its argument.  Since everything is
+an expression, the @code{lambda} expression returns an anonymous procedure,
+which can in turn be applied to an argument:
+
+@example scheme
+> ((lambda (x) (* x x)) 3)
+9
+@end example
+
+@item
+Anything can be assigned a global name with @code{define}:
+
+@example scheme
+> (define a 3)
+> (define square (lambda (x) (* x x)))
+> (square a)
+9
+@end example
+
+@item
+Procedures can be defined more concisely with the following syntax:
+
+@example scheme
+(define (square x) (* x x))
+@end example
+
+@item
+A list structure can be created with the @code{list} procedure:
+
+@example scheme
+> (list 2 a 5 7)
+(2 3 5 7)
+@end example
+
+@item
+The @emph{quote} disables evaluation of a parenthesized expression: the first
+term is not called over the other terms.  Thus it effectively returns a list
+of terms.
+
+@example scheme
+> '(display (string-append "Hello " "Guix" "\n"))
+(display (string-append "Hello " "Guix" "\n"))
+> '(2 a 5 7)
+(2 a 5 7)
+@end example
+
+@item
+The @emph{quasiquote} disables evaluation of a parenthesized expression until
+a comma re-enables it.  Thus it provides us with fine-grained control over
+what is evaluated and what is not.
+
+@example scheme
+> `(2 a 5 7 (2 ,a 5 ,(+ a 4)))
+(2 a 5 7 (2 3 5 7))
+@end example
+
+Note that the above result is a list of mixed elements: numbers, symbols (here
+@code{a}) and the last element is a list itself.
+
+@item
+Multiple variables can be named locally with @code{let}:
+
+@example scheme
+> (define x 10)
+> (let ((x 2)
+        (y 3))
+    (list x y))
+(2 3)
+> x
+10
+> y
+ERROR: In procedure module-lookup: Unbound variable: y
+@end example
+
+Use @code{let*} to allow later variable declarations to refer to earlier
+definitions.
+
+@example scheme
+> (let* ((x 2)
+         (y (* x 3)))
+    (list x y))
+(2 6)
+@end example
+
+@item
+The keyword syntax is @code{#:}; it is used to create unique identifiers.
+@pxref{Keywords,,, guile, GNU Guile Reference Manual}.
+
+@item
+The percentage @code{%} is typically used for read-only global variables in
+the build stage.  Note that it is merely a convention, like @code{_} in C.
+Scheme treats @code{%} exactly the same as any other letter.
+
+@item
+Modules are created with @code{define-module}.  For instance
+
+@example scheme
+(define-module (guix build-system ruby)
+  #:use-module (guix store)
+  #:export (ruby-build
+            ruby-build-system))
+@end example
+
+defines the module @code{guix build-system ruby} which must be located in
+@file{guix/build-system/ruby.scm} somewhere in the Guile load path.  It
+depends on the @code{(guix store)} module and it exports two variables,
+@code{ruby-build} and @code{ruby-build-system}.
+@end itemize
+
+For a more detailed introduction, check out
+@uref{http://www.troubleshooters.com/codecorn/scheme_guile/hello.htm, Scheme
+at a Glance}, by Steve Litt.
+
+One of the reference Scheme books is the seminal ``Structure and
+Interpretation of Computer Programs'', by Harold Abelson and Gerald Jay
+Sussman, with Julie Sussman.  You'll find a
+@uref{https://mitpress.mit.edu/sites/default/files/sicp/index.html, free copy
+online}, together with
+@uref{https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/,
+videos of the lectures by the authors}.  The book is available in Texinfo
+format as the @code{sicp} Guix package.  Go ahead, run @code{guix install
+sicp} and start reading with @code{info sicp} (or with the Emacs Info reader).
+An @uref{https://sarabander.github.io/sicp/, unofficial ebook is also
+available}.
+
+You'll find more books, tutorials and other resources at
+@url{https://schemers.org/}.
+
+
+@c *********************************************************************
+@node Packaging
+@chapter Packaging
+
+@cindex packaging
+
+This chapter is dedicated to teaching you how to add packages to the
+collection of packages that come with GNU Guix.  This involves writing package
+definitions in Guile Scheme, organizing them in package modules, and building
+them.
+
+@menu
+* Packaging Tutorial::         A tutorial on how to add packages to Guix.
+@end menu
+
+@node Packaging Tutorial
+@section Packaging Tutorial
+
+GNU Guix stands out as the @emph{hackable} package manager, mostly because it
+uses @uref{https://www.gnu.org/software/guile/, GNU Guile}, a powerful
+high-level programming language, one of the
+@uref{https://en.wikipedia.org/wiki/Scheme_%28programming_language%29, Scheme}
+dialects from the
+@uref{https://en.wikipedia.org/wiki/Lisp_%28programming_language%29, Lisp family}.
+
+Package definitions are also written in Scheme, which empowers Guix in some
+very unique ways, unlike most other package managers that use shell scripts or
+simple languages.
+
+@itemize
+@item
+Use functions, structures, macros and all of Scheme expressiveness for your
+package definitions.
+
+@item
+Inheritance makes it easy to customize a package by inheriting from it and
+modifying only what is needed.
+ 
+@item
+Batch processing: the whole package collection can be parsed, filtered and
+processed.  Building a headless server with all graphical interfaces stripped
+out?  It's possible.  Want to rebuild everything from source using specific
+compiler optimization flags?  Pass the @code{#:make-flags "..."} argument to
+the list of packages.  It wouldn't be a stretch to think
+@uref{https://wiki.gentoo.org/wiki/USE_flag, Gentoo USE flags} here, but this
+goes even further: the changes don't have to be thought out beforehand by the
+packager, they can be @emph{programmed} by the user!
+@end itemize
+
+The following tutorial covers all the basics around package creation with Guix.
+It does not assume much knowledge of the Guix system nor of the Lisp language.
+The reader is only expected to be familiar with the command line and to have some
+basic programming knowledge.
+
+@subsection A "Hello World" package
+
+The “Defining Packages” section of the manual introduces the basics of Guix
+packaging (@pxref{Defining Packages,,, guix, GNU Guix Reference Manual}).  In
+the following section, we will partly go over those basics again.
+
+``GNU hello'' is a dummy project that serves as an idiomatic example for
+packaging.  It uses the GNU build system (@code{./configure && make && make
+install}).  Guix already provides a package definition which is a perfect
+example to start with.  You can look up its declaration with @code{guix edit
+hello} from the command line.  Let's see how it looks:
+
+@example scheme
+(define-public hello
+  (package
+    (name "hello")
+    (version "2.10")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://gnu/hello/hello-" version
+                                  ".tar.gz"))
+              (sha256
+               (base32
+                "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
+    (build-system gnu-build-system)
+    (synopsis "Hello, GNU world: An example GNU package")
+    (description
+     "GNU Hello prints the message \"Hello, world!\" and then exits.  It
+serves as an example of standard GNU coding practices.  As such, it supports
+command-line arguments, multiple languages, and so on.")
+    (home-page "https://www.gnu.org/software/hello/")
+    (license gpl3+)))
+@end example
+
+As you can see, most of it is rather straightforward.  But let's review the
+fields together:
+
+@table @samp
+@item name
+The project name.  Using Scheme conventions, we prefer to keep it
+lower case, without underscore and using dash-separated words.
+
+@item source
+This field contains a description of the source code origin.  The
+@code{origin} record contains these fields:
+
+@enumerate
+@item  The method, here @code{url-fetch} to download via HTTP/FTP, but other methods
+    exist, such as @code{git-fetch} for Git repositories.
+@item  The URI, which is typically some @code{https://} location for @code{url-fetch}.  Here
+    the special `mirror://gnu` refers to a set of well known locations, all of
+    which can be used by Guix to fetch the source, should some of them fail.
+@item  The @code{sha256} checksum of the requested file.  This is essential to ensure
+    the source is not corrupted.  Note that Guix works with base32 strings,
+    hence the call to the @code{base32} function.
+@end enumerate
+
+@item build-system
+
+This is where the power of abstraction provided by the Scheme language really
+shines: in this case, the @code{gnu-build-system} abstracts away the famous
+@code{./configure && make && make install} shell invocations.  Other build
+systems include the @code{trivial-build-system} which does not do anything and
+requires from the packager to program all the build steps, the
+@code{python-build-system}, the @code{emacs-build-system}, and many more
+(@pxref{Build Systems,,, guix, GNU Guix Reference Manual}).
+
+@item synopsis
+It should be a concise summary of what the package does.  For many packages a
+tagline from the project's home page can be used as the synopsis.
+
+@item description
+Same as for the synopsis, it's fine to re-use the project description from the
+homepage.  Note that Guix uses Texinfo syntax.
+
+@item home-page
+Use HTTPS if available.
+
+@item license
+See @code{guix/licenses.scm} in the project source for a full list of
+available licenses.
+@end table
+
+Time to build our first package!  Nothing fancy here for now: we will stick to a
+dummy "my-hello", a copy of the above declaration.
+
+As with the ritualistic "Hello World" taught with most programming languages,
+this will possibly be the most "manual" approach.  We will work out an ideal
+setup later; for now we will go the simplest route.
+
+Save the following to a file @file{my-hello.scm}.
+
+@example scheme
+(use-modules (guix packages)
+             (guix download)
+             (guix build-system gnu)
+             (guix licenses))
+
+(package
+  (name "my-hello")
+  (version "2.10")
+  (source (origin
+            (method url-fetch)
+            (uri (string-append "mirror://gnu/hello/hello-" version
+                                ".tar.gz"))
+            (sha256
+             (base32
+              "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
+  (build-system gnu-build-system)
+  (synopsis "Hello, Guix world: An example custom Guix package")
+  (description
+   "GNU Hello prints the message \"Hello, world!\" and then exits.  It
+serves as an example of standard GNU coding practices.  As such, it supports
+command-line arguments, multiple languages, and so on.")
+  (home-page "https://www.gnu.org/software/hello/")
+  (license gpl3+))
+@end example
+
+We will explain the extra code in a moment.
+
+Feel free to play with the different values of the various fields.  If you
+change the source, you'll need to update the checksum.  Indeed, Guix refuses to
+build anything if the given checksum does not match the computed checksum of the
+source code.  To obtain the correct checksum of the package declaration, we
+need to download the source, compute the sha256 checksum and convert it to
+base32.
+
+Thankfully, Guix can automate this task for us; all we need is to provide the
+URI:
+
+@c TRANSLATORS: This is example shell output.
+@example sh
+$ guix download mirror://gnu/hello/hello-2.10.tar.gz
+
+Starting download of /tmp/guix-file.JLYgL7
+From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz...
+following redirection to `https://mirror.ibcp.fr/pub/gnu/hello/hello-2.10.tar.gz'...
+ …10.tar.gz  709KiB                                 2.5MiB/s 00:00 [##################] 100.0%
+/gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz
+0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
+@end example
+
+In this specific case the output tells us which mirror was chosen.
+If the result of the above command is not the same as in the above snippet,
+update your @code{my-hello} declaration accordingly.
+
+Note that GNU package tarballs come with an OpenPGP signature, so you
+should definitely check the signature of this tarball with `gpg` to
+authenticate it before going further:
+
+@c TRANSLATORS: This is example shell output.
+@example sh
+$ guix download mirror://gnu/hello/hello-2.10.tar.gz.sig
+
+Starting download of /tmp/guix-file.03tFfb
+From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz.sig...
+following redirection to `https://ftp.igh.cnrs.fr/pub/gnu/hello/hello-2.10.tar.gz.sig'...
+ ….tar.gz.sig  819B                                                                                                                       1.2MiB/s 00:00 [##################] 100.0%
+/gnu/store/rzs8wba9ka7grrmgcpfyxvs58mly0sx6-hello-2.10.tar.gz.sig
+0q0v86n3y38z17rl146gdakw9xc4mcscpk8dscs412j22glrv9jf
+$ gpg --verify /gnu/store/rzs8wba9ka7grrmgcpfyxvs58mly0sx6-hello-2.10.tar.gz.sig /gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz
+gpg: Signature made Sun 16 Nov 2014 01:08:37 PM CET
+gpg:                using RSA key A9553245FDE9B739
+gpg: Good signature from "Sami Kerola <kerolasa@@iki.fi>" [unknown]
+gpg:                 aka "Sami Kerola (http://www.iki.fi/kerolasa/) <kerolasa@@iki.fi>" [unknown]
+gpg: WARNING: This key is not certified with a trusted signature!
+gpg:          There is no indication that the signature belongs to the owner.
+Primary key fingerprint: 8ED3 96E3 7E38 D471 A005  30D3 A955 3245 FDE9 B739
+@end example
+
+You can then happily run
+
+@c TRANSLATORS: Do not translate this command
+@example sh
+$ guix package --install-from-file=my-hello.scm
+@end example
+
+You should now have @code{my-hello} in your profile!
+
+@c TRANSLATORS: Do not translate this command
+@example sh
+$ guix package --list-installed=my-hello
+my-hello	2.10	out
+/gnu/store/f1db2mfm8syb8qvc357c53slbvf1g9m9-my-hello-2.10
+@end example
+
+We've gone as far as we could without any knowledge of Scheme.  Before moving
+on to more complex packages, now is the right time to brush up on your Scheme
+knowledge.  @pxref{A Scheme Crash Course} to get up to speed.
+
+@c TODO: Continue the tutorial
+
+
+@c *********************************************************************
+@node System Configuration
+@chapter System Configuration
+
+Guix offers a flexible language for declaratively configuring your Guix
+System.  This flexibility can at times be overwhelming.  The purpose of this
+chapter is to demonstrate some advanced configuration concepts.
+
+@pxref{System Configuration,,, guix, GNU Guix Reference Manual} for a complete
+reference.
+
+@menu
+* Customizing the Kernel::     Creating and using a custom Linux kernel on Guix System.
+@end menu
+
+@node Customizing the Kernel
+@section Customizing the Kernel
+
+Guix is, at its core, a source based distribution with substitutes
+(@pxref{Substitutes,,, guix, GNU Guix Reference Manual}), and as such building
+packages from their source code is an expected part of regular package
+installations and upgrades.  Given this starting point, it makes sense that
+efforts are made to reduce the amount of time spent compiling packages, and
+recent changes and upgrades to the building and distribution of substitutes
+continues to be a topic of discussion within Guix.
+
+The kernel, while not requiring an overabundance of RAM to build, does take a
+rather long time on an average machine.  The official kernel configuration, as
+is the case with many GNU/Linux distributions, errs on the side of
+inclusiveness, and this is really what causes the build to take such a long
+time when the kernel is built from source.
+
+The Linux kernel, however, can also just be described as a regular old
+package, and as such can be customized just like any other package.  The
+procedure is a little bit different, although this is primarily due to the
+nature of how the package definition is written.
+
+The @code{linux-libre} kernel package definition is actually a procedure which
+creates a package.
+
+@example scheme
+(define* (make-linux-libre version hash supported-systems
+                           #:key
+                           ;; A function that takes an arch and a variant.
+                           ;; See kernel-config for an example.
+                           (extra-version #f)
+                           (configuration-file #f)
+                           (defconfig "defconfig")
+                           (extra-options %default-extra-linux-options)
+                           (patches (list %boot-logo-patch)))
+  ...)
+@end example
+
+The current @code{linux-libre} package is for the 5.1.x series, and is
+declared like this:
+
+@example scheme
+(define-public linux-libre
+  (make-linux-libre %linux-libre-version
+                    %linux-libre-hash
+                    '("x86_64-linux" "i686-linux" "armhf-linux" "aarch64-linux")
+                    #:patches %linux-libre-5.1-patches
+                    #:configuration-file kernel-config))
+@end example
+
+Any keys which are not assigned values inherit their default value from the
+@code{make-linux-libre} definition.  When comparing the two snippets above,
+you may notice that the code comment in the first doesn't actually refer to
+the @code{#:extra-version} keyword; it is actually for
+@code{#:configuration-file}.  Because of this, it is not actually easy to
+include a custom kernel configuration from the definition, but don't worry,
+there are other ways to work with what we do have.
+
+There are two ways to create a kernel with a custom kernel configuration.  The
+first is to provide a standard @file{.config} file during the build process by
+including an actual @file{.config} file as a native input to our custom
+kernel.  The following is a snippet from the custom @code{'configure} phase of
+the @code{make-linux-libre} package definition:
+
+@example scheme
+(let ((build  (assoc-ref %standard-phases 'build))
+      (config (assoc-ref (or native-inputs inputs) "kconfig")))
+
+  ;; Use a custom kernel configuration file or a default
+  ;; configuration file.
+  (if config
+      (begin
+        (copy-file config ".config")
+        (chmod ".config" #o666))
+      (invoke "make" ,defconfig))
+@end example
+
+Below is a sample kernel package.  The @code{linux-libre} package is nothing
+special and can be inherited from and have its fields overridden like any
+other package:
+
+@example scheme
+(define-public linux-libre/E2140
+  (package
+    (inherit linux-libre)
+    (native-inputs
+     `(("kconfig" ,(local-file "E2140.config"))
+      ,@@(alist-delete "kconfig"
+                      (package-native-inputs linux-libre))))))
+@end example
+
+In the same directory as the file defining @code{linux-libre-E2140} is a file
+named @file{E2140.config}, which is an actual kernel configuration file.  The
+@code{defconfig} keyword of @code{make-linux-libre} is left blank here, so the
+only kernel configuration in the package is the one which was included in the
+@code{native-inputs} field.
+
+The second way to create a custom kernel is to pass a new value to the
+@code{extra-options} keyword of the @code{make-linux-libre} procedure.  The
+@code{extra-options} keyword works with another function defined right below
+it:
+
+@example scheme
+(define %default-extra-linux-options
+  `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html
+   ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #t)
+   ;; Modules required for initrd:
+   ("CONFIG_NET_9P" . m)
+   ("CONFIG_NET_9P_VIRTIO" . m)
+   ("CONFIG_VIRTIO_BLK" . m)
+   ("CONFIG_VIRTIO_NET" . m)
+   ("CONFIG_VIRTIO_PCI" . m)
+   ("CONFIG_VIRTIO_BALLOON" . m)
+   ("CONFIG_VIRTIO_MMIO" . m)
+   ("CONFIG_FUSE_FS" . m)
+   ("CONFIG_CIFS" . m)
+   ("CONFIG_9P_FS" . m)))
+
+(define (config->string options)
+  (string-join (map (match-lambda
+                      ((option . 'm)
+                       (string-append option "=m"))
+                      ((option . #t)
+                       (string-append option "=y"))
+                      ((option . #f)
+                       (string-append option "=n")))
+                    options)
+               "\n"))
+@end example
+
+And in the custom configure script from the `make-linux-libre` package:
+
+@example scheme
+;; Appending works even when the option wasn't in the
+;; file.  The last one prevails if duplicated.
+(let ((port (open-file ".config" "a"))
+      (extra-configuration ,(config->string extra-options)))
+  (display extra-configuration port)
+  (close-port port))
+
+(invoke "make" "oldconfig"))))
+@end example
+
+So by not providing a configuration-file the @file{.config} starts blank, and
+then we write into it the collection of flags that we want.  Here's another
+custom kernel:
+
+@example scheme
+(define %macbook41-full-config
+  (append %macbook41-config-options
+          %filesystems
+          %efi-support
+          %emulation
+          (@@@@ (gnu packages linux) %default-extra-linux-options)))
+
+(define-public linux-libre-macbook41
+  ;; XXX: Access the internal 'make-linux-libre' procedure, which is
+  ;; private and unexported, and is liable to change in the future.
+  ((@@@@ (gnu packages linux) make-linux-libre) (@@@@ (gnu packages linux) %linux-libre-version)
+                      (@@@@ (gnu packages linux) %linux-libre-hash)
+                      '("x86_64-linux")
+                      #:extra-version "macbook41"
+                      #:patches (@@@@ (gnu packages linux) %linux-libre-5.1-patches)
+                      #:extra-options %macbook41-config-options))
+@end example
+
+In the above example @code{%filesystems} is a collection of flags enabling
+different filesystem 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.
+
+This all sounds like it should be doable, but how does one even know which
+modules are required for a particular system?  Two places that can be helpful
+in trying to answer this question is the
+@uref{https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Kernel, Gentoo
+Handbook} and the
+@uref{https://www.kernel.org/doc/html/latest/admin-guide/README.html?highlight=localmodconfig,
+documentation from the kernel itself}.  From the kernel documentation, it
+seems that @code{make localmodconfig} is the command we want.
+
+In order to actually run @code{make localmodconfig} we first need to get and
+unpack the kernel source code:
+
+@example shell
+tar xf $(guix build linux-libre --source)
+@end example
+
+Once inside the directory containing the source code run @code{touch .config}
+to create an initial, empty @file{.config} to start with.  @code{make
+localmodconfig} works by seeing what you already have in @file{.config} and
+letting you know what you're missing.  If the file is blank then you're
+missing everything.  The next step is to run:
+
+@example shell
+guix environment linux-libre -- make localmodconfig
+@end example
+
+and note the output.  Do note that the @file{.config} file is still empty.
+The output generally contains two types of warnings.  The first start with
+"WARNING" and can actually be ignored in our case.  The second read:
+
+@example shell
+module pcspkr did not have configs CONFIG_INPUT_PCSPKR
+@end example
+
+For each of these lines, copy the @code{CONFIG_XXXX_XXXX} portion into the
+@file{.config} in the directory, and append @code{=m}, so in the end it looks
+like this:
+
+@example shell
+CONFIG_INPUT_PCSPKR=m
+CONFIG_VIRTIO=m
+@end example
+
+After copying all the configuration options, run @code{make localmodconfig}
+again to make sure that you don't have any output starting with "module".
+After all of these machine specific modules there are a couple more left that
+are also needed.  @code{CONFIG_MODULES} is necessary so that you can build and
+load modules separately and not have everything built into the kernel.
+@code{CONFIG_BLK_DEV_SD} is required for reading from hard drives.  It is
+possible that there are other modules which you will need.
+
+This post does not aim to be a guide to configuring your own kernel however,
+so if you do decide to build a custom kernel you'll have to seek out other
+guides to create a kernel which is just right for your needs.
+
+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
+see at a glance what features are enabled and to make sure you don't have
+features in one kernel but missing in another.
+
+Left undiscussed however, is Guix's initrd and its customization.  It is
+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.
+
+@c *********************************************************************
+@node Acknowledgments
+@chapter Acknowledgments
+
+Guix is based on the @uref{https://nixos.org/nix/, Nix package manager},
+which was designed and
+implemented by Eelco Dolstra, with contributions from other people (see
+the @file{nix/AUTHORS} file in Guix.)  Nix pioneered functional package
+management, and promoted unprecedented features, such as transactional
+package upgrades and rollbacks, per-user profiles, and referentially
+transparent build processes.  Without this work, Guix would not exist.
+
+The Nix-based software distributions, Nixpkgs and NixOS, have also been
+an inspiration for Guix.
+
+GNU@tie{}Guix itself is a collective work with contributions from a
+number of people.  See the @file{AUTHORS} file in Guix for more
+information on these fine people.  The @file{THANKS} file lists people
+who have helped by reporting bugs, taking care of the infrastructure,
+providing artwork and themes, making suggestions, and more---thank you!
+
+This document includes adapted sections from articles that have previously
+been published on the Guix blog at @uref{https://guix.gnu.org/blog}.
+
+
+@c *********************************************************************
+@node GNU Free Documentation License
+@appendix GNU Free Documentation License
+@cindex license, GNU Free Documentation License
+@include fdl-1.3.texi
+
+@c *********************************************************************
+@node Concept Index
+@unnumbered Concept Index
+@printindex cp
+
+@bye
+
+@c Local Variables:
+@c ispell-local-dictionary: "american";
+@c End:
diff --git a/doc/local.mk b/doc/local.mk
index 336e961c4f..850612605b 100644
--- a/doc/local.mk
+++ b/doc/local.mk
@@ -26,7 +26,8 @@ info_TEXINFOS = %D%/guix.texi			\
   %D%/guix.es.texi				\
   %D%/guix.fr.texi				\
   %D%/guix.ru.texi				\
-  %D%/guix.zh_CN.texi
+  %D%/guix.zh_CN.texi				\
+  %D%/guix-cookbook.texi
 
 %C%_guix_TEXINFOS = \
   %D%/contributing.texi \
@@ -108,6 +109,12 @@ $(srcdir)/%D%/guix.%.texi: po/doc/guix-manual.%.po $(srcdir)/%D%/contributing.%.
 	-$(AM_V_POXREF)$(xref_command)
 	-mv "$@.tmp" "$@"
 
+$(srcdir)/%D%/guix-cookbook.%.texi: po/doc/guix-cookbook.%.po
+	-$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/guix-cookbook.texi" -p "$<" -l "$@.tmp"
+	-sed -i "s|guix-cookbook\.info|$$(basename "$@" | sed 's|texi$$|info|')|" "$@.tmp"
+	-$(AM_V_POXREF)$(xref_command)
+	-mv "$@.tmp" "$@"
+
 $(srcdir)/%D%/contributing.%.texi: po/doc/guix-manual.%.po
 	-$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/contributing.texi" -p "$<" -l "$@.tmp"
 	-$(AM_V_POXREF)$(xref_command)
diff --git a/po/doc/local.mk b/po/doc/local.mk
index fb3c5aee03..f1a52615c1 100644
--- a/po/doc/local.mk
+++ b/po/doc/local.mk
@@ -23,9 +23,13 @@ DOC_PO_FILES=					\
   %D%/guix-manual.ru.po				\
   %D%/guix-manual.zh_CN.po
 
+DOC_COOKBOOK_PO_FILES=
+
 EXTRA_DIST = \
   %D%/guix-manual.pot \
-  $(DOC_PO_FILES)
+  %D%/guix-cookbook.pot \
+  $(DOC_PO_FILES) \
+  $(DOC_COOKBOOK_PO_FILES)
 
 POT_OPTIONS = --package-name "guix" --package-version "$(VERSION)" \
 	          --copyright-holder "Ludovic Courtès" \
@@ -52,6 +56,27 @@ doc-po-update-%:
 	     exit 1; \
 	fi
 
+doc-po-update-cookbook-%:
+	@lang=`echo "$@" | sed -e's/^doc-po-update-//'` ; \
+	output="$(srcdir)/po/doc/guix-cookbook.$$lang.po" ; \
+	input="$(srcdir)/po/doc/guix-cookbook.pot" ; \
+	if test -f "$$output"; then \
+	  test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+	  echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $$output $$input"; \
+	  cd $(srcdir) \
+	    && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
+	        '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
+	          $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) "$$output" "$$input";; \
+	        *) \
+	          $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} "$$output" "$$input";; \
+	      esac; \
+	    }; \
+	  touch "$$output"; \
+	else \
+	     echo "File $$output does not exist.  If you are a translator, you can create it with 'msginit'." 1>&2; \
+	     exit 1; \
+	fi
+
 $(srcdir)/po/doc/%.pot-update: doc/%.texi
 	$(AM_V_PO4A)$(PO4A_UPDATEPO) -M UTF-8 -f texinfo -m "$<" \
 		-p "$$(echo $@ | sed 's|-update||')" $(POT_OPTIONS)
@@ -64,6 +89,7 @@ doc-pot-update:
 		$(MAKE) $(srcdir)/po/doc/guix.pot-update; \
 		$(MAKE) $(srcdir)/po/doc/contributing.pot-update; \
 	done
+	$(MAKE) $(srcdir)/po/doc/guix-cookbook.pot-update;
 	msgcat $(addprefix $(srcdir)/po/doc/, $(TMP_POT_FILES)) > $(srcdir)/po/doc/guix-manual.pot
 	rm -f $(addprefix $(srcdir)/po/doc/, $(TMP_POT_FILES))
 
@@ -72,5 +98,10 @@ doc-po-update: doc-pot-update
 	  lang="`echo "$$f" | $(SED) -es'|.*/guix-manual\.\(.*\)\.po$$|\1|g'`";	\
 	  $(MAKE) "doc-po-update-$$lang";					\
 	done
+	for f in $(DOC_COOKBOOK_PO_FILES); do						\
+	  lang="`echo "$$f" | $(SED) -es'|.*/guix-cookbook\.\(.*\)\.po$$|\1|g'`";	\
+	  $(MAKE) "doc-po-update-cookbook-$$lang";						\
+	done
+
 
 .PHONY: doc-po-update doc-pot-update