1
0

Compare commits

..

4 Commits

Author SHA1 Message Date
be06363e4f new example for rsync/usb backup server 2023-03-10 18:42:32 +00:00
9f03276db8 move noise sources around in tests
wlan test shows output to make it easier to see when it went wrong
2023-03-10 18:41:43 +00:00
225fc6fe51 configurable busybox
allows modules to add to the busybox applets and change config
2023-03-10 18:40:45 +00:00
8b2fcb5336 move non-normative examples into a subdirectory 2023-03-10 14:38:13 +00:00
17 changed files with 287 additions and 25 deletions

2
ci.nix
View File

@ -31,4 +31,4 @@ let
liminix-config = vanilla; liminix-config = vanilla;
}).outputs.default; }).outputs.default;
}; };
in builtins.trace jobs jobs in jobs

View File

@ -22,6 +22,7 @@ let
{ _module.args = { inherit pkgs; lib = pkgs.lib; }; } { _module.args = { inherit pkgs; lib = pkgs.lib; }; }
./modules/hardware.nix ./modules/hardware.nix
./modules/base.nix ./modules/base.nix
./modules/busybox.nix
./modules/hostname.nix ./modules/hostname.nix
device.module device.module
liminix-config liminix-config

View File

@ -173,6 +173,8 @@
GPIOLIB="y"; GPIOLIB="y";
GPIO_MT7621 = "y"; GPIO_MT7621 = "y";
PHY_RALINK_USB = "y";
CMDLINE_PARTITION = "y"; CMDLINE_PARTITION = "y";
EARLY_PRINTK = "y"; EARLY_PRINTK = "y";

179
examples/arhcive.nix Normal file
View File

@ -0,0 +1,179 @@
# This is not part of Liminix per se. This is a "scratchpad"
# configuration for a device I'm testing with.
#
# Parts of it do do things that Liminix eventually needs to do, but
# don't look in here for solutions - just for identifying the
# problems.
{
config,
pkgs,
lib,
...
}: let
secrets = import ./extneder-secrets.nix;
inherit
(pkgs.liminix.networking)
address
udhcpc
interface
route
;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) writeText dropbear ifwait serviceFns
;
in rec {
boot = {
tftp = {
enable = true;
serverip = "192.168.8.148";
ipaddr = "192.168.8.251";
};
};
imports = [
../modules/tftpboot.nix
../modules/wlan.nix
# ./modules/flashable.nix
];
hostname = "arhcive";
kernel = {
config = {
USB = "y";
USB_EHCI_HCD = "y";
USB_EHCI_HCD_PLATFORM = "y";
USB_OHCI_HCD = "y";
USB_OHCI_HCD_PLATFORM = "y";
USB_SUPPORT = "y";
USB_COMMON = "y";
USB_STORAGE = "y";
USB_STORAGE_DEBUG = "n";
USB_UAS = "y";
USB_ANNOUNCE_NEW_DEVICES = "y";
SCSI = "y";
BLK_DEV_SD = "y";
USB_PRINTER = "y";
PARTITION_ADVANCED = "y";
MSDOS_PARTITION = "y";
EFI_PARTITION = "y";
EXT4_FS = "y";
EXT4_USE_FOR_EXT2 = "y";
FS_ENCRYPTION = "y";
};
};
services.dhcpc = (udhcpc config.hardware.networkInterfaces.lan {
dependencies = [ config.services.hostname ];
}) // { inherit (config.hardware.networkInterfaces.lan) device; };
services.sshd = longrun {
name = "sshd";
run = ''
mkdir -p /run/dropbear
${dropbear}/bin/dropbear -E -P /run/dropbear.pid -R -F
'';
};
services.resolvconf = oneshot rec {
dependencies = [ services.dhcpc ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
for i in $(output ${services.dhcpc} dns); do
echo "nameserver $i" > resolv.conf
done
)
'';
down = ''
rm -rf /run/service-state/${name}/
'';
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
srv = dir {};
};
services.defaultroute4 = route {
name = "defaultroute";
via = "$(output ${services.dhcpc} router)";
target = "default";
dependencies = [services.dhcpc];
};
programs.busybox = {
applets = ["blkid" "lsusb" "tar"];
options = {
FEATURE_LS_TIMESTAMPS = "y";
FEATURE_LS_SORTFILES = "y";
FEATURE_BLKID_TYPE = "y";
FEATURE_MOUNT_FLAGS = "y";
FEATURE_MOUNT_LABEL = "y";
FEATURE_VOLUMEID_EXT = "y";
};
};
services.mount_external_disk = oneshot {
name = "mount_external_disk";
up = "mount -t ext4 LABEL=backup-disk /srv";
down = "umount /srv";
};
services.rsync =
let
secrets_file = oneshot rec {
name = "rsync-secrets";
up = ''
. ${serviceFns}
(in_outputs ${name}
echo "backup:${secrets.rsync_secret}" > secrets)
'';
down = "true";
};
configFile = writeText "rsync.conf" ''
pid file = /run/rsyncd.pid
uid = store
[srv]
path = /srv
use chroot = yes
auth users = backup
read only = false
secrets file = ${secrets_file}/.outputs/secrets
'';
in longrun {
name = "rsync";
run = ''
${pkgs.rsync}/bin/rsync --no-detach --daemon --config=${configFile}
'';
dependencies = [
secrets_file
services.mount_external_disk
config.hardware.networkInterfaces.lan
] ;
};
services.default = target {
name = "default";
contents =
let links = config.hardware.networkInterfaces;
in with config.services; [
links.lo links.eth links.wlan
defaultroute4
resolvconf
sshd
rsync
];
};
users.root.passwd = lib.mkForce secrets.root_password;
users.store = {
uid=500; gid=500; gecos="Storage owner"; dir="/srv";
shell="/dev/null"; # authorizedKeys = [];
};
defaultProfile.packages = with pkgs; [e2fsprogs strace tcpdump ];
}

