liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 45025f128afb9c88fe0059fcb4ec0b80171d8d90
parent 6be5b90c9654c9b5194e3d72f7e08fbf809d6962
Author: Daniel Barlow <dan@telent.net>
Date:   Wed, 21 Sep 2022 23:01:21 +0100

switch to s6-linux-init and s6-rc

This is at the point where it runs a getty and a pile of s6-supervise
processes, though it doesn't seem to run the things being supervised

Diffstat:
MREADME.md | 24+++++++++++++++++++-----
Mmake-image.nix | 39+++++++++++++++++++++++----------------
Moverlay.nix | 4+++-
Apkgs/pseudofile/default.nix | 37+++++++++++++++++++++++++++++++++++++
Apkgs/s6-init-files/default.nix | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apkgs/s6-init-files/scripts/rc.init | 42++++++++++++++++++++++++++++++++++++++++++
Apkgs/s6-init-files/scripts/rc.shutdown | 19+++++++++++++++++++
Apkgs/s6-init-files/scripts/rc.shutdown.final | 18++++++++++++++++++
Apkgs/s6-init-files/scripts/runlevel | 12++++++++++++
Atests/pseudofiles/result.expected | 14++++++++++++++
Atests/pseudofiles/run.sh | 17+++++++++++++++++
Atests/pseudofiles/structure.nix | 45+++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 405 insertions(+), 22 deletions(-)

