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 2024-02-21
New port! Thanks to Raito Bezarius, Liminix now runs on the Zyxel NWA50AX, New port! Thanks to Raito Bezarius, Liminix now runs on the Zyxel NWA50AX,
an MT7621 (MIPS EL) dual radio WiFi AP. 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;
};
})
];

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

View File

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

60
ci.nix
View File

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

View File

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

View File

@ -73,7 +73,7 @@
MTK_INFRACFG = "y"; MTK_INFRACFG = "y";
MTK_PMIC_WRAP = "y"; MTK_PMIC_WRAP = "y";
NVMEM_MTK_EFUSE="y"; MTK_EFUSE="y";
# MTK_HSDMA="y"; # MTK_HSDMA="y";
MTK_SCPSYS="y"; MTK_SCPSYS="y";
MTK_SCPSYS_PM_DOMAINS="y"; MTK_SCPSYS_PM_DOMAINS="y";
@ -92,6 +92,7 @@
MEDIATEK_GE_PHY = "y"; MEDIATEK_GE_PHY = "y";
# MEDIATEK_MT6577_AUXADC = "y"; # MEDIATEK_MT6577_AUXADC = "y";
# MEDIATEK_WATCHDOG = "y";
NET_MEDIATEK_SOC = "y"; NET_MEDIATEK_SOC = "y";
NET_MEDIATEK_SOC_WED = "y"; NET_MEDIATEK_SOC_WED = "y";
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
@ -213,6 +214,7 @@
networkInterfaces = networkInterfaces =
let let
inherit (config.system.service.network) link; inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec { in rec {
wan = link.build { ifname = "wan"; }; wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; }; 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_BLK = "y";
VIRTIO_NET = "y"; VIRTIO_NET = "y";
}; };
conditionalConfig = {
WLAN= {
MAC80211_HWSIM = "m";
};
};
}; };
hardware = hardware =
let let
mac80211 = pkgs.kmodloader.override { mac80211 = pkgs.mac80211.override {
inherit (config.system.outputs) kernel; drivers = ["mac80211_hwsim"];
targets = ["mac80211_hwsim"]; klibBuild = config.system.outputs.kernel.modulesupport;
}; };
in { in {
defaultOutput = "vmroot"; defaultOutput = "vmroot";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,11 @@
{ eval, lib, pkgs }: { eval, lib, pkgs }:
let let
inherit (lib) types;
conf = eval.config; conf = eval.config;
rootDir = builtins.toPath ./..; rootDir = builtins.toPath ./..;
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) [ "${rootDir}/" ]; stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix)
optToDoc = name: opt: { ["${rootDir}/"];
optToDoc = name: opt : {
inherit name; inherit name;
description = opt.description or null; description = opt.description or null;
default = opt.default or null; default = opt.default or null;
@ -24,6 +26,7 @@ let
let x = lib.mapAttrsToList optToDoc sd.parameters; in x; let x = lib.mapAttrsToList optToDoc sd.parameters; in x;
} }
else else
item // { declarations = map stripAnyPrefixes item.declarations; }; item // { declarations = map stripAnyPrefixes item.declarations; };
in 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 let
inherit (builtins) stringLength readDir filter; inherit (builtins) stringLength readDir filter;
devices = filter (n: n != "families") (lib.mapAttrsToList (n: t: n) (readDir ../devices)); devices = filter (n: n != "families")
texts = map ( (lib.mapAttrsToList (n: t: n) (readDir ../devices));
n: texts = map (n:
let let d = import ../devices/${n}/default.nix;
d = import ../devices/${n}/default.nix; d' = {
d' = { description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
description = "${n}\n${substring 0 (stringLength n) "********************************"}\n"; } // d;
} // d; installer =
in if d ? description && d ? installer
d'.description then ''
) devices;
The default installation route for this device is
:ref:`system-outputs-${d.installer}`
''
else "";
in d'.description)
devices;
in in
writeText "hwdoc" '' writeText "hwdoc" ''
Supported hardware Supported hardware

View File

