2
0

62 Commits

Author SHA1 Message Date
dan 26b4a7a145 wip it good 2024-07-01 23:32:37 +01:00
dan 2663f58807 disable security for bordervm "liminix" share
tftp needs to be able to follow symlinks into the store
2024-07-01 20:53:03 +01:00
dan 9dbc285605 build libusb1 without libatomic 2024-06-30 17:52:17 +01:00
dan 8b6aa2134e zyxel dual image; restore deleted params 2024-06-30 17:50:45 +01:00
dan 3df1ec76ff cleanup whitespace and commas
* [] is now [ ]
* {} is now { }
* commas in arglists go at end of line not beginning

In short, I ran the whole thing through nixfmt-rfc-style but only
accepted about 30% of its changes. I might grow accustomed to more
of it over time
2024-06-30 17:16:28 +01:00
dan 0d3218127f remove unused makeWrapper input 2024-06-30 10:46:37 +01:00
dan e94bf62ec1 remove dead code (run deadnix) 2024-06-29 22:59:27 +01:00
dan 16a2499d74 avoid makeWrapper on host, it requires bash 2024-06-29 22:36:05 +01:00
dan d4d8093f97 working l2tp-over-wwan stick example 2024-06-20 10:15:54 +01:00
dan 7c9c801afc rename isTrigger to restart-on-upgrade
we're moving away from "trigger" services to "controller" services,
and "restart-on-upgrade" is the name used by s6-rc
2024-06-16 12:58:06 +01:00
dan c4185617c0 a6-rc-up-tree wait for lock if needed 2024-06-15 15:36:07 +01:00
dan 06d28e9b08 dhcpc handle case when env vars are missing
the notify-script should continue and signal readiness even if one or
more of the outputs it writes are mssing in the environment
2024-06-15 15:34:49 +01:00
dan 9540fc2641 add writeAshScriptBin (forgot to add file) 2024-06-15 15:04:56 +01:00
dan adc84108ad Revert "wwan gets address from ppp ipcp not dhcp"
This reverts commit be13ab23ca.
2024-06-15 15:04:33 +01:00
dan eae99051fa exec devout in service definition
makes little practical difference but saves a process slot
2024-06-15 15:01:57 +01:00
dan 49d1703428 add s6-rc-up-tree: start reverse deps of controlled service
When s6-rc stops a service, it also stops everything that
depends on it. but when it starts a service it starts only
that service, so we have to go through the other services
depending on it and figure out if they should be started too.
2024-06-15 14:59:34 +01:00
dan 1d337588f9 think 2024-06-15 09:04:19 +01:00
dan 29a869b4fa qemu: use kmodloader for wifi 2024-06-13 10:12:17 +01:00
dan 5ae1b0a193 Revert "bodervm: remove usbutils until we can fix the udev dep"
This reverts commit c22e3fb2ef.
2024-06-12 20:58:13 +01:00
dan 473a4947a5 inout test: wait longer for disk to appear 2024-06-12 20:44:03 +01:00
dan 50bad5c604 libusb needs udev on build
this is a workaround to make CI work again, but what we really need to
do is completely separate the nixpkgs used for nixos build-system
tools from the nixpkgs we use for liminix host binaries
2024-06-12 18:55:30 +01:00
dan c22e3fb2ef bodervm: remove usbutils until we can fix the udev dep 2024-06-12 13:07:29 +01:00
dan f898e4dca2 remove debug 2024-06-12 13:03:26 +01:00
dan 5121a8563d callService: dependencies are services not names 2024-06-12 12:58:57 +01:00
dan 78be354b6e think 2024-06-12 12:52:52 +01:00
dan be13ab23ca wwan gets address from ppp ipcp not dhcp 2024-06-12 12:51:07 +01:00
dan 4b30cd7a75 think 2024-06-11 14:05:32 +01:00
dan b15542b668 start correct services at boot
- uncontrolled services that are not dependent on a controlled service
- controllers
- _not_ controlled services or any other service that depends on one
2024-06-11 14:04:14 +01:00
dan 6daeaf29a0 flip controller/controlled relationship for wwan services 2024-06-11 14:02:48 +01:00
dan e6ca5ea064 store derivations not just names for service deps
.. also controllers, contents. This is to make it possible (easier)
to work out transitive dependencies at build time
2024-06-11 14:01:06 +01:00
dan e6e4665a18 flip dependencies for triggered/controlled services
Instead of treating the trigger as the "main" service and the
triggered service as subsidary, now we treat the triggered
service as the service and the trigger as "subsidary". This
needs some special handling when we work out which services
go in the default bundle, but it works better for declaring
dependencies on triggered services because it means the
dependency runs after the triggered service comes up, not
just when the watcher-for-events starts
2024-06-09 22:37:45 +01:00
dan 2c10790a6d think 2024-06-09 11:19:38 +01:00
dan 571adf84c0 inherit builtins.map 2024-06-07 16:55:45 +01:00
dan c8c79fd75a update all calls to uevent-watch 2024-06-02 20:42:09 +01:00
dan 884d8d194e wrap uevent-watch in a service 2024-06-02 20:42:09 +01:00
dan f091bbd706 devout: recognise attr,attrs when parsing search term string 2024-06-01 23:48:05 +01:00
dan 37d7e20582 wwan use uevent-watch to find tty for AT commands 2024-06-01 23:47:20 +01:00
dan 04b068f7a3 delete unused code 2024-06-01 22:43:48 +01:00
dan 53f57c1a8c devout: support sysfs attributes for (grand*)parent device 2024-06-01 22:43:27 +01:00
dan 19aba0d873 devout: support search for sysfs attributes 2024-06-01 21:20:41 +01:00
dan 7d00b39249 rename attributes->properties when referring to uevent fields
properties: key-value pairs in the uevent message
attributes: file contents in sysfs
2024-06-01 12:17:49 +01:00
dan 7aa8633cde think 2024-06-01 12:16:21 +01:00
dan 58bec8a40f semi-automate tftpbooting with minicom 2024-05-26 18:03:32 +01:00
dan a3fca5bf05 devout: add functions to read sysfs attributes 2024-05-26 18:03:32 +01:00
dan e0bd7aec1e wwan: hook usb-modeswitch to uevent 2024-05-26 18:03:32 +01:00
dan e815f61bb5 think 2024-05-26 18:00:31 +01:00
dan af9200a136 skip symlink handing unless linkname was provided 2024-05-26 18:00:31 +01:00
dan 898958fa10 make a serviceDefn for wwan 2024-05-22 18:54:49 +01:00
dan fa0f262706 commentary 2024-05-22 18:54:49 +01:00
dan 71aeb27b2f add hacky wwan service with hardcoding all over 2024-05-22 18:54:49 +01:00
dan 530b4080c9 create cdc-ncm module 2024-05-22 18:54:49 +01:00
dan 58cd007ccc barebones usb_modeswitch package 2024-05-22 18:54:49 +01:00
dan 3a56798eb5 l2tp set default route via tunnel 2024-05-22 18:54:49 +01:00
dan 758c7ef657 exec xl2tpd
haven't fully worked out why, but without this s6 is unable to stop it.
2024-05-22 18:54:49 +01:00
dan 73225a70b2 add rudimentary l2tp service module 2024-05-22 18:54:49 +01:00
dan ab304dd3f1 bordervm enable nat 2024-05-22 18:47:37 +01:00
dan 0d49f0f7a7 gl-ar750 appendDTB 2024-05-22 18:47:16 +01:00
dan e64390460a memorable net device names for gl-ar750
linux's view of eth1 and eth0 are opposite to that of u-boot
2024-05-22 18:47:08 +01:00
dan c0ef6ce282 list pkgs we need in bordervm build
it's a bit silly trying to build it with the whole liminix overlay
when it's a nixos system not a liminix system
2024-05-22 18:45:35 +01:00
dan bd6ec5201f run dhcp server on bordervm
this is for testing clients that have dhcp upstream
2024-05-22 18:45:35 +01:00
dan b4068da9fe tftp addresses 2024-05-22 18:45:35 +01:00
dan aa4b09da85 think (foreshadowing) 2024-05-22 18:45:23 +01:00
1581 changed files with 3359 additions and 792 deletions
+423 -3
View File
@@ -4726,9 +4726,9 @@ outside of it
[X] 2) if so, convert it to lualinux
[X] 3) add netlink socket to event loop
[X] 4) make it send messages to subscribers
5) package it
6) make uevent-watcher use it instead of netlink directly
7) write an inout test variant that has the stick inserted
[X] 5) package it
[X] 6) make uevent-watcher use it instead of netlink directly
[X] 7) write an inout test variant that has the stick inserted
at boot time already
I'm also thinking we could wrap the raw fds from lualinux into small
@@ -4741,3 +4741,423 @@ state before subscribing them [ needs a test ]
figure out what event format the subscribers want? lua-ish or send the
same messages as udev would? If we're going to send the originals,
should we store them alongside the parsed, or reconstruct from parsed?
Sat Apr 27 21:52:11 BST 2024
We have a passing inout test. Next thing to do is try it on
the actual arhcive hardware
Next big thing is some kind of failovery service. Almost-obvious
candidate is LTE failover with aaisp l2tp tunnel
Tue Apr 30 23:27:30 BST 2024
I want to connect my new ip camera to arthur without letting it reach the
internet, or the internet reach it.
we could plug it into a gl.inet box running dhcp server on lan
and client on wan, then use NAT to expose the camera's http and rtsp
ports on whatever address it has on the wan interface
Tue May 7 22:23:49 BST 2024
If we want to build a config with an l2tp upstream, it needs an
underlying dhcp interface not pppoe as we can't use the bordervm l2tp
account simultaneously. Having bordervm do dhcp might be quite useful
anyway for other applications, although it will have to double-nat to
the internet. We could give it an aaisp /64 and have routable ipv6 but
maybe that's a level of faff too high.
Given that we can build xl2tpd and a service for it.
're using the same l2tp account for thingy that we use to simulate ppp,
we need an upstream which is not ppp
We need a less shit coldplug that copes with filenames containing spaces (!)
Fri May 10 00:33:14 BST 2024
Getting xl2tp hackily running turned out to be not a lot of work. However,
we need to figure out routing
- we need a route on lan device to the dns to lookup l2tp.aaisp.net.uk
- we need a route on lan device to l2tp.aaisp.net.uk
also it doesn't die when the tunnel closes, which is a bit shit
maybe this is where we lean into health check services
a health check service is just a service that watches another service
and kills it if it's not healthy.
for xl2tpd, "not healthy" is "there is no ppp process" or "there is no
tunnel" or "the tunnel has no sessions". I don't know how we
(robustly) test for no ppp process associated with the l2tp peer
when ppp quits, does the tunnel come down?
in xl2tld.c child_handler we respond to sigchld by closing c->fd
and setting it to -1
Sat May 11 17:55:04 BST 2024
A better way to monitor the connection health would be to ping a
computer on the internet (preferably one that doesn't mind being
pinged). If we combine autodial with "is $isp still there" then we
should have something fairly robust.
xl2tpd spawns pppd, we should equip it with config that writes the
ppp outputs (ip address etc) to the xl2tp service directory so
that it can be used like a regular ppp. This will also make
it possible to have the health check work by pinging the peer address
Sun May 12 22:33:09 BST 2024
sleep until the interface is probably up
failure counter = 0
loop indefinitely
get outputs/peer-address of watched ppp service
ping it
if ok
reset failure counter
else
increment failure counter
fi
if failure counter > threshold
bounce the ppp service
exit, if previous action didn't do that already
end
sleep(check interval)
end loop
# ps ax | grep l2tp
72 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp
73 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp-log
122 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
1099 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
1102 root 1104 S {xl2tpd} /nix/store/i1bbqh7vybam03l6jzf4sm4np3k4ack5
1115 root 1420 S grep l2tp
# s6-rc -d change l2tp.aaisp.net.uk.l2tp
# ps ax | grep l2tp
72 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp
73 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp-log
122 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
1102 root 1104 S {xl2tpd} /nix/store/i1bbqh7vybam03l6jzf4sm4np3k4ack5
1122 root 1420 S grep l2tp
Mon May 13 19:45:59 BST 2024
We need to do the usb id swithcing dance thing for the lte modem.
At startup it's 12d1:14fe, which is "mass storage mode", although the
disks seem to disappear as soon as they appear which is weird
probably the mode switch should be triggered by device insertion
usb_modeswitch -v 12d1 -p 14fe --huawei-new-mode
https://github.com/pixelspark/tymodem?tab=readme-ov-file
Tue May 14 21:58:25 BST 2024
[ we didn't need this. the first form is the default, the second
is what something on the internet said we should change it to, the
third is setting it back to default ]
^SETPORT:A1,A2;12,1,16,A1,A2
AT^SETPORT="FF;12,16"
AT^SETPORT="A1,A2;12,1,16,A1,A2"
Wed May 15 21:55:11 BST 2024
we can use uevent-watch to look for devtype=usb_device product=12d1/14fe/102
and trigger a oneshot that runs usb-modeswitch
we can use uevent-watch to look for devtype=usb_device product=12d1/1506/102
and trigger a oneshot that runs the AT commands
if wwan0 is a triggered service how can dhcp depend on it? arse
- we can get reverse dependencies from s6-rc-db, so the sematics of
starting a triggered service could include starting everything it
enables
- we don't want to inadvertently start it on boot by putting it in the
global config.services
Thu May 16 09:09:44 BST 2024
we could do something cleverish with the config.services at build time
by stripping from it everything depending on a trigger. but then how
_do_ they get started? the intent of putting it in config.services
is that it will be started when conditions are suitable.
can we: go through each service in config.services, detect the trigger
that started it, and add it to a bundle named for that trigger?
we need something in the triggering service to mark the triggered
service as not-for-boot, and then to apply that transitively to
everyting depending on it
I don't think we have common code for triggers, so either we need to
add some or put this marking in all of the current examples
Wed May 22 22:29:46 BST 2024
# cat /sys/bus/usb/devices/1-1.2:1.2/uevent
DEVTYPE=usb_interface
DRIVER=huawei_cdc_ncm
PRODUCT=12d1/1506/102
TYPE=0/0/0
INTERFACE=255/2/22
MODALIAS=usb:v12D1p1506d0102dc00dsc00dp00icFFisc02ip16in02
# cat /sys/bus/usb/devices/1-1.2:1.0/uevent
DEVTYPE=usb_interface
DRIVER=option
PRODUCT=12d1/1506/102
TYPE=0/0/0
INTERFACE=255/2/18
MODALIAS=usb:v12D1p1506d0102dc00dsc00dp00icFFisc02ip12in00
neither of these is a tty. however, there's a ttyUSB0
diretory in there -
# cat /sys/bus/usb/devices/1-1.2:1.0/ttyUSB0/uevent
DRIVER=option1
# cat /sys/bus/usb/devices/1-1.2:1.0/ttyUSB0/tty/ttyUSB0/uevent
MAJOR=188
MINOR=0
DEVNAME=ttyUSB0
We can query devout using s6-ipcclient:
$ s6-ipcclient -v /run/devout.sock sh -c "echo devtype=wwan >&7; cat <&6 >&2"
we're going to need to expose sysfs parent attributes in devout,
so that we can tie together vendor/product and tty name
- they don't come from netlink socket so we'll have to read the
filesystem
- we don't know if we can cache them indefinitely or if they change
- we also will want to match on parent attributes
- per https://www.kernel.org/doc/html/v4.16/admin-guide/sysfs-rules.html
we should do that by getting the parent directory, not by
following symlinks
I think we are going to document "a rule depending on attrs won't
trigger if those attrs change silently without a uevent". attrs for a
path are rescanned only when a event for that path (or a child?)
is received.
we need to avoid using stdio to read sysfs attributes because of the
need for atomicity
Sun May 26 12:24:45 BST 2024
cd /
mkdir -p /tmp/sys/devices
find /sys/devices -type f | while read F ; do
D=/tmp/$(dirname $F)
test -d $D || mkdir -p $D
test -r $F && cat $F > /tmp/$F
done
Tue May 28 20:58:58 BST 2024
To make testing easier, we pass the /sys mount point as a param
to (sysfs) via (database)
This means that for event:match to work with attributes, the event
also has to point back to the database, or at least to sysfs. However
we'd like to do the attr tests after the regular uevent key tests
and the attrs tests after even that, because they're that mich slower.
-----
Let's change it up. The database contains kobjects not events. A
kobject knows its mountpoint as well as its path, and implements the
attr and attrs methods
Sun Jun 2 20:58:47 BST 2024
we have a new uevent-rule service that can start/stop its controlled
service based on uevent fields and sysfs attrs for the corresponding
device/any ancestor of its sysfs path
we need
- a way of starting _dependent_ services of the controlled service:
we want to activate that whole sub-branch of the dependency tree
- a way to not attempt to start dependents of the controlled service
at boot time: we don't want to put them in the default bundle if
they depend on stuff that's part of the default service set.
what happens when a service depends on _two_ controlled services?
we want to start it only when _both_ of them are up. That discourages
any idea of creating a bundle for each controlled service and its
dependants
Tue Jun 4 19:07:44 BST 2024
we have to do it at runtime. I think we can add a file in the service
directory to identify that it's triggered (i.e. only run in response
to an event, we could use better terminology here(
for s in the reverse deps of $triggered
unless any? (s1: { s1.triggered && s1.down } )
s.dependencies
start s
we can do this in ci, maybe adapt the inout test
two triggered services, A with a uevent that does happen
and B which doesn't
two dependent services; C depends on A only and D on A+B.
each should write an output
we check that the output from C is present but not the one from D
Tue Jun 4 22:22:20 BST 2024
We can't have dependencies of triggered services unless we expose the
triggered service instead of the watcher from the module that sets up
uevent-watch. otherwise the user will be declaring their dependencies
on the watcher and they will start when the watcher does. We need to
invert it.
Bother.
services.mount-foo = oneshot {
name = "blah";
up = "mount /dev/disk/by-partlabel/mydisk";
runCondition = conditions.sysfs {
terms = { partlabel = "blah"; };
symlink = "/dev/disk/by-partlabel/mydisk";
}
}
To process this, we need to
- remove it from the default bundle
- create a service that _is_ in the default bundle which
starts this one when runCondition is true
How would it look for service conditions other than uevents
Thu Jun 6 21:49:10 BST 2024
runCondition can be a function that accepts the service to be
watched and returns a service that does the watching. The
derivation calls this function and makes the watched service
depend on the watcher.
When adding services to the default bundle (wherever that happens, I
no longer remember) we need to check if the service has a controller
and add that instead of the service itself.
s6-ipcclient -v /run/devout.sock sh -c "echo subsystem=tty attrs.idVendor=12d1 >&7; cat <&6 >&2"
Sun Jun 9 22:55:05 BST 2024
services which depend on services that have controllers should not be
added to default bundle, otherwise they will try to start the controlled
service before its ready
Tue Jun 11 20:00:04 BST 2024
we can't look in /run/service/name to see if it's controlled, because
if it's a oneshot that directory won't exist. likewise /run/s6-rc/servicedirs/
we could add the controller to the dependencies, then
controlled? = (any dependency is a controller)
what about generating a script at build time that has the knowledge
baked in?
to_start = reverse deps of service
print "to_start=$to_start"
for each service s1 in to_start
if isControlled s1
rd = reverse deps of s1
print "test_stopped s1 && not_to_start="$not_to_start $rd"
print ''
for s in $to_start; do
case " $not_to_start " in
*" $s "*) true;;
*) s6-rc -u change $s ;;
esac
done
''
---
would it help to make an empty bundle called "controlled" and have all
controlled services depend on it? no, because the condition for
skipping a service is that it depends on a _different_ controlled
service that's down
s6-rc -u change $service
for s in $(s6-rc-db -d all-dependencies $service); do
if (s6-rc-db all-dependencies $s | grep controlled); do
# do nothing: if it's stopped, we don't want to start it,
# and if it's already running there's no need to.
# XXX what if it's running but its children are not?
# XXX 2 this fails as written because _every_ service $s depends
# on the controlled service $service
else
start s
"[service] Names cannot be duplicated and cannot contain a slash or a
newline; they can contain spaces and tabs, but using anything else
than alphanumerical characters, underscores and dashes is discouraged"
would this be simpler in fennel?
(each [l (lines (io.popen (%. "s6-rc-db -d all-dependencies %s" service)))]
(if (not (controlled-ancestor l))
(tset to-start l true)))
Sat Jun 15 08:51:21 BST 2024
# do this at boot
for s in $(s6-rc-db -d dependencies controlled); do
mkdir -p /run/services/controlled
touch /run/services/controlled/$s
done
# now we can do this to start a service tree
for controlled in $(cd /run/services/controlled/ && echo *); do
if down $controlled; then
blocks="$blocks $controlled "
fi
done
for s in $(s6-rc-db -d all-dependencies $service); do
for dep in $(s6-rc-db all-dependencies $s)
case "$blocks" in
"* $dep *")
: don't start
;;
*)
s6-rc -u change $s
;;
esac
done
done
+20
View File
@@ -0,0 +1,20 @@
# This is for use with minicom, but needs you to configure it to
# use expect as its "Script program" instead of runscript. Try
# Ctrl+A O -> Filenames and paths -> D
log_user 0
log_file -a -open stderr
set f [open "result/boot.scr"]
send "version\r"
set timeout 60
while {[gets $f line] >= 0} {
puts stderr "next line $line\r"
puts stderr "waiting for prompt\r"
expect {
"ath>" {}
"BusyBox" { puts stderr "DONE"; exit 0 }
}
send "$line\r\n"
}
puts stderr "done\r\n"
close $f
+35 -19
View File
@@ -6,7 +6,7 @@ in {
options.bordervm = {
keys = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
};
l2tp = {
host = mkOption {
@@ -55,18 +55,17 @@ in {
<nixpkgs/nixos/modules/virtualisation/qemu-vm.nix>
];
config = {
boot.kernelParams = [
"loglevel=9"
];
boot.kernelParams = [ "loglevel=9" ];
systemd.services.pppoe =
let conf = pkgs.writeText "kpppoed.toml"
''
interface_name = "eth1"
services = [ "myservice" ]
lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
ac_name = "kpppoed-1.0"
'';
in {
let
conf = pkgs.writeText "kpppoed.toml" ''
interface_name = "eth1"
services = [ "myservice" ]
lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
ac_name = "kpppoed-1.0"
'';
in
{
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
serviceConfig = {
@@ -80,24 +79,36 @@ in {
};
};
services.openssh.enable = true;
services.dnsmasq = {
enable = true;
resolveLocalQueries = false;
settings = {
# domain-needed = true;
dhcp-range = [ "10.0.0.10,10.0.0.240" ];
interface = "eth1";
};
};
systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
virtualisation = {
qemu = {
networkingOptions = [];
options = [] ++
optional cfg.ethernet.pci.enable
"-device vfio-pci,host=${cfg.ethernet.pci.id}" ++
optionals cfg.ethernet.usb.enable [
networkingOptions = [ ];
options =
[ ]
++ optional cfg.ethernet.pci.enable "-device vfio-pci,host=${cfg.ethernet.pci.id}"
++ optionals cfg.ethernet.usb.enable [
"-device usb-ehci,id=ehci"
"-device usb-host,bus=ehci.0,vendorid=${cfg.ethernet.usb.vendor},productid=${cfg.ethernet.usb.product}"
] ++ [
]
++ [
"-nographic"
"-serial mon:stdio"
];
};
sharedDirectories = {
liminix = {
securityModel = "none";
source = builtins.toString ./.;
target = "/home/liminix/liminix";
};
@@ -122,11 +133,16 @@ in {
useDHCP = false;
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}];
};
nat = {
enable = true;
internalInterfaces = [ "eth1" ];
externalInterface = "eth0";
};
};
users.users.liminix = {
isNormalUser = true;
uid = 1000;
extraGroups = [ "wheel"];
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = cfg.keys;
};
services.getty.autologinUser = "liminix";
+6 -2
View File
@@ -1,8 +1,12 @@
{...}:
{ ... }:
{
bordervm = {
# ethernet.pci = { id = "01:00.0"; enable = true; };
ethernet.usb = { vendor = "0x0bda"; product = "0x8153"; enable = true; };
ethernet.usb = {
vendor = "0x0bda";
product = "0x8153";
enable = true;
};
l2tp = {
host = "l2tp.aa.net.uk";
};
+31 -29
View File
@@ -1,12 +1,12 @@
{
nixpkgs
, unstable
, liminix
, ... }:
nixpkgs,
unstable,
liminix,
...
}:
let
inherit (builtins) map;
pkgs = (import nixpkgs {});
borderVmConf = ./bordervm.conf-example.nix;
pkgs = (import nixpkgs { });
borderVmConf = ./bordervm.conf-example.nix;
inherit (pkgs.lib.attrsets) genAttrs;
devices = [
"gl-ar750"
@@ -27,33 +27,35 @@ let
}).outputs.default;
tests = import ./tests/ci.nix;
jobs =
(genAttrs devices for-device) //
tests //
{
buildEnv = (import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).buildEnv;
(genAttrs devices for-device)
// tests
// {
buildEnv =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).buildEnv;
doc =
let json =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = {...} : {
let
json =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config =
{ ... }:
{
imports = [ ./modules/all-modules.nix ];
};
}).outputs.optionsJson;
installers = map (f: "system.outputs.${f}") [
"vmroot"
"mtdimage"
"ubimage"
];
inherit (pkgs.lib) concatStringsSep;
in pkgs.stdenv.mkDerivation {
}).outputs.optionsJson;
in
pkgs.stdenv.mkDerivation {
name = "liminix-doc";
nativeBuildInputs = with pkgs; [
gnumake sphinx fennel luaPackages.lyaml
gnumake
sphinx
fennel
luaPackages.lyaml
];
src = ./.;
buildPhase = ''
+27 -17
View File
@@ -1,24 +1,27 @@
{
deviceName ? null
, device ? (import ./devices/${deviceName} )
, liminix-config ? <liminix-config>
, nixpkgs ? <nixpkgs>
, borderVmConf ? ./bordervm.conf.nix
, imageType ? "primary"
deviceName ? null,
device ? (import ./devices/${deviceName}),
liminix-config ? <liminix-config>,
nixpkgs ? <nixpkgs>,
borderVmConf ? ./bordervm.conf.nix,
imageType ? "primary",
}:
let
overlay = import ./overlay.nix;
pkgs = import nixpkgs (device.system // {
overlays = [overlay];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.6" # kernel backports needs python <3
"python-2.7.18.7"
];
};
});
pkgs = import nixpkgs (
device.system
// {
overlays = [ overlay ];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.6" # kernel backports needs python <3
"python-2.7.18.7"
];
};
}
);
eval = pkgs.lib.evalModules {
specialArgs = {
@@ -46,7 +49,14 @@ let
borderVm = ((import <nixpkgs/nixos/lib/eval-config.nix>) {
system = builtins.currentSystem;
modules = [
({ ... } : { nixpkgs.overlays = [ overlay ]; })
{
nixpkgs.overlays = [
(final: prev: {
go-l2tp = final.callPackage ./pkgs/go-l2tp {};
tufted = final.callPackage ./pkgs/tufted {};
})
];
}
(import ./bordervm-configuration.nix)
borderVmConf
];
-1
View File
@@ -213,7 +213,6 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };
+8 -3
View File
@@ -23,12 +23,17 @@
VIRTIO_BLK = "y";
VIRTIO_NET = "y";
};
conditionalConfig = {
WLAN= {
MAC80211_HWSIM = "m";
};
};
};
hardware =
let
mac80211 = pkgs.mac80211.override {
drivers = ["mac80211_hwsim"];
klibBuild = config.system.outputs.kernel.modulesupport;
mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
targets = ["mac80211_hwsim"];
};
in {
defaultOutput = "vmroot";
+11 -3
View File
@@ -92,7 +92,6 @@
'';
};
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) interface;
in {
imports = [
../../modules/network
@@ -125,8 +124,16 @@
networkInterfaces =
let inherit (config.system.service.network) link;
in {
lan = link.build { ifname = "eth0"; };
wan = link.build { ifname = "eth1"; };
lan = link.build {
ifname = "lan";
# devpath = "/devices/platform/ahb/19000000.eth";
devpath = "/devices/platform/ahb/1a000000.eth";
};
wan = link.build {
ifname = "wan";
devpath = "/devices/platform/ahb/19000000.eth";
# devpath = "/devices/platform/ahb/1a000000.eth";
};
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
@@ -149,6 +156,7 @@
};
boot.tftp = {
loadAddress = lim.parseInt "0x00A00000";
appendDTB = true;
};
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
-14
View File
@@ -45,7 +45,6 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override {
targets = ["rt2800soc"];
@@ -90,19 +89,6 @@
let
inherit (config.system.service.network) link;
inherit (config.system.service) vlan;
inherit (pkgs.liminix.services) oneshot;
swconfig = oneshot {
name = "swconfig";
up = ''
PATH=${pkgs.swconfig}/bin:$PATH
swconfig dev switch0 set reset
swconfig dev switch0 set enable_vlan 1
swconfig dev switch0 vlan 1 set ports '1 2 3 4 6t'
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; };
# lan and wan ports are both behind a switch on eth0
-1
View File
@@ -38,7 +38,6 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
+1 -1
View File
@@ -26,7 +26,7 @@
# this device is described by the "qemu" device
installer = "vmroot";
module = {pkgs, config, lim, ... }: {
module = { config, lim, ... }: {
imports = [
../../modules/arch/aarch64.nix
../families/qemu.nix
+1 -1
View File
@@ -24,7 +24,7 @@
'';
installer = "vmroot";
module = {pkgs, config, lim, ... }: {
module = { config, lim, ... }: {
imports = [
../../modules/arch/arm.nix
../families/qemu.nix
+1 -1
View File
@@ -36,7 +36,7 @@
in the Development manual.
'';
module = {pkgs, config, lib, lim, ... }: {
module = { config, lib, lim, ... }: {
imports = [
../../modules/arch/mipseb.nix
../families/qemu.nix
-1
View File
@@ -419,7 +419,6 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
-3
View File
@@ -155,8 +155,6 @@
module = {pkgs, config, lib, lim, ... }:
let
openwrt = pkgs.openwrt;
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
mtd_by_name_links = pkgs.liminix.services.oneshot rec {
@@ -358,7 +356,6 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
en70000 = link.build {
# in armada-38x.dtsi this is eth0.
-2
View File
@@ -103,8 +103,6 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
+4 -7
View File
@@ -1,11 +1,9 @@
{ eval, lib, pkgs }:
let
inherit (lib) types;
conf = eval.config;
rootDir = builtins.toPath ./..;
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix)
["${rootDir}/"];
optToDoc = name: opt : {
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) [ "${rootDir}/" ];
optToDoc = name: opt: {
inherit name;
description = opt.description or null;
default = opt.default or null;
@@ -26,7 +24,6 @@ let
let x = lib.mapAttrsToList optToDoc sd.parameters; in x;
}
else
item // { declarations = map stripAnyPrefixes item.declarations; };
item // { declarations = map stripAnyPrefixes item.declarations; };
in
builtins.map spliceServiceDefn
(pkgs.lib.optionAttrSetToDocList eval.options)
builtins.map spliceServiceDefn (pkgs.lib.optionAttrSetToDocList eval.options)
+12 -18
View File
@@ -1,24 +1,18 @@
with import <nixpkgs> {} ;
with import <nixpkgs> { };
let
inherit (builtins) stringLength readDir filter;
devices = filter (n: n != "families")
(lib.mapAttrsToList (n: t: n) (readDir ../devices));
texts = map (n:
let d = import ../devices/${n}/default.nix;
d' = {
description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
} // d;
installer =
if d ? description && d ? installer
then ''
The default installation route for this device is
:ref:`system-outputs-${d.installer}`
''
else "";
in d'.description)
devices;
devices = filter (n: n != "families") (lib.mapAttrsToList (n: t: n) (readDir ../devices));
texts = map (
n:
let
d = import ../devices/${n}/default.nix;
d' = {
description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
} // d;
in
d'.description
) devices;
in
writeText "hwdoc" ''
Supported hardware
+14 -12
View File
@@ -11,15 +11,15 @@
...
}: let
secrets = import ./extneder-secrets.nix;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) writeText dropbear ifwait serviceFns;
inherit (pkgs) writeText serviceFns;
svc = config.system.service;
in rec {
boot = {
tftp = {
serverip = "192.168.8.148";
ipaddr = "192.168.8.251";
serverip = "10.0.0.1";
ipaddr = "10.0.0.8";
};
};
@@ -119,29 +119,31 @@ in rec {
secrets_file
services.mount_external_disk
config.hardware.networkInterfaces.lan
] ;
];
};
users.root = {
passwd = lib.mkForce secrets.root.passwd;
# openssh.authorizedKeys.keys = [
# (builtins.readFile "/home/dan/.ssh/id_rsa.pub")
# ];
openssh.authorizedKeys.keys = secrets.root.keys;
};
users.backup = {
uid=500; gid=500; gecos="Storage owner"; dir="/srv";
shell="/dev/null";
uid = 500;
gid = 500;
gecos = "Storage owner";
dir = "/srv";
shell = "/dev/null";
};
groups.backup = {
gid=500; usernames = ["backup"];
gid = 500;
usernames = [ "backup" ];
};
defaultProfile.packages = with pkgs; [
e2fsprogs
mtdutils
(levitate.override {
config = {
config = {
services = {
inherit (config.services) dhcpc sshd watchdog;
};
+23 -17
View File
@@ -5,9 +5,9 @@
# wherever the text "EDIT" appears - please consult the tutorial
# documentation for details.
{ config, pkgs, lib, ... } :
{ config, pkgs, ... }:
let
inherit (pkgs.liminix.services) bundle oneshot longrun;
inherit (pkgs.liminix.services) bundle oneshot;
inherit (pkgs) serviceFns;
# EDIT: you can pick your preferred RFC1918 address space
# for NATted connections, if you don't like this one.
@@ -49,31 +49,40 @@ in rec {
country_code = "GB";
wpa_passphrase = "not a real wifi password";
hw_mode="g";
hw_mode = "g";
ieee80211n = 1;
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa_key_mgmt = "WPA-PSK";
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
wmm_enabled = 1;
};
};
services.int = svc.network.address.build {
interface = svc.bridge.primary.build { ifname = "int"; };
family = "inet"; address = "${ipv4LocalNet}.1"; prefixLength = 16;
family = "inet";
address = "${ipv4LocalNet}.1";
prefixLength = 16;
};
services.bridge = svc.bridge.members.build {
services.bridge = svc.bridge.members.build {
primary = services.int;
members = with config.hardware.networkInterfaces;
[ wlan lan ];
members = with config.hardware.networkInterfaces; [
wlan
lan
];
};
services.ntp = svc.ntp.build {
pools = { "pool.ntp.org" = ["iburst"]; };
makestep = { threshold = 1.0; limit = 3; };
pools = {
"pool.ntp.org" = [ "iburst" ];
};
makestep = {
threshold = 1.0;
limit = 3;
};
};
services.sshd = svc.ssh.build { };
@@ -157,8 +166,7 @@ in rec {
interface = services.wan;
};
services.firewall = svc.firewall.build {
};
services.firewall = svc.firewall.build { };
services.packet_forwarding = svc.network.forward.build { };
@@ -195,7 +203,5 @@ in rec {
];
};
defaultProfile.packages = with pkgs; [
min-collect-garbage
];
defaultProfile.packages = with pkgs; [ min-collect-garbage ];
}
+1 -2
View File
@@ -1,6 +1,5 @@
{ config, pkgs, lib, ... } :
{ config, pkgs, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {
+1 -2
View File
@@ -1,6 +1,5 @@
{ config, pkgs, lib, ... } :
{ config, pkgs, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {
+177
View File
@@ -0,0 +1,177 @@
{
config,
pkgs,
lib,
...
}: let
secrets = import ./extneder-secrets.nix;
rsecrets = import ./rotuer-secrets.nix;
# https://support.aa.net.uk/Category:Incoming_L2TP says:
# "Please use the DNS name (l2tp.aa.net.uk) instead of hardcoding an
# IP address; IP addresses can and do change. If you have to use an
# IP, use 194.4.172.12, but do check the DNS for l2tp.aa.net.uk in
# case it changes."
# but (1) we don't want to use the wwan stick's dns as our main
# resolver: it's provided by some mobile ISP and they aren't
# necessarily the best at providing unfettered services without
# deciding to do something weird; (2) it's not simple to arrange
# that xl2tpd gets a different resolver than every other process;
# (3) there's no way to specify an lns address to xl2tpd at runtime
# except by rewriting its config file. So what we will do is lookup
# the lns hostname using the mobile ISP's dns server and then refuse
# to start l2tp unless the expected lns address is one of the
# addresses returned. I think this satisfies "do check the DNS"
lns = { hostname = "l2tp.aaisp.net.uk"; address = "194.4.172.12"; };
inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {
boot = {
tftp = {
serverip = "10.0.0.1";
ipaddr = "10.0.0.8";
};
};
imports = [
../modules/cdc-ncm
../modules/network
../modules/vlan
../modules/ssh
../modules/usb.nix
../modules/watchdog
../modules/mount
../modules/ppp
];
hostname = "thing";
services.wwan = svc.wwan.build {
apn = "data.uk";
username = "user";
password = "one2one";
authType = "chap";
};
services.wan =
let
z = final : prev: {
controller = longrun rec {
name = "wan-switcher";
run = ''
(in_outputs ${name}
${pkgs.s6-rc-round-robin}/bin/s6-rc-round-robin \
-p ${final.proxy.name} \
${lib.concatStringsSep " "
(builtins.map (f: f.name) [final.pppoe final.l2tp])}
)
'';
};
pppoe = (svc.pppoe.build {
interface = config.hardware.networkInterfaces.wan;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" rsecrets.l2tp.name
"password" rsecrets.l2tp.password
];
}).overrideAttrs(o: { inherit (final) controller; });
l2tp =
let
check-address = oneshot rec {
name = "check-lns-address";
up = "grep -Fx ${ lns.address} $(output_path ${services.lns-address} addresses)";
dependencies = [ services.lns-address ];
};
route = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = lns.address;
dependencies = [services.dhcpc check-address];
};
in (svc.l2tp.build {
lns = lns.address;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" rsecrets.l2tp.name
"connect-delay" "5000"
"password" rsecrets.l2tp.password
];
dependencies = [config.services.lns-address route check-address];
}).overrideAttrs(o: { inherit (final) controller; });
proxy = oneshot rec {
name = "wan-proxy";
inherit (final) controller;
buildInputs = with final; [ pppoe l2tp];
up = ''
echo start proxy ${name}
set -x
(in_outputs ${name}
cp -rv $(output_path ${final.controller} active)/* .
)
'';
};
};
in (lib.fix (lib.extends z (prev : { }))).proxy;
services.sshd = svc.ssh.build { };
services.resolvconf = oneshot rec {
dependencies = [ services.wan ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
for i in ns1 ns2 ; do
ns=$(output ${services.wan} $i)
echo "nameserver $ns" >> resolv.conf
done
)
'';
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
};
services.dhcpc = svc.network.dhcp.client.build {
interface = config.services.wwan;
dependencies = [ config.services.hostname ];
};
services.lns-address = let
ns = "$(output_word ${services.dhcpc} dns 1)";
route-to-bootstrap-nameserver = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = ns;
dependencies = [services.dhcpc];
};
in oneshot rec {
name = "resolve-l2tp-server";
dependencies = [ services.dhcpc route-to-bootstrap-nameserver ];
up = ''
(in_outputs ${name}
DNSCACHEIP="${ns}" ${pkgs.s6-dns}/bin/s6-dnsip4 ${lns.hostname} \
> addresses
)
'';
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.wan} peer-address)";
target = "default";
dependencies = [services.wan];
};
# defaultProfile.packages = [ pkgs.go-l2tp ];
users.root = {
passwd = lib.mkForce secrets.root.passwd;
openssh.authorizedKeys.keys = secrets.root.keys;
};
}
+1 -2
View File
@@ -1,7 +1,6 @@
{ config, pkgs, ... } :
let
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs) writeText;
inherit (pkgs.liminix.services) target;
svc = config.system.service;
secrets-1 = {
ssid = "Zyxel 2G (N)";
+3 -3
View File
@@ -3,8 +3,8 @@ let
inherit (pkgs) serviceFns;
svc = config.system.service;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
some-util-linux = pkgs.runCommand "some-util-linux" {} ''
inherit (pkgs.liminix.services) oneshot target;
some-util-linux = pkgs.runCommand "some-util-linux" { } ''
mkdir -p $out/bin
cd ${pkgs.util-linux-small}/bin
cp fdisk sfdisk mkswap $out/bin
@@ -53,7 +53,7 @@ in rec {
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = "default";
dependencies = [services.dhcpc];
dependencies = [ services.dhcpc ];
};
services.resolvconf = oneshot rec {
+1 -3
View File
@@ -8,12 +8,10 @@
root = {
# mkpasswd -m sha512crypt
passwd = "$6$6pt0mpbgcB7kC2RJ$kSBoCYGyi1.qxt7dqmexLj1l8E6oTZJZmfGyJSsMYMW.jlsETxdgQSdv6ptOYDM7DHAwf6vLG0pz3UD31XBfC1";
openssh.authorizedKeys.keys = [
];
openssh.authorizedKeys.keys = [ ];
};
lan = {
prefix = "10.8.0";
};
}
+4 -6
View File
@@ -10,12 +10,10 @@
let
secrets = {
domainName = "fake.liminix.org";
firewallRules = {};
firewallRules = { };
} // (import ./rotuer-secrets.nix);
inherit (pkgs.liminix.services) oneshot bundle;
inherit (pkgs) serviceFns;
svc = config.system.service;
wirelessConfig = {
wirelessConfig = {
country_code = "GB";
inherit (secrets) wpa_passphrase;
wmm_enabled = 1;
@@ -72,13 +70,13 @@ in rec {
wireless.networks = {
"${secrets.ssid}" = {
interface = config.hardware.networkInterfaces.wlan;
hw_mode="g";
hw_mode = "g";
channel = "2";
ieee80211n = 1;
} // wirelessConfig;
"${secrets.ssid}5" = rec {
interface = config.hardware.networkInterfaces.wlan5;
hw_mode="a";
hw_mode = "a";
channel = 36;
ht_capab = "[HT40+]";
vht_oper_chwidth = 1;
+1 -2
View File
@@ -1,6 +1,5 @@
{ config, pkgs, lib, lim, ... } :
{ config, pkgs, lim, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {
+1 -1
View File
@@ -1,4 +1,4 @@
{ lib, lim, pkgs, config, ...}:
{ lim, pkgs, config, ...}:
{
config = {
kernel.config = {
+1 -1
View File
@@ -1,4 +1,4 @@
{ lib, lim, pkgs, config, ...}:
{ lim, pkgs, config, ...}:
{
config = {
kernel.config = {
+1 -1
View File
@@ -1,4 +1,4 @@
{ lib, pkgs, config, lim, ...}:
{ config, lim, ...}:
{
config = {
kernel.config = {
+1 -1
View File
@@ -1,4 +1,4 @@
{ lib, pkgs, config, ...}:
{ pkgs, config, ...}:
{
imports = [ ./mips.nix ];
config = {
+1 -1
View File
@@ -1,4 +1,4 @@
{ lib, pkgs, config, ...}:
{ config, ...}:
{
imports = [ ./mips.nix ];
config = {
+18 -13
View File
@@ -4,10 +4,8 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (lib) mkOption types;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) address interface;
inherit (pkgs.liminix.services) bundle;
type_service = pkgs.liminix.lib.types.service;
@@ -38,7 +36,7 @@ in {
'';
# internal = true; # probably a good case to make this internal
};
rootfsType = mkOption {
rootfsType = mkOption {
default = "squashfs";
type = types.enum [
"btrfs"
@@ -48,7 +46,7 @@ in {
"ubifs"
];
};
rootOptions = mkOption {
rootOptions = mkOption {
type = types.nullOr types.str;
default = null;
};
@@ -56,20 +54,29 @@ in {
boot = {
commandLine = mkOption {
type = types.listOf types.nonEmptyStr;
default = [];
default = [ ];
description = "Kernel command line";
};
commandLineDtbNode = mkOption {
type = types.enum [ "bootargs" "bootargs-override" ];
type = types.enum [
"bootargs"
"bootargs-override"
];
default = "bootargs";
description = "Kernel command line's devicetree node";
};
imageType = mkOption {
type = types.enum [ "primary" "secondary" ];
type = types.enum [
"primary"
"secondary"
];
default = "primary";
};
imageFormat = mkOption {
type = types.enum ["fit" "uimage"];
type = types.enum [
"fit"
"uimage"
];
default = "uimage";
};
tftp = {
@@ -85,7 +92,7 @@ in {
};
# These names match the uboot environment variables. I reserve
# the right to change them if I think of better ones.
ipaddr = mkOption {
ipaddr = mkOption {
type = types.str;
description = ''
Our IP address to use when creating scripts to
@@ -130,13 +137,11 @@ in {
s = pkg (checkTypes parameters
(builtins.removeAttrs args ["dependencies"]));
in s.overrideAttrs (o: {
dependencies = (builtins.map (d: d.name) dependencies) ++ o.dependencies;
dependencies = dependencies ++ o.dependencies;
buildInputs = dependencies ++ o.buildInputs;
});
};
users.root = {
uid = 0; gid= 0; gecos = "Root of all evaluation";
dir = "/home/root/";
-1
View File
@@ -10,7 +10,6 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{
-2
View File
@@ -1,7 +1,6 @@
{
liminix
, ifwait
, lib
, svc
}:
{ members, primary } :
@@ -9,7 +8,6 @@
let
inherit (liminix.networking) interface;
inherit (liminix.services) bundle oneshot;
inherit (lib) mkOption types;
addif = member :
# how do we get sight of services from here? maybe we need to
# implement ifwait as a regualr derivation instead of a
+1 -3
View File
@@ -1,12 +1,10 @@
{
liminix
, ifwait
, lib
}:
{ ifname } :
let
inherit (liminix.services) bundle oneshot;
inherit (lib) mkOption types;
inherit (liminix.services) oneshot;
in oneshot rec {
name = "${ifname}.link";
up = ''
+8 -5
View File
@@ -8,7 +8,7 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption mkEnableOption types mapAttrsToList;
inherit (lib) mkOption types mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink;
inherit (lib.strings) toUpper;
@@ -85,10 +85,13 @@ in {
};
};
filesystem = dir {
bin = dir ({
busybox = symlink "${busybox}/bin/busybox";
sh = symlink "${busybox}/bin/busybox";
} // makeLinks);
bin = dir (
{
busybox = symlink "${busybox}/bin/busybox";
sh = symlink "${busybox}/bin/busybox";
}
// makeLinks
);
};
};
}
+31
View File
@@ -0,0 +1,31 @@
{ config, pkgs, lib, ... }:
let
inherit (pkgs) liminix;
inherit (lib) mkOption types;
in {
imports = [
../service-trigger
];
options = {
system.service.wwan = mkOption {
type = liminix.lib.types.serviceDefn;
};
};
config = {
kernel.config = {
USB_NET_HUAWEI_CDC_NCM = "y";
USB_USBNET = "y";
USB_SERIAL = "y";
USB_SERIAL_OPTION = "y";
};
# https://www.0xf8.org/2017/01/flashing-a-huawei-e3372h-4g-lte-stick-from-hilink-to-stick-mode/
system.service.wwan = config.system.callService ./wwan.nix {
apn = mkOption { type = types.str; };
username = mkOption { type = types.str; };
password = mkOption { type = types.str; };
authType = mkOption { type = types.enum [ "pap" "chap" ]; };
};
};
}
+67
View File
@@ -0,0 +1,67 @@
{
liminix
, usb-modeswitch
, ppp
, lib
, svc
, uevent-watch
}:
{ apn, username, password, authType }:
let
inherit (liminix.services) oneshot;
authTypeNum = if authType == "pap" then "1" else "2";
chat = lib.escapeShellArgs [
# Your usb modem thing might present as a tty that you run PPP
# over, or as a network device ("ndis" or "ncm"). The latter
# kind is to be preferred, at least in principle, because it's
# faster. This initialization sequence works for the Huawei
# E3372, and took much swearing: the error messages are *awful*
"" "AT"
"OK" "ATZ"
# create PDP context
"OK" "AT+CGDCONT=1,\"IP\",\"${apn}\""
# activate PDP context
"OK" "AT+CGACT=1,1"
# setup username and password per requirements of sim provider.
# (caret is special to chat, so needs escaping in AT commands)
"OK" "AT\\^AUTHDATA=1,${authTypeNum},\"\",\"${password}\",\"${username}\""
# start the thing (I am choosing to read this as "NDIS DialUP")
"OK" "AT\\^NDISDUP=1,1"
"OK"
];
modeswitch = oneshot rec {
name = "modem-modeswitch";
controller = (svc.uevent-rule.build {
serviceName = name;
terms = { devtype = "usb_device"; product = "12d1/14fe/102"; };
});
up = ''
${usb-modeswitch}/bin/usb_modeswitch -v 12d1 -p 14fe --huawei-new-mode
'';
};
atz = oneshot rec {
name = "modem-atz";
dependencies = [ modeswitch ];
controller = (svc.uevent-rule.build {
serviceName = name;
terms = {
subsystem = "tty";
attrs = {
idVendor = "12d1";
idProduct = "1506";
};
};
symlink = "/dev/modem";
});
up = ''
ls -l /dev/modem
test -L /dev/modem || exit 1
${ppp}/bin/chat -s -v ${chat} 0<>/dev/modem 1>&0
'';
down = "${ppp}/bin/chat -v '' ATZ OK 0<>/dev/modem 1>&0";
};
in svc.network.link.build {
ifname = "wwan0";
dependencies = [ atz ];
}
@@ -2,7 +2,6 @@
writeFennel
, linotify
, anoia
, lua
, lualinux
}:
writeFennel "acquire-delegated-prefix" {
-2
View File
@@ -1,12 +1,10 @@
{
liminix
, lib
, callPackage
}:
{ client, interface } :
let
inherit (liminix.services) longrun;
inherit (lib) mkOption types;
name = "dhcp6c.addr.${client.name}.${interface.name}";
script = callPackage ./acquire-wan-address.nix { };
in longrun {
-2
View File
@@ -1,13 +1,11 @@
{
liminix
, lib
, odhcp6c
, odhcp-script
}:
{ interface } :
let
inherit (liminix.services) longrun;
inherit (lib) mkOption types;
name = "dhcp6c.${interface.name}";
in longrun {
inherit name;
-1
View File
@@ -12,7 +12,6 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{
-2
View File
@@ -1,12 +1,10 @@
{
liminix
, lib
, callPackage
}:
{ client, interface } :
let
inherit (liminix.services) longrun;
inherit (lib) mkOption types;
name = "dhcp6c.prefix.${client.name}.${interface.name}";
script = callPackage ./acquire-delegated-prefix.nix { };
in longrun {
+1 -1
View File
@@ -18,7 +18,7 @@ let
name = "${interface.name}.dnsmasq";
inherit (liminix.services) longrun;
inherit (lib) concatStrings concatStringsSep mapAttrsToList;
hostOpt = name : { mac, v4, v6, leasetime } @ attrs:
hostOpt = name : { mac, v4, v6, leasetime }:
let v6s = concatStrings (map (a : ",[${a}]") v6);
in "--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}";
in
-1
View File
@@ -8,7 +8,6 @@
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
inherit (pkgs.liminix.services) oneshot;
kmodules = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
-2
View File
@@ -7,8 +7,6 @@
{ rules, extraRules }:
let
inherit (liminix.services) oneshot;
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
script = firewallgen "firewall.nft" (lib.recursiveUpdate rules extraRules);
in oneshot {
name = "firewall";
+6 -7
View File
@@ -5,14 +5,13 @@
## you want to run on it, and would usually be set in the "device" file:
## :file:`devices/manuf-model/default.nix`
{ lib, pkgs, config, ...}:
{ lib, ... }:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
in {
inherit (lib) mkOption types;
in
{
options = {
boot = {
};
boot = { };
hardware = {
dts = {
src = mkOption {
@@ -26,7 +25,7 @@ in {
'';
};
includes = mkOption {
default = [];
default = [ ];
description = "List of directories to search for DTS includes (.dtsi files)";
type = types.listOf types.path;
};
-2
View File
@@ -8,8 +8,6 @@
let
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList;
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
# This is not a friendly interface to configuring a wireless AP: it
# just passes everything straight through to the hostapd config.
+1 -1
View File
@@ -9,7 +9,7 @@ let
in longrun {
name = "ifwait.${interface.name}";
buildInputs = [ service ];
isTrigger = true;
restart-on-upgrade = true;
run = ''
${ifwait}/bin/ifwait -s ${service.name} $(output ${interface} ifname) ${state}
'';
+1 -6
View File
@@ -5,14 +5,9 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) address interface;
inherit (pkgs.liminix.services) bundle;
inherit (lib) mkOption types ;
inherit (pkgs) liminix;
type_service = pkgs.liminix.lib.types.service;
mergeConditionals = conf : conditions :
# for each key in conditions, if it is present in conf
# then merge the associated value into conf
+7 -4
View File
@@ -1,4 +1,4 @@
{ config, pkgs, lib, ...} :
{ config, pkgs, ...} :
let inherit (pkgs.liminix.services) oneshot longrun;
in {
config = {
@@ -11,16 +11,19 @@ in {
devout = longrun {
name = "devout";
notification-fd = 10;
run = "${pkgs.devout}/bin/devout /run/devout.sock 4";
run = "exec ${pkgs.devout}/bin/devout /run/devout.sock 4";
};
coldplug = oneshot {
name ="coldplug";
name = "coldplug";
# would love to know what mdevd-coldplug/udevadm trigger does
# that this doesn't
up = ''
for i in $(find /sys -name uevent); do ( echo change > $i ) ; done
'';
dependencies = [devout mdevd];
dependencies = [
devout
mdevd
];
};
};
};
+2 -7
View File
@@ -7,11 +7,6 @@
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
mkBoolOption = description : mkOption {
type = types.bool;
inherit description;
default = true;
};
in {
options = {
@@ -19,9 +14,9 @@ in {
type = liminix.lib.types.serviceDefn;
};
};
imports = [ ../mdevd.nix ];
imports = [ ../mdevd.nix ../service-trigger ];
config.system.service.mount =
let svc = liminix.callService ./service.nix {
let svc = config.system.callService ./service.nix {
partlabel = mkOption {
type = types.str;
example = "my-usb-stick";
+16 -15
View File
@@ -1,26 +1,27 @@
{
liminix
, uevent-watch
, lib
, svc
}:
{ partlabel, mountpoint, options, fstype }:
let
inherit (liminix.services) longrun oneshot;
inherit (liminix.services) oneshot;
device = "/dev/disk/by-partlabel/${partlabel}";
name = "mount.${lib.strings.sanitizeDerivationName (lib.escapeURL mountpoint)}";
options_string =
if options == [] then "" else "-o ${lib.concatStringsSep "," options}";
mount_service = oneshot {
name = "mount.${lib.escapeURL mountpoint}";
timeout-up = 3600;
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";
down = "umount ${mountpoint}";
controller = svc.uevent-rule.build {
serviceName = name;
symlink = device;
terms = {
partname = partlabel;
devtype = "partition";
};
};
in longrun {
name = "watch-mount.${lib.strings.sanitizeDerivationName mountpoint}";
isTrigger = true;
buildInputs = [ mount_service ];
run = ''
${uevent-watch}/bin/uevent-watch -s ${mount_service.name} -n ${device} partname=${partlabel} devtype=partition
'';
in oneshot {
inherit name;
timeout-up = 3600;
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";
down = "umount ${mountpoint}";
inherit controller;
}
-1
View File
@@ -1,6 +1,5 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
+2 -2
View File
@@ -17,7 +17,7 @@ let
ip address replace $ip/$mask dev $interface
(in_outputs ${name}
for i in lease mask ip router siaddr dns serverid subnet opt53 interface ; do
printenv $i > $i
(printenv $i || true) > $i
done)
}
case $action in
@@ -40,7 +40,7 @@ let
'';
in longrun {
inherit name;
run = "/bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
run = "exec /bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
notification-fd = 10;
dependencies = [ interface ];
}
-2
View File
@@ -1,7 +1,5 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{ enableIPv4, enableIPv6 }:
+1 -4
View File
@@ -1,7 +1,5 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{
@@ -11,8 +9,7 @@
# if devpath is supplied, we rename the interface at that
# path to have the specified name.
let
inherit (liminix.services) longrun oneshot;
inherit (lib) concatStringsSep;
inherit (liminix.services) oneshot;
name = "${ifname}.link";
rename = if devpath != null
then ''
+3 -3
View File
@@ -1,15 +1,15 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{ target, via, interface ? null, metric }:
let
inherit (liminix.services) oneshot;
with_dev = if interface != null then "dev $(output ${interface} ifname)" else "";
target_hash = builtins.substring 0 12 (builtins.hashString "sha256" target);
via_hash = builtins.substring 0 12 (builtins.hashString "sha256" via);
in oneshot {
name = "route-${target}-${builtins.substring 0 12 (builtins.hashString "sha256" "${via}-${if interface!=null then interface.name else ""}")}";
name = "route-${target_hash}-${builtins.substring 0 12 (builtins.hashString "sha256" "${via_hash}-${if interface!=null then interface.name else ""}")}";
up = ''
ip route add ${target} via ${via} metric ${toString metric} ${with_dev}
'';
-5
View File
@@ -1,7 +1,6 @@
{
liminix
, chrony
, serviceFns
, lib
, writeText
}:
@@ -9,10 +8,6 @@ params:
let
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList;
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
serverOpts = types.listOf types.str;
configFile = p:
(mapAttrsToList (name: opts: "server ${name} ${concatStringsSep "" opts}")
p.servers)
+9 -9
View File
@@ -1,12 +1,12 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (pkgs) liminix callPackage writeText;
inherit (pkgs) liminix writeText;
o = config.system.outputs;
in
{
@@ -22,7 +22,7 @@ in
# but only part of one.
kernel = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
kernel
******
@@ -42,7 +42,7 @@ in
};
dtb = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
dtb
***
@@ -52,7 +52,7 @@ in
};
uimage = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
uimage
******
@@ -68,7 +68,7 @@ in
};
manifest = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
Debugging aid. JSON rendition of config.filesystem, on
which can run "nix-store -q --tree" on it and find
+1 -1
View File
@@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkOption types;
inherit (lib) mkIf;
o = config.system.outputs;
in
{
+1 -1
View File
@@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkOption types;
inherit (lib) mkIf;
o = config.system.outputs;
in
{
+1 -1
View File
@@ -6,7 +6,7 @@
}:
let
inherit (lib) mkEnableOption mkOption mkIf types;
inherit (pkgs) runCommand callPackage writeText;
inherit (pkgs) runCommand;
in
{
options = {
+1 -1
View File
@@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkOption types;
inherit (lib) mkIf;
o = config.system.outputs;
in
{
+2 -3
View File
@@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption mkForce types concatStringsSep;
inherit (lib) mkOption types concatStringsSep;
in {
imports = [ ../ramdisk.nix ];
options.system.outputs = {
@@ -42,8 +42,7 @@ in {
boot-sh =
let
inherit (pkgs.lib.trivial) toHexString;
inherit (config.system.outputs) rootfs kernel;
inherit (config.system.outputs) rootfs;
cmdline = concatStringsSep " " config.boot.commandLine;
in
pkgs.buildPackages.runCommand "boot.sh.sh" {
+1 -1
View File
@@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (lib) mkOption types;
o = config.system.outputs;
phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024);
in {
-1
View File
@@ -58,7 +58,6 @@ in {
system.outputs = rec {
tftpboot =
let
inherit (pkgs.lib.trivial) toHexString;
o = config.system.outputs;
image = let choices = {
uimage = o.uimage;
+1 -1
View File
@@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (lib) mkOption types;
o = config.system.outputs;
cfg = config.tplink-safeloader;
in {
+1 -1
View File
@@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
inherit (lib) mkIf mkOption types;
cfg = config.boot.tftp;
instructions = pkgs.writeText "env.scr" ''
setenv serverip ${cfg.serverip}
-1
View File
@@ -5,7 +5,6 @@
, ...
}:
let
inherit (pkgs) liminix;
inherit (lib) mkIf mkOption types concatStringsSep optionalString;
in
{
+1 -1
View File
@@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
inherit (lib) mkIf mkOption types;
models = "6b e1 6f e1 ff ff ff ff ff ff";
in {
options.system.outputs = {
+15
View File
@@ -17,6 +17,9 @@ in {
system.service.pppoe = mkOption {
type = liminix.lib.types.serviceDefn;
};
system.service.l2tp = mkOption {
type = liminix.lib.types.serviceDefn;
};
};
config = {
system.service.pppoe = pkgs.liminix.callService ./pppoe.nix {
@@ -29,6 +32,16 @@ in {
description = "options supplied on ppp command line";
};
};
system.service.l2tp = pkgs.liminix.callService ./l2tp.nix {
lns = mkOption {
type = types.str;
description = "hostname or address of the L2TP network server";
};
ppp-options = mkOption {
type = types.listOf types.str;
description = "options supplied on ppp command line";
};
};
kernel = {
config = {
PPP = "y";
@@ -36,6 +49,8 @@ in {
PPP_DEFLATE = "y";
PPP_ASYNC = "y";
PPP_SYNC_TTY = "y";
PPPOL2TP = "y";
L2TP = "y";
};
};
};
+61
View File
@@ -0,0 +1,61 @@
{
liminix
, writeAshScript
, writeText
, serviceFns
, xl2tpd
} :
{ lns, ppp-options }:
let
inherit (liminix.services) longrun;
name = "${lns}.l2tp";
ip-up = writeAshScript "ip-up" {} ''
. ${serviceFns}
(in_outputs ${name}
echo $1 > ifname
echo $2 > tty
echo $3 > speed
echo $4 > address
echo $5 > peer-address
echo $DNS1 > ns1
echo $DNS2 > ns2
)
echo >/proc/self/fd/10
'';
ip6-up = writeAshScript "ip6-up" {} ''
. ${serviceFns}
(in_outputs ${name}
echo $4 > ipv6-address
echo $5 > ipv6-peer-address
)
echo >/proc/self/fd/10
'';
ppp-options' = ppp-options ++ [
"ip-up-script" ip-up
"ipv6-up-script" ip6-up
"ipparam" name
"nodetach"
"usepeerdns"
"logfd" "2"
];
conf = writeText "xl2tpd.conf" ''
[lac upstream]
lns = ${lns}
require authentication = no
pppoptfile = ${writeText "ppp-options" ppp-options'}
autodial = yes
redial = no
max redials = 1
'';
control = "/run/xl2tpd/control-${name}";
in
longrun {
inherit name;
run = ''
mkdir -p /run/xl2tpd
touch ${control}
exec ${xl2tpd}/bin/xl2tpd -D -p /run/xl2tpd/${name}.pid -c ${conf} -C ${control}
'';
notification-fd = 10;
timeout-up = 40 * 1000;
}
+8 -2
View File
@@ -9,6 +9,8 @@
{ interface, ppp-options }:
let
inherit (liminix.services) longrun;
lcp-echo-interval = 4;
lcp-echo-failure = 3;
name = "${interface.name}.pppoe";
ip-up = writeAshScript "ip-up" {} ''
. ${serviceFns}
@@ -37,15 +39,19 @@ let
"ipparam" name
"nodetach"
"usepeerdns"
"lcp-echo-interval" (builtins.toString lcp-echo-interval)
"lcp-echo-failure" (builtins.toString lcp-echo-failure)
"logfd" "2"
];
in
longrun {
inherit name;
run = ''
. ${serviceFns}
${ppp}/bin/pppd pty "${pppoe}/bin/pppoe -I $(output ${interface} ifname)" ${lib.concatStringsSep " " ppp-options'}
. ${serviceFns}
echo Starting pppoe, pppd pid is $$
exec ${ppp}/bin/pppd pty "${pppoe}/bin/pppoe -T ${builtins.toString (4 * lcp-echo-interval)} -I $(output ${interface} ifname)" ${lib.concatStringsSep " " ppp-options'}
'';
notification-fd = 10;
timeout-up = (10 + lcp-echo-failure * lcp-echo-interval) * 1000;
dependencies = [ interface ];
}
+1 -1
View File
@@ -2,7 +2,7 @@
let
svc = config.system.service;
cfg = config.profile.gateway;
inherit (lib) mkOption mkEnableOption mkIf mdDoc types optional optionals;
inherit (lib) mkOption mkEnableOption mkIf types;
inherit (pkgs) liminix serviceFns;
inherit (liminix.services) bundle oneshot;
hostaps =
+2 -2
View File
@@ -5,9 +5,9 @@
...
}: let
inherit (pkgs) liminix;
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (lib) mkOption types ;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.liminix.services) oneshot target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) serviceFns;
svc = config.system.service;
+2 -7
View File
@@ -1,11 +1,6 @@
{
config
, pkgs
, lib
, ...
}:
{ config, lib, ... }:
let
inherit (lib) mkIf mkEnableOption mkOption; # types concatStringsSep;
inherit (lib) mkIf mkEnableOption; # types concatStringsSep;
in {
options = {
boot = {
+39 -3
View File
@@ -1,4 +1,4 @@
{ config, pkgs, ... }:
{ config, pkgs, lib, ... }:
let
inherit (pkgs)
execline
@@ -6,14 +6,50 @@ let
s6-init-bin
s6-linux-init
stdenvNoCC;
inherit (lib.lists) unique concatMap;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) bundle;
inherit (pkgs.liminix.services) oneshot bundle;
s6-rc-db =
let
# In the default bundle we need to have all the services
# in config.services except for controlled services and
# anything that depends on one. But we do need the controllers
# themselves.
# So, find all required services and their transitive
# dependencies and their controllers. remove all controlled
# services and all services that have a controlled service as
# dependency
isControlled = s : s ? controller && s.controller != null;
deps = s : s.dependencies ++
lib.optional (isControlled s) s.controller;
flatDeps = s : [s] ++ concatMap flatDeps (deps s);
allServices = unique (concatMap flatDeps (builtins.attrValues config.services));
isDependentOnControlled = s :
isControlled s ||
(lib.lists.any isDependentOnControlled s.dependencies);
# all controlled services depend on this oneshot, which
# makes a list of them so we can identify them at runtime
controlled = oneshot {
name = "controlled";
up = ''
mkdir -p /run/services/controlled
for s in $(s6-rc-db -d dependencies controlled); do
touch /run/services/controlled/$s
done
'';
down = "rm -r /run/services/controlled";
};
defaultStart =
builtins.filter
(s: !(isDependentOnControlled s)) allServices;
defaultDefaultTarget = bundle {
name = "default";
contents = builtins.attrValues config.services;
contents = defaultStart ++ [controlled];
};
servicesAttrs = {
default = defaultDefaultTarget;
+1 -1
View File
@@ -1,4 +1,4 @@
{ config, pkgs, lib, ... } :
{ config, pkgs, ... } :
{
config = {
programs.busybox = {
+37
View File
@@ -0,0 +1,37 @@
# this is unlikely to be the final form or location of this code, it's
# an interim module which wraps the uevent-watch command
{ lib, pkgs, config, ... }:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
# inherit (pkgs.liminix.services) bundle;
in {
options = {
system.service.uevent-rule = mkOption {
description = "a service which starts other services based on device state (sysfs)";
type = liminix.lib.types.serviceDefn;
};
};
config = {
system.service.uevent-rule = liminix.callService ./rule.nix {
serviceName = mkOption {
description = "name of the service to run when the rule matches";
type = types.str;
};
terms = mkOption {
type = types.attrs;
example = {
devtype = "usb_device";
attrs.idVendor = "8086";
};
default = {};
};
symlink = mkOption {
description = "create symlink targeted on devpath";
type = types.nullOr types.str;
default = null;
};
};
};
}
+23
View File
@@ -0,0 +1,23 @@
{
liminix
, uevent-watch
, lib }:
{
serviceName, terms, symlink
}:
let
inherit (liminix.services) longrun;
inherit (lib.attrsets) collect mapAttrsRecursive;
inherit (lib.strings) concatStringsSep;
stringify = attrs :
concatStringsSep " "
(collect lib.isString
(mapAttrsRecursive
(path : value : "${concatStringsSep "." path}=${value}")
attrs));
termsString = stringify terms;
in longrun {
name = "watch-for-${serviceName}";
restart-on-upgrade = true;
run = "${uevent-watch}/bin/uevent-watch ${if symlink != null then "-n ${symlink}" else ""} -s ${serviceName} ${termsString}";
}
+4 -4
View File
@@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (pkgs) liminix;
-1
View File
@@ -1,7 +1,6 @@
{
liminix
, dropbear
, serviceFns
, lib
}:
p :
+1 -3
View File
@@ -1,7 +1,7 @@
# support for USB block devices and the common filesystems
# they're likely to provide
{lib, config, ... }:
{ config, ... }:
{
kernel = {
config = {
@@ -24,8 +24,6 @@
EXT4_FS = "y";
EXT4_USE_FOR_EXT2 = "y";
FS_ENCRYPTION = "y";
};
};
}
+11 -5
View File
@@ -16,11 +16,17 @@ let
inherit (lib)
concatStrings concatStringsSep mapAttrsToList mkOption types;
inherit (builtins) toString;
inherit (pkgs.pseudofile) dir symlink;
passwd-file =
let lines = mapAttrsToList (name: u: "${name}:${if u ? passwd then u.passwd else "!!"}:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n" )
config.users;
in concatStrings lines;
inherit (pkgs.pseudofile) dir;
passwd-file =
let
lines = mapAttrsToList (
name: u:
"${name}:${
if u ? passwd then u.passwd else "!!"
}:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n"
) config.users;
in
concatStrings lines;
group-file =
let lines = mapAttrsToList
(name: {gid, usernames ? []}:
-1
View File
@@ -13,7 +13,6 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{
+1 -2
View File
@@ -1,11 +1,10 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) stdenv wireless-regdb;
regulatory = stdenv.mkDerivation {
name = "regulatory.db";
phases = ["installPhase"];
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out
cp ${wireless-regdb}/lib/firmware/regulatory.db $out/
+31 -20
View File
@@ -46,7 +46,7 @@ in
extraPkgs // {
# liminix library functions
lim = {
parseInt = s : (builtins.fromTOML "r=${s}").r;
parseInt = s: (builtins.fromTOML "r=${s}").r;
};
# keep these alphabetical
@@ -74,7 +74,6 @@ extraPkgs // {
# should texinfo be in nativeBuildInputs instead of
# buildInputs?
texinfo = null;
};
# luarocks wants a cross-compiled cmake (which seems like a bug,
@@ -186,9 +185,12 @@ extraPkgs // {
# done. Do it the ugly way..
postPatch =
o.postPatch
+ (with final;
lib.optionalString (stdenv.buildPlatform != stdenv.hostPlatform)
"\nsed -i.bak 's/linux.*-mips/linux-mops/' Configure\n");
+ (
with final;
lib.optionalString (
stdenv.buildPlatform != stdenv.hostPlatform
) "\nsed -i.bak 's/linux.*-mips/linux-mops/' Configure\n"
);
});
pppBuild = prev.ppp;
@@ -200,13 +202,12 @@ extraPkgs // {
}); in q.override { nixosTestRunner = true; sdlSupport = false; };
rsyncSmall =
let r = prev.rsync.overrideAttrs(o: {
configureFlags = o.configureFlags ++ [
"--disable-openssl"
];
});
in r.override { openssl = null; };
let
r = prev.rsync.overrideAttrs (o: {
configureFlags = o.configureFlags ++ [ "--disable-openssl" ];
});
in
r.override { openssl = null; };
inherit s6;
s6-linux-init = prev.s6-linux-init.override {
@@ -224,14 +225,14 @@ extraPkgs // {
ubootQemuAarch64 = final.buildUBoot {
defconfig = "qemu_arm64_defconfig";
extraMeta.platforms = ["aarch64-linux"];
filesToInstall = ["u-boot.bin"];
extraMeta.platforms = [ "aarch64-linux" ];
filesToInstall = [ "u-boot.bin" ];
};
ubootQemuArm = final.buildUBoot {
defconfig = "qemu_arm_defconfig";
extraMeta.platforms = ["armv7l-linux"];
filesToInstall = ["u-boot.bin"];
extraMeta.platforms = [ "armv7l-linux" ];
filesToInstall = [ "u-boot.bin" ];
extraConfig = ''
CONFIG_CMD_UBI=y
CONFIG_CMD_UBIFS=y
@@ -245,8 +246,8 @@ extraPkgs // {
ubootQemuMips = final.buildUBoot {
defconfig = "malta_defconfig";
extraMeta.platforms = ["mips-linux"];
filesToInstall = ["u-boot.bin"];
extraMeta.platforms = [ "mips-linux" ];
filesToInstall = [ "u-boot.bin" ];
# define the prompt to be the same as arm{32,64} so
# we can use the same expect script for both
extraPatches = [ ./pkgs/u-boot/0002-virtio-init-for-malta.patch ];
@@ -268,9 +269,20 @@ extraPkgs // {
CONFIG_MIPS_BOOT_FDT=y
CONFIG_OF_LIBFDT=y
CONFIG_OF_STDOUT_VIA_ALIAS=y
'';
'';
};
libusb1 =
let u = prev.libusb1.overrideAttrs(o: {
# don't use gcc libatomic because it vastly increases the
# closure size
preConfigure = "sed -i.bak /__atomic_fetch_add_4/c\: configure.ac";
});
in u.override {
enableUdev = final.stdenv.buildPlatform == final.stdenv.hostPlatform;
withDocs = false;
};
util-linux-small = prev.util-linux.override {
ncursesSupport = false;
pamSupport = false;
@@ -279,5 +291,4 @@ extraPkgs // {
translateManpages = false;
capabilitiesSupport = false;
};
}
+6 -6
View File
@@ -1,10 +1,10 @@
{
fennel
, stdenv
, linotify
, lua
, lualinux
, cpio
fennel,
stdenv,
linotify,
lua,
lualinux,
cpio,
}:
let pname = "anoia";
in stdenv.mkDerivation {
+58 -57
View File
@@ -1,7 +1,4 @@
{
callPackage
, lib
}:
{ callPackage, lib }:
let
typeChecked = caller: type: value:
let
@@ -11,11 +8,11 @@ let
in (mergeDefinitions [] type' defs).mergedValue;
in {
liminix = {
builders = {
squashfs = callPackage ./liminix-tools/builders/squashfs.nix {};
dtb = callPackage ./kernel/dtb.nix {};
uimage = callPackage ./kernel/uimage.nix {};
kernel = callPackage ./kernel {};
builders = {
squashfs = callPackage ./liminix-tools/builders/squashfs.nix { };
dtb = callPackage ./kernel/dtb.nix { };
uimage = callPackage ./kernel/uimage.nix { };
kernel = callPackage ./kernel { };
};
callService = path : parameters :
let pkg = callPackage path {};
@@ -27,7 +24,7 @@ in {
s = pkg (checkTypes parameters
(builtins.removeAttrs args ["dependencies"]));
in s.overrideAttrs (o: {
dependencies = (builtins.map (d: d.name) dependencies) ++ o.dependencies;
dependencies = dependencies ++ o.dependencies;
buildInputs = dependencies ++ o.buildInputs;
});
};
@@ -49,68 +46,72 @@ in {
};
inherit typeChecked;
};
networking = callPackage ./liminix-tools/networking {};
services = callPackage ./liminix-tools/services {};
networking = callPackage ./liminix-tools/networking { };
services = callPackage ./liminix-tools/services { };
};
# please keep the rest of this list alphabetised :-)
anoia = callPackage ./anoia {};
devout = callPackage ./devout {};
fennel = callPackage ./fennel {};
fennelrepl = callPackage ./fennelrepl {};
firewallgen = callPackage ./firewallgen {};
firmware-utils = callPackage ./firmware-utils {};
gen_init_cpio = callPackage ./gen_init_cpio {};
go-l2tp = callPackage ./go-l2tp {};
hi = callPackage ./hi {};
ifwait = callPackage ./ifwait {};
initramfs-peek = callPackage ./initramfs-peek {};
kernel-backport = callPackage ./kernel-backport {};
kmodloader = callPackage ./kmodloader {};
levitate = callPackage ./levitate {};
libubootenv = callPackage ./libubootenv {};
linotify = callPackage ./linotify {};
lualinux = callPackage ./lualinux {};
anoia = callPackage ./anoia { };
devout = callPackage ./devout { };
fennel = callPackage ./fennel { };
fennelrepl = callPackage ./fennelrepl { };
firewallgen = callPackage ./firewallgen { };
firmware-utils = callPackage ./firmware-utils { };
gen_init_cpio = callPackage ./gen_init_cpio { };
go-l2tp = callPackage ./go-l2tp { };
hi = callPackage ./hi { };
ifwait = callPackage ./ifwait { };
initramfs-peek = callPackage ./initramfs-peek { };
kernel-backport = callPackage ./kernel-backport { };
kmodloader = callPackage ./kmodloader { };
levitate = callPackage ./levitate { };
libubootenv = callPackage ./libubootenv { };
linotify = callPackage ./linotify { };
lualinux = callPackage ./lualinux { };
# we need to build real lzma instead of using xz, because the lzma
# decoder in u-boot doesn't understand streaming lzma archives
# ("Stream with EOS marker is not supported") and xz can't create
# non-streaming ones. See
# https://sourceforge.net/p/squashfs/mailman/message/26599379/
lzma = callPackage ./lzma {};
lzma = callPackage ./lzma { };
mac80211 = callPackage ./mac80211 {};
zyxel-bootconfig = callPackage ./zyxel-bootconfig {};
min-collect-garbage = callPackage ./min-collect-garbage {};
min-copy-closure = callPackage ./min-copy-closure {};
minisock = callPackage ./minisock {};
nellie = callPackage ./nellie {};
netlink-lua = callPackage ./netlink-lua {};
odhcp-script = callPackage ./odhcp-script {};
odhcp6c = callPackage ./odhcp6c {};
openwrt = callPackage ./openwrt {};
ppp = callPackage ./ppp {};
pppoe = callPackage ./pppoe {};
preinit = callPackage ./preinit {};
pseudofile = callPackage ./pseudofile {};
routeros = callPackage ./routeros {};
run-liminix-vm = callPackage ./run-liminix-vm {};
s6-init-bin = callPackage ./s6-init-bin {};
s6-rc-database = callPackage ./s6-rc-database {};
mac80211 = callPackage ./mac80211 { };
zyxel-bootconfig = callPackage ./zyxel-bootconfig { };
min-collect-garbage = callPackage ./min-collect-garbage { };
min-copy-closure = callPackage ./min-copy-closure { };
minisock = callPackage ./minisock { };
nellie = callPackage ./nellie { };
netlink-lua = callPackage ./netlink-lua { };
odhcp-script = callPackage ./odhcp-script { };
odhcp6c = callPackage ./odhcp6c { };
openwrt = callPackage ./openwrt { };
ppp = callPackage ./ppp { };
pppoe = callPackage ./pppoe { };
preinit = callPackage ./preinit { };
pseudofile = callPackage ./pseudofile { };
routeros = callPackage ./routeros { };
run-liminix-vm = callPackage ./run-liminix-vm { };
s6-init-bin = callPackage ./s6-init-bin { };
s6-rc-database = callPackage ./s6-rc-database { };
s6-rc-round-robin = callPackage ./s6-rc-round-robin { };
s6-rc-up-tree = callPackage ./s6-rc-up-tree { };
# schnapps is written by Turris and provides a high-level interface
# to btrfs snapshots. It may be useful on the Turris Omnia to
# install Liminix while retaining the ability to rollback to the
# vendor OS, or even to derisk Liminix updates on that device
schnapps = callPackage ./schnapps {};
schnapps = callPackage ./schnapps { };
serviceFns = callPackage ./service-fns {};
swconfig = callPackage ./swconfig {};
systemconfig = callPackage ./systemconfig {};
tufted = callPackage ./tufted {};
uevent-watch = callPackage ./uevent-watch {};
writeAshScript = callPackage ./write-ash-script {};
writeFennel = callPackage ./write-fennel {};
writeFennelScript = callPackage ./write-fennel-script {};
serviceFns = callPackage ./service-fns { };
swconfig = callPackage ./swconfig { };
systemconfig = callPackage ./systemconfig { };
tufted = callPackage ./tufted { };
uevent-watch = callPackage ./uevent-watch { };
usb-modeswitch = callPackage ./usb-modeswitch { };
writeAshScript = callPackage ./write-ash-script { };
writeAshScriptBin = callPackage ./write-ash-script/bin.nix { };
writeFennel = callPackage ./write-fennel { };
writeFennelScript = callPackage ./write-fennel-script { };
}
+7 -8
View File
@@ -1,12 +1,11 @@
{
lua
, nellie
, writeFennel
, anoia
, fennel
, stdenv
, fennelrepl
, lualinux
nellie,
writeFennel,
anoia,
fennel,
stdenv,
fennelrepl,
lualinux,
}:
stdenv.mkDerivation {
name = "devout";
+71 -22
View File
@@ -1,3 +1,4 @@
(local { : dirname : merge } (require :anoia))
(local ll (require :lualinux))
(local {
: AF_LOCAL
@@ -21,28 +22,62 @@
(..
(string.format "%s@%s\0" e.action e.path)
(table.concat
(icollect [k v (pairs e.attributes)]
(icollect [k v (pairs e.properties)]
(string.format "%s=%s" (string.upper k) v ))
"\n")))
(fn attrs-match? [event expected]
(accumulate [match? true
name value (pairs expected)]
(and match? (= value (event:attr name)))))
(fn ancestor-attrs-match? [event expected]
(accumulate [match? true
name value (pairs expected)]
(and match? (= value (event:ancestor-attr name)))))
(fn event-matches? [e terms]
(accumulate [match? true
name value (pairs terms)]
(and match? (= value (. e.attributes name)))))
(and match?
(case name
:attr (attrs-match? e value)
:attrs (ancestor-attrs-match? e value)
other (= value (. e.properties name))))))
(fn read-if-exists [pathname]
(match (ll.open pathname 0 0)
fd (let [s (ll.read fd 4096)
s1 (string.gsub s "[ \n]*(.-)[ \n]*" "%1")]
(ll.close fd)
s1)
nil nil))
(fn event-ancestor-attr [event name]
(fn walk-up [sys-path path name]
(when path
(or (read-if-exists (.. sys-path "/" path "/" name))
(walk-up sys-path (dirname path) name))))
(walk-up event.sys-path event.path name))
(fn event-attr [event name]
(read-if-exists (.. event.sys-path "/" event.path "/" name)))
(fn parse-event [s]
(let [at (string.find s "@" 1 true)
(nl nxt) (string.find s "\0" 1 true)
attributes
properties
(collect [k v (string.gmatch
(string.sub s (+ 1 nxt))
"(%g-)=(%g+)")]
(k:lower) v)]
{ : attributes
{ : properties
:path (string.sub s (+ at 1) (- nl 1))
:action (string.sub s 1 (- at 1))
:format format-event
:matches? event-matches?
:attr event-attr
:ancestor-attr event-ancestor-attr
}))
(fn find-in-database [db terms]
@@ -52,24 +87,28 @@
(doto found (table.insert e))
found)))
(fn record-event [db subscribers str]
(let [e (parse-event str)]
(match e.action
:add (tset db e.path e)
:change (tset db e.path e)
;; should we do something for bind?
:remove (tset db e.path nil)
)
(each [_ { : terms : callback } (pairs subscribers)]
(if (e:matches? terms) (callback e)))
e))
(fn record-event [db subscribers e]
(match e.action
:add (tset db e.path e)
:change (tset db e.path e)
;; should we do something for bind?
:remove (tset db e.path nil)
)
(each [_ { : terms : callback } (pairs subscribers)]
(if (e:matches? terms) (callback e)))
e)
(fn database []
(fn database [options]
(let [db {}
subscribers []]
subscribers []
{ : sys-path } (or options {:sys-path "/sys" })]
{
:find (fn [_ terms] (find-in-database db terms))
:add (fn [_ event-string] (when event-string (record-event db subscribers event-string)))
:add (fn [_ event-string]
(when event-string
(let [e (doto (parse-event event-string)
(tset :sys-path sys-path))]
(record-event db subscribers e))))
:at-path (fn [_ path] (. db path))
:subscribe (fn [_ id callback terms]
(let [past-events (find-in-database db terms)]
@@ -108,8 +147,16 @@
(values fd (if (> revent 0) revent nil)))))
(fn parse-terms [str]
(collect [n (string.gmatch (str:gsub "\n+$" "") "([^ ]+)")]
(string.match n "(.-)=(.+)")))
(let [keys {}
attr {}
attrs {}]
(each [term (string.gmatch (str:gsub "\n+$" "") "([^ ]+)")]
(let [(k v) (string.match term "(.-)=(.+)")]
(match (string.match k "(.+)%.(.+)")
("attrs" a) (tset attrs a v)
("attr" a) (tset attr a v)
nil (tset keys k v))))
(merge keys {: attr : attrs})))
(fn handle-client [db client]
(match (ll.read client)
@@ -131,7 +178,6 @@
AF_NETLINK 0 0 groups)))
(nil errno) (values nil errno)))
(fn event-loop []
(let [fds {}]
{
@@ -170,4 +216,7 @@
(ll.poll pollfds 5000)
(loop:feed (unpack-pollfds pollfds))))))
{ : database : run : event-loop : parse-event }
{ : database : run : event-loop : parse-event
: parse-terms
}
@@ -0,0 +1 @@
0x0c0330

Some files were not shown because too many files have changed in this diff Show More