Nix-enabled environment for your Android device. [maintainers=@t184256,@Gerschtli]
Nix-on-Droid
Nix package manager on Android, in a single-click installable package. This is not full NixOS running inside Android, but you get easy access to nixpkgs' vast collection of (precompiled!) software and the best package manager under the sun. It's prototype-grade quality as of now, but hey, it works!
It does not require root, user namespaces support or disabling SELinux, but it relies on proot and other hacks instead. It uses a fork of Termux-the-terminal-emulator app, but has no relation to Termux-the-distro. Please do not pester Termux folks about Nix-on-Droid.
This repository contains:
- Nix expressions that generate a bootstrap zipball,
nix-on-droid executable.
- A module system for configuring the local Nix-on-Droid installation directly
It is only tested with aarch64 (64-bit ARM devices). It also used to compile for i686 devices, but the developers don't own any and nobody has reported whether it actually worked or not, so it's no longer built unless a user shows up. Sorry, it would not work on 32-bit ARM devices and it's not an easy feat to pull off.
Try it out
Install it from F-Droid, launch the app, press OK, expect many hundreds megabytes of downloads to happen.
Nix-on-Droid and the module system
Config file
The Nix-on-Droid system can be managed through a custom config file in ~/.config/nixpkgs/nix-on-droid.nix as generated on first build, for example:
{ pkgs, ... }:
{ environment.packages = [ pkgs.vim ]; system.stateVersion = "24.05"; }
An alternative location is ~/.config/nixpkgs/config.nix with the key nix-on-droid, for example:
{
nix-on-droid =
{ pkgs, ... }:
{ environment.packages = [ pkgs.vim ]; system.stateVersion = "24.05"; }; }
See
home-manager integration
To enable home-manager you simply need to follow the instructions already provided in the example nix-on-droid.nix:
- Add
home-managerchannel:
nix-channel --add https://github.com/nix-community/home-manager/archive/release-24.05.tar.gz home-manager
nix-channel --update
- Configure
home-manager:
{ pkgs, ... }:
{ # Read Nix-on-Droid changelog before changing this value system.stateVersion = "24.05";
# insert Nix-on-Droid config
home-manager.config = { pkgs, ... }: { # Read home-manager changelog before changing this value home.stateVersion = "24.05";
# insert home-manager config };
# or if you have a separate home.nix already present: home-manager.config = ./home.nix; }
nix-on-droid executable
This executable is responsible for activating new configurations: Use nix-on-droid switch to activate the current configuration and nix-on-droid rollback to rollback to the latest build.
For more information, please run nix-on-droid help.
Build Nix-on-Droid on your own
The terminal emulator part is probably not interesting for you, just download and use a prebuilt one. If you really want to rebuild it, you can just use Android Studio for that.
The zipball generation is probably what you are after. Get an x86_64 computer with flake-enabled Nix.
tl;dr: Use the deploy app like the following which executes all steps mentioned below:>
> # or run the following for explanation of this script > nix run ".#deploy" >> nix run ".#deploy" -- <publicurl> <rsynctarget>
Run
nix build ".#bootstrapZip-aarch64" --impure
Put the zip file from result on some HTTP server and specify the parent directory URL during the installation. To re-trigger the installation, you can use 'clear data' on the Android app (after backing stuff up, obviously).
If you want to change the Nix-on-Droid channel to your custom one, you can do that either with nix-channel after the installation, or by setting the environment variable NIXONDROIDCHANNELURL. Other environment variables are NIXPKGSCHANNELURL an NIXONDROIDFLAKEURL.
Note: The proot binary is not built on the android device (NDK is required for building it, and it's not available on mobile platforms). The way we work around it is to push proot derivation to cachix. The current workaround is to hardcode the path to the wanted proot nix store path in modules/environment/login/default.nix. During evaluation time on the android device this store path will be downloaded from the binary cache (proot derivation has to be present there or in any other binary cache configured in the nix.conf on the device.
If you want to build that proot derivation (possibly to put it in your own cache):
# must run on a linux-x86_64 system (cross-compile only)
nix build ".#prootTermux-aarch64"
Obviously it's an annoyance if one wants to fork this repo and test something. To minimize the hassle with this scenario, proot derivation is also bundled with the bootstrap zipball. This way you only need your own binary cache if you are planning to maintain a long-term fork that users can update from. In case you only care about updates through wiping the data, or are forking to submit a one-off pull request, you shouldn't need a binary cache for that.
Nix flakes
Note: Nix flake support is still experimental at the moment and subject to change.
Examples / templates
A minimal example could look like the following:
{
description = "Minimal example of Nix-on-Droid system config.";
inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
nix-on-droid = { url = "github:nix-community/nix-on-droid/release-24.05"; inputs.nixpkgs.follows = "nixpkgs"; }; };
outputs = { self, nixpkgs, nix-on-droid }: {
nixOnDroidConfigurations.default = nix-on-droid.lib.nixOnDroidConfiguration { pkgs = import nixpkgs { system = "aarch64-linux"; }; modules = [ ./nix-on-droid.nix ]; };
}; }
For more examples and nix flake templates, see templates directory or explore with:
nix flake init --template github:nix-community/nix-on-droid#advanced
Usage with nix-on-droid
Use nix-on-droid switch --flake path/to/flake#device to build and activate your configuration (path/to/flake#device will expand to .#nixOnDroidConfigurations.device). If you run nix-on-droid switch --flake path/to/flake, the default configuration will be used.
Note: Currently, Nix-on-Droid can not be built with an pure flake build because of hardcoded store paths for proot. Therefore, every evaluation of a flake configuration will be executed with --impure flag. (This behaviour will be dropped as soon as the default setup does not require it anymore.)
Testing
In the ./tests/on-device directory, there is small set of bats tests that can be executed on a real or emulated android device.
To run the tests, execute
nix-on-droid on-device-test
Note: This currently requires a channel setup and should only be executed on clean, disposable installations.
Tips
- To grant the app access to the storage, use the toggle in the app settings
- If the terminal freezes, use 'Acquire wakelock' button in the notification
- We have a wiki
Technical overview
OK, real brief.
Developer's device:
prootfor the target platform is cross-compiled againstbionic,
/nix/store; think 'userspace chroot')
- Target
nixis taken from the original release tarball - Target
nixdatabase is initialized - Support scripts and config files are built with
nixand the Nix-on-Droid
- From these, a bootstrap zipball is built and published on an HTTP server
- Android app is installed and launched, bootstrap URL is entered
- Bootstrap zipball gets downloaded and unpacked
- 'First boot' begins, Nix builds the environment
- Nix installs the environment (login scripts, config files, etc.)
Licensing and credits
Licensed under MIT License, see LICENSE. Copyright (c) 2019-2021 Alexander Sosedkin and other contributors, see AUTHORS.
Two rewrites ago it was based off the official Nix install script (https://nixos.org/nix/install), presumably written by Eelco Dolstra.
Is deployed and used with a fork of Termux-the-terminal-emulator app, but has no relation to Termux-the-distro.
Previous project that did use Termux-the-distro: https://github.com/t184256/nix-in-termux
