Skip to content

Add NixOS support, CHANGLOG and other changes#17

Open
phodina wants to merge 98 commits intotinythings:masterfrom
phodina:fixes
Open

Add NixOS support, CHANGLOG and other changes#17
phodina wants to merge 98 commits intotinythings:masterfrom
phodina:fixes

Conversation

@phodina
Copy link
Collaborator

@phodina phodina commented Jan 25, 2026

@isbm thanks for this project, here's small MR with demo ;-)

  • add mp4 of rendered asciinema showing the booting
  • Nix flake support for building packages
    (support for aarch64-linux and x86_64-linux platforms)
  • GitHub workflow for building Nix packages across multiple platforms
  • Add support for overlayfs to support read-only rootfs
  • Handle missing kernel modules gracefuly in runtime
  • Add kernel config validation
  • Add arguments to specify and validate the filesystem
    and block device for rootfs during creation
  • Support block devices using also labels
  • Add Nix definitions for u-boot and latest stable kernel
  • Add support to run qemu-system-aarch64
  • Add example minimal Nixos system to boot

@isbm
Copy link
Member

isbm commented Jan 25, 2026

@phodina whoa! Awesome work. Now I owe you to ditch Ubuntu and go to Nix. 😛

If you would present that at https://fosdem.org/2026/schedule/track/nix-and-nixos/ then I would merge that as is. 😆 Otherwise, seems not everything is through: would you please double-check actions? I am not sure aarch64/darwin will do here...

Also, please make check && make fix so Clippy is happy (insanity check test) — seems if you make fix that, it should just do automatically. Also please ensure you are compiling with the latest/greatest Rust.

P.S. Absolutely cool!

@isbm isbm requested a review from Ichmed January 25, 2026 00:24
@isbm
Copy link
Member

isbm commented Jan 25, 2026

@Ichmed could you take a second look, please?

@phodina
Copy link
Collaborator Author

phodina commented Jan 25, 2026

Also, please make check && make fix so Clippy is happy (insanity check test) — seems if you make fix that, it should just do automatically. Also please ensure you are compiling with the latest/greatest Rust.

Sure will run the Clippy check to pass. Regarding the Darwin, i do own a Mac Mini M1 machine to test but it runs Asahi Linux :D
The CI seems to keep the nixbld users as an artifact as running it in non-daemon mode is no longer supported. So will probably drop this, if anyone is interested can look into that.

I intend to use it mainly for Mobile Nixos (surprise :) mobile-nixos/mobile-nixos#853 and also later for embedded systems.

The pull request stalls as the initramfs there uses Ruby. It offers a lot of features but having embedded background I appreciate the effort but IMHO don't thing Ruby is good choice.

Mostly I'm used to busybox+shell scripts style initramfs but for some time I thought about single binary init system also written in Rust. So thanks for bootstrapping the effort!

Also noticed OpenSUSE on your profile, what's you affiliation?

@isbm
Copy link
Member

isbm commented Jan 25, 2026

Sure will run the Clippy check to pass.

Yes! Please rebase on master and then make check.

So will probably drop this, if anyone is interested can look into that.

Yes, I was about to suggest that. Let's just drop that for now.

I intend to use it mainly for Mobile Nixos (surprise :) mobile-nixos/mobile-nixos#853 and also later for embedded systems.

❤️!

The pull request stalls as the initramfs there uses Ruby. It offers a lot of features but having embedded background I appreciate the effort but IMHO don't thing Ruby is good choice.

"Embedded system" and "lots of features"? An embedded system must have only what it must use. Basically, you should have no /bin/ls because why would you need that, if you do know your system? Busybox is actually "too much" and you probably want to compile it only with a clinic minimum applets that it gives you a bit oxygen to live and that's all.

Mostly I'm used to busybox+shell scripts style initramfs but for some time I thought about single binary init system also written in Rust. So thanks for bootstrapping the effort!
Also noticed OpenSUSE on your profile, what's you affiliation?

