Compare commits
4 Commits
83092b7b73
...
0a6af46364
Author | SHA1 | Date | |
---|---|---|---|
0a6af46364 | |||
a24c2a23a0 | |||
9e52faa0b6 | |||
3bdc986dd7 |
100
THOUGHTS.txt
100
THOUGHTS.txt
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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
49
modules/mount/default.nix
Normal 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
18
modules/mount/service.nix
Normal 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}";
|
||||
}
|
Loading…
Reference in New Issue
Block a user