commit 4b118bca19b29c9427f3c0cd9a0005695637f46e
Author: Daniel Barlow <dan@telent.net>
Date: Mon, 19 Sep 2022 23:51:38 +0100
generate a mips squashfs with some s6-rc services
haven't even tried booting it but I don't expect it to work. Needs
- s6-linux-init or some other pid 1 program
- a kernel
Diffstat:
7 files changed, 223 insertions(+), 0 deletions(-)
diff --git a/default.nix b/default.nix
@@ -0,0 +1,21 @@
+{ device ? (import devices/gl-ar750.nix)
+}:
+
+let
+ overlay = import ./overlay.nix;
+ nixpkgs = import <nixpkgs> ( device.system // {overlays = [overlay]; });
+ config = (import <liminix-config>) {
+ config = {
+ systemPackages = [];
+ services = {};
+ };
+ tools = nixpkgs.pkgs.callPackage ./tools {};
+ inherit (nixpkgs) pkgs;
+ };
+ finalConfig = config // {
+ packages = (with nixpkgs.pkgs; [ s6-rc ]) ++
+ config.systemPackages ++
+ (builtins.attrValues config.services)
+ ;
+ };
+in (import ./make-image.nix) nixpkgs finalConfig
diff --git a/devices/gl-ar750.nix b/devices/gl-ar750.nix
@@ -0,0 +1,11 @@
+{
+ system = {
+ crossSystem = {
+ config = "mips-unknown-linux-musl";
+ gcc = {
+ abi = "32";
+ arch = "mips32"; # maybe mips_24kc-
+ };
+ };
+ };
+}
diff --git a/example-configuration.nix b/example-configuration.nix
@@ -0,0 +1,57 @@
+{ config, tools, pkgs } :
+let
+ inherit (tools.networking) interface address udhcpc odhcpc;
+ inherit (tools.services) oneshot longrun bundle output;
+in rec {
+ services.loopback =
+ let iface = interface { type = "loopback"; device = "lo";};
+ in bundle {
+ name = "loopback";
+ contents = [
+ (address iface { family = "inet4"; addr ="127.0.0.1";})
+ (address iface { family = "inet6"; addr ="::1";})
+ ];
+ };
+ services.dhcpv4 =
+ let iface = interface { type = "hardware"; device = "eth0"; };
+ in udhcpc iface {};
+
+ services.dhcpv6 =
+ let iface = interface { type = "hardware"; device = "eth0"; };
+ in odhcpc iface { uid = "e7"; };
+
+ services.ntp = longrun {
+ # the simplest approach at the consumer end is to require the
+ # producer to create a file per output variable.
+ name = "ntp";
+ run = let s = services;
+ r = "${pkgs.ntp}/bin/ntp $(cat ${output s.dhcpv4 "ntp_servers"}) $(cat ${output s.dhcpv6 "NTP_IP"})";
+ in (builtins.trace r r);
+ # I don't think it's possible to standardise the file names
+ # generally, as different services have different outputs, but it
+ # would be cool if services that provide an interface could use
+ # the same name as each other. e.g. for anything implementing
+ # addressProvider you might expect (output svc "address") or
+ # (output svc "family") to work. Otherwise switching a network link
+ # from static to dhcp might require reviewing all the downstreams
+ # that refer to it.
+ # Also, services should declare the outputs they provide
+ outputs = [];
+ dependencies = [services.dhcpv4];
+ };
+
+ services.defaultroute4 =
+ let s = services;
+ in oneshot {
+ name = "defaultroute4";
+ up = ''
+ ip route add default gw $(cat ${output s.dhcpv4 "address"})
+ echo "1" > /sys/net/ipv4/$(cat ${output s.dhcpv4 "ifname"})
+ '';
+ down = ''
+ ip route del default gw $(cat ${output s.dhcpv4 "address"})
+ echo "0" > /sys/net/ipv4/$(cat ${output s.dhcpv4 "ifname"})
+ '';
+ };
+ systemPackages = [ pkgs.hello ] ;
+}
diff --git a/make-image.nix b/make-image.nix
@@ -0,0 +1,35 @@
+pkgs: config:
+let
+ inherit (pkgs) buildPlatform callPackage runCommandNoCC closureInfo stdenv writeText s6-rc;
+
+ # we need to generate s6 db, by generating closure of all
+ # config.services and calling s6-rc-compile on them
+ allServices = closureInfo {
+ rootPaths = builtins.attrValues config.services;
+ };
+ s6db = stdenv.mkDerivation {
+ name = "make-s6-db";
+ nativeBuildInputs = [pkgs.buildPackages.s6-rc];
+ builder = writeText "find-s6-services" ''
+ source $stdenv/setup
+ mkdir -p $out
+ srcs=""
+ shopt -s nullglob
+ for i in $(cat ${allServices}/store-paths ); do
+ if test -d $i; then
+ for j in $i/* ; do
+ if test -f $j/type ; then
+ srcs="$srcs $i"
+ fi
+ done
+ fi
+ done
+ echo s6-rc-compile $out/compiled $srcs
+ s6-rc-compile $out/compiled $srcs
+ '';
+ };
+ makeSquashfs = callPackage <nixpkgs/nixos/lib/make-squashfs.nix> {
+ storeContents = [ s6db ] ++ config.packages ;
+ # comp = "xz -Xdict-size 100%"
+ };
+in makeSquashfs
diff --git a/overlay.nix b/overlay.nix
@@ -0,0 +1,3 @@
+final: prev: {
+# s6-rc = final.callPackage ./pkgs/s6-rc;
+}
diff --git a/tools/builder.sh b/tools/builder.sh
@@ -0,0 +1,16 @@
+source $stdenv/setup
+mkdir -p $out/${name}
+echo $type > $out/${name}/type
+mkdir -p $out/${name}/dependencies.d
+echo $buildInputs > $out/buildInputs
+test -n "$dependencies" && for d in "$dependencies"; do
+ touch $out/${name}/dependencies.d/$d
+done
+test -n "$contents" && for d in "$contents"; do
+ mkdir -p $out/${name}/contents.d
+ touch $out/${name}/contents.d/$d
+done
+test -n "$run" && (echo "$run" > $out/${name}/run)
+test -n "$up" && (echo "$up" > $out/${name}/up)
+test -n "$down" && (echo "$down" > $out/${name}/down)
+(echo $out/${name} && cd $out/${name} && find . -ls)
diff --git a/tools/default.nix b/tools/default.nix
@@ -0,0 +1,80 @@
+{
+ stdenvNoCC
+, s6-rc
+} :let
+ inherit (builtins) concatStringsSep;
+ longrun = {
+ name
+ , run
+ , outputs ? []
+ , dependencies ? []
+ } @ args: stdenvNoCC.mkDerivation {
+ name = "${name}.service";
+ type = "longrun";
+ buildInputs = dependencies;
+ dependencies = builtins.map (d: d.name) dependencies;
+ inherit run;
+ builder = ./builder.sh;
+ };
+ oneshot = {
+ name
+ , up
+ , down
+ , outputs ? []
+ , dependencies ? []
+ , ...
+ } @ args: stdenvNoCC.mkDerivation {
+ # stdenvNoCC is to avoid generating derivations with names
+ # like foo.service-mips-linux-musl
+ name = "${name}.service";
+ type = "oneshot";
+ # does this suffice to make sure dependencies are included
+ # even though the built output has no references to their
+ # store directories?
+ buildInputs = dependencies;
+ inherit up down;
+ dependencies = builtins.map (d: d.name) dependencies;
+ builder = ./builder.sh;
+ };
+ bundle = {
+ name
+ , contents ? []
+ , dependencies ? []
+ , ...
+ }: stdenvNoCC.mkDerivation {
+ name = "${name}.bundle";
+ type = "bundle";
+ contents = builtins.map (d: d.name) contents;
+ buildInputs = dependencies ++ contents;
+ dependencies = builtins.map (d: d.name) dependencies;
+ builder = ./builder.sh;
+ };
+in {
+ networking = {
+ interface = { type, device } @ args: oneshot {
+ name = "${device}.link";
+ up = "ip link set up dev ${device}";
+ down = "ip link set down dev ${device}";
+ } // {
+ inherit device;
+ };
+ address = interface: { family, addr } @ args: oneshot {
+ dependencies = [ interface ];
+ name = "${interface.device}.addr.${addr}";
+ up = "ip address add ${addr} dev ${interface.device} ";
+ down = "ip address del ${addr} dev ${interface.device} ";
+ };
+ udhcpc = interface: { ... } @ args: longrun {
+ name = "${interface.device}.udhcp";
+ run = "udhchpcd ${interface.device}";
+ };
+ odhcpc = interface: { ... } @ args: longrun {
+ name = "${interface.device}.odhcp";
+ run = "odhcpcd ${interface.device}";
+ };
+ };
+ services = {
+ inherit longrun oneshot bundle;
+ output = service: name: "/run/services/outputs/${service.name}/${name}";
+ };
+}