diff --git a/doc/admin.rst b/doc/admin.rst
index 6bb159a8..ec8253a4 100644
--- a/doc/admin.rst
+++ b/doc/admin.rst
@@ -116,140 +116,6 @@ human-readable format, use :command:`s6-tai64nlocal`.
 
 
 
-Flashing and updating
-*********************
-
-
-
-Flashing from Liminix
-=====================
-
-The flash procedure from an existing Liminix-system has two steps.
-First we reboot the device (using "kexec") into an "ephemeral"
-RAM-based version of the new configuration, then when we're happy it
-works we can flash the image - and if it doesn't work we can reboot
-the device again and it will boot from the old image.
-
-
-Building the RAM-based image
-----------------------------
-
-To create the ephemeral image, build ``outputs.kexecboot`` instead of
-``outputs.default``.  This generates a directory containing the root
-filesystem image and kernel, along with an executable called `kexec`
-and a `boot.sh` script that runs it with appropriate arguments.
-
-For example
-
-.. code-block:: console
-
-   nix-build -I liminix-config=./examples/arhcive.nix \
-     --arg device "import ./devices/gl-ar750"
-     -A outputs.kexecboot && \
-     (tar chf - result | ssh root@the-device tar -C /run -xvf -)
-
-and then login to the device and run
-
-.. code-block:: console
-
-   cd /run/result
-   sh ./boot.sh .
-
-
-This will load the new kernel and map the root filesystem into a RAM
-disk, then start executing the new kernel. *This is effectively a
-reboot - be sure to close all open files and finish anything else
-you were doing first.*
-
-If the new system crashes or is rebooted, then the device will revert
-to the old configuration it finds in flash.
-
-
-Building the second (permanent) image
--------------------------------------
-
-While running in the kexecboot system, you can build the permanent
-image and copy it to the device with :command:`ssh`
-
-.. code-block:: console
-
-   build-machine$ nix-build -I liminix-config=./examples/arhcive.nix \
-     --arg device "import ./devices/gl-ar750"
-     -A outputs.default && \
-     (tar chf - result | ssh root@the-device tar -C /run -xvf -)
-
-   build-machine$ tar chf - result/firmware.bin | \
-    ssh root@the-device tar -C /run -xvf -
-
-Next you need to connect to the device and locate the "firmware"
-partition, which you can do with a combination of :command:`dmesg`
-output and the contents of :file:`/proc/mtd`
-
-.. code-block:: console
-
-   <5>[    0.469841] Creating 4 MTD partitions on "spi0.0":
-   <5>[    0.474837] 0x000000000000-0x000000040000 : "u-boot"
-   <5>[    0.480796] 0x000000040000-0x000000050000 : "u-boot-env"
-   <5>[    0.487056] 0x000000050000-0x000000060000 : "art"
-   <5>[    0.492753] 0x000000060000-0x000001000000 : "firmware"
-
-   # cat /proc/mtd
-   dev:    size   erasesize  name
-   mtd0: 00040000 00001000 "u-boot"
-   mtd1: 00010000 00001000 "u-boot-env"
-   mtd2: 00010000 00001000 "art"
-   mtd3: 00fa0000 00001000 "firmware"
-   mtd4: 002a0000 00001000 "kernel"
-   mtd5: 00d00000 00001000 "rootfs"
-
-Now run (in this example)
-
-.. code-block:: console
-
-   flashcp -v firmware.bin /dev/mtd3
-
-
-"I know my new image is good, can I skip the intermediate step?"
-----------------------------------------------------------------
-
-In addition to giving you a chance to see if the new image works, this
-two-step process ensures that you're not copying the new image over
-the top of the active root filesystem. Sometimes it works, but you
-will at least need physical access to the device to power-cycle it
-because it will be effectively frozen afterwards.
-
-
-Flashing from the boot monitor
-==============================
-
-If you are prepared to open the device and have a TTL serial adaptor
-of some kind to connect it to, you can probably use U-Boot and a TFTP
-server to download and flash the image.  This is quite
-hardware-specific, and sometimes involves soldering: please refer
-to :ref:`serial`.
-
-
-Flashing from OpenWrt
-=====================
-
-.. CAUTION:: Untested! A previous version of these instructions
-	     (without the -e flag) led to bricking the device
-	     when flashing a jffs2 image. If you are reading
-	     this message, nobody has yet reported on whether the
-	     new instructions are any better.
-
-If your device is running OpenWrt then it probably has the
-:command:`mtd` command installed. After transferring the image onto the
-device using e.g. :command:`ssh`,  you can run it as follows:
-
-.. code-block:: console
-
-   mtd -e -r write /tmp/firmware.bin firmware
-
-The options to this command are for "erase before writing" and "reboot
-after writing".
-
-For more information, please see the `OpenWrt manual <https://openwrt.org/docs/guide-user/installation/sysupgrade.cli>`_ which may also contain (hardware-dependent) instructions on how to flash an image using the vendor firmware - perhaps even from a web interface.
 
 Updating an installed system (JFFS2)
 ************************************
