1
0

Compare commits

...

4 Commits

Author SHA1 Message Date
0a6af46364 support dhcp static leases 2023-09-04 22:08:07 +01:00
a24c2a23a0 whitespace 2023-09-04 22:06:15 +01:00
9e52faa0b6 remove unused imports 2023-09-04 22:05:42 +01:00
3bdc986dd7 extract "mount filesystem" to module 2023-09-04 21:17:52 +01:00
7 changed files with 211 additions and 25 deletions

View File

@ -2141,8 +2141,8 @@ Thu Aug 31 23:53:54 BST 2023
- packet forwarding
- and arhcive
- rsync
- watchdog
- mount
- [done] watchdog
- [done] mount
- nftables syntax error
- tidy up the dependency handling in serviceDefn build
(interface is fine, implementation is a bit brutal)
@ -2151,3 +2151,99 @@ Thu Aug 31 23:53:54 BST 2023
- [done] ntp is not setting the time
- static dhcp(6) lease support reqd for dogfooding
Sat Sep 2 21:35:41 BST 2023
Considerations for "mount" service: each filesystem needs to depend on
any mount points for its parent directories, and maybe also on other
services (e.g. filesystem modules, network devices, routes)
mountpoints = {
mnt = {
media = svc.mountpoint.build {
fstype = "msdos";
device = "/dev/sda1";
options = [ ...];
};
archive = svc.mountpoint.build {
fstype = "ext4";
device = "/dev/sda2";
options = [ ...];
mountpoints = {
remote = svc.mountpoint.build {
fstype = "nfs";
device = "doc.ic.ac.uk:/public";
};
};
};
};
}
services.somethingelse = svc.ftpd.build {
# ...
dependencies = [ mountpoints.mnt.archive ];
}
what don't we like about this? we have to walk the nested attrset in a
weird way, because the services may contain other mountpoints. Maybe
just keep it simple and do
services.mountpoints = bundle {
name = "mountpoints";
contents = [
svc.mountpoint.build {
device = "/dev/sda2"; fstype = "ext4"; directory = "/mnt/isos";
};
svc.mountpoint.build {
device = "/dev/sdb1"; fstype = "msdos"; directory = "/mnt/backup";
dependencies = [ load-vfat-module ];
};
];
}
Sun Sep 3 17:34:36 BST 2023
how to dogfood
DHCP6 server: static lease support
DHCP client and acquire-{lan-prefix,wan-address}
The emergency boot thingy in glinet u-boot won't help because it
expects to flash from its tftp request instead of booting it. So we
could use kexec instead except that the openwrt install doesn't have
it. So we could swap the hardware devices, the only downside of that
being that then I don't have a test system any more. Or we could YOLO it.
Sun Sep 3 22:11:02 BST 2023
I think we should rejigger the documentation ...
- "getting started": worked example, building and installing Liminix
with a very simple config (wifi AP with ssh daemon)
- using modules
- link to module reference
- creating custom services
- longrun or oneshot
- dependencies
- outputs
- creating your own modules
- hacking on Liminix itself
- contributing
- external links and resources
- module reference
- hardware device reference
---
I think we might rename wlan_24 to wlan and wlan_5 to wlan1.
This is on the assumption that almost no device is 5GHz only, so
would make it easier to write a basic wlan example that works
both on 2.4GHz boards and dual radio boards

View File

