liminix/extneder.nix
2023-03-07 21:33:01 +00:00

193 lines
4.5 KiB
Nix

# This is not part of Liminix per se. This is a "scratchpad"
# configuration for a device I'm testing with.
#
# Parts of it do do things that Liminix eventually needs to do, but
# don't look in here for solutions - just for identifying the
# problems.
{
config,
pkgs,
lib,
...
}: let
secrets = import ./rotuer-secrets.nix;
inherit
(pkgs.liminix.networking)
address
udhcpc
hostapd
interface
route
;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) dropbear ifwait serviceFns
;
in rec {
services.loopback = let
iface = interface {
type = "loopback";
device = "lo";
};
in
bundle {
name = "loopback";
contents = [
(address iface {
family = "inet4";
address = "127.0.0.1";
prefixLength = 8;
})
(address iface {
family = "inet6";
address = "::1";
prefixLength = 128;
})
];
};
boot = {
tftp = {
enable = true;
serverip = "192.168.8.148";
ipaddr = "192.168.8.251";
};
};
imports = [
./modules/wlan.nix
./modules/tftpboot.nix
# ./modules/flashable.nix
];
kernel = {
config = {
BRIDGE = "y";
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
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";
};
};
services.hostap = hostapd (config.hardware.networkInterfaces.wlan) {
params = {
ssid = "liminix.dev";
country_code = "GB";
hw_mode = "g";
channel = "6";
wmm_enabled = 1;
ieee80211n = 1;
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
};
};
services.int = interface {
type = "bridge";
device = "int";
};
services.dhcpc = (udhcpc services.int {}) // {device = "int";};
services.bridge = let
primary = services.int;
addif = dev:
oneshot {
name = "add-${dev.device}-to-bridge";
up = "${ifwait}/bin/ifwait -v ${dev.device} running && ip link set dev ${dev.device} master ${primary.device}";
down = "ip link set dev ${dev} nomaster";
dependencies = [primary dev];
};
in
bundle {
name = "bridge-members";
contents = with config.hardware.networkInterfaces;
map addif [
lan
wlan
];
};
services.sshd = longrun {
name = "sshd";
run = ''
mkdir -p /run/dropbear
${dropbear}/bin/dropbear -E -P /run/dropbear.pid -R -F
'';
};
services.resolvconf = oneshot rec {
dependencies = [ services.dhcpc ];
name = "resolvconf";
# CHECK: https://udhcp.busybox.net/README.udhcpc says
# 'A list of DNS server' but doesn't say what separates the
# list members. Assuming it's a space or other IFS character
up = ''
. ${serviceFns}
( in_outputs ${name}
for i in $(cat $(output ${services.dhcpc} dns)); do
echo "nameserver $i" > resolv.conf
done
)
'';
down = ''
rm -rf /run/service-state/${name}/
'';
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
};
services.defaultroute4 = route {
name = "defaultroute";
via = "$(output ${services.dhcpc} router)";
target = "default";
dependencies = [services.dhcpc];
};
services.default = target {
name = "default";
contents = with services; [
loopback
config.hardware.networkInterfaces.eth
config.hardware.networkInterfaces.wlan
int
bridge
hostap
defaultroute4
# resolvconf
sshd
];
};
defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig];
}