220 lines
7.1 KiB
Nix
220 lines
7.1 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
namespace,
|
|
...
|
|
}:
|
|
with lib;
|
|
let
|
|
cfg = config.${namespace}.network;
|
|
|
|
profiles =
|
|
let
|
|
make =
|
|
name: profile:
|
|
nameValuePair "${name}" {
|
|
connection = {
|
|
id = name;
|
|
type = profile.type;
|
|
autoconnect = profile.autoconnect;
|
|
autoconnect-retries = profile.autoconnect-retries;
|
|
autoconnect-priority = profile.priority;
|
|
interface-name = profile.interface or cfg.ipv4.interface;
|
|
};
|
|
ipv4 = {
|
|
method = cfg.ipv4.method;
|
|
}
|
|
// (
|
|
if (cfg.ipv4.method == "auto") then
|
|
{ }
|
|
else
|
|
{
|
|
address = cfg.ipv4.address;
|
|
gateway = cfg.ipv4.gateway;
|
|
dns = cfg.ipv4.dns;
|
|
}
|
|
);
|
|
ipv6 = {
|
|
addr-gen-mode = "stable-privacy";
|
|
method = "auto";
|
|
};
|
|
wifi = mkIf (profile.type == "wifi") {
|
|
mode = "infrastructure";
|
|
ssid = profile.ssid;
|
|
roaming = "allowed";
|
|
};
|
|
wifi-security = mkIf (profile.type == "wifi") {
|
|
key-mgmt = profile.keyMgmt;
|
|
psk = profile.psk;
|
|
};
|
|
};
|
|
|
|
userProfiles = mapAttrs' make cfg.networkmanager.profiles;
|
|
|
|
# When using manual IP with NM enabled, auto-generate an ethernet profile
|
|
# so NM actually assigns the static address (not just DHCP).
|
|
ethernetProfile =
|
|
optionalAttrs (cfg.ipv4.method == "manual" && cfg.ipv4.interface != "" && cfg.networkmanager.enable)
|
|
{
|
|
"static-${cfg.ipv4.interface}" = {
|
|
connection = {
|
|
id = "static-${cfg.ipv4.interface}";
|
|
type = "ethernet";
|
|
autoconnect = true;
|
|
interface-name = cfg.ipv4.interface;
|
|
};
|
|
ipv4 = {
|
|
method = "manual";
|
|
address = cfg.ipv4.address;
|
|
gateway = cfg.ipv4.gateway;
|
|
dns = cfg.ipv4.dns;
|
|
};
|
|
ipv6 = {
|
|
addr-gen-mode = "stable-privacy";
|
|
method = "auto";
|
|
};
|
|
};
|
|
};
|
|
in
|
|
userProfiles // ethernetProfile;
|
|
in
|
|
{
|
|
imports = [
|
|
./options.nix
|
|
];
|
|
|
|
config = {
|
|
assertions = [
|
|
{
|
|
assertion = cfg.hostName != "";
|
|
message = "mjallen.network.hostName must be set to a non-empty string.";
|
|
}
|
|
{
|
|
assertion = cfg.ipv4.method == "auto" || cfg.ipv4.method == "manual";
|
|
message = "mjallen.network.ipv4.method must be either \"auto\" or \"manual\" (got \"${cfg.ipv4.method}\").";
|
|
}
|
|
{
|
|
assertion = cfg.ipv4.method != "manual" || cfg.ipv4.interface != "";
|
|
message = "mjallen.network.ipv4.interface must be set when ipv4.method is \"manual\".";
|
|
}
|
|
{
|
|
assertion = cfg.ipv4.method != "manual" || cfg.ipv4.address != "";
|
|
message = "mjallen.network.ipv4.address must be set when ipv4.method is \"manual\".";
|
|
}
|
|
{
|
|
assertion = cfg.ipv4.method != "manual" || cfg.ipv4.gateway != "";
|
|
message = "mjallen.network.ipv4.gateway must be set when ipv4.method is \"manual\".";
|
|
}
|
|
{
|
|
assertion = cfg.nat.enable -> cfg.nat.externalInterface != "";
|
|
message = "mjallen.network.nat.externalInterface must be set when NAT is enabled.";
|
|
}
|
|
];
|
|
|
|
systemd = {
|
|
services = {
|
|
NetworkManager-wait-online.enable = false;
|
|
systemd-networkd-wait-online.enable = lib.mkForce false;
|
|
systemd-networkd.stopIfChanged = false;
|
|
systemd-resolved.stopIfChanged = false;
|
|
};
|
|
network.wait-online.enable = false;
|
|
};
|
|
|
|
# Restrict Avahi to the configured LAN interface when one is explicitly set.
|
|
# This prevents Avahi from announcing on virtual/container interfaces (veth*,
|
|
# podman0, virbr0, etc.) which causes hostname conflicts and suffix mangling
|
|
# (e.g. "jallen-nas-4.local" instead of "jallen-nas.local").
|
|
services.avahi = lib.mkIf (cfg.ipv4.interface != "") {
|
|
allowInterfaces = [ cfg.ipv4.interface ];
|
|
};
|
|
|
|
networking = {
|
|
hostName = lib.mkForce cfg.hostName;
|
|
|
|
# Use networkd if enabled
|
|
useNetworkd = lib.mkDefault true;
|
|
|
|
# Set default gateway and nameservers if in manual mode
|
|
defaultGateway = lib.mkIf (cfg.ipv4.method == "manual") {
|
|
address = cfg.ipv4.gateway;
|
|
interface = lib.mkIf (cfg.ipv4.interface != "") cfg.ipv4.interface;
|
|
};
|
|
|
|
nameservers = lib.mkIf (cfg.ipv4.method == "manual") [ cfg.ipv4.dns ];
|
|
|
|
# Set hostId if provided
|
|
hostId = lib.mkIf (cfg.hostId != "") cfg.hostId;
|
|
|
|
# Configure NAT if enabled
|
|
nat = lib.mkIf cfg.nat.enable {
|
|
enable = true;
|
|
internalInterfaces = cfg.nat.internalInterfaces;
|
|
externalInterface = cfg.nat.externalInterface;
|
|
enableIPv6 = cfg.nat.enableIPv6;
|
|
};
|
|
|
|
# Configure firewall
|
|
firewall = {
|
|
enable = cfg.firewall.enable;
|
|
allowPing = cfg.firewall.allowPing;
|
|
allowedTCPPorts = cfg.firewall.allowedTCPPorts;
|
|
allowedUDPPorts = cfg.firewall.allowedUDPPorts;
|
|
trustedInterfaces = cfg.firewall.trustedInterfaces;
|
|
|
|
# Default port ranges for KDE Connect
|
|
allowedTCPPortRanges = lib.mkIf cfg.firewall.kdeConnect.enable [
|
|
{
|
|
from = cfg.firewall.kdeConnect.tcpRange.from;
|
|
to = cfg.firewall.kdeConnect.tcpRange.to;
|
|
}
|
|
];
|
|
allowedUDPPortRanges = lib.mkIf cfg.firewall.kdeConnect.enable [
|
|
{
|
|
from = cfg.firewall.kdeConnect.udpRange.from;
|
|
to = cfg.firewall.kdeConnect.udpRange.to;
|
|
}
|
|
];
|
|
|
|
# Extra firewall commands
|
|
extraCommands = lib.mkIf (cfg.extraFirewallCommands != "") cfg.extraFirewallCommands;
|
|
};
|
|
|
|
# Enable iwd daemon when requested.
|
|
# When iwd is enabled alongside NetworkManager, iwd acts as the WiFi
|
|
# backend for NM (iwd handles scanning/association; NM handles
|
|
# connection management). They are not mutually exclusive.
|
|
wireless.iwd = lib.mkIf cfg.iwd.enable {
|
|
enable = true;
|
|
settings = cfg.iwd.settings;
|
|
};
|
|
|
|
# Configure NetworkManager when enabled
|
|
networkmanager = mkIf cfg.networkmanager.enable {
|
|
enable = true;
|
|
# Use iwd as the WiFi backend when iwd is also enabled
|
|
wifi.backend = mkIf cfg.iwd.enable "iwd";
|
|
wifi.powersave = cfg.networkmanager.powersave;
|
|
settings.connectivity.uri = "http://nmcheck.gnome.org/check_network_status.txt";
|
|
plugins = with pkgs; [
|
|
networkmanager-fortisslvpn
|
|
networkmanager-iodine
|
|
networkmanager-l2tp
|
|
networkmanager-openconnect
|
|
networkmanager-openvpn
|
|
networkmanager-sstp
|
|
networkmanager-strongswan
|
|
networkmanager-vpnc
|
|
];
|
|
|
|
# Configure profiles if any are defined
|
|
ensureProfiles = mkIf (profiles != { }) {
|
|
environmentFiles = lib.optional (config.sops.secrets ? wifi) config.sops.secrets.wifi.path;
|
|
profiles = profiles;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|