aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-05-08 17:11:22 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-05-09 12:23:55 -0700
commitb29195fe9f1a865ebbc6a9db3823c2b3f1d81d6c (patch)
tree5f040cd9017707dd4e21bb3d6c049a2927d2a847 /doc
parent9db6ca02489e88165cba102f1379f121cd37b817 (diff)
downloadconsfigurator-b29195fe9f1a865ebbc6a9db3823c2b3f1d81d6c.tar.gz
add a tutorial for building disk images
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'doc')
-rw-r--r--doc/index.rst1
-rw-r--r--doc/introduction.rst2
-rw-r--r--doc/tutorial/conventions.rst17
-rw-r--r--doc/tutorial/disk_image.rst117
4 files changed, 137 insertions, 0 deletions
diff --git a/doc/index.rst b/doc/index.rst
index 55c910c..680f406 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -7,6 +7,7 @@ Consfigurator user's manual
introduction
installation
+ tutorial/disk_image
connections
properties
hosts
diff --git a/doc/introduction.rst b/doc/introduction.rst
index 37bbd2a..47122d7 100644
--- a/doc/introduction.rst
+++ b/doc/introduction.rst
@@ -1,3 +1,5 @@
+.. _introduction:
+
Introduction
============
diff --git a/doc/tutorial/conventions.rst b/doc/tutorial/conventions.rst
new file mode 100644
index 0000000..753ae03
--- /dev/null
+++ b/doc/tutorial/conventions.rst
@@ -0,0 +1,17 @@
+Tutorial conventions
+--------------------
+
+In these tutorials we assume that you have a workstation called
+``laptop.silentflame.com`` where you run the root Lisp. We also assume that
+Consfigurator knows about your laptop, and that it has a host deployment
+specified, so that you can use ``HOSTDEPLOY-THESE`` to deploy properties to
+the laptop as root. For example,::
+
+ (defhost laptop.silentflame.com
+ (:deploy ((:sudo :as "spwhitton@melete.silentflame.com") :sbcl))
+ "Sean's laptop."
+ (os:debian-stable "bullseye" :amd64))
+
+We suppose that you've already set up sources of prerequisite data to provide
+sudo passwords and the like. See the :ref:`introduction<introduction>` if you
+haven't set this up yet.
diff --git a/doc/tutorial/disk_image.rst b/doc/tutorial/disk_image.rst
new file mode 100644
index 0000000..bad4c27
--- /dev/null
+++ b/doc/tutorial/disk_image.rst
@@ -0,0 +1,117 @@
+Tutorial: building disk images
+==============================
+
+In this tutorial we will show you what properties you need to use to build
+bootable disk images.
+
+.. include:: conventions.rst
+
+Consfiguration
+--------------
+
+Here is a minimal definition of the host for which we can build a disk image:::
+
+ (defhost test.silentflame.com ()
+ (os:debian-stable "bullseye" :amd64)
+ (disk:has-volumes
+ (physical-disk
+ :boots-with '(grub:grub :target "x86_64-efi" :force-extra-removable t)
+ (partitioned-volume
+ ((partition
+ :partition-typecode #xEF00
+ (fat32-filesystem :volume-size 512 :mount-point #P"/boot/efi"))
+ (partition
+ (ext4-filesystem :extra-space 400 :mount-point #P"/"))))))
+ (installer:bootloader-binaries-installed)
+ (apt:installed "linux-image-amd64"))
+
+- The ``DISK:HAS-VOLUMES`` property is like the ``OS:DEBIAN-STABLE`` property
+ in that both simply set hostattrs on the host -- they establish metadata to
+ which other properties may refer. In this case, we specify that the machine
+ has a single physical disk with two partitions, and that it boots with GRUB.
+ We also request that Consfigurator pass the ``--force-extra-removable`` flag
+ to grub-install(8), because that makes it a bit easier to test our image,
+ given how UEFI works.
+
+ We've requested 400M of free space on the root partition beyond whatever the
+ base system install takes up. For the EFI system partition we specify an
+ absolute size.
+
+- The ``INSTALLER:BOOTLOADER-BINARIES-INSTALLED`` property reads the metadata
+ established by ``DISK:HAS-VOLUMES`` and ensures that binaries like
+ grub-install(8) are available. In this case you could replace it with just
+ ``(apt:installed "grub-efi-amd64")``, but using this property avoids
+ repeating yourself.
+
+- Finally, building a bootable image requires installing a kernel.
+
+Building the image
+------------------
+
+What we've established so far is a definition of a host. But it does not yet
+make any sense to say ``(deploy :foo test.silentflame.com ...)`` because the
+host does not yet exist anywhere for us to connect to it. What we can now use
+is the ``DISK:RAW-IMAGE-BUILT-FOR`` property, which we can apply to a host
+which *does* already exist to build an image for our host which does not yet
+exist:::
+
+ CONSFIG> (hostdeploy-these laptop.silentflame.com
+ (disk:raw-image-built-for
+ nil test.silentflame.com "/home/spwhitton/tmp/test.img"))
+
+This property does the following on laptop.silentflame.com:
+
+1. Build a chroot with the root filesystem of test.silentflame.com, and apply
+ all its properties, such as installing the kernel and building the
+ initramfs.
+
+2. Transform the metadata set by ``DISK:HAS-VOLUMES`` such that the instance
+ of ``PHYSICAL-DISK`` is replaced with an instance of ``RAW-DISK-IMAGE``,
+ and then make, partition and mount the image file, using tools like
+ kpartx(8).
+
+3. Rsync the contents of the chroot into the mounted partitions.
+
+4. Update /etc/fstab so that it contains the UUIDs of the partitions.
+
+5. Install the bootloader(s), again as specified by ``DISK:HAS-VOLUMES``.
+
+Here we've described this procedurally, but the semantics of
+``DISK:RAW-IMAGE-BUILT-FOR`` are declarative, like all properties. You can
+add the property to the ``DEFHOST`` for your laptop and Consfigurator will
+just do whatever is needed to keep the chroot and the disk image up-to-date
+(though see the docstring for that property for some limitations).
+
+All of this is modular: take a look in ``src/property/disk.lisp`` to see how
+new volume types can be defined, and in ``src/property/grub.lisp`` and
+``src/property/u-boot.lisp`` to see how Consfigurator can be taught to install
+different bootloaders.
+
+Testing the image
+-----------------
+
+Here's a quick way to test what we've built:::
+
+ % sudo chown $USER tmp/test.img
+ % qemu-system-x86_64 -m 2G -drive file=tmp/test.img,format=raw \
+ -drive "if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE.fd"
+
+It should boot up but you probably won't get a login prompt, since the root
+account's password is locked and we debootstrapped a very minimal system.
+
+Uses for the disk image
+-----------------------
+
+You might upload this image to a cloud provider and boot up a minimal
+instance. Supposing we also added at least an sshd and our public key, we
+could then continue to add properties to the ``DEFHOST`` for
+test.silentflame.com and then apply them with SSH:::
+
+ CONSFIG> (deploy ((:ssh :user "root") :sbcl) test.silentflame.com)
+
+Another possibility is to dd the image out to a USB flash drive and then boot
+a physical machine from it.
+
+It should be straightforward to adapt the existing code to have Consfigurator
+install a bootable system to a physical volume rather than to a disk image,
+but the high level properties for this haven't been written yet.