@ -11,15 +11,15 @@
... ...
}: let }: let
secrets = import ./extneder-secrets.nix; 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.pseudofile) dir symlink;
inherit (pkgs) writeText serviceFns; inherit (pkgs) writeText dropbear ifwait serviceFns;
svc = config.system.service; svc = config.system.service;
in rec { in rec {
boot = { boot = {
tftp = { tftp = {
serverip = "10.0.0.1"; serverip = "192.168.8.148";
ipaddr = "10.0.0.8"; ipaddr = "192.168.8.251";
}; };
}; };
@ -28,12 +28,34 @@ in rec {
../modules/network ../modules/network
../modules/vlan ../modules/vlan
../modules/ssh ../modules/ssh
../modules/usb.nix
../modules/watchdog ../modules/watchdog
../modules/mount ../modules/mount
]; ];
hostname = "arhcive"; 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 = services.dhcpc =
let iface = config.hardware.networkInterfaces.lan; let iface = config.hardware.networkInterfaces.lan;
@ -83,7 +105,7 @@ in rec {
}; };
services.mount_external_disk = svc.mount.build { services.mount_external_disk = svc.mount.build {
partlabel = "backup-disk"; device = "LABEL=backup-disk";
mountpoint = "/srv"; mountpoint = "/srv";
fstype = "ext4"; fstype = "ext4";
}; };
@ -119,37 +141,23 @@ in rec {
secrets_file secrets_file
services.mount_external_disk services.mount_external_disk
config.hardware.networkInterfaces.lan config.hardware.networkInterfaces.lan
]; ] ;
}; };
users.root = { users.root = {
passwd = lib.mkForce secrets.root.passwd; 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 = { users.backup = {
uid = 500; uid=500; gid=500; gecos="Storage owner"; dir="/srv";
gid = 500; shell="/dev/null";
gecos = "Storage owner";
dir = "/srv";
shell = "/dev/null";
}; };
groups.backup = { groups.backup = {
gid = 500; gid=500; usernames = ["backup"];
usernames = [ "backup" ];
}; };
defaultProfile.packages = with pkgs; [ defaultProfile.packages = with pkgs; [e2fsprogs strace tcpdump ];
e2fsprogs
mtdutils
(levitate.override {
config = {
services = {
inherit (config.services) dhcpc sshd watchdog;
};
defaultProfile.packages = [ mtdutils ];
users.root.openssh.authorizedKeys.keys = secrets.root.keys;
};
})
];
} }

View File

