diff --git a/hosts/kima/modules.nix b/hosts/kima/modules.nix index 948688da..bcf9185d 100644 --- a/hosts/kima/modules.nix +++ b/hosts/kima/modules.nix @@ -39,6 +39,7 @@ 192.168.88.14 qbt.cnst.dev 192.168.88.14 jellyseerr.cnst.dev 192.168.88.14 jellyfin.cnst.dev + 192.168.88.14 uptime.cnst.dev ''; interfaces = { "eno1" = { diff --git a/hosts/sobotka/server.nix b/hosts/sobotka/server.nix index 8cecb5e3..f129bafb 100644 --- a/hosts/sobotka/server.nix +++ b/hosts/sobotka/server.nix @@ -7,6 +7,10 @@ group = "share"; uid = 994; gid = 993; + + unbound = { + enable = true; + }; caddy = { enable = true; }; diff --git a/modules/default.nix b/modules/default.nix index 8f00b542..3fd7e280 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -133,6 +133,7 @@ ./server/jellyseerr ./server/jellyfin ./server/qbittorrent + ./server/unbound ./server/uptime-kuma ]; }; diff --git a/modules/server/pihole/default.nix b/modules/server/pihole/default.nix new file mode 100644 index 00000000..8e73e58e --- /dev/null +++ b/modules/server/pihole/default.nix @@ -0,0 +1,76 @@ +{ + config, + lib, + ... +}: let + unit = "pihole"; + srv = config.server; + cfg = config.server.${unit}; +in { + options.server.${unit} = { + enable = lib.mkEnableOption { + description = "Enable ${unit}"; + }; + url = lib.mkOption { + type = lib.types.str; + default = "${unit}.${srv.domain}"; + }; + homepage.name = lib.mkOption { + type = lib.types.str; + default = "PiHole"; + }; + homepage.description = lib.mkOption { + type = lib.types.str; + default = "Adblocking and DNS service"; + }; + homepage.icon = lib.mkOption { + type = lib.types.str; + default = "pihole.svg"; + }; + homepage.category = lib.mkOption { + type = lib.types.str; + default = "Services"; + }; + }; + config = lib.mkIf cfg.enable { + networking.firewall = { + allowedTCPPorts = [53 5335]; + allowedUDPPorts = [53 5335]; + }; + + services.unbound.settings.server = { + access-control = ["10.88.0.0/24 allow"]; + port = "5335"; + }; + + virtualisation.oci-containers = { + backend = "podman"; + containers.pihole = { + autoStart = true; + image = "pihole/pihole:latest"; + volumes = ["/var/lib/pihole:/etc/pihole/"]; + environment = { + CUSTOM_CACHE_SIZE = "0"; + PIHOLE_DNS_ = "10.88.0.1#5335"; + DNSSEC = "false"; + REV_SERVER = "true"; + VIRTUAL_HOST = "${unit}.${srv.domain}"; + WEBTHEME = "default-darker"; + }; + environmentFiles = [config.age.secrets.pihole.path]; + ports = [ + "53:53/tcp" + "53:53/udp" + "8053:80/tcp" + ]; + }; + }; + + services.caddy.virtualHosts."${cfg.url}" = { + useACMEHost = srv.domain; + extraConfig = '' + reverse_proxy http://127.0.0.1:8686 + ''; + }; + }; +} diff --git a/modules/server/unbound/default.nix b/modules/server/unbound/default.nix new file mode 100644 index 00000000..54b6c85b --- /dev/null +++ b/modules/server/unbound/default.nix @@ -0,0 +1,93 @@ +{ + lib, + pkgs, + config, + ... +}: let + unit = "unbound"; + cfg = config.server.${unit}; +in { + options.server.${unit} = { + enable = lib.mkEnableOption { + description = "Enable ${unit}"; + }; + }; + config = lib.mkIf cfg.enable { + services = { + # resolved.enable = lib.mkForce false; + unbound = { + enable = true; + enableRootTrustAnchor = true; + localControlSocketPath = "/run/unbound/unbound.ctl"; + resolveLocalQueries = true; + package = pkgs.unbound-full; + settings = { + server = { + aggressive-nsec = true; + cache-max-ttl = 86400; + cache-min-ttl = 300; + delay-close = 10000; + deny-any = true; + do-ip4 = true; + do-ip6 = true; + do-tcp = true; + do-udp = true; + prefer-ip6 = false; + edns-buffer-size = "1232"; + extended-statistics = true; + harden-algo-downgrade = true; + harden-below-nxdomain = true; + harden-dnssec-stripped = true; + harden-glue = true; + harden-large-queries = true; + harden-short-bufsize = true; + infra-cache-slabs = 8; + interface = [ + "127.0.0.1@5335" + "::@5335" + ]; + key-cache-slabs = 8; + msg-cache-size = "256m"; + msg-cache-slabs = 8; + neg-cache-size = "256m"; + num-queries-per-thread = 4096; + num-threads = 4; + outgoing-range = 8192; + prefetch = true; + prefetch-key = true; + qname-minimisation = true; + rrset-cache-size = "256m"; + rrset-cache-slabs = 8; + rrset-roundrobin = true; + serve-expired = true; + so-rcvbuf = "2m"; + so-reuseport = true; + so-sndbuf = "2m"; + statistics-cumulative = true; + statistics-interval = 0; + tls-cert-bundle = "/etc/ssl/certs/ca-certificates.crt"; + unwanted-reply-threshold = 100000; + use-caps-for-id = false; + verbosity = 1; + private-address = [ + "10.0.0.0/8" + "169.254.0.0/16" + "172.16.0.0/12" + "192.168.0.0/16" + "fd00::/8" + "fe80::/10" + + "192.0.2.0/24" + "198.51.100.0/24" + "203.0.113.0/24" + "255.255.255.255/32" + "2001:db8::/32" + ]; + private-domain = ["local"]; + domain-insecure = ["local"]; + }; + }; + }; + }; + }; +}