@ -30,6 +30,7 @@ in rec {
../modules/vlan
../modules/ssh
../modules/watchdog
../modules/mount
];
hostname = "arhcive";
@ -101,27 +102,18 @@ in rec {
};
programs.busybox = {
applets = ["blkid" "lsusb" "findfs" "tar"];
applets = ["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 = ''
while ! findfs LABEL=backup-disk; do
echo waiting for backup-disk
sleep 1
done
mount -t ext4 LABEL=backup-disk /srv
'';
down = "umount /srv";
services.mount_external_disk = svc.mount.build {
device = "LABEL=backup-disk";
mountpoint = "/srv";
fstype = "ext4";
};
services.rsync =

View File

@ -9,13 +9,8 @@
{ config, pkgs, lib, ... } :
let
secrets = import ./rotuer-secrets.nix;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs)
dropbear
ifwait
writeText
writeFennelScript
serviceFns;
inherit (pkgs.liminix.services) oneshot longrun;
inherit (pkgs) serviceFns;
svc = config.system.service;
wirelessConfig = {
country_code = "GB";
@ -131,6 +126,7 @@ in rec {
rm -rf /run/service-state/${name}/
'';
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in dir {
@ -139,7 +135,6 @@ in rec {
};
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.wan} address)";
target = "default";

View File

@ -42,6 +42,37 @@ in {
ranges = mkOption {
type = types.listOf types.str;
};
hosts = mkOption {
type = types.attrsOf (types.submodule {
options = {
mac = mkOption {
description = ''
MAC or other hardware address to match on. For Ethernet
this is a 48 bit address represented as colon-separated
hex bytes, or "id:clientid" to match a presented
client id (IPv6 DUID)
'';
type = types.str;
example = "01:20:31:4a:50";
};
v4 = mkOption {
description = "IPv4 address to assign to this client";
example = "192.0.2.1";
type = types.str;
};
v6 = mkOption {
type = types.listOf types.str;
description = "IPv6 addresses or interface-ids to assign to this client";
default = [];
example = [ "fe80::42:1eff:fefd:b341" "::1234"];
};
leasetime = mkOption {
type = types.int;
default = 86400;
};
};
});
};
domain = mkOption {
# this can be given multiple times so probably should be
# domains plural and list of string

View File

@ -10,13 +10,17 @@
, domain
, group
, ranges
, hosts
, upstreams
, resolvconf
}:
let
name = "${interface.name}.dnsmasq";
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep;
inherit (lib) concatStrings concatStringsSep mapAttrsToList;
hostOpt = name : { mac, v4, v6, leasetime } @ attrs:
let v6s = concatStrings (map (a : ",[${a}]") v6);
in "--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}";
in
longrun {
inherit name;
@ -33,6 +37,7 @@ longrun {
--keep-in-foreground \
--dhcp-authoritative \
${if resolvconf != null then "--resolv-file=$(output_path ${resolvconf} resolv.conf)" else "--no-resolv"} \
${lib.concatStringsSep " " (mapAttrsToList hostOpt hosts)} \
--no-hosts \
--log-dhcp \
--enable-ra \

49
modules/mount/default.nix Normal file
View File

@ -0,0 +1,49 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
mkBoolOption = description : mkOption {
type = types.bool;
inherit description;
default = true;
};
in {
options = {
system.service.mount = mkOption {
type = liminix.lib.types.serviceDefn;
};
};
config.system.service = {
mount = liminix.callService ./service.nix {
device = mkOption {
type = types.str;
example = "/dev/sda1";
};
mountpoint = mkOption {
type = types.str;
example = "/mnt/media";
};
options = mkOption {
type = types.listOf types.str;
default = [];
example = ["noatime" "ro" "sync"];
};
fstype = mkOption {
type = types.str;
default = "auto";
example = "vfat";
};
};
};
config.programs.busybox = {
applets = ["blkid" "findfs"];
options = {
FEATURE_BLKID_TYPE = "y";
FEATURE_MOUNT_FLAGS = "y";
FEATURE_MOUNT_LABEL = "y";
FEATURE_VOLUMEID_EXT = "y";
};
};
}

18
modules/mount/service.nix Normal file
View File

@ -0,0 +1,18 @@
{
liminix
, lib
}:
{ device, mountpoint, options, fstype }:
let
inherit (liminix.services) oneshot;
in oneshot {
name = "mount.${lib.escapeURL mountpoint}";
up = ''
while ! findfs ${device}; do
echo waiting for device ${device}
sleep 1
done
mount -t ${fstype} -o ${lib.concatStringsSep "," options} ${device} ${mountpoint}
'';
down = "umount ${mountpoint}";
}