diff --git a/config/fudo/garbage-collector.nix b/config/fudo/garbage-collector.nix new file mode 100644 index 0000000..3eafdd6 --- /dev/null +++ b/config/fudo/garbage-collector.nix @@ -0,0 +1,49 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.fudo.garbage-collector; + +in { + + options.fudo.garbage-collector = { + enable = mkEnableOption "Enable periodic NixOS garbage collection"; + + timing = mkOption { + type = types.str; + default = "weekly"; + description = "Period (systemd format) at which to run garbage collector."; + }; + + age = mkOption { + type = types.str; + default = "30d"; + description = "Age of garbage to collect (eg. 30d)."; + }; + }; + + config = mkIf cfg.enable { + systemd = { + timers.fudo-garbage-collector = { + enable = true; + description = "Collect NixOS garbage older than ${cfg.age}"; + partOf = [ "fudo-garbage-collector.service" ]; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = cfg.timing; + }; + }; + + services.fudo-garbage-collector = { + enable = true; + serviceConfig = { + Type = "oneshot"; + StandardOutput = "journal"; + }; + script = '' + ${pkgs.nix}/bin/nix-collect-garbage --delete-older-than ${cfg.age} + ''; + }; + }; + }; +} diff --git a/config/fudo/local-network.nix b/config/fudo/local-network.nix index 1b036f2..023ad5d 100644 --- a/config/fudo/local-network.nix +++ b/config/fudo/local-network.nix @@ -20,10 +20,11 @@ let }; mac-address = mkOption { - type = types.str; + type = with types; nullOr types.str; description = '' The MAC address of a given host, if desired for IP reservation. ''; + default = null; }; ssh-fingerprints = mkOption { @@ -43,7 +44,7 @@ in { enable = mkEnableOption "Enable local network configuration (DHCP & DNS)."; hosts = mkOption { - type = with types; loaOf (submodule hostOpts); + type = with types; attrsOf (submodule hostOpts); default = {}; description = "A map of hostname => { host_attributes }."; }; @@ -74,7 +75,7 @@ in { }; aliases = mkOption { - type = with types; loaOf str; + type = with types; attrsOf str; default = {}; description = "A mapping of host-alias => hostname to use on the local network."; }; @@ -148,7 +149,7 @@ in { ethernetAddress = hostOpts.mac-address; hostName = hostname; ipAddress = hostOpts.ip-address; - }) cfg.hosts; + }) (filterAttrs (host: hostOpts: hostOpts.mac-address != null) cfg.hosts); interfaces = cfg.dhcp-interfaces; @@ -210,6 +211,13 @@ in { cacheNetworks = [ cfg.network "localhost" "localnets" ]; forwarders = [ cfg.recursive-resolver ]; listenOn = cfg.dns-serve-ips; + extraOptions = concatStringsSep "\n" [ + "dnssec-enable yes;" + "dnssec-validation yes;" + "auth-nxdomain no;" + "recursion yes;" + "allow-recursion { any; };" + ]; zones = [ { master = true; diff --git a/config/local.nix b/config/local.nix index 681da1e..7c2b692 100644 --- a/config/local.nix +++ b/config/local.nix @@ -10,6 +10,7 @@ with lib; ./fudo/client/dns.nix ./fudo/common.nix ./fudo/dns.nix + ./fudo/garbage-collector.nix ./fudo/git.nix ./fudo/grafana.nix ./fudo/kdc.nix diff --git a/defaults.nix b/defaults.nix index 4178d9c..89e36e1 100644 --- a/defaults.nix +++ b/defaults.nix @@ -30,7 +30,6 @@ clang curl dpkg - emacs enca fail2ban file diff --git a/fudo/profiles/common-ui.nix b/fudo/profiles/common-ui.nix index e016ef8..0e0cbfd 100644 --- a/fudo/profiles/common-ui.nix +++ b/fudo/profiles/common-ui.nix @@ -19,6 +19,7 @@ let corefonts chrome-gnome-shell chromium + emacs evince firefox gimp diff --git a/fudo/profiles/server.nix b/fudo/profiles/server.nix index c9d9dd3..a095170 100644 --- a/fudo/profiles/server.nix +++ b/fudo/profiles/server.nix @@ -51,6 +51,7 @@ in { config = mkIf (config.fudo.common.profile == "server") { environment = { systemPackages = with pkgs; [ + emacs-nox ldns ldns.examples racket-minimal @@ -67,8 +68,8 @@ in { networking = { networkmanager.enable = mkForce false; - } -; + }; + boot.tmpOnTmpfs = true; services.xserver.enable = false; diff --git a/fudo/sites/russell.nix b/fudo/sites/russell.nix index e10a3c4..0eb6a64 100644 --- a/fudo/sites/russell.nix +++ b/fudo/sites/russell.nix @@ -4,10 +4,11 @@ with lib; let admin = "admin@fudo.org"; - nameservers = [ - "1.1.1.1" - "8.8.8.8" - ]; + local-domain = "rus.selby.ca"; + + gateway = "10.0.0.1"; + + nameservers = [ "10.0.0.1" ]; hostname = config.networking.hostName; @@ -20,15 +21,146 @@ in { }; networking = { - domain = "fudo.org"; - search = ["fudo.org"]; - firewall.enable = false; + domain = "rus.selby.ca"; + search = [local-domain "fudo.org" "selby.ca"]; nameservers = nameservers; + + # Don't set the gateway if we ARE the gateway. + # This is the most generic way I can think of to do that. local-network is really + # about running all the local servers (DNS, DHCP, and providing gateway). + defaultGateway = optionalString (config.fudo.local-network.enable != true) gateway; + + enableIPv6 = true; + + + # Necessary to make sure than Kerberos and Avahi both work (the former + # needs the full reverse-lookup name of the server, the latter wants + # `hostname` to return just the host itself. + hosts = { + "127.0.0.1" = [ + "${config.networking.hostName}.${local-domain}" + config.networking.hostName + ]; + }; }; - # fudo.node-exporter = { - # enable = true; - # hostname = hostname; - # }; + krb5.libdefaults.default_realm = "FUDO.ORG"; + + users.extraUsers = { + guest = { + isNormalUser = true; + uid = 1000; + description = "Guest User"; + extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"]; + }; + ken = { + isNormalUser = true; + uid = 10035; + createHome = true; + description = "Ken Selby"; + extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"]; + group = "users"; + home = "/home/selby/ken"; + hashedPassword = "$6$EwK9fpbH8$gYVzYY1IYw2/G0wCeUxXrZZqvjWCkCZbBqCOhxowbMuYtC5G0vp.AoYhVKWOJcHJM2c7TdPmAdnhLIe2KYStf."; + }; + xiaoxuan = { + isNormalUser = true; + uid = 10065; + createHome = true; + description = "Xiaoxuan Jin"; + extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"]; + group = "users"; + home = "/home/xiaoxuan"; + hashedPassword = "$6$C8lYHrK7KvdKm/RE$cHZ2hg5gEOEjTV8Zoayik8sz5h.Vh0.ClCgOlQn8l/2Qx/qdxqZ7xCsAZ1GZ.IEyESfhJeJbjLpykXDwPpfVF0"; + }; + }; + + fudo.common.domain = "sea.fudo.org"; + + fudo.local-network = { + domain = "${local-domain}"; + + network = "10.0.0.0/16"; + + dhcp-dynamic-network = "10.0.1.0/24"; + + enable-reverse-mappings = true; + + srv-records = { + tcp = { + domain = [{ + port = 53; + host = "clunk.${local-domain}"; + }]; + kerberos = [{ + port = 88; + host = "france.fudo.org"; + }]; + kerberos-adm = [{ + port = 88; + host = "france.fudo.org"; + }]; + ssh = [{ + port = 22; + host = "clunk.${local-domain}"; + }]; + }; + + udp = { + domain = [{ + port = 53; + host = "clunk.${local-domain}"; + }]; + kerberos = [{ + port = 88; + host = "france.fudo.org"; + }]; + kerboros-master = [{ + port = 88; + host = "france.fudo.org"; + }]; + kpasswd = [{ + port = 464; + host = "france.fudo.org"; + }]; + }; + }; + + aliases = { + dns-hole = "clunk"; + }; + + hosts = { + clunk = { + ip-address = "10.0.0.1"; + mac-address = "02:44:d1:eb:c3:6b"; + }; + + dns-proxy = { + ip-address = "10.0.0.2"; + # This is just an alias for clunk's primary interface + }; + + google-wifi = { + ip-address = "10.0.0.11"; + mac-address = "70:3a:cb:c0:3b:09"; + }; + + pselby-work = { + ip-address = "10.0.0.151"; + mac-address = "00:50:b6:aa:bd:b3"; + }; + + downstairs-desktop = { + ip-address = "10.0.0.100"; + mac-address = "90:b1:1c:8e:29:cf"; + }; + + upstairs-desktop = { + ip-address = "10.0.0.101"; + mac-address = "00:21:70:70:25:7d"; + }; + }; + }; }; } diff --git a/fudo/sites/seattle.nix b/fudo/sites/seattle.nix index 289166f..9a0384b 100644 --- a/fudo/sites/seattle.nix +++ b/fudo/sites/seattle.nix @@ -118,8 +118,8 @@ in { domain = "${local-domain}"; aliases = { - kadmin = "slab"; - kdc = "slab"; + kadmin = "nostromo"; + kdc = "nostromo"; photo = "doraemon"; music = "doraemon"; panopticon = "hyperion"; diff --git a/hosts/clunk.nix b/hosts/clunk.nix index b1fb4fb..b93770a 100644 --- a/hosts/clunk.nix +++ b/hosts/clunk.nix @@ -3,6 +3,7 @@ let hostname = "clunk"; host-internal-ip = "10.0.0.1"; + dns-proxy-ip = "10.0.0.2"; inherit (lib.strings) concatStringsSep; in { @@ -11,6 +12,10 @@ in { boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; + boot = { + runSize = "50%"; + }; + hardware.bluetooth.enable = false; imports = [ @@ -23,17 +28,16 @@ in { site = "russell"; }; - # fudo.local-network = { - # enable = true; - # dns-servers = [ host-internal-ip ]; - # gateway = host-internal-ip; - # dhcp-interfaces = [ "intif0" ]; - # dns-serve-ips = [ host-internal-ip "127.0.0.1" "127.0.1.1" ]; - # # Using a pihole running in docker, see below - # recursive-resolver = "${host-internal-ip} port 5353"; - # # recursive-resolver = "1.1.1.1"; - # server-ip = host-internal-ip; - # }; + fudo.local-network = { + enable = true; + dns-servers = [ host-internal-ip ]; + gateway = host-internal-ip; + dhcp-interfaces = [ "intif0" ]; + dns-serve-ips = [ host-internal-ip "127.0.0.1" "127.0.1.1" "::1" ]; + # Using a pihole running in docker, see below + recursive-resolver = "${host-internal-ip} port 5353"; + server-ip = host-internal-ip; + }; networking = { hostName = hostname; @@ -48,6 +52,11 @@ in { }; }; + firewall = { + enable = true; + trustedInterfaces = [ "intif0" "docker0" ]; + }; + interfaces = { enp2s0.useDHCP = false; enp3s0.useDHCP = false; @@ -65,6 +74,11 @@ in { address = host-internal-ip; prefixLength = 22; } + + { + address = dns-proxy-ip; + prefixLength = 32; + } ]; }; }; @@ -77,13 +91,21 @@ in { }; fudo = { + garbage-collector = { + enable = true; + timing = "hourly"; + }; + secure-dns-proxy = { enable = true; - port = 3535; + port = 53; upstream-dns = [ - "https://cloudflare-dns.com/dns-query" + "https://1.1.1.1/dns-query" + "https://1.0.0.1/dns-query" + #"https://9.9.9.9/dns-query" ]; bootstrap-dns = "1.1.1.1"; + listen-ips = [dns-proxy-ip]; }; }; @@ -101,7 +123,7 @@ in { docker-containers = { pihole = { - image = "pihole/pihole:4.3.2-1"; + image = "pihole/pihole:v5.1.2"; ports = [ "5353:53/tcp" "5353:53/udp" @@ -109,18 +131,46 @@ in { ]; environment = { ServerIP = host-internal-ip; - VIRTUAL_HOST = "dns-hole.sea.fudo.org"; - DNS1 = "1.1.1.1"; - DNS2 = "8.8.8.8"; + VIRTUAL_HOST = "dns-hole.rus.selby.ca"; + # Not working? + DNS1 = dns-proxy-ip; + #DNS1 = "1.1.1.1"; }; volumes = [ "/srv/pihole/etc-pihole/:/etc/pihole/" "/srv/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" ]; - # TODO: DNS-over-HTTPS via cloudflared - # extraDockerOptions = [ - # "--dns=1.1.1.1" - # ]; + }; + }; + + services.nginx = { + enable = true; + + recommendedOptimisation = true; + recommendedGzipSettings = true; + + virtualHosts = { + "dns-hole.rus.selby.ca" = { + serverAliases = [ + "pihole.rus.selby.ca" + "hole.rus.selby.ca" + "pihole" + "dns-hole" + "hole" + ]; + + locations."/" = { + proxyPass = "http://127.0.0.1:3080"; + + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-By $server_addr:$server_port; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; }; }; }