Mauro Morales

software developer

Tag: Linux

  • How does a Raspberry Pi5 boot an image?

    When the Raspberry Pi5 is turned on, it will check on which device it is configured to boot. By default, this is the SD card, but you can change it to boot from an NVMe or USB drive while still fallback to SD. In my case, I’m using a USB SSD. Let’s take a look at how the disk is partitioned.

    For this article, I will be making reference to the Ubuntu 24.04 server image because its configuration is easier to understand than the Raspbian one, which uses implicit defaults. I mounted the image as a loop device, hence the dev/loop44 in the examples, but if you burned it to an SSD or SD card, you could get the same results from /dev/sdX and /dev/mmcblkY.

    root@zeno:~# lsblk -f /dev/loop44
    NAME       FSTYPE FSVER LABEL       UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
    loop44
    ├─loop44p1 vfat   FAT32 system-boot F526-0340                             419.3M    17% /media/mauro/system-boot
    └─loop44p2 ext4   1.0   writable    1305c13b-200a-49e8-8083-80cd01552617  781.9M    66% /media/mauro/writable

    From the labels, we can assume the system-boot partition will be the one booting the system, but how does the system know this is the case. From the documentation, I was able to find this:

    Partition numbers start at 1 and the MBR partitions are 1 to 4. Specifying partition 0 means boot from the default partition which is the first bootable FAT partition.

    Bootable partitions must be formatted as FAT12, FAT16 or FAT32 and contain a start.elf file (or config.txt file on Raspberry Pi 5) in order to be classed as be bootable by the bootloader

    Looking at the output of the previous command, only the system-boot partition has the right format, so let’s look into that one first.

    # ls -1 /media/mauro/system-boot/
    README
    bcm2710-rpi-2-b.dtb
    bcm2710-rpi-3-b-plus.dtb
    bcm2710-rpi-3-b.dtb
    bcm2710-rpi-cm3.dtb
    bcm2710-rpi-zero-2-w.dtb
    bcm2710-rpi-zero-2.dtb
    bcm2711-rpi-4-b.dtb
    bcm2711-rpi-400.dtb
    bcm2711-rpi-cm4.dtb
    bcm2711-rpi-cm4s.dtb
    bcm2712-rpi-5-b.dtb
    bcm2712-rpi-cm5-cm4io.dtb
    bcm2712-rpi-cm5-cm5io.dtb
    bcm2712d0-rpi-5-b.dtb
    boot.scr
    bootcode.bin
    cmdline.txt
    config.txt
    fixup.dat
    fixup4.dat
    fixup4cd.dat
    fixup4db.dat
    fixup4x.dat
    fixup_cd.dat
    fixup_db.dat
    fixup_x.dat
    hat_map.dtb
    initrd.img
    meta-data
    network-config
    overlays
    start.elf
    start4.elf
    start4cd.elf
    start4db.elf
    start4x.elf
    start_cd.elf
    start_db.elf
    start_x.elf
    uboot_rpi_3.bin
    uboot_rpi_4.bin
    uboot_rpi_arm64.bin
    user-data
    vmlinuz
    

    We can see that the expected config.txt. Let’s take a look at its contents.

    root@zeno:~# cat /media/mauro/system-boot/config.txt
    [all]
    kernel=vmlinuz
    cmdline=cmdline.txt
    initramfs initrd.img followkernel
    
    [pi4]
    max_framebuffers=2
    arm_boost=1
    
    [all]
    # Enable the audio output, I2C and SPI interfaces on the GPIO header. As these
    # parameters related to the base device-tree they must appear *before* any
    # other dtoverlay= specification
    dtparam=audio=on
    dtparam=i2c_arm=on
    dtparam=spi=on
    
    # Comment out the following line if the edges of the desktop appear outside
    # the edges of your display
    disable_overscan=1
    
    # If you have issues with audio, you may try uncommenting the following line
    # which forces the HDMI output into HDMI mode instead of DVI (which doesn't
    # support audio output)
    #hdmi_drive=2
    
    # Enable the serial pins
    enable_uart=1
    
    # Autoload overlays for any recognized cameras or displays that are attached
    # to the CSI/DSI ports. Please note this is for libcamera support, *not* for
    # the legacy camera stack
    camera_auto_detect=1
    display_auto_detect=1
    
    # Config settings specific to arm64
    arm_64bit=1
    dtoverlay=dwc2
    
    # Enable the KMS ("full" KMS) graphics overlay, leaving GPU memory as the
    # default (the kernel is in control of graphics memory with full KMS)
    dtoverlay=vc4-kms-v3d
    disable_fw_kms_setup=1
    
    [pi3+]
    # Use a smaller contiguous memory area, specifically on the 3A+ to avoid an
    # OOM oops on boot. The 3B+ is also affected by this section, but it shouldn't
    # cause any issues on that board
    dtoverlay=vc4-kms-v3d,cma-128
    
    [pi02]
    # The Zero 2W is another 512MB board which is occasionally affected by the same
    # OOM oops on boot.
    dtoverlay=vc4-kms-v3d,cma-128
    
    [all]
    
    [cm4]
    # Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into
    # such a board)
    dtoverlay=dwc2,dr_mode=host
    
    [all]

    I’m only interested in the first 5 lines.

    • [all]: makes reference to the board, or in this case, all boards
    • kernel: defines the kernel file to be read, in this case vmlinuz which was present on the files list
    • cmdline: defines the file with the cmdline used to boot the kernel. In this case cmdline.txt which is also there
    • initramfs: defines the initrd file to be loaded, in this case initrd.img, also there. And the followkernel stanza loads the initrd file in memory right after the kernel. Pay attention that this instruction, different from all others, doesn’t use the assignment =.

    Now we can take a look into cmdline.txt

    # cat /media/mauro/system-boot/cmdline.txt
    console=serial0,115200 multipath=off dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc
    

    This tells us that the root of the system is a partition with the label writable. This matches with the output of our very first command. Listing everything in writable we find:

    root@zeno:~# ls -1 /media/mauro/writable/
    bin
    bin.usr-is-merged
    boot
    dev
    etc
    home
    lib
    lib.usr-is-merged
    lost+found
    media
    mnt
    opt
    proc
    root
    run
    sbin
    sbin.usr-is-merged
    snap
    srv
    sys
    tmp
    usr
    var

    This looks like a common root directory for an Ubuntu system, so I will not go deeper into it.

    From a Linux installation on a PC the bootloader, but it turns out that for the Pi 5 it is already part of the EEPROM. So we can trust that it’s present and following the instructions from config.txt.

    An important part of this process is the Device Tree (.dtb files), which is also read by the bootloader. The Device Tree describes the hardware present on the board, ensuring that the kernel knows how to interact with all connected peripherals.

    To summarize it all. When the Raspberry Pi 5 powers up, the EEPROM will look for the first bootable partition, where it will read the config.txt file. The configuration file tells the bootloader which kernel, initramfs and cmdline params to load. After that, it’s the kernel’s job to decide how to proceed, in this case after the kernel and initramfs are running in memory, it will pivot to the system living in the writable partition. Last and out of the scope of this article, the init system will finalize the system.

    Raspbian

    Keep in mind that the Raspbian image doesn’t define all these details, since it uses defaults:

    The Raspberry Pi 5 firmware defaults to loading kernel_2712.img because this image contains optimizations specific to Raspberry Pi 5 (e.g. 16K page-size). If this file is not present, then the common 64-bit kernel (kernel8.img) will be loaded instead.

    And I assume that for initramfs, if not defined, it will also look within the directory and load either initramfs8 or initramfs_2712 by default since those files are present in the raspbian image.

  • A New Dawn for Secure Linux in Untrusted Environments

    Linux has become the default operating system for running web applications. However, like any system connected to the internet, it is exposed to remote attacks. While public cloud environments and private datacenters offer some security from physical tampering, edge computing presents unique challenges.

    For this article, an edge device refers to a headless computer system (without direct human interface) deployed in remote locations like coffee shops, gas stations, or warehouses.

    The Security Challenge at the Edge

    Contrary to popular belief, Linux systems lack certain critical security features found in Windows (Trusted Boot) and macOS (Startup Security). While Linux supports Secure Boot and full-disk encryption, these measures alone are insufficient for edge environments where devices are physically accessible to untrusted parties.

    The primary security goals for edge devices are:

    1. Preventing unauthorized access to data if the device is stolen.
    2. Ensuring the device does not boot if tampered with.

    Protecting Your Data with Encryption

    Encrypting the disk keeps your data safe when the device is powered off, addressing the first security goal. However, this protection is compromised if the device is tampered with, leading us to the second goal.

    Protecting Your Device from Tampering

    Understanding the Linux boot process is crucial for securing a device against tampering. Upon powering on, a modern computer runs the UEFI firmware, which hands control to a bootloader. The bootloader initiates the operating system, which then decrypts your data and starts your application.

    Secure Boot helps secure the initial stage by only allowing execution of digitally signed bootloaders. However, the problem lies in the next stage: most Linux distributions’ bootloaders do not verify the signatures of the Kernel or Initrd, nor do they measure the integrity of these components. This oversight allows potential tampering to go unnoticed.

    Measuring for Integrity

    Measuring involves calculating a hash for artifacts like the Linux Kernel. Any change in these artifacts alters the hash. Utilizing Trusted Platform Module (TPM) chips, we can establish a validation system that only proceeds with booting if the measurements match the expected values.

    Unified System Image (USI)

    One effective solution is creating a Unified System Image (USI). This combines the Kernel, cmdline parameters, and Initrd into a single, immutable image. By measuring this single image, we ensure the integrity of the entire system. There’s no need to encrypt this image since it contains no sensitive data, which resides in the encrypted area. The system configuration and valuable data remain secure, and the image is mounted read-only to prevent changes.

    For more detailed information on this process, refer to the UAPI Group’s page and Lennart Poettering’s article, “Brave New Trusted Boot World.”

    Kairos: Simplifying Trusted Boot

    Implementing a USI with Trusted Boot can be complex. Kairos aims to simplify this process. Visit our Trusted Boot Installation instructions to try it out, or delve into the Trusted Boot Architecture documentation for a deeper understanding of how Kairos enhances security in untrusted environments.

  • Remote Setup with EdgeVPN

    Last week I started using my old 13″ laptop and left the bulky 15″ workstation permanently at my desk. This setup gives me portability without loosing power when I’m connected to my home network. Today, I decided to configure EdgeVPN on both devices to also have this setup while on the road.

    EdgeVPN makes use of tokens, to connect nodes to a network. Since I have a Nextcloud server, which keeps files in sync on both of my laptops. I decided to put the EdgeVPN configuration file there and created a small script that reads from it to generate the token, and decide which IP to give to each device, based on their hostname:

    #!/bin/sh
    TOKEN=$(cat /path/to/Nextcloud/edgevpn-config.yaml | base64 -w0)
    IP=""
    if [ "$(hostname)" = "zeno" ]; then
    	IP="10.1.0.10"
    elif [ "$(hostname)" = "seneca" ]; then
    	IP="10.1.0.11"
    fi
    
    if [ "$IP" = "" ]; then
    	echo "IP not configured for $(hostname)"
    	exit 1
    else
    	echo Using IP: $IP
    fi
    edgevpn --token="$TOKEN" --address="$IP/24"
    

    Plus I created systemd services so I can make use of systemctl instead of having to remember the name of that shell script

    [Unit]
    Description=EdgeVPN
    Wants=network.target
    
    [Service]
    ExecStart=/path/to/start-edgevpn.sh
    
    [Install]
    WantedBy=multi-user.target

    On any of the nodes, I can start EdgeVPN’s web UI and list all connected nodes

  • It’s Kairos Time

    I’m excited to announce that I joined Spectro Cloud. I’ll be part of the team building Kairos, the immutable Linux meta-distribution for edge Kubernetes.

    Ok, a lot to unpack there, and I’m still very new to it, so I have numerous questions myself, but for my own sake, I will unwrap it:

    • Immutable Linux: there are some parts of the file system in the OS that are read-only. This means that if you want to add a package, or make some configuration change, you need to build a new image of the OS with the given changes. This is good for two reasons, on the one hand, it reduces the attack surface and, on the other, it helps to roll back to a specific version of the OS.
    • Meta-distribution: you can pick the flavor of the base Linux distribution on which Kairos is built. For what I can tell, openSUSE, Ubuntu and Alpine are already available, but others could follow up.
    • Edge computing: systems nowadays are being centralized in datacenters. While this can be beneficial in some cases, it can also be unpractical for others. When you have a system, running as far away from the datacenter, then you’re running at the edge of the network. For example, a computer in a parking lot, taking pictures of car plates and calculating the amount they need to be charged.
    • Kubernetes: it’s a platform to deploy applications. It was started by Google and became quite popular. It’s now part of the CNCF.

    For as long as I can remember, I’ve been a Linux enthusiast, so I’m very much looking forward to this experience.

  • Running MNT Reform OS on an NVME Disk

    Running the MNT Reform 2 from an SD card is not a bad solution. It’s similar to the way a Raspberry Pi is run. However, I wanted to free the SD card slot. In this post I describe the whole process from picking and buying an NVMe SSD, to installing and configuring it.

    But before I continue, I cannot take credit for this work, as it’s summarized in the Operating System on NVMe Without SD Card Post. I just wanted to give a little more detail into the steps I took, some of the mistakes I made, and add some information related to using an encrypted device.

    PARTS AND TOOLS NEEDED

    • 1 NVMe disk
    • 1 Phillips screw driver
    • 1 M2x4mm pan head screw (included in the DIY kit)

    PICKING AND BUYING AN NVME DISK

    I bought the one that MNT puts on the assembled version of the Reform 2, a 1Tb Transcend MTE220S because I didn’t want to risk it. I bought it from amazon.de (I tried to look for it in local businesses in Belgium but I couldn’t find it in the ones I was suggested to check). The price was around 125 Euro with shipping included.

    There’s a community page on Confirmed Working NVMe Drives that will hopefully hold more options in the future but so far, the Transcend disk seems like a very good one.

    INSTALLING THE DISK

    1. Disconnect the laptop from the power
    2. Discharge yourself by touching a metal surface or using a discharge bracelet
    3. Remove the acrylic bottom
    4. Remove the batteries
    5. Place the NVMe device in the M2 socket
    6. Secure it

    Do not close the laptop just yet. Turn it around, plug the power, turn it on and log in with your user. If the installation was successful, you should be able to see the device on the Disks application

    PARTITIONING, FORMATTING AND ENCRYPTING

    The next step is to create one or more partitions on the disk. I used Gnome Disks but it’s limited because you cannot do logical volumes, so you might want to install gparted or follow some tutorial for the CLI on how to achieve your specific partitioning setup.

    Note: If you are planning to use the whole disk without partitioning and only format the disk, using the Drive Options menu (3 dots at the top right corner). The script mounting your partition /sbin/reform-init might have issues because of the name of the device. At least that’s what I experienced the first time I did this process.

    My current setup is one encrypted partition with ext4 file system for root and one encrypted partition with ext4 file system for home (I will write about this in a next post). This means that I have to enter two passwords when booting. I’m planning to use a key in the future but if you don’t want to have to enter two passwords, read about logical volumes, or if you don’t want encryption at all then you don’t have to worry about this.

    1. Select the NVMe Disk
    2. Click on the + sign to create a new partition
    3. Select the size (needs to be at least the size of the SD card) and continue
    4. Give it a name e.g. “root”
    5. Select ext4 as your file system
    6. Select encryption with LUKS
    7. Press “Next”
    8. Add a pass phrase
    9. Press “Done”

    MIGRATE YOUR DATA

    To copy all your data in the SD card to the NVMe disk, we first need to unlock the disk. The first argument is the path to the device, so it needs to map whatever partition number you did in the previous step. The second argument is the name you want to give, so choose whatever you prefer.

    # cryptsetup luksOpen /dev/nvme0n1p1 crypt

    The unencrypted partition will be accessible on /dev/mapper/crypt

    We can use that path to run the reform-migrate script

    # reform-migrate /dev/mapper/crypt

    You can of course use Disks to unlock (open lock button) and mount (play button) the device instead. You will need to use the following command to move all your data.

    # rsync -axHAWXS --numeric-ids --info=progress2 / /media/USER/NAME

    Make sure to update the last argument to be the path to where you mounted the device.

    CONFIGURE BOOTING FROM NVME

    Booting from the NVMe disk is a two step process. We first need to configure the laptop to boot from the eMMC drive, and configure it to decrypt and mount the NVMe drive and init from it.

    Read more about this topic on Section 10.2 and 10.3 from the Operators Handbook.

    To switch the booting mechanism from the SD card to the inner eMMC module where the MNT Rescue disk resides, we need to flip a dip switch that resides underneath the heat sink.

    1. Shutdown and disconnect from power
    2. Remove the heat sink (be careful not to put the heat sink bottom flat on top of a surface since there’s some paste in it)
    3. Flip the dip switch on the bottom right (or top left depending on your perspective)
    4. Place the heat sink back in place

    We can now plug the power again and start the machine. When prompted for a logging you need to use “root” without a password since this is a completely different system from the one configured on the SD card.

    Now we need to download a newer version of U-boot in the rescue disk.

    # wget http://mntre.com/reform_md/flash-rescue-reform-init.bin

    U-boot is a mini OS used to boot Linux. For what I understand, this “newer” version is just the same version than is in the SD drive, so trying that instead of downloading a new one would also be an option.

    To flash the new U-boot we need to unlock the boot partition

    # echo 0 > /sys/class/block/mmcblk0boot0/force_ro

    And flash the binary

    # dd if=flash-rescue-reform-init.bin of=/dev/mmcblk0boot0 bs=1024 seek=33

    Now that we have this U-boot version in place, we can configure it to boot from the NVMe drive

    # reform-boot-config nvme

    This creates the file /reform-boot-medium with the word nvme in it. This is important because it’s used by reform-init.

    Note: One important thing to mention is that reform-init will only try to unlock and mount the encrypted partition under /dev/nvme0n1p1. With a different setup, one needs to go and modify this script to the right path. I stumbled across this problem on my first attempt but it was quite simple to debug and to help me understand better what’s going on under the hood.

    If everything went well you should be able to reboot the device and it will boot from the NVMe drive successfully. To finalize this process

    1. Shutdown the system and unplug it
    2. Put the batteries back in place (be careful with the polarity)
    3. Place the acrylic bottom
  • MNT Reform 2 DIY Kit Review

    The MNT Reform 2 laptop was made available on Crowd Supply in June 2020. This review is for the DIY kit version, and I’ll focus on the experience of supporting this project and its vendor through crowdsourcing, the process of putting the machine together, and my first impressions. I plan to share a second post with my thoughts on the experience of using the device as my computer for personal use.

    WHAT IS THE MNT REFORM 2 DIY KIT?

    The MNT Reform 2 is an Open Hardware Laptop. It comes with the Open Source operating system Debian Linux pre-installed. The DIY kit is just a disassembled version with a set of instructions on how to put it together.

    Nowadays laptops, and most electronic devices, lose their warranty if you try to tinker or repair them yourself. This laptop is one of the few that invite you to open them and make them your own. If you don’t believe me, take a pick through the bottom, made of see-through acrylic.

    THE CROWDFUNDING EXPERIENCE

    As soon as I saw the project on Crowd Supply, I got hooked and decided to support it. If I remember correctly, the project got fully funded reasonably quickly, and by the time the campaign finished, the number of backers tripled.

    The original shipping date was in December 2020, but I only received mine in April 2021. Four months of wait time can sound like a lot, but you need to consider that many producers and shipping companies had delays because of the COVID-19 pandemic. It would have been silly to expect that MNT wouldn’t be affected by this. On top of that, there are always delays in February because of the Chinese New Year. In the end, I think these delays ended up being positive because the MNT team used the time to make improvements to the keyboard and battery life. Lukas, MNT’s CEO, constantly shared about progress and any delays. It was pretty entertaining to follow up.

    PACKAGING

    In my opinion, most open projects don’t have a very appealing branding. MNT is the complete contrary. I’m glad they put the same passion on the packaging as they did on the product.

    PUTTING IT ALL TOGETHER

    The kit comes with a big printout that has on one side the instructions and on the other side pictures to give you a good idea of what is what. All you need is a cross screwdriver.

    While most steps were clear, there was one that I couldn’t figure out about the right way to plug the monitor. Fortunately, all I had to do is open the device again and invert the connector. In total, it took me between 2.5 and 3 hours to get the machine to boot. I swear I hadn’t had this much fun with a device in a very long time.

    FIRST IMPRESSIONS

    HARDWARE

    The laptop is gorgeous. When the lid is closed, it has this old-school Thinkpad vibe. The aluminum enclosing is pleasant to the touch and hardly picks any fingerprints. The MNT Reform 2 is quite thick if you compare it to today’s standards, which has its benefits, as you’ll see.

    On one side, there’s an HDMI port and three USB type-A ports. On the other side, a port for SD cards, a headphone jack, a network port, and one for the charger. I’m pleased about this because there’s nothing more annoying (and ugly if you ask me) than all those dongles coming out of a beautiful laptop.

    If you flip the computer, you can pick into the electronics thanks to the acrylic bottom. At first, I wasn’t very excited about this feature. It’s not that I don’t like it, but I think that after a while, it will get scratched, and then it won’t look as good. If there had been an option to get it with an aluminum bottom, I would have probably gotten that one. But I’m glad it is this way because it feels like an invitation to open and tinker with the device.

    If you open the lid, the first thing you notice is the trackball. It’s also possible to buy it with a trackpad, but I thought this would be more fun. Plus, I can always replace it if I don’t like it. So far, it’s been quite fun to use, but it will take some time to get used to it.

    Next, you might notice the small display on top of the keyboard. It’s helpful to get additional feedback, like battery percentage or the system’s status. The best part is that I can turn it off whenever I don’t need to look into it and avoid wasting precious energy.

    And of course, here’s where we find the mechanical keyboard. The keycaps feel very natural to the touch. The switches have excellent travel and sound amazing. However, this could be problematic when working with others, just like with any other mechanical keyboard, and there doesn’t seem to be a way to put dampers on these switches. I’m now used to Cherry MX Silent Red switches, and these are louder. Typing is very comfortable, except for the keys I press with my thumbs. The keyboard sits only slightly above the level of the palms rest, and because of the long travel, I feel like I’m constantly pushing the palms rest with the side of my thumb. In my opinion, raising the keyboard a little bit or making the inclination between the palm rest and the keyboard a bit more prominent would help.

    The layout of the keys is quite good. I love having a dedicated row for the function keys and a split space bar with two alt keys in between, which makes it more natural to reach them. Instead of a caps lock key, you get a control key, which I already configure on every other laptop. Details like these make this laptop feel like if it is tailor-made. I don’t particularly appreciate having the up arrow where the shift key is typically, but that’s where the open-source part comes very handy. I plan to flash a new layout into the keyboard, hopefully, one with multiple layers.

    The last tiny issue I will mention is that the printout of the quotes key was inverted, but MNT is already aware of this, so they might have it fixed for future machines. None of the issues I just mentioned are deal-breakers. This keyboard is by far the best I’ve used on a laptop.

    On the top panel are the display and two speakers. I like the side and top bezels, but the bottom one is a bit prominent and could use, in my opinion, some design or an MNT logo. I decided to put the sticker with the serial number there. The sturdiness of the top panel feels solid. I can move, and it doesn’t wobble. The hinges feel pretty sturdy like they can last forever. The display quality is excellent, but the speakers are a bit too quiet.

    Last but not least, I must mention the parts that are not present with the machine. The MNT Reform 2 doesn’t have a webcam or a microphone (I remember reading somewhere that this was by design thinking about privacy first, but I couldn’t find this information on the Crowd Supply or MNT Reform websites). The DIY kit doesn’t come with an SSD or a WiFi card, but these can be bought online or at a local store. Lukas shared the exact models that come with the assembled version.

    SOFTWARE

    The MNT Reform 2 initially boots into text mode, where you first have to follow a few steps to create your user account. The Operator’s Handbook explains every step in detail. Once you have an account, you can start the graphical interface. The three options that come pre-installed are Sway, Gnome 3, and Window Maker. But you can install any other that’s available for Debian.

    Sway is a tiling window manager, and you make heavy use of shortcuts to control it. It takes a little getting used to, but it feels suitable for this machine. It’s also the only one described in detail in the Operators Handbook. The device runs smoothly while using Sway. So far, my test consisted of watching a video with MPV, browsing the web, and editing text with Neovim simultaneously. The only case when the machine started struggling was when I tried to improve this text using Grammarly. Their JavaScript app doesn’t crash Firefox or Chromium, but it is painful. While I could blame the machine for not having enough power, I think the problem is we’ve gotten used to web-based technologies built without performance in mind. I find it ridiculous that you need a high-end laptop to run a web application. I tried to use my iPad (A-12 chip) for comparison, but Grammarly doesn’t even let you use the web application on Safari iOS, which proves my point.

    The Gnome 3 version that comes with the MNT Reform 2 has fewer components than the vanilla version. I guess that it helps reduce the load since full DEs are very power-hungry. I tried to do the same experiment as with Sway, but unfortunately, none of the videos played well on MPV, and in general, I did feel a bit of lag when using Gnome for some tasks.

    If you cannot live with a tiling window manager, I recommend you go with Window Maker. It doesn’t look very up-to-date, but after trying it for a while, I must say it performed very well. Like with Sway, there was no issue at all having my three designated applications running simultaneously.

    FINAL THOUGHTS

    I’ve been using the MNT Reform 2 to write these notes down for the past few days. Hearing the sound of the mechanical keyboard is music to my ears. Not having a network connection allows me to concentrate on what I want to say instead of being annoyed by multiple notifications. From time to time, I plug an ethernet cable to search for something online and eventually publish these words on my blog. The whole experience reminded me about times when computing felt a lot more personal, and our lives didn’t need to be online 24/7.

    Not only has it been fun to build and use this machine, but I’m also very excited about the idea of being able to service and extend its life. I love the concept of having a device that evolves according to my needs. Above all, it feels good to own a device not because it’s the latest and greatest but because its ethos resonates with my own. Only time will tell if the MNT Reform 2 will live up to its promises, but I’m certainly rooting for it.