@ -5,9 +5,9 @@
# wherever the text "EDIT" appears - please consult the tutorial # wherever the text "EDIT" appears - please consult the tutorial
# documentation for details. # documentation for details.
{ config, pkgs, ... }: { config, pkgs, lib, ... } :
let let
inherit (pkgs.liminix.services) bundle oneshot; inherit (pkgs.liminix.services) bundle oneshot longrun;
inherit (pkgs) serviceFns; inherit (pkgs) serviceFns;
# EDIT: you can pick your preferred RFC1918 address space # EDIT: you can pick your preferred RFC1918 address space
# for NATted connections, if you don't like this one. # for NATted connections, if you don't like this one.
@ -49,40 +49,31 @@ in rec {
country_code = "GB"; country_code = "GB";
wpa_passphrase = "not a real wifi password"; wpa_passphrase = "not a real wifi password";
hw_mode = "g"; hw_mode="g";
ieee80211n = 1; ieee80211n = 1;
auth_algs = 1; # 1=wpa2, 2=wep, 3=both 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_key_mgmt = "WPA-PSK";
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?) wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2 rsn_pairwise = "CCMP"; # auth for wpa2
wmm_enabled = 1; wmm_enabled = 1;
}; };
}; };
services.int = svc.network.address.build { services.int = svc.network.address.build {
interface = svc.bridge.primary.build { ifname = "int"; }; interface = svc.bridge.primary.build { ifname = "int"; };
family = "inet"; family = "inet"; address = "${ipv4LocalNet}.1"; prefixLength = 16;
address = "${ipv4LocalNet}.1";
prefixLength = 16;
}; };
services.bridge = svc.bridge.members.build { services.bridge = svc.bridge.members.build {
primary = services.int; primary = services.int;
members = with config.hardware.networkInterfaces; [ members = with config.hardware.networkInterfaces;
wlan [ wlan lan ];
lan
];
}; };
services.ntp = svc.ntp.build { services.ntp = svc.ntp.build {
pools = { pools = { "pool.ntp.org" = ["iburst"]; };
"pool.ntp.org" = [ "iburst" ]; makestep = { threshold = 1.0; limit = 3; };
};
makestep = {
threshold = 1.0;
limit = 3;
};
}; };
services.sshd = svc.ssh.build { }; services.sshd = svc.ssh.build { };
@ -166,7 +157,9 @@ in rec {
interface = services.wan; 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 { }; 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, config,
pkgs, pkgs,
lib, lib,
modulesPath,
... ...
}: let }: let
secrets = import ./extneder-secrets.nix; secrets = import ./extneder-secrets.nix;
svc = config.system.service;
in rec { in rec {
boot = { boot = {
tftp = { tftp = {
@ -22,13 +20,47 @@ in rec {
}; };
imports = [ imports = [
"${modulesPath}/profiles/wap.nix" ../modules/profiles/wap.nix
"${modulesPath}/vlan" ../modules/vlan
"${modulesPath}/ssh"
]; ];
hostname = "extneder"; 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 = { profile.wap = {
interfaces = with config.hardware.networkInterfaces; [ interfaces = with config.hardware.networkInterfaces; [
lan lan
@ -47,7 +79,6 @@ in rec {
}; };
}; };
services.sshd = svc.ssh.build {};
users.root.passwd = lib.mkForce secrets.root.passwd; 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

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

View File

@ -1,5 +1,6 @@
{ config, pkgs, ... } : { config, pkgs, lib, ... } :
let let
inherit (pkgs) serviceFns;
svc = config.system.service; svc = config.system.service;
in rec { 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, ... } : { config, pkgs, ... } :
let let
inherit (pkgs.liminix.services) target; inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs) writeText;
svc = config.system.service; svc = config.system.service;
secrets-1 = { secrets-1 = {
ssid = "Zyxel 2G (N)"; ssid = "Zyxel 2G (N)";

View File

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

View File

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

View File

@ -6,16 +6,23 @@
# problems. # problems.
{ config, pkgs, lib, modulesPath, ... } : { config, pkgs, lib, ... } :
let let
secrets = { secrets = {
domainName = "fake.liminix.org"; domainName = "fake.liminix.org";
firewallRules = { }; firewallRules = {};
} // (import ./rotuer-secrets.nix); } // (import ./rotuer-secrets.nix);
inherit (pkgs.liminix.services) oneshot longrun bundle;
inherit (pkgs) serviceFns;
svc = config.system.service; svc = config.system.service;
wirelessConfig = { wirelessConfig = {
country_code = "GB"; country_code = "GB";
inherit (secrets) wpa_passphrase; 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; wmm_enabled = 1;
}; };
@ -29,62 +36,65 @@ in rec {
}; };
imports = [ imports = [
"${modulesPath}/profiles/gateway.nix" ../modules/wlan.nix
"${modulesPath}/schnapps" ../modules/network
"${modulesPath}/outputs/btrfs.nix" ../modules/ppp
"${modulesPath}/outputs/extlinux.nix" ../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"; hostname = "rotuer";
rootfsType = "btrfs"; rootfsType = "btrfs";
rootOptions = "subvol=@"; rootOptions = "subvol=@";
boot.loader.extlinux.enable = true; boot.loader.extlinux.enable = true;
profile.gateway = { services.hostap = svc.hostapd.build {
lan = { interface = config.hardware.networkInterfaces.wlan;
interfaces = with config.hardware.networkInterfaces; params = {
[ ssid = secrets.ssid;
wlan wlan5 hw_mode="g";
lan0 lan1 lan2 lan3 lan4 channel = "2";
]; ieee80211n = 1;
inherit (secrets.lan) prefix; } // wirelessConfig;
address = { };
family = "inet"; address ="${secrets.lan.prefix}.1"; prefixLength = 24;
}; services.hostap5 = svc.hostapd.build {
dhcp = { interface = config.hardware.networkInterfaces.wlan5;
start = 10; params = rec {
end = 240; ssid = "${secrets.ssid}5";
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix); hw_mode="a";
localDomain = "lan"; channel = 36;
}; ht_capab = "[HT40+]";
}; vht_oper_chwidth = 1;
wan = { vht_oper_centr_freq_seg0_idx = channel + 6;
interface = config.hardware.networkInterfaces.wan; ieee80211n = 1;
username = secrets.l2tp.name; ieee80211ac = 1;
password = secrets.l2tp.password; } // wirelessConfig;
dhcp6.enable = true; };
};
firewall = { services.int = svc.network.address.build {
enable = true; interface = svc.bridge.primary.build { ifname = "int"; };
rules = secrets.firewallRules; family = "inet"; address ="${secrets.lan.prefix}.1"; prefixLength = 24;
}; };
wireless.networks = {
"${secrets.ssid}" = { services.bridge = svc.bridge.members.build {
interface = config.hardware.networkInterfaces.wlan; primary = services.int;
hw_mode = "g"; members = with config.hardware.networkInterfaces;
channel = "2"; [ wlan
ieee80211n = 1; wlan5
} // wirelessConfig; lan0
"${secrets.ssid}5" = rec { lan1
interface = config.hardware.networkInterfaces.wlan5; lan2
hw_mode = "a"; lan3
channel = 36; lan4
ht_capab = "[HT40+]"; ];
vht_oper_chwidth = 1;
vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211n = 1;
ieee80211ac = 1;
} // wirelessConfig;
};
}; };
services.ntp = svc.ntp.build { services.ntp = svc.ntp.build {
@ -96,6 +106,95 @@ in rec {
users.root = secrets.root; 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; [ defaultProfile.packages = with pkgs; [
min-collect-garbage min-collect-garbage
nftables nftables

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@
{ lib, pkgs, config, ...}: { lib, pkgs, config, ...}:
let let
inherit (lib) mkOption types mapAttrsToList; inherit (lib) mkOption mkEnableOption types mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (lib.strings) toUpper; inherit (lib.strings) toUpper;
@ -85,13 +85,10 @@ in {
}; };
}; };
filesystem = dir { filesystem = dir {
bin = dir ( bin = dir ({
{ busybox = symlink "${busybox}/bin/busybox";
busybox = symlink "${busybox}/bin/busybox"; sh = symlink "${busybox}/bin/busybox";
sh = symlink "${busybox}/bin/busybox"; } // makeLinks);
}
// 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 writeFennel
, linotify , linotify
, anoia , anoia
, lualinux , lua
}: }:
writeFennel "acquire-delegated-prefix" { writeFennel "acquire-delegated-prefix" {
packages = [ linotify anoia lualinux ]; packages = [ linotify anoia lua.pkgs.luafilesystem ];
mainFunction = "run"; mainFunction = "run";
} ./acquire-delegated-prefix.fnl } ./acquire-delegated-prefix.fnl

View File

@ -1,8 +1,7 @@
(local subject (require :acquire-wan-address)) (local subject (require :acquire-wan-address))
(import-macros { : expect= } :anoia.assert) (local { : view } (require :fennel))
(local { : merge : dup } (require :anoia)) (local { : merge : dup } (require :anoia))
;; nix-shell --run "cd modules/dhcp6c && fennelrepl acquire-wan-address-test.fnl"
(local a1 (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 [] (fn first-address []
(let [deleted (let [deleted
(subject.deletions (subject.deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,7 +18,7 @@ let
name = "${interface.name}.dnsmasq"; name = "${interface.name}.dnsmasq";
inherit (liminix.services) longrun; inherit (liminix.services) longrun;
inherit (lib) concatStrings concatStringsSep mapAttrsToList; 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); let v6s = concatStrings (map (a : ",[${a}]") v6);
in "--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}"; in "--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}";
in in

View File

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

View File

@ -4,10 +4,12 @@
, firewallgen , firewallgen
, nftables , nftables
}: }:
{ rules, extraRules }: { ruleset }:
let let
inherit (liminix.services) oneshot; 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 { in oneshot {
name = "firewall"; name = "firewall";
up = script; up = script;

View File

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

View File

@ -7,7 +7,9 @@
{ interface, params} : { interface, params} :
let let
inherit (liminix.services) longrun; 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 # This is not a friendly interface to configuring a wireless AP: it
# just passes everything straight through to the hostapd config. # just passes everything straight through to the hostapd config.
@ -20,15 +22,14 @@ let
driver = "nl80211"; driver = "nl80211";
logger_syslog = "-1"; logger_syslog = "-1";
logger_syslog_level = 1; logger_syslog_level = 1;
ctrl_interface = "/run/hostapd"; ctrl_interface = "/run/hostapd.${name}";
ctrl_interface_group = 0; ctrl_interface_group = 0;
}; };
conf = writeText "hostapd.conf" conf = writeText "hostapd.conf"
(concatStringsSep (concatStrings
"\n"
(mapAttrsToList (mapAttrsToList
(name: value: "${name}=${toString value}") (name: value: "${name}=${toString value}\n")
(defaults // params))); (defaults // params)));
in longrun { in longrun {
inherit name; 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, ...}: { lib, pkgs, config, ...}:
let 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; inherit (pkgs) liminix;
type_service = pkgs.liminix.lib.types.service;
mergeConditionals = conf : conditions : mergeConditionals = conf : conditions :
# for each key in conditions, if it is present in conf # for each key in conditions, if it is present in conf
# then merge the associated value into conf # then merge the associated value into conf
@ -126,6 +131,8 @@ in {
# at boot time unless we disable trying to call it. # at boot time unless we disable trying to call it.
# https://lkml.org/lkml/2013/8/5/175 # https://lkml.org/lkml/2013/8/5/175
FW_LOADER_USER_HELPER = "n"; 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 let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (pkgs) liminix; inherit (pkgs) liminix;
mkBoolOption = description : mkOption {
type = types.bool;
inherit description;
default = true;
};
in { in {
options = { options = {
@ -14,39 +19,28 @@ in {
type = liminix.lib.types.serviceDefn; type = liminix.lib.types.serviceDefn;
}; };
}; };
imports = [ ../mdevd.nix ../service-trigger ]; config.system.service = {
config.system.service.mount = mount = liminix.callService ./service.nix {
let svc = config.system.callService ./service.nix { device = mkOption {
partlabel = mkOption { type = types.str;
type = types.str; example = "/dev/sda1";
example = "my-usb-stick"; };
}; mountpoint = mkOption {
mountpoint = mkOption { type = types.str;
type = types.str; example = "/mnt/media";
example = "/mnt/media"; };
}; options = mkOption {
options = mkOption { type = types.listOf types.str;
type = types.listOf types.str; default = [];
default = []; example = ["noatime" "ro" "sync"];
example = ["noatime" "ro" "sync"]; };
}; fstype = mkOption {
fstype = mkOption { type = types.str;
type = types.str; default = "auto";
default = "auto"; example = "vfat";
example = "vfat"; };
};
};
in svc // {
build = args:
let args' = args // {
dependencies = (args.dependencies or []) ++ [
config.services.mdevd
config.services.devout
];
};
in svc.build args' ;
}; };
};
config.programs.busybox = { config.programs.busybox = {
applets = ["blkid" "findfs"]; applets = ["blkid" "findfs"];
options = { options = {

View File

@ -1,27 +1,18 @@
{ {
liminix liminix
, lib , lib
, svc
}: }:
{ partlabel, mountpoint, options, fstype }: { device, mountpoint, options, fstype }:
let let
inherit (liminix.services) oneshot; inherit (liminix.services) oneshot;
device = "/dev/disk/by-partlabel/${partlabel}";
name = "mount.${lib.strings.sanitizeDerivationName (lib.escapeURL mountpoint)}";
options_string =
if options == [] then "" else "-o ${lib.concatStringsSep "," options}";
controller = svc.uevent-rule.build {
serviceName = name;
symlink = device;
terms = {
partname = partlabel;
devtype = "partition";
};
};
in oneshot { in oneshot {
inherit name; name = "mount.${lib.escapeURL mountpoint}";
timeout-up = 3600; up = ''
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}"; while ! findfs ${device}; do
echo waiting for device ${device}
sleep 1
done
mount -t ${fstype} -o ${lib.concatStringsSep "," options} ${device} ${mountpoint}
'';
down = "umount ${mountpoint}"; down = "umount ${mountpoint}";
inherit controller;
} }

View File

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

View File

@ -17,7 +17,7 @@ let
ip address replace $ip/$mask dev $interface ip address replace $ip/$mask dev $interface
(in_outputs ${name} (in_outputs ${name}
for i in lease mask ip router siaddr dns serverid subnet opt53 interface ; do for i in lease mask ip router siaddr dns serverid subnet opt53 interface ; do
(printenv $i || true) > $i printenv $i > $i
done) done)
} }
case $action in case $action in
@ -40,7 +40,7 @@ let
''; '';
in longrun { in longrun {
inherit name; 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; notification-fd = 10;
dependencies = [ interface ]; dependencies = [ interface ];
} }

View File

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

View File

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

View File

@ -1,15 +1,15 @@
{ {
liminix liminix
, ifwait
, serviceFns
, lib , lib
}: }:
{ target, via, interface ? null, metric }: { target, via, interface ? null, metric }:
let let
inherit (liminix.services) oneshot; inherit (liminix.services) oneshot;
with_dev = if interface != null then "dev $(output ${interface} ifname)" else ""; 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 { 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 = '' up = ''
ip route add ${target} via ${via} metric ${toString metric} ${with_dev} ip route add ${target} via ${via} metric ${toString metric} ${with_dev}
''; '';

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -58,6 +58,7 @@ in {
system.outputs = rec { system.outputs = rec {
tftpboot = tftpboot =
let let
inherit (pkgs.lib.trivial) toHexString;
o = config.system.outputs; o = config.system.outputs;
image = let choices = { image = let choices = {
uimage = o.uimage; 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) 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"; 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 ) dtbSize=$(binsize ./dtb )

View File

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

View File

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

View File

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

View File

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

View File

@ -17,9 +17,6 @@ in {
system.service.pppoe = mkOption { system.service.pppoe = mkOption {
type = liminix.lib.types.serviceDefn; type = liminix.lib.types.serviceDefn;
}; };
system.service.l2tp = mkOption {
type = liminix.lib.types.serviceDefn;
};
}; };
config = { config = {
system.service.pppoe = pkgs.liminix.callService ./pppoe.nix { system.service.pppoe = pkgs.liminix.callService ./pppoe.nix {
@ -32,16 +29,6 @@ in {
description = "options supplied on ppp command line"; 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 = { kernel = {
config = { config = {
PPP = "y"; PPP = "y";
@ -49,8 +36,6 @@ in {
PPP_DEFLATE = "y"; PPP_DEFLATE = "y";
PPP_ASYNC = "y"; PPP_ASYNC = "y";
PPP_SYNC_TTY = "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 }: let
inherit (pkgs) liminix; 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.pseudofile) dir symlink;
inherit (pkgs) serviceFns; inherit (pkgs) serviceFns;
svc = config.system.service; svc = config.system.service;
@ -40,6 +40,7 @@ in {
../network ../network
../hostapd ../hostapd
../bridge ../bridge
../ssh
{ config.services = hostaps; } { config.services = hostaps; }
]; ];
@ -53,6 +54,7 @@ in {
}; };
}; };
config = { config = {
services.sshd = svc.ssh.build {};
services.int = svc.bridge.primary.build { services.int = svc.bridge.primary.build {
ifname = "int"; ifname = "int";

View File

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

View File

@ -1,4 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, ... }:
let let
inherit (pkgs) inherit (pkgs)
execline execline
@ -6,50 +6,14 @@ let
s6-init-bin s6-init-bin
s6-linux-init s6-linux-init
stdenvNoCC; stdenvNoCC;
inherit (lib.lists) unique concatMap;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) oneshot bundle; inherit (pkgs.liminix.services) bundle;
s6-rc-db = s6-rc-db =
let 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 { defaultDefaultTarget = bundle {
name = "default"; name = "default";
contents = defaultStart ++ [controlled]; contents = builtins.attrValues config.services;
}; };
servicesAttrs = { servicesAttrs = {
default = defaultDefaultTarget; default = defaultDefaultTarget;

View File

@ -34,7 +34,7 @@ fi
### If your services are managed by s6-rc: ### If your services are managed by s6-rc:
### (replace /run/service with your scandir) ### (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 ### 2. Starting the wanted set of services

View File

@ -1,4 +1,4 @@
{ config, pkgs, ... } : { config, pkgs, lib, ... } :
{ {
config = { config = {
programs.busybox = { 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, config
pkgs, , pkgs
lib, , lib
... , ...
}: }:
let let
inherit (pkgs) liminix; inherit (pkgs) liminix;

View File

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

View File

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

View File

@ -16,17 +16,11 @@ let
inherit (lib) inherit (lib)
concatStrings concatStringsSep mapAttrsToList mkOption types; concatStrings concatStringsSep mapAttrsToList mkOption types;
inherit (builtins) toString; inherit (builtins) toString;
inherit (pkgs.pseudofile) dir; inherit (pkgs.pseudofile) dir symlink;
passwd-file = passwd-file =
let 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" )
lines = mapAttrsToList ( config.users;
name: u: in concatStrings lines;
"${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 = group-file =
let lines = mapAttrsToList let lines = mapAttrsToList
(name: {gid, usernames ? []}: (name: {gid, usernames ? []}:

View File

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

View File

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

View File

@ -1,7 +1,6 @@
{ {
liminix liminix
, lib , lib
, s6
}: }:
{ watched, headStart } : { watched, headStart } :
let let
@ -9,5 +8,5 @@ let
in longrun { in longrun {
name = "watchdog"; name = "watchdog";
run = 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, ...}: { lib, pkgs, config, ...}:
let let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink; inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) stdenv wireless-regdb; inherit (pkgs) stdenv wireless-regdb;
regulatory = stdenv.mkDerivation { regulatory = stdenv.mkDerivation {
name = "regulatory.db"; name = "regulatory.db";
phases = [ "installPhase" ]; phases = ["installPhase"];
installPhase = '' installPhase = ''
mkdir -p $out mkdir -p $out
cp ${wireless-regdb}/lib/firmware/regulatory.db $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