feat: nb only serve ddev.site locally which is currently running

This commit is contained in:
Dominik Polakovics Polakovics 2026-04-02 15:19:44 +02:00
parent ab3b4a000e
commit 84d8c44876

View file

@ -1,5 +1,27 @@
{ 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
services.resolved = {
@ -14,18 +36,66 @@
# Integrate NetworkManager with systemd-resolved
networking.networkmanager.dns = "systemd-resolved";
# Local dnsmasq for .ddev.site resolution only (port 5353)
# 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;
no-resolv = true;
address = "/.ddev.site/127.0.0.1";
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 ];
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";
options = [ "NOPASSWD" ];
}
];
}
];
# WireGuard VPN configuration
networking.wireguard.interfaces = {
wg0 = {