From d9ea6a9ecc783bf085dd0a17d860fa00ad81db57 Mon Sep 17 00:00:00 2001 From: Erik Simon Date: Mon, 20 Jul 2026 19:41:39 +0200 Subject: [PATCH] mercury: join the tailnet mercury was the only host with no tailscale at all -- no module import, no secret, no key in its sops file. It had been enrolled before the NixOS migration and silently dropped off the tailnet when it was reflashed with a config that omitted it. --accept-dns=false, as on neptun and for a sharper reason: headscale pushes override_local_dns, so accepting MagicDNS would repoint the LAN's own DNS server at 100.100.100.100 and make house-wide name resolution depend on tailscaled being up. This host has already deadlocked once on boot-time DNS (see CLAUDE.md). darman_password is also rotated: the account had "!" in /etc/shadow, because on mercury's first boot the secret wasn't readable yet and update-users-groups.pl falls back to a locked account. mutableUsers is true, so no later rebuild ever revisited it and the lock was permanent. Co-Authored-By: Claude Opus 4.8 --- hosts/mercury/configuration.nix | 8 ++++++++ hosts/mercury/secrets.nix | 4 ++++ secrets/mercury.yaml | 7 ++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/hosts/mercury/configuration.nix b/hosts/mercury/configuration.nix index 37c404c..c06c3bc 100644 --- a/hosts/mercury/configuration.nix +++ b/hosts/mercury/configuration.nix @@ -9,6 +9,7 @@ ./secrets.nix # sops-nix: darman password (age key on boot part.) ../../services/network/unbound.nix # local recursive resolver (127.0.0.1:5335) ../../services/network/pihole.nix # DNS adblock + DHCP (declarative static leases) + ../../services/vpn/tailscale.nix # tailnet node (headscale on neptun) ]; networking.hostName = "mercury"; @@ -33,6 +34,13 @@ # host resolves during boot without depending on its own pihole/unbound. networking.nameservers = [ "1.1.1.1" "9.9.9.9" ]; + # Never take MagicDNS on THIS host. headscale pushes override_local_dns, so + # accepting it would repoint mercury's resolv.conf at 100.100.100.100 and + # make the LAN's DNS server depend on tailscaled to resolve anything — the + # same boot-time DNS deadlock this host already hit once (see CLAUDE.md), + # except a failure here takes the whole network's DNS down with it. + services.tailscale.extraUpFlags = [ "--accept-dns=false" ]; + # ---- pihole web admin password (from sops) ---- # The pihole container reads FTLCONF_* env vars. Render an env file from the # sops secret and feed it to the container — password stays out of repo/store. diff --git a/hosts/mercury/secrets.nix b/hosts/mercury/secrets.nix index 10be8a7..3c1bc5e 100644 --- a/hosts/mercury/secrets.nix +++ b/hosts/mercury/secrets.nix @@ -15,4 +15,8 @@ # host = different password per host. sops.secrets.darman_password.neededForUsers = true; users.users.darman.hashedPasswordFile = config.sops.secrets.darman_password.path; + + # Pre-auth key for services/vpn/tailscale.nix. Root-owned 0400 is right: + # tailscaled runs as root and reads authKeyFile itself. + sops.secrets.tailscale_authkey = { }; } diff --git a/secrets/mercury.yaml b/secrets/mercury.yaml index 6b70d56..93f8f6c 100644 --- a/secrets/mercury.yaml +++ b/secrets/mercury.yaml @@ -1,5 +1,6 @@ -darman_password: ENC[AES256_GCM,data:Wc7y/5QPUxD4mxDGBp9V2k6YNrbmehbpcltInIBSGk70cdqxSUOjHZIL0hzPS4ijrXPnR9gwSZbc7EmgbLZ2K96SJtz9+upDAQVVUFfNx0o+SfGEu3ai3Qi7tKa+1N9wZQW/+6gQOAMAGQ==,iv:K/GrcQFtYWgQAtDlNVaYS5jUADYfX6rMSIUM9niRcWQ=,tag:9dbiRlIzAkm382Bkc6LfJA==,type:str] +darman_password: ENC[AES256_GCM,data:iZQERcXtyH+91yUc3r7U6jnFYrGQPFeCPk/9ZDfxOhPLlGMX3/iEZ+SzZ7a7rDKUeUAaQUsrqANLDLclRYm4Ngo09EkbDxBx5x2GpQwlqSAS45LHnTen9LTzisWghdy79Xnilq322eaB3g==,iv:ozx/BPLR8nZTKHZroKrrh2z6ZlVCuLydQ3aNY4XvcIg=,tag:CSrq5ZipYxtXTT8RintuHQ==,type:str] pihole_webpassword: ENC[AES256_GCM,data:5iOTqD0CcbOCnM1b4+RbajMTyAU=,iv:2ZRW7dshnPzWkuudrn6n92y4Z2n/6fdnBB7BO5/ypS4=,tag:8UZSqJM6dVECQgrF6v5Fuw==,type:str] +tailscale_authkey: ENC[AES256_GCM,data:CZe1wkh2DNF2g4wy30Wph0c4/3f1M2K9Up+3oAcLEVdZjJzLRJotAU/0Nw2PSGoDZTtqOSfDaEXsaa45DBIJj2EUvWKSYrkV4XkLCio6ZWoGhmxH9PYfkw==,iv:UqNZz7grRPT/d1a2Tv1PW4H2k5FeZCuDy/fK+jVou9E=,tag:cYbLk+7JqU/1by8j2ri0Xg==,type:str] sops: age: - enc: | @@ -20,7 +21,7 @@ sops: x6FfYadcRfqvSX60l6+TGdzq6xDpxLIZOJ8q19qZsAvB0in50HW5gg== -----END AGE ENCRYPTED FILE----- recipient: age1cpty7zrgnn6l97upq00w5wa8zcvnkxkdt2jvhlj97jh83exure4slha43t - lastmodified: "2026-07-13T20:42:08Z" - mac: ENC[AES256_GCM,data:TWismb9lTPOp9RC0u7zlQPoJtql5G0obxFIcI2D4R43VCRKux6LPzZvVEwLe7KjkLC9c6p+ti1dy4lIL9lo57BJfyh1HV+u+RvVCTbVw0Cd8EoGCC3NWJ+jFJi6jWAwOdJ2SOgOavpxBaFObYpEGkJ4XZqJX7XCY/k4YuuFT/yo=,iv:XtHOSE2ZH3j3blSWkXUqxWmZOO1tVEKoWgHB7rt81qA=,tag:7JBmUyHgqSbrmNqPXfXMTQ==,type:str] + lastmodified: "2026-07-20T08:31:19Z" + mac: ENC[AES256_GCM,data:kdWGhCOENvnUAnwbLW58JH8Ur+g+f4Z1pr3seZGGOFa04xeXb5HOzegpIH+x7OT5OvsKZsMKWf7sBGgB/nx+m2ZKy4NLC39dLbV8V5hs18NhRKl5vKZBZHE1D2xAK4+REwRYT6LiXArQssPv9e2q5fcW6q3rtnlHMF0tUsWip9o=,iv:BkKv2ZBxZMX4agHTzF2Mcmasxpp+hqkiu9mH0mUeLS4=,tag:t0MeKRPikYR5MAmU8r77sg==,type:str] unencrypted_suffix: _unencrypted version: 3.13.1