View File

@ -35,7 +35,7 @@ in rec {
imports = [ imports = [
./modules/wlan.nix ./modules/wlan.nix
./modules/tftpboot.nix ./modules/tftpboot.nix
./modules/flashable.nix # ./modules/flashable.nix
]; ];
hostname = "extneder"; hostname = "extneder";

View File

@ -2,7 +2,7 @@
let let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ; inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) busybox; # inherit (pkgs) busybox;
inherit (pkgs.liminix.networking) address interface; inherit (pkgs.liminix.networking) address interface;
inherit (pkgs.liminix.services) bundle; inherit (pkgs.liminix.services) bundle;
@ -46,7 +46,7 @@ in {
}; };
config = { config = {
defaultProfile.packages = with pkgs; defaultProfile.packages = with pkgs;
[ s6 s6-init-bin busybox execline s6-linux-init s6-rc ]; [ s6 s6-init-bin execline s6-linux-init s6-rc ];
hardware.networkInterfaces = { hardware.networkInterfaces = {
lo = lo =
@ -113,10 +113,6 @@ in {
}; };
filesystem = dir { filesystem = dir {
bin = dir {
sh = symlink "${busybox}/bin/sh";
busybox = symlink "${busybox}/bin/busybox";
};
dev = dev =
let node = type: major: minor: mode : { inherit type major minor mode; }; let node = type: major: minor: mode : { inherit type major minor mode; };
in dir { in dir {
@ -129,7 +125,7 @@ in {
etc = dir { etc = dir {
profile = symlink profile = symlink
(pkgs.writeScript ".profile" '' (pkgs.writeScript ".profile" ''
PATH=${lib.makeBinPath config.defaultProfile.packages} PATH=${lib.makeBinPath config.defaultProfile.packages}:/bin
export PATH export PATH
''); '');
}; };

85
modules/busybox.nix Normal file
View File

@ -0,0 +1,85 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption mkEnableOption types mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink;
inherit (lib.strings) toUpper;
attrs = { options, applets } :
let
extraOptions = builtins.concatStringsSep "\n"
(mapAttrsToList (n: v: "CONFIG_${toUpper n} ${toString v}") options);
appletOptions = builtins.concatStringsSep "\n"
(map (n: "CONFIG_${toUpper n} y") applets);
in {
enableMinimal = true;
extraConfig = ''
${extraOptions}
${appletOptions}
'';
};
cfg = config.programs.busybox;
busybox = pkgs.busybox.override (attrs { inherit (cfg) applets options; });
makeLinks = lib.attrsets.genAttrs
cfg.applets
(a: symlink "${busybox}/bin/busybox");
minimalApplets = [
# this is probably less minimal than it could be "arch" "ash"
"base64" "basename" "bc" "brctl" "bunzip2"
"bzcat" "bzip2" "cal" "cat" "chattr" "chgrp" "chmod" "chown"
"chpst" "chroot" "clear" "cmp" "comm" "cp" "cpio" "cut" "date"
"dd" "df" "dirname" "dmesg" "du" "echo" "egrep" "env" "expand"
"expr" "false" "fdisk" "fgrep" "find" "free" "fuser" "grep"
"gunzip" "gzip" "head" "hexdump" "hostname" "hwclock" "ifconfig"
"ip" "iplink" "ipneigh" "iproute" "iprule" "kill" "killall"
"killall5" "less" "ln" "ls" "lsattr" "lsof" "md5sum" "mkdir"
"mknod" "mktemp" "mount" "mv" "nc" "netstat" "nohup" "od" "pgrep"
"pidof" "ping" "ping6" "pkill" "pmap" "printenv" "printf" "ps"
"pwd" "readlink" "realpath" "reset" "rm" "rmdir" "route" "sed"
"seq" "setsid" "sha1sum" "sha256sum" "sha512sum" "sleep" "sort"
"stat" "strings" "stty" "su" "sum" "swapoff" "swapon" "sync"
"tail" "tee" "test" "time" "touch" "tr" "traceroute"
"traceroute6" "true" "truncate" "tty" "udhcpc" "udhcpc6" "umount"
"uname" "unexpand" "uniq" "unlink" "unlzma" "unxz" "unzip"
"uptime" "watch" "wc" "whoami" "xargs" "xxd" "xz" "xzcat" "yes"
"zcat"
];
in {
options = {
programs.busybox = {
applets = mkOption {
type = types.listOf types.str;
default = [];
example = ["sh" "getty" "login"];
};
options = mkOption {
# mostly the values are y n or m, but sometimes
# other strings are also used
type = types.attrsOf types.nonEmptyStr;
default = { };
};
};
};
config = {
programs.busybox = {
applets = minimalApplets;
options = {
ASH_ECHO = "y";
# ASH_OPTIMIZE_FOR_SIZE = "y";
BASH_IS_NONE = "y";
SH_IS_ASH = "y";
ASH_BASH_COMPAT = "y";
FEATURE_EDITING = "y"; # readline-ish command editing
FEATURE_EDITING_HISTORY = "128";
FEATURE_EDITING_MAX_LEN = "1024";
FEATURE_TAB_COMPLETION = "y";
FEATURE_EDITING_WINCH = "y";
};
};
filesystem = dir {
bin = dir ({
busybox = symlink "${busybox}/bin/busybox";
sh = symlink "${busybox}/bin/busybox";
} // makeLinks);
};
};
}

View File

@ -73,7 +73,7 @@ let
run = { run = {
file = '' file = ''
#!${execline}/bin/execlineb -P #!${execline}/bin/execlineb -P
${busybox}/bin/getty -l ${busybox}/bin/login 115200 /dev/console /bin/getty -l /bin/login 115200 /dev/console
''; '';
mode = "0755"; mode = "0755";
}; };
@ -134,6 +134,7 @@ let
}; };
in { in {
config = { config = {
programs.busybox.applets = [ "login" "getty" ];
filesystem = dir { filesystem = dir {
etc = dir { etc = dir {
s6-rc = dir { s6-rc = dir {

View File

@ -2,7 +2,7 @@
let let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ; inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) stdenv busybox wireless-regdb; inherit (pkgs) stdenv wireless-regdb;
regulatory = stdenv.mkDerivation { regulatory = stdenv.mkDerivation {
name = "regulatory.db"; name = "regulatory.db";
phases = ["installPhase"]; phases = ["installPhase"];
@ -20,6 +20,9 @@ in {
}; };
}; };
}; };
programs.busybox.applets = [
"insmod" "rmmod"
];
kernel = rec { kernel = rec {
config = { config = {
# Most of this is necessary infra to allow wireless stack/ # Most of this is necessary infra to allow wireless stack/

View File

@ -1,7 +1,6 @@
{ {
liminix liminix
, lib , lib
, busybox
, ppp , ppp
, pppoe , pppoe
, writeAshScript , writeAshScript

View File

@ -1,6 +1,5 @@
{ {
liminix liminix
, busybox
, writeAshScript , writeAshScript
, serviceFns , serviceFns
} : } :
@ -43,7 +42,7 @@ let
''; '';
in longrun { in longrun {
inherit name; inherit name;
run = "${busybox}/bin/udhcpc -f -i ${interface.device} -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}"; run = "/bin/udhcpc -f -i ${interface.device} -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
notification-fd = 10; notification-fd = 10;
dependencies = [ interface ] ++ dependencies; dependencies = [ interface ] ++ dependencies;
} }

View File

@ -3,7 +3,6 @@
, s6-rc , s6-rc
, s6 , s6
, lib , lib
, busybox
, callPackage , callPackage
, writeScript , writeScript
, serviceFns , serviceFns
@ -12,7 +11,7 @@ let
inherit (builtins) concatStringsSep; inherit (builtins) concatStringsSep;
output = service: name: "/run/service-state/${service.name}/${name}"; output = service: name: "/run/service-state/${service.name}/${name}";
serviceScript = commands : '' serviceScript = commands : ''
#!${busybox}/bin/sh #!/bin/sh
exec 2>&1 exec 2>&1
. ${serviceFns} . ${serviceFns}
${commands} ${commands}

View File

@ -4,7 +4,6 @@
, writeScript , writeScript
, stdenvNoCC , stdenvNoCC
, lib , lib
, busybox
, s6-rc , s6-rc
}: }:
let let
@ -14,7 +13,7 @@ let
''; '';
init = writeScript "init" '' init = writeScript "init" ''
#!${execline}/bin/execlineb -S0 #!${execline}/bin/execlineb -S0
${s6-linux-init}/bin/s6-linux-init -c /etc/s6-linux-init/current -m 0022 -p ${lib.makeBinPath [busybox execline s6-linux-init s6-rc]}:/usr/bin:/bin -d /dev -- "\$@" ${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 -- "\$@"
''; '';
in stdenvNoCC.mkDerivation { in stdenvNoCC.mkDerivation {
name = "s6-init-bin"; name = "s6-init-bin";

View File

@ -1,14 +1,13 @@
{ {
busybox writeScript
, writeScript
, lib , lib
} }
: name : { runtimeInputs ? [] } : text : writeScript name '' : name : { runtimeInputs ? [] } : text : writeScript name ''
#!${busybox}/bin/sh #!/bin/sh
set -o errexit set -o errexit
set -o nounset set -o nounset
set -o pipefail set -o pipefail
export PATH="${lib.makeBinPath ([ busybox ] ++ runtimeInputs)}:$PATH" export PATH="${lib.makeBinPath runtimeInputs}:$PATH"
${text} ${text}
'' ''

View File

@ -35,5 +35,5 @@ trap fatal ERR
mkdir vm mkdir vm
mips-vm --background ./vm ${img}/vmlinux ${img}/squashfs mips-vm --background ./vm ${img}/vmlinux ${img}/squashfs
expect ${./wait-for-wlan.expect} > output && mv output $out expect ${./wait-for-wlan.expect} |tee output && mv output $out
'' ''

View File

@ -3,11 +3,11 @@ set timeout 60
spawn socat unix-connect:vm/console - spawn socat unix-connect:vm/console -
send "\r\n" send "\r\n"
expect "login:" { send "root\r\n" } expect "login:" { send "root\r\n" }
expect "/ #" expect "#"
set FINISHED 0 set FINISHED 0
set EXIT "1" set EXIT "1"
send "ls -l /run/uncaught-logs/current\r\n" send "ls -l /run/uncaught-logs/current\r\n"
expect "/ #" expect "#"
while { $FINISHED < 10 } { while { $FINISHED < 10 } {
send "grep AP-ENABLED /run/uncaught-logs/current || echo not\r\n" send "grep AP-ENABLED /run/uncaught-logs/current || echo not\r\n"