10 years worked there making SLES. Actually microhop was made exactly for this: ditch that enormously "Yuuge!" initramfs of their distro (it has systemd — yes, it does, — and probably a SIEMENS dishwasher drivers too, because why wouldn't they?). So I could just boot their literally unbootable distro on my old Rpi. Microhop was also made to boot systems as fast as they can be booted.

Feel free to add stuff to it. 😉

@isbm
Copy link
Member

isbm commented Jan 25, 2026

@phodina BTW, there is also a very good reason why we don't update embedded systems with the packages: they introduce config drift and then you risk bricking your device. There are some distros on the market with pkgs, but this is a very tricky/risky business.

I am not entirely sure NixOS is a good idea for the embedded in general, as it looks to be overlybloated, but trying? — why not... Maybe it is a good idea, I still need to explore that. RedHat's OS Tree is actually a right thing to do, but it is also way too bloated at the moment. Canonocal's Ubuntu Core is a good idea too, but the implementation is catastrophically bad.

So the best of best for now I would suggest this: https://elbe-rfs.org/new_site/index.html
(yes, they do need microhop!)

Petr Hodina added 2 commits January 26, 2026 01:38
We are interested in machine architecture and want to get:

```
$ uname -m
aarch64

$ uname -m
x86_64
```

Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
@phodina
Copy link
Collaborator Author

phodina commented Jan 26, 2026

Yes! Please rebase on master and then make check.

Done ;-)

Dropped support for Darwin, WSL2 not tested but normally packages build there in nix work.

"Embedded system" and "lots of features"? An embedded system must have only what it must use. Basically, you should have no /bin/ls because why would you need that, if you do know your system? Busybox is actually "too much" and you probably want to compile it only with a clinic minimum applets that it gives you a bit oxygen to live and that's all.

Totally agree with you on the just boot the system as fast as possible. It should not be swiss knife nor have there kitchen sink otherwise it's prone to failure or worse attack vector.

However, I do understand the need to have some features. The mobile phones are locked down and the bootloaders can't be changed.

So the idea with mobile nixos is to have u-boot chainloaded by the abl usually the lk into memory. This build also will bear any non upstreamable patches so the Linux kernel could be fully mainline (one day :) and along the initramfs will be packed in Android boot image.

Now back to features. I also don't like the feature creep but there are some that should be implemented in the initramfs. Definitely the LUKS unlock. Which on phone requires the framebuffer passed by Android bootloader and the touchscreen.

Sure the u-boot could unlock the LUKS partition but the issue is the key input. Storing it in the Android boot image renders the encrypted storage useless. So it has to be stored somewhere else or passed as input from user.

Both options require drivers or components currently not present in u-boot. Porting them from the kernel for different phones is not fun and IMHO overkill.

So better to draw keyboard and text input in the initramfs for the LUKS key.

In similar fashion if we would be able to store the key in the TrustZone we could use the tee-supplicant (or the proprietary qseecom on Qualcomm :P) which requires userspace service and kernel driver.

As an alternative NFC with some security token e.g. Yubikey could be also used. That would also require the NFC driver and daemon.

So even though I agree with the minimal and fast boot approach there are some valid usecases where it will require more functionality which could be gated using the rust features.

Other stuff like which slot to boot can be handled by the u-boot.

Also I'm aware that the initramfs, kernel, bootloader are risky parts to update. In embedded systems and Android there are usually slots - A and B. So if the company does due diligence on the Q&A of the OTA updates the device should not be bricked. Ideally it should not be updated frequently in the field.

I am not entirely sure NixOS is a good idea for the embedded in general, as it looks to be overlybloated, but trying? — why not... Maybe it is a good idea, I still need to explore that. RedHat's OS Tree is actually a right thing to do, but it is also way too bloated at the moment. Canonocal's Ubuntu Core is a good idea too, but the implementation is catastrophically bad.

Build mostly in the past systems either through buildroot, OpenWrt or Yocto. Since it was custom hardware and SoC which was far better supported in the vendor SDK there was no intention to reduce the size and time of the build (what a waste of resources).

Well I like Yocto, but then for each device you build custom image, which if you are a bigger company and don't care about the updates for the product is guess fine.

But for normal system I'd either go with Debian based system or NixOS. Sure it's not targeted for that but the descriptive language, remote builders and also certain immutability with generations has an edge (at least for me).

So specifically on phones it would allow me and others to try the latest features on next kernel and if it breaks just reboot and pick older generation that works.

The first devices, that were initially called embedded Linux, had about 4MiB flash and around 16MiB of RAM. With these constrains in mind people started to hack a root file system for their devices. If they had bad luck you had to start with building a cross toolchain first.
I do remember the routers with these kinds of hardware resources. And I'd like to also limit the resources needed to boot and run the system. Also with the RAM prices it might pursue more vendors to do the same :)

The reason I asked about the OpenSUSE affiliation is that with David Heidlberg we are trying to get the Linux next kernel running on mobile phones and SUSE in Prague helps us by providing spaces for hackadays. Big thanks to @lkocman for making this happen!

@isbm
Copy link
Member

isbm commented Jan 26, 2026

