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