forked from dan/liminix
add example with real hardware
This commit is contained in:
parent
8600dfc8cf
commit
56261f77b0
129
doc/new.rst
129
doc/new.rst
|
@ -129,6 +129,135 @@ 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
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
{ config, pkgs, lib, ... } :
|
||||
let
|
||||
inherit (pkgs) serviceFns;
|
||||
svc = config.system.service;
|
||||
|
||||
in rec {
|
||||
imports = [
|
||||
../modules/network
|
||||
../modules/ssh
|
||||
../modules/vlan
|
||||
../modules/flashimage.nix
|
||||
];
|
||||
|
||||
boot.tftp = {
|
||||
# IP addresses to use in the boot monitor when flashing/ booting
|
||||
# over TFTP. If you are flashing using the stock firmware's Web UI
|
||||
# then these dummy values are fine
|
||||
ipaddr = "192.0.2.115"; # my address
|
||||
serverip = "192.0.2.5"; # build machine or other tftp server
|
||||
};
|
||||
|
||||
hostname = "hello";
|
||||
|
||||
services.dhcpc = svc.network.dhcp.client.build {
|
||||
interface = config.hardware.networkInterfaces.lan;
|
||||
|
||||
# don't start DHCP until the hostname is configured,
|
||||
# so it can identify itself to the DHCP server
|
||||
dependencies = [ config.services.hostname ];
|
||||
};
|
||||
|
||||
services.sshd = svc.ssh.build { };
|
||||
|
||||
users.root = {
|
||||
# the password is "secret". Use mkpasswd -m sha512crypt to
|
||||
# create this hashed password string
|
||||
passwd = "$6$y7WZ5hM6l5nriLmo$5AJlmzQZ6WA.7uBC7S8L4o19ESR28Dg25v64/vDvvCN01Ms9QoHeGByj8lGlJ4/b.dbwR9Hq2KXurSnLigt1W1";
|
||||
};
|
||||
|
||||
defaultProfile.packages = with pkgs; [
|
||||
figlet
|
||||
];
|
||||
}
|
Loading…
Reference in New Issue