Repository navigation
Nixup 0.1.1 BETA
Nixup 0.1.1 BETA
-
Password logins over SSH work: with
services.openssh.settings.PasswordAuthentication = truesshd checks a
user's password through PAM, as on NixOS (UsePAMis on by itself then; pam_unix reads the view's/etc/shadow).
Without PAM, nixpkgs' OpenSSH could only check DES passwords, so no NixOS-style hash ever matched. -
Users' passwords, as on NixOS:
users.users.<name>.hashedPassword,password(hashed on the phone),
hashedPasswordFile(a file from the config's folder, put on the phone readable by root alone, or one already
there),initialPasswordandinitialHashedPassword, in the view's/etc/shadow, which sshd takes for a
password login;expires(no logins from that day on). Alsoenable = false(the user is left out),
linger = false(its own units do not run),subUidRanges,subGidRangesandautoSubUidGidRange
(/etc/subuid,/etc/subgid),users.defaultUserHomeandusers.manageLingering, with NixOS's checks and
warnings. -
A new phone builds again: today's nixos-unstable dropped a NixOS module Nixup imported (
security/dhparams.nix),
which stopped every first build; Nixup now takes only the modules the nixpkgs has, and evaluates a
configuration.nix with that nixpkgs' own lib (Home Manager no longer warns of a mismatch). -
Safer by default: Nixup's folders and its
/etcwere writable by every user of its view (Magisk starts modules
with umask 0), so a service's user or a build user could change what root runs; they are root's alone now, and
an older install's are put right at the next start. -
On Samsung phones (One UI): density and navigation go back to the phone's own when they leave the config (its
screen resolution's density, its own navigation); settings One UI resets at each start are put back at each
start; Quick Settings tiles it refuses are told, not shown as done; a Samsung preload that cannot be brought back
is told as such. -
A build in which a service, a setting or an activation script failed is still the phone's build (its services
start at boot, its generation is kept), as NixOS's switch does, and ends failed with what did not work. A profile
in a format the module does not know (sent by a PC with a newer Nixup) is refused before anything changes. -
The app's New and Pick file work in Downloads; an install that waits on Google Play Protect's question says so,
andandroid.settings.developer.verifyAdbApps = falseis set before the installs. -
Builds, backups and updates keep the phone awake while they run (a timer's at night no longer stops when the
phone sleeps), and two of them at once no longer mix their files; a broken-off build is picked up after a restart
as before, and Free up space waits for a running build. -
Removing Nixup waits for the phone's unlock and tries again at the next start when something did not go back.
Installing it again with the same config works at once: the apps the removal took off (their data kept) no longer
stop the first build with "this system has no such switch"; their settings wait until the build installs them. -
Restoring an app's backup no longer follows the links in its data: restoring Termux could empty the whole shared
storage (itsstorage/sharedlink). Nixup never follows a link when it empties a folder (a user's in/run
either), nor when it gives a user's folders their owner and mode. -
unitConfig'sAfter,Wants,Requiresand the other order keys work as on NixOS,ConditionUseris
decided when the config is built, and sockets, timers, paths and targets takerestartTriggersand NixOS's other
unit options;users.groupshas NixOS'swheel,users,disk,ttyanddialout. -
A path unit can watch a path under a specifier, as systemd's:
PathChanged = "%h/inbox"in a Home Manager or
systemd.userunit is in its user's home (%t,%S,%C,%L,%Etoo). -
A config whose profile is past 128 KiB (a few specialisations, or Home Manager users with many units) builds on
the phone: it stopped with "Argument list too long". -
A service's
ExecStopthat hangs is ended afterTimeoutStopSec, as systemd ends it, with what it started. -
Removing a user together with its Home Manager config is told plainly (its home is left as it is, as NixOS
leaves it), not as a failure. -
Users that only Nixup knows (a
uidof their own) log in without "bad uid" and get theirXDG_RUNTIME_DIR. -
A user's own shell package (
users.users.<name>.shell = pkgs.xonsh) is fetched: sshd refused such a user ("shell
… does not exist") unless the same package was inenvironment.systemPackages. -
NixOS's
programs.*for the shells, as nixpkgs' own modules:programs.tmux,git,neovim,vim,htop,
direnv,starship,zoxide,fzf,bat,nix-index,yazi,ssh,mosh,nushelland others, with
environment.corePackagesandenvironment.defaultPackages; nano and command-not-found stay off on a phone. -
NixOS's
networking.hostFiles,networking.stevenblack(nixpkgs' own module: StevenBlack's ad and tracker
blocklist, withblockandwhitelist) andnetworking.proxy(default,httpProxy,httpsProxy,
ftpProxy,rsyncProxy,allProxy,noProxy): the files' lines go into the/etc/hostsof Nixup's
services and shells (Android's apps keep Android's), and the proxy into every shell session, Nix's daemon and
the phone's own builds' downloads. -
The shells as on NixOS, with nixpkgs' own modules:
environment.shellAliases,shellInit,loginShellInit,
interactiveShellInit,localBinInPath,homeBinInPath,shellsandprofiles, andprograms.bash,
programs.zsh,programs.fishandprograms.xonshwith their options and plugins (bash's completion, zsh's
autosuggestions and syntax highlighting, oh-my-zsh, ...). With Nix packages,/etc/profile,/etc/bashrc,
/etc/zshrc,/etc/fishand/etc/set-environmentare NixOS's own, the prompt is NixOS's (with the phone's name),
and PATH is made of the profiles, as on NixOS: the user's own,/etc/profiles/per-user/<user>, root's, and
/run/current-system/sw(system.path), with Android's commands after them.users.defaultUserShellis the
users' shell (bash, asprograms.bashmakes it), and a user whose shell is zsh, fish or xonsh needs its
programs.<shell>.enable, as on NixOS. Each user that logs in gets a/run/user/<uid>(XDG_RUNTIME_DIR).
Without Nix packages the phone's shell stays Android's sh, withenvironment.variablesandextraInit. -
The system's version, as on NixOS: each generation keeps its label (
system.nixos.label, with
system.nixos.tagsand the nixpkgs version) and the config's commit (system.configurationRevision), which
the app's Generations shows;system.copySystemConfiguration = true;keeps a copy of the configuration.nix
with each generation.nixos-versiontells them (--revision,--configuration-revision,--json),
/etc/os-releaseand/etc/lsb-releaseare in Nixup's view, andsystem.build.toplevelis the profile. -
Scripts, as on NixOS:
system.activationScriptsrun as root with each build and each start of the phone, in
Nixup's view, before the services start (in the order theirdepssay; a dry run runs those with
supportsDryActivation, withNIXOS_ACTION=dry-activate);system.preSwitchChecksrun before a build changes
anything, and one that fails stops it (NIXOS_NO_CHECK=1leaves them out);system.userActivationScriptsrun
as each normal user when they change and at each start of the phone, through NixOS'snixos-activationunit. A script'sundo(Nixup's own) runs once when it
leaves the config and when Nixup is removed, so the phone gets back what it changed. NixOS's modules that have
activation scripts build now. -
The phone builds its config by itself, as NixOS's
system.autoUpgrade: atdates(withrandomizedDelaySec,
fixedRandomDelayandpersistent) it builds again with everything at its newest (upgrade = false: as locked),
the picked config (a git clone gets its new commits first) orflake, withchannelfor a configuration.nix
alone, keeping the specialisation in use, and frees up space after (runGarbageCollection). Only on Wi-Fi unless
android.autoUpgrade.onlyOnUnmetered = false, only while charging withandroid.autoUpgrade.onlyWhileCharging,
and never on a low battery. -
nix.buildMachineswithnix.distributedBuilds, as on NixOS: a package cache.nixos.org has not got (an overlay's,
an unfree one) is built on those machines over ssh and sent back, where the build stopped at it before; the
shells' builds go to them too (/etc/nix/machines). -
systemd timers'
FixedRandomDelayworks (it was taken and did nothing). -
Seraph is now called Nixup: the app (
dev.nixup.manager), the Magisk module (nixup), its data
(/data/adb/nixup),nixup-rebuild,nixup-play-login,nixup-shell,nixup-backup, and the flake
(github:by-architect/Nixup,nixup.lib.nixupSystem,nixupConfigurations). Installing Nixup takes a
Seraph install over, as Seraph took Andronix's: its data moves (with a link left at/data/adb/seraph, so
paths a config names there still work), its module and app go, and its config stays where it is. Allow the
Nixup app root when it asks. A flake made for Seraph (seraph.lib.seraphSystem,seraphConfigurations)
andandroidApp = "dev.seraph.manager"build as they are. -
Nix in the phone's shells (the app's terminal, ssh,
su -c nixup-shell), as on NixOS:nix shell nixpkgs#htop,
nix run,nix profile add,nix-shell -p,nix-env -iA nixpkgs.htop,nix-build,nix-collect-garbageand
the rest, with the module's own Nix (nothing to download) and Nixup's store.nixpkgsthere is the config's own
(the registry's and<nixpkgs>, NixOS'snixpkgs.flake.setFlakeRegistryandsetNixPath): the phone keeps it,
andnixup-rebuildsends it once when the phone has not got it. What a user installs is on their PATH. -
NixOS's
nix.*options do what they do on NixOS:nix.enable,nix.package,nix.settingsandnix.extraOptions
(/etc/nix/nix.conf; flakes on, the sandbox off, as Android's kernels lack its namespaces),nix.registry,
nix.nixPath,nix.channel.enable,nix.nrBuildUsers(builds run asnixbldusers with uids from 400 to 999),
nix.gcandnix.optimiseat their times. Nix's daemon runs for the other users that log in.nix.sshServeand
nix.checkConfigare there too, so a NixOS module that sets them builds. -
A shell another program starts (
nix shell's, tmux's) keeps its PATH and gets the same prompt:SHELLis the shell
itself, as on NixOS, and/etc/bashrchas the prompt. -
Free up space runs in Nixup's view, where the users' own Nix profiles are roots it keeps.
-
Fixed: Nix's garbage collector (Free up space,
nix-collect-garbage) could stop with "read of 65536 bytes: Out of
memory" on an Android 4.x kernel, which refuses a big read of/proc/sys/kernel/modprobeandpoweroff_cmd: those
are empty in Nixup's view, as containers have them. -
nixup-rebuildsends what it sends of Nix's store compressed, to a module that takes it so. -
Home Manager, as on NixOS: import its NixOS module (a flake's
home-manager.nixosModules.home-manager, or
<home-manager/nixos>in a configuration.nix alone, which the phone then fetches as it fetches nixpkgs) and
home-manager.users.<name>has all of Home Manager's options. Each user's Home Manager runs as the user at each
build that changes it and at the phone's start (home-manager-<name>in the Services tab), linking its files into
its home; the services it makes (everyservices.*module's,systemd.user.servicesof one's own) run as the
user's own (user-<name>-<service>); its packages are the user's profile. Taking a user out takes Home Manager's
links out of its home again. No desktop session or D-Bus session bus on a phone: what needs one is not started, or
fails; the manual page, the desktop's file types and the locales but UTF-8's are off by default. -
A user's packages (
users.users.<name>.packages) are its own profile now,/etc/profiles/per-user/<name>, on its
PATHbeforeenvironment.systemPackages, as on NixOS; before, they were on everyone'sPATH. A user's own shell
(users.users.<name>.shell, bash or zsh) gets the samePATH, time zone andenvironment.extraInitas Nixup's
login shell (/etc/profile,/etc/zshenv). -
Users' own units (
systemd.user) run as each user'ssystemd --userwould:%tis its/run/user/<uid>,%S,
%C,%Eand%Lare in its home, and so are itsStateDirectory,CacheDirectory,LogsDirectoryand
ConfigurationDirectory(RuntimeDirectoryin/run/user/<uid>); its sockets and their folders are the user's,
and the user's profile is on theirPATH. A unix socket's path may start with a specifier (%t/foo.sock). -
Sockets are handed over with their names (
FileDescriptorName, else their socket unit's, asLISTEN_FDNAMES), and
a unix socket's folder is made with itsDirectoryMode. -
The build's messages name a user's unit where the config gives it (
home-manager.users.<name>.systemd.user...). -
Fixed: a specifier only known when a unit runs (its user's
%h,%U,%G, a user's unit's%t) stayed empty in a
command's single quotes (bash -c 'echo %t'); it is filled in there too, as systemd fills specifiers in everywhere. -
Specialisations, as on NixOS:
specialisation.<name>.configurationmakes other versions of the config (a
"work" or "travel" one) with each build. ⋮ → Specialisations switches to one, or back to the config itself,
without building again;build.shandnixup-rebuildtake--specialisation <name>. The phone keeps the
one picked, across restarts too, until a build picks another, and each generation remembers its own. -
NixOS's own service modules run on the phone as they are, from your nixpkgs:
services.ntfy-sh.enable = true;
runs nixpkgs' module, with its options, its user and its settings file, as on NixOS. The 67 Nixup has tried
(AdGuard Home, Caddy, cron, Forgejo, Gitea, Gotify, Grafana, harmonia, Jellyfin, Navidrome, nginx, ntfy, Redis,
Sonarr, Tor, Transmission, Uptime Kuma, Vaultwarden, ...) are listed in nix/nixos.nix (PostgreSQL is not: it needs
shared memory Android's kernel has not got);
another can be added as on NixOS,imports = [ "${modulesPath}/services/…" ];. -
Services can run as their own user (
User,Group,DynamicUser, as NixOS's modules give them): a user with
no uid gets one from 400 to 999, which the phone keeps. Android lets those on the network; one in the
media_rwgroup (serviceConfig.SupplementaryGroups = [ "media_rw" ];) gets the shared storage too (your
files and SD cards, as/storageand/sdcard), in its own view of the phone. -
Timers, as on NixOS: a service's
startAt, andsystemd.timerswithOnCalendar(systemd's calendar
events: "daily", "Mon..Fri 07:30", "*:0/15", with a time zone or the phone's),OnBootSec,OnActiveSec,
OnUnitActiveSec,OnUnitInactiveSec,Persistent(a time missed while the phone was off comes at its
start) andRandomizedDelaySec. The Services tab shows when each service a timer starts runs next. -
Sockets, as on NixOS (
systemd.sockets, TCP, UDP and unix): the phone opens them and hands them to their
service as systemd does, so nixpkgs' modules that use them run as they are (harmonia, a binary cache of the
phone's store, is on the list), and a port below 1024 can be a service user's. A service nothing else wants
starts at its first connection (the Services tab says "listening" until then); withAccept = trueeach
connection goes to a run of its own of the socket's template service. -
Templates (
foo@) and their instances (foo@bar,%i), path units (systemd.paths), units in packages
(systemd.packages: static-web-server's runs as nixpkgs' module makes it) and users' own units
(systemd.user.services,timers,sockets,paths: each normal user's, run as that user), as on NixOS. -
Type = "notify": a service counts as started once it saysREADY=1, and withWatchdogSecit is ended and
started again (Restart = "on-watchdog") when it stops sayingWATCHDOG=1. -
LoadCredentialEncryptedandSetCredentialEncrypted, assystemd-creds encryptmakes them on the phone
(with its own key); Nixup's/etchas amachine-id, as NixOS's has. -
A unit's
Environmentvalues have their specifiers filled in (%S,%N,%d,%h, ...), as systemd does. -
A module that adds
boot.kernelModules(nginx'stls) builds, with a warning: the phone loads no modules. -
Fixed: stopping a service took up to minutes on a phone with many processes (each of them was looked at with
a command of its own); one look at all of them takes a moment now. -
Fixed: a build did not wait for a forking service to have started before it said so (it looked before the
service's loop was there); a notify service that never says it is ready is told as not started. -
Fixed: services kept the DNS servers of the network of the last build or start, which another network (mobile
data, another Wi-Fi) may not answer: Nixup's /etc/resolv.conf now follows the phone's network. -
Fixed: services started with whatever environment the build or start came with (its TMPDIR, HOSTNAME, TERM, an
adb session's ...); they start clean now, as systemd starts them, with Android's own variables and root's HOME
for root's units. -
Fixed: a notify service that restarted could kill another process (one with the pid its listener had before).
-
Fixed: a service's stop or restart could end another service's processes: Android gives a new view the number a
view that just ended had, and the stopped service's loop took the new one's processes for its own. Each view
now keeps its number while its loop looks. -
Fixed: the "runs again" notice could come for a service stopped in the minute after it had stopped by itself,
once another process had its old process number. -
Fixed: the app was not told when a service stopped by itself, or when it ran again.
-
A unit's own Environment wins over its user's HOME and USER (NixOS's couchdb), /etc/hosts has the phone's own
name, an empty LoadCredential is taken as systemd takes it (ttyd), an empty environment.etc file is written
(homepage-dashboard), a command's lines continued with a backslash are one (prometheus), and a user's socket
with Accept = true runs its connections as that user. -
Nixup's /etc has every time zone of Android's data in /etc/zoneinfo, as NixOS has, with /etc/localtime a link to
the phone's (programs know its name by it: .NET's Kavita needs it) and TZDIR set for the services. -
A command's @ prefix (another name for the program, as systemd takes it: NixOS's Apache) works.
-
networking.hostName not set is "localhost" for NixOS's modules that read a name (Apache's ServerName); the phone
keeps its own name, as before. -
Services and the jobs cron starts have the phone's time zone in Nixup's
/etc/localtime, out of Android's
time zone data, so summer time comes too; cron's jobs ran in UTC before. -
system.path(cron'sPATH) is made by Nix itself, without Perl. -
A service nothing starts at boot (one a timer starts, or one to start by hand) is in the Services tab after
each build, ready to start. -
BindPathsare mounted before the service goes into itsWorkingDirectory, as systemd does. -
More of systemd's unit settings:
EnvironmentFile,LoadCredentialandSetCredential, the cache, logs and
configuration folders,BindPaths, conditions andExecCondition,Type = "forking"withPIDFile,
KillMode,TimeoutStopSec,ExecStopPost(andpreStop,postStop), everyRestartvalue,UMaskand
Limit…, targets ofsystemd.targets. What only hardens a service on NixOS (ProtectSystem, ...) is taken
and does nothing. -
environment.etc,systemd.tmpfiles,networking.hosts,networking.nameserversand
environment.variables, as on NixOS, in Nixup's view of the phone. -
The phone builds the small files a config makes (a service's settings file, a script) from what
cache.nixos.org has, and a build on a PC sends their recipes along; a package itself it still never builds.
YAML, JSON and TOML files are written without Python. -
sshd stops alone when a build restarts it, as on NixOS: SSH sessions, and a build run through one, stay.
-
Fixed: a build started over adb or ssh through Nixup's own Tailscale stopped halfway when it restarted
Tailscale (the session went, and the build with it): a build now goes on to its end, with all of it in
its log, when the session it came from is cut. -
Nixup's view has
/var/run,/var/lock(as/run's) and/var/tmp, as NixOS has them; cron needs them. -
After this update every running service starts again once.
-
A module that tells NixOS from a phone by
options ? networking.firewallnow finds that option on the phone
too (NixOS's modules need it): checkoptions ? androidinstead. -
Services that need the phone's storage say so with
unitConfig.RequiresMountsFor, as on NixOS: they
start once it is mounted (an SD card, or what Android mounts once the phone is first unlocked), waiting
quietly till then instead of failing; one whose storage came after its start starts again in a fresh
view, and one whose storage goes away stops to wait for it. The Services tab shows "waiting". -
serviceConfig.SuccessExitStatusandRestartForceExitStatus, as on NixOS: Syncthing restarting itself
(exit 3) is no longer told as a failure. -
services.syncthingwaits for its folders' storage, so it no longer fails at every start before the
phone is unlocked. -
Fixed: an automatic backup at the phone's first unlock failed ("the repository cannot be opened"): it
checked that the SD card's folder was there, which Android makes before it mounts the card. It now
checks the card is mounted, and waits for the next check when it is not. -
users.users.<name>.androidApp: a user with the uid of an app, looked up on the phone at each build (an app
installed again gets another one).androidApp = "dev.nixup.manager"is Nixup's own: an SSH login that
may use su as Nixup may, with no other app (no Termux). -
A normal user's home is
/home/<name>(Nixup's own folder), made by the build and there from the phone's
start on, before it is first unlocked. -
terminal.fontandterminal.colors, as Nix-on-Droid has them: the app's terminal takes its font (a file
of a Nix package) and colors from the config each time it opens. -
Services get Android's time zone, so the dates their programs write are the phone's local time.
-
Fixed: the phone took four minutes longer to start, also after the module was removed. Android relabels every
file of /data/adb at each start, and Nixup's Nix store has hundreds of thousands; now each start runs
restorecon on Nixup's folder, which leaves the mark that makes Android skip it from then on. -
A newer Nixup whose services' view changed starts the running services again in the new one (sshd saw
no /home until it did). -
Apps from Google Play:
android.packages.playstore = [ "com.whatsapp" ];installs and updates
them as Aurora Store would download them, with the split APKs made for the phone; no Play Store
or GApps needed. A Google account signs in once in the app (⋮ → Google Play account), which then
shows its token to copy or save, orandroid.playstore.tokenFilegives the token, which
nixup-play-loginmakes on a PC. A build that lists such apps stops first when no account is
signed in, or Google refuses its token, and says to sign in. -
Cloning a git repository has a "Clone its submodules too" box (off by default); pulls and builds
then include them, and a private submodule uses the same token. -
The app is installed for the phone's owner only, and removed from app clones and work profiles,
where Magisk refuses root without asking; opened there, it says so. -
Search: the Updates, Backups, Services and Logs tabs have a search box that keeps the rows with
what is typed in them (any case, with or without accents: "sifre" finds "şifre"), each log has
one that keeps the lines with it, and Back up… → Apps finds an app by its name or package. -
Fixed: picking up broken-off runs could start a second build next to one still running, which
deleted its new profile, so the build applied but the phone kept the old profile. A run still
going is now left alone, a second build, update or backup waits for the first, and each run has
its own temporary profile. -
Fixed: a flake with no
nixupConfigurationsnow says so instead of failing with no reason. -
Tailscale says when its auth key is refused, instead of an empty login link.
-
Fixed: a service runs again when a secret file it reads changes (a new Tailscale auth key, an
ssh host key); before, only a change to the service itself restarted it, so a new key waited
for a restart. -
Fixed: restoring an app that is no longer on the phone failed with "not installed" when its
backup held only its data (as withandroid.backup.defaults.apk = false). Such an app now comes
back whole: its APK first, from that backup or another backup of it, then its data; when no backup
has its APK, the restore says "app not found".nixup-backup restore <app>takes the newest
backup with data, not a newer one that holds only the APK. -
Fixed: pulling a config cloned with its submodules failed ("not our ref") when a commit on another
branch named a submodule commit its server no longer has. A pull now brings the submodules only to
the commits the pulled branch names.