Compare commits

..

5 Commits

Author SHA1 Message Date
Linus Heckemann ee7f740a2f kernel: enable magic sysrq
This can be useful via /proc/sysrq-trigger or by sending a break on
the serial.
2024-03-07 01:07:21 +01:00
Linus Heckemann 242876d0d4 cudy-x6: don't set tftp serverip/ipaddr 2024-03-07 01:07:21 +01:00
Linus Heckemann c6f1cfccd3 cudy-x6: fix network interface names 2024-03-07 01:07:21 +01:00
Linus Heckemann 044af5efa3 hostapd: use trailing newlines rather than separating ones 2024-03-07 01:07:21 +01:00
Linus Heckemann 38934984d9 wip: cudy-x6 2024-03-02 23:15:17 +01:00
1617 changed files with 1305 additions and 5970 deletions

21
NEWS
View File

@ -83,23 +83,4 @@ sponsoring this development (and funding the hardware)
2024-02-21
New port! Thanks to Raito Bezarius, Liminix now runs on the Zyxel NWA50AX,
an MT7621 (MIPS EL) dual radio WiFi AP.
2024-04-29
The setup for using `levitate` has changed: now it accepts an entire
config fragment, not just a list of services. Hopefully this makes it
a bit more useful :-)
defaultProfile.packages = with pkgs; [
...
(levitate.override {
config = {
services = {
inherit (config.services) dhcpc sshd watchdog;
};
defaultProfile.packages = [ mtdutils ];
users.root.openssh.authorizedKeys.keys = secrets.root.keys;
};
})
];
an MT7621 (MIPS EL) dual radio WiFi AP.

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +0,0 @@
# This is for use with minicom, but needs you to configure it to
# use expect as its "Script program" instead of runscript. Try
# Ctrl+A O -> Filenames and paths -> D
log_user 0
log_file -a -open stderr
set f [open "result/boot.scr"]
send "version\r"
set timeout 60
while {[gets $f line] >= 0} {
puts stderr "next line $line\r"
puts stderr "waiting for prompt\r"
expect {
"ath>" {}
"BusyBox" { puts stderr "DONE"; exit 0 }
}
send "$line\r\n"
}
puts stderr "done\r\n"
close $f

View File

@ -4,10 +4,6 @@ let
inherit (lib) mkOption mkEnableOption mdDoc types optional optionals;
in {
options.bordervm = {
keys = mkOption {
type = types.listOf types.str;
default = [ ];
};
l2tp = {
host = mkOption {
description = mdDoc ''
@ -55,17 +51,18 @@ in {
<nixpkgs/nixos/modules/virtualisation/qemu-vm.nix>
];
config = {
boot.kernelParams = [ "loglevel=9" ];
boot.kernelParams = [
"loglevel=9"
];
systemd.services.pppoe =
let
conf = pkgs.writeText "kpppoed.toml" ''
interface_name = "eth1"
services = [ "myservice" ]
lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
ac_name = "kpppoed-1.0"
'';
in
{
let conf = pkgs.writeText "kpppoed.toml"
''
interface_name = "eth1"
services = [ "myservice" ]
lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
ac_name = "kpppoed-1.0"
'';
in {
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
serviceConfig = {
@ -79,36 +76,24 @@ in {
};
};
services.openssh.enable = true;
services.dnsmasq = {
enable = true;
resolveLocalQueries = false;
settings = {
# domain-needed = true;
dhcp-range = [ "10.0.0.10,10.0.0.240" ];
interface = "eth1";
};
};
systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
virtualisation = {
qemu = {
networkingOptions = [ ];
options =
[ ]
++ optional cfg.ethernet.pci.enable "-device vfio-pci,host=${cfg.ethernet.pci.id}"
++ optionals cfg.ethernet.usb.enable [
networkingOptions = [];
options = [] ++
optional cfg.ethernet.pci.enable
"-device vfio-pci,host=${cfg.ethernet.pci.id}" ++
optionals cfg.ethernet.usb.enable [
"-device usb-ehci,id=ehci"
"-device usb-host,bus=ehci.0,vendorid=${cfg.ethernet.usb.vendor},productid=${cfg.ethernet.usb.product}"
]
++ [
] ++ [
"-nographic"
"-serial mon:stdio"
];
};
sharedDirectories = {
liminix = {
securityModel = "none";
source = builtins.toString ./.;
target = "/home/liminix/liminix";
};
@ -123,7 +108,6 @@ in {
tufted
iptables
usbutils
busybox
];
security.sudo.wheelNeedsPassword = false;
networking = {
@ -133,17 +117,11 @@ in {
useDHCP = false;
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}];
};
nat = {
enable = true;
internalInterfaces = [ "eth1" ];
externalInterface = "eth0";
};
};
users.users.liminix = {
isNormalUser = true;
uid = 1000;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = cfg.keys;
extraGroups = [ "wheel"];
};
services.getty.autologinUser = "liminix";
};

View File

@ -1,12 +1,8 @@
{ ... }:
{...}:
{
bordervm = {
# ethernet.pci = { id = "01:00.0"; enable = true; };
ethernet.usb = {
vendor = "0x0bda";
product = "0x8153";
enable = true;
};
ethernet.usb = { vendor = "0x0bda"; product = "0x8153"; enable = true; };
l2tp = {
host = "l2tp.aa.net.uk";
};

60
ci.nix
View File

@ -1,12 +1,12 @@
{
nixpkgs,
unstable,
liminix,
...
}:
nixpkgs
, unstable
, liminix
, ... }:
let
pkgs = (import nixpkgs { });
borderVmConf = ./bordervm.conf-example.nix;
inherit (builtins) map;
pkgs = (import nixpkgs {});
borderVmConf = ./bordervm.conf-example.nix;
inherit (pkgs.lib.attrsets) genAttrs;
devices = [
"gl-ar750"
@ -27,35 +27,33 @@ let
}).outputs.default;
tests = import ./tests/ci.nix;
jobs =
(genAttrs devices for-device)
// tests
// {
buildEnv =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).buildEnv;
(genAttrs devices for-device) //
tests //
{
buildEnv = (import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).buildEnv;
doc =
let
json =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config =
{ ... }:
{
let json =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = {...} : {
imports = [ ./modules/all-modules.nix ];
};
}).outputs.optionsJson;
in
pkgs.stdenv.mkDerivation {
}).outputs.optionsJson;
installers = map (f: "system.outputs.${f}") [
"vmroot"
"mtdimage"
"ubimage"
];
inherit (pkgs.lib) concatStringsSep;
in pkgs.stdenv.mkDerivation {
name = "liminix-doc";
nativeBuildInputs = with pkgs; [
gnumake
sphinx
fennel
luaPackages.lyaml
gnumake sphinx fennel luaPackages.lyaml
];
src = ./.;
buildPhase = ''

View File

@ -1,39 +1,31 @@
{
deviceName ? null,
device ? (import ./devices/${deviceName}),
liminix-config ? <liminix-config>,
nixpkgs ? <nixpkgs>,
borderVmConf ? ./bordervm.conf.nix,
imageType ? "primary",
device
, liminix-config ? <liminix-config>
, nixpkgs ? <nixpkgs>
, borderVmConf ? ./bordervm.conf.nix
, imageType ? "primary"
}:
let
overlay = import ./overlay.nix;
pkgs = import nixpkgs (
device.system
// {
overlays = [ overlay ];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.6" # kernel backports needs python <3
"python-2.7.18.7"
];
};
}
);
pkgs = import nixpkgs (device.system // {
overlays = [overlay];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.6" # kernel backports needs python <3
"python-2.7.18.7"
];
};
});
eval = pkgs.lib.evalModules {
specialArgs = {
modulesPath = builtins.toString ./modules;
};
modules = [
{ _module.args = { inherit pkgs; inherit (pkgs) lim; }; }
./modules/hardware.nix
./modules/base.nix
./modules/busybox.nix
./modules/hostname.nix
./modules/kernel
device.module
liminix-config
./modules/s6
@ -49,14 +41,7 @@ let
borderVm = ((import <nixpkgs/nixos/lib/eval-config.nix>) {
system = builtins.currentSystem;
modules = [
{
nixpkgs.overlays = [
(final: prev: {
go-l2tp = final.callPackage ./pkgs/go-l2tp {};
tufted = final.callPackage ./pkgs/tufted {};
})
];
}
({ ... } : { nixpkgs.overlays = [ overlay ]; })
(import ./bordervm-configuration.nix)
borderVmConf
];
@ -87,7 +72,6 @@ in {
min-copy-closure
fennelrepl
lzma
lua
];
};
}

View File

@ -73,7 +73,7 @@
MTK_INFRACFG = "y";
MTK_PMIC_WRAP = "y";
NVMEM_MTK_EFUSE="y";
MTK_EFUSE="y";
# MTK_HSDMA="y";
MTK_SCPSYS="y";
MTK_SCPSYS_PM_DOMAINS="y";
@ -92,6 +92,7 @@
MEDIATEK_GE_PHY = "y";
# MEDIATEK_MT6577_AUXADC = "y";
# MEDIATEK_WATCHDOG = "y";
NET_MEDIATEK_SOC = "y";
NET_MEDIATEK_SOC_WED = "y";
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
@ -213,6 +214,7 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };

234
devices/cudy-x6/default.nix Normal file
View File

@ -0,0 +1,234 @@
{
system = {
crossSystem = {
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # mips32r2?
};
};
};
description = ''
Cudy X6
********************
Zyxel NWA50AX is quite close to the GL-MT300N-v2 "Mango" device, but it is based on the MT7621
chipset instead of the MT7628.
Installation
============
'';
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
mac80211 = pkgs.mac80211.override {
drivers = [ "mt7915e" ];
klibBuild = config.system.outputs.kernel.modulesupport;
};
# v204520220929
wlan_firmware = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_wa.bin";
hash = "sha256-wooyefzb0i8640+lwq3vNhcBXRFCtGuo+jiL7afZaKA=";
};
wlan_firmware' = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_wm.bin";
hash = "sha256-k62nQewRuKjBLd5R3RxU4F74YKnQx5zr6gqMMImqVQw=";
};
wlan_firmware'' = pkgs.fetchurl {
url = "https://github.com/openwrt/mt76/raw/1b88dd07f153b202e57fe29734806744ed006b0e/firmware/mt7915_rom_patch.bin";
hash = "sha256-ifriAjWzFACrxVWCANZpUaEZgB/0pdbhnTVQytx6ddg=";
};
in {
imports = [
# We include it to ensure the bridge functionality
# is available on the target kernel.
../../modules/bridge
../../modules/arch/mipsel.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/mtdimage.nix
];
filesystem = dir {
lib = dir {
firmware = dir {
mediatek = dir {
"mt7915_wa.bin" = symlink wlan_firmware;
"mt7915_wm.bin" = symlink wlan_firmware';
"mt7915_rom_patch.bin" = symlink wlan_firmware'';
};
};
};
};
hardware = {
rootDevice = "/dev/mtdblock5";
defaultOutput = "mtdimage";
loadAddress = lim.parseInt "0x80001000";
entryPoint = lim.parseInt "0x80001000";
# Aligned on 2kb.
alignment = 2048;
flash = {
address = lim.parseInt "0xbc050000";
eraseBlockSize = 65536;
size = lim.parseInt "0x1F80000";
};
dts = {
src = "${openwrt.src}/target/linux/ramips/dts/mt7621_cudy_x6-v1.dts";
includes = [
"${openwrt.src}/target/linux/ramips/dts"
];
};
networkInterfaces =
let
inherit (config.system.service.network) link;
in {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };
lan3 = link.build { ifname = "lan3"; };
lan4 = link.build { ifname = "lan4"; };
wlan0 = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
};
wlan1 = link.build {
ifname = "wlan1";
dependencies = [ mac80211 ];
};
};
};
boot = {
imageFormat = "fit";
tftp = {
# 5MB is nice.
freeSpaceBytes = 5 * 1024 * 1024;
loadAddress = lim.parseInt "0x2000000";
};
};
kernel = {
src = pkgs.fetchurl {
name = "linux.tar.gz";
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
};
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
'';
config = {
RALINK = "y";
PCI = "y";
PHY_MT7621_PCI = "y";
PCIE_MT7621 = "y";
SOC_MT7621 = "y";
CLK_MT7621 = "y";
CLOCKSOURCE_WATCHDOG = "y";
SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y";
SERIAL_OF_PLATFORM = "y";
SERIAL_8250_NR_UARTS = "3";
SERIAL_8250_RUNTIME_UARTS = "3";
SERIAL_MCTRL_GPIO = "y";
CONSOLE_LOGLEVEL_DEFAULT = "8";
CONSOLE_LOGLEVEL_QUIET = "4";
# MTD_UBI_BEB_LIMIT = "20";
# MTD_UBI_WL_THRESHOLD = "4096";
MTD = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_dev
MTD_RAW_NAND = "y";
MTD_NAND_MT7621 = "y";
MTD_NAND_MTK_BMT = "y"; # Bad-block Management Table
MTD_NAND_ECC_SW_HAMMING= "y";
MTD_SPI_NAND= "y";
MTD_OF_PARTS = "y";
MTD_NAND_CORE= "y";
MTD_SPLIT_FIRMWARE= "y";
MTD_SPLIT_FIT_FW= "y";
PINCTRL = "y";
PINCTRL_MT7621 = "y";
I2C = "y";
I2C_MT7621 = "y";
SPI = "y";
MTD_SPI_NOR = "y";
SPI_MT7621 = "y";
SPI_MASTER = "y";
SPI_MEM = "y";
REGULATOR = "y";
REGULATOR_FIXED_VOLTAGE = "y";
RESET_CONTROLLER = "y";
POWER_RESET = "y";
POWER_RESET_GPIO = "y";
POWER_SUPPLY = "y";
LED_TRIGGER_PHY = "y";
PCI_DISABLE_COMMON_QUIRKS = "y";
PCI_DOMAINS = "y";
PCI_DOMAINS_GENERIC = "y";
PCI_DRIVERS_GENERIC = "y";
PCS_MTK_LYNXI = "y";
SOC_BUS = "y";
NET = "y";
ETHERNET = "y";
WLAN = "y";
PHYLIB = "y";
AT803X_PHY = "y";
FIXED_PHY = "y";
GENERIC_PHY = "y";
NET_DSA = "y";
NET_DSA_MT7530 = "y";
NET_DSA_MT7530_MDIO = "y";
NET_DSA_TAG_MTK = "y";
NET_MEDIATEK_SOC = "y";
NET_SWITCHDEV = "y";
NET_VENDOR_MEDIATEK = "y";
SWPHY = "y";
GPIOLIB = "y";
GPIO_MT7621 = "y";
OF_GPIO = "y";
EARLY_PRINTK = "y";
NEW_LEDS = "y";
LEDS_TRIGGERS = "y";
LEDS_CLASS = "y"; # required by rt2x00lib
LEDS_CLASS_MULTICOLOR = "y";
LEDS_BRIGHTNESS_HW_CHANGED = "y";
PRINTK_TIME = "y";
} // lib.optionalAttrs (config.system.service ? vlan) {
SWCONFIG = "y";
} // lib.optionalAttrs (config.system.service ? watchdog) {
RALINK_WDT = "y"; # watchdog
MT7621_WDT = "y"; # or it might be this one
};
};
};
}