Funny I demoed Microhop booting a SLES in 2024 at OpenSUSE Con. I also tried last year to show something at DevConf.cz in Brno, but RedHat, like Microsoft, is overly obsessed with AI at the moment, so let's wait when they fail and go back to normal.

Well, this is a big difference between "embedded system" and "general distro" which SUSE is making traditionally. You are NOT supposed to pull out a disk with an embedded system, plug it elsewhere and boot. But you ARE supposed to do that with a generic system. That's why adding even a braille driver in SUSE's case is the right thing to do. This is also why Microhop does not have that auto/update to kernel swappings, because by definition you are supposed to do all that routine fully manually: put a new kernel, pick your modules, reconstruct initrd, put all that together, bake an image and only then push the update.

That's why I was experimenting with bootr: another project that is working like RedHat's bootable containers, except very tiny and very small. So the idea is to push image updates over an existing system, just like you do with the containers. I stopped that because my focus now is elsewhere and I have only 24 hours and two arms. 😆

While writing this: there's still one forgotten-and-unused import. Typically make fix does the trick for you automagically.

P.S. @lkocman see you in Nue/Z-Bau at next OpenSUSE Con! 😛

@phodina
Copy link
Collaborator Author

phodina commented Jan 26, 2026

While writing this: there's still one forgotten-and-unused import. Typically make fix does the trick for you automagically.

@isbm sorry missed the flags in actions so the warning that turned into error slipped through my fingers

That's why I was experimenting with bootr: another project that is working like RedHat's bootable containers, except very tiny and very small. So the idea is to push image updates over an existing system, just like you do with the containers. I stopped that because my focus now is elsewhere and I have only 24 hours and two arms

Good to know there are still great humans around and not just bots creating more boilerplate work :D

@phodina
Copy link
Collaborator Author

phodina commented Jan 26, 2026

The only thing missing is support to copy over firmware files as these are needed on the sdm845 to boot the adreno GPU. Have a crude way to add those but will refactor that.

Otherwise would be cool to present this on FOSDEM booth. It will be more about the Mobile Nixos + other stuff but I think a bumble init system also deserves mention. What do you think? @isbm

Funny enough you can't pull the whole firmware to the boot.img as just the modem is almost 2x big as the partition itself :D

@isbm
Copy link
Member

isbm commented Jan 27, 2026

Otherwise would be cool to present this on FOSDEM booth.

Well, I think it is too late. 😢 But in any case, if you go to FOSDEM in just four days — I will be there too.

@isbm
Copy link
Member

isbm commented Jan 27, 2026

@phodina OK, looks good. Anything else from your side to this PR or more improvements coming in different PRs 😛 ?

@isbm isbm requested a review from Copilot January 27, 2026 13:39
@isbm isbm added documentation Improvements or additions to documentation enhancement New feature or request labels Jan 27, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Nix/NixOS tooling and a demo boot flow, plus runtime enhancements for mounting and kernel/initramfs generation (overlayfs support, cmdline-based root selection, and kernel config validation).

Changes:

  • Add overlayfs support and mount flag handling (incl. read-only root scenarios).
  • Add kernel cmdline parsing + improved device resolution (UUID/label/path) and more tolerant module loading.
  • Add Nix flake packaging, NixOS demo components (kernel/u-boot/rootfs/initramfs), and a GitHub Actions workflow to build Nix packages.

Reviewed changes

Copilot reviewed 25 out of 28 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
syslib/src/fs.rs Adds mount-with-flags helper and overlayfs detection/mount support.
syslib/src/blk.rs Expands block device probing to include raw devices (not only partitions).
src/microhop.rs Adds mount mode support, cmdline-based root selection, and UUID/label device resolution.
src/main.rs Integrates overlayfs boot flow and pivots into overlay root when configured.
src/kmodprobe.rs Makes missing kernel modules a handled runtime condition (logs + returns).
src/cmdline.rs New cmdline parser for /proc/cmdline to support root=, rootfstype=, rootflags=.
rustfmt.toml Updates rustfmt configuration key for function parameter layout.
profile/src/cfg.rs Extends config schema with an overlayfs section and accessors.
nixos/u-boot.nix Adds Nix derivation to build u-boot for QEMU aarch64.
nixos/nixos-rootfs.nix Adds a minimal Nix-built squashfs rootfs for the demo boot flow.
nixos/microhop-config.nix Provides a microhop.conf for the QEMU demo (overlayfs + squashfs intent).
nixos/kernel.nix Adds a Nix-built kernel with an embedded config tailored for the demo.
nixos/initramfs-microgen.nix Builds an initramfs via microgen new with kernel-config validation inputs.
nixos/example-system.nix Adds an example NixOS system configuration intended for testing microhop.
microgen/src/rdpack.rs Makes initramfs packer create output directory before writing the archive.
microgen/src/rdgen.rs Allows initramfs generation without kernel modules (monolithic kernels).
microgen/src/main.rs Adds kernel config validation flow and new info listing commands.
microgen/src/kconfig_validator.rs New kernel .config validator with filesystem/block-device support lists.
microgen/src/clidef.rs Extends CLI flags for validation and supported-feature listing.
flake.nix Adds flake packaging for microhop/microgen and demo QEMU boot app for aarch64.
flake.lock Pins Nix inputs for reproducible builds.
etc/microhop.conf Updates sample config to document UUID/label specs and overlayfs configuration.
README.md Documents Nix build usage and links to changelog; references demo video.
Makefile Adjusts architecture detection to use uname -m.
CHANGELOG.md Introduces a changelog documenting new Nix/overlayfs/validation features.
.gitignore Ignores Nix result/ output.
.github/workflows/build.yml Adds CI workflow to build Nix packages across multiple platforms and publish releases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@phodina
Copy link
Collaborator Author

