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