summary refs log tree commit diff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/build.scm563
-rw-r--r--doc/guix.texi122
2 files changed, 685 insertions, 0 deletions
diff --git a/doc/build.scm b/doc/build.scm
new file mode 100644
index 0000000000..e628a91048
--- /dev/null
+++ b/doc/build.scm
@@ -0,0 +1,563 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+
+;; This file contains machinery to build HTML and PDF copies of the manual
+;; that can be readily published on the web site.  To do that, run:
+;;
+;;  guix build -f build.scm
+;;
+;; The result is a directory hierarchy that can be used as the manual/
+;; sub-directory of the web site.
+
+(use-modules (guix)
+             (guix gexp)
+             (guix git)
+             (guix git-download)
+             (git)
+             (gnu packages base)
+             (gnu packages gawk)
+             (gnu packages gettext)
+             (gnu packages guile)
+             (gnu packages texinfo)
+             (gnu packages tex)
+             (srfi srfi-19)
+             (srfi srfi-71))
+
+(define file-append*
+  (@@ (guix self) file-append*))
+
+(define translated-texi-manuals
+  (@@ (guix self) translate-texi-manuals))
+
+(define info-manual
+  (@@ (guix self) info-manual))
+
+(define %languages
+  '("de" "en" "es" "fr" "ru" "zh_CN"))
+
+(define (texinfo-manual-images source)
+  "Return a directory containing all the images used by the user manual, taken
+from SOURCE, the root of the source tree."
+  (define graphviz
+    (module-ref (resolve-interface '(gnu packages graphviz))
+                'graphviz))
+
+  (define images
+    (file-append* source "doc/images"))
+
+  (define build
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils)
+                       (srfi srfi-26))
+
+          (define (dot->image dot-file format)
+            (invoke #+(file-append graphviz "/bin/dot")
+                    "-T" format "-Gratio=.9" "-Gnodesep=.005"
+                    "-Granksep=.00005" "-Nfontsize=9"
+                    "-Nheight=.1" "-Nwidth=.1"
+                    "-o" (string-append #$output "/"
+                                        (basename dot-file ".dot")
+                                        "." format)
+                    dot-file))
+
+          ;; Build graphs.
+          (mkdir-p #$output)
+          (for-each (lambda (dot-file)
+                      (for-each (cut dot->image dot-file <>)
+                                '("png" "pdf")))
+                    (find-files #$images "\\.dot$"))
+
+          ;; Copy other PNGs.
+          (for-each (lambda (png-file)
+                      (install-file png-file #$output))
+                    (find-files #$images "\\.png$")))))
+
+  (computed-file "texinfo-manual-images" build))
+
+(define* (texinfo-manual-source source #:key
+                                (version "0.0")
+                                (languages %languages)
+                                (date 1))
+  "Gather all the source files of the Texinfo manuals from SOURCE--.texi file
+as well as images, OS examples, and translations."
+  (define documentation
+    (file-append* source "doc"))
+
+  (define examples
+    (file-append* source "gnu/system/examples"))
+
+  (define build
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils)
+                       (srfi srfi-19))
+
+          (define (make-version-texi language)
+            ;; Create the 'version.texi' file for LANGUAGE.
+            (let ((file (if (string=? language "en")
+                            "version.texi"
+                            (string-append "version-" language ".texi"))))
+              (call-with-output-file (string-append #$output "/" file)
+                (lambda (port)
+                  (let* ((version #$version)
+                         (time    (make-time time-utc 0 #$date))
+                         (date    (time-utc->date time)))
+                    (format port "
+@set UPDATED ~a
+@set UPDATED-MONTH ~a
+@set EDITION ~a
+@set VERSION ~a\n"
+                            (date->string date "~e ~B ~Y")
+                            (date->string date "~B ~Y")
+                            version version))))))
+
+          (install-file #$(file-append* documentation "/htmlxref.cnf")
+                        #$output)
+
+          (for-each (lambda (texi)
+                      (install-file texi #$output))
+                    (append (find-files #$documentation "\\.(texi|scm)$")
+                            (find-files #$(translated-texi-manuals source)
+                                        "\\.texi$")))
+
+          ;; Create 'version.texi'.
+          (for-each make-version-texi '#$languages)
+
+          ;; Copy configuration templates that the manual includes.
+          (for-each (lambda (template)
+                      (copy-file template
+                                 (string-append
+                                  #$output "/os-config-"
+                                  (basename template ".tmpl")
+                                  ".texi")))
+                    (find-files #$examples "\\.tmpl$"))
+
+          (symlink #$(texinfo-manual-images source)
+                   (string-append #$output "/images")))))
+
+  (computed-file "texinfo-manual-source" build))
+
+(define %web-site-url
+  ;; URL of the web site home page.
+  (or (getenv "GUIX_WEB_SITE_URL")
+      "/software/guix/"))
+
+(define %makeinfo-html-options
+  ;; Options passed to 'makeinfo --html'.
+  '("--css-ref=https://www.gnu.org/software/gnulib/manual.css"))
+
+(define* (html-manual source #:key (languages %languages)
+                      (version "0.0")
+                      (manual "guix")
+                      (date 1)
+                      (options %makeinfo-html-options))
+  "Return the HTML manuals built from SOURCE for all LANGUAGES, with the given
+makeinfo OPTIONS."
+  (define manual-source
+    (texinfo-manual-source source
+                           #:version version
+                           #:languages languages
+                           #:date date))
+
+  (define build
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils)
+                       (ice-9 match))
+
+          (define (normalize language)
+            ;; Normalize LANGUAGE.  For instance, "zh_CN" become "zh-cn".
+            (string-map (match-lambda
+                          (#\_ #\-)
+                          (chr chr))
+                        (string-downcase language)))
+
+          ;; Install a UTF-8 locale so that 'makeinfo' is at ease.
+          (setenv "GUIX_LOCPATH"
+                  #+(file-append glibc-utf8-locales "/lib/locale"))
+          (setenv "LC_ALL" "en_US.utf8")
+
+          (setvbuf (current-output-port) 'line)
+          (setvbuf (current-error-port) 'line)
+
+          (for-each (lambda (language)
+                      (let ((opts `("--html"
+                                    "-c" ,(string-append "TOP_NODE_UP_URL=/manual/"
+                                                         language)
+                                    #$@options
+                                    ,(if (string=? language "en")
+                                         (string-append #$manual-source "/"
+                                                        #$manual ".texi")
+                                         (string-append #$manual-source "/"
+                                                        #$manual "." language ".texi")))))
+                        (format #t "building HTML manual for language '~a'...~%"
+                                language)
+                        (mkdir-p (string-append #$output "/"
+                                                (normalize language)))
+                        (setenv "LANGUAGE" language)
+                        (apply invoke #$(file-append texinfo "/bin/makeinfo")
+                               "-o" (string-append #$output "/"
+                                                   (normalize language)
+                                                   "/html_node")
+                               opts)
+                        (apply invoke #$(file-append texinfo "/bin/makeinfo")
+                               "--no-split"
+                               "-o"
+                               (string-append #$output "/"
+                                              (normalize language)
+                                              "/" #$manual
+                                              (if (string=? language "en")
+                                                  ""
+                                                  (string-append "." language))
+                                              ".html")
+                               opts)))
+                    '#$languages))))
+
+  (computed-file (string-append manual "-html-manual") build))
+
+(define* (pdf-manual source #:key (languages %languages)
+                     (version "0.0")
+                     (manual "guix")
+                     (date 1)
+                     (options '()))
+  "Return the HTML manuals built from SOURCE for all LANGUAGES, with the given
+makeinfo OPTIONS."
+  (define manual-source
+    (texinfo-manual-source source
+                           #:version version
+                           #:languages languages
+                           #:date date))
+
+  ;; FIXME: This union works, except for the table of contents of non-English
+  ;; manuals, which contains escape sequences like "^^ca^^fe" instead of
+  ;; accented letters.
+  ;;
+  ;; (define texlive
+  ;;   (texlive-union (list texlive-tex-texinfo
+  ;;                        texlive-generic-epsf
+  ;;                        texlive-fonts-ec)))
+
+  (define build
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils)
+                       (srfi srfi-34)
+                       (ice-9 match))
+
+          (define (normalize language)            ;XXX: deduplicate
+            ;; Normalize LANGUAGE.  For instance, "zh_CN" becomes "zh-cn".
+            (string-map (match-lambda
+                          (#\_ #\-)
+                          (chr chr))
+                        (string-downcase language)))
+
+          ;; Install a UTF-8 locale so that 'makeinfo' is at ease.
+          (setenv "GUIX_LOCPATH"
+                  #+(file-append glibc-utf8-locales "/lib/locale"))
+          (setenv "LC_ALL" "en_US.utf8")
+          (setenv "PATH"
+                  (string-append #+(file-append texlive "/bin") ":"
+                                 #+(file-append texinfo "/bin") ":"
+
+                                 ;; Below are command-line tools needed by
+                                 ;; 'texi2dvi' and friends.
+                                 #+(file-append sed "/bin") ":"
+                                 #+(file-append grep "/bin") ":"
+                                 #+(file-append coreutils "/bin") ":"
+                                 #+(file-append gawk "/bin") ":"
+                                 #+(file-append tar "/bin") ":"
+                                 #+(file-append diffutils "/bin")))
+
+          (setvbuf (current-output-port) 'line)
+          (setvbuf (current-error-port) 'line)
+
+          (setenv "HOME" (getcwd))                ;for kpathsea/mktextfm
+
+          ;; 'SOURCE_DATE_EPOCH' is honored by pdftex.
+          (setenv "SOURCE_DATE_EPOCH" "1")
+
+          (for-each (lambda (language)
+                      (let ((opts `("--pdf"
+                                    "-I" "."
+                                    #$@options
+                                    ,(if (string=? language "en")
+                                         (string-append #$manual-source "/"
+                                                        #$manual ".texi")
+                                         (string-append #$manual-source "/"
+                                                        #$manual "." language ".texi")))))
+                        (format #t "building PDF manual for language '~a'...~%"
+                                language)
+                        (mkdir-p (string-append #$output "/"
+                                                (normalize language)))
+                        (setenv "LANGUAGE" language)
+
+
+                        ;; FIXME: Unfortunately building PDFs for non-Latin
+                        ;; alphabets doesn't work:
+                        ;; <https://lists.gnu.org/archive/html/help-texinfo/2012-01/msg00014.html>.
+                        (guard (c ((invoke-error? c)
+                                   (format (current-error-port)
+                                           "~%~%Failed to produce \
+PDF for language '~a'!~%~%"
+                                           language)))
+                         (apply invoke #$(file-append texinfo "/bin/makeinfo")
+                                "--pdf" "-o"
+                                (string-append #$output "/"
+                                               (normalize language)
+                                               "/" #$manual
+                                               (if (string=? language "en")
+                                                   ""
+                                                   (string-append "."
+                                                                  language))
+                                               ".pdf")
+                                opts))))
+                    '#$languages))))
+
+  (computed-file (string-append manual "-pdf-manual") build))
+
+(define (guix-manual-text-domain source languages)
+  "Return the PO files for LANGUAGES of the 'guix-manual' text domain taken
+from SOURCE."
+  (define po-directory
+    (file-append* source "/po/doc"))
+
+  (define build
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils))
+
+          (mkdir-p #$output)
+          (for-each (lambda (language)
+                      (define directory
+                        (string-append #$output "/" language
+                                       "/LC_MESSAGES"))
+
+                      (mkdir-p directory)
+                      (invoke #+(file-append gnu-gettext "/bin/msgfmt")
+                              "-c" "-o"
+                              (string-append directory "/guix-manual.mo")
+                              (string-append #$po-directory "/guix-manual."
+                                             language ".po")))
+                    '#$(delete "en" languages)))))
+
+  (computed-file "guix-manual-po" build))
+
+(define* (html-manual-indexes source
+                              #:key (languages %languages)
+                              (version "0.0")
+                              (manual "guix")
+                              (date 1))
+  (define build
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils)
+                       (ice-9 match)
+                       (ice-9 popen)
+                       (sxml simple)
+                       (srfi srfi-19))
+
+          (define (normalize language)            ;XXX: deduplicate
+            ;; Normalize LANGUAGE.  For instance, "zh_CN" become "zh-cn".
+            (string-map (match-lambda
+                          (#\_ #\-)
+                          (chr chr))
+                        (string-downcase language)))
+
+          (define-syntax-rule (with-language language exp ...)
+            (let ((lang (getenv "LANGUAGE")))
+              (dynamic-wind
+                (lambda ()
+                  (setenv "LANGUAGE" language)
+                  (setlocale LC_MESSAGES))
+                (lambda () exp ...)
+                (lambda ()
+                  (if lang
+                      (setenv "LANGUAGE" lang)
+                      (unsetenv "LANGUAGE"))
+                  (setlocale LC_MESSAGES)))))
+
+          ;; (put 'with-language 'scheme-indent-function 1)
+          (define* (translate str language
+                              #:key (domain "guix-manual"))
+            (define exp
+              `(begin
+                 (bindtextdomain "guix-manual"
+                                 #+(guix-manual-text-domain
+                                    source
+                                    languages))
+                 (write (gettext ,str "guix-manual"))))
+
+            (with-language language
+              ;; Since the 'gettext' function caches msgid translations,
+              ;; regardless of $LANGUAGE, we have to spawn a new process each
+              ;; time we want to translate to a different language.  Bah!
+              (let* ((pipe (open-pipe* OPEN_READ
+                                       #+(file-append guile-2.2
+                                                      "/bin/guile")
+                                       "-c" (object->string exp)))
+                     (str  (read pipe)))
+                (close-pipe pipe)
+                str)))
+
+          (define (seconds->string seconds language)
+            (let* ((time (make-time time-utc 0 seconds))
+                   (date (time-utc->date time)))
+              (with-language language (date->string date "~e ~B ~Y"))))
+
+          (define (guix-url path)
+            (string-append #$%web-site-url path))
+
+          (define (sxml-index language)
+            (define title
+              (translate "GNU Guix Reference Manual" language))
+
+            ;; FIXME: Avoid duplicating styling info from guix-artwork.git.
+            `(html (@ (lang ,language))
+                   (head
+                    (title ,(string-append title " — GNU Guix"))
+                    (meta (@ (charset "UTF-8")))
+                    (meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0")))
+                    ;; Menu prefetch.
+                    (link (@ (rel "prefetch") (href ,(guix-url "menu/index.html"))))
+                    ;; Base CSS.
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/elements.css"))))
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/common.css"))))
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/messages.css"))))
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/navbar.css"))))
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/breadcrumbs.css"))))
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/buttons.css"))))
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/footer.css"))))
+
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/page.css"))))
+                    (link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/post.css")))))
+                   (body
+                    (header (@ (class "navbar"))
+                            (h1 (a (@ (class "branding")
+                                      (href #$%web-site-url)))
+                                (span (@ (class "a11y-offset"))
+                                      "Guix"))
+                            (nav (@ (class "menu"))))
+                    (nav (@ (class "breadcrumbs"))
+                         (a (@ (class "crumb")
+                               (href #$%web-site-url))
+                            "Home"))
+                    (main
+                     (article
+                      (@ (class "page centered-block limit-width"))
+                      (h2 ,title)
+                      (p (@ (class "post-metadata centered-text"))
+                         #$version " — "
+                         ,(seconds->string #$date language))
+
+                      (div
+                       (ul
+                        (li (a (@ (href "html_node"))
+                               "HTML, with one page per node"))
+                        (li (a (@ (href
+                                   ,(string-append
+                                     #$manual
+                                     (if (string=? language
+                                                   "en")
+                                         ""
+                                         (string-append "."
+                                                        language))
+                                     ".html")))
+                               "HTML, entirely on one page"))
+                        ,@(if (member language '("ru" "zh_CN"))
+                              '()
+                              `((li (a (@ (href ,(string-append
+                                                  #$manual
+                                                  (if (string=? language "en")
+                                                      ""
+                                                      (string-append "."
+                                                                     language))
+                                                  ".pdf"))))
+                                    "PDF")))))))
+                    (footer))))
+
+          (define (write-index language file)
+            (call-with-output-file file
+              (lambda (port)
+                (display "<!DOCTYPE html>\n" port)
+                (sxml->xml (sxml-index language) port))))
+
+          (setenv "GUIX_LOCPATH"
+                  #+(file-append glibc-utf8-locales "/lib/locale"))
+          (setenv "LC_ALL" "en_US.utf8")
+          (setlocale LC_ALL "en_US.utf8")
+
+          (bindtextdomain "guix-manual"
+                          #+(guix-manual-text-domain source languages))
+
+          (for-each (lambda (language)
+                      (define directory
+                        (string-append #$output "/"
+                                       (normalize language)))
+
+                      (mkdir-p directory)
+                      (write-index language
+                                   (string-append directory
+                                                  "/index.html")))
+                    '#$languages))))
+
+  (computed-file "html-indexes" build))
+
+(define* (pdf+html-manual source
+                          #:key (languages %languages)
+                          (version "0.0")
+                          (date (time-second (current-time time-utc)))
+                          (manual "guix"))
+  "Return the union of the HTML and PDF manuals, as well as the indexes."
+  (directory-union (string-append manual "-manual")
+                   (map (lambda (proc)
+                          (proc source
+                                #:date date
+                                #:languages languages
+                                #:version version
+                                #:manual manual))
+                        (list html-manual-indexes
+                              html-manual pdf-manual))
+                   #:copy? #t))
+
+(define (latest-commit+date directory)
+  "Return two values: the last commit ID (a hex string) for DIRECTORY, and its
+commit date (an integer)."
+  (let* ((repository (repository-open directory))
+         (head       (repository-head repository))
+         (oid        (reference-target head))
+         (commit     (commit-lookup repository oid)))
+    ;; TODO: Use (git describe) when it's widely available.
+    (values (oid->string oid) (commit-time commit))))
+
+
+(let* ((root (canonicalize-path
+              (string-append (current-source-directory) "/..")))
+       (commit date (latest-commit+date root)))
+  (format (current-error-port)
+          "building manual from work tree around commit ~a, ~a~%"
+          commit
+          (let* ((time (make-time time-utc 0 date))
+                 (date (time-utc->date time)))
+            (date->string date "~e ~B ~Y")))
+  (pdf+html-manual (local-file root "guix" #:recursive? #t
+                               #:select? (git-predicate root))
+                   #:version (or (getenv "GUIX_MANUAL_VERSION")
+                                 (string-take commit 7))
+                   #:date date))
diff --git a/doc/guix.texi b/doc/guix.texi
index 33a3fbff5a..cb2cfed637 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -65,6 +65,7 @@ Copyright @copyright{} 2018 Alex Vong@*
 Copyright @copyright{} 2019 Josh Holland@*
 Copyright @copyright{} 2019 Diego Nicola Barbato@*
 Copyright @copyright{} 2019 Ivan Petkov@*
+Copyright @copyright{} 2019 Jakob L. Kreuze@*
 
 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -81,6 +82,7 @@ Documentation License''.
 * guix gc: (guix)Invoking guix gc.            Reclaiming unused disk space.
 * guix pull: (guix)Invoking guix pull.        Update the list of available packages.
 * guix system: (guix)Invoking guix system.    Manage the operating system configuration.
+* guix deploy: (guix)Invoking guix deploy.    Manage operating system configurations for remote hosts.
 @end direntry
 
 @dircategory Software development
@@ -269,6 +271,7 @@ System Configuration
 * Initial RAM Disk::            Linux-Libre bootstrapping.
 * Bootloader Configuration::    Configuring the boot loader.
 * Invoking guix system::        Instantiating a system configuration.
+* Invoking guix deploy::        Deploying a system configuration to a remote host.
 * Running Guix in a VM::        How to run Guix System in a virtual machine.
 * Defining Services::           Adding new service definitions.
 
@@ -4654,6 +4657,14 @@ While this will limit the leaking of user identity through home paths
 and each of the user fields, this is only one useful component of a
 broader privacy/anonymity solution---not one in and of itself.
 
+@item --no-cwd
+For containers, the default behavior is to share the current working
+directory with the isolated container and immediately change to that
+directory within the container.  If this is undesirable, @code{--no-cwd}
+will cause the current working directory to @emph{not} be automatically
+shared and will change to the user's home directory within the container
+instead.  See also @code{--user}.
+
 @item --expose=@var{source}[=@var{target}]
 For containers, expose the file system @var{source} from the host system
 as the read-only file system @var{target} within the container.  If
@@ -10296,6 +10307,7 @@ instance to support new system services.
 * Initial RAM Disk::            Linux-Libre bootstrapping.
 * Bootloader Configuration::    Configuring the boot loader.
 * Invoking guix system::        Instantiating a system configuration.
+* Invoking guix deploy::        Deploying a system configuration to a remote host.
 * Running Guix in a VM::        How to run Guix System in a virtual machine.
 * Defining Services::           Adding new service definitions.
 @end menu
@@ -25392,6 +25404,116 @@ example graph.
 
 @end table
 
+@node Invoking guix deploy
+@section Invoking @code{guix deploy}
+
+We've already seen @code{operating-system} declarations used to manage a
+machine's configuration locally.  Suppose you need to configure multiple
+machines, though---perhaps you're managing a service on the web that's
+comprised of several servers.  @command{guix deploy} enables you to use those
+same @code{operating-system} declarations to manage multiple remote hosts at
+once as a logical ``deployment''.
+
+@quotation Note
+The functionality described in this section is still under development
+and is subject to change.  Get in touch with us on
+@email{guix-devel@@gnu.org}!
+@end quotation
+
+@example
+guix deploy @var{file}
+@end example
+
+Such an invocation will deploy the machines that the code within @var{file}
+evaluates to.  As an example, @var{file} might contain a definition like this:
+
+@example
+;; This is a Guix deployment of a "bare bones" setup, with
+;; no X11 display server, to a machine with an SSH daemon
+;; listening on localhost:2222. A configuration such as this
+;; may be appropriate for virtual machine with ports
+;; forwarded to the host's loopback interface.
+
+(use-service-modules networking ssh)
+(use-package-modules bootloaders)
+
+(define %system
+  (operating-system
+   (host-name "gnu-deployed")
+   (timezone "Etc/UTC")
+   (bootloader (bootloader-configuration
+                (bootloader grub-bootloader)
+                (target "/dev/vda")
+                (terminal-outputs '(console))))
+   (file-systems (cons (file-system
+                        (mount-point "/")
+                        (device "/dev/vda1")
+                        (type "ext4"))
+                       %base-file-systems))
+   (services
+    (append (list (service dhcp-client-service-type)
+                  (service openssh-service-type
+                           (openssh-configuration
+                            (permit-root-login #t)
+                            (allow-empty-passwords? #t))))
+            %base-services))))
+
+(list (machine
+       (system %system)
+       (environment managed-host-environment-type)
+       (configuration (machine-ssh-configuration
+                       (host-name "localhost")
+                       (identity "./id_rsa")
+                       (port 2222)))))
+@end example
+
+The file should evaluate to a list of @var{machine} objects.  This example,
+upon being deployed, will create a new generation on the remote system
+realizing the @code{operating-system} declaration @var{%system}.
+@var{environment} and @var{configuration} specify how the machine should be
+provisioned---that is, how the computing resources should be created and
+managed.  The above example does not create any resources, as a
+@code{'managed-host} is a machine that is already running the Guix system and
+available over the network.  This is a particularly simple case; a more
+complex deployment may involve, for example, starting virtual machines through
+a Virtual Private Server (VPS) provider.  In such a case, a different
+@var{environment} type would be used.
+
+@deftp {Data Type} machine
+This is the data type representing a single machine in a heterogeneous Guix
+deployment.
+
+@table @asis
+@item @code{system}
+The object of the operating system configuration to deploy.
+
+@item @code{environment}
+An @code{environment-type} describing how the machine should be provisioned.
+At the moment, the only supported value is
+@code{managed-host-environment-type}.
+
+@item @code{configuration} (default: @code{#f})
+An object describing the configuration for the machine's @code{environment}.
+If the @code{environment} has a default configuration, @code{#f} maybe used.
+If @code{#f} is used for an environment with no default configuration,
+however, an error will be thrown.
+@end table
+@end deftp
+
+@deftp {Data Type} machine-ssh-configuration
+This is the data type representing the SSH client parameters for a machine
+with an @code{environment} of @code{managed-host-environment-type}.
+
+@table @asis
+@item @code{host-name}
+@item @code{port} (default: @code{22})
+@item @code{user} (default: @code{"root"})
+@item @code{identity} (default: @code{#f})
+If specified, the path to the SSH private key to use to authenticate with the
+remote host.
+@end table
+@end deftp
+
 @node Running Guix in a VM
 @section Running Guix in a Virtual Machine