Working again having folded in france's changes.
This commit is contained in:
@@ -16,7 +16,7 @@ with lib;
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Domain of the
|
||||
Domain of the local network.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
+228
-48
@@ -1,96 +1,276 @@
|
||||
# UNFINISHED!
|
||||
#
|
||||
# The plan is to bootstrap a local network config: DNS, DHCP, etc.
|
||||
|
||||
{ lib, config, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
hostOpts = { config, ... }: {
|
||||
options = {
|
||||
ipv6Address = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The V6 IP of a given host, if any.
|
||||
'';
|
||||
};
|
||||
cfg = config.fudo.local-network;
|
||||
|
||||
ipv4Address = mkOption {
|
||||
join-lines = concatStringsSep "\n";
|
||||
|
||||
ip = import ../../lib/ip.nix { lib = lib; };
|
||||
|
||||
hostOpts = { hostname, ... }: {
|
||||
options = {
|
||||
ip-address = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The V4 IP of a given host, if any.
|
||||
'';
|
||||
};
|
||||
|
||||
macAddress = mkOption {
|
||||
mac-address = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The MAC address of a given host, if desired for IP reservation.
|
||||
'';
|
||||
};
|
||||
|
||||
ssh-fingerprints = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "A list of DNS SSHFP records for this host.";
|
||||
default = [];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
localNameServerOpts = { config, ... }: {
|
||||
traceout = out: builtins.trace out out;
|
||||
|
||||
srvRecordOpts = with types; {
|
||||
options = {
|
||||
ipv6Address = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The V6 IP of this nameserver, if any.
|
||||
'';
|
||||
weight = mkOption {
|
||||
type = int;
|
||||
description = "Weight relative to other records.";
|
||||
default = 1;
|
||||
};
|
||||
|
||||
ipv4Address = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The V4 IP of this nameserver, if any.
|
||||
'';
|
||||
priority = mkOption {
|
||||
type = int;
|
||||
description = "Priority to give this record.";
|
||||
default = 0;
|
||||
};
|
||||
|
||||
ipv4ReverseDomain = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The domain of the IPv4 address range for which this nameserver is responsible.
|
||||
port = mkOption {
|
||||
type = port;
|
||||
description = "Port to use when connecting.";
|
||||
};
|
||||
|
||||
Eg: 0.10.in-addr.arpa
|
||||
'';
|
||||
host = mkOption {
|
||||
type = str;
|
||||
description = "Host to contact for this service.";
|
||||
example = "my-host.my-domain.com.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in {
|
||||
|
||||
options = {
|
||||
options.fudo.local-network = {
|
||||
|
||||
fudo.localNetwork.hosts = mkOption {
|
||||
type = types.listOf (submodule hostOpts);
|
||||
enable = mkEnableOption "Enable local network configuration (DHCP & DNS).";
|
||||
|
||||
hosts = mkOption {
|
||||
type = with types; loaOf (submodule hostOpts);
|
||||
default = {};
|
||||
description = ''
|
||||
A map of hostname => { host_attributes }.
|
||||
'';
|
||||
description = "A map of hostname => { host_attributes }.";
|
||||
};
|
||||
|
||||
fudo.localNetwork.domain = mkOption {
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
description = "The domain to use for the local network.";
|
||||
};
|
||||
|
||||
dns-servers = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "A list of domain name server to use for the local network.";
|
||||
};
|
||||
|
||||
dhcp-interfaces = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "A list of interfaces on which to serve DHCP.";
|
||||
};
|
||||
|
||||
dns-serve-ips = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "A list of IPs on which to server DNS queries.";
|
||||
};
|
||||
|
||||
gateway = mkOption {
|
||||
type = types.str;
|
||||
description = "The gateway to use for the local network.";
|
||||
};
|
||||
|
||||
aliases = mkOption {
|
||||
type = with types; loaOf str;
|
||||
default = {};
|
||||
description = "A mapping of host-alias => hostname to use on the local network.";
|
||||
};
|
||||
|
||||
network = mkOption {
|
||||
type = types.str;
|
||||
description = "Network to treat as local.";
|
||||
};
|
||||
|
||||
enable-reverse-mappings = mkOption {
|
||||
type = types.bool;
|
||||
description = "Genereate PTR reverse lookup records.";
|
||||
default = false;
|
||||
};
|
||||
|
||||
dhcp-dynamic-network = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The domain to use for the local network.
|
||||
The network from which to dynamically allocate IPs via DHCP.
|
||||
|
||||
Must be a subnet of <network>.
|
||||
'';
|
||||
};
|
||||
|
||||
fudo.localNetwork.hostAliases = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
recursive-resolver = mkOption {
|
||||
type = types.str;
|
||||
description = "DNS nameserver to use for recursive resolution.";
|
||||
};
|
||||
|
||||
server-ip = mkOption {
|
||||
type = types.str;
|
||||
description = "IP of the DNS server.";
|
||||
};
|
||||
|
||||
extra-dns-records = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "Records to be inserted verbatim into the DNS zone.";
|
||||
example = ["some-host IN CNAME other-host"];
|
||||
default = [];
|
||||
};
|
||||
|
||||
srv-records = mkOption {
|
||||
type = with types; attrsOf (attrsOf (listOf (submodule srvRecordOpts)));
|
||||
description = "Map of traffic type to srv records.";
|
||||
default = {};
|
||||
description = ''
|
||||
A mapping of hostAlias => hostName to use on the local network.
|
||||
example = {
|
||||
tcp = {
|
||||
kerberos = {
|
||||
port = 88;
|
||||
host = "auth-host.my-domain.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
search-domains = mkOption {
|
||||
type = with types; listOf str;
|
||||
description = "A list of domains to search for DNS names.";
|
||||
example = ["my-domain.com" "other-domain.com"];
|
||||
default = [];
|
||||
};
|
||||
|
||||
# TODO: srv records
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.dhcpd4 = {
|
||||
enable = true;
|
||||
|
||||
machines = mapAttrsToList (hostname: hostOpts: {
|
||||
ethernetAddress = hostOpts.mac-address;
|
||||
hostName = hostname;
|
||||
ipAddress = hostOpts.ip-address;
|
||||
}) cfg.hosts;
|
||||
|
||||
interfaces = cfg.dhcp-interfaces;
|
||||
|
||||
extraConfig = ''
|
||||
subnet ${ip.getNetworkBase cfg.network} netmask ${ip.maskFromV32Network cfg.network} {
|
||||
authoritative;
|
||||
option subnet-mask ${ip.maskFromV32Network cfg.network};
|
||||
option broadcast-address ${ip.networkMaxIp cfg.network};
|
||||
option routers ${cfg.gateway};
|
||||
option domain-name-servers ${concatStringsSep " " cfg.dns-servers};
|
||||
option domain-name "${cfg.domain}";
|
||||
option domain-search ${join-lines (map (dom: "\"${dom}\"") ([cfg.domain] ++ cfg.search-domains))};
|
||||
range ${ip.networkMinIp cfg.dhcp-dynamic-network} ${ip.networkMaxButOneIp cfg.dhcp-dynamic-network};
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
fudo.localNetwork.localNameServer = mkOption {
|
||||
type = (submodule localNameServerOpts);
|
||||
description = ''
|
||||
The master nameserver of the local network.
|
||||
'';
|
||||
services.bind = let
|
||||
blockHostsToZone = block: hosts-data: {
|
||||
master = true;
|
||||
name = "${block}.in-addr.arpa";
|
||||
file = let
|
||||
# We should add these...but need a domain to assign them to.
|
||||
# ip-last-el = ip: toInt (last (splitString "." ip));
|
||||
# used-els = map (host-data: ip-last-el host-data.ip-address) hosts-data;
|
||||
# unused-els = subtractLists used-els (map toString (range 1 255));
|
||||
|
||||
in pkgs.writeText "db.${block}-zone" ''
|
||||
$ORIGIN ${block}.in-addr.arpa.
|
||||
$TTL 1h
|
||||
|
||||
@ IN SOA ns1.${cfg.domain}. hostmaster.${cfg.domain}. (
|
||||
${toString builtins.currentTime}
|
||||
1800
|
||||
900
|
||||
604800
|
||||
1800)
|
||||
|
||||
@ IN NS ns1.${cfg.domain}.
|
||||
|
||||
${join-lines (map hostPtrRecord hosts-data)}
|
||||
'';
|
||||
};
|
||||
|
||||
ipToBlock = ip: concatStringsSep "." (reverseList (take 3 (splitString "." ip)));
|
||||
compactHosts = mapAttrsToList (host: data: data // { host = host; }) cfg.hosts;
|
||||
hostsByBlock = groupBy (host-data: ipToBlock host-data.ip-address) compactHosts;
|
||||
hostPtrRecord = host-data:
|
||||
"${last (splitString "." host-data.ip-address)} IN PTR ${host-data.host}.${cfg.domain}.";
|
||||
|
||||
blockZones = mapAttrsToList blockHostsToZone hostsByBlock;
|
||||
|
||||
hostARecord = host: data: "${host} IN A ${data.ip-address}";
|
||||
hostSshFpRecords = host: data: join-lines (map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints);
|
||||
cnameRecord = alias: host: "${alias} IN CNAME ${host}";
|
||||
|
||||
makeSrvRecords = protocol: type: records:
|
||||
join-lines (map (record: "_${type}._${protocol} IN SRV ${toString record.priority} ${toString record.weight} ${toString record.port} ${record.host}.")
|
||||
records);
|
||||
|
||||
makeSrvProtocolRecords = protocol: types: join-lines (mapAttrsToList (makeSrvRecords protocol) types);
|
||||
|
||||
in {
|
||||
enable = true;
|
||||
cacheNetworks = [ cfg.network "localhost" "localnets" ];
|
||||
forwarders = [ cfg.recursive-resolver ];
|
||||
listenOn = cfg.dns-serve-ips;
|
||||
zones = [
|
||||
{
|
||||
master = true;
|
||||
name = cfg.domain;
|
||||
file = pkgs.writeText "${cfg.domain}-zone" ''
|
||||
@ IN SOA ns1.${cfg.domain}. hostmaster.${cfg.domain}. (
|
||||
${toString builtins.currentTime}
|
||||
5m
|
||||
2m
|
||||
6w
|
||||
5m)
|
||||
|
||||
$TTL 1h
|
||||
|
||||
@ IN NS ns1.${cfg.domain}.
|
||||
|
||||
$ORIGIN ${cfg.domain}.
|
||||
|
||||
$TTL 30m
|
||||
|
||||
ns1 IN A ${cfg.server-ip}
|
||||
${join-lines (mapAttrsToList hostARecord cfg.hosts)}
|
||||
${join-lines (mapAttrsToList hostSshFpRecords cfg.hosts)}
|
||||
${join-lines (mapAttrsToList cnameRecord cfg.aliases)}
|
||||
${join-lines cfg.extra-dns-records}
|
||||
${join-lines (mapAttrsToList makeSrvProtocolRecords cfg.srv-records)}
|
||||
'';
|
||||
}
|
||||
] ++ blockZones;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ with lib;
|
||||
./fudo/grafana.nix
|
||||
./fudo/kdc.nix
|
||||
./fudo/ldap.nix
|
||||
./fudo/local-network.nix
|
||||
./fudo/mail.nix
|
||||
./fudo/mail-container.nix
|
||||
./fudo/minecraft-server.nix
|
||||
|
||||
Reference in New Issue
Block a user