phodina commented Jan 27, 2026

@phodina OK, looks good. Anything else from your side to this PR or more improvements coming in different PRs 😛 ?

Added the last missing piece, adding the firmware files.

I went the way to specify file with records SRC:DST and specifying the base of the firmware in config file to limit the misuse of copying the files.

Well, I think it is too late. 😢 But in any case, if you go to FOSDEM in just four days — I will be there too.

Will be nice to see you there in person.

I meant only to mention it uses microhop as the initramfs and mention it on a flyer to the NixOS phones :)

@isbm
Copy link
Member

isbm commented Jan 27, 2026

@phodina seems like The System ™ isn't completely happy and seems some of these points are quite valid. Could you please take a look?

@phodina
Copy link
Collaborator Author

phodina commented Jan 27, 2026

@isbm sure will look into it tomorrow :)

Petr Hodina added 5 commits January 28, 2026 16:56
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Petr Hodina added 13 commits February 5, 2026 16:24
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
@phodina
Copy link
Collaborator Author

phodina commented Feb 5, 2026

Added some more quality of life features and fixes to boot on mobile devices (as they can corrupt the rootfs :)

[pethod@nixos:~/nixos/microhop]$ ./result/bin/microgen help
microgen - utility for generating microhop-based initramfs
Build-time features: fsck,nixos    <--- pack only what's needed by gated features

Usage: microgen [COMMAND]

Commands:
  info      Information about current system
  analyse   Analyse current system and generate a profile from it
  validate  Validate microhop.conf configuration file
  new       Create a new initramfs from a specified profile
  help      Print this message or the help of the given subcommand(s)

Options:
  -v, --version  Show version of Microhop
  -h, --help     Print help

[pethod@nixos:~/nixos/microhop]$ ./result/bin/microgen -v
Version: 0.2.1 (commit: 871035fcd4df67b359c1ef73b53a2ac138699368) <--- build commit ID

Also in runtime:

[    0.400588][    T0][Microhop] I: Welcome to the Microhop 0.2.1!
[    0.405751][    T0][Microhop] D: Init program: /nix/store/44k60k5x65xc3nxfaqim5rvw523fw5jv-systemd-258.3/lib/systemd/systemd
[    0.407219][    T0][Microhop] D: No cmdline parameters to mask
[    0.408378][    T0][Microhop] D: Disk device: /dev/vda, fs type: ext4, mountpoint: "/", mode: rw
[    0.408795][    T0][Microhop] D: Kernel modules:
[    0.409108][    T0][Microhop] I: Microhop build info:
[    0.409348][    T0][Microhop] I:   Git commit: 07f28aa1fdda7f53466ba15f92816571773d219e
[    0.409569][    T0][Microhop] I:   Features: fsck,nixos
[    0.409816][    T0][Microhop] D: Configuration metadata:
[    0.410055][    T0][Microhop] D:   Git commit: 07f28aa1fdda7f53466ba15f92816571773d219e
[    0.410371][    T0][Microhop] D:   Generated at: 2026-02-05 15:38:27 +00:00

@isbm I'd say now it's ready for review as it allows the boot to systemd.

@phodina
Copy link
Collaborator Author

phodina commented Feb 5, 2026

Also will have to modify the non nix scripts:

error: microhop
  --> microgen/src/rdgen.rs:18:40
   |
