diff --git a/config/hardware/clunk.nix b/config/hardware/clunk.nix index 4761098..4559098 100644 --- a/config/hardware/clunk.nix +++ b/config/hardware/clunk.nix @@ -42,7 +42,7 @@ hardware.bluetooth.enable = false; - network = { + networking = { macvlans = { intif0 = { interface = "enp2s0"; diff --git a/config/hosts/clunk.nix b/config/hosts/clunk.nix index 838b6ba..1bdcfb1 100644 --- a/config/hosts/clunk.nix +++ b/config/hosts/clunk.nix @@ -4,8 +4,14 @@ let primary-ip = "10.0.0.1"; dns-proxy-ip = "10.0.0.2"; + site-name = config.fudo.hosts.${config.instance.hostname}.site; + site = config.fudo.site.${site-name}; + in { - fudo.local-network = { + fudo.local-network = let + site-name = config.fudo.hosts.${config.instance.hostname}.site; + site = config.fudo.sites.${site-name}; + in { # FIXME: think about this -- actual network config? enable = true; # NOTE: requests go: @@ -19,6 +25,8 @@ in { recursive-resolver = "${primary-ip} port 5353"; server-ip = primary-ip; domain = "rus.selby.ca"; + network = site.network; + dhcp-dynamic-network = site.dynamic-network; }; networking = { @@ -77,7 +85,7 @@ in { # environment.systemPackages = with pkgs; [ dnsproxy ]; - virtualization = { + virtualisation = { docker = { enable = true; autoPrune.enable = true; diff --git a/config/profiles/gateway-server.nix b/config/profiles/gateway-server.nix deleted file mode 100644 index e784a32..0000000 --- a/config/profiles/gateway-server.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - hostname = config.instance.hostname; - host-config = config.fudo.hosts.${hostname}; - external-interface = host-config.gateway-config.external-interface; - internal-interfaces = host-config.gateway-config.internal-interfaces; - -in { - imports = [ ./server.nix ]; - - config = { - networking = { - nat = { - enable = true; - externalInterface = external-interface; - internalInterfaces = internal-interfaces; - }; - - firewall = { - enable = true; - trustedInterfaces = internal-interfaces; - interfaces."${external-interface}" = { - allowedTCPPorts = host-config.gateway-config.external-tcp-ports; - allowedUDPPorts = host-config.gateway-config.external-udp-ports; - }; - }; - }; - }; -} diff --git a/config/sites.nix b/config/sites.nix index 9d50568..8097af9 100644 --- a/config/sites.nix +++ b/config/sites.nix @@ -5,6 +5,8 @@ seattle = { gateway-v4 = "10.0.0.1"; nameservers = [ "10.0.0.1" ]; + network = "10.0.0.0/16"; + dynamic-network = "10.0.1.0/24"; timezone = "America/Los_Angeles"; gateway-host = "nostromo"; # FIXME: good idea? @@ -39,6 +41,7 @@ portage = { gateway-v4 = "208.81.3.113"; # gateway-v6 = "265:e200:d200:1::1"; + network = "208.81.3.112/28"; nameservers = [ "1.1.1.1" "208.81.7.14" "2606:4700:4700::1111" ]; timezone = "America/Winnipeg"; }; @@ -46,12 +49,15 @@ russell = { gateway-v4 = "10.0.0.1"; nameservers = [ "10.0.0.1" ]; + network = "10.0.0.0/16"; + dynamic-network = "10.0.1.0/24"; timezone = "America/Winnipeg"; gateway-host = "clunk"; }; joes-datacenter-0 = { gateway-v4 = "172.86.179.17"; + network = "FIXME"; nameservers = [ "1.1.1.1" "2606:4700:4700::1111" ]; timezone = "America/Winnipeg"; }; diff --git a/configuration.nix b/configuration.nix index 166ffce..92d48ab 100644 --- a/configuration.nix +++ b/configuration.nix @@ -4,9 +4,7 @@ let local = import ../host-config.nix; initialize = import ./initialize.nix; - # (import "${builtins.fetchTarball https://github.com/rycee/home-manager/archive/master.tar.gz}/nixos") - -in { +in { imports = [ (initialize { hostname = local.hostname; @@ -15,7 +13,7 @@ in { domain = local.domain; home-manager-package = builtins.fetchGit { url = "https://github.com/nix-community/home-manager.git"; - ref = "release-20.09"; + ref = "release-20.09"; }; }) ]; diff --git a/initialize.nix b/initialize.nix index caa6fc8..dba470e 100644 --- a/initialize.nix +++ b/initialize.nix @@ -6,19 +6,17 @@ ./config ./packages - (import "${home-manager-package}/nixos") - (./. + "/config/hardware/${hostname}.nix") (./. + "/config/hosts/${hostname}.nix") (./. + "/config/profiles/${profile}.nix") (./. + "/config/domains/${domain}.nix") (./. + "/config/sites/${site}.nix") + + (import "${home-manager-package}/nixos") ]; - + config = { - instance = { - hostname = hostname; - }; + instance = { hostname = hostname; }; fudo.hosts."${hostname}" = { domain = domain; @@ -27,4 +25,4 @@ profile = profile; }; }; -} \ No newline at end of file +} diff --git a/lib/default.nix b/lib/default.nix index 1c17c37..3620f53 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,9 +1,13 @@ { lib, config, pkgs, ... }: with lib; { - lib = lib // { fudo = import ./lib/fudolib.nix { }; }; + + lib = lib // { fudo = import ./lib/lib.nix { inherit lib; }; }; imports = [ + ../config + ../packages + ./instance.nix ./fudo/acme-for-hostname.nix diff --git a/lib/fudo/hosts.nix b/lib/fudo/hosts.nix index 998e59b..53a3d23 100644 --- a/lib/fudo/hosts.nix +++ b/lib/fudo/hosts.nix @@ -32,7 +32,7 @@ let profile = mkOption { # FIXME: get this list from profiles directly type = with types; - listof (enum "desktop" "laptop" "server" "gateway-server"); + listof (enum "desktop" "laptop" "server"); description = "The profile to be applied to the host, determining what software is included."; }; diff --git a/lib/fudo/local-network.nix b/lib/fudo/local-network.nix index cb52e2a..0751232 100644 --- a/lib/fudo/local-network.nix +++ b/lib/fudo/local-network.nix @@ -5,8 +5,8 @@ with lib; let cfg = config.fudo.local-network; - ip = import ../../lib/ip.nix {}; - dns = import ../../lib/dns.nix {}; + dns = import ../lib/dns.nix { inherit lib; }; + ip = import ../lib/ip.nix { inherit lib; }; join-lines = concatStringsSep "\n"; @@ -30,7 +30,7 @@ let ssh-fingerprints = mkOption { type = with types; listOf str; description = "A list of DNS SSHFP records for this host."; - default = []; + default = [ ]; }; }; }; @@ -45,7 +45,7 @@ in { hosts = mkOption { type = with types; attrsOf (submodule hostOpts); - default = {}; + default = { }; description = "A map of hostname => { host_attributes }."; }; @@ -56,7 +56,8 @@ in { dns-servers = mkOption { type = with types; listOf str; - description = "A list of domain name server to use for the local network."; + description = + "A list of domain name server to use for the local network."; }; dhcp-interfaces = mkOption { @@ -76,8 +77,9 @@ in { aliases = mkOption { type = with types; attrsOf str; - default = {}; - description = "A mapping of host-alias => hostname to use on the local network."; + default = { }; + description = + "A mapping of host-alias => hostname to use on the local network."; }; network = mkOption { @@ -113,14 +115,14 @@ in { 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 = []; + example = [ "some-host IN CNAME other-host" ]; + default = [ ]; }; srv-records = mkOption { type = dns.srvRecords; description = "Map of traffic type to srv records."; - default = {}; + default = { }; example = { tcp = { kerberos = { @@ -134,8 +136,8 @@ in { 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 = []; + example = [ "my-domain.com" "other-domain.com" ]; + default = [ ]; }; # TODO: srv records @@ -154,15 +156,22 @@ in { interfaces = cfg.dhcp-interfaces; extraConfig = '' - subnet ${ip.getNetworkBase cfg.network} netmask ${ip.maskFromV32Network cfg.network} { + 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}; + 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 + }; } ''; }; @@ -194,16 +203,23 @@ in { ''; }; - 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; + 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}."; + "${ + 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); + hostSshFpRecords = host: data: + join-lines + (map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints); cnameRecord = alias: host: "${alias} IN CNAME ${host}"; in { @@ -218,35 +234,33 @@ in { "recursion yes;" "allow-recursion { any; };" ]; - 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) + 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 + $TTL 1h - @ IN NS ns1.${cfg.domain}. + @ IN NS ns1.${cfg.domain}. - $ORIGIN ${cfg.domain}. + $ORIGIN ${cfg.domain}. - $TTL 30m + $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} - ${dns.srvRecordsToBindZone cfg.srv-records} - ''; - } - ] ++ blockZones; + 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} + ${dns.srvRecordsToBindZone cfg.srv-records} + ''; + }] ++ blockZones; }; }; } diff --git a/lib/fudo/secure-dns-proxy.nix b/lib/fudo/secure-dns-proxy.nix index 3f481e1..ee6678d 100644 --- a/lib/fudo/secure-dns-proxy.nix +++ b/lib/fudo/secure-dns-proxy.nix @@ -1,14 +1,14 @@ { lib, pkgs, config, ... }: with lib; -let - cfg = config.fudo.secure-dns-proxy; +let cfg = config.fudo.secure-dns-proxy; in { options.fudo.secure-dns-proxy = { - enable = mkEnableOption "Enable a DNS server using an encrypted upstream source."; + enable = + mkEnableOption "Enable a DNS server using an encrypted upstream source."; - port = mkOption { + listen-port = mkOption { type = types.port; description = "Port on which to listen for DNS queries."; default = 53; @@ -21,26 +21,25 @@ in { See: https://github.com/AdguardTeam/dnsproxy ''; - default = ["https://cloudflare-dns.com/dns-query"]; + default = [ "https://cloudflare-dns.com/dns-query" ]; }; bootstrap-dns = mkOption { type = types.str; - description = "A simple DNS server from which HTTPS DNS can be bootstrapped, if necessary."; + description = + "A simple DNS server from which HTTPS DNS can be bootstrapped, if necessary."; default = "1.1.1.1"; }; listen-ips = mkOption { type = with types; listOf str; description = "A list of local IP addresses on which to listen."; - default = ["0.0.0.0"]; + default = [ "0.0.0.0" ]; }; }; config = mkIf cfg.enable { - environment.systemPackages = with pkgs; [ - dnsproxy - ]; + environment.systemPackages = with pkgs; [ dnsproxy ]; systemd.services.secure-dns-proxy = { enable = true; @@ -50,13 +49,13 @@ in { serviceConfig = let upstreams = map (upstream: "-u ${upstream}") cfg.upstream-dns; upstream-line = concatStringsSep " " upstreams; - listen-line = concatStringsSep " " - (map (listen: "-l ${listen}") cfg.listen-ips); - cmd = "${pkgs.dnsproxy}/bin/dnsproxy -p ${toString cfg.port} ${upstream-line} ${listen-line} -b ${cfg.bootstrap-dns}"; + listen-line = + concatStringsSep " " (map (listen: "-l ${listen}") cfg.listen-ips); + cmd = "${pkgs.dnsproxy}/bin/dnsproxy -p ${ + toString cfg.listen-port + } ${upstream-line} ${listen-line} -b ${cfg.bootstrap-dns}"; - in { - ExecStart = cmd; - }; + in { ExecStart = cmd; }; }; }; } diff --git a/lib/fudo/sites.nix b/lib/fudo/sites.nix index 98d342a..61179bb 100644 --- a/lib/fudo/sites.nix +++ b/lib/fudo/sites.nix @@ -10,6 +10,17 @@ let default = site; }; + network = mkOption { + type = types.str; + description = "Network to be treated as local."; + }; + + dynamic-network = mkOption { + type = with types; nullOr str; + description = "Network to be allocated by DHCP."; + default = null; + }; + gateway-v4 = mkOption { type = with types; nullOr str; description = "Gateway to use for public ipv4 internet access."; @@ -30,20 +41,22 @@ let local-groups = mkOption { type = with types; listOf str; - description = "List of groups which should exist at this site."; - default = [ ]; + description = "List of groups which should exist at this site."; + default = [ ]; }; local-users = mkOption { type = with types; listOf str; - description = "List of users which should exist on all hosts at this site."; - default = [ ]; + description = + "List of users which should exist on all hosts at this site."; + default = [ ]; }; local-admins = mkOption { type = with types; listOf str; - description = "List of admin users which should exist on all hosts at this site."; - default = [ ]; + description = + "List of admin users which should exist on all hosts at this site."; + default = [ ]; }; enable-monitoring = @@ -57,8 +70,8 @@ let timezone = mkOption { type = types.str; - description = "Timezone of the site."; - example = "America/Winnipeg"; + description = "Timezone of the site."; + example = "America/Winnipeg"; }; }; }; diff --git a/lib/fudolib.nix b/lib/fudolib.nix deleted file mode 100644 index f253011..0000000 --- a/lib/fudolib.nix +++ /dev/null @@ -1,6 +0,0 @@ -{ lib, ... }: - -{ - ip = import ./fudolib/ip.nix { }; - dns = import ./fudolib/dns.nix { }; -} diff --git a/lib/lib.nix b/lib/lib.nix new file mode 100644 index 0000000..1e2d6e8 --- /dev/null +++ b/lib/lib.nix @@ -0,0 +1,6 @@ +{ lib, ... }: + +{ + ip = import ./lib/ip.nix { }; + dns = import ./lib/dns.nix { }; +} diff --git a/lib/fudolib/dns.nix b/lib/lib/dns.nix similarity index 100% rename from lib/fudolib/dns.nix rename to lib/lib/dns.nix diff --git a/lib/fudolib/ip.nix b/lib/lib/ip.nix similarity index 100% rename from lib/fudolib/ip.nix rename to lib/lib/ip.nix