{ zentralwerk, config, pkgs, ... }: let systemctl = "${pkgs.systemd}/bin/systemctl"; deployCommand = "${systemctl} start deploy-c3d2-dns"; # wrap reload in freeze/thaw so that zones are reloaded that had # been updated by dyndns reloadCommand = with pkgs; writeScript "reload-bind" '' #! ${runtimeShell} rndc() { ${bind}/sbin/rndc -k /etc/bind/rndc.key $@ } rndc freeze rndc reload rndc thaw ''; in { c3d2 = { isInHq = false; hq.statistics.enable = true; deployment.server = "server10"; }; system.stateVersion = "22.05"; networking = { hostName = "bind"; firewall = { allowedTCPPorts = [ 53 # DNS 80 443 # HTTP(s) ]; allowedUDPPorts = [ 53 # DNS ]; }; }; # DNS server services.bind = { enable = true; extraConfig = '' include "${config.users.users.c3d2-dns.home}/c3d2-dns/zones.conf"; include "${zentralwerk.packages.${pkgs.system}.dns-slaves}"; # for collectd statistics-channels { inet 127.0.0.1 port 8053; }; ''; }; systemd.services.bind = { serviceConfig = { Restart = "always"; RestartSec = "1s"; }; }; # BIND statistics in Grafana services.collectd.plugins.bind = '' URL "http://127.0.0.1:8053/"; ParseTime false OpCodes true QTypes true ServerStats true ZoneMaintStats true ResolverStats false MemoryStats true ''; # Build user users.groups.c3d2-dns = {}; users.users.c3d2-dns = { isSystemUser = true; group = "c3d2-dns"; home = "/var/lib/c3d2-dns"; }; systemd.tmpfiles.rules = [ "d ${config.users.users.c3d2-dns.home} 0755 c3d2-dns ${config.users.users.c3d2-dns.group} - -" "d /var/lib/bind/slave 0755 named nogroup - -" ]; # Build script systemd.services.deploy-c3d2-dns = let inherit (pkgs.bind-secrets) giteaToken sshPrivkey; in { wantedBy = [ "multi-user.target" ]; before = [ "bind.service" ]; after = [ "network-online.target" ]; path = with pkgs; [ git nix curl openssh ]; script = '' mkdir -p .ssh cp ${builtins.toFile "id_ed25519" sshPrivkey} .ssh/id_ed25519 echo "gitea.c3d2.de ${config.c3d2.hosts.gitea.publicKey}" > .ssh/known_hosts chmod 0600 .ssh/id_ed25519 # Build at least once touch deploy-pending status() { curl -X POST \ "https://gitea.c3d2.de/api/v1/repos/c3d2-admins/c3d2-dns/statuses/$REV?token=${giteaToken}" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ -d "$1" } [ -d c3d2-dns ] || git clone --depth=1 gitea@gitea.c3d2.de:c3d2-admins/c3d2-dns.git cd c3d2-dns # Loop in case the webhook was called while we were building while [ -e ../deploy-pending ]; do rm ../deploy-pending git checkout . git pull REV=$(git rev-parse HEAD) set +e status "{ \"context\": \"c3d2-dns\", \"description\": \"reloading...\", \"state\": \"pending\"}" # Fix legacy paths (TODO) for f in *.conf ; do sed -e 's#/home/git/#${config.users.users.c3d2-dns.home}/#g' -i $f done # Allow creation of .jnl files by BIND for DynDNS chmod a+w zones # Clean up .jnl files rm -f zones/*.jnl # Take action if systemctl is-active -q bind; then /run/wrappers/bin/sudo ${reloadCommand} fi if [ $? = 0 ]; then status "{ \"context\": \"c3d2-dns\", \"description\": \"reloaded\", \"state\": \"success\"}" else status "{ \"context\": \"c3d2-dns\", \"description\": \"reload failure\", \"state\": \"failure\"}" fi set -e done ''; serviceConfig = { User = "c3d2-dns"; Group = config.users.users.c3d2-dns.group; PrivateTmp = true; ProtectSystem = "full"; ReadWritePaths = config.users.users.c3d2-dns.home; WorkingDirectory = config.users.users.c3d2-dns.home; }; }; # Privileged commands triggered by webhook/deploy-c3d2-dns security.sudo.extraRules = [ { users = [ "c3d2-dns" ]; commands = [ { command = deployCommand; options = [ "NOPASSWD" ]; } { command = toString reloadCommand; options = [ "NOPASSWD" ]; } ]; } ]; # Web server just for the webhook services.nginx = { enable = true; virtualHosts = { # hooks, logs "bind.serv.zentralwerk.org" = { default = true; enableACME = true; forceSSL = true; locations."/hooks/".proxyPass = "http://localhost:9000/hooks/"; }; }; }; # Webhook service systemd.services.webhook = let hooksJson = pkgs.writeText "hooks.json" (builtins.toJSON [ { id = "deploy-c3d2-dns"; execute-command = pkgs.writeShellScript "deploy-c3d2-dns" '' # Request (re-)deployment touch ${config.users.users.c3d2-dns.home}/deploy-pending # Start deploy-c3d2-dns.service if not already running exec /run/wrappers/bin/sudo ${deployCommand} ''; } ]); in { wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.webhook}/bin/webhook -hooks ${hooksJson} -verbose -ip 127.0.0.1"; User = "c3d2-dns"; Group = config.users.users.c3d2-dns.group; PrivateTmp = true; ProtectSystem = "full"; }; }; }