liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

tutorial.rst (12985B)


      1 Tutorial
      2 ########
      3 
      4 Liminix is very configurable, which can make it initially quite
      5 daunting - especially if you're learning Nix or Linux or networking
      6 concepts at the same time. In this section we build some "worked
      7 example" Liminix images to introduce the concepts. If you follow the
      8 examples exactly, they should work. If you change things as you go
      9 along, they may work differently or not at all, but the experience
     10 should be educational either way.
     11 
     12 
     13 Requirements
     14 ************
     15 
     16 You will need a reasonably powerful computer running Nix.  Target
     17 devices for Liminix are unlikely to have the CPU power and disk space
     18 to be able to build it in situ, so the build process is based around
     19 "cross-compilation" from another computer. The build machine can be
     20 any reasonably powerful desktop/laptop/server PC running NixOS.
     21 Standalone Nixpkgs installations on other Linux distributions - or on
     22 MacOS, or even in a Docker container - also ought to work but are
     23 untested.
     24 
     25 
     26 Running in Qemu
     27 ***************
     28 
     29 You can try out Liminix without even having a router to play with.
     30 Clone the Liminix git repository and change into its directory
     31 
     32 
     33 .. code-block:: console
     34 
     35     git clone https://gti.telent.net/dan/liminix
     36     cd liminix
     37 
     38 Now build Liminix
     39 
     40 .. code-block:: console
     41 
     42     nix-build -I liminix-config=./examples/hello-from-qemu.nix \
     43      --arg device "import ./devices/qemu" -A outputs.default
     44 
     45 In this command ``liminix-config`` points to the desired software
     46 configuration (e.g. services, users, filesystem, secrets) and
     47 ``device`` describes the hardware (or emulated hardware) to run it on.
     48 ``outputs.default`` tells Liminix that we want the default image
     49 output for flashing to the device: for the Qemu "hardware" it's an
     50 alias for ``outputs.vmbuild``, which creates a directory containing a
     51 root filesystem image and a kernel.
     52 
     53 .. tip:: The first time you run this it may take several hours,
     54          because it builds all of the dependencies including a full
     55          MIPS gcc and library toolchain. Once those intermediate build
     56          products are in the nix store, subsequent builds will be much
     57          faster - practically instant, if nothing has changed.
     58 
     59 Now you can try it:
     60 
     61 .. code-block:: console
     62 
     63     ./result/run.sh
     64 
     65 This starts the Qemu emulator with a bunch of useful options, to run
     66 the Liminix configuration you just built.  It connects the emulated
     67 device's serial console and the `QEMU monitor
     68 <https://www.qemu.org/docs/master/system/monitor.html>`_ to
     69 stdin/stdout.
     70 
     71 You should now see Linux boot messages and after a few seconds be
     72 presented with a root shell prompt.  You can run commands to look at
     73 the filesystem, see what processes are running, view log messages (in
     74 :file:/run/uncaught-logs.current), etc. To kill the emulator, press ^P
     75 (Control P) then c to enter the "QEMU Monitor", then type ``quit`` at
     76 the ``(qemu)`` prompt.
     77 
     78 To see that it's running network services we need to connect to its
     79 emulated network. Start the machine again, if you had stopped it, and
     80 open up a second terminal on your build machine. We're going to run
     81 another virtual machine attached to the virtual network, which will
     82 request an IP address from our Liminix system and give you a shell you
     83 can run ssh from.
     84 
     85 We use `System Rescue <https://www.system-rescue.org/>`_ in tty
     86 mode (no graphical output) for this example, but if you have some
     87 other favourite Linux Live CD ISO - or, for that matter, any other OS
     88 image that QEMU can boot - adjust the command to suit.
     89 
     90 Download the System Rescue ISO:
     91 
     92 .. code-block:: console
     93 
     94     curl https://fastly-cdn.system-rescue.org/releases/10.01/systemrescue-10.01-amd64.iso -O
     95 
     96 and run it
     97 
     98 .. code-block:: console
     99 
    100     nix-shell -p qemu --run " \
    101     qemu-system-x86_64 \
    102 	-echr 16 \
    103 	-m 1024 \
    104 	-cdrom systemrescue-10.01-amd64.iso \
    105 	-netdev socket,mcast=230.0.0.1:1235,localaddr=127.0.0.1,id=lan \
    106 	-device virtio-net,disable-legacy=on,disable-modern=off,netdev=lan,mac=ba:ad:3d:ea:21:01 \
    107 	-display none -serial mon:stdio"
    108 
    109 System Rescue displays a boot menu at which you should select the
    110 "serial console" option, then after a few moments it boots to a root
    111 prompt. You can now try things out:
    112 
    113 * run :command:`ip a` and see that it's been allocated an IP address in the range 10.3.0.0/16.
    114 
    115 * run :command:`ping 10.3.0.1` to see that the Liminix VM responds
    116 
    117 * run :command:`ssh root@10.3.0.1` to try logging into it.
    118 
    119 Congratulations! You have installed your first Liminix system - albeit
    120 it has no practical use and it's not even real. The next step is to try
    121 running it on hardware.
    122 
    123 Installing on hardware
    124 **********************
    125 
    126 For the next example, we're going to install onto an actual hardware
    127 device.  These steps have been tested using a GL.iNet GL-MT300A, which
    128 has been chosen for the purpose because it's cheap and easy to
    129 unbrick if necessary.
    130 
    131 .. warning:: There is always a risk of rendering your device
    132 	     unbootable by flashing it with an image that doesn't
    133 	     work. The GL-MT300A has a builtin "debrick" procedure in
    134 	     the boot monitor and is also comparatively simple to
    135 	     attach serial cables to (soldering not required), so it
    136 	     is lower-risk than some devices.  Using some other
    137 	     Liminix-supported MIPS hardware device also *ought* to
    138 	     work here, but you accept the slightly greater bricking
    139 	     risk if it doesn't.
    140 
    141 See :doc:`hardware` for device support status.
    142 
    143 You may want to read and inwardly digest the Develoment Manual section
    144 :ref:`serial` when you start working with Liminix on real hardware. You
    145 won't *need* serial access for this example, assuming it works, but it
    146 allows you
    147 to see the boot monitor and kernel messages, and to login directly to
    148 the device if for some reason it doesn't bring its network up.
    149 
    150 Now we can build Liminix. Although we could use the same example
    151 configuration as we did for Qemu, you might not want to plug a DHCP
    152 server into your working LAN because it will compete with the real
    153 DHCP service. So we're going to use a different configuration with a
    154 DHCP client: this is :file:`examples/hello-from-mt300.nix`
    155 
    156 It's instructive to compare the two configurations:
    157 
    158 .. code-block:: console
    159 
    160     diff -u examples/hello-from-qemu.nix examples/hello-from-mt300.nix
    161 
    162 You'll see a new ``boot.tftp`` stanza which you can ignore,
    163 ``services.dns`` has been removed, and the static IP address allocation
    164 has been replaced by a ``dhcp.client`` service.
    165 
    166 .. code-block:: console
    167 
    168     nix-build -I liminix-config=./examples/hello-from-mt300.nix \
    169      --arg device "import ./devices/gl-mt300a" -A outputs.default
    170 
    171 .. tip:: The first time you run this it may take several hours.
    172          Again? Yes, even if you ran the previous example. Qemu is
    173          set up as a big-endian system whereas the MediaTek SoC
    174          on this device is little-endian - so it requires building
    175          all of the dependencies including an entirely different
    176          MIPS gcc and library toolchain to the other one.
    177 
    178 This time in :file:`result/` you will see a bunch of files. Most of
    179 them you can ignore for the moment, but :file:`result/firmware.bin` is
    180 the firmware image you can flash.
    181 
    182 
    183 Flashing
    184 ========
    185 
    186 Again, there are a number of different ways you could do this: using
    187 TFTP with a serial cable, through the stock firmware's web UI, or
    188 using the `vendor's "debrick" process
    189 <https://docs.gl-inet.com/router/en/3/tutorials/debrick/>`_. The last
    190 of these options has a lot to recommend it for a first attempt:
    191 
    192 * it works no matter what firmware is currently installed
    193 
    194 * it doesn't require plugging a router into the same network as your
    195   build system and potentially messing up your actual upstream
    196 
    197 * no need to open the device and add cables
    198 
    199 You can read detailed instructions on the vendor site, but the short version is:
    200 
    201 1. turn the device off
    202 2. connect it by ethernet cable to a computer
    203 3. configure the computer to have static ip address 192.168.1.10
    204 4. while holding down the Reset button, turn the device on
    205 5. after about five seconds you can release the Reset button
    206 6. visit http://192.168.1.1/ using a web browser on the connected computer
    207 7. click on "Browse" and choose :file:`result/firmware.bin`
    208 8. click on "Update firmware"
    209 9. wait a minute or so while it updates.
    210 
    211 There's no feedback from the web interface when the flashing is
    212 finished, but what should happen is that the router reboots and
    213 starts running Liminix. Now you need to figure out what address it got
    214 from DHCP - e.g. by checking the DHCP server logs, or maybe by pinging
    215 ``hello.lan`` or something. Once you've found it on the
    216 network you can ping it and ssh to it just like you did the Qemu
    217 example, but this time for real.
    218 
    219 .. warning:: Do not leave the default root password in place on any
    220              device exposed to the internet!  Although it has no
    221              writable storage and no default route, a motivated attacker
    222 	     with some imagination could probably still do something
    223 	     awful using it.
    224 
    225 Congratulations Part II! You have installed your first Liminix system on actual hardware - albeit that it *still* has no practical use.
    226 
    227 Exercise for the reader: change the default password by editing
    228 :file:`examples/hello-from-mt300.nix`, and then create and upload a
    229 new image that has it set to something less hopeless.
    230 
    231 Routing
    232 *******
    233 
    234 The third example :file:`examples/demo.nix` is a fully-functional home
    235 "WiFi router" - although you will have to edit it a bit before it will
    236 actually work for you. Copy :file:`examples/demo.nix` to
    237 :file:`my-router.nix` (or other name of your choice) and open it in
    238 your favourite text editor. Everywhere that the text :code:`EDIT`
    239 appears is either a place you probably want to change or a place you
    240 almost certainly need to change.
    241 
    242 There's a lot going on in this configuration:
    243 
    244 * it provides a wireless access point using the :code:`hostapd`
    245   service: in this stanza you can change the ssid, the channel,
    246   the passphrase etc.
    247 
    248 * the wireless lan and wired lan are bridged together with the
    249   :code:`bridge` service, so that your wired and wireless clients appear
    250   to be on the same network.
    251 
    252 .. tip:: If you were using a hardware device that provides both 2.4GHz
    253 	  and 5GHz wifi, you'd probably find that it has two wireless
    254 	  devices (often called wlan0 and wlan1). In Liminix we handle
    255 	  this by running two :code:`hostapd` services, and adding
    256 	  both of them to the network bridge along with the wired lan.
    257 	  (You can see an example in :file:`examples/rotuer.nix`)
    258 
    259 * we use the combination DNS and DHCP daemon provided by the
    260   :code:`dnsmasq` service, which you can configure
    261 
    262 * the upstream network is "PPP over Ethernet", provided by the
    263   :code:`pppoe` service. Assuming that your ISP uses this standard,
    264   they will have provided you with a PPP username and password
    265   (sometimes this will be listed as "PAP" or "CHAP") which you can edit
    266   into the configuration
    267 
    268 * this example supports the new [#ipv6]_ Internet Protocol v6
    269   as well as traditional IPv4. Configuring IPv6 seems to
    270   vary from one ISP to the next: this example expects them
    271   to be providing IP address allocation and "prefix delegation"
    272   using DHCP6.
    273 
    274 Build it using the same method as the previous example
    275 
    276 
    277 .. code-block:: console
    278 
    279     nix-build -I liminix-config=./my-router.nix \
    280      --arg device "import ./devices/gl-mt300a" -A outputs.default
    281 
    282 and then you can flash it to the device.
    283 
    284 
    285 Bonus: in-place updates
    286 =======================
    287 
    288 This configuration uses a writable filesystem (see the line
    289 :code:`rootfsType = "jffs2"`), which means that once you've flashed it
    290 for the first time, you can make further updates over SSH onto the
    291 running router. To try this, make a small change (I'd suggest changing
    292 the hostname) and then run
    293 
    294 .. code-block:: console
    295 
    296     nix-shell --run "liminix-rebuild root@address-of-the-device  -I liminix-config=./my-router.nix --arg device "import ./devices/gl-ar750""
    297 
    298 (This requires the device to be network-accessible from your build
    299 machine, which for a test/demo system might involve a second network
    300 device in your build system - USB ethernet adapters are cheap - or
    301 a bit of messing around unplugging cables.)
    302 
    303 For more information about :code:`liminix-rebuild`, see the manual section :ref:`admin:Rebuilding the system`.
    304 
    305 
    306 Final thoughts
    307 **************
    308 
    309 * These are demonstration configs for pedagogical purposes. If you'd
    310   like to see some more realistic uses of Liminix,
    311   :file:`examples/rotuer,arhcive,extneder.nix` are based on some
    312   actual real hosts in my home network.
    313 
    314 * The technique used here for flashing was chosen mostly because it
    315   doesn't need much infrastructure/tooling, but it is a bit of a faff
    316   (requires physical access, vendor specific). There are slicker ways
    317   to do it that need a bit more setup - we'll talk about that later as
    318   well.
    319 
    320 
    321 
    322 .. rubric:: Footnotes
    323 
    324 .. [#ipv6] `RFC1883 Internet Protocol, Version 6 <https://datatracker.ietf.org/doc/html/rfc1883>`_ was published in 1995, so only "new" when Bill Clinton was US President