1
0

nixfmt-rfc-style

There is nothing in this commit except for the changes made by
nix-shell -p nixfmt-rfc-style --run "nixfmt ."

If this has mucked up your open branches then sorry about that. You
can probably nixfmt them to match before merging
This commit is contained in:
Daniel Barlow 2025-02-10 21:55:08 +00:00
parent 13cc5a8992
commit 7e2b0068e6
211 changed files with 6049 additions and 4355 deletions

View File

@ -1,8 +1,21 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.bordervm;
inherit (lib) mkOption mkEnableOption mdDoc types optional optionals;
in {
inherit (lib)
mkOption
mkEnableOption
mdDoc
types
optional
optionals
;
in
{
options.bordervm = {
keys = mkOption {
type = types.listOf types.str;
@ -113,7 +126,8 @@ in {
host.port = 2222;
guest.address = "10.0.2.15";
guest.port = 22;
}];
}
];
qemu = {
networkingOptions = [ ];
options =
@ -139,12 +153,18 @@ in {
services.tang = {
enable = true;
ipAddressAllow = [ "10.0.0.0/24" "0.0.0.0/0" ];
ipAddressAllow = [
"10.0.0.0/24"
"0.0.0.0/0"
];
};
environment.systemPackages =
let wireshark-nogui = pkgs.wireshark.override { withQt = false ; };
in with pkgs; [
let
wireshark-nogui = pkgs.wireshark.override { withQt = false; };
in
with pkgs;
[
tcpdump
wireshark-nogui
socat
@ -157,10 +177,17 @@ in {
security.sudo.wheelNeedsPassword = false;
networking = {
hostName = "border";
firewall = { enable = false; };
firewall = {
enable = false;
};
interfaces.eth1 = {
useDHCP = false;
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}];
ipv4.addresses = [
{
address = "10.0.0.1";
prefixLength = 24;
}
];
};
nat = {
enable = true;

8
ci.nix
View File

@ -17,7 +17,8 @@ let
"belkin-rt3200"
];
vanilla = ./vanilla-configuration.nix;
for-device = name:
for-device =
name:
(import liminix {
inherit borderVmConf;
device = import (liminix + "/devices/${name}");
@ -73,8 +74,9 @@ let
'';
};
};
in jobs //
{
in
jobs
// {
all = pkgs.mkShell {
name = "all tests";
contents = pkgs.lib.collect pkgs.lib.isDerivation jobs;

View File

@ -27,7 +27,12 @@ let
modulesPath = builtins.toString ./modules;
};
modules = [
{ _module.args = { inherit pkgs; inherit (pkgs) lim; }; }
{
_module.args = {
inherit pkgs;
inherit (pkgs) lim;
};
}
./modules/hardware.nix
./modules/base.nix
./modules/busybox.nix
@ -47,7 +52,8 @@ let
};
config = eval.config;
borderVm = ((import <nixpkgs/nixos/lib/eval-config.nix>) {
borderVm =
((import <nixpkgs/nixos/lib/eval-config.nix>) {
system = builtins.currentSystem;
modules = [
{
@ -62,15 +68,18 @@ let
borderVmConf
];
}).config.system;
in {
in
{
outputs = config.system.outputs // {
default = config.system.outputs.${config.hardware.defaultOutput};
optionsJson =
let o = import ./doc/extract-options.nix {
let
o = import ./doc/extract-options.nix {
inherit pkgs eval;
lib = pkgs.lib;
};
in pkgs.writeText "options.json" (builtins.toJSON o);
in
pkgs.writeText "options.json" (builtins.toJSON o);
};
# this is just here as a convenience, so that we can get a

View File

@ -115,8 +115,16 @@
};
};
module = {pkgs, config, lib, lim, ... }:
let inherit (lib) mkIf;
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (lib) mkIf;
firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = [ "installPhase" ];
@ -126,7 +134,8 @@
'';
};
openwrt = pkgs.openwrt_24_10;
in {
in
{
imports = [
../../modules/arch/aarch64.nix
../../modules/outputs/tftpboot.nix
@ -240,7 +249,8 @@
};
rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
@ -253,10 +263,14 @@
hardware =
let
mac80211 = pkgs.kmodloader.override {
targets = ["mt7615e" "mt7915e"];
targets = [
"mt7615e"
"mt7915e"
];
inherit (config.system.outputs) kernel;
};
in {
in
{
ubi = {
minIOSize = "2048";
logicalEraseBlockSize = "126976";
@ -294,7 +308,8 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
in
rec {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };

View File

@ -30,14 +30,17 @@
inherit (config.system.outputs) kernel;
targets = [ "mac80211_hwsim" ];
};
in {
in
{
defaultOutput = "vmroot";
rootDevice = "/dev/mtdblock0";
dts.src = pkgs.lib.mkDefault null;
flash.eraseBlockSize = 65536;
networkInterfaces =
let inherit (config.system.service.network) link;
in {
let
inherit (config.system.service.network) link;
in
{
wan = link.build {
devpath = "/devices/pci0000:00/0000:00:13.0/virtio0";
ifname = "wan";

View File

@ -53,7 +53,14 @@
'';
module = {pkgs, config, lim, lib, ... }:
module =
{
pkgs,
config,
lim,
lib,
...
}:
let
inherit (lib) mkIf;
openwrt = pkgs.openwrt;
@ -74,7 +81,10 @@
'';
};
mac80211 = pkgs.kmodloader.override {
targets = ["ath9k" "ath10k_pci"];
targets = [
"ath9k"
"ath10k_pci"
];
inherit (config.system.outputs) kernel;
dependencies = [ ath10k_cal_data ];
};
@ -82,7 +92,8 @@
let
offset = lim.parseInt "0x5000";
size = lim.parseInt "0x844";
in pkgs.liminix.services.oneshot rec {
in
pkgs.liminix.services.oneshot rec {
name = "ath10k_cal_data";
up = ''
part=$(basename $(dirname $(grep -l art /sys/class/mtd/*/name)))
@ -94,7 +105,8 @@
'';
};
inherit (pkgs.pseudofile) dir symlink;
in {
in
{
imports = [
../../modules/network
../../modules/arch/mipseb.nix
@ -127,8 +139,10 @@
};
networkInterfaces =
let inherit (config.system.service.network) link;
in {
let
inherit (config.system.service.network) link;
in
{
lan = link.build {
ifname = "lan";
devpath = "/devices/platform/ahb/1a000000.eth";
@ -143,7 +157,10 @@
};
wlan5 = link.build {
ifname = "wlan1";
dependencies = [ ath10k_cal_data mac80211 ];
dependencies = [
ath10k_cal_data
mac80211
];
};
};
};

View File

@ -44,14 +44,22 @@
'';
module = { pkgs, config, lib, lim, ...}:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override {
targets = [ "rt2800soc" ];
inherit (config.system.outputs) kernel;
};
in {
in
{
imports = [
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
@ -90,7 +98,8 @@
let
inherit (config.system.service.network) link;
inherit (config.system.service) vlan;
in rec {
in
rec {
eth = link.build { ifname = "eth0"; };
# lan and wan ports are both behind a switch on eth0
lan = vlan.build {
@ -119,7 +128,8 @@
${openwrt.applyPatches.ramips}
${openwrt.applyPatches.rt2x00}
'';
config = {
config =
{
RALINK = "y";
PCI = "y";
@ -157,7 +167,8 @@
LEDS_CLASS = "y"; # required by rt2x00lib
PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
}
// lib.optionalAttrs (config.system.service ? vlan) {
SWCONFIG = "y";
};
conditionalConfig = {

View File

@ -37,7 +37,14 @@
'';
module = { pkgs, config, lib, lim, ...}:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
@ -51,7 +58,8 @@
url = "https://github.com/openwrt/mt76/raw/f24b56f935392ca1d35fae5fd6e56ef9deda4aad/firmware/mt7628_e2.bin";
hash = "sha256:1dkhfznmdz6s50kwc841x3wj0h6zg6icg5g2bim9pvg66as2vmh9";
};
in {
in
{
imports = [
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
@ -99,8 +107,12 @@
'';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; dependencies = [swconfig]; };
in
rec {
eth = link.build {
ifname = "eth0";
dependencies = [ swconfig ];
};
# lan and wan ports are both behind a switch on eth0
lan = vlan.build {
ifname = "eth0.1";
@ -129,7 +141,8 @@
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
'';
config = {
config =
{
RALINK = "y";
PCI = "y";
@ -175,9 +188,11 @@
EARLY_PRINTK = "y";
PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
}
// lib.optionalAttrs (config.system.service ? vlan) {
SWCONFIG = "y";
} // lib.optionalAttrs (config.system.service ? watchdog) {
}
// lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};

View File

@ -79,7 +79,14 @@
};
};
module = {pkgs, config, lib, lim, ... }:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
openwrt = pkgs.openwrt_24_10;
mediatek-firmware = pkgs.stdenv.mkDerivation {
@ -100,7 +107,8 @@
cp ${pkgs.linux-firmware}/lib/firmware/airoha/* $out
'';
};
in {
in
{
imports = [
../../modules/arch/aarch64.nix
../../modules/outputs/tftpboot.nix
@ -113,7 +121,8 @@
extraPatchPhase = ''
${openwrt.applyPatches.mediatek}
'';
config = {
config =
{
NET = "y"; # unlock NET_XGRESS
SERIAL_8250 = "y"; # unlock SERIAL_8250_FSL
SERIAL_8250_CONSOLE = "y"; # to get the serial console
@ -593,7 +602,8 @@
# ???
AQUANTIA_PHY = "m";
MT798X_WMAC = "y";
} // lib.optionalAttrs (config.system.service ? watchdog) {
}
// lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
@ -617,7 +627,8 @@
};
rootfsType = lib.mkDefault "ubifs"; # override this if you are building tftpboot
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
@ -647,7 +658,8 @@
];
inherit (config.system.outputs) kernel;
};
in {
in
{
# from OEM bootlog
# Creating 4 MTD partitions on "spi0.0":
# 0x000000000000-0x000000040000 : "bl2-nor"
@ -698,7 +710,6 @@
maxLEBcount = "1024"; # guessing
};
defaultOutput = "ubimage";
loadAddress = lim.parseInt "0x44000000";
entryPoint = lim.parseInt "0x44000000";
@ -717,7 +728,8 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
in
rec {
eth0 = link.build {
ifname = "eth0";
dependencies = [ phy ];

View File

@ -26,7 +26,9 @@
# this device is described by the "qemu" device
installer = "vmroot";
module = { config, lim, ... }: {
module =
{ config, lim, ... }:
{
imports = [
../../modules/arch/aarch64.nix
../families/qemu.nix
@ -43,7 +45,11 @@
boot.commandLine = [
"console=ttyAMA0,38400"
];
hardware = let addr = lim.parseInt "0x40010000"; in {
hardware =
let
addr = lim.parseInt "0x40010000";
in
{
loadAddress = addr;
entryPoint = addr;
};

View File

@ -24,7 +24,9 @@
'';
installer = "vmroot";
module = { config, lim, ... }: {
module =
{ config, lim, ... }:
{
imports = [
../../modules/arch/arm.nix
../families/qemu.nix
@ -45,7 +47,11 @@
boot.commandLine = [
"console=ttyAMA0"
];
hardware = let addr = lim.parseInt "0x40008000"; in {
hardware =
let
addr = lim.parseInt "0x40008000";
in
{
loadAddress = addr;
entryPoint = addr;
};

View File

@ -36,7 +36,14 @@
in the Development manual.
'';
module = { config, lib, lim, ... }: {
module =
{
config,
lib,
lim,
...
}:
{
imports = [
../../modules/arch/mipseb.nix
../families/qemu.nix
@ -55,8 +62,10 @@
};
hardware =
# from arch/mips/mti-malta/Platform:load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
let addr = lim.parseInt "0x80100000";
in {
let
addr = lim.parseInt "0x80100000";
in
{
loadAddress = addr;
entryPoint = addr;

View File

@ -33,8 +33,16 @@
};
};
module = {pkgs, config, lib, lim, ... }:
let firmware = pkgs.stdenv.mkDerivation {
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
firmware = pkgs.stdenv.mkDerivation {
name = "wlan-firmware";
phases = [ "installPhase" ];
installPhase = ''
@ -42,7 +50,8 @@
cp ${pkgs.linux-firmware}/lib/firmware/mediatek/{mt7915,mt7615,mt7622}* $out
'';
};
in {
in
{
imports = [
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
@ -53,7 +62,8 @@
extraPatchPhase = ''
${pkgs.openwrt.applyPatches.ramips}
'';
config = {
config =
{
# Initially taken from openwrt's ./target/linux/ramips/mt7621/config-5.15,
# then tweaked here and there
ARCH_32BIT_OFF_T = "y";
@ -316,7 +326,8 @@
ZLIB_INFLATE = "y";
ZSTD_COMPRESS = "y";
ZSTD_DECOMPRESS = "y";
} // lib.optionalAttrs (config.system.service ? watchdog) {
}
// lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
@ -340,7 +351,8 @@
};
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
lib = dir {
@ -359,7 +371,8 @@
];
inherit (config.system.outputs) kernel;
};
in {
in
{
# from OEM bootlog (openwrt wiki):
# 4 cmdlinepart partitions found on MTD device raspi
# Creating 4 MTD partitions on "raspi":
@ -414,7 +427,8 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
in
rec {
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };

View File

@ -153,7 +153,14 @@
};
};
module = {pkgs, config, lib, lim, ... }:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
@ -167,7 +174,8 @@
done
'';
};
in {
in
{
imports = [
../../modules/arch/arm.nix
../../modules/outputs/tftpboot.nix
@ -204,7 +212,6 @@
EXPERT = "y";
ALLOW_DEV_COREDUMP = "n";
# dts has a compatible for this but dmesg is not
# showing it
EEPROM_AT24 = "y"; # atmel,24c64
@ -312,7 +319,8 @@
cp -r ${pkgs.linux-firmware}/lib/firmware/ath10k/QCA988X $out
'';
};
in dir {
in
dir {
lib = dir {
firmware = dir {
ath10k = symlink firmware;
@ -320,10 +328,12 @@
};
etc = dir {
"fw_env.config" =
let f = pkgs.writeText "fw_env.config" ''
let
f = pkgs.writeText "fw_env.config" ''
/dev/mtd/by-name/u-boot-env 0x0 0x10000 0x10000
'';
in symlink f;
in
symlink f;
};
};
@ -333,12 +343,17 @@
compressRoot = true;
};
hardware = let
hardware =
let
mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
targets = ["ath9k" "ath10k_pci"];
targets = [
"ath9k"
"ath10k_pci"
];
};
in {
in
{
defaultOutput = "updater";
loadAddress = lim.parseInt "0x00800000"; # "0x00008000";
entryPoint = lim.parseInt "0x00800000"; # "0x00008000";
@ -354,7 +369,8 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
in rec {
in
rec {
en70000 = link.build {
# in armada-38x.dtsi this is eth0.
# It's connected to port 5 of the 88E6176 switch

View File

@ -101,7 +101,14 @@
'';
module = { pkgs, config, lib, lim, ...}:
module =
{
pkgs,
config,
lib,
lim,
...
}:
let
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
@ -123,7 +130,8 @@
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin";
hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg=";
};
in {
in
{
imports = [
# We include it to ensure the bridge functionality
# is available on the target kernel.
@ -201,7 +209,8 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
in {
in
{
eth = link.build { ifname = "eth0"; };
lan = link.build { ifname = "lan"; };
wlan0 = link.build {
@ -253,7 +262,8 @@
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
'';
config = {
config =
{
RALINK = "y";
PCI = "y";
@ -348,9 +358,11 @@
LEDS_BRIGHTNESS_HW_CHANGED = "y";
PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
}
// lib.optionalAttrs (config.system.service ? vlan) {
SWCONFIG = "y";
} // lib.optionalAttrs (config.system.service ? watchdog) {
}
// lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};

View File

@ -1,4 +1,8 @@
{ eval, lib, pkgs }:
{
eval,
lib,
pkgs,
}:
let
conf = eval.config;
rootDir = builtins.toPath ./..;
@ -7,21 +11,24 @@ let
inherit name;
description = opt.description or null;
default = opt.default or null;
visible =
if (opt ? visible && opt.visible == "shallow")
then true
else opt.visible or true;
visible = if (opt ? visible && opt.visible == "shallow") then true else opt.visible or true;
readOnly = opt.readOnly or false;
type = opt.type.description or "unspecified";
};
spliceServiceDefn = item :
if item.type == "parametrisable s6-rc service definition"
then
let sd = lib.attrByPath item.loc ["not found"] conf;
in item // {
spliceServiceDefn =
item:
if item.type == "parametrisable s6-rc service definition" then
let
sd = lib.attrByPath item.loc [ "not found" ] conf;
in
item
// {
declarations = map stripAnyPrefixes item.declarations;
parameters =
let x = lib.mapAttrsToList optToDoc sd.parameters; in x;
let
x = lib.mapAttrsToList optToDoc sd.parameters;
in
x;
}
else
item // { declarations = map stripAnyPrefixes item.declarations; };

View File

@ -9,13 +9,15 @@
pkgs,
lib,
...
}: let
}:
let
secrets = import ./extneder-secrets.nix;
inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) writeText serviceFns;
svc = config.system.service;
in rec {
in
rec {
boot = {
tftp = {
serverip = "10.0.0.1";
@ -34,10 +36,11 @@ in rec {
];
hostname = "arhcive";
services.dhcpc =
let iface = config.hardware.networkInterfaces.lan;
in svc.network.dhcp.client.build {
let
iface = config.hardware.networkInterfaces.lan;
in
svc.network.dhcp.client.build {
interface = iface;
dependencies = [ config.services.hostname ];
};
@ -45,7 +48,10 @@ in rec {
services.sshd = svc.ssh.build { };
services.watchdog = svc.watchdog.build {
watched = with config.services ; [ sshd dhcpc ];
watched = with config.services; [
sshd
dhcpc
];
};
services.resolvconf = oneshot rec {
@ -73,7 +79,10 @@ in rec {
};
programs.busybox = {
applets = ["lsusb" "tar"];
applets = [
"lsusb"
"tar"
];
options = {
FEATURE_LS_TIMESTAMPS = "y";
FEATURE_LS_SORTFILES = "y";
@ -108,7 +117,8 @@ in rec {
gid = backup
secrets file = ${secrets_file}/.outputs/secrets
'';
in longrun {
in
longrun {
name = "rsync";
run = ''
${pkgs.rsyncSmall}/bin/rsync --no-detach --daemon --config=${configFile}

View File

@ -14,7 +14,8 @@ let
ipv4LocalNet = "10.8.0";
svc = config.system.service;
in rec {
in
rec {
boot = {
tftp = {
freeSpaceBytes = 3 * 1024 * 1024;
@ -99,8 +100,10 @@ in rec {
};
services.dns =
let interface = services.int;
in svc.dnsmasq.build {
let
interface = services.int;
in
svc.dnsmasq.build {
resolvconf = services.resolvconf;
inherit interface;
ranges = [
@ -124,12 +127,16 @@ in rec {
services.wan = svc.pppoe.build {
interface = config.hardware.networkInterfaces.wan;
ppp-options = [
"debug" "+ipv6" "noauth"
"debug"
"+ipv6"
"noauth"
# EDIT: change the strings "chap-username"
# and "chap-secret" to match the username/password
# provided by your ISP for PPP logins
"name" "chap-username"
"password" "chap-secret"
"name"
"chap-username"
"password"
"chap-secret"
];
};
@ -146,8 +153,10 @@ in rec {
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in dir {
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
@ -176,10 +185,12 @@ in rec {
# LAN interfaces respectively.
services.dhcp6c =
let client = svc.dhcp6c.client.build {
let
client = svc.dhcp6c.client.build {
interface = services.wan;
};
in bundle {
in
bundle {
name = "dhcp6c";
contents = [
(svc.dhcp6c.prefix.build {

View File

@ -10,10 +10,12 @@
lib,
modulesPath,
...
}: let
}:
let
secrets = import ./extneder-secrets.nix;
svc = config.system.service;
in rec {
in
rec {
boot = {
tftp = {
serverip = "192.168.8.148";
@ -49,5 +51,10 @@ in rec {
services.sshd = svc.ssh.build { };
users.root.passwd = lib.mkForce secrets.root.passwd;
defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig];
defaultProfile.packages = with pkgs; [
nftables
strace
tcpdump
swconfig
];
}

View File

@ -2,7 +2,8 @@
let
svc = config.system.service;
in rec {
in
rec {
imports = [
../modules/network
../modules/ssh

View File

@ -2,7 +2,8 @@
let
svc = config.system.service;
in rec {
in
rec {
imports = [
../modules/network
../modules/dnsmasq
@ -14,7 +15,9 @@ in rec {
# configure the internal network (LAN) with an address
services.int = svc.network.address.build {
interface = config.hardware.networkInterfaces.lan;
family = "inet"; address ="10.3.0.1"; prefixLength = 16;
family = "inet";
address = "10.3.0.1";
prefixLength = 16;
};
services.sshd = svc.ssh.build { };
@ -26,8 +29,10 @@ in rec {
};
services.dns =
let interface = services.int;
in svc.dnsmasq.build {
let
interface = services.int;
in
svc.dnsmasq.build {
inherit interface;
ranges = [
"10.3.0.10,10.3.0.240"

View File

@ -22,10 +22,12 @@ let
inherit (pkgs.liminix.services) longrun;
inherit (pkgs) writeText;
nginx_uid = 62;
in {
in
{
config = {
users.nginx = {
uid = nginx_uid; gid= nginx_uid;
uid = nginx_uid;
gid = nginx_uid;
dir = "/run/";
shell = "/bin/false";
};
@ -41,7 +43,8 @@ in {
zlib = null;
options = [
"stream"
"stream_ssl_module" "stream_ssl_preread_module"
"stream_ssl_module"
"stream_ssl_preread_module"
"stream_map_module"
];
};
@ -72,7 +75,8 @@ in {
}
}
'';
in longrun {
in
longrun {
name = "sniproxy";
run = ''
${nginx}/bin/nginx -c ${conf}

View File

@ -43,13 +43,16 @@ let
he_oper_centr_freq_seg0_idx = 42;
require_vht = 1;
};
mkWifiSta = params: interface: secrets: svc.hostapd.build {
mkWifiSta =
params: interface: secrets:
svc.hostapd.build {
inherit interface;
params = params // {
inherit (secrets) ssid wpa_passphrase;
};
};
in rec {
in
rec {
imports = [
../modules/wlan.nix
../modules/network
@ -87,8 +90,10 @@ in rec {
};
services.dhcpv4 =
let iface = services.int;
in svc.network.dhcp.client.build { interface = iface; };
let
iface = services.int;
in
svc.network.dhcp.client.build { interface = iface; };
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpv4} address)";
@ -102,7 +107,9 @@ in rec {
};
services.ntp = config.system.service.ntp.build {
pools = { "pool.ntp.org" = ["iburst"] ; };
pools = {
"pool.ntp.org" = [ "iburst" ];
};
};
boot.tftp = {
@ -113,7 +120,14 @@ in rec {
# wlan0 is the 2.4GHz interface.
services.hostap-1 = mkWifiSta baseParams config.hardware.networkInterfaces.wlan0 secrets-1;
# wlan1 is the 5GHz interface, e.g. AX capable.
services.hostap-2 = mkWifiSta (baseParams // modernParams) config.hardware.networkInterfaces.wlan1 secrets-2;
services.hostap-2 = mkWifiSta (
baseParams // modernParams
) config.hardware.networkInterfaces.wlan1 secrets-2;
defaultProfile.packages = with pkgs; [ zyxel-bootconfig iw min-collect-garbage mtdutils ];
defaultProfile.packages = with pkgs; [
zyxel-bootconfig
iw
min-collect-garbage
mtdutils
];
}

View File

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... } :
{
config,
pkgs,
lib,
...
}:
let
inherit (pkgs) serviceFns;
svc = config.system.service;
@ -9,7 +14,8 @@ let
cd ${pkgs.util-linux-small}/bin
cp fdisk sfdisk mkswap $out/bin
'';
in rec {
in
rec {
imports = [
../modules/network
../modules/ssh
@ -67,7 +73,11 @@ in rec {
'';
};
services.growfs = let name = "growfs"; in oneshot {
services.growfs =
let
name = "growfs";
in
oneshot {
inherit name;
up = ''
device=$(grep /persist /proc/1/mountinfo | cut -f9 -d' ')
@ -92,13 +102,13 @@ in rec {
# create this hashed password string
passwd = "$6$y7WZ5hM6l5nriLmo$5AJlmzQZ6WA.7uBC7S8L4o19ESR28Dg25v64/vDvvCN01Ms9QoHeGByj8lGlJ4/b.dbwR9Hq2KXurSnLigt1W1";
openssh.authorizedKeys.keys =
let fromBuild =
(builtins.readFile
((builtins.toPath (builtins.getEnv "HOME")) + "/.ssh/authorized_keys")
let
fromBuild = (
builtins.readFile ((builtins.toPath (builtins.getEnv "HOME")) + "/.ssh/authorized_keys")
);
in lib.splitString "\n" fromBuild;
in
lib.splitString "\n" fromBuild;
};
defaultProfile.packages = with pkgs; [

View File

@ -4,7 +4,13 @@
# devices: mostly you will need to attend to the number of wlan and lan
# interfaces
{ config, pkgs, lib, modulesPath, ... } :
{
config,
pkgs,
lib,
modulesPath,
...
}:
let
secrets = {
domainName = "fake.liminix.org";
@ -17,7 +23,8 @@ let
wmm_enabled = 1;
};
in rec {
in
rec {
boot = {
tftp = {
freeSpaceBytes = 3 * 1024 * 1024;
@ -33,22 +40,26 @@ in rec {
profile.gateway = {
lan = {
interfaces = with config.hardware.networkInterfaces;
[
interfaces = with config.hardware.networkInterfaces; [
# EDIT: these are the interfaces exposed by the gl.inet gl-ar750:
# if your device has more or differently named lan interfaces,
# specify them here
wlan wlan5
wlan
wlan5
lan
];
inherit (secrets.lan) prefix;
address = {
family = "inet"; address ="${secrets.lan.prefix}.1"; prefixLength = 24;
family = "inet";
address = "${secrets.lan.prefix}.1";
prefixLength = 24;
};
dhcp = {
start = 10;
end = 240;
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
hosts =
{ }
// lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
localDomain = "lan";
};
};
@ -95,8 +106,13 @@ in rec {
};
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 { };
@ -113,7 +129,8 @@ in rec {
programs.busybox = {
applets = [
"fdisk" "sfdisk"
"fdisk"
"sfdisk"
];
options = {
FEATURE_FANCY_TAIL = "y";

View File

@ -6,7 +6,8 @@
pkgs,
lib,
...
}: let
}:
let
secrets = import ./extneder-secrets.nix;
rsecrets = import ./rotuer-secrets.nix;
@ -27,7 +28,10 @@
# 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"; };
lns = {
hostname = "l2tp.aaisp.net.uk";
address = "194.4.172.12";
};
inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.liminix) outputRef;
@ -39,7 +43,8 @@
inherit (rsecrets) wpa_passphrase;
wmm_enabled = 1;
};
in rec {
in
rec {
boot = {
tftp = {
serverip = "10.0.0.1";
@ -62,7 +67,9 @@ in rec {
services.wan-address-for-secrets = svc.network.address.build {
interface = config.hardware.networkInterfaces.wan;
family = "inet"; address ="10.0.0.10"; prefixLength = 24;
family = "inet";
address = "10.0.0.10";
prefixLength = 24;
};
services.secrets = svc.secrets.outboard.build {
@ -83,22 +90,26 @@ in rec {
profile.gateway = {
lan = {
interfaces = with config.hardware.networkInterfaces;
[
interfaces = with config.hardware.networkInterfaces; [
# EDIT: these are the interfaces exposed by the gl.inet gl-ar750:
# if your device has more or differently named lan interfaces,
# specify them here
wlan wlan5
wlan
wlan5
lan
];
inherit (rsecrets.lan) prefix;
address = {
family = "inet"; address ="${rsecrets.lan.prefix}.1"; prefixLength = 24;
family = "inet";
address = "${rsecrets.lan.prefix}.1";
prefixLength = 24;
};
dhcp = {
start = 10;
end = 240;
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
hosts =
{ }
// lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
localDomain = "lan";
};
};
@ -107,7 +118,8 @@ in rec {
secret = outputRef config.services.secrets;
username = secret "ppp/username";
password = secret "ppp/password";
in {
in
{
interface =
let
pppoe = svc.pppoe.build {
@ -126,12 +138,19 @@ in rec {
route = svc.network.route.build {
via = "$(output ${services.bootstrap-dhcpc} router)";
target = lns.address;
dependencies = [services.bootstrap-dhcpc check-address];
dependencies = [
services.bootstrap-dhcpc
check-address
];
};
l2tpd = svc.l2tp.build {
lns = lns.address;
inherit username password;
dependencies = [config.services.lns-address route check-address];
dependencies = [
config.services.lns-address
route
check-address
];
};
in
svc.health-check.build {
@ -140,7 +159,8 @@ in rec {
interval = 2;
healthCheck = pkgs.writeAshScript "ping-check" { } "ping 1.1.1.1";
};
in svc.round-robin.build {
in
svc.round-robin.build {
name = "wan";
services = [
pppoe
@ -151,16 +171,20 @@ in rec {
};
wireless.networks = {
"${rsecrets.ssid}" = {
"${rsecrets.ssid}" =
{
interface = config.hardware.networkInterfaces.wlan;
hw_mode = "g";
channel = "6";
ieee80211n = 1;
} // wirelessConfig // {
}
// wirelessConfig
// {
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase";
};
"${rsecrets.ssid}5" = rec {
"${rsecrets.ssid}5" =
rec {
interface = config.hardware.networkInterfaces.wlan5;
hw_mode = "a";
channel = 36;
@ -169,7 +193,9 @@ in rec {
vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211n = 1;
ieee80211ac = 1;
} // wirelessConfig // {
}
// wirelessConfig
// {
wpa_passphrase = outputRef config.services.secrets "wpa_passphrase";
};
};
@ -184,16 +210,21 @@ in rec {
authorizedKeys = outputRef config.services.secrets "ssh/authorizedKeys";
};
services.lns-address = let
services.lns-address =
let
ns = "$(output_word ${services.bootstrap-dhcpc} dns 1)";
route-to-bootstrap-nameserver = svc.network.route.build {
via = "$(output ${services.bootstrap-dhcpc} router)";
target = ns;
dependencies = [ services.bootstrap-dhcpc ];
};
in oneshot rec {
in
oneshot rec {
name = "resolve-l2tp-server";
dependencies = [ services.bootstrap-dhcpc route-to-bootstrap-nameserver ];
dependencies = [
services.bootstrap-dhcpc
route-to-bootstrap-nameserver
];
up = ''
(in_outputs ${name}
DNSCACHEIP="${ns}" ${pkgs.s6-dns}/bin/s6-dnsip4 ${lns.hostname} \

View File

@ -1,8 +1,14 @@
{ config, pkgs, lim, ... } :
{
config,
pkgs,
lim,
...
}:
let
svc = config.system.service;
in rec {
in
rec {
imports = [
../modules/network
../modules/ssh
@ -29,12 +35,14 @@ in rec {
hostname = "omnia";
services.hostap =
let secrets = {
let
secrets = {
ssid = "not-the-internet";
channel = 4;
wpa_passphrase = "diamond dogs";
};
in svc.hostapd.build {
in
svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan;
params = {
country_code = "GB";
@ -51,12 +59,14 @@ in rec {
};
services.hostap5 =
let secrets = {
let
secrets = {
ssid = "not-the-internet";
channel = 36;
wpa_passphrase = "diamond dogs";
};
in svc.hostapd.build {
in
svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan5;
params = {
country_code = "GB";
@ -103,6 +113,7 @@ in rec {
};
defaultProfile.packages = with pkgs; [
figlet pciutils
figlet
pciutils
];
}

View File

@ -1,4 +1,9 @@
{ lim, pkgs, config, ...}:
{
lim,
pkgs,
config,
...
}:
{
config = {
kernel.config = {

View File

@ -1,4 +1,9 @@
{ lim, pkgs, config, ...}:
{
lim,
pkgs,
config,
...
}:
{
config = {
kernel.config = {

View File

@ -1,15 +1,20 @@
## Base options
## ============
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs.pseudofile) dir symlink;
type_service = pkgs.liminix.lib.types.service;
in {
in
{
options = {
defaultProfile = {
packages = mkOption {
@ -109,8 +114,13 @@ in {
};
};
config = {
defaultProfile.packages = with pkgs;
[ s6 s6-init-bin execline s6-linux-init s6-rc ];
defaultProfile.packages = with pkgs; [
s6
s6-init-bin
execline
s6-linux-init
s6-rc
];
boot.commandLine = [
"panic=10 oops=panic init=/bin/init loglevel=8"
@ -119,61 +129,90 @@ in {
"fw_devlink=off"
] ++ lib.optional (config.rootOptions != null) "rootflags=${config.rootOptions}";
system.callService = path : parameters :
system.callService =
path: parameters:
let
typeChecked = caller: type: value:
typeChecked =
caller: type: value:
let
inherit (lib) types mergeDefinitions;
defs = [{ file = caller; inherit value; }];
defs = [
{
file = caller;
inherit value;
}
];
type' = types.submodule { options = type; };
in (mergeDefinitions [] type' defs).mergedValue;
in
(mergeDefinitions [ ] type' defs).mergedValue;
cp = lib.callPackageWith (pkgs // { svc = config.system.service; });
pkg = cp path { };
checkTypes = t: p: typeChecked (builtins.toString path) t p;
in {
in
{
inherit parameters;
build = { dependencies ? [], ... } @ args :
build =
{
dependencies ? [ ],
...
}@args:
let
s = pkg (checkTypes parameters
(builtins.removeAttrs args ["dependencies"]));
in s.overrideAttrs (o: {
s = pkg (checkTypes parameters (builtins.removeAttrs args [ "dependencies" ]));
in
s.overrideAttrs (o: {
dependencies = dependencies ++ o.dependencies;
buildInputs = dependencies ++ o.buildInputs;
});
};
users.root = {
uid = 0; gid= 0; gecos = "Root of all evaluation";
uid = 0;
gid = 0;
gecos = "Root of all evaluation";
dir = "/home/root/";
passwd = lib.mkDefault "";
shell = "/bin/sh";
};
groups = {
root = {
gid = 0; usernames = ["root"];
gid = 0;
usernames = [ "root" ];
};
system = {
gid = 1; usernames = ["root"];
gid = 1;
usernames = [ "root" ];
};
};
filesystem = dir {
dev =
let node = type: major: minor: mode : { inherit type major minor mode; };
in dir {
let
node = type: major: minor: mode: {
inherit
type
major
minor
mode
;
};
in
dir {
null = node "c" "1" "3" "0666";
zero = node "c" "1" "5" "0666";
tty = node "c" "5" "0" "0666";
console = node "c" "5" "1" "0600";
pts = dir { };
};
etc = let
profile = symlink
(pkgs.writeScript ".profile" ''
etc =
let
profile = symlink (
pkgs.writeScript ".profile" ''
PATH=${lib.makeBinPath config.defaultProfile.packages}:/bin
export PATH
'');
in dir {
''
);
in
dir {
inherit profile;
ashrc = profile;
};

View File

@ -6,8 +6,12 @@
## with one or more WLANs so that several local devices appear to be
## on the same network.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
@ -40,10 +44,12 @@ in
};
};
};
config.kernel.config = {
config.kernel.config =
{
BRIDGE = "y";
BRIDGE_IGMP_SNOOPING = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
}
// lib.optionalAttrs (config.system.service ? vlan) {
# depends on bridge _and_ vlan. I would like there to be
# a better way to test for the existence of vlan config:
# maybe the module should set an `enabled` attribute?

View File

@ -1,21 +1,25 @@
{
liminix
, ifwait
, svc
liminix,
ifwait,
svc,
}:
{ members, primary }:
let
inherit (liminix.networking) interface;
inherit (liminix.services) bundle oneshot;
addif = member :
addif =
member:
# how do we get sight of services from here? maybe we need to
# implement ifwait as a regualr derivation instead of a
# servicedefinition
svc.ifwait.build {
state = "running";
interface = member;
dependencies = [ primary member ];
dependencies = [
primary
member
];
service = oneshot {
name = "${primary.name}.member.${member.name}";
up = ''
@ -24,7 +28,8 @@ let
down = "ip link set dev $(output ${member} ifname) nomaster";
};
};
in bundle {
in
bundle {
name = "${primary.name}.members";
contents = map addif members;
}

View File

@ -1,11 +1,12 @@
{
liminix
, lib
liminix,
lib,
}:
{ ifname }:
let
inherit (liminix.services) oneshot;
in oneshot rec {
in
oneshot rec {
name = "${ifname}.link";
up = ''
ip link add name ${ifname} type bridge

View File

@ -6,19 +6,26 @@
## the commands (termed "applets") required by the user or
## by other included modules.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink;
inherit (lib.strings) toUpper;
attrs = { options, applets } :
attrs =
{ options, applets }:
let
extraOptions = builtins.concatStringsSep "\n"
(mapAttrsToList (n: v: "CONFIG_${toUpper n} ${toString v}") options);
appletOptions = builtins.concatStringsSep "\n"
(map (n: "CONFIG_${toUpper n} y") applets);
in {
extraOptions = builtins.concatStringsSep "\n" (
mapAttrsToList (n: v: "CONFIG_${toUpper n} ${toString v}") options
);
appletOptions = builtins.concatStringsSep "\n" (map (n: "CONFIG_${toUpper n} y") applets);
in
{
enableMinimal = true;
extraConfig = ''
${extraOptions}
@ -26,36 +33,161 @@ let
'';
};
cfg = config.programs.busybox;
busybox = pkgs.busybox.override (attrs { inherit (cfg) applets options; });
makeLinks = lib.attrsets.genAttrs
cfg.applets
(a: symlink "${busybox}/bin/busybox");
busybox = pkgs.busybox.override (attrs {
inherit (cfg) applets options;
});
makeLinks = lib.attrsets.genAttrs cfg.applets (a: symlink "${busybox}/bin/busybox");
minimalApplets = [
# this is probably less minimal than it could be
"arch" "ash" "base64" "basename" "bc" "brctl" "bunzip2" "bzcat" "bzip2"
"cal" "cat" "chattr" "chgrp" "chmod" "chown" "chpst" "chroot" "clear" "cmp"
"comm" "cp" "cpio" "cut" "date" "dhcprelay" "dd" "df" "dirname" "dmesg"
"du" "echo" "egrep" "env" "expand" "expr" "false" "fdisk" "fgrep" "find"
"free" "fuser" "grep" "gunzip" "gzip" "head" "hexdump" "hostname" "hwclock"
"ifconfig" "ip" "ipaddr" "iplink" "ipneigh" "iproute" "iprule" "kill"
"killall" "killall5" "less" "ln" "ls" "lsattr" "lsof" "md5sum" "mkdir"
"mknod" "mktemp" "mount" "mv" "nc" "netstat" "nohup" "od" "pgrep" "pidof"
"ping" "ping6" "pkill" "pmap" "printenv" "printf" "ps" "pwd" "readlink"
"realpath" "reset" "rm" "rmdir" "route" "sed" "seq" "setsid" "sha1sum"
"sha256sum" "sha512sum" "sleep" "sort" "stat" "strings" "stty" "su" "sum"
"swapoff" "swapon" "sync" "tail" "tee" "test" "time" "touch" "tr"
"traceroute" "traceroute6" "true" "truncate" "tty" "udhcpc" "umount"
"uname" "unexpand" "uniq" "unlink" "unlzma" "unxz" "unzip" "uptime" "watch"
"wc" "whoami" "xargs" "xxd" "xz" "xzcat" "yes" "zcat"
"arch"
"ash"
"base64"
"basename"
"bc"
"brctl"
"bunzip2"
"bzcat"
"bzip2"
"cal"
"cat"
"chattr"
"chgrp"
"chmod"
"chown"
"chpst"
"chroot"
"clear"
"cmp"
"comm"
"cp"
"cpio"
"cut"
"date"
"dhcprelay"
"dd"
"df"
"dirname"
"dmesg"
"du"
"echo"
"egrep"
"env"
"expand"
"expr"
"false"
"fdisk"
"fgrep"
"find"
"free"
"fuser"
"grep"
"gunzip"
"gzip"
"head"
"hexdump"
"hostname"
"hwclock"
"ifconfig"
"ip"
"ipaddr"
"iplink"
"ipneigh"
"iproute"
"iprule"
"kill"
"killall"
"killall5"
"less"
"ln"
"ls"
"lsattr"
"lsof"
"md5sum"
"mkdir"
"mknod"
"mktemp"
"mount"
"mv"
"nc"
"netstat"
"nohup"
"od"
"pgrep"
"pidof"
"ping"
"ping6"
"pkill"
"pmap"
"printenv"
"printf"
"ps"
"pwd"
"readlink"
"realpath"
"reset"
"rm"
"rmdir"
"route"
"sed"
"seq"
"setsid"
"sha1sum"
"sha256sum"
"sha512sum"
"sleep"
"sort"
"stat"
"strings"
"stty"
"su"
"sum"
"swapoff"
"swapon"
"sync"
"tail"
"tee"
"test"
"time"
"touch"
"tr"
"traceroute"
"traceroute6"
"true"
"truncate"
"tty"
"udhcpc"
"umount"
"uname"
"unexpand"
"uniq"
"unlink"
"unlzma"
"unxz"
"unzip"
"uptime"
"watch"
"wc"
"whoami"
"xargs"
"xxd"
"xz"
"xzcat"
"yes"
"zcat"
];
in {
in
{
options = {
programs.busybox = {
applets = mkOption {
type = types.listOf types.str;
description = "Applets required";
default = [ ];
example = ["sh" "getty" "login"];
example = [
"sh"
"getty"
"login"
];
};
options = mkOption {
# mostly the values are y n or m, but sometimes
@ -63,7 +195,9 @@ in {
description = "Other busybox config flags that do not map directly to applet names (often prefixed FEATURE_)";
type = types.attrsOf types.nonEmptyStr;
default = { };
example = { FEATURE_DD_IBS_OBS = "y"; };
example = {
FEATURE_DD_IBS_OBS = "y";
};
};
};
};

View File

@ -1,10 +1,14 @@
{
writeFennel
, linotify
, anoia
, lualinux
writeFennel,
linotify,
anoia,
lualinux,
}:
writeFennel "acquire-delegated-prefix" {
packages = [ linotify anoia lualinux ];
packages = [
linotify
anoia
lualinux
];
mainFunction = "run";
} ./acquire-delegated-prefix.fnl

View File

@ -1,10 +1,14 @@
{
writeFennel
, linotify
, anoia
, lualinux
writeFennel,
linotify,
anoia,
lualinux,
}:
writeFennel "acquire-wan-address" {
packages = [ linotify anoia lualinux ];
packages = [
linotify
anoia
lualinux
];
mainFunction = "run";
} ./acquire-wan-address.fnl

View File

@ -1,14 +1,18 @@
{
liminix
, callPackage
liminix,
callPackage,
}:
{ client, interface }:
let
inherit (liminix.services) longrun;
name = "dhcp6c.addr.${client.name}.${interface.name}";
script = callPackage ./acquire-wan-address.nix { };
in longrun {
in
longrun {
inherit name;
run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)";
dependencies = [ client interface ];
dependencies = [
client
interface
];
}

View File

@ -1,13 +1,14 @@
{
liminix
, odhcp6c
, odhcp-script
liminix,
odhcp6c,
odhcp-script,
}:
{ interface }:
let
inherit (liminix.services) longrun;
name = "dhcp6c.${interface.name}";
in longrun {
in
longrun {
inherit name;
notification-fd = 10;
run = ''

View File

@ -9,7 +9,12 @@
## addresses of network interfaces that you want to assign those
## prefixes to
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;

View File

@ -1,14 +1,18 @@
{
liminix
, callPackage
liminix,
callPackage,
}:
{ client, interface }:
let
inherit (liminix.services) longrun;
name = "dhcp6c.prefix.${client.name}.${interface.name}";
script = callPackage ./acquire-delegated-prefix.nix { };
in longrun {
in
longrun {
inherit name;
run = "${script} $SERVICE_OUTPUTS/${client.name} $(output ${interface} ifname)";
dependencies = [ client interface ];
dependencies = [
client
interface
];
}

View File

@ -4,12 +4,17 @@
## This module includes a service to provide DNS, DHCP, and IPv6
## router advertisement for the local network.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
in {
in
{
options = {
system.service.dnsmasq = mkOption {
type = liminix.lib.types.serviceDefn;
@ -44,7 +49,8 @@ in {
};
hosts = mkOption {
default = { };
type = types.attrsOf (types.submodule {
type = types.attrsOf (
types.submodule {
options = {
mac = mkOption {
description = ''
@ -65,14 +71,18 @@ in {
type = types.listOf types.str;
description = "IPv6 addresses or interface-ids to assign to this client";
default = [ ];
example = [ "fe80::42:1eff:fefd:b341" "::1234"];
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
@ -83,12 +93,15 @@ in {
};
};
users.dnsmasq = {
uid = 51; gid= 51; gecos = "DNS/DHCP service user";
uid = 51;
gid = 51;
gecos = "DNS/DHCP service user";
dir = "/run/dnsmasq";
shell = "/bin/false";
};
groups.dnsmasq = {
gid = 51; usernames = ["dnsmasq"];
gid = 51;
usernames = [ "dnsmasq" ];
};
groups.system.usernames = [ "dnsmasq" ];
};

View File

@ -1,26 +1,35 @@
{
liminix
, dnsmasq
, serviceFns
, lib
liminix,
dnsmasq,
serviceFns,
lib,
}:
{
interface
, user
, domain
, group
, ranges
, hosts
, upstreams
, resolvconf
interface,
user,
domain,
group,
ranges,
hosts,
upstreams,
resolvconf,
}:
let
name = "${interface.name}.dnsmasq";
inherit (liminix.services) longrun;
inherit (lib) concatStrings concatStringsSep mapAttrsToList;
hostOpt = name : { mac, v4, v6, leasetime }:
let v6s = concatStrings (map (a : ",[${a}]") v6);
in "--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}";
hostOpt =
name:
{
mac,
v4,
v6,
leasetime,
}:
let
v6s = concatStrings (map (a: ",[${a}]") v6);
in
"--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}";
in
longrun {
inherit name;
@ -35,7 +44,12 @@ longrun {
${lib.concatStringsSep " " (builtins.map (r: "--server=${r}") upstreams)} \
--keep-in-foreground \
--dhcp-authoritative \
${if resolvconf != null then "--resolv-file=$(output_path ${resolvconf} resolv.conf)" else "--no-resolv"} \
${
if resolvconf != null then
"--resolv-file=$(output_path ${resolvconf} resolv.conf)"
else
"--no-resolv"
} \
${lib.concatStringsSep " " (mapAttrsToList hostOpt hosts)} \
--no-hosts \
--log-dhcp \

View File

@ -3,7 +3,8 @@ let
accept = expr: "${expr} accept";
mcast-scope = 8;
allow-incoming = false;
in {
in
{
bogons-ip6 = {
type = "filter";
family = "ip6";
@ -60,7 +61,8 @@ in {
(drop
# dest addr first byte 0xff, low nibble of second byte <= scope
# https://www.mankier.com/8/nft#Payload_Expressions-Raw_Payload_Expression
"@nh,192,8 eq 0xff @nh,204,4 le ${toString mcast-scope}")
"@nh,192,8 eq 0xff @nh,204,4 le ${toString mcast-scope}"
)
(accept "oifname @lan iifname @wan meta l4proto udp ct state established,related")
(accept "iifname @lan oifname @wan meta l4proto udp")
@ -88,9 +90,11 @@ in {
# we can allow all reasonable inbound, or we can use an explicit
# allowlist to enumerate the endpoints that are allowed to
# accept inbound from the WAN
(if allow-incoming
then accept "oifname @lan iifname @wan"
else "iifname @wan jump incoming-allowed-ip6"
(
if allow-incoming then
accept "oifname @lan iifname @wan"
else
"iifname @wan jump incoming-allowed-ip6"
)
# allow all outbound and any inbound that's part of a
# recognised (outbound-initiated) flow
@ -130,10 +134,7 @@ in {
(accept "meta l4proto icmpv6")
"iifname @lan jump input-ip6-lan"
"iifname @wan jump input-ip6-wan"
(if allow-incoming
then accept "iifname @wan"
else "iifname @wan jump incoming-allowed-ip6"
)
(if allow-incoming then accept "iifname @wan" else "iifname @wan jump incoming-allowed-ip6")
# how does this even make sense in an input chain?
(accept "iifname @wan ct state established,related")
(accept "iifname @lan ")

View File

@ -4,7 +4,12 @@
## Provides a service to create an nftables ruleset based on
## configuration supplied to it.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
@ -54,7 +59,8 @@ in
};
config = {
system.service.firewall =
let svc = config.system.callService ./service.nix {
let
svc = config.system.callService ./service.nix {
extraRules = mkOption {
type = types.attrsOf types.attrs;
description = "firewall ruleset";
@ -76,15 +82,21 @@ in
description = "firewall ruleset";
};
};
in svc // {
build = args :
let args' = args // {
in
svc
// {
build =
args:
let
args' = args // {
dependencies = (args.dependencies or [ ]) ++ [ kmodules ];
};
in svc.build args' ;
in
svc.build args';
};
programs.busybox.applets = [
"insmod" "rmmod"
"insmod"
"rmmod"
];
kernel.config = {
NETFILTER = "y";

View File

@ -1,37 +1,44 @@
{
liminix
, lib
, firewallgen
, nftables
, writeFennel
, anoia
, lualinux
, linotify
liminix,
lib,
firewallgen,
nftables,
writeFennel,
anoia,
lualinux,
linotify,
}:
{
rules,
extraRules,
zones,
}:
{ rules, extraRules, zones }:
let
inherit (liminix.services) longrun;
inherit (lib.attrsets) mapAttrs' nameValuePair mapAttrsToList;
inherit (lib.strings) concatStringsSep;
inherit (lib.lists) flatten;
mkSet = family : name :
nameValuePair
"${name}-set-${family}"
{
mkSet =
family: name:
nameValuePair "${name}-set-${family}" {
kind = "set";
inherit name family;
type = "ifname";
};
sets = (mapAttrs' (n : _ : mkSet "ip" n) zones) //
(mapAttrs' (n : _ : mkSet "ip6" n) zones);
sets = (mapAttrs' (n: _: mkSet "ip" n) zones) // (mapAttrs' (n: _: mkSet "ip6" n) zones);
allRules = lib.recursiveUpdate extraRules (lib.recursiveUpdate (builtins.trace sets sets) rules);
script = firewallgen "firewall1.nft" allRules;
ifwatch = writeFennel "ifwatch" {
packages = [anoia lualinux linotify];
packages = [
anoia
lualinux
linotify
];
mainFunction = "run";
} ./ifwatch.fnl;
watchArg = z: intfs: map (i: "${z}:${i}/.outputs") intfs;
in longrun {
in
longrun {
name = "firewall";
run = ''
${script}

View File

@ -75,9 +75,16 @@ in
type = types.ints.unsigned;
};
};
loadAddress = mkOption { type = types.ints.unsigned; default = null; };
loadAddress = mkOption {
type = types.ints.unsigned;
default = null;
};
entryPoint = mkOption { type = types.ints.unsigned; };
alignment = mkOption { type = types.nullOr types.ints.unsigned; default = null; description = "Alignment passed to `mkimage` for FIT"; };
alignment = mkOption {
type = types.nullOr types.ints.unsigned;
default = null;
description = "Alignment passed to `mkimage` for FIT";
};
radios = mkOption {
description = ''
Kernel modules (from mac80211 package) required for the
@ -85,7 +92,10 @@ in
'';
type = types.listOf types.str;
default = [ ];
example = ["ath9k" "ath10k"];
example = [
"ath9k"
"ath10k"
];
};
rootDevice = mkOption {
description = "Full path to preferred root device";

View File

@ -6,13 +6,18 @@
## have other behaviours by e.g. combining this service with a round-robin
## for failover)
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
in
# inherit (pkgs.liminix.services) longrun;
in {
{
options = {
system.service.health-check = mkOption {
description = "run a service while periodically checking it is healthy";

View File

@ -1,12 +1,24 @@
{
liminix, lib, lim, s6
liminix,
lib,
lim,
s6,
}:
{
service,
interval,
threshold,
healthCheck,
}:
{ service, interval, threshold, healthCheck } :
let
inherit (liminix.services) oneshot longrun;
inherit (builtins) toString;
inherit (service) name;
checker = let name' = "check-${name}"; in longrun {
checker =
let
name' = "check-${name}";
in
longrun {
name = name';
run = ''
fails=0
@ -31,7 +43,8 @@ let
done
'';
};
in service.overrideAttrs(o: {
in
service.overrideAttrs (o: {
buildInputs = (lim.orEmpty o.buildInputs) ++ [ checker ];
dependencies = (lim.orEmpty o.dependencies) ++ [ checker ];
})

View File

@ -11,11 +11,17 @@
## If you have more than one wireless network interface (e.g.
## wlan0, wlan1) you can run an instance of hostapd on each of them.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
in {
in
{
imports = [ ../secrets ];
options = {
system.service.hostapd = mkOption {

View File

@ -1,16 +1,23 @@
{
liminix
, svc
, hostapd
, output-template
, writeText
, lib
liminix,
svc,
hostapd,
output-template,
writeText,
lib,
}:
{ interface, params }:
let
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList unique;
inherit (builtins) map filter attrValues length head typeOf;
inherit (builtins)
map
filter
attrValues
length
head
typeOf
;
# This is not a friendly interface to configuring a wireless AP: it
# just passes everything straight through to the hostapd config.
@ -27,19 +34,23 @@ let
ctrl_interface_group = 0;
};
attrs = defaults // params;
literal_or_output = o: ({
literal_or_output =
o:
(
{
string = builtins.toJSON;
int = builtins.toJSON;
lambda = (o: "output(${builtins.toJSON (o "service")}, ${builtins.toJSON (o "path")})");
}.${builtins.typeOf o}) o;
}
.${builtins.typeOf o}
)
o;
conf =
(writeText "hostapd.conf.in"
((concatStringsSep
"\n"
(mapAttrsToList
(n : v : "${n}={{ ${literal_or_output v} }}")
attrs)) + "\n"));
conf = (
writeText "hostapd.conf.in" (
(concatStringsSep "\n" (mapAttrsToList (n: v: "${n}={{ ${literal_or_output v} }}") attrs)) + "\n"
)
);
service = longrun {
inherit name;
dependencies = [ interface ];
@ -51,7 +62,8 @@ let
'';
};
watch = filter (f: typeOf f == "lambda") (attrValues attrs);
in svc.secrets.subscriber.build {
in
svc.secrets.subscriber.build {
inherit service watch;
action = "restart-all";
}

View File

@ -1,8 +1,14 @@
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
in {
in
{
options = {
hostname = mkOption {
description = ''

View File

@ -1,10 +1,15 @@
{ config, pkgs, lib, ... } :
{
config,
pkgs,
lib,
...
}:
let
inherit (pkgs) liminix;
inherit (lib) mkOption types;
in {
options.system.service.ifwait =
mkOption { type = liminix.lib.types.serviceDefn; };
in
{
options.system.service.ifwait = mkOption { type = liminix.lib.types.serviceDefn; };
config.system.service.ifwait = config.system.callService ./ifwait.nix {
state = mkOption { type = types.str; };

View File

@ -1,12 +1,13 @@
{ ifwait, liminix }:
{
state
, interface
, service
state,
interface,
service,
}:
let
inherit (liminix.services) longrun;
in longrun {
in
longrun {
name = "ifwait.${interface.name}";
buildInputs = [ service ];
restart-on-upgrade = true;

View File

@ -3,26 +3,36 @@
##
##
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix openwrt;
mergeConditionals = conf : conditions :
mergeConditionals =
conf: conditions:
# for each key in conditions, if it is present in conf
# then merge the associated value into conf
lib.foldlAttrs
(acc: name: value:
if (conf ? ${name}) && (conf.${name} != "n")
then acc // value
else acc)
conf
conditions;
in {
lib.foldlAttrs (
acc: name: value:
if (conf ? ${name}) && (conf.${name} != "n") then acc // value else acc
) conf conditions;
in
{
options = {
kernel = {
src = mkOption { type = types.path; default = openwrt.kernelSrc; } ;
version = mkOption { type = types.str; default = openwrt.kernelVersion;} ;
src = mkOption {
type = types.path;
default = openwrt.kernelSrc;
};
version = mkOption {
type = types.str;
default = openwrt.kernelVersion;
};
modular = mkOption {
type = types.bool;
default = true;
@ -70,10 +80,9 @@ in {
config = {
system.outputs.kernel =
let
mergedConfig = mergeConditionals
config.kernel.config
config.kernel.conditionalConfig;
in liminix.builders.kernel.override {
mergedConfig = mergeConditionals config.kernel.config config.kernel.conditionalConfig;
in
liminix.builders.kernel.override {
config = mergedConfig;
inherit (config.kernel) version src extraPatchPhase;
targets = config.kernel.makeTargets;

View File

@ -1,7 +1,13 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (pkgs.liminix.services) longrun;
in {
in
{
config.services.klogd = longrun {
name = "klogd";
run = ''

View File

@ -1,7 +1,13 @@
{ config, lib, ... }:
let
inherit (lib) mkIf mkEnableOption mkOption types;
in {
inherit (lib)
mkIf
mkEnableOption
mkOption
types
;
in
{
options = {
logging = {
persistent = {

View File

@ -1,6 +1,8 @@
{ config, pkgs, ... }:
let inherit (pkgs.liminix.services) oneshot longrun;
in {
let
inherit (pkgs.liminix.services) oneshot longrun;
in
{
config = {
services = rec {
mdevd = longrun {

View File

@ -2,21 +2,30 @@
##
## Mount filesystems
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
in {
in
{
options = {
system.service.mount = mkOption {
type = liminix.lib.types.serviceDefn;
};
};
imports = [ ../mdevd.nix ../uevent-rule ];
imports = [
../mdevd.nix
../uevent-rule
];
config.system.service.mount =
let svc = config.system.callService ./service.nix {
let
svc = config.system.callService ./service.nix {
partlabel = mkOption {
type = types.str;
example = "my-usb-stick";
@ -28,7 +37,11 @@ in {
options = mkOption {
type = types.listOf types.str;
default = [ ];
example = ["noatime" "ro" "sync"];
example = [
"noatime"
"ro"
"sync"
];
};
fstype = mkOption {
type = types.str;
@ -36,19 +49,27 @@ in {
example = "vfat";
};
};
in svc // {
build = args:
let args' = args // {
in
svc
// {
build =
args:
let
args' = args // {
dependencies = (args.dependencies or [ ]) ++ [
config.services.mdevd
config.services.devout
];
};
in svc.build args' ;
in
svc.build args';
};
config.programs.busybox = {
applets = ["blkid" "findfs"];
applets = [
"blkid"
"findfs"
];
options = {
FEATURE_BLKID_TYPE = "y";
FEATURE_MOUNT_FLAGS = "y";

View File

@ -1,15 +1,19 @@
{
liminix
, lib
, svc
liminix,
lib,
svc,
}:
{
partlabel,
mountpoint,
options,
fstype,
}:
{ partlabel, mountpoint, options, fstype }:
let
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}";
options_string = if options == [ ] then "" else "-o ${lib.concatStringsSep "," options}";
controller = svc.uevent-rule.build {
serviceName = name;
symlink = device;
@ -18,7 +22,8 @@ let
devtype = "partition";
};
};
in oneshot {
in
oneshot {
inherit name;
timeout-up = 3600;
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";

View File

@ -1,9 +1,14 @@
{
liminix
, serviceFns
, lib
liminix,
serviceFns,
lib,
}:
{
interface,
family,
address,
prefixLength,
}:
{interface, family, address, prefixLength} :
let
inherit (liminix.services) oneshot;
# rather depending on the assumption that nobody will
@ -20,7 +25,8 @@ let
echo $dev > ifname
)
'';
in oneshot {
in
oneshot {
inherit name up;
down = "true"; # this has been broken for ~ ages
dependencies = [ interface ];

View File

@ -4,13 +4,18 @@
## Basic network services for creating hardware ethernet devices
## and adding addresses
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
inherit (pkgs.liminix.services) bundle;
in {
in
{
options = {
system.service.network = {
link = mkOption {
@ -43,7 +48,8 @@ in {
let
net = config.system.service.network;
iface = net.link.build { ifname = "lo"; };
in bundle {
in
bundle {
name = "loopback";
contents = [
(net.address.build {
@ -82,7 +88,8 @@ in {
Path to the sysfs node of the device. If you provide this
and the ifname option, the device will be renamed to the
name given by ifname.
''; };
'';
};
# other "ip link add" options could go here as well
mtu = mkOption {
type = types.nullOr types.int;
@ -94,7 +101,10 @@ in {
type = liminix.lib.types.service;
};
family = mkOption {
type = types.enum [ "inet" "inet6" ];
type = types.enum [
"inet"
"inet6"
];
};
address = mkOption {
type = types.str;

View File

@ -1,8 +1,8 @@
{
liminix
, writeAshScript
, serviceFns
, lib
liminix,
writeAshScript,
serviceFns,
lib,
}:
{ interface }:
let
@ -38,7 +38,8 @@ let
;;
esac
'';
in longrun {
in
longrun {
inherit name;
run = "exec /bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
notification-fd = 10;

View File

@ -1,6 +1,6 @@
{
liminix
, lib
liminix,
lib,
}:
{ enableIPv4, enableIPv6 }:
let
@ -8,11 +8,9 @@ let
ip4 = "/proc/sys/net/ipv4/conf/all/forwarding";
ip6 = "/proc/sys/net/ipv6/conf/all/forwarding";
opt = lib.optionalString;
sysctls = b :
""
+ opt enableIPv4 "echo ${b} > ${ip4}\n"
+ opt enableIPv6 "echo ${b} > ${ip6}\n";
in oneshot {
sysctls = b: "" + opt enableIPv4 "echo ${b} > ${ip4}\n" + opt enableIPv6 "echo ${b} > ${ip6}\n";
in
oneshot {
name = "forwarding${opt enableIPv4 "4"}${opt enableIPv6 "6"}";
up = sysctls "1";
down = sysctls "0";

View File

@ -1,23 +1,27 @@
{
liminix
, lib
liminix,
lib,
}:
{
ifname
, devpath ? null
, mtu} :
ifname,
devpath ? null,
mtu,
}:
# if devpath is supplied, we rename the interface at that
# path to have the specified name.
let
inherit (liminix.services) oneshot;
name = "${ifname}.link";
rename = if devpath != null
then ''
rename =
if devpath != null then
''
oldname=$(cd /sys${devpath} && cd net/ && echo *)
ip link set ''${oldname} name ${ifname}
''
else "";
in oneshot {
else
"";
in
oneshot {
inherit name;
up = ''
${rename}

View File

@ -1,15 +1,25 @@
{
liminix
, lib
liminix,
lib,
}:
{
target,
via,
interface ? null,
metric,
}:
{ 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_hash}-${builtins.substring 0 12 (builtins.hashString "sha256" "${via_hash}-${if interface!=null then interface.name else ""}")}";
in
oneshot {
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}
'';

View File

@ -6,12 +6,18 @@
## optionally also provide time service to its peers. The
## implementation used in Liminix is Chrony
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
serverOpts = types.listOf types.str;
in {
in
{
options = {
system.service.ntp = mkOption {
type = liminix.lib.types.serviceDefn;
@ -23,18 +29,31 @@ in {
type = types.str;
default = "ntp";
};
servers = mkOption { type = types.attrsOf serverOpts; default = {}; };
pools = mkOption { type = types.attrsOf serverOpts; default = {}; };
peers = mkOption { type = types.attrsOf serverOpts; default = {}; };
servers = mkOption {
type = types.attrsOf serverOpts;
default = { };
};
pools = mkOption {
type = types.attrsOf serverOpts;
default = { };
};
peers = mkOption {
type = types.attrsOf serverOpts;
default = { };
};
makestep = mkOption {
default = null;
type = types.nullOr
(types.submodule {
type = types.nullOr (
types.submodule {
options = {
threshold = mkOption { type = types.number; default = null;};
threshold = mkOption {
type = types.number;
default = null;
};
limit = mkOption { type = types.number; };
};
});
}
);
};
allow = mkOption {
description = "subnets from which NTP clients are allowed to access the server";
@ -60,7 +79,9 @@ in {
};
};
users.ntp = {
uid = 52; gid= 52; gecos = "Unprivileged NTP user";
uid = 52;
gid = 52;
gecos = "Unprivileged NTP user";
dir = "/run/ntp";
shell = "/bin/false";
};

View File

@ -1,25 +1,23 @@
{
liminix
, chrony
, lib
, writeText
liminix,
chrony,
lib,
writeText,
}:
params:
let
name = "ntp"; # bad name, needs to be unique
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList;
configFile = p:
(mapAttrsToList (name: opts: "server ${name} ${concatStringsSep "" opts}")
p.servers)
++
(mapAttrsToList (name: opts: "pool ${name} ${concatStringsSep "" opts}")
p.pools)
++
(mapAttrsToList (name: opts: "peer ${name} ${concatStringsSep "" opts}")
p.peers)
configFile =
p:
(mapAttrsToList (name: opts: "server ${name} ${concatStringsSep "" opts}") p.servers)
++ (mapAttrsToList (name: opts: "pool ${name} ${concatStringsSep "" opts}") p.pools)
++ (mapAttrsToList (name: opts: "peer ${name} ${concatStringsSep "" opts}") p.peers)
++ lib.optional (p.user != null) "user ${p.user}"
++ (lib.optional (p.makestep != null) "makestep ${toString p.makestep.threshold} ${toString p.makestep.limit}")
++ (lib.optional (
p.makestep != null
) "makestep ${toString p.makestep.threshold} ${toString p.makestep.limit}")
++ (map (n: "allow ${n}") p.allow)
++ (lib.optional (p.bindaddress != null) "bindaddress ${p.bindaddress}")
++ (lib.optional (p.binddevice != null) "binddevice ${p.binddevice}")
@ -30,9 +28,9 @@ let
]
++ [ p.extraConfig ];
config = writeText "chrony.conf"
(concatStringsSep "\n" (configFile params));
in longrun {
config = writeText "chrony.conf" (concatStringsSep "\n" (configFile params));
in
longrun {
inherit name;
run = "${chrony}/bin/chronyd -f ${config} -d";
}

View File

@ -105,7 +105,8 @@ in
rootdir =
let
inherit (pkgs.pkgsBuildBuild) runCommand;
in runCommand "mktree" { } ''
in
runCommand "mktree" { } ''
mkdir -p $out/nix/store/ $out/secrets $out/boot
cp ${o.systemConfiguration}/bin/activate $out/activate
ln -s ${pkgs.s6-init-bin}/bin/init $out/init
@ -115,12 +116,16 @@ in
done
'';
bootablerootdir =
let inherit (pkgs.pkgsBuildBuild) runCommand;
in runCommand "add-slash-boot" { } ''
let
inherit (pkgs.pkgsBuildBuild) runCommand;
in
runCommand "add-slash-boot" { } ''
cp -a ${o.rootdir} $out
${if o.bootfiles != null
then "(cd $out && chmod -R +w . && rmdir boot && cp -a ${o.bootfiles} boot)"
else ""
${
if o.bootfiles != null then
"(cd $out && chmod -R +w . && rmdir boot && cp -a ${o.bootfiles} boot)"
else
""
}
'';
manifest = writeText "manifest.json" (builtins.toJSON config.filesystem.contents);

View File

@ -1,17 +1,24 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
inherit (lib)
mkIf
mkEnableOption
mkOption
types
concatStringsSep
;
inherit (pkgs.pseudofile) dir symlink;
cfg = config.boot.loader.extlinux;
o = config.system.outputs;
cmdline = concatStringsSep " " config.boot.commandLine;
wantsDtb = config.hardware.dts ? src && config.hardware.dts.src != null;
in {
in
{
options.boot.loader.extlinux.enable = mkEnableOption "extlinux";
config = mkIf cfg.enable {

View File

@ -1,17 +1,24 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
inherit (lib)
mkIf
mkEnableOption
mkOption
types
concatStringsSep
;
inherit (pkgs.pseudofile) dir symlink;
cfg = config.boot.loader.fit;
o = config.system.outputs;
cmdline = concatStringsSep " " config.boot.commandLine;
wantsDtb = config.hardware.dts ? src && config.hardware.dts.src != null;
in {
in
{
options.boot.loader.fit.enable = mkEnableOption "FIT in /boot";
config = mkIf cfg.enable {

View File

@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf;
@ -21,9 +21,12 @@ in
rootfs =
let
inherit (pkgs.pkgsBuildBuild) runCommand e2fsprogs;
in runCommand "mkfs.btrfs" {
in
runCommand "mkfs.btrfs"
{
depsBuildBuild = [ e2fsprogs ];
} ''
}
''
tree=${o.bootablerootdir}
size=$(du -s --apparent-size --block-size 1024 $tree |cut -f1)
# add 25% for filesystem overhead

View File

@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf;
@ -23,9 +23,12 @@ in
rootfs =
let
inherit (pkgs.pkgsBuildBuild) runCommand e2fsprogs;
in runCommand "mkfs.ext4" {
in
runCommand "mkfs.ext4"
{
depsBuildBuild = [ e2fsprogs ];
} ''
}
''
tree=${o.bootablerootdir}
size=$(du -s --apparent-size --block-size 1024 $tree |cut -f1)
# add 25% for filesystem overhead

View File

@ -1,11 +1,16 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkEnableOption mkOption mkIf types;
inherit (lib)
mkEnableOption
mkOption
mkIf
types
;
inherit (pkgs) runCommand;
in
{
@ -34,8 +39,10 @@ in
system.outputs = {
initramfs =
let inherit (pkgs.pkgsBuildBuild) gen_init_cpio;
in runCommand "initramfs.cpio" {} ''
let
inherit (pkgs.pkgsBuildBuild) gen_init_cpio;
in
runCommand "initramfs.cpio" { } ''
cat << SPECIALS | ${gen_init_cpio}/bin/gen_init_cpio /dev/stdin > $out
dir /proc 0755 0 0
dir /dev 0755 0 0

View File

@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf;
@ -27,11 +27,13 @@ in
rootfs =
let
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
endian = if pkgs.stdenv.isBigEndian
then "--big-endian" else "--little-endian";
in runCommand "make-jffs2" {
endian = if pkgs.stdenv.isBigEndian then "--big-endian" else "--little-endian";
in
runCommand "make-jffs2"
{
depsBuildBuild = [ mtdutils ];
} ''
}
''
tree=${o.bootablerootdir}
(cd $tree && mkfs.jffs2 --compression-mode=size ${endian} -e ${toString config.hardware.flash.eraseBlockSize} --enable-compressor=lzo --pad --root . --output $out --squash --faketime )
'';

View File

@ -1,14 +1,15 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkOption types;
o = config.system.outputs;
phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024);
in {
in
{
options.system.outputs = {
mbrimage = mkOption {
type = types.package;
@ -28,9 +29,12 @@ in {
mbrimage =
let
o = config.system.outputs;
in pkgs.runCommand "mbrimage" {
in
pkgs.runCommand "mbrimage"
{
depsBuildBuild = [ pkgs.pkgsBuildBuild.util-linux ];
} ''
}
''
# leave 4 sectors at start for partition table
# and alignment to 2048 bytes (does that help?)
dd if=${o.rootfs} of=$out bs=512 seek=4 conv=sync

View File

@ -1,13 +1,14 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (config.boot) tftp;
in {
in
{
options.system.outputs = {
firmware = mkOption {
type = types.package;
@ -60,10 +61,12 @@ in {
config = {
kernel = {
config = {
config =
{
# this needs to be conditional on "not qemu"
MTD_SPLIT_UIMAGE_FW = "y";
} // lib.optionalAttrs (pkgs.stdenv.isMips) {
}
// lib.optionalAttrs (pkgs.stdenv.isMips) {
# https://stackoverflow.com/questions/26466470/can-the-logical-erase-block-size-of-an-mtd-device-be-increased
MTD_SPI_NOR_USE_4K_SECTORS = "n";
};
@ -78,12 +81,15 @@ in {
let
o = config.system.outputs;
bs = toString config.hardware.flash.eraseBlockSize;
in pkgs.runCommand "firmware" {} ''
in
pkgs.runCommand "firmware" { } ''
dd if=${o.uimage} of=$out bs=${bs} conv=sync
dd if=${o.rootfs} of=$out bs=${bs} conv=sync,nocreat,notrunc oflag=append
'';
mtdimage =
let o = config.system.outputs; in
let
o = config.system.outputs;
in
# could use trivial-builders.linkFarmFromDrvs here?
pkgs.runCommand "mtdimage" { } ''
mkdir $out

View File

@ -10,8 +10,7 @@ let
in
{
config = mkIf (config.rootfsType == "squashfs") {
system.outputs.rootfs =
liminix.builders.squashfs config.filesystem.contents;
system.outputs.rootfs = liminix.builders.squashfs config.filesystem.contents;
kernel.config = {
SQUASHFS = "y";
SQUASHFS_XZ = "y";

View File

@ -1,11 +1,16 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkEnableOption mkOption mkIf types;
inherit (lib)
mkEnableOption
mkOption
mkIf
types
;
inherit (pkgs) runCommand;
in
{
@ -22,7 +27,6 @@ in
};
};
config = {
system.outputs.systemConfiguration =
pkgs.systemconfig config.filesystem.contents;
system.outputs.systemConfiguration = pkgs.systemconfig config.filesystem.contents;
};
}

View File

@ -1,15 +1,16 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkOption types concatStringsSep;
cfg = config.boot.tftp;
hw = config.hardware;
arch = pkgs.stdenv.hostPlatform.linuxArch;
in {
in
{
imports = [ ../ramdisk.nix ];
options.boot.tftp = {
freeSpaceBytes = mkOption {
@ -17,7 +18,10 @@ in {
default = 0;
};
kernelFormat = mkOption {
type = types.enum [ "zimage" "uimage" ];
type = types.enum [
"zimage"
"uimage"
];
default = "uimage";
};
compressRoot = mkOption {
@ -61,14 +65,22 @@ in {
assert config.rootfsType != "ubifs";
let
o = config.system.outputs;
image = let choices = {
image =
let
choices = {
uimage = o.uimage;
zimage = o.kernel.zImage;
}; in choices.${cfg.kernelFormat};
bootCommand = let choices = {
};
in
choices.${cfg.kernelFormat};
bootCommand =
let
choices = {
uimage = "bootm";
zimage = "bootz";
}; in choices.${cfg.kernelFormat};
};
in
choices.${cfg.kernelFormat};
cmdline = concatStringsSep " " config.boot.commandLine;
objcopy = "${pkgs.stdenv.cc.bintools.targetPrefix}objcopy";
@ -77,7 +89,16 @@ in {
rm -f vmlinux.bin.lzma ; lzma -k -z vmlinux.bin
'';
in
pkgs.runCommand "tftpboot" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc pkgs.stdenv.cc ubootTools ]; } ''
pkgs.runCommand "tftpboot"
{
nativeBuildInputs = with pkgs.pkgsBuildBuild; [
lzma
dtc
pkgs.stdenv.cc
ubootTools
];
}
''
mkdir $out
cd $out
binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
@ -97,14 +118,16 @@ in {
# end of the kernel is free
dtbStart=$(($rootfsStart + $rootfsSize))
${if cfg.compressRoot
then ''
${
if cfg.compressRoot then
''
lzma -z9cv ${o.rootfs} > rootfs.lz
rootfsLzStart=$dtbStart
rootfsLzSize=$(binsize rootfs.lz)
dtbStart=$(($dtbStart + $rootfsLzSize))
''
else ''
else
''
ln -s ${o.rootfs} rootfs
''
}
@ -128,7 +151,9 @@ in {
dtbSize=$(binsize ./dtb )
${if cfg.appendDTB then ''
${
if cfg.appendDTB then
''
imageStart=$dtbStart
# re-package image with updated dtb
cat ${o.kernel} > vmlinux.elf
@ -138,25 +163,26 @@ in {
# dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1
tftpcmd="tftpboot $(hex $imageStart) result/image "
bootcmd="bootm $(hex $imageStart)"
'' else ''
''
else
''
imageStart=$(($dtbStart + $dtbSize))
tftpcmd="tftpboot $(hex $imageStart) result/image; tftpboot $(hex $dtbStart) result/dtb "
ln -s ${image} image
bootcmd="${bootCommand} $(hex $imageStart) - $(hex $dtbStart)"
''}
''
}
cat > boot.scr << EOF
setenv serverip ${cfg.serverip}
setenv ipaddr ${cfg.ipaddr}
${
if cfg.compressRoot
then "tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
else "tftpboot $(hex $rootfsStart) result/rootfs"
if cfg.compressRoot then
"tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
else
"tftpboot $(hex $rootfsStart) result/rootfs"
}; $tftpcmd
${if cfg.compressRoot
then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart); "
else ""
} $bootcmd
${if cfg.compressRoot then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart); " else ""} $bootcmd
EOF
'';

View File

@ -1,14 +1,15 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkOption types;
o = config.system.outputs;
cfg = config.tplink-safeloader;
in {
in
{
options.tplink-safeloader = {
board = mkOption {
type = types.str;
@ -53,7 +54,8 @@ in {
config = {
system.outputs = rec {
tplink-safeloader =
pkgs.runCommand "tplink" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ firmware-utils ]; } ''
pkgs.runCommand "tplink" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ firmware-utils ]; }
''
tplink-safeloader -B "${cfg.board}" -k "${o.uimage}" -r "${o.rootfs}" -o $out
'';
};

View File

@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf mkOption types;
@ -25,9 +25,12 @@ in
let
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
cfg = config.hardware.ubi;
in runCommand "mkfs.ubifs" {
in
runCommand "mkfs.ubifs"
{
depsBuildBuild = [ mtdutils ];
} ''
}
''
mkdir tmp
tree=${o.bootablerootdir}
mkfs.ubifs -x favor_lzo -c ${cfg.maxLEBcount} -m ${cfg.minIOSize} -e ${cfg.logicalEraseBlockSize} -y -r $tree --output $out --squash-uids -o $out

View File

@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf mkOption types;
@ -14,7 +14,8 @@ let
tftpboot $loadaddr result/rootfs
ubi write $loadaddr liminix $filesize
'';
in {
in
{
options.system.outputs = {
ubimage = mkOption {
type = types.package;
@ -110,7 +111,9 @@ variable to change)
config.system.outputs.ubimage =
assert config.rootfsType == "ubifs";
let o = config.system.outputs; in
let
o = config.system.outputs;
in
pkgs.runCommand "ubimage" { } ''
mkdir $out
cd $out

View File

@ -1,11 +1,17 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf mkOption types concatStringsSep optionalString;
inherit (lib)
mkIf
mkOption
types
concatStringsSep
optionalString
;
in
{
imports = [
@ -34,7 +40,13 @@ in
system.outputs.ubivolume =
let
inherit (pkgs.pkgsBuildBuild) runCommand;
ubiVolume = ({ name, volumeId, image, flags ? [] }:
ubiVolume = (
{
name,
volumeId,
image,
flags ? [ ],
}:
''
[${name}]
mode=ubi
@ -51,26 +63,32 @@ in
${optionalString (flags != [ ]) ''
vol_flags=${concatStringsSep "," flags}
''}
'');
''
);
ubiImage = (volumes:
ubiImage = (
volumes:
let
ubinizeConfig = pkgs.writeText "ubinize.conf" (concatStringsSep "\n" volumes);
inherit (pkgs.pkgsBuildBuild) mtdutils;
in
runCommand "ubinize" {
runCommand "ubinize"
{
depsBuildBuild = [ mtdutils ];
# block size := 128kb
# page size := 2048
# ubninize opts := -E 5
} ''
}
''
ubinize -Q "$SOURCE_DATE_EPOCH" -o $out \
-p ${config.hardware.ubi.physicalEraseBlockSize} -m ${config.hardware.ubi.minIOSize} \
-e ${config.hardware.ubi.logicalEraseBlockSize} \
${ubinizeConfig}
'');
''
);
ubiDisk = ({ initramfs }:
ubiDisk = (
{ initramfs }:
let
initramfsUbi = ubiVolume {
name = "rootfs";
@ -81,7 +99,8 @@ in
in
ubiImage [
initramfsUbi
]);
]
);
disk = ubiDisk {
initramfs = config.system.outputs.rootfs; # ???

View File

@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf;
@ -25,8 +25,7 @@ in
'';
};
config.system.outputs.updater =
runCommand "buildUpdater" { } ''
config.system.outputs.updater = runCommand "buildUpdater" { } ''
mkdir -p $out/bin $out/etc
cp ${o.kernel.config} $out/etc/kconfig
substitute ${./update.sh} $out/bin/update.sh \

View File

@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkOption types concatStringsSep;
@ -49,12 +49,15 @@ in
let
inherit (config.system.outputs) rootfs kernel manifest;
cmdline = builtins.toJSON (concatStringsSep " " config.boot.commandLine);
makeBootableImage = pkgs.runCommandCC "objcopy" {}
(if pkgs.stdenv.hostPlatform.isAarch
then "${pkgs.stdenv.cc.targetPrefix}objcopy -O binary -R .comment -S ${kernel} $out"
else "cp ${kernel} $out");
makeBootableImage = pkgs.runCommandCC "objcopy" { } (
if pkgs.stdenv.hostPlatform.isAarch then
"${pkgs.stdenv.cc.targetPrefix}objcopy -O binary -R .comment -S ${kernel} $out"
else
"cp ${kernel} $out"
);
phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024);
in pkgs.runCommand "vmroot" {} ''
in
pkgs.runCommand "vmroot" { } ''
mkdir $out
cd $out
ln -s ${rootfs} rootfs

View File

@ -1,13 +1,14 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkIf mkOption types;
models = "6b e1 6f e1 ff ff ff ff ff ff";
in {
in
{
options.system.outputs = {
zyxel-nwa-fit = mkOption {
type = types.package;
@ -62,9 +63,14 @@ on a system with pre-existing firmware and OS.
};
'';
in
pkgs.runCommand "zyxel-nwa-fit-${config.boot.imageType}" {
nativeBuildInputs = [ pkgs.pkgsBuildBuild.ubootTools pkgs.pkgsBuildBuild.dtc ];
} ''
pkgs.runCommand "zyxel-nwa-fit-${config.boot.imageType}"
{
nativeBuildInputs = [
pkgs.pkgsBuildBuild.ubootTools
pkgs.pkgsBuildBuild.dtc
];
}
''
mkimage -f ${dts} $out
'';
};

View File

@ -1,16 +1,28 @@
{ writeAshScript, liminix, svc, lib, serviceFns, output-template }:
{
writeAshScript,
liminix,
svc,
lib,
serviceFns,
output-template,
}:
{
command,
name,
debug
, username,
debug,
username,
password,
lcpEcho,
ppp-options,
dependencies ? []
dependencies ? [ ],
}:
let
inherit (lib) optional optionals escapeShellArgs concatStringsSep;
inherit (lib)
optional
optionals
escapeShellArgs
concatStringsSep
;
inherit (liminix.services) longrun;
inherit (builtins) toJSON toString typeOf;
@ -37,34 +49,60 @@ let
test -e ifname && echo >/proc/self/fd/10
'';
literal_or_output =
let v = o: ({
let
v =
o:
(
{
string = toJSON;
int = toJSON;
lambda = (o: "output(${toJSON (o "service")}, ${toJSON (o "path")})");
}.${typeOf o}) o;
in o: "{{ ${v o} }}";
}
.${typeOf o}
)
o;
in
o: "{{ ${v o} }}";
ppp-options' =
["+ipv6" "noauth"]
[
"+ipv6"
"noauth"
]
++ optional debug "debug"
++ optionals (username != null) ["name" (literal_or_output username)]
++ optionals (password != null) ["password" (literal_or_output password)]
++ optionals (username != null) [
"name"
(literal_or_output username)
]
++ optionals (password != null) [
"password"
(literal_or_output password)
]
++ optional lcpEcho.adaptive "lcp-echo-adaptive"
++ optionals (lcpEcho.interval != null)
["lcp-echo-interval" (toString lcpEcho.interval)]
++ optionals (lcpEcho.failure != null)
["lcp-echo-failure" (toString lcpEcho.failure)]
++ optionals (lcpEcho.interval != null) [
"lcp-echo-interval"
(toString lcpEcho.interval)
]
++ optionals (lcpEcho.failure != null) [
"lcp-echo-failure"
(toString lcpEcho.failure)
]
++ ppp-options
++ ["ip-up-script" ip-up
"ipv6-up-script" ip6-up
"ipparam" name
++ [
"ip-up-script"
ip-up
"ipv6-up-script"
ip6-up
"ipparam"
name
"nodetach"
# usepeerdns requests DNS servers from peer (which is good),
# then attempts to write them to /nix/store/xxxx/ppp/resolv.conf
# which causes an unsightly but inconsequential error message
"usepeerdns"
"nodefaultroute"
"logfd" "2"
"logfd"
"2"
];
service = longrun {
inherit name;
@ -77,12 +115,15 @@ let
${command}
'';
notification-fd = 10;
timeout-up = if lcpEcho.failure != null
then (10 + lcpEcho.failure * lcpEcho.interval) * 1000
else 60 * 1000;
timeout-up =
if lcpEcho.failure != null then (10 + lcpEcho.failure * lcpEcho.interval) * 1000 else 60 * 1000;
inherit dependencies;
};
in svc.secrets.subscriber.build {
watch = lib.filter (n: typeOf n=="lambda") [ username password ];
in
svc.secrets.subscriber.build {
watch = lib.filter (n: typeOf n == "lambda") [
username
password
];
inherit service;
}

View File

@ -13,18 +13,24 @@
## conjunction with a DHCP uplink, or other more creative forms of
## network connection
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
mkStringOption =
description: mkOption {
description:
mkOption {
type = types.nullOr types.str;
default = null;
inherit description;
};
in {
in
{
imports = [ ../secrets ];
options = {
system.service.pppoe = mkOption {

View File

@ -7,14 +7,15 @@
writeAshScript,
writeText,
xl2tpd,
callPackage
callPackage,
}:
{ lns,
{
lns,
ppp-options,
lcpEcho,
username,
password,
debug
debug,
}:
let
name = "${lns}.l2tp";
@ -31,8 +32,16 @@ let
max redials = 2 # this gives 1 actual retry, as xl2tpd can't count
'';
control = "/run/${name}/control";
in common {
inherit name debug username password lcpEcho ppp-options;
in
common {
inherit
name
debug
username
password
lcpEcho
ppp-options
;
command = ''
touch ${control}
exec ${xl2tpd}/bin/xl2tpd -D -p /run/${name}/${name}.pid -c ${conf} -C ${control}

View File

@ -7,22 +7,32 @@
serviceFns,
svc,
writeAshScript,
callPackage
callPackage,
}:
{ interface,
{
interface,
ppp-options,
lcpEcho,
username,
password,
debug
debug,
}:
let
name = "${interface.name}.pppoe";
common = callPackage ./common.nix { inherit svc; };
timeoutOpt = if lcpEcho.interval != null then "-T ${builtins.toString (4 * lcpEcho.interval)}" else "";
in common {
inherit name debug username password lcpEcho ppp-options;
timeoutOpt =
if lcpEcho.interval != null then "-T ${builtins.toString (4 * lcpEcho.interval)}" else "";
in
common {
inherit
name
debug
username
password
lcpEcho
ppp-options
;
command = ''
exec ${ppp}/bin/pppd pty "${pppoe}/bin/pppoe ${timeoutOpt} -I $(output ${interface} ifname)" file /run/${name}/ppp-options
'';

View File

@ -1,8 +1,18 @@
{ config, pkgs, lib, ... } :
{
config,
pkgs,
lib,
...
}:
let
svc = config.system.service;
cfg = config.profile.gateway;
inherit (lib) mkOption mkEnableOption mkIf types;
inherit (lib)
mkOption
mkEnableOption
mkIf
types
;
inherit (pkgs) liminix serviceFns;
inherit (liminix.services) bundle oneshot;
hostaps =
@ -14,18 +24,21 @@ let
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
};
in lib.mapAttrs'
(name : value :
in
lib.mapAttrs' (
name: value:
let
attrs = defaults // { ssid = name; } // value;
in lib.nameValuePair
"hostap-${name}"
(svc.hostapd.build {
in
lib.nameValuePair "hostap-${name}" (
svc.hostapd.build {
interface = attrs.interface;
params = lib.filterAttrs (k: v: k != "interface") attrs;
}))
cfg.wireless.networks;
in {
}
)
) cfg.wireless.networks;
in
{
options.profile.gateway = {
lan = {
@ -82,9 +95,12 @@ in {
];
config = {
services.int = svc.network.address.build ({
services.int = svc.network.address.build (
{
interface = svc.bridge.primary.build { ifname = "int"; };
} // cfg.lan.address);
}
// cfg.lan.address
);
services.bridge = svc.bridge.members.build {
primary = config.services.int;
@ -113,12 +129,15 @@ in {
})
];
};
in mkIf cfg.wan.dhcp6.enable bundl;
in
mkIf cfg.wan.dhcp6.enable bundl;
services.dns =
let interface = config.services.int;
let
interface = config.services.int;
dcfg = cfg.lan.dhcp;
in svc.dnsmasq.build {
in
svc.dnsmasq.build {
resolvconf = config.services.resolvconf;
inherit interface;
ranges = [
@ -147,11 +166,12 @@ in {
interface = config.services.wan;
};
services.firewall = mkIf cfg.firewall.enable
(svc.firewall.build {
services.firewall = mkIf cfg.firewall.enable (
svc.firewall.build {
extraRules = cfg.firewall.rules;
inherit (cfg.firewall) zones;
});
}
);
services.resolvconf = oneshot rec {
dependencies = [ config.services.wan ];
@ -166,8 +186,10 @@ in {
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in dir {
let
inherit (pkgs.pseudofile) dir symlink;
in
dir {
etc = dir {
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
};

View File

@ -3,7 +3,8 @@
pkgs,
lib,
...
}: let
}:
let
inherit (pkgs) liminix;
inherit (lib) mkOption types;
@ -22,19 +23,22 @@
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
};
in lib.mapAttrs'
(name : value :
in
lib.mapAttrs' (
name: value:
let
attrs = defaults // { ssid = name; } // value;
in lib.nameValuePair
"hostap-${name}"
(svc.hostapd.build {
in
lib.nameValuePair "hostap-${name}" (
svc.hostapd.build {
interface = attrs.interface;
params = lib.filterAttrs (k: v: k != "interface") attrs;
}))
cfg.wireless.networks;
}
)
) cfg.wireless.networks;
in {
in
{
imports = [
../wlan.nix
../network

View File

@ -1,7 +1,8 @@
{ config, lib, ... }:
let
inherit (lib) mkIf mkEnableOption; # types concatStringsSep;
in {
in
{
options = {
boot = {
ramdisk = {

View File

@ -3,13 +3,18 @@
## Given a list of services, run each in turn until it exits, then
## runs the next.
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
inherit (pkgs.liminix.services) longrun;
in {
in
{
options = {
system.service.round-robin = mkOption {
description = "run services one at a time and failover to next";

View File

@ -1,20 +1,28 @@
{
liminix, lib, s6-rc-round-robin
liminix,
lib,
s6-rc-round-robin,
}:
{ services, name }:
let
inherit (liminix.services) oneshot longrun;
controlled-services = builtins.map
(s: s.overrideAttrs(o: { inherit controller; }))
services;
controller = let name' = "control-${name}"; in longrun {
controlled-services = builtins.map (
s:
s.overrideAttrs (o: {
inherit controller;
})
) services;
controller =
let
name' = "control-${name}";
in
longrun {
name = name';
run = ''
in_outputs ${name'}
exec ${s6-rc-round-robin}/bin/s6-rc-round-robin \
-p ${proxy.name} \
${lib.concatStringsSep " "
(builtins.map (f: f.name) controlled-services)}
${lib.concatStringsSep " " (builtins.map (f: f.name) controlled-services)}
'';
};
proxy = oneshot rec {
@ -29,4 +37,5 @@ let
)
'';
};
in proxy
in
proxy

View File

@ -1,27 +1,39 @@
{ config, pkgs, lib, lim, ... }:
{
config,
pkgs,
lib,
lim,
...
}:
let
inherit (pkgs)
execline
s6
s6-init-bin
s6-linux-init
stdenvNoCC;
stdenvNoCC
;
inherit (lib.lists) unique concatMap;
inherit (lib) concatStrings;
inherit (builtins) map;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) oneshot bundle longrun;
inherit (lib) mkIf mkEnableOption mkOption types;
inherit (lib)
mkIf
mkEnableOption
mkOption
types
;
cfg = config.logging;
logger =
let pipecmds =
["${s6}/bin/s6-log -bpd3 -- ${cfg.script} 1"] ++
(lib.optional (cfg ? persistent && cfg.persistent.enable)
"/bin/tee /dev/pmsg0") ++
(lib.optional cfg.shipping.enable
"${pkgs.logshipper}/bin/logtap ${cfg.shipping.socket} logshipper-socket-event");
in ''
let
pipecmds =
[ "${s6}/bin/s6-log -bpd3 -- ${cfg.script} 1" ]
++ (lib.optional (cfg ? persistent && cfg.persistent.enable) "/bin/tee /dev/pmsg0")
++ (lib.optional cfg.shipping.enable "${pkgs.logshipper}/bin/logtap ${cfg.shipping.socket} logshipper-socket-event");
in
''
#!${execline}/bin/execlineb -P
${execline}/bin/redirfd -w 1 /dev/null
${execline}/bin/redirfd -rnb 0 fifo
@ -41,13 +53,11 @@ let
# dependency
isControlled = s: s ? controller && s.controller != null;
deps = s : s.dependencies ++
lib.optional (isControlled s) s.controller;
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);
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
@ -62,9 +72,7 @@ let
down = "rm -r /run/services/controlled";
};
defaultStart =
builtins.filter
(s: !(isDependentOnControlled s)) allServices;
defaultStart = builtins.filter (s: !(isDependentOnControlled s)) allServices;
defaultDefaultTarget = bundle {
name = "default";
contents = defaultStart ++ [ controlled ];
@ -79,7 +87,10 @@ let
s6-init-scripts = stdenvNoCC.mkDerivation {
name = "s6-scripts";
src = ./scripts;
phases = ["unpackPhase" "installPhase" ];
phases = [
"unpackPhase"
"installPhase"
];
buildInputs = [ ];
installPhase = ''
mkdir $out
@ -89,7 +100,9 @@ let
};
service = dir {
s6-linux-init-runleveld = dir {
notification-fd = { file = "3"; };
notification-fd = {
file = "3";
};
run = {
file = ''
#!${execline}/bin/execlineb -P
@ -122,8 +135,13 @@ let
type = "i";
mode = "0600";
};
notification-fd = { file = "3"; };
run = { file = logger; mode = "0755"; };
notification-fd = {
file = "3";
};
run = {
file = logger;
mode = "0755";
};
};
getty = dir {
run = {
@ -166,7 +184,8 @@ let
${s6-linux-init}/bin/s6-linux-init-shutdown -a #{action} -- now
'';
empty = "#!${execline}/bin/execlineb -P\n";
in dir {
in
dir {
crash = {
file = quit "s6-svscan crashed. Rebooting.";
mode = "0755";
@ -212,13 +231,15 @@ let
};
};
in {
in
{
options = {
logging = {
shipping = {
enable = mkEnableOption "unix socket for log shipping";
socket = mkOption {
description = "socket pathname"; type = types.path;
description = "socket pathname";
type = types.path;
default = "/run/.log-shipping.sock";
};
service = mkOption {
@ -239,12 +260,21 @@ in {
};
};
imports = [
( {config, pkgs, lib, ...}:
(
{
config,
pkgs,
lib,
...
}:
let
cfg = config.logging;
pipeline = shipper: bundle {
pipeline =
shipper:
bundle {
name = "log-shipping-pipe";
contents = let
contents =
let
eat = longrun {
name = "log-shipping-pipe-eat";
run = ''
@ -258,12 +288,18 @@ in {
spew = shipper.override {
consumer-for = "log-shipping-pipe-eat";
};
in [ eat spew ];
in
[
eat
spew
];
};
in mkIf cfg.shipping.enable {
in
mkIf cfg.shipping.enable {
services.${cfg.shipping.service.name} = pipeline cfg.shipping.service;
}
)];
)
];
config = {
filesystem = dir {
@ -276,7 +312,9 @@ in {
scripts = symlink "${s6-init-scripts}/scripts";
env = dir { };
run-image = dir {
uncaught-logs = (dir {}) // {mode = "2750";};
uncaught-logs = (dir { }) // {
mode = "2750";
};
inherit service;
};
};

View File

@ -3,12 +3,18 @@
## various ways to manage secrets without writing them to the
## nix store
{ lib, pkgs, config, ...}:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
inherit (pkgs.liminix.services) longrun;
in {
in
{
options.system.service.secrets = {
outboard = mkOption {
description = "fetch secrets from external vault with https";
@ -76,9 +82,16 @@ in {
description = "how do we notify the service to regenerate its config";
default = "restart-all";
type = types.enum [
"restart" "restart-all"
"hup" "int" "quit" "kill" "term"
"winch" "usr1" "usr2"
"restart"
"restart-all"
"hup"
"int"
"quit"
"kill"
"term"
"winch"
"usr1"
"usr2"
];
};
};

View File

@ -1,11 +1,21 @@
{
liminix, lib, json-to-fstree, serviceFns
liminix,
lib,
json-to-fstree,
serviceFns,
}:
{
name,
url,
interval,
username,
password,
}:
{ name, url, interval, username, password } :
let
inherit (liminix.services) oneshot longrun;
inherit (lib) optionalString;
in longrun {
in
longrun {
inherit name;
buildInputs = [ json-to-fstree ];
run = ''

View File

@ -1,7 +1,16 @@
{
liminix, lib, lim, s6, s6-rc, watch-outputs
liminix,
lib,
lim,
s6,
s6-rc,
watch-outputs,
}:
{
watch,
service,
action,
}:
{ watch, service, action } :
let
inherit (liminix.services) oneshot longrun;
inherit (builtins) length head toString;
@ -11,7 +20,8 @@ let
watched-services = unique (map (f: f "service") watch);
paths = unique (map (f: f "path") watch);
restart-flag = {
restart-flag =
{
restart = "-r";
restart-all = "-R";
"hup" = "-s 1";
@ -22,16 +32,22 @@ let
"winch" = "-s 28";
"usr1" = "-s 10";
"usr2" = "-s 12";
}.${action};
}
.${action};
watched-service =
if length watched-services == 0
then null
else if length watched-services == 1
then head watched-services
else throw "cannot subscribe to more than one source service for secrets";
if length watched-services == 0 then
null
else if length watched-services == 1 then
head watched-services
else
throw "cannot subscribe to more than one source service for secrets";
watcher = let name' = "restart-${name}"; in longrun {
watcher =
let
name' = "restart-${name}";
in
longrun {
name = name';
run = ''
dir=/run/service/${name}
@ -42,10 +58,13 @@ let
${watch-outputs}/bin/watch-outputs ${restart-flag} ${name} ${watched-service.name} ${lib.concatStringsSep " " paths}
'';
};
in service.overrideAttrs(o: {
buildInputs = (lim.orEmpty o.buildInputs) ++
optional (watched-service != null) watcher;
dependencies = (lim.orEmpty o.dependencies) ++
optionals (watched-service != null)
[ watcher watched-service ];
in
service.overrideAttrs (o: {
buildInputs = (lim.orEmpty o.buildInputs) ++ optional (watched-service != null) watcher;
dependencies =
(lim.orEmpty o.dependencies)
++ optionals (watched-service != null) [
watcher
watched-service
];
})

View File

@ -1,11 +1,20 @@
{
liminix, lib, json-to-fstree, serviceFns, tangc
liminix,
lib,
json-to-fstree,
serviceFns,
tangc,
}:
{
name,
path,
interval,
}:
{ name, path, interval } :
let
inherit (liminix.services) longrun;
inherit (lib) optionalString;
in longrun {
in
longrun {
inherit name;
buildInputs = [ json-to-fstree ];
notification-fd = 10;

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