18 | const MICROHOP: &[u8] = include_bytes!(env!("MICROHOP_BINARY_PATH", "microhop"));
   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: e2fsck
  --> microgen/src/rdgen.rs:22:38
   |
22 | const E2FSCK: &[u8] = include_bytes!(env!("E2FSCK_BINARY_PATH", "e2fsck"));
   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

@isbm
Copy link
Member

isbm commented Feb 5, 2026

@phodina but let's just don't overdo that. The PR became very big and generic. 😉 Let's finish this one, and then let's add more stuff separately.

@phodina
Copy link
Collaborator Author

phodina commented Feb 6, 2026

@isbm the main issue and reason is that I do get system booting with these changes on real device mainly Google Pixel 3 as it has serial line ;-)

However, it boots only once or if there is no issue with system shutdown. If I hold combination of reset buttons the rootfs gets corrupted and on boot the mount just refuses to touch the filesystem until the corruption is fixed.

[    6.391207][    T6][Microhop] E: Failed to mount /sysroot (/dev/sda21): Failed to mount ext4 on /dev/sda21 as /sysroot: EUCLEAN: Structure needs cleaning
[    6.420297][    T6][Microhop] E: e2fsck reported operational error (exit code 12)

So I belive this is the last missing piece to get it to a working state.

I tried to use build the e2fsprogs statically and embed them to the binary. It works but the tools don't have stable API and some wrappers/crates need to be used. Also the work the standalone binaries (fsck, etc.) has to be replicated. Well would be another nice PR maybe in a distant future ...

So the other approach is to build the tools statically embed it to microgen and place them during generation of the initramfs to /bin. Which is the current approach, but it might need more than single binary.

To overcome the issue with damaged ext4 I will probably switch to a squashfs rootfs and mount RAM based overlayfs. I will loose the contents on each reboot but it will allow me to fine tune the Nixos install for time being.

@isbm
Copy link
Member

isbm commented Feb 6, 2026

@phodina well it is all fine, just ensure you're not pushing more features into one PR than it is needed for your current step. You're welcome to add more stuff, but let's just keep that under control, so we aren't losing/breaking things that already working.

@isbm
Copy link
Member

isbm commented Feb 6, 2026

@phodina checks are failing, could you please take a look?

@phodina
Copy link
Collaborator Author

phodina commented Feb 6, 2026

@isbm it's comes down to the binaries, microhop env variable is easy. Harder is the e2fsck. Not sure how to embed that if we don't build it in Rust :/

One solution would be to download the artifact but then it comes to the trust. They are available:
https://github.com/vk496/static-binaries

Or build it first in Nix and embed that artifact.

Temporary solution until that's decided is to remove the "fsck" from the default features.

#17 (comment)

@phodina
Copy link
Collaborator Author

phodina commented Feb 6, 2026

I added the package to fork of mobile Nixos. Tracked in this branch:

https://github.com/phodina/mobile-nixos-next/tree/microhop

It just pulls the Rust source code and builds it. Does not depend on any Nix code in the microhop repository. FIY the code there is not Flake based so would probably not be accepted :)

It depends on you if you wish to keep the Nix source code here.

The advantage of the Nix is to build the whole bootable system without solving dependencies on every distro so my idea was to have system tests to run.

@isbm
Copy link
Member

isbm commented Feb 7, 2026

One solution would be to download the artifact but then it comes to the trust. They are available: https://github.com/vk496/static-binaries

Yes, I am in favour of it. Because it is solely for the testing/preview purposes, thus we can just include that static stuff "as is". For redistribution/packaging — that's the job of packagers how to distribute that properly (e.g. they could grab that stuff themselves and compile it elsewhere separately).

Thoughts?

@phodina
Copy link
Collaborator Author

phodina commented Feb 7, 2026

@isbm agree on that.

Here's if you agree the default/test binaries. Otherwise any distro can choose their own static binaries by setting correctly the env variables.

https://github.com/phodina/static-tools.

@phodina
Copy link
Collaborator Author

phodina commented Feb 7, 2026

Now it will fetch the static binaries and setup the env vars :)

@isbm
Copy link
Member

isbm commented Feb 7, 2026

Yeah, static binaries aren't any good idea to distribute it, but for development and testing like this — perfectly foin. Now, seems you forgot to make check it. 😉

@phodina
Copy link
Collaborator Author

phodina commented Feb 10, 2026

@isbm refactored most of the environment variables code, previously was in Nix shell so make check would not fail for me.

So tested as well on Fedora and cherry-picked 2 commits that will benefit anyone.
#18

Also simplified the Nix devShell since most of the logic is in the packages already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants