NixOS on my phone?

It’s quickly becoming a reality! Look at the devices list to see if your device is already supported. Otherwise, read about the porting process to understand if you can get NixOS on your phone.

News Items

This update is the nineteenth in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

During the two months 11 pull requests were merged.

This report is not a report of flashy new features. Foundational work to make it possible to finish work on flashy new features had to be made.

Validated kernel configurations

One of the hardest tasks with doing a port, whether it’s your first or your tenth, is figuring out the kernel configuration options that needs to be set, and those that should not be set.

With the changes in #410, it is now entirely automated and part of both the normalization step, and the usual build steps.

It means that when you normalize a kernel configuration with the tooling, the options that are required to be set or unset are set or unset accordingly automatically for the developer. Since it is also validated at build time, it means that any changes in the configurations that has not been handled by the maintainer will cause an obvious build failure with appropriate error messages.

Hopefully this means that future ports are this much more trivial.

Rewritten early user interface bindings

While working on an upcoming feature requiring further use of the early user interface for Mobile NixOS, it was found that the FFI bindings for them were a dead-end.

These bindings worked seemingly well enough, but had issues. The more easily observable issue was the lack of proper ownership tracking for the FFI object, which meant that anything made through the mruby bindings needed to be tracked manually or else garbage collection would free up resources it shouldn’t have freed.

The workarounds seemed enough. They were not, when tested against more and more complex applications. Further causing issues, the FFI bindings were basically not debuggable. Whenever a crash happened, it crashed way too late to allow debugging the root cause of the issues.

With these issues in mind, I circled back to the approach tentatively used initially, and generated native code bindings for the library. But this time, with a slight twist. I already had a list of desired bindings with the FFI bindings. So I used the same API as the FFI bindings used. In the end, this rewrite needed some light correctness fixes outside of the bindings, but was almost entirely a drop-in replacement.

And this time, it can be debugged. I had to do so to figure out a few teething issues. Additionally, the untraceable segfaults I had with the new usage has simply vanished. It wasn’t as trivial as a garbage collection issue, as disabling the garbage collection didn’t solve any of the issues.

With these exhausting changes, I can finally put my efforts towards actually authoring the new feature!

Developer experience updates

A somewhat major change is that the default in-repository builds now use a pinned Nixpkgs revision. This should help providing a known working starting point for end-users. The pin will be manually moved as time goes on to known good revisions with good Hydra coverage.

Mobile NixOS outputs are now presented in the outputs attribute. There is a backward compatibility layer added to ensure previous incantations still work, but it will be removed at some point in the future.

Nixpkgs work

With Plasma Mobile Gear approved, and soon merged, its upgrade a shoe-in, Plasma Mobile support in Nixpkgs is shaping up.

As for the desktop environment, the additin of Plasma Mobile proper is soon good to go. The main issues regarding Plasma with Wayland support fixed the last blocker issues for its inclusion.


No new port were made in during this span. There is still a total of 21 devices you can build for.

July 2021 round-up

August 3rd 2021

This update is the eighteenth in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

During the two months 12 pull requests were merged.

Stage-1 apps re-design

The applications for stage-1 were redesigned in #364. Though it is an understatement to imply that they only were redesigned. While, yes, this follows the design language of the redesigned website, some work was needed to achieve the result.

First, support for truetype fonts needed to be added to the GUI toolkit. While it may seem like it’s not required for this limited use case, in reality this not only allows using more fonts than the hardcoded ones, it allows scalable fonts. With these changes, text should be big and readable on all devices.

Truetype fonts support also gives us the ability to fall back to other fonts. This initial implementation falls back to FontAwesome, giving us access to the full library of glyphs, rather than a selected subset.

In addition to these user-facing changes, a lot of work was done to rework some parts of the implementation and packaging of these applications. This should reduce the burden on packaging new features or applications made with this toolkit.

In another pull request, large images were fixed. This fixes corruption with images with higher resolution devices.

Notable changes

Device-specific changes

Pinephone improvements

A flurry of changes for the Pinephone, most authored by @tomfitzhenry.

Succinctly, updates to the latest revisions for the different mainline components, and other fixes and feature enablement.


No new port were made in April. There is still a total of 21 devices you can build for.

This update is the seventeenth in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

During the two months 10 pull requests were merged.

Not too different from last update, work has happened, but not present as merged pull requests in the Mobile NixOS repository.

In addition, some time was spent by the main author working on a side-project, unrelated to Mobile NixOS, but related to NixOS on ARM. Fear not, work is not really expected to slow down.

What’s been done elsewhere

Let’s not forget the still in-progress Plasma Mobile work. The initial pull request now includes only Plasma Mobile itself, while a new pull request was opened for the Plasma Mobile applications (#125156). Doing so should make it easier to finish up and land the changes, as it’s simply too big otherwise.

Work upstream on Nixpkgs has been started to refresh the Anbox module (#125600).

Preview of what’s coming

While a more in-depth write-up will come with the next update, pull request #364 refreshes the recovery and boot menu appearance. While working on this refresh, time was spent tracking down a rare, but reproducible crash.

Device-specific changes

Pinephone improvements


Support for three new devices was merged in this period.

Bringing the total of devices to 21.

This update is the sixteenth in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

During the two months 11 pull requests were merged.

This sounds like there’s not much that has been happening, but this is only half of the story.

Plasma Mobile support in NixOS

A good portion of my time has been spent working on adding support for Plasma Mobile in NixOS. The pull request needs some work still, as there are issues, mainly dealing with Wayland and Plasma integration with NixOS.

With that said, a draft for a Mobile NixOS demo image using Plasma Mobile was also made. It relies on the NixOS changes. After all, Mobile NixOS is a superset composed on top of NixOS.

I wouldn’t recommend anyone to use it at the moment, but it’s not a disaster. It’s the final paper cuts, the final 10% that needs 90% of the work. It’s close to being done, yet far from being over.

Phosh support in NixOS

Some community members, starting way back in May 2020, and even before, were working on their side on adding Phosh support in NixOS

@zhaofengli ran the last mile in #121226, with the initial support for Phosh in NixOS. There is also an example configuration demo system for Phosh for Mobile NixOS.

Since Phosh is already being built in Nixpkgs, you can take inspiration from that example configuration and start using it at this moment.

I invite you to follow through to the different pull requests, and thank the involved individuals.


Support for one new device was merged in this period.

Bringing the total of devices to 18.

February 2021 round-up

March 2nd 2021

This update is the fifteenth in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

Compared to the last month, they’re more subtle changes.

More hermetic evaluation

This started off the work from @eamsden, where uses of <nixpkgs> were removed almost everywhere in #238.

With the changes, the value <nixpkgs> is now used only at one location, at the start of the evaluation, in a way that can be overridden easily if needed.

This means that evaluation now works fine without a NIX_PATH. This is useful to allow users of Nix flakes to use the project.

Similar changes were made in #310 to rely on a single <nixpkgs> value for release.nix and example configuration evaluations.

Finalize stage-0

When #262 was merged in December, it was done so with two main features missing.

When a device supports stage-0 boot, a new toggle is shown in the generations list allowing the user to skip rebooting into the generation’s kernel.

When booting a generation, the device tree built from the same kernel source tree is now used. The pull request itself contains technical details. This was less trivial than expected.

armv7 works again

Using armv7 with Nixpkgs or NixOS is not always easy. There is no binary cache, and cross-compilation is as YMMV as it is for AArch64.

This is the reason why armv7 Mobile NixOS devices haven’t seen much work done and things slowly started not working.

With #306 time was taken to ensure contributors with armv7 devices wouldn’t be left with hard to debug issues from Mobile NixOS itself.

With this work finally taken care of, there is a recent known good starting point to use for armv7 devices.

A few recent WIP device ports were made on top of these changes. Stay tuned as they may become supported devices at some point in the future.

Android Flashable Zips

With #320, Android flashable zip support was added to Mobile NixOS. This is used to produce .zip files that can be installed to the devices using the mechanism commonly used to apply OTA updates in Android.

Why would this new flashing method be needed or desired?

First, it is more universal than fastboot, as some OEMs implement alternative flashing modes in their devices (e.g. Odin for Samsung).

Then, some devices (e.g. oneplus-oneplus3) have problematic fastboot flash behaviours when flashing to the userdata partition. Some devices (e.g. amazon-austin) need to apply some out-of-band "fixes" to the boot images, which happens for free when using a flashable zip.

With that said, all methods to flash the system to the device should produce the same outcome in most cases. As long as your device boots fine, there is no reason to prefer one or the other flashing method.

Device-specific changes

Wi-Fi support for Pixel XL

Following last month’s updates, @danielfullmer made the required changes to enable Wi-Fi for google-marlin (#295).


No new port were made in February. There is still a total of 17 devices you can build for.

January 2021 round-up

February 2nd 2021

This update is the fourteenth in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

Buckle-up, this month there’s a lot to say.

Go go all USB gadget modes

A couple changes this month are related to USB gadget mode. This is the name of the feature allowing a device (your cellphone) to be used as a USB device on your computer.

Target disk mode

This is not a fresh feature, the implementation pull request was opened in March 2020.

Once a device is booted with this example system, the device’s internal storage is made available over USB, as if it was a USB mass storage device.

The feature is limited to select devices, as it can be easily misused. The pine64-pinephone and asus-dumo devices are configured for this feature. It is limited as the block device to export has to be configured on a per-device basis. A further reason is the following:


Target disk mode should not be used to export the full drive of Android-based devices as it becomes trivial to brick a device. Some of their partitions should not be touched.

This is because for most Android-based devices, part of their basic firmware needed for booting is found on the main block device. Erasing or modifying the wrong partition would be like erasing the BIOS from your computer.

Broader ADB support

Time was taken to understand why ADB didn’t work on newer Android-based devices. It was initially suspected that the ADB daemon was incompatible with GadgetFS and FunctionFS.

It was much more trivial. The FunctionFS feature of the kernel needed the daemon to be started at a specific moment during the configuration, rather than at any time after.

With the fixes in #290 any device with GadgetFS can use ADB.

This means inspecting newer Android-based devices is easier, as it will most likely work if the device boots with a vendor kernel.

Using ADB is not limited to Android-based devices. The asus-dumo device is confirmed to be able to also use ADB. It is now the recommended basic method for getting a shell into a Mobile NixOS device, as it is easier to use than rndis.

LVGUI updates

A few updates were bundled together in #285. A few improvements to the early boot toolkit.

DRM support

Our toolkit used for user interfaces during early boot can now use DRM for rendering, in addition to fbdev.

The old framebuffer support is still present. In fact, compiling with DRM support implicitly also builds with fbdev support, as it will fall back to fbdev if DRM cannot be used. This allows one unique build to be used across devices with and without DRM support.

Adding support for DRM gives us an additional method of rendering. Some vendor kernels have broken fbdev implementations, like the SDM845 found in the razer-cheryl2 phone. With this change, early boot can be used on this device.

DRM is also the "future" of rendering on Linux. Well, it is the present of rendering on Linux. This is why it is now the preferred method to render the interface, when possible.

Libinput support

The evdev-based input driver has been replaced with a libinput driver. Libinput is the current recommended method for handling input with Linux. Evdev being one of the primitive constructs it uses.

Compared to the previous evdev driver used, there should be no differences with basic behaviour. Mainly, this was a clean-up, allowing us to remove some hacks that were used to identify device types with evdev. Libinput intrinsically knows more about the device than evdev did.

Device-specific changes

Wi-Fi support for qcacld-2.0 devices

The requirements for devices with qcacld-2.0 Wi-Fi hardware have been identified.

Support has been added in the following pull requests for the following devices:

The following device also uses qcacld-2.0 Wi-Fi. Support has not been added yet.

  • google-marlin

Initial support for Samsung Galaxy A5 (2017)

Support for the Samsung Galaxy A5 (2017) has been added.

It is the first Exynos device in Mobile NixOS, with an Exynos 7880. The device is otherwise unremarkable, it turns out that Mobile NixOS mostly just worked with Samsung’s initial boot flow. It required some minor adjustments, which are likely to help with their other phones and tablets.

Pinephone U-Boot update

January saw the release of U-Boot 2021.01. Mobile NixOS was already one version late, as 2020.10 was never packaged.

As with the previous update, upstream U-Boot is used, preferring to import well-identified patches for the remaining features desired.

This change should change nothing for many users. Users with a 3GB variant of the Pinephone will be relieved to know that they can now boot Mobile NixOS without additional work.

Other notable changes

  • #287 Fixes job control in the initrd shell

  • #292 asus-dumo gadget mode


One new device was merged in January.

Bringing the total of devices to 17.

2020 in the rear-view mirror

January 11th 2021

The year 2020 was my first full calendar year dedicated to working on the Mobile NixOS project. Let’s look at the progress, from the state of the project before January 2020, up to the state after December 2020.

Comparisons will start from the last commit of 2019, 7803d9ec0e35fe602f75d08e6bcb6db720ad897c. They are compared against the last commit for 2020, d5869523869eb029b712a3f2b7b1c3199874f221.

You might also be interested in looking at all the merged pull requests for 2020.

Some numbers

They’re quite arbitrary. I don’t know what other relevant stats could be used here.

  • 111 merged pull requests

  • 805 commits (skipping merge commits)

  • 10 commit authors (filtering duplicates)

  • Devices: 10 → 16

  • Modules: 39 → 56 (Nix files in modules/)

And here’s what cloc reveals:

[nix-shell:~/.../mobile-nixos/2019]$ cloc .
     274 text files.
     263 unique files.
      36 files ignored.

Language                      files          blank        comment           code
diff                             55            741           2623          16308
Nix                             108            719            772           4311
SVG                               7              4              4           2950
LESS                             24            263            333           1257
Ruby                             16            147             85            706
AsciiDoc                          7            130              3            243
XML                               5             19             12            160
ERB                               8              4              0             89
Markdown                          4             43              0             85
Lua                               1             15             41             58
Bourne Again Shell                2              9             10             21
C/C++ Header                      1             13             35             21
C                                 1              1              0             17
SUM:                            239           2108           3918          26226

[nix-shell:~/.../mobile-nixos/2020]$ cloc .
     482 text files.
     463 unique files.
      54 files ignored.

Language                      files          blank        comment           code
diff                             89           1429           5081          22047
Nix                             170           1266           1149           7576
Ruby                             76            690            575           4132
SVG                              10              4              4           3538
LESS                             25            291            334           1413
JSON                              6              0              0            959
AsciiDoc                         25            396              3            844
XML                               5             19             12            160
Markdown                          8             88              0            159
ERB                              10             23              0            130
Lua                               1             15             41             58
YAML                              1              1              0             40
C                                 1             11              5             37
C/C++ Header                      1             13             35             21
Bourne Again Shell                1              2              0              4
SUM:                            429           4248           7239          41118

Stage-1 improvements

This is where almost all of the work time this year was spent. Work started in January. Continuing through February, with the graphical interface. Further work punctuated the year. Neither words, screen captures or video can properly convey the amount of work spent on producing the best stage-1 experience that works across this wide range of devices.

We went from a rigid shell-script based approach, to a list of tasks handled through dependency resolution.

Additionally, before February, there was no way to select a previous generation. With the added GUI, generation selection is possible, error reporting in early boot is verbose, and boot progress is shown graphically.

Builds on Hydra

Before March 2020, no pre-built artifacts were produced. This is quite obvious when you try to build artifacts from the January checkout.

More important than build artifacts, this gave us continuous delivery of builds. With this we can track regressions, both in Mobile NixOS proper, or from changes in Nixpkgs.

Device support

Introduced in March 2020 the Pinephone is one of those devices with the biggest mind share in the community. Though, I personally don’t think it is the most interesting. After all, it is a somewhat boring device (in all the right ways!). Things with the Pinephone are expected to just work, and they mostly do, once the time is invested in implementing them.

Personally, at the top of the list of surprises are the Asus Zenfone Max Plus (M1) and the Moto E6. While less of the hardware is working, they are personally notable for me because they both do not have any alternative operating available. They were acquired as a challenge for me, to work strictly with sources from the vendor. This proved to myself that, yes, it is possible to work with devices that does not have a strong community behind them.

Closing word

I’m excited to continue working on this project. Let’s see what we can make out of 2021.

Don’t forget you can keep tabs on the project either by coming to the website regularly, or better yet, subscribe to the RSS feed!

December 2020 round-up

January 5th 2021

This update is the thirteenth in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

Some interesting improvements landed, let’s dive in.

stage-0: boot in generation kernel+initrd

One of the biggest flaw with the approach Mobile NixOS takes with the boot flow is that it completely ignores the system generation’s kernel and stage-1 image. In turn, this reduces some of the benefits from NixOS, by reducing the coherency of the running system; the kernel and stage-1 are managed out of band.

With the changes from #262, devices can opt-in to a stage-0 scheme. A stage-0 image is the same as a stage-1 image, except that it will use kexec to boot into the generation’s kernel and stage-1 image.

Devices, and their kernels, need to support kexec. This is not a given for vendor kernels. At the time being, none of the Android-based devices (all using the vendor kernels) can use this feature. On the bright side, the Pinephone has been verified to work well. Additionally, UEFI x86_64 based devices, too, can use the stage-0 scheme.

Device-specific changes

pine64-pinephone: Crust firmware support

To use U-Boot with Crust, you will need to build it, then install it manually on your boot media. (A helper to upgrade the firmware is planned for the future.)

Not related to Crust, the usual kernel upgrade for the Pinephone has been made.

Introduction of uefi-x86_64

The introduction of the Generic UEFI build (x86_64) "device" may seem odd. It is meant to be used on a standard computer. But a standard computer is not a mobile device.

Really, this is a dogfooding measure. With this change, it is now possible for me to replace the usual NixOS stage-1 from my personal machines, ensuring I take the stability of Mobile NixOS seriously!

Additionally, this should allow supporting some x86_64 Windows-based tablets with the Mobile NixOS toolchain. While not required, the touchscreen-first boot flow will be helpful for those without a keyboard.

These changes also help exercising the foundations, by creating a new system type.

Removal of qemu-x86_64

As part of the changes for #253, the qemu-x86_64 device has been removed. Instead, a more generic device has been added, which by default builds images that can boot on standard UEFI, and which in turn provide the build.vm output to boot that generic UEFI image with QEMU, using Tianocore.


Two new devices were merged in December, one was removed.

Bringing the total of devices to 16.

November 2020 round-up

December 1st 2020

This update is the twelfth in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

Some major improvements landed, let’s take a peek.

Progress in stage-1

The boot splash utility now shows the progress of the boot. This is done with a simple progress bar shows how much of the tasks have been handled. Long-running tasks can provide a message to show so the user knows things aren’t necessarily hung.

Speaking of hung tasks. Our init now detects when no tasks resolved in a given amount of time. When this happens, the boot is being failed with, hopefully enough context in the error message to help the user.

Speaking of error messages. Error messages are now less of a dead-end for our users. The interface has been reviewed to put the text message front and center. Previously we were showing a big image because we didn’t even have text rendering at this state. Now that we do, let’s use it.

In addition to that, the error applet is now somewhat interactive. There is now a cancellable countdown; when the time is elapsed the kernel is crashed, which allows the platform to do its default action (generally reboot). When canceled, the user can select different options, either through the touch screen, using a mouse, a keyboard or using volume-keys navigation.

The user can select to power off their device, which default action (so mashing the power key will power off the device). Depending on whether the platform supports it, the usual different reboot options are given.

Encrypted root filesystem support

Thought we were done with stage-1 updates? No! What if it was now able to decrypt LUKS encrypted filesystems? Well it can! For now, this is mainly the plumbing to make it all work. Getting a LUKS encrypted filesystem on your device is left as an exercise to the reader.

Our stage-1 can now ask for a passphrase during the early boot process phases. This is done through an on-screen keyboard. For the time being the keyboard is hard-coded to be the US QWERTY layout, and this is bad. Further improvements are planned, but out of scope for releasing the feature. The on-screen keyboard will be necessary for other upcoming planned features.

While using an on-screen keyboard is useful when you don’t have a physical keyboard, physical keyboards also can be used with that interface. Similarly to the previous note, it is hardcoded to be the US QWERTY keyboard, but the tooling chosen to drive the keyboard mapping (libxkbcommon) will give us the ability to configure both the on-screen and physical keyboard.


No new ports were made in November. There is still a total of 15 devices you can build for.

October 2020 round-up

November 3rd 2020

This update is the eleventh in a series of regular updates on the state of the project.

Only changes that have been accepted and merged in Mobile NixOS are chronicled here. There’s always more work currently in-progress.

Notable changes

Some interesting changes were made during the month, let’s look at some of them.

Re-done kernel builder ergonomics

The goal of this change is to make the kernel derivations as lean as possible, relying on the builder, rather than relying on copy-pasting common patterns around.

This is a change that was needed since the project was started. Though, it could not have happened much earlier than this late in the project. This is because multiple different quirky kernels needed to exist to properly show what needed to be abstracted.

With this, all common patterns for quirks have been identified and put behind flags. Those flags are described in Notes about the kernel builder.

End-users shouldn’t see any difference, this will help people who make ports.

Compile kernels only once

While testing the previous change, it was observed by @danielfullmer that kernel compilation happened twice for some devices.

This was not a regression. Though looking at things trying to find problems you are bound to see the existing flaws!

This was worked around by doing everything in one make invocation. The end-result is that some kernel builds will finish twice as quickly!

Pinephone Modem support improvements

With that said, there’s more to it. End-users shouldn’t have to care about a deeply-rooted /sys fs path to turn the modem off or on. This is why the modem-control service has been added. It mirrors the modem’s state using bindsTo and wantedBy.

With this service, the modem is better integrated with systemd, but more importantly the user can stop and start it using systemctl, rather than to dig for a particular less user-friendly path.

Calls and SMS will be tested at a later point in time. Though it is expected that calls will require some work for the audio to work properly (a known upstream issue).

New ports

One new device was merged this time.

Bringing the total of devices to 15.