liminix

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

tutorial.rst (12937B)


      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 You may want to read and inwardly digest the Develoment Manual section
    142 :ref:`serial` when you start working with Liminix on real hardware. You
    143 won't *need* serial access for this example, assuming it works, but it
    144 allows you
    145 to see the boot monitor and kernel messages, and to login directly to
    146 the device if for some reason it doesn't bring its network up.
    147 
    148 Now we can build Liminix. Although we could use the same example
    149 configuration as we did for Qemu, you might not want to plug a DHCP
    150 server into your working LAN because it will compete with the real
    151 DHCP service. So we're going to use a different configuration with a
    152 DHCP client: this is :file:`examples/hello-from-mt300.nix`
    153 
    154 It's instructive to compare the two configurations:
    155 
    156 .. code-block:: console
    157 
    158     diff -u examples/hello-from-qemu.nix examples/hello-from-mt300.nix
    159 
    160 You'll see a new ``boot.tftp`` stanza which you can ignore,
    161 ``services.dns`` has been removed, and the static IP address allocation
    162 has been replaced by a ``dhcp.client`` service.
    163 
    164 .. code-block:: console
    165 
    166     nix-build -I liminix-config=./examples/hello-from-mt300.nix \
    167      --arg device "import ./devices/gl-mt300a" -A outputs.default
    168 
    169 .. tip:: The first time you run this it may take several hours.
    170          Again? Yes, even if you ran the previous example. Qemu is
    171          set up as a big-endian system whereas the MediaTek SoC
    172          on this device is little-endian - so it requires building
    173          all of the dependencies including an entirely different
    174          MIPS gcc and library toolchain to the other one.
    175 
    176 This time in :file:`result/` you will see a bunch of files. Most of
    177 them you can ignore for the moment, but :file:`result/firmware.bin` is
    178 the firmware image you can flash.
    179 
    180 
    181 Flashing
    182 ========
    183 
    184 Again, there are a number of different ways you could do this: using
    185 TFTP with a serial cable, through the stock firmware's web UI, or
    186 using the `vendor's "debrick" process
    187 <https://docs.gl-inet.com/router/en/3/tutorials/debrick/>`_. The last
    188 of these options has a lot to recommend it for a first attempt:
    189 
    190 * it works no matter what firmware is currently installed
    191 
    192 * it doesn't require plugging a router into the same network as your
    193   build system and potentially messing up your actual upstream
    194 
    195 * no need to open the device and add cables
    196 
    197 You can read detailed instructions on the vendor site, but the short version is:
    198 
    199 1. turn the device off
    200 2. connect it by ethernet cable to a computer
    201 3. configure the computer to have static ip address 192.168.1.10
    202 4. while holding down the Reset button, turn the device on
    203 5. after about five seconds you can release the Reset button
    204 6. visit http://192.168.1.1/ using a web browser on the connected computer
    205 7. click on "Browse" and choose :file:`result/firmware.bin`
    206 8. click on "Update firmware"
    207 9. wait a minute or so while it updates.
    208 
    209 There's no feedback from the web interface when the flashing is
    210 finished, but what should happen is that the router reboots and
    211 starts running Liminix. Now you need to figure out what address it got
    212 from DHCP - e.g. by checking the DHCP server logs, or maybe by pinging
    213 ``hello.lan`` or something. Once you've found it on the
    214 network you can ping it and ssh to it just like you did the Qemu
    215 example, but this time for real.
    216 
    217 .. warning:: Do not leave the default root password in place on any
    218              device exposed to the internet!  Although it has no
    219              writable storage and no default route, a motivated attacker
    220 	     with some imagination could probably still do something
    221 	     awful using it.
    222 
    223 Congratulations Part II! You have installed your first Liminix system on actual hardware - albeit that it *still* has no practical use.
    224 
    225 Exercise for the reader: change the default password by editing
    226 :file:`examples/hello-from-mt300.nix`, and then create and upload a
    227 new image that has it set to something less hopeless.
    228 
    229 Routing
    230 *******
    231 
    232 The third example :file:`examples/demo.nix` is a fully-functional home
    233 "WiFi router" - although you will have to edit it a bit before it will
    234 actually work for you. Copy :file:`examples/demo.nix` to
    235 :file:`my-router.nix` (or other name of your choice) and open it in
    236 your favourite text editor. Everywhere that the text :code:`EDIT`
    237 appears is either a place you probably want to change or a place you
    238 almost certainly need to change.
    239 
    240 There's a lot going on in this configuration:
    241 
    242 * it provides a wireless access point using the :code:`hostapd`
    243   service: in this stanza you can change the ssid, the channel,
    244   the passphrase etc.
    245 
    246 * the wireless lan and wired lan are bridged together with the
    247   :code:`bridge` service, so that your wired and wireless clients appear
    248   to be on the same network.
    249 
    250 .. tip:: If you were using a hardware device that provides both 2.4GHz
    251 	  and 5GHz wifi, you'd probably find that it has two wireless
    252 	  devices (often called wlan0 and wlan1). In Liminix we handle
    253 	  this by running two :code:`hostapd` services, and adding
    254 	  both of them to the network bridge along with the wired lan.
    255 	  (You can see an example in :file:`examples/rotuer.nix`)
    256 
    257 * we use the combination DNS and DHCP daemon provided by the
    258   :code:`dnsmasq` service, which you can configure
    259 
    260 * the upstream network is "PPP over Ethernet", provided by the
    261   :code:`pppoe` service. Assuming that your ISP uses this standard,
    262   they will have provided you with a PPP username and password
    263   (sometimes this will be listed as "PAP" or "CHAP") which you can edit
    264   into the configuration
    265 
    266 * this example supports the new [#ipv6]_ Internet Protocol v6
    267   as well as traditional IPv4. Configuring IPv6 seems to
    268   vary from one ISP to the next: this example expects them
    269   to be providing IP address allocation and "prefix delegation"
    270   using DHCP6.
    271 
    272 Build it using the same method as the previous example
    273 
    274 
    275 .. code-block:: console
    276 
    277     nix-build -I liminix-config=./my-router.nix \
    278      --arg device "import ./devices/gl-mt300a" -A outputs.default
    279 
    280 and then you can flash it to the device.
    281 
    282 
    283 Bonus: in-place updates
    284 =======================
    285 
    286 This configuration uses a writable filesystem (see the line
    287 :code:`rootfsType = "jffs2"`), which means that once you've flashed it
    288 for the first time, you can make further updates over SSH onto the
    289 running router. To try this, make a small change (I'd suggest changing
    290 the hostname) and then run
    291 
    292 .. code-block:: console
    293 
    294     nix-shell --run "liminix-rebuild root@address-of-the-device  -I liminix-config=./my-router.nix --arg device "import ./devices/gl-ar750""
    295 
    296 (This requires the device to be network-accessible from your build
    297 machine, which for a test/demo system might involve a second network
    298 device in your build system - USB ethernet adapters are cheap - or
    299 a bit of messing around unplugging cables.)
    300 
    301 For more information about :code:`liminix-rebuild`, see the manual section :ref:`admin:Rebuilding the system`.
    302 
    303 
    304 Final thoughts
    305 **************
    306 
    307 * These are demonstration configs for pedagogical purposes. If you'd
    308   like to see some more realistic uses of Liminix,
    309   :file:`examples/rotuer,arhcive,extneder.nix` are based on some
    310   actual real hosts in my home network.
    311 
    312 * The technique used here for flashing was chosen mostly because it
    313   doesn't need much infrastructure/tooling, but it is a bit of a faff
    314   (requires physical access, vendor specific). There are slicker ways
    315   to do it that need a bit more setup - we'll talk about that later as
    316   well.
    317 
    318 
    319 
    320 .. rubric:: Footnotes
    321 
    322 .. [#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