liminix

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

commit f81aa54444486e5ba559a13e60939a0a1817c3e7
parent 56261f77b030172cf2aeab0b006b6be9212e79d2
Author: Daniel Barlow <dan@telent.net>
Date:   Sun, 17 Sep 2023 00:06:53 +0100

rename file

Diffstat:
Mdoc/index.rst | 2+-
Ddoc/new.rst | 282-------------------------------------------------------------------------------
Adoc/tutorial.rst | 257+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 258 insertions(+), 283 deletions(-)

diff --git a/doc/index.rst b/doc/index.rst @@ -5,7 +5,7 @@ Liminix :maxdepth: 3 :caption: Contents: - new + tutorial Indices and tables diff --git a/doc/new.rst b/doc/new.rst @@ -1,282 +0,0 @@ -Getting Started -############### - -Liminix is very configurable, which can make it initially quite -daunting, especially if you're learning Nix or Linux or networking -concepts at the same time. In this section we build some "worked -example" Liminix images to introduce the concepts. If you follow the -examples exactly, they should work. If you change things as you go -along, they may work differently or not at all, but the experience -should be educational either way. - - -.. warning:: The first example we will look at runs under emulation, - so there is no danger of bricking your hardware - device. For the second example you may (if you have - appropriate hardware and choose to do so) flash the - configuration onto an actual router. There is always a - risk of rendering the device unbootable when you do this, - and various ways to recover depending on what went wrong. - We'll write more about that at the appropriate point - - -Requirements -************ - -You will need a reasonably powerful computer running Nix. Target -devices for Liminix are unlikely to have the CPU power and disk space -to be able to build it in situ, so the build process is based around -"cross-compilation" from another computer. The build machine can be -any reasonably powerful desktop/laptop/server PC running NixOS. -Standalone Nixpkgs installations on other Linux distributions - or on -MacOS, or even in a Docker container - also ought to work but are -untested. - - -Running in Qemu -*************** - -You can try out Liminix without even having a router to play with. -Clone the Liminix git repository and change into its directory - - -.. code-block:: console - - git clone https://gti.telent.net/dan/liminix - cd liminix - -Now build Liminix - -.. code-block:: console - - nix-build -I liminix-config=./examples/hello-from-qemu.nix \ - --arg device "import ./devices/qemu" -A outputs.default - -In this command ``liminix-config`` points to the desired software -configuration (e.g. services, users, filesystem, secrets) and -``device`` describes the hardware (or emulated hardware) to run it on. -``outputs.default`` tells Liminix that we want the default image -output for flashing to the device: for the Qemu "hardware" it's an -alias for ``outputs.vmbuild``, which creates a directory containing a -root filesystem image and a kernel. - -.. tip:: The first time you run this it may take several hours, - because it builds all of the dependencies including a full - MIPS gcc and library toolchain. Once those intermediate build - products are in the nix store, subsequent builds will be much - faster - practically instant, if nothing has changed. - -Now you can try it: - -.. code-block:: console - - nix-shell --run "mips-vm ./result/vmlinux ./result/rootfs" - -This starts the Qemu emulator with a bunch of useful options, to run -the Liminix configuration you just built. It connects the emulated -device's serial console and the `QEMU monitor -<https://www.qemu.org/docs/master/system/monitor.html>`_ to -stdin/stdout. - -You should now see Linux boot messages and after a few seconds be -presented with a login prompt. You can login on the console as -``root`` (password is "secret") and poke around to see what processes are -running. To kill the emulator, press ^P (Control P) then c to enter the -"QEMU Monitor", then type ``quit`` at the ``(qemu)`` prompt. - -To see that it's running network services we need to connect to its -emulated network. Start the machine again, if you had stopped it, and -open up a second terminal on your build machine. We're going to run -another virtual machine attached to the virtual network, which will -request an IP address from our Liminix system and give you a shell you -can run ssh from. - -We use `System Rescue <https://www.system-rescue.org/>`_ in tty -mode (no graphical output) for this example, but if you have some -other favourite Linux Live CD ISO - or, for that matter, any other OS -image that QEMU can boot - adjust the command to suit. - -Download the System Rescue ISO: - -.. code-block:: console - - curl https://fastly-cdn.system-rescue.org/releases/10.01/systemrescue-10.01-amd64.iso -O - -and run it - -.. code-block:: console - - nix-shell -p qemu --run " \ - qemu-system-x86_64 \ - -echr 16 \ - -m 1024 \ - -cdrom systemrescue-10.01-amd64.iso \ - -netdev socket,mcast=230.0.0.1:1235,localaddr=127.0.0.1,id=lan \ - -device virtio-net,disable-legacy=on,disable-modern=off,netdev=lan,mac=ba:ad:3d:ea:21:01 \ - -display none -serial mon:stdio" - -System Rescue displays a boot menu at which you should select the -"serial console" option, then after a few moments it boots to a root -prompt. You can now try things out: - -* run :command:`ip a` and see that it's been allocated an IP address in the range 10.3.0.0/16. - -* run :command:`ping 10.3.0.1` to see that the Liminix VM responds - -* run :command:`ssh root@10.3.0.1` to try logging into it. - -Congratulations! You have installed your first Liminix system - albeit -it has no practical use and it's not even real. The next step is to try -running it on hardware. - -Installing on hardware -********************** - -For the next example, we're going to install onto an actual hardware -device. These steps have been tested using a GL-iNet GL-MT300A, which -has been chosen for the purpose because it's cheap and easy to -unbrick. Using some other Liminix-supported MIPS hardware device also -*ought* to work here, but you accept the slightly greater bricking -risk if it doesn't. - -You may want to acquire a `USB TTL serial cable -<https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable>`_ -when you start working with Liminix on real hardware. You -won't *need* it for this example, assuming it works, but it -allows you -to see the boot monitor and kernel messages, and to login directly to -the device if for some reason it doesn't bring its network up. You have options -here: the FTDI-based cables are the Rolls Royce of serial cables, -whereas the ones based on PL2303 and CP2102 chipsets are cheaper but -also fussier - or you could even get creative and use e.g. a -`Raspberry Pi <https://pinout.xyz/#>`_ or other SBC with a UART and -TX/RX/GND header pins. Make sure that the voltages are compatible: -this is a 3.3v device and you don't want to be sending it 5v or (even -worse) 12v. - -Now we can build Liminix. Although we could use the same example -configuration as we did for Qemu, you might not want to plug a DHCP -server into your working LAN because it will compete with the real -DHCP service. So we're going to use a different configuration with a -DHCP client: this is :file:`examples/hello-from-mt300.nix` - -It's instructive to compare the two configurations: - -.. code-block:: console - - diff -u examples/hello-from-qemu.nix examples/hello-from-mt300.nix - -You'll see a new ``boot.tftp`` stanza which you can ignore, -``services.dns`` has been removed, and the static IP address allocation -has been replaced by a ``dhcp.client`` service. - -.. code-block:: console - - nix-build -I liminix-config=./examples/hello-from-mt300.nix \ - --arg device "import ./devices/gl-mt300a" -A outputs.default - -.. tip:: The first time you run this it may take several hours. - Again? Yes, even if you ran the previous example. Qemu is - set up as a big-endian system whereas the MediaTek SoC - on this device is little-endian - so it requires building - all of the dependencies including an entirely different - MIPS gcc and library toolchain to the other one. - -This time in :file:`result/` you will see a bunch of files. Most of -them you can ignore for the moment, but :file:`result/firmware.bin` is -the firmware image you can flash. - - -Flashing -======== - -Again, there are a number of different ways you could do this: using -TFTP with a serial cable, through the stock firmware's web UI, or -using the `vendor's "debrick" process -<https://docs.gl-inet.com/router/en/3/tutorials/debrick/>`_. The last -of these options has a lot to recommend it for a first attempt: - -* it works no matter what firmware is currently installed - -* it doesn't require plugging a router into the same network as your - build system and potentially messing up your actual upstream - -* no need to open the device and add cables - -You can read detailed instructions on the vendor site, but the short version is: - -1. turn the device off -2. connect it by ethernet cable to a computer -3. configure the computer to have static ip address 192.168.1.10 -4. while holding down the Reset button, turn the device on -5. after about five seconds you can release the Reset button -6. visit http://192.168.1.1/ using a web browser on the connected computer -7. click on "Browse" and choose :file:`result/firmware.bin` -8. click on "Update firmware" -9. wait a minute or so while it updates. - -There's no feedback from the web interface when the flashing is -finished, but what should happen is that the router reboots and -starts running Liminix. Now you need to figure out what address it got -from DHCP - e.g. by checking the DHCP server logs, or maybe by pinging -``hello.lan`` or something. Once you've found it on the -network you can ping it and ssh to it just like you did the Qemu -example, but this time for real. - -.. warning:: Do not leave the default root password in place on any - device exposed to the internet! Although it has no - writable storage and no default route, a motivated attacker - with some imagination could probably still do something - awful using it. - -Congratulations Part II! You have installed your first Liminix system on -actual hardware - albeit that it *still* has no practical use. - -Exercise for the reader: change the default password by editing -:file:`examples/hello-from-mt300.nix`, and then create and upload a -new image that has it set to something less hopeless. - - -Final thoughts -************** - -* These are demonstration configs for pedagogical purposes. If you'd - like to see some more realistic uses of Liminix, - :file:`examples/rotuer,arhcive,extneder.nix` are based on some - actual real hosts in my home network. - -* These example images are not writable. Later we will explain how to - generate an image that can be changed after installation, and - even use :command:`liminix-rebuild` (analogous to :command:`nixos-rebuild`) - to keep it up to date. - -* The technique used here for flashing was chosen mostly because it - doesn't need much infrastructure/tooling, but it is a bit of a faff - (requires physical access, vendor specific). There are slicker ways - to do it that need a bit more setup - we'll talk about that later as - well. - - - - -- using modules - - - link to module reference - -- creating custom services - - - longrun or oneshot - - dependencies - - outputs - -- creating your own modules - -- hacking on Liminix itself - -- contributing - -- external links and resources - -- module reference - -- hardware device reference diff --git a/doc/tutorial.rst b/doc/tutorial.rst @@ -0,0 +1,257 @@ +Getting Started +############### + +Liminix is very configurable, which can make it initially quite +daunting, especially if you're learning Nix or Linux or networking +concepts at the same time. In this section we build some "worked +example" Liminix images to introduce the concepts. If you follow the +examples exactly, they should work. If you change things as you go +along, they may work differently or not at all, but the experience +should be educational either way. + + +.. warning:: The first example we will look at runs under emulation, + so there is no danger of bricking your hardware + device. For the second example you may (if you have + appropriate hardware and choose to do so) flash the + configuration onto an actual router. There is always a + risk of rendering the device unbootable when you do this, + and various ways to recover depending on what went wrong. + We'll write more about that at the appropriate point + + +Requirements +************ + +You will need a reasonably powerful computer running Nix. Target +devices for Liminix are unlikely to have the CPU power and disk space +to be able to build it in situ, so the build process is based around +"cross-compilation" from another computer. The build machine can be +any reasonably powerful desktop/laptop/server PC running NixOS. +Standalone Nixpkgs installations on other Linux distributions - or on +MacOS, or even in a Docker container - also ought to work but are +untested. + + +Running in Qemu +*************** + +You can try out Liminix without even having a router to play with. +Clone the Liminix git repository and change into its directory + + +.. code-block:: console + + git clone https://gti.telent.net/dan/liminix + cd liminix + +Now build Liminix + +.. code-block:: console + + nix-build -I liminix-config=./examples/hello-from-qemu.nix \ + --arg device "import ./devices/qemu" -A outputs.default + +In this command ``liminix-config`` points to the desired software +configuration (e.g. services, users, filesystem, secrets) and +``device`` describes the hardware (or emulated hardware) to run it on. +``outputs.default`` tells Liminix that we want the default image +output for flashing to the device: for the Qemu "hardware" it's an +alias for ``outputs.vmbuild``, which creates a directory containing a +root filesystem image and a kernel. + +.. tip:: The first time you run this it may take several hours, + because it builds all of the dependencies including a full + MIPS gcc and library toolchain. Once those intermediate build + products are in the nix store, subsequent builds will be much + faster - practically instant, if nothing has changed. + +Now you can try it: + +.. code-block:: console + + nix-shell --run "mips-vm ./result/vmlinux ./result/rootfs" + +This starts the Qemu emulator with a bunch of useful options, to run +the Liminix configuration you just built. It connects the emulated +device's serial console and the `QEMU monitor +<https://www.qemu.org/docs/master/system/monitor.html>`_ to +stdin/stdout. + +You should now see Linux boot messages and after a few seconds be +presented with a login prompt. You can login on the console as +``root`` (password is "secret") and poke around to see what processes are +running. To kill the emulator, press ^P (Control P) then c to enter the +"QEMU Monitor", then type ``quit`` at the ``(qemu)`` prompt. + +To see that it's running network services we need to connect to its +emulated network. Start the machine again, if you had stopped it, and +open up a second terminal on your build machine. We're going to run +another virtual machine attached to the virtual network, which will +request an IP address from our Liminix system and give you a shell you +can run ssh from. + +We use `System Rescue <https://www.system-rescue.org/>`_ in tty +mode (no graphical output) for this example, but if you have some +other favourite Linux Live CD ISO - or, for that matter, any other OS +image that QEMU can boot - adjust the command to suit. + +Download the System Rescue ISO: + +.. code-block:: console + + curl https://fastly-cdn.system-rescue.org/releases/10.01/systemrescue-10.01-amd64.iso -O + +and run it + +.. code-block:: console + + nix-shell -p qemu --run " \ + qemu-system-x86_64 \ + -echr 16 \ + -m 1024 \ + -cdrom systemrescue-10.01-amd64.iso \ + -netdev socket,mcast=230.0.0.1:1235,localaddr=127.0.0.1,id=lan \ + -device virtio-net,disable-legacy=on,disable-modern=off,netdev=lan,mac=ba:ad:3d:ea:21:01 \ + -display none -serial mon:stdio" + +System Rescue displays a boot menu at which you should select the +"serial console" option, then after a few moments it boots to a root +prompt. You can now try things out: + +* run :command:`ip a` and see that it's been allocated an IP address in the range 10.3.0.0/16. + +* run :command:`ping 10.3.0.1` to see that the Liminix VM responds + +* run :command:`ssh root@10.3.0.1` to try logging into it. + +Congratulations! You have installed your first Liminix system - albeit +it has no practical use and it's not even real. The next step is to try +running it on hardware. + +Installing on hardware +********************** + +For the next example, we're going to install onto an actual hardware +device. These steps have been tested using a GL-iNet GL-MT300A, which +has been chosen for the purpose because it's cheap and easy to +unbrick. Using some other Liminix-supported MIPS hardware device also +*ought* to work here, but you accept the slightly greater bricking +risk if it doesn't. + +You may want to acquire a `USB TTL serial cable +<https://cpc.farnell.com/ftdi/ttl-232r-rpi/cable-debug-ttl-232-usb-rpi/dp/SC12825?st=usb%20to%20uart%20cable>`_ +when you start working with Liminix on real hardware. You +won't *need* it for this example, assuming it works, but it +allows you +to see the boot monitor and kernel messages, and to login directly to +the device if for some reason it doesn't bring its network up. You have options +here: the FTDI-based cables are the Rolls Royce of serial cables, +whereas the ones based on PL2303 and CP2102 chipsets are cheaper but +also fussier - or you could even get creative and use e.g. a +`Raspberry Pi <https://pinout.xyz/#>`_ or other SBC with a UART and +TX/RX/GND header pins. Make sure that the voltages are compatible: +this is a 3.3v device and you don't want to be sending it 5v or (even +worse) 12v. + +Now we can build Liminix. Although we could use the same example +configuration as we did for Qemu, you might not want to plug a DHCP +server into your working LAN because it will compete with the real +DHCP service. So we're going to use a different configuration with a +DHCP client: this is :file:`examples/hello-from-mt300.nix` + +It's instructive to compare the two configurations: + +.. code-block:: console + + diff -u examples/hello-from-qemu.nix examples/hello-from-mt300.nix + +You'll see a new ``boot.tftp`` stanza which you can ignore, +``services.dns`` has been removed, and the static IP address allocation +has been replaced by a ``dhcp.client`` service. + +.. code-block:: console + + nix-build -I liminix-config=./examples/hello-from-mt300.nix \ + --arg device "import ./devices/gl-mt300a" -A outputs.default + +.. tip:: The first time you run this it may take several hours. + Again? Yes, even if you ran the previous example. Qemu is + set up as a big-endian system whereas the MediaTek SoC + on this device is little-endian - so it requires building + all of the dependencies including an entirely different + MIPS gcc and library toolchain to the other one. + +This time in :file:`result/` you will see a bunch of files. Most of +them you can ignore for the moment, but :file:`result/firmware.bin` is +the firmware image you can flash. + + +Flashing +======== + +Again, there are a number of different ways you could do this: using +TFTP with a serial cable, through the stock firmware's web UI, or +using the `vendor's "debrick" process +<https://docs.gl-inet.com/router/en/3/tutorials/debrick/>`_. The last +of these options has a lot to recommend it for a first attempt: + +* it works no matter what firmware is currently installed + +* it doesn't require plugging a router into the same network as your + build system and potentially messing up your actual upstream + +* no need to open the device and add cables + +You can read detailed instructions on the vendor site, but the short version is: + +1. turn the device off +2. connect it by ethernet cable to a computer +3. configure the computer to have static ip address 192.168.1.10 +4. while holding down the Reset button, turn the device on +5. after about five seconds you can release the Reset button +6. visit http://192.168.1.1/ using a web browser on the connected computer +7. click on "Browse" and choose :file:`result/firmware.bin` +8. click on "Update firmware" +9. wait a minute or so while it updates. + +There's no feedback from the web interface when the flashing is +finished, but what should happen is that the router reboots and +starts running Liminix. Now you need to figure out what address it got +from DHCP - e.g. by checking the DHCP server logs, or maybe by pinging +``hello.lan`` or something. Once you've found it on the +network you can ping it and ssh to it just like you did the Qemu +example, but this time for real. + +.. warning:: Do not leave the default root password in place on any + device exposed to the internet! Although it has no + writable storage and no default route, a motivated attacker + with some imagination could probably still do something + awful using it. + +Congratulations Part II! You have installed your first Liminix system on +actual hardware - albeit that it *still* has no practical use. + +Exercise for the reader: change the default password by editing +:file:`examples/hello-from-mt300.nix`, and then create and upload a +new image that has it set to something less hopeless. + + +Final thoughts +************** + +* These are demonstration configs for pedagogical purposes. If you'd + like to see some more realistic uses of Liminix, + :file:`examples/rotuer,arhcive,extneder.nix` are based on some + actual real hosts in my home network. + +* These example images are not writable. Later we will explain how to + generate an image that can be changed after installation, and + even use :command:`liminix-rebuild` (analogous to :command:`nixos-rebuild`) + to keep it up to date. + +* The technique used here for flashing was chosen mostly because it + doesn't need much infrastructure/tooling, but it is a bit of a faff + (requires physical access, vendor specific). There are slicker ways + to do it that need a bit more setup - we'll talk about that later as + well.