diff --git a/README.md b/README.md @@ -1,10 +1,6 @@ # Liminix -Līminis + Nix - -* Līminis : Latin, genitive declension of limen. "Of the threshold" -* Nix : a tool for reproducible and declarative configuration management -* Liminix : a Nix-based system for configuring consumer wifi routers +A Nix-based system for configuring consumer wifi routers. ## What is this? @@ -16,6 +12,11 @@ This is not NixOS-on-your-router: it's aimed at devices that are underpowered for the full NixOS experience. It uses busybox tools, musl instead of GNU libc, and s6-rc instead of systemd. +The Liminix name comes from Liminis, in Latin the genitive declension +of "limen", or "of the threshold". Your router stands at the threshold +of your (online) home and everything you send to/receive from the +outside word goes across it. + ## Building @@ -52,3 +53,16 @@ took full advantage of the basic application armoring features provided by the operating system. Indeed, only one or two models even came close, and no brand did well consistently across all models tested" + + + + +----- + +s6/ directory has the result of running s6-linux-init-maker, plus edits +to the scripts for s6-rc + +- need to fix the bin/ directory (maybe they were copied from + s6-linux-init?) + +- maybe the run-image directory can be added as a squashfs source directory? diff --git a/make-image.nix b/make-image.nix @@ -3,6 +3,7 @@ let inherit (pkgs) callPackage closureInfo + lib runCommand s6-rc stdenv @@ -46,36 +47,42 @@ let mount -t proc none /proc mkdir -p /run/services ''; - storefs = callPackage <nixpkgs/nixos/lib/make-squashfs.nix> { - storeContents = [ rcS pkgs.pkgsStatic.busybox s6db pkgs.s6-linux-init ] ++ config.packages ; - # comp = "xz -Xdict-size 100%" - }; + s6-pseudofiles = pkgs.s6-init-files; pseudofiles = writeText "pseudofiles" '' / d 0755 0 0 /bin d 0755 0 0 /etc d 0755 0 0 /run d 0755 0 0 /dev d 0755 0 0 - /dev/console c 0600 root root 5 1 /dev/null c 0666 root root 1 3 - /dev/tty c 0777 root root 5 0 + /dev/zero c 0666 root root 1 5 /dev/tty1 c 0777 root root 4 1 /dev/tty2 c 0777 root root 4 2 /dev/tty3 c 0777 root root 4 3 /dev/tty4 c 0777 root root 4 4 - /dev/zero c 0666 root root 1 5 + /dev/tty c 0777 root root 5 0 + /dev/console c 0600 root root 5 1 /proc d 0555 root root /dev/pts d 0755 0 0 /etc/init.d d 0755 0 0 - /bin/init s 0755 0 0 ${pkgs.pkgsStatic.busybox}/bin/init + /bin/init s 0755 0 0 /etc/s6-linux-init/current/bin/init /bin/sh s 0755 0 0 ${pkgs.pkgsStatic.busybox}/bin/sh - /bin/busybox s 0755 0 0 ${pkgs.pkgsStatic.busybox}/bin/busybox + /bin/busybox s 0755 0 0 ${pkgs.busybox}/bin/busybox /etc/init.d/rcS s 0755 0 0 ${rcS} + /etc/s6-rc d 0755 0 0 + /etc/s6-rc/compiled s 0755 0 0 ${s6db}/compiled + /etc/passwd f 0644 0 0 echo "root::0:0:root:/:/bin/sh" ''; -in runCommand "frob-squashfs" {} '' - cp ${storefs} ./store.img - chmod +w store.img - ${pkgs.buildPackages.squashfsTools}/bin/mksquashfs - store.img -no-recovery -quiet -no-progress -root-becomes store -p "/ d 0755 0 0" - ${pkgs.buildPackages.squashfsTools}/bin/mksquashfs - store.img -no-recovery -quiet -no-progress -root-becomes nix -pf ${pseudofiles} - cp store.img $out -'' + storefs = callPackage <nixpkgs/nixos/lib/make-squashfs.nix> { + storeContents = [ pseudofiles pkgs.strace s6-pseudofiles rcS pkgs.pkgsStatic.busybox s6db pkgs.s6-linux-init ] ++ config.packages ; + # comp = "xz -Xdict-size 100%" + }; +in runCommand "frob-squashfs" { + nativeBuildInputs = with pkgs.buildPackages; [ squashfsTools qprint ]; + } '' + cp ${storefs} ./store.img + chmod +w store.img + mksquashfs - store.img -no-recovery -quiet -no-progress -root-becomes store -p "/ d 0755 0 0" + mksquashfs - store.img -no-recovery -quiet -no-progress -root-becomes nix -pf ${pseudofiles} -pf ${s6-pseudofiles} + cp store.img $out + '' diff --git a/overlay.nix b/overlay.nix @@ -1,3 +1,5 @@ final: prev: { -# s6-rc = final.callPackage ./pkgs/s6-rc; + pseudofile = final.callPackage ./pkgs/pseudofile {}; + s6-init-files = final.callPackage ./pkgs/s6-init-files {}; + strace = prev.strace.override { libunwind = null; }; } diff --git a/pkgs/pseudofile/default.nix b/pkgs/pseudofile/default.nix @@ -0,0 +1,37 @@ +{ + writeText +, lib +}: +filename : attrset : +let + inherit (lib.debug) traceSeqN; + inherit (lib.attrsets) mapAttrsToList; + visit = prefix: attrset: + let + qprint = msg : builtins.replaceStrings ["\n" "=" "\""] ["=0A" "=3D" "=22"] msg; + l = + mapAttrsToList + (filename: attrs: + let + attrs' = {type = "f"; } // attrs; + mode = if attrs ? mode then attrs.mode else + (if attrs'.type == "d" then "0755" else "0644"); + line = "${prefix}/${filename} ${attrs'.type} ${mode} 0 0"; + in + if attrs'.type == "f" then + "${line} echo -n \"${qprint attrs'.file}\" |qprint -d" + else if attrs'.type == "d" then + (visit "${prefix}/${filename}" attrs.contents) + + "\n" + line + else if attrs'.type == "s" then + "${line} ${attrs'.target}" + else if attrs'.type == "l" then + "${prefix}/${filename} l ${attrs'.target}" + else if attrs'.type == "i" then + "${line} ${attrs.subtype}" + else + line) + attrset; + in builtins.concatStringsSep "\n" l; + res = (visit "" attrset); +in writeText filename res diff --git a/pkgs/s6-init-files/default.nix b/pkgs/s6-init-files/default.nix @@ -0,0 +1,156 @@ +{ + execline +, s6 +, s6-linux-init +, s6-rc +, pseudofile +, lib +, stdenvNoCC +, busybox +} : +let + initscripts = stdenvNoCC.mkDerivation { + name = "s6-scripts"; + src = ./scripts; + phases = ["unpackPhase" "installPhase" ]; + buildInputs = [busybox]; + installPhase = '' + mkdir $out + cp -r $src $out/scripts + chmod -R +w $out + patchShebangs $out/scripts + ''; + }; + dir = contents: { type = "d"; inherit contents; }; + symlink = target: { type = "s"; inherit target; }; + hpr = arg: "#!${execline}/bin/execlineb -S0\n${s6-linux-init}/bin/s6-linux-init-hpr ${arg} \$@"; + bin = dir { + shutdown = symlink "${s6-linux-init}/bin/s6-linux-init-shutdown"; + telinit = symlink "${s6-linux-init}/bin/s6-linux-init-telinit"; + reboot = { type="f"; file = hpr "-r"; mode="0755"; }; + poweroff = { type="f"; file = hpr "-p"; mode="0755"; }; + halt = { type="f"; file = hpr "-h"; mode="0755"; }; + init = { + type="f"; mode="0755"; + file = "#!${execline}/bin/execlineb -S0\n${s6-linux-init}/bin/s6-linux-init -c /etc/s6-linux-init/current -m 0022 -p ${lib.makeBinPath [execline s6-linux-init s6-rc]}:/usr/bin:/bin -d /dev -- \"\\$@\""; + }; + }; + scripts = symlink "${initscripts}/scripts"; + env = dir {}; + run-image = dir { + service = dir { + s6-linux-init-runleveld = dir { + notification-fd = { file = "3"; }; + run = { + file = '' + #!${execline}/bin/execlineb -P + ${execline}/bin/fdmove -c 2 1 + ${execline}/bin/bin/fdmove 1 3 + ${s6}/s6-ipcserver -1 -a 0700 -c 1 -- s + ${s6}/bin/s6-sudod -dt30000 -- "/etc/s6-linux-init/current"/scripts/runlevel + ''; + mode = "0755"; + }; + }; + s6-linux-init-shutdownd = dir { + fifo = { + type = "i"; + subtype = "f"; + mode = "0600"; + }; + run = { + file = '' + #!${execline}/bin/execlineb -P + ${s6-linux-init}/bin/s6-linux-init-shutdownd -c "/etc/s6-linux-init/current" -g 3000 + ''; + mode = "0755"; + }; + + }; + s6-svscan-log = dir { + fifo = { + type = "i"; + subtype = "f"; + mode = "0600"; + }; + notification-fd = { file = "3"; }; + run = { + file = '' + #!${execline}/bin/execlineb -P + ${execline}/bin/redirfd -w 1 /dev/null + ${execline}/bin/redirfd -rnb 0 fifo + ${s6}/bin/s6-log -bpd3 -- t /run/uncaught-logs + ''; + mode = "0755"; + }; + }; + getty = dir { + run = { + file = '' + #!${execline}/bin/execlineb -P + ${busybox}/bin/getty -l ${busybox}/bin/login 38400 /dev/console + ''; + mode = "0755"; + }; + }; + ".s6-svscan" = + let + quit = message: '' + #!${execline}/bin/execlineb -P + ${execline}/bin/redirfd -w 2 /dev/console + ${execline}/bin/bin/fdmove -c 1 2 + ${execline}/bin/foreground { ${s6-linux-init}/bin/s6-linux-init-echo -- ${message} } + ${s6-linux-init}/bin/s6-linux-init-hpr -fr + ''; + shutdown = action: '' + #!${execline}/bin/execlineb -P + ${s6-linux-init}/bin/s6-linux-init-hpr -a #{action} -- now + ''; + empty = "#!${execline}/bin/execlineb -P\n"; + in dir { + crash = { + file = quit "s6-svscan crashed. Rebooting."; + mode = "0755"; + }; + finish = { + file = quit "s6-svscan exited. Rebooting."; + mode = "0755"; + }; + SIGINT = { + file = shutdown "-r"; + mode = "0755"; + }; + SIGPWR = { + file = shutdown "-p"; + mode = "0755"; + }; + SIGQUIT = { + file = empty; + mode = "0755"; + }; + SIGTERM = { + file = empty; + mode = "0755"; + }; + SIGUSR1 = { + file = shutdown "-p"; + mode = "0755"; + }; + SIGUSR2 = { + file = shutdown "-h"; + mode = "0755"; + }; + SIGWINCH = { + file = empty; + mode = "0755"; + }; + + }; + }; + uncaught-logs = (dir {}) // {mode = "2750";}; + }; + structure = { etc = dir { s6-linux-init = dir { current = dir { + inherit bin scripts env run-image; + };};};}; + +in pseudofile "pseudo.s6-init" structure diff --git a/pkgs/s6-init-files/scripts/rc.init b/pkgs/s6-init-files/scripts/rc.init @@ -0,0 +1,42 @@ +#!/usr/bin/env sh + +rl="$1" +shift + +### argv now contains the arguments of the kernel command line that are +### not of the form key=value. (The key=value arguments were stored by +### s6-linux-init into an envdir, if instructed so via the -s option.) +### Normally this argv remains unused because programs that need the +### kernel command line usually read it later on from /proc/cmdline - +### but just in case, it's available here. + + +### 1. Early preparation +### This is done only once at boot time. +### Ideally, this phase should just initialize the service manager. + +### If your services are managed by s6-rc: +### (replace /run/service with your scandir) +s6-rc-init /run/service -d -c /etc/s6-rc/compiled + + +### 2. Starting the wanted set of services +### This is also called every time you change runlevels with telinit. +### (edit the location to suit your installation) +### By default, $rl is the string "default", unless you changed it +### via the -D option to s6-linux-init-maker. +### Numeric arguments from 1 to 5 on the kernel command line will +### override the default. + +exec /etc/s6-linux-init/current/scripts/runlevel "$rl" + + +### If this script is run in a container, then 1. and 2. above do not +### apply and you should just call your CMD, if any, or let your +### services run. +### Something like this: + +# if test -z "$*" ; then return 0 ; fi +# $@ +# echo $? > /run/s6-linux-init-container-results/exitcode +# halt diff --git a/pkgs/s6-init-files/scripts/rc.shutdown b/pkgs/s6-init-files/scripts/rc.shutdown @@ -0,0 +1,19 @@ +#!/usr/bin/env sh + + +### Things to do before hardware halt/reboot/poweroff. +### Ideally, it should be a single call to the service manager, +### telling it to bring all the services down. + +### If your s6-linux-init-maker invocation was made with the -1 +### option, messages from rc.shutdown will appear on /dev/console +### as well as be logged by the catch-all logger. +### If your s6-linux-init-maker invocation did NOT include the -1 +### option, messages from rc.shutdown will only be logged by the +### catch-all logger and will NOT appear on /dev/console. In order +### to print them to /dev/console instead, you may want to +### uncomment the following line: +exec >/dev/console 2>&1 + +### If your services are managed by s6-rc: +exec s6-rc -v2 -bDa change diff --git a/pkgs/s6-init-files/scripts/rc.shutdown.final b/pkgs/s6-init-files/scripts/rc.shutdown.final @@ -0,0 +1,18 @@ +#!/nix/store/xbdqbi2mscmhl5wcpbgpjdwxbsrvpkil-bash-5.1-p16/bin/sh -e + +### Things to do *right before* the machine gets rebooted or +### powered off, at the very end of the shutdown sequence, +### when all the filesystems are unmounted. + +### This is a last resort hook; normally nothing should be +### done here (your rc.shutdown script should have taken care +### of everything) and you should leave this script empty. + +### Some distributions, however, may need to perform some +### actions after unmounting the filesystems: typically if +### an additional teardown action is required on a filesystem +### after unmounting it, or if the system needs to be +### pivot_rooted before it can be shut down, etc. + +### Those are all exceptional cases. If you don't know for +### certain that you need to do something here, you don't. diff --git a/pkgs/s6-init-files/scripts/runlevel b/pkgs/s6-init-files/scripts/runlevel @@ -0,0 +1,12 @@ +#!/usr/bin/env sh -e + +### This script is called once at boot time by rc.init, and is +### also called by the runleveld service every time the user +### requests a machine state change via telinit. +### Ideally, it should just be a call to the service manager. + +test "$#" -gt 0 || { echo 'runlevel: fatal: too few arguments' 1>&2 ; exit 100 ; } + + +### If your services are managed by s6-rc: +exec s6-rc -v2 -up change "$1" diff --git a/tests/pseudofiles/result.expected b/tests/pseudofiles/result.expected @@ -0,0 +1,13 @@ +/service/s6-linux-init-runleveld/notification-fd f 0644 0 0 echo -n "3" |qprint -d +/service/s6-linux-init-runleveld/run f 0755 0 0 echo -n " hello=0A newline=0A" |qprint -d +/service/s6-linux-init-runleveld d 0755 0 0 +/service/s6-linux-init-shutdownd/fifo i 0600 0 0 f +/service/s6-linux-init-shutdownd/run f 0755 0 0 echo -n "s6-linux-init/bin/s6-linux-init-shutdownd -c =22/etc/s6-linux-init/current=22 -g 3000=0A" |qprint -d +/service/s6-linux-init-shutdownd d 0755 0 0 +/service/s6-svscan-log/fifo i 0600 0 0 f +/service/s6-svscan-log/notification-fd f 0644 0 0 echo -n "3" |qprint -d +/service/s6-svscan-log/run f 0644 0 0 echo -n "gdsgdfgsdgf=0A" |qprint -d +/service/s6-svscan-log d 0755 0 0 +/service d 0755 0 0 + +/uncaught-logs d 2750 0 0 +\ No newline at end of file diff --git a/tests/pseudofiles/run.sh b/tests/pseudofiles/run.sh @@ -0,0 +1,17 @@ +set -e + +expr=$(cat <<"EXPR" +let + overlay = import ./overlay.nix; + nixpkgs = import <nixpkgs> ( {overlays = [overlay]; }); + structure = import ./tests/pseudofiles/structure.nix; +in nixpkgs.pkgs.pseudofile "pseudo.s6-init" structure +EXPR + ) + +NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-build -E "${expr}" -o tests/pseudofiles/result $* +diff tests/pseudofiles/result tests/pseudofiles/result.expected +test -f /tmp/out.squashfs && rm /tmp/out.squashfs +nix-shell -p squashfsTools -p qprint --run "mksquashfs - /tmp/out.squashfs -p '/ d 755 0 0' -pf tests/pseudofiles/result -quiet -no-progress" +foo="$(nix-shell -p squashfsTools --run 'unsquashfs -cat /tmp/out.squashfs service/s6-linux-init-runleveld/run')" +test "$foo" = "$(printf "hello\nworld")" diff --git a/tests/pseudofiles/structure.nix b/tests/pseudofiles/structure.nix @@ -0,0 +1,45 @@ +let + dir = contents: { type = "d"; inherit contents; }; + structure = { + service = dir { + s6-linux-init-runleveld = dir { + notification-fd = { file = "3"; }; + run = { + file = '' + hello + world + ''; + mode = "0755"; + }; + }; + s6-linux-init-shutdownd = dir { + fifo = { + type = "i"; + subtype = "f"; + mode = "0600"; + }; + run = { + file = '' + s6-linux-init/bin/s6-linux-init-shutdownd -c "/etc/s6-linux-init/current" -g 3000 + ''; + mode = "0755"; + }; + + }; + s6-svscan-log = dir { + fifo = { + type = "i"; + subtype = "f"; + mode = "0600"; + }; + notification-fd = { file = "3"; }; + run = { + file = '' + gdsgdfgsdgf + ''; + }; + }; + }; + uncaught-logs = (dir {}) // {mode = "2750";}; + }; +in structure