diff --git a/doc/development.rst b/doc/development.rst
index dca89c5b..c82373c2 100644
--- a/doc/development.rst
+++ b/doc/development.rst
@@ -88,64 +88,6 @@ time with configurations for RP-PPPoE and/or Accel PPP.`
 Hardware devices
 ****************
 
-.. _serial:
-
-U-Boot and serial shenanigans
-=============================
-
-Every device that we have so far encountered in Liminix uses `U-Boot,
-the "Universal Boot Loader" <https://docs.u-boot.org/en/latest/>`_ so
-it's worth knowing a bit about it. "Universal" is in this context a
-bit of a misnomer, though: encountering *mainline* U-Boot is very rare
-and often you'll find it is a fork from some version last updated
-in 2008. Upgrading U-Boot is more or less complicated depending on the
-device and is outside scope for Liminix.
-
-To speak to U-Boot on your device you'll usually need a serial
-connection to it.  This is device-specific. Usually it involves
-opening the box, locating the serial header pins (TX, RX and GND) and
-connecting a USB TTL converter to them.
-
-The Rolls Royce of USB/UART cables is the `FTDI cable
-<https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable>`_,
-but there are cheaper alternatives based on the PL2303 and CP2102 chipsets.  Or
-get creative and use the `UART GPIO pins <https://pinout.xyz/>`_ on a Raspberry Pi. Whatever you do, make sure
-that the voltages are compatible: if your device is 3.3V (this is
-typical but not universal), you don't want to be sending it 5v or
-(even worse) 12v.
-
-Run a terminal emulator such as Minicom on the computer at other end
-of the link. 115200 8N1 is the typical speed.
-
-.. NOTE::
-
-   TTL serial connections typically have no form of flow control and
-   so don't always like having massive chunks of text pasted into
-   them - and U-Boot may drop characters while it's busy. So don't
-   necessarily expect to copy-paste large chunks of text into the
-   terminal emulator and have it work just like that.
-
-   If using Minicom, you may find it helps to bring up the "Termimal
-   settings" dialog (C^A T), then configure "Newline tx delay" to
-   some small but non-zero value.
-
-When you turn the router on you should be greeted with some messages
-from U-Boot, followed by the instruction to hit some key to stop
-autoboot. Do this and you will get to the prompt. If you didn't see
-anything, the strong likelihood is that TX and RX are the wrong way
-around. If you see garbage, try a different speed.
-
-Interesting commands to try first in U-Boot are :command:`help` and
-:command:`printenv`.
-
-To do anything useful with U-Boot you will probably need a way to get
-large binary files onto the device, and the usual way to do this is by
-adding a network connection and using TFTP to download them. It's
-quite common that the device's U-Boot doesn't speak DHCP so it will
-need a static LAN address. You might also want to keep it away from
-your "real" LAN: see :ref:`bng` for some potentially useful tooling
-to use it on an isolated network.
-
 
 TFTP
 ====
diff --git a/doc/index.rst b/doc/index.rst
index 9632bf6f..d8199c85 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -8,6 +8,7 @@ Liminix
    intro
    tutorial
    configuration
+   installation
    admin
    development
    modules
