From 5191597f6311e3042d58ef36dcc845d6ca65bd4b Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Fri, 10 Apr 2026 15:41:53 +0200 Subject: [PATCH] fix: nb ddev networking --- hosts/nb/modules/networking.nix | 96 ++++++--------------------------- 1 file changed, 17 insertions(+), 79 deletions(-) diff --git a/hosts/nb/modules/networking.nix b/hosts/nb/modules/networking.nix index 3182ca3..12cb048 100644 --- a/hosts/nb/modules/networking.nix +++ b/hosts/nb/modules/networking.nix @@ -1,95 +1,29 @@ { config, lib, pkgs, ... }: -let - ddev-dns-update = pkgs.writeShellScriptBin "ddev-dns-update" '' - set -e - hosts_file="/var/lib/dnsmasq/ddev-hosts" - new_hosts=$(${pkgs.coreutils}/bin/mktemp) - trap '${pkgs.coreutils}/bin/rm -f "$new_hosts"' EXIT - - # Get running DDEV project names - running=$(${pkgs.ddev}/bin/ddev list --json-output 2>/dev/null \ - | ${pkgs.jq}/bin/jq -r '.raw[]? | select(.status == "running") | .name // empty' 2>/dev/null) || true - - # Build hosts entries - for name in $running; do - echo "127.0.0.1 $name.ddev.site" >> "$new_hosts" - done - - # Only reload dnsmasq if content changed - if ! ${pkgs.diffutils}/bin/cmp -s "$new_hosts" "$hosts_file"; then - ${pkgs.coreutils}/bin/cp "$new_hosts" "$hosts_file" - /run/wrappers/bin/sudo /run/current-system/systemd/bin/systemctl reload dnsmasq.service 2>/dev/null || true - fi - ''; -in { - # Enable systemd-resolved with split DNS for ddev.site + # Let DDEV manage /etc/hosts entries for its projects via `ddev-hostname`. + # Setting a mode makes setup-etc.pl copy the rendered file into /etc/ instead + # of symlinking to /etc/static/hosts, so DDEV can mutate it at runtime. + # Trade-off: every nixos-rebuild/boot resets /etc/hosts to the rendered + # content, so the user must re-run `ddev start` after a reboot/rebuild. + environment.etc.hosts.mode = "0644"; + services.resolved = { enable = true; dnssec = "false"; - extraConfig = '' - DNS=127.0.0.1:5353 - Domains=~ddev.site - ''; }; # Integrate NetworkManager with systemd-resolved networking.networkmanager.dns = "systemd-resolved"; - # Local dnsmasq for .ddev.site resolution (port 5353) - # Dynamic hosts file resolves running DDEV projects to 127.0.0.1; - # unmatched .ddev.site queries forward to VPN DNS (returns dev server IP) - services.dnsmasq = { - enable = true; - resolveLocalQueries = false; - settings = { - port = 5353; - listen-address = "127.0.0.1"; - bind-interfaces = true; - server = [ "/ddev.site/10.42.97.1" ]; - addn-hosts = "/var/lib/dnsmasq/ddev-hosts"; - }; - }; - - # Ensure hosts file exists before dnsmasq starts (owned by dominik so the - # user-level service can write it) - systemd.tmpfiles.rules = [ - "d /var/lib/dnsmasq 0755 root root -" - "f /var/lib/dnsmasq/ddev-hosts 0644 dominik root -" - ]; - - # Poll running DDEV projects and update dnsmasq hosts - # Runs as dominik because ddev needs user-level Docker access - systemd.services.ddev-dns-update = { - description = "Update dnsmasq hosts for running DDEV projects"; - after = [ "dnsmasq.service" "docker.service" ]; - serviceConfig = { - Type = "oneshot"; - User = "dominik"; - ExecStart = "${ddev-dns-update}/bin/ddev-dns-update"; - }; - }; - - systemd.timers.ddev-dns-update = { - wantedBy = [ "timers.target" ]; - timerConfig = { - OnBootSec = "30s"; - OnUnitActiveSec = "10s"; - }; - }; - - environment.systemPackages = [ ddev-dns-update ]; - + # DDEV shells out to `sudo ddev-hostname` to edit /etc/hosts. Allow it + # without a password prompt. Using the /run/current-system path keeps the + # rule valid across DDEV package updates. security.sudo.extraRules = [ { users = [ "dominik" ]; commands = [ { - command = "${ddev-dns-update}/bin/ddev-dns-update"; - options = [ "NOPASSWD" ]; - } - { - command = "/run/current-system/systemd/bin/systemctl reload dnsmasq.service"; + command = "/run/current-system/sw/bin/ddev-hostname"; options = [ "NOPASSWD" ]; } ]; @@ -122,11 +56,15 @@ in } ]; - # Use resolvectl for systemd-resolved integration + # Route *.ddev.site queries through wg0's DNS while the VPN is up so + # remote project hostnames resolve to the dev server. DDEV's hosts-file + # override then shadows those with 127.0.0.1 for locally running + # projects. When wg0 is down, queries fall back to the public + # *.ddev.site wildcard (→ 127.0.0.1). # Note: No postDown needed - systemd-resolved automatically handles interface removal postSetup = '' ${pkgs.systemd}/bin/resolvectl dns wg0 10.42.97.1 - ${pkgs.systemd}/bin/resolvectl domain wg0 cloonar.com + ${pkgs.systemd}/bin/resolvectl domain wg0 cloonar.com '~ddev.site' ''; }; };