A completely open source laptop by MNT Research GmbH. Its motherboard is built to accept custom system-on-module boards that allow upgrading the device without replacing everything else. It also uses standard 18650-form battery cells instead of pouches, and has a mechanical keyboard using low-profile Choc switches. Optionally comes with a trackball (my own preference) instead of a trackpad.
Notably there is no lid switch, no webcam, and no microphone. MNT Research does sell an open source webcam as well, which was developed after the release of the Reform.
Rather thick, with a solid aluminum chassis. There is currently a smaller (but no thinner) "Pocket" variant available, and a thinner "Next" variant in the works.
I've been using one as my primary computing device for a couple years now. If you're the tinkering type, they can be quite fun.
I wasn't getting good wifi reception in some parts of my house initially, so I replaced the stock antenna with a pair of 8dBi wifi antennas, and designed 3D-printed rabbit ear-style mounts for them.
After I had a kid, he wound up tearing one of the ears clean off, along with the antenna panel, so I designed low profile antenna mounts that fit under the keyboard ledge, which is what I've been using to this day.
Both were designed in OpenSCAD, and the source for the mods is up on Codeberg.
I've tried out a number of configurations for this laptop. Recently I had the notion of being able to have OpenBSD, 9front, and Debian booting from different SD cards, like game cartridges, a very common configuration and one for which the MNT Reform is uniquely suited, but with all differences from the stock OSes (plus my own personal files) kept on an NVMe, with having to split it up into different partitions (since resizing partitions without LVM2 support would be difficult) and with seperate folders for each OS' files, and for the personal files I hoped to share across all three. So I've set up the NVMe in my laptop with an ext4 partition and LUKS encryption, which all three OSes appear to support to some degree. So far, I've only got Debian set up this way. 9front will pose a particular challenge, as I'm running the RK3588 module and there is not yet support for it; I'm hoping to use 9front's support for the Reform's iMX8MQ module as a starting point to port it.
After flashing the official stock image to an SD card and booting into it, I wrote a script to decrypt the NVMe during the initramfs stage of booting:
#!/bin/sh tries=0 maxtries=3 while [ ! -e /dev/mapper/reform_crypt ]; do if [ "$tries" = "$maxtries" ]; then echo "Couldn't decrypt root partition. Launching emergency shell." exit 1 fi cryptsetup open /dev/nvme0n1p1 reform_crypt tries="$(expr $tries + 1)" done exit 0
I placed the script above at /etc/initramfs-tools/scripts/init-premount/mount-crypt and set the executable bit with chmod. Then I ran sudo update-initramfs -c -k all
to generate a new initramfs containing that script. (sudo update-initramfs -u
probably would have worked just as well, but I did what I did.)
I updated the fstab on the SD card to mount the NVMe at /ssd
on the SD card, and to mount all the drives with the noatime
option set in order to reduce writes:
LABEL=reformsdroot / auto noatime,errors=remount-ro 0 1 LABEL=reformsdboot /boot auto noatime,errors=remount-ro 0 1 /dev/mapper/reform_crypt /ssd auto noatime,errors=remount-ro 0 1
I wrote an fstab config for the filesystem overlays at /etc/overlayfstab
:
overlay /etc overlay defaults,x-systemd.requires=/ssd,lowerdir=/etc,upperdir=/ssd/overlays/debian/upper/etc,workdir=/ssd/overlays/debian/working/etc 0 0 overlay /var overlay defaults,x-systemd.requires=/ssd,lowerdir=/var,upperdir=/ssd/overlays/debian/upper/var,workdir=/ssd/overlays/debian/working/var 0 0 overlay /usr overlay defaults,x-systemd.requires=/ssd,lowerdir=/usr,upperdir=/ssd/overlays/debian/upper/usr,workdir=/ssd/overlays/debian/working/usr 0 0 overlay /home overlay defaults,x-systemd.requires=/ssd,lowerdir=/home,upperdir=/ssd/overlays/debian/upper/home,workdir=/ssd/overlays/debian/working/home 0 0 overlay /opt overlay defaults,x-systemd.requires=/ssd,lowerdir=/opt,upperdir=/ssd/overlays/debian/upper/opt,workdir=/ssd/overlays/debian/working/opt 0 0 overlay /srv overlay defaults,x-systemd.requires=/ssd,lowerdir=/srv,upperdir=/ssd/overlays/debian/upper/srv,workdir=/ssd/overlays/debian/working/srv 0 0
I'd tried to put these entries in /etc/fstab
originally, but it seemed as though the initramfs was doing a dry-run of /etc/fstab
on boot insteada of actually executing it, which meant the overlays always failed. Initially I'd thought it was an issue with entries being mounted out of order, which is how mount -F
behaves, but even removing all the overlayfs entries and dropping into a shell during the init-bottom
phase, the final phase before the script exec
s to the target filesystem's /sbin/init
, showed that it was only the root filesystem entry being mounted. My entry for the NVMe was being completely ignored. I tried writing a script for the init-bottom
phase that ran mount
on that file, but Debian uses BusyBox's mount
implementation which doesn't have a --target-prefix
flag, and using chroot
to mount devices relative to the root filesystem's mountpoint in the initramfs didn't seem to work either. So all overlayfstab
entries would have had to have all target paths prepended with the path at which the initramfs mounted the root filesystem, which would have felt like both a clumsy abstraction leak and a point of potential failure if that path were to ever change.
I wound up moving /sbin/init
on the SD card to /sbin/init.systemd
and creating a dpkg diversion to write all future /sbin/init
updates to /sbin/init.systemd
instead:
sudo dpkg-divert --divert /sbin/init.systemd --no-rename /sbin/init
I then wrote my own /sbin/init
and set its executable bit:
#!/bin/sh if [ -e /etc/overlayfstab ]; then mount /ssd mount --all --fstab /etc/overlayfstab fi exec /sbin/init.systemd
After this, I had a system where all future changes to anything under Debian's standard directories would be diverted to the NVMe under the paths I'd chosen.