diff --git a/doc/installation.rst b/doc/installation.rst
new file mode 100644
index 00000000..4aaa8ff3
--- /dev/null
+++ b/doc/installation.rst
@@ -0,0 +1,173 @@
+Installation
+############
+
+Hardware devices vary wildly in their affordances for installing new
+operating systems, so it should be no surprise that the Liminix
+installation procedure is hardware-dependent. This section contains
+generic instructions, but please refer to the documentation for your
+device to find whether and how well they apply.
+
+
+
+Flashing from the boot monitor (TFTP install)
+*********************************************
+
+If you are prepared to open the device and have a TTL serial adaptor
+of some kind to connect it to, you can probably use U-Boot and a TFTP
+server to download and flash the image.
+
+This is quite hardware-specific and may even involve soldering - see
+the documention for your device. However, it is in some ways the most
+"reliable" option: if you can see what's happening (or not happening)
+in early boot, the risk of "bricking" is substantially reduced and you
+have options for recovering if you misstep or flash a bad image.
+
+
+.. _serial:
+
+U-Boot and serial shenanigans
+=============================
+
+Every device that we have so far encountered in Liminix uses `U-Boot,
+the "Universal Boot Loader" <https://docs.u-boot.org/en/latest/>`_ so
+it's worth knowing a bit about it. "Universal" is in this context a
+bit of a misnomer, though: encountering *mainline* U-Boot is very rare
+and often you'll find it is a fork from some version last updated
+in 2008. Upgrading U-Boot is more or less complicated depending on the
+device and is outside scope for Liminix.
+
+To speak to U-Boot on your device you'll usually need a serial
+connection to it.  This typically involves opening the box, locating
+the serial header pins (TX, RX and GND) and connecting a USB TTL
+converter to them.
+
+The Rolls Royce of USB/UART cables is the `FTDI cable
+<https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable>`_,
+but there are cheaper alternatives based on the PL2303 and CP2102 chipsets -   or you could even 
+get creative and use the `UART GPIO pins <https://pinout.xyz/>`_ on a Raspberry Pi. Whatever you do, make sure
+that the voltages are compatible: if your device is 3.3V (this is
+typical but not universal), you don't want to be sending it 5v or
+(even worse) 12v.
+
+Run a terminal emulator such as Minicom on the computer at other end
+of the link. 115200 8N1 is the typical speed.
+
+.. NOTE::
+
+   TTL serial connections often have no flow control and
+   so don't always like having massive chunks of text pasted into
+   them - and U-Boot may drop characters while it's busy. So don't
+   do that.
+
+   If using Minicom, you may find it helps to bring up the "Termimal
+   settings" dialog (C^A T), then configure "Newline tx delay" to
+   some small but non-zero value.
+
+When you turn the router on you should be greeted with some messages
+from U-Boot, followed by the instruction to hit some key to stop
+autoboot. Do this and you will get to the prompt. If you didn't see
+anything, the strong likelihood is that TX and RX are the wrong way
+around. If you see garbage, try a different speed.
+
+Interesting commands to try first in U-Boot are :command:`help` and
+:command:`printenv`.
+
+You will also need to configure a TFTP server on a network that's
+accessible to the device: how you do that will vary according to which
+TFTP server you're using and so is out of scope for this document.
+
+
+
+Buildiing and installing the image
+==================================
+
+Follow the device-specific instructions for "TFTP install": usually,
+the steps are 
+
+* build the `outputs.mtdimage` output
+* copy :file:`result/firmware.bin` to your TFTP server
+* copy/paste the commands in :file:`result/flash.scr` one at a time into the U-Boot command line
+* reset the device
+
+You should now see messages from U-Boot, then from the Linux kernel
+and eventually a shell prompt.
+
+.. NOTE:: Before you reboot, check which networks the device is
+          plugged into, and disconnect as necessary. If you've just
+          installed a DHCP server or anything similar that responds to
+          broadcasts, you may not want it to do that on the network
+          that you temporarily connected it to for installing it.
+
+
+
+Flashing from OpenWrt
+*********************
+
+.. CAUTION:: Untested! A previous version of these instructions
+	     (without the -e flag) led to bricking the device
+	     when flashing a jffs2 image. If you are reading
+	     this message, nobody has yet reported on whether the
+	     new instructions are any better.
+
+If your device is running OpenWrt then it probably has the
+:command:`mtd` command installed. Build the `outputs.mtdimage` output
+(as you would for a TFTP install) and then transfer
+:file:`result/firmware.bin` onto the device using e.g.
+:command:`scp`. Now flash as follows:
+
+.. code-block:: console
+
+   mtd -e -r write /tmp/firmware.bin firmware
+
+The options to this command are for "erase before writing" and "reboot
+after writing".
+
+For more information, please see the `OpenWrt manual <https://openwrt.org/docs/guide-user/installation/sysupgrade.cli>`_ which may also contain (hardware-dependent) instructions on how to flash an image using the vendor firmware - perhaps even from a web interface.
+
+
+Flashing from Liminix
+*********************
+
+If the device is already running Liminix and has been configured with
+:command:`levitate`, you can use that to safely flash your new image.
+Refer to :ref:`levitate` for an explanation.
+
+If the device is running Liminix but doesn't have :command:`levitate`
+your options are more limited. You may attempt to use
+:command:`flashcp` but it doesn't always work: as it copies the new
+image over the top of the active root filesystem, surprise may ensue.
+Consider instead using a serial connection: you may need one anyway
+after trying flashcp if it corrupts the image.
+
+flashcp (not generally recommended)
+===================================
+
+Connect to the device and locate the "firmware" partition, which you
+can do with a combination of :command:`dmesg` output and the contents
+of :file:`/proc/mtd`
+
+.. code-block:: console
+
+   <5>[    0.469841] Creating 4 MTD partitions on "spi0.0":
+   <5>[    0.474837] 0x000000000000-0x000000040000 : "u-boot"
+   <5>[    0.480796] 0x000000040000-0x000000050000 : "u-boot-env"
+   <5>[    0.487056] 0x000000050000-0x000000060000 : "art"
+   <5>[    0.492753] 0x000000060000-0x000001000000 : "firmware"
+
+   # cat /proc/mtd
+   dev:    size   erasesize  name
+   mtd0: 00040000 00001000 "u-boot"
+   mtd1: 00010000 00001000 "u-boot-env"
+   mtd2: 00010000 00001000 "art"
+   mtd3: 00fa0000 00001000 "firmware"
+   mtd4: 002a0000 00001000 "kernel"
+   mtd5: 00d00000 00001000 "rootfs"
+
+Copy :file:`result/firmware.bin` to the device and now run (in this
+example)
+
+.. code-block:: console
+
+   flashcp -v firmware.bin /dev/mtd3
+
+