View File

@ -23,17 +23,12 @@
VIRTIO_BLK = "y";
VIRTIO_NET = "y";
};
conditionalConfig = {
WLAN= {
MAC80211_HWSIM = "m";
};
};
};
hardware =
let
mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
targets = ["mac80211_hwsim"];
mac80211 = pkgs.mac80211.override {
drivers = ["mac80211_hwsim"];
klibBuild = config.system.outputs.kernel.modulesupport;
};
in {
defaultOutput = "vmroot";

View File

@ -92,6 +92,7 @@
'';
};
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) interface;
in {
imports = [
../../modules/network
@ -124,14 +125,8 @@
networkInterfaces =
let inherit (config.system.service.network) link;
in {
lan = link.build {
ifname = "lan";
devpath = "/devices/platform/ahb/19000000.eth";
};
wan = link.build {
ifname = "wan";
devpath = "/devices/platform/ahb/1a000000.eth";
};
lan = link.build { ifname = "eth0"; };
wan = link.build { ifname = "eth1"; };
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
@ -154,7 +149,6 @@
};
boot.tftp = {
loadAddress = lim.parseInt "0x00A00000";
appendDTB = true;
};
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {

View File

@ -45,6 +45,7 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override {
targets = ["rt2800soc"];
@ -89,6 +90,19 @@
let
inherit (config.system.service.network) link;
inherit (config.system.service) vlan;
inherit (pkgs.liminix.services) oneshot;
swconfig = oneshot {
name = "swconfig";
up = ''
PATH=${pkgs.swconfig}/bin:$PATH
swconfig dev switch0 set reset
swconfig dev switch0 set enable_vlan 1
swconfig dev switch0 vlan 1 set ports '1 2 3 4 6t'
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; };
# lan and wan ports are both behind a switch on eth0
@ -96,11 +110,13 @@
ifname = "eth0.1";
primary = eth;
vid = "1";
dependencies = [swconfig eth];
};
wan = vlan.build {
ifname = "eth0.2";
primary = eth;
vid = "2";
dependencies = [swconfig eth];
};
wlan = link.build {
ifname = "wlan0";
@ -110,8 +126,7 @@
};
boot.tftp = {
loadAddress = lim.parseInt "0x00A00000";
appendDTB = true;
};
};
kernel = {
src = pkgs.fetchurl {
@ -121,7 +136,6 @@
};
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
${openwrt.applyPatches.rt2x00}
'';
config = {

View File

@ -38,6 +38,7 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
@ -96,7 +97,7 @@
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
down = "swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; dependencies = [swconfig]; };
@ -121,7 +122,6 @@
# 20MB seems to give enough room to uncompress the kernel
# without anything getting trodden on. 10MB was too small
loadAddress = lim.parseInt "0x1400000";
appendDTB = true;
};
kernel = {

View File

@ -26,7 +26,7 @@
# this device is described by the "qemu" device
installer = "vmroot";
module = { config, lim, ... }: {
module = {pkgs, config, lim, ... }: {
imports = [
../../modules/arch/aarch64.nix
../families/qemu.nix

View File

@ -24,7 +24,7 @@
'';
installer = "vmroot";
module = { config, lim, ... }: {
module = {pkgs, config, lim, ... }: {
imports = [
../../modules/arch/arm.nix
../families/qemu.nix

View File

@ -36,7 +36,7 @@
in the Development manual.
'';
module = { config, lib, lim, ... }: {
module = {pkgs, config, lib, lim, ... }: {
imports = [
../../modules/arch/mipseb.nix
../families/qemu.nix

View File

@ -419,6 +419,7 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };

View File

@ -155,6 +155,8 @@
module = {pkgs, config, lib, lim, ... }:
let
openwrt = pkgs.openwrt;
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
mtd_by_name_links = pkgs.liminix.services.oneshot rec {
@ -356,6 +358,7 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
en70000 = link.build {
# in armada-38x.dtsi this is eth0.

View File

@ -103,6 +103,8 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;

View File

@ -1,9 +1,11 @@
{ eval, lib, pkgs }:
let
inherit (lib) types;
conf = eval.config;
rootDir = builtins.toPath ./..;
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) [ "${rootDir}/" ];
optToDoc = name: opt: {
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix)
["${rootDir}/"];
optToDoc = name: opt : {
inherit name;
description = opt.description or null;
default = opt.default or null;
@ -24,6 +26,7 @@ let
let x = lib.mapAttrsToList optToDoc sd.parameters; in x;
}
else
item // { declarations = map stripAnyPrefixes item.declarations; };
item // { declarations = map stripAnyPrefixes item.declarations; };
in
builtins.map spliceServiceDefn (pkgs.lib.optionAttrSetToDocList eval.options)
builtins.map spliceServiceDefn
(pkgs.lib.optionAttrSetToDocList eval.options)

View File

@ -1,18 +1,24 @@
with import <nixpkgs> { };
with import <nixpkgs> {} ;
let
inherit (builtins) stringLength readDir filter;
devices = filter (n: n != "families") (lib.mapAttrsToList (n: t: n) (readDir ../devices));
texts = map (
n:
let
d = import ../devices/${n}/default.nix;
d' = {
description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
} // d;
in
d'.description
) devices;
devices = filter (n: n != "families")
(lib.mapAttrsToList (n: t: n) (readDir ../devices));
texts = map (n:
let d = import ../devices/${n}/default.nix;
d' = {
description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
} // d;
installer =
if d ? description && d ? installer
then ''
The default installation route for this device is
:ref:`system-outputs-${d.installer}`
''
else "";
in d'.description)
devices;
in
writeText "hwdoc" ''
Supported hardware

View File

@ -11,15 +11,15 @@
...
}: let
secrets = import ./extneder-secrets.nix;
inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) writeText serviceFns;
inherit (pkgs) writeText dropbear ifwait serviceFns;
svc = config.system.service;
in rec {
boot = {
tftp = {
serverip = "10.0.0.1";
ipaddr = "10.0.0.8";
serverip = "192.168.8.148";
ipaddr = "192.168.8.251";
};
};
@ -28,12 +28,34 @@ in rec {
../modules/network
../modules/vlan
../modules/ssh
../modules/usb.nix
../modules/watchdog
../modules/mount
];
hostname = "arhcive";
kernel = {
config = {
USB = "y";
USB_EHCI_HCD = "y";
USB_EHCI_HCD_PLATFORM = "y";
USB_OHCI_HCD = "y";
USB_OHCI_HCD_PLATFORM = "y";
USB_SUPPORT = "y";
USB_COMMON = "y";
USB_STORAGE = "y";
USB_STORAGE_DEBUG = "n";
USB_UAS = "y";
USB_ANNOUNCE_NEW_DEVICES = "y";
SCSI = "y";
BLK_DEV_SD = "y";
USB_PRINTER = "y";
MSDOS_PARTITION = "y";
EFI_PARTITION = "y";
EXT4_FS = "y";
EXT4_USE_FOR_EXT2 = "y";
FS_ENCRYPTION = "y";
};
};
services.dhcpc =
let iface = config.hardware.networkInterfaces.lan;
@ -83,7 +105,7 @@ in rec {
};
services.mount_external_disk = svc.mount.build {
partlabel = "backup-disk";
device = "LABEL=backup-disk";
mountpoint = "/srv";
fstype = "ext4";
};
@ -119,37 +141,23 @@ in rec {
secrets_file
services.mount_external_disk
config.hardware.networkInterfaces.lan
];
] ;
};
users.root = {
passwd = lib.mkForce secrets.root.passwd;
openssh.authorizedKeys.keys = secrets.root.keys;
# openssh.authorizedKeys.keys = [
# (builtins.readFile "/home/dan/.ssh/id_rsa.pub")
# ];
};
users.backup = {
uid = 500;
gid = 500;
gecos = "Storage owner";
dir = "/srv";
shell = "/dev/null";
uid=500; gid=500; gecos="Storage owner"; dir="/srv";
shell="/dev/null";
};
groups.backup = {
gid = 500;
usernames = [ "backup" ];
gid=500; usernames = ["backup"];
};
defaultProfile.packages = with pkgs; [
e2fsprogs
mtdutils
(levitate.override {
config = {
services = {
inherit (config.services) dhcpc sshd watchdog;
};
defaultProfile.packages = [ mtdutils ];
users.root.openssh.authorizedKeys.keys = secrets.root.keys;
};
})
];
defaultProfile.packages = with pkgs; [e2fsprogs strace tcpdump ];
}

View File

@ -5,9 +5,9 @@
# wherever the text "EDIT" appears - please consult the tutorial
# documentation for details.
{ config, pkgs, ... }:
{ config, pkgs, lib, ... } :
let
inherit (pkgs.liminix.services) bundle oneshot;
inherit (pkgs.liminix.services) bundle oneshot longrun;
inherit (pkgs) serviceFns;
# EDIT: you can pick your preferred RFC1918 address space
# for NATted connections, if you don't like this one.
@ -49,40 +49,31 @@ in rec {
country_code = "GB";
wpa_passphrase = "not a real wifi password";
hw_mode = "g";
hw_mode="g";
ieee80211n = 1;
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa_key_mgmt = "WPA-PSK";
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
wmm_enabled = 1;
};
};
services.int = svc.network.address.build {
interface = svc.bridge.primary.build { ifname = "int"; };
family = "inet";
address = "${ipv4LocalNet}.1";
prefixLength = 16;
family = "inet"; address = "${ipv4LocalNet}.1"; prefixLength = 16;
};
services.bridge = svc.bridge.members.build {
services.bridge = svc.bridge.members.build {
primary = services.int;
members = with config.hardware.networkInterfaces; [
wlan
lan
];
members = with config.hardware.networkInterfaces;
[ wlan lan ];
};
services.ntp = svc.ntp.build {
pools = {
"pool.ntp.org" = [ "iburst" ];
};
makestep = {
threshold = 1.0;
limit = 3;
};
pools = { "pool.ntp.org" = ["iburst"]; };
makestep = { threshold = 1.0; limit = 3; };
};
services.sshd = svc.ssh.build { };
@ -166,7 +157,9 @@ in rec {
interface = services.wan;
};
services.firewall = svc.firewall.build { };
services.firewall = svc.firewall.build {
ruleset = import ./demo-firewall.nix;
};
services.packet_forwarding = svc.network.forward.build { };
@ -203,5 +196,7 @@ in rec {
];
};
defaultProfile.packages = with pkgs; [ min-collect-garbage ];
defaultProfile.packages = with pkgs; [
min-collect-garbage
];
}

View File

@ -8,11 +8,9 @@
config,
pkgs,
lib,
modulesPath,
...
}: let
secrets = import ./extneder-secrets.nix;
svc = config.system.service;
in rec {
boot = {
tftp = {
@ -22,13 +20,47 @@ in rec {
};
imports = [
"${modulesPath}/profiles/wap.nix"
"${modulesPath}/vlan"
"${modulesPath}/ssh"
../modules/profiles/wap.nix
../modules/vlan
];
hostname = "extneder";
kernel = {
config = {
NETFILTER_XT_MATCH_CONNTRACK = "y";
IP6_NF_IPTABLES = "y"; # do we still need these
IP_NF_IPTABLES = "y"; # if using nftables directly
# these are copied from rotuer and need review.
# we're not running a firewall, so why do we need
# nftables config?
IP_NF_NAT = "y";
IP_NF_TARGET_MASQUERADE = "y";
NETFILTER = "y";
NETFILTER_ADVANCED = "y";
NETFILTER_XTABLES = "y";
NFT_COMPAT = "y";
NFT_CT = "y";
NFT_LOG = "y";
NFT_MASQ = "y";
NFT_NAT = "y";
NFT_REJECT = "y";
NFT_REJECT_INET = "y";
NF_CONNTRACK = "y";
NF_NAT = "y";
NF_NAT_MASQUERADE = "y";
NF_TABLES = "y";
NF_TABLES_INET = "y";
NF_TABLES_IPV4 = "y";
NF_TABLES_IPV6 = "y";
};
};
profile.wap = {
interfaces = with config.hardware.networkInterfaces; [
lan
@ -47,7 +79,6 @@ in rec {
};
};
services.sshd = svc.ssh.build {};
users.root.passwd = lib.mkForce secrets.root.passwd;
defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig];
}

View File

@ -1,5 +1,6 @@
{ config, pkgs, ... } :
{ config, pkgs, lib, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {

View File

@ -1,5 +1,6 @@
{ config, pkgs, ... } :
{ config, pkgs, lib, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {

View File

@ -1,141 +0,0 @@
{
config,
pkgs,
lib,
...
}: let
secrets = import ./extneder-secrets.nix;
rsecrets = import ./rotuer-secrets.nix;
# https://support.aa.net.uk/Category:Incoming_L2TP says:
# "Please use the DNS name (l2tp.aa.net.uk) instead of hardcoding an
# IP address; IP addresses can and do change. If you have to use an
# IP, use 194.4.172.12, but do check the DNS for l2tp.aa.net.uk in
# case it changes."
# but (1) we don't want to use the wwan stick's dns as our main
# resolver: it's provided by some mobile ISP and they aren't
# necessarily the best at providing unfettered services without
# deciding to do something weird; (2) it's not simple to arrange
# that xl2tpd gets a different resolver than every other process;
# (3) there's no way to specify an lns address to xl2tpd at runtime
# except by rewriting its config file. So what we will do is lookup
# the lns hostname using the mobile ISP's dns server and then refuse
# to start l2tp unless the expected lns address is one of the
# addresses returned. I think this satisfies "do check the DNS"
lns = { hostname = "l2tp.aaisp.net.uk"; address = "194.4.172.12"; };
inherit (pkgs.liminix.services) oneshot target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {
boot = {
tftp = {
serverip = "10.0.0.1";
ipaddr = "10.0.0.8";
};
};
imports = [
../modules/cdc-ncm
../modules/network
../modules/vlan
../modules/ssh
../modules/usb.nix
../modules/watchdog
../modules/mount
../modules/ppp
];
hostname = "thing";
services.wwan = svc.wwan.build {
apn = "data.uk";
username = "user";
password = "one2one";
authType = "chap";
};
services.dhcpc = svc.network.dhcp.client.build {
interface = config.services.wwan;
dependencies = [ config.services.hostname ];
};
services.sshd = svc.ssh.build { };
services.resolvconf = oneshot rec {
dependencies = [ services.l2tp ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
for i in ns1 ns2 ; do
ns=$(output ${services.l2tp} $i)
echo "nameserver $ns" >> resolv.conf
done
)
'';
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
};
services.lns-address = let
ns = "$(output_word ${services.dhcpc} dns 1)";
route-to-bootstrap-nameserver = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = ns;
dependencies = [services.dhcpc];
};
in oneshot rec {
name = "resolve-l2tp-server";
dependencies = [ services.dhcpc route-to-bootstrap-nameserver ];
up = ''
(in_outputs ${name}
DNSCACHEIP="${ns}" ${pkgs.s6-dns}/bin/s6-dnsip4 ${lns.hostname} \
> addresses
)
'';
};
services.l2tp =
let
check-address = oneshot rec {
name = "check-lns-address";
up = ''
grep -Fx ${lns.address} $(output_path ${services.lns-address} addresses)
'';
dependencies = [ services.lns-address ];
};
route = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = lns.address;
dependencies = [services.dhcpc check-address];
};
in svc.l2tp.build {
lns = lns.address;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" rsecrets.l2tp.name
"connect-delay" "5000"
"password" rsecrets.l2tp.password
];
dependencies = [config.services.lns-address route check-address];
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.l2tp} peer-address)";
target = "default";
dependencies = [services.l2tp];
};
# defaultProfile.packages = [ pkgs.go-l2tp ];
users.root = {
passwd = lib.mkForce secrets.root.passwd;
openssh.authorizedKeys.keys = secrets.root.keys;
};
}

View File

@ -1,6 +1,7 @@
{ config, pkgs, ... } :
let
inherit (pkgs.liminix.services) target;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs) writeText;
svc = config.system.service;
secrets-1 = {
ssid = "Zyxel 2G (N)";

View File

@ -3,8 +3,8 @@ let
inherit (pkgs) serviceFns;
svc = config.system.service;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) oneshot target;
some-util-linux = pkgs.runCommand "some-util-linux" { } ''
inherit (pkgs.liminix.services) oneshot longrun bundle target;
some-util-linux = pkgs.runCommand "some-util-linux" {} ''
mkdir -p $out/bin
cd ${pkgs.util-linux-small}/bin
cp fdisk sfdisk mkswap $out/bin
@ -53,7 +53,7 @@ in rec {
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = "default";
dependencies = [ services.dhcpc ];
dependencies = [services.dhcpc];
};
services.resolvconf = oneshot rec {

View File

@ -8,10 +8,12 @@
root = {
# mkpasswd -m sha512crypt
passwd = "$6$6pt0mpbgcB7kC2RJ$kSBoCYGyi1.qxt7dqmexLj1l8E6oTZJZmfGyJSsMYMW.jlsETxdgQSdv6ptOYDM7DHAwf6vLG0pz3UD31XBfC1";
openssh.authorizedKeys.keys = [ ];
openssh.authorizedKeys.keys = [
];
};
lan = {
prefix = "10.8.0";
};
}

View File

@ -6,16 +6,23 @@
# problems.
{ config, pkgs, lib, modulesPath, ... } :
{ config, pkgs, lib, ... } :
let
secrets = {
domainName = "fake.liminix.org";
firewallRules = { };
firewallRules = {};
} // (import ./rotuer-secrets.nix);
inherit (pkgs.liminix.services) oneshot longrun bundle;
inherit (pkgs) serviceFns;
svc = config.system.service;
wirelessConfig = {
wirelessConfig = {
country_code = "GB";
inherit (secrets) wpa_passphrase;
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa_key_mgmt = "WPA-PSK";
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
wmm_enabled = 1;
};
@ -29,62 +36,65 @@ in rec {
};
imports = [
"${modulesPath}/profiles/gateway.nix"
"${modulesPath}/schnapps"
"${modulesPath}/outputs/btrfs.nix"
"${modulesPath}/outputs/extlinux.nix"
../modules/wlan.nix
../modules/network
../modules/ppp
../modules/dnsmasq
../modules/dhcp6c
../modules/firewall
../modules/hostapd
../modules/bridge
../modules/ntp
../modules/schnapps
../modules/ssh
../modules/outputs/btrfs.nix
../modules/outputs/extlinux.nix
];
hostname = "rotuer";
rootfsType = "btrfs";
rootOptions = "subvol=@";
boot.loader.extlinux.enable = true;
profile.gateway = {
lan = {
interfaces = with config.hardware.networkInterfaces;
[
wlan wlan5
lan0 lan1 lan2 lan3 lan4
];
inherit (secrets.lan) prefix;
address = {
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);
localDomain = "lan";
};
};
wan = {
interface = config.hardware.networkInterfaces.wan;
username = secrets.l2tp.name;
password = secrets.l2tp.password;
dhcp6.enable = true;
};
firewall = {
enable = true;
rules = secrets.firewallRules;
};
wireless.networks = {
"${secrets.ssid}" = {
interface = config.hardware.networkInterfaces.wlan;
hw_mode = "g";
channel = "2";
ieee80211n = 1;
} // wirelessConfig;
"${secrets.ssid}5" = rec {
interface = config.hardware.networkInterfaces.wlan5;
hw_mode = "a";
channel = 36;
ht_capab = "[HT40+]";
vht_oper_chwidth = 1;
vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211n = 1;
ieee80211ac = 1;
} // wirelessConfig;
};
services.hostap = svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan;
params = {
ssid = secrets.ssid;
hw_mode="g";
channel = "2";
ieee80211n = 1;
} // wirelessConfig;
};
services.hostap5 = svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan5;
params = rec {
ssid = "${secrets.ssid}5";
hw_mode="a";
channel = 36;
ht_capab = "[HT40+]";
vht_oper_chwidth = 1;
vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211n = 1;
ieee80211ac = 1;
} // wirelessConfig;
};
services.int = svc.network.address.build {
interface = svc.bridge.primary.build { ifname = "int"; };
family = "inet"; address ="${secrets.lan.prefix}.1"; prefixLength = 24;
};
services.bridge = svc.bridge.members.build {
primary = services.int;
members = with config.hardware.networkInterfaces;
[ wlan
wlan5
lan0
lan1
lan2
lan3
lan4
];
};
services.ntp = svc.ntp.build {
@ -96,6 +106,95 @@ in rec {
users.root = secrets.root;
services.dns =
let interface = services.int;
in svc.dnsmasq.build {
resolvconf = services.resolvconf;
inherit interface;
ranges = [
"${secrets.lan.prefix}.10,${secrets.lan.prefix}.240"
# ra-stateless: sends router advertisements with the O and A
# bits set, and provides a stateless DHCP service. The client
# will use a SLAAC address, and use DHCP for other
# configuration information.
"::,constructor:$(output ${interface} ifname),ra-stateless"
];
# You can add static addresses for the DHCP server here. I'm
# not putting my actual MAC addresses in a public git repo ...
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
upstreams = [ "/${secrets.domainName}/" ];
domain = secrets.domainName;
};
services.wan = svc.pppoe.build {
interface = config.hardware.networkInterfaces.wan;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" secrets.l2tp.name
"password" secrets.l2tp.password
];
};
services.resolvconf = oneshot rec {
dependencies = [ services.wan ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
echo "nameserver $(output ${services.wan} ns1)" > resolv.conf
echo "nameserver $(output ${services.wan} ns2)" >> resolv.conf
chmod 0444 resolv.conf
)
'';
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.wan} address)";
target = "default";
dependencies = [ services.wan ];
};
services.defaultroute6 = svc.network.route.build {
via = "$(output ${services.wan} ipv6-peer-address)";
target = "default";
interface = services.wan;
};
services.firewall = svc.firewall.build {
ruleset =
let defaults = import ./demo-firewall.nix;
in lib.recursiveUpdate defaults secrets.firewallRules;
};
services.packet_forwarding = svc.network.forward.build { };
services.dhcp6c =
let client = svc.dhcp6c.client.build {
interface = services.wan;
};
in bundle {
name = "dhcp6c";
contents = [
(svc.dhcp6c.prefix.build {
inherit client;
interface = services.int;
})
(svc.dhcp6c.address.build {
inherit client;
interface = services.wan;
})
];
};
defaultProfile.packages = with pkgs; [
min-collect-garbage
nftables

View File

@ -1,5 +1,6 @@
{ config, pkgs, lim, ... } :
{ config, pkgs, lib, lim, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {

View File

@ -9,29 +9,29 @@
./busybox.nix
./dhcp6c
./dnsmasq
./outputs/ext4fs.nix
./firewall
./hardware.nix
./hostapd
./hostname.nix
./outputs/initramfs.nix
./outputs/jffs2.nix
./kernel
./mdevd.nix
./outputs/kexecboot.nix
./mount
./network
./ntp
./outputs.nix
./outputs/ext4fs.nix
./outputs/initramfs.nix
./outputs/jffs2.nix
./outputs/kexecboot.nix
./outputs/mtdimage.nix
./outputs/tftpboot.nix
./outputs/ubifs.nix
./outputs/ubimage.nix
./outputs/vmroot.nix
./outputs/ubimage.nix
./outputs/mtdimage.nix
./ppp
./ramdisk.nix
./squashfs.nix
./ssh
./outputs/tftpboot.nix
./outputs/ubifs.nix
./ubinize.nix
./users.nix
./vlan
./watchdog

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
{ pkgs, config, ...}:
{ lib, pkgs, config, ...}:
{
imports = [ ./mips.nix ];
config = {

View File

@ -1,4 +1,4 @@
{ config, ...}:
{ lib, pkgs, config, ...}:
{
imports = [ ./mips.nix ];
config = {

View File

@ -4,12 +4,17 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) address interface;
inherit (pkgs.liminix.services) bundle;
type_service = pkgs.liminix.lib.types.service;
in {
imports = [
./kernel # kernel is a separate module for doc purposes
];
options = {
defaultProfile = {
packages = mkOption {
@ -24,10 +29,6 @@ in {
services = mkOption {
type = types.attrsOf type_service;
};
system.callService = mkOption {
type = types.functionTo (types.functionTo types.anything);
};
filesystem = mkOption {
type = types.anything;
description = ''
@ -36,7 +37,7 @@ in {
'';
# internal = true; # probably a good case to make this internal
};
rootfsType = mkOption {
rootfsType = mkOption {
default = "squashfs";
type = types.enum [
"btrfs"
@ -46,7 +47,7 @@ in {
"ubifs"
];
};
rootOptions = mkOption {
rootOptions = mkOption {
type = types.nullOr types.str;
default = null;
};
@ -54,29 +55,20 @@ in {
boot = {
commandLine = mkOption {
type = types.listOf types.nonEmptyStr;
default = [ ];
default = [];
description = "Kernel command line";
};
commandLineDtbNode = mkOption {
type = types.enum [
"bootargs"
"bootargs-override"
];
type = types.enum [ "bootargs" "bootargs-override" ];
default = "bootargs";
description = "Kernel command line's devicetree node";
};
imageType = mkOption {
type = types.enum [
"primary"
"secondary"
];
type = types.enum [ "primary" "secondary" ];
default = "primary";
};
imageFormat = mkOption {
type = types.enum [
"fit"
"uimage"
];
type = types.enum ["fit" "uimage"];
default = "uimage";
};
tftp = {
@ -92,7 +84,7 @@ in {
};
# These names match the uboot environment variables. I reserve
# the right to change them if I think of better ones.
ipaddr = mkOption {
ipaddr = mkOption {
type = types.str;
description = ''
Our IP address to use when creating scripts to
@ -119,29 +111,6 @@ in {
"fw_devlink=off"
] ++ lib.optional (config.rootOptions != null) "rootflags=${config.rootOptions}";
system.callService = path : parameters :
let
typeChecked = caller: type: value:
let
inherit (lib) types mergeDefinitions;
defs = [{ file = caller; inherit value; }];
type' = types.submodule { options = type; };
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 {
inherit parameters;
build = { dependencies ? [], ... } @ args :
let
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";
dir = "/home/root/";

View File

@ -10,11 +10,10 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{
imports = [ ../ifwait ];
options = {
system.service.bridge = {
primary = mkOption { type = liminix.lib.types.serviceDefn; };
@ -28,7 +27,7 @@ in
description = "bridge interface name to create";
};
};
members = config.system.callService ./members.nix {
members = liminix.callService ./members.nix {
primary = mkOption {
type = liminix.lib.types.interface;
description = "primary bridge interface";
@ -48,5 +47,5 @@ in
# a better way to test for the existence of vlan config:
# maybe the module should set an `enabled` attribute?
BRIDGE_VLAN_FILTERING = "y";
};
};
}

View File

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

View File

@ -1,10 +1,12 @@
{
liminix
, ifwait
, lib
}:
{ ifname } :
let
inherit (liminix.services) oneshot;
inherit (liminix.services) bundle oneshot;
inherit (lib) mkOption types;
in oneshot rec {
name = "${ifname}.link";
up = ''

View File

@ -8,7 +8,7 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types mapAttrsToList;
inherit (lib) mkOption mkEnableOption types mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink;
inherit (lib.strings) toUpper;
@ -85,13 +85,10 @@ in {
};
};
filesystem = dir {
bin = dir (
{
busybox = symlink "${busybox}/bin/busybox";
sh = symlink "${busybox}/bin/busybox";
}
// makeLinks
);
bin = dir ({
busybox = symlink "${busybox}/bin/busybox";
sh = symlink "${busybox}/bin/busybox";
} // makeLinks);
};
};
}

View File

@ -1,31 +0,0 @@
{ config, pkgs, lib, ... }:
let
inherit (pkgs) liminix;
inherit (lib) mkOption types;
in {
imports = [
../service-trigger
];
options = {
system.service.wwan = mkOption {
type = liminix.lib.types.serviceDefn;
};
};
config = {
kernel.config = {
USB_NET_HUAWEI_CDC_NCM = "y";
USB_USBNET = "y";
USB_SERIAL = "y";
USB_SERIAL_OPTION = "y";
};
# https://www.0xf8.org/2017/01/flashing-a-huawei-e3372h-4g-lte-stick-from-hilink-to-stick-mode/
system.service.wwan = config.system.callService ./wwan.nix {
apn = mkOption { type = types.str; };
username = mkOption { type = types.str; };
password = mkOption { type = types.str; };
authType = mkOption { type = types.enum [ "pap" "chap" ]; };
};
};
}

View File

@ -1,67 +0,0 @@
{
liminix
, usb-modeswitch
, ppp
, lib
, svc
, uevent-watch
}:
{ apn, username, password, authType }:
let
inherit (liminix.services) oneshot;
authTypeNum = if authType == "pap" then "1" else "2";
chat = lib.escapeShellArgs [
# Your usb modem thing might present as a tty that you run PPP
# over, or as a network device ("ndis" or "ncm"). The latter
# kind is to be preferred, at least in principle, because it's
# faster. This initialization sequence works for the Huawei
# E3372, and took much swearing: the error messages are *awful*
"" "AT"
"OK" "ATZ"
# create PDP context
"OK" "AT+CGDCONT=1,\"IP\",\"${apn}\""
# activate PDP context
"OK" "AT+CGACT=1,1"
# setup username and password per requirements of sim provider.
# (caret is special to chat, so needs escaping in AT commands)
"OK" "AT\\^AUTHDATA=1,${authTypeNum},\"\",\"${password}\",\"${username}\""
# start the thing (I am choosing to read this as "NDIS DialUP")
"OK" "AT\\^NDISDUP=1,1"
"OK"
];
modeswitch = oneshot rec {
name = "modem-modeswitch";
controller = (svc.uevent-rule.build {
serviceName = name;
terms = { devtype = "usb_device"; product = "12d1/14fe/102"; };
});
up = ''
${usb-modeswitch}/bin/usb_modeswitch -v 12d1 -p 14fe --huawei-new-mode
'';
};
atz = oneshot rec {
name = "modem-atz";
dependencies = [ modeswitch ];
controller = (svc.uevent-rule.build {
serviceName = name;
terms = {
subsystem = "tty";
attrs = {
idVendor = "12d1";
idProduct = "1506";
};
};
symlink = "/dev/modem";
});
up = ''
ls -l /dev/modem
test -L /dev/modem || exit 1
${ppp}/bin/chat -s -v ${chat} 0<>/dev/modem 1>&0
'';
down = "${ppp}/bin/chat -v '' ATZ OK 0<>/dev/modem 1>&0";
};
in svc.network.link.build {
ifname = "wwan0";
dependencies = [ atz ];
}

View File

@ -2,9 +2,9 @@
writeFennel
, linotify
, anoia
, lualinux
, lua
}:
writeFennel "acquire-delegated-prefix" {
packages = [ linotify anoia lualinux ];
packages = [ linotify anoia lua.pkgs.luafilesystem ];
mainFunction = "run";
} ./acquire-delegated-prefix.fnl

View File

@ -1,8 +1,7 @@
(local subject (require :acquire-wan-address))
(import-macros { : expect= } :anoia.assert)
(local { : view } (require :fennel))
(local { : merge : dup } (require :anoia))
;; nix-shell --run "cd modules/dhcp6c && fennelrepl acquire-wan-address-test.fnl"
(local a1
{
@ -48,6 +47,19 @@
}
)
(macro expect [assertion]
(let [msg (.. "expectation failed: " (view assertion))]
`(when (not ,assertion)
(assert false ,msg))))
(macro expect= [actual expected]
`(let [ve# (view ,expected)
va# (view ,actual)]
(when (not (= ve# va#))
(assert false
(.. "\nexpected " ve# "\ngot " va#)
))))
(fn first-address []
(let [deleted
(subject.deletions

View File

@ -2,10 +2,9 @@
writeFennel
, linotify
, anoia
, lualinux
, lua
}:
writeFennel "acquire-wan-address" {
packages = [ linotify anoia lualinux ];
packages = [ linotify anoia lua.pkgs.luafilesystem ];
mainFunction = "run";
} ./acquire-wan-address.fnl

View File

@ -1,10 +1,12 @@
{
liminix
, lib
, callPackage
}:
{ client, interface } :
let
inherit (liminix.services) longrun;
inherit (lib) mkOption types;
name = "dhcp6c.addr.${client.name}.${interface.name}";
script = callPackage ./acquire-wan-address.nix { };
in longrun {

View File

@ -1,11 +1,13 @@
{
liminix
, lib
, odhcp6c
, odhcp-script
}:
{ interface } :
let
inherit (liminix.services) longrun;
inherit (lib) mkOption types;
name = "dhcp6c.${interface.name}";
in longrun {
inherit name;

View File

@ -12,6 +12,7 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{

View File

@ -1,10 +1,12 @@
{
liminix
, lib
, callPackage
}:
{ client, interface } :
let
inherit (liminix.services) longrun;
inherit (lib) mkOption types;
name = "dhcp6c.prefix.${client.name}.${interface.name}";
script = callPackage ./acquire-delegated-prefix.nix { };
in longrun {

View File

@ -18,7 +18,7 @@ let
name = "${interface.name}.dnsmasq";
inherit (liminix.services) longrun;
inherit (lib) concatStrings concatStringsSep mapAttrsToList;
hostOpt = name : { mac, v4, v6, leasetime }:
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

View File

@ -8,6 +8,7 @@
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
inherit (pkgs.liminix.services) oneshot;
kmodules = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
@ -55,14 +56,8 @@ in
config = {
system.service.firewall =
let svc = liminix.callService ./service.nix {
extraRules = mkOption {
type = types.attrsOf types.attrs;
description = "firewall ruleset";
default = {};
};
rules = mkOption {
ruleset = mkOption {
type = types.attrsOf types.attrs; # we could usefully tighten this a bit :-)
default = import ./default-rules.nix;
description = "firewall ruleset";
};
};
@ -73,17 +68,13 @@ in
};
in svc.build args' ;
};
programs.busybox.applets = [
"insmod" "rmmod"
];
kernel.config = {
NETFILTER = "y";
NETFILTER_ADVANCED = "y";
NETFILTER_NETLINK = "m";
NF_CONNTRACK = "m";
NETLINK_DIAG = "y";
IP6_NF_IPTABLES= "m";
IP_NF_IPTABLES = "m";
IP_NF_NAT = "m";

View File

@ -4,10 +4,12 @@
, firewallgen
, nftables
}:
{ rules, extraRules }:
{ ruleset }:
let
inherit (liminix.services) oneshot;
script = firewallgen "firewall.nft" (lib.recursiveUpdate rules extraRules);
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
script = firewallgen "firewall.nft" ruleset;
in oneshot {
name = "firewall";
up = script;

View File

@ -5,13 +5,14 @@
## you want to run on it, and would usually be set in the "device" file:
## :file:`devices/manuf-model/default.nix`
{ lib, ... }:
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
in
{
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
in {
options = {
boot = { };
boot = {
};
hardware = {
dts = {
src = mkOption {
@ -25,7 +26,7 @@ in
'';
};
includes = mkOption {
default = [ ];
default = [];
description = "List of directories to search for DTS includes (.dtsi files)";
type = types.listOf types.path;
};

View File

@ -7,7 +7,9 @@
{ interface, params} :
let
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList;
inherit (lib) concatStrings mapAttrsToList;
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
# This is not a friendly interface to configuring a wireless AP: it
# just passes everything straight through to the hostapd config.
@ -20,15 +22,14 @@ let
driver = "nl80211";
logger_syslog = "-1";
logger_syslog_level = 1;
ctrl_interface = "/run/hostapd";
ctrl_interface = "/run/hostapd.${name}";
ctrl_interface_group = 0;
};
conf = writeText "hostapd.conf"
(concatStringsSep
"\n"
(concatStrings
(mapAttrsToList
(name: value: "${name}=${toString value}")
(name: value: "${name}=${toString value}\n")
(defaults // params)));
in longrun {
inherit name;

View File

@ -1,18 +0,0 @@
{ config, pkgs, lib, ... } :
let
inherit (pkgs) liminix;
inherit (lib) mkOption types;
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; };
interface = mkOption {
type = liminix.lib.types.interface;
};
service = mkOption {
type = liminix.lib.types.service;
};
};
}

View File

@ -1,16 +0,0 @@
{ ifwait, liminix } :
{
state
, interface
, service
}:
let
inherit (liminix.services) longrun;
in longrun {
name = "ifwait.${interface.name}";
buildInputs = [ service ];
restart-on-upgrade = true;
run = ''
${ifwait}/bin/ifwait -s ${service.name} $(output ${interface} ifname) ${state}
'';
}

View File

@ -5,9 +5,14 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types ;
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) address interface;
inherit (pkgs.liminix.services) bundle;
inherit (pkgs) liminix;
type_service = pkgs.liminix.lib.types.service;
mergeConditionals = conf : conditions :
# for each key in conditions, if it is present in conf
# then merge the associated value into conf
@ -126,6 +131,8 @@ in {
# at boot time unless we disable trying to call it.
# https://lkml.org/lkml/2013/8/5/175
FW_LOADER_USER_HELPER = "n";
MAGIC_SYSRQ = "y";
};
};
};

View File

@ -1,30 +0,0 @@
{ config, pkgs, ...} :
let inherit (pkgs.liminix.services) oneshot longrun;
in {
config = {
services = rec {
mdevd = longrun {
name = "mdevd";
notification-fd = 3;
run = "${pkgs.mdevd}/bin/mdevd -D 3 -b 200000 -O4";
};
devout = longrun {
name = "devout";
notification-fd = 10;
run = "exec ${pkgs.devout}/bin/devout /run/devout.sock 4";
};
coldplug = oneshot {
name = "coldplug";
# would love to know what mdevd-coldplug/udevadm trigger does
# that this doesn't
up = ''
for i in $(find /sys -name uevent); do ( echo change > $i ) ; done
'';
dependencies = [
devout
mdevd
];
};
};
};
}

View File

@ -7,6 +7,11 @@
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
mkBoolOption = description : mkOption {
type = types.bool;
inherit description;
default = true;
};
in {
options = {
@ -14,39 +19,28 @@ in {
type = liminix.lib.types.serviceDefn;
};
};
imports = [ ../mdevd.nix ../service-trigger ];
config.system.service.mount =
let svc = config.system.callService ./service.nix {
partlabel = mkOption {
type = types.str;
example = "my-usb-stick";
};
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";
};
};
in svc // {
build = args:
let args' = args // {
dependencies = (args.dependencies or []) ++ [
config.services.mdevd
config.services.devout
];
};
in svc.build args' ;
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 = {

View File

@ -1,27 +1,18 @@
{
liminix
, lib
, svc
}:
{ partlabel, mountpoint, options, fstype }:
{ device, 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}";
controller = svc.uevent-rule.build {
serviceName = name;
symlink = device;
terms = {
partname = partlabel;
devtype = "partition";
};
};
in oneshot {
inherit name;
timeout-up = 3600;
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";
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}";
inherit controller;
}

View File

@ -1,5 +1,6 @@
{
liminix
, ifwait
, serviceFns
, lib
}:

View File

@ -17,7 +17,7 @@ let
ip address replace $ip/$mask dev $interface
(in_outputs ${name}
for i in lease mask ip router siaddr dns serverid subnet opt53 interface ; do
(printenv $i || true) > $i
printenv $i > $i
done)
}
case $action in
@ -40,7 +40,7 @@ let
'';
in longrun {
inherit name;
run = "exec /bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
run = "/bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
notification-fd = 10;
dependencies = [ interface ];
}

View File

@ -1,5 +1,7 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{ enableIPv4, enableIPv6 }:

View File

@ -1,5 +1,7 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{
@ -9,7 +11,8 @@
# if devpath is supplied, we rename the interface at that
# path to have the specified name.
let
inherit (liminix.services) oneshot;
inherit (liminix.services) longrun oneshot;
inherit (lib) concatStringsSep;
name = "${ifname}.link";
rename = if devpath != null
then ''

View File

@ -1,15 +1,15 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{ target, via, interface ? null, metric }:
let
inherit (liminix.services) oneshot;
with_dev = if interface != null then "dev $(output ${interface} ifname)" else "";
target_hash = builtins.substring 0 12 (builtins.hashString "sha256" target);
via_hash = builtins.substring 0 12 (builtins.hashString "sha256" via);
in oneshot {
name = "route-${target_hash}-${builtins.substring 0 12 (builtins.hashString "sha256" "${via_hash}-${if interface!=null then interface.name else ""}")}";
name = "route-${target}-${builtins.substring 0 12 (builtins.hashString "sha256" "${via}-${if interface!=null then interface.name else ""}")}";
up = ''
ip route add ${target} via ${via} metric ${toString metric} ${with_dev}
'';

View File

@ -1,6 +1,7 @@
{
liminix
, chrony
, serviceFns
, lib
, writeText
}:
@ -8,6 +9,10 @@ params:
let
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList;
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
serverOpts = types.listOf types.str;
configFile = p:
(mapAttrsToList (name: opts: "server ${name} ${concatStringsSep "" opts}")
p.servers)

View File

@ -1,12 +1,12 @@
{
config,
pkgs,
lib,
...
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (pkgs) liminix writeText;
inherit (pkgs) liminix callPackage writeText;
o = config.system.outputs;
in
{
@ -22,7 +22,7 @@ in
# but only part of one.
kernel = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
kernel
******
@ -42,7 +42,7 @@ in
};
dtb = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
dtb
***
@ -52,7 +52,7 @@ in
};
uimage = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
uimage
******
@ -68,7 +68,7 @@ in
};
manifest = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
Debugging aid. JSON rendition of config.filesystem, on
which can run "nix-store -q --tree" on it and find

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf;
inherit (lib) mkIf mkOption types;
o = config.system.outputs;
in
{

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf;
inherit (lib) mkIf mkOption types;
o = config.system.outputs;
in
{

View File

@ -6,7 +6,7 @@
}:
let
inherit (lib) mkEnableOption mkOption mkIf types;
inherit (pkgs) runCommand;
inherit (pkgs) runCommand callPackage writeText;
in
{
options = {

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf;
inherit (lib) mkIf mkOption types;
o = config.system.outputs;
in
{

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (lib) mkOption mkForce types concatStringsSep;
in {
imports = [ ../ramdisk.nix ];
options.system.outputs = {
@ -42,7 +42,8 @@ in {
boot-sh =
let
inherit (config.system.outputs) rootfs;
inherit (pkgs.lib.trivial) toHexString;
inherit (config.system.outputs) rootfs kernel;
cmdline = concatStringsSep " " config.boot.commandLine;
in
pkgs.buildPackages.runCommand "boot.sh.sh" {

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption types;
inherit (lib) mkOption types concatStringsSep;
o = config.system.outputs;
phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024);
in {

View File

@ -58,6 +58,7 @@ in {
system.outputs = rec {
tftpboot =
let
inherit (pkgs.lib.trivial) toHexString;
o = config.system.outputs;
image = let choices = {
uimage = o.uimage;
@ -121,7 +122,7 @@ in {
fdtput -p -t lx dtb /reserved-memory/$node reg $ac_prefix $(hex $rootfsStart) $sz_prefix $(hex $rootfsSize)
cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsSize}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
fdtput -t s dtb /chosen ${config.boot.commandLineDtbNode} "$cmd"
fdtput -t s dtb /chosen bootargs "$cmd"
dtbSize=$(binsize ./dtb )

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption types;
inherit (lib) mkOption types concatStringsSep;
o = config.system.outputs;
cfg = config.tplink-safeloader;
in {

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkOption types;
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
cfg = config.boot.tftp;
instructions = pkgs.writeText "env.scr" ''
setenv serverip ${cfg.serverip}

View File

@ -5,6 +5,7 @@
, ...
}:
let
inherit (pkgs) liminix;
inherit (lib) mkIf mkOption types concatStringsSep optionalString;
in
{

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkOption types;
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
models = "6b e1 6f e1 ff ff ff ff ff ff";
in {
options.system.outputs = {

View File

@ -17,9 +17,6 @@ in {
system.service.pppoe = mkOption {
type = liminix.lib.types.serviceDefn;
};
system.service.l2tp = mkOption {
type = liminix.lib.types.serviceDefn;
};
};
config = {
system.service.pppoe = pkgs.liminix.callService ./pppoe.nix {
@ -32,16 +29,6 @@ in {
description = "options supplied on ppp command line";
};
};
system.service.l2tp = pkgs.liminix.callService ./l2tp.nix {
lns = mkOption {
type = types.str;
description = "hostname or address of the L2TP network server";
};
ppp-options = mkOption {
type = types.listOf types.str;
description = "options supplied on ppp command line";
};
};
kernel = {
config = {
PPP = "y";
@ -49,8 +36,6 @@ in {
PPP_DEFLATE = "y";
PPP_ASYNC = "y";
PPP_SYNC_TTY = "y";
PPPOL2TP = "y";
L2TP = "y";
};
};
};

View File

@ -1,59 +0,0 @@
{
liminix
, writeAshScript
, writeText
, serviceFns
, xl2tpd
} :
{ lns, ppp-options }:
let
inherit (liminix.services) longrun;
name = "${lns}.l2tp";
ip-up = writeAshScript "ip-up" {} ''
. ${serviceFns}
(in_outputs ${name}
echo $1 > ifname
echo $2 > tty
echo $3 > speed
echo $4 > address
echo $5 > peer-address
echo $DNS1 > ns1
echo $DNS2 > ns2
)
echo >/proc/self/fd/10
'';
ip6-up = writeAshScript "ip6-up" {} ''
. ${serviceFns}
(in_outputs ${name}
echo $4 > ipv6-address
echo $5 > ipv6-peer-address
)
echo >/proc/self/fd/10
'';
ppp-options' = ppp-options ++ [
"ip-up-script" ip-up
"ipv6-up-script" ip6-up
"ipparam" name
"nodetach"
"usepeerdns"
"logfd" "2"
];
conf = writeText "xl2tpd.conf" ''
[lac upstream]
lns = ${lns}
require authentication = no
pppoptfile = ${writeText "ppp-options" ppp-options'}
autodial = yes
redial = yes
'';
control = "/run/xl2tpd/control-${name}";
in
longrun {
inherit name;
run = ''
mkdir -p /run/xl2tpd
touch ${control}
exec ${xl2tpd}/bin/xl2tpd -D -p /run/xl2tpd/${name}.pid -c ${conf} -C ${control}
'';
notification-fd = 10;
}

View File

@ -1,178 +0,0 @@
{ config, pkgs, lib, ... } :
let
svc = config.system.service;
cfg = config.profile.gateway;
inherit (lib) mkOption mkEnableOption mkIf types;
inherit (pkgs) liminix serviceFns;
inherit (liminix.services) bundle oneshot;
hostaps =
let
defaults = {
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa_key_mgmt = "WPA-PSK";
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
};
in lib.mapAttrs'
(name : value :
let
attrs = defaults // { ssid = name; } // value;
in lib.nameValuePair
"hostap-${name}"
(svc.hostapd.build {
interface = attrs.interface;
params = lib.filterAttrs (k: v: k != "interface") attrs;
}))
cfg.wireless.networks;
in {
options.profile.gateway = {
lan = {
interfaces = mkOption {
type = types.listOf liminix.lib.types.interface;
default = [];
};
address = mkOption {
type = types.attrs;
};
prefix = mkOption { type = types.str; };
dhcp = {
start = mkOption { type = types.int; };
end = mkOption { type = types.int; };
hosts = mkOption { type = types.attrs; };
localDomain = mkOption { type = types.str; };
};
};
firewall = {
enable = mkEnableOption "firewall";
rules = mkOption { type = types.attrsOf types.attrs; };
};
wan = {
interface = mkOption { type = liminix.lib.types.interface; };
username = mkOption { type = types.str; };
password = mkOption { type = types.str; };
dhcp6.enable = mkOption { type = types.bool; };
};
wireless = mkOption {
type = types.attrsOf types.anything;
};
};
imports = [
../wlan.nix
../network
../ppp
../dnsmasq
../dhcp6c
../firewall
../hostapd
../bridge
../ntp
../ssh
{ config.services = hostaps; }
];
config = {
services.int = svc.network.address.build ({
interface = svc.bridge.primary.build { ifname = "int"; };
} // cfg.lan.address);
services.bridge = svc.bridge.members.build {
primary = config.services.int;
members = cfg.lan.interfaces;
};
services.wan = svc.pppoe.build {
inherit (cfg.wan) interface;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" cfg.wan.username
"password" cfg.wan.password
];
};
services.packet_forwarding = svc.network.forward.build { };
services.dhcp6c =
let
client = svc.dhcp6c.client.build {
interface = config.services.wan;
};
bundl = bundle {
name = "dhcp6c";
contents = [
(svc.dhcp6c.prefix.build {
inherit client;
interface = config.services.int;
})
(svc.dhcp6c.address.build {
inherit client;
interface = config.services.wan;
})
];
};
in mkIf cfg.wan.dhcp6.enable bundl;
services.dns =
let interface = config.services.int;
dcfg = cfg.lan.dhcp;
in svc.dnsmasq.build {
resolvconf = config.services.resolvconf;
inherit interface;
ranges = [
"${cfg.lan.prefix}.${toString dcfg.start},${cfg.lan.prefix}.${toString dcfg.end}"
# ra-stateless: sends router advertisements with the O and A
# bits set, and provides a stateless DHCP service. The client
# will use a SLAAC address, and use DHCP for other
# configuration information.
"::,constructor:$(output ${interface} ifname),ra-stateless"
];
hosts = dcfg.hosts;
upstreams = [ "/${dcfg.localDomain}/" ];
domain = dcfg.localDomain;
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${config.services.wan} address)";
target = "default";
dependencies = [ config.services.wan ];
};
services.defaultroute6 = svc.network.route.build {
via = "$(output ${config.services.wan} ipv6-peer-address)";
target = "default";
interface = config.services.wan;
};
services.firewall = mkIf cfg.firewall.enable
(svc.firewall.build {
extraRules = cfg.firewall.rules;
});
services.resolvconf = oneshot rec {
dependencies = [ config.services.wan ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
echo "nameserver $(output ${config.services.wan} ns1)" > resolv.conf
echo "nameserver $(output ${config.services.wan} ns2)" >> resolv.conf
chmod 0444 resolv.conf
)
'';
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in dir {
etc = dir {
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
};
};
};
}

View File

@ -5,9 +5,9 @@
...
}: let
inherit (pkgs) liminix;
inherit (lib) mkOption types ;
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.liminix.services) oneshot target;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) serviceFns;
svc = config.system.service;
@ -40,6 +40,7 @@ in {
../network
../hostapd
../bridge
../ssh
{ config.services = hostaps; }
];
@ -53,6 +54,7 @@ in {
};
};
config = {
services.sshd = svc.ssh.build {};
services.int = svc.bridge.primary.build {
ifname = "int";

View File

@ -1,6 +1,11 @@
{ config, lib, ... }:
{
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkIf mkEnableOption; # types concatStringsSep;
inherit (lib) mkIf mkEnableOption mkOption; # types concatStringsSep;
in {
options = {
boot = {

View File

@ -1,4 +1,4 @@
{ config, pkgs, lib, ... }:
{ config, pkgs, ... }:
let
inherit (pkgs)
execline
@ -6,50 +6,14 @@ let
s6-init-bin
s6-linux-init
stdenvNoCC;
inherit (lib.lists) unique concatMap;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) oneshot bundle;
inherit (pkgs.liminix.services) bundle;
s6-rc-db =
let
# In the default bundle we need to have all the services
# in config.services except for controlled services and
# anything that depends on one. But we do need the controllers
# themselves.
# So, find all required services and their transitive
# dependencies and their controllers. remove all controlled
# services and all services that have a controlled service as
# dependency
isControlled = s : s ? controller && s.controller != null;
deps = s : s.dependencies ++
lib.optional (isControlled s) s.controller;
flatDeps = s : [s] ++ concatMap flatDeps (deps s);
allServices = unique (concatMap flatDeps (builtins.attrValues config.services));
isDependentOnControlled = s :
isControlled s ||
(lib.lists.any isDependentOnControlled s.dependencies);
# all controlled services depend on this oneshot, which
# makes a list of them so we can identify them at runtime
controlled = oneshot {
name = "controlled";
up = ''
mkdir -p /run/services/controlled
for s in $(s6-rc-db -d dependencies controlled); do
touch /run/services/controlled/$s
done
'';
down = "rm -r /run/services/controlled";
};
defaultStart =
builtins.filter
(s: !(isDependentOnControlled s)) allServices;
defaultDefaultTarget = bundle {
name = "default";
contents = defaultStart ++ [controlled];
contents = builtins.attrValues config.services;
};
servicesAttrs = {
default = defaultDefaultTarget;

View File

@ -34,7 +34,7 @@ fi
### If your services are managed by s6-rc:
### (replace /run/service with your scandir)
s6-rc-init -d -c /etc/s6-rc/compiled /run/service
s6-rc-init /run/service -d -c /etc/s6-rc/compiled
### 2. Starting the wanted set of services

View File

@ -1,4 +1,4 @@
{ config, pkgs, ... } :
{ config, pkgs, lib, ... } :
{
config = {
programs.busybox = {

View File

@ -1,37 +0,0 @@
# this is unlikely to be the final form or location of this code, it's
# an interim module which wraps the uevent-watch command
{ lib, pkgs, config, ... }:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
# inherit (pkgs.liminix.services) bundle;
in {
options = {
system.service.uevent-rule = mkOption {
description = "a service which starts other services based on device state (sysfs)";
type = liminix.lib.types.serviceDefn;
};
};
config = {
system.service.uevent-rule = liminix.callService ./rule.nix {
serviceName = mkOption {
description = "name of the service to run when the rule matches";
type = types.str;
};
terms = mkOption {
type = types.attrs;
example = {
devtype = "usb_device";
attrs.idVendor = "8086";
};
default = {};
};
symlink = mkOption {
description = "create symlink targeted on devpath";
type = types.nullOr types.str;
default = null;
};
};
};
}

View File

@ -1,23 +0,0 @@
{
liminix
, uevent-watch
, lib }:
{
serviceName, terms, symlink
}:
let
inherit (liminix.services) longrun;
inherit (lib.attrsets) collect mapAttrsRecursive;
inherit (lib.strings) concatStringsSep;
stringify = attrs :
concatStringsSep " "
(collect lib.isString
(mapAttrsRecursive
(path : value : "${concatStringsSep "." path}=${value}")
attrs));
termsString = stringify terms;
in longrun {
name = "watch-for-${serviceName}";
restart-on-upgrade = true;
run = "${uevent-watch}/bin/uevent-watch ${if symlink != null then "-n ${symlink}" else ""} -s ${serviceName} ${termsString}";
}

View File

@ -1,8 +1,8 @@
{
config,
pkgs,
lib,
...
config
, pkgs
, lib
, ...
}:
let
inherit (pkgs) liminix;

View File

@ -1,6 +1,7 @@
{
liminix
, dropbear
, serviceFns
, lib
}:
p :

View File

@ -1,7 +1,7 @@
# support for USB block devices and the common filesystems
# they're likely to provide
{ config, ... }:
{lib, config, ... }:
{
kernel = {
config = {
@ -24,6 +24,8 @@
EXT4_FS = "y";
EXT4_USE_FOR_EXT2 = "y";
FS_ENCRYPTION = "y";
};
};
}

View File

@ -16,17 +16,11 @@ let
inherit (lib)
concatStrings concatStringsSep mapAttrsToList mkOption types;
inherit (builtins) toString;
inherit (pkgs.pseudofile) dir;
passwd-file =
let
lines = mapAttrsToList (
name: u:
"${name}:${
if u ? passwd then u.passwd else "!!"
}:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n"
) config.users;
in
concatStrings lines;
inherit (pkgs.pseudofile) dir symlink;
passwd-file =
let lines = mapAttrsToList (name: u: "${name}:${if u ? passwd then u.passwd else "!!"}:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n" )
config.users;
in concatStrings lines;
group-file =
let lines = mapAttrsToList
(name: {gid, usernames ? []}:

View File

@ -13,6 +13,7 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{

View File

@ -15,5 +15,4 @@ in oneshot rec {
)
'';
down = "ip link set down dev ${ifname}";
dependencies = [ primary ];
}

View File

@ -1,7 +1,6 @@
{
liminix
, lib
, s6
}:
{ watched, headStart } :
let
@ -9,5 +8,5 @@ let
in longrun {
name = "watchdog";
run =
"PATH=${s6}/bin:$PATH HEADSTART=${toString headStart} ${./gaspode.sh} ${lib.concatStringsSep " " (builtins.map (s: s.name) watched)}";
"HEADSTART=${toString headStart} ${./gaspode.sh} ${lib.concatStringsSep " " (builtins.map (s: s.name) watched)}";
}

View File

@ -1,10 +1,11 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) stdenv wireless-regdb;
regulatory = stdenv.mkDerivation {
name = "regulatory.db";
phases = [ "installPhase" ];
phases = ["installPhase"];
installPhase = ''
mkdir -p $out
cp ${wireless-regdb}/lib/firmware/regulatory.db $out/

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