diff --git a/README.md b/README.md index b24f943..88fbab6 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,32 @@ Also, note that you may have to get permission to be added as a user first: ``` HOST=seed.radicle.xyz; nixos-rebuild switch --target-host "${USER}@${HOST}" --build-host "${USER}@${HOST}" --use-remote-sudo --flake . ``` + +## DNS + +The radicle.xyz. zone is configured via [DNSControl]. +Previewing and pushing changes requires a [Cloudflare API Token] in the environment at `CLOUDFLARE_API_TOKEN`. + +In `/dns`: + +Sanity-check with: + + dnscontrol check + +Preview changes with: + + dnscontrol preview + +If the preview looks good, finally + + dnscontrol push + +Please keep `dnsconfig.js` tidy with + + dnscontrol fmt > tmp.js && mv tmp.js dnscontrol.js + +(As of 2025-06, there is no pre-commit hook for `dnscontrol`.) + + +[Cloudflare API Token]: https://dash.cloudflare.com/profile/api-tokens +[DNSControl]: https://docs.dnscontrol.org diff --git a/dns/creds.json b/dns/creds.json new file mode 100644 index 0000000..4f417ec --- /dev/null +++ b/dns/creds.json @@ -0,0 +1,10 @@ +{ + "cloudflare": { + "TYPE": "CLOUDFLAREAPI", + "accountid": "dcd58b4607e42dafa1592d13077a60bc", + "apitoken": "$CLOUDFLARE_API_TOKEN" + }, + "namecheap": { + "TYPE": "NAMECHEAP" + } +} diff --git a/dns/dnsconfig.js b/dns/dnsconfig.js new file mode 100644 index 0000000..0d7959b --- /dev/null +++ b/dns/dnsconfig.js @@ -0,0 +1,98 @@ +var DSP_CLOUDFLARE = NewDnsProvider("cloudflare"); +var REG_NONE = NewRegistrar("none"); +// var REG_NAMECHEAP = NewRegistrar("namecheap"); + +D("radicle.xyz", REG_NONE, DnsProvider(DSP_CLOUDFLARE), + DefaultTTL(1), + + AAAA("@", "100::", CF_PROXY_ON), + + + CNAME("docs", "radicle.xyz."), + CNAME("www", "radicle.xyz."), + + + CNAME("app", "cname.vercel-dns.com."), + CNAME("desktop", "cname.vercel-dns.com."), + TXT("@", "\"_vercel.radicle.xyz\""), + + + CNAME("toot", "vip.masto.host."), + + + TXT("_atproto", "\"did=did:plc:h3rhdktoagtwfu452cjyw3df\""), + + + CAA("@", "issue", "letsencrypt.org"), + + + // Migadu + MX("@", 10, "aspmx1.migadu.com."), + MX("@", 20, "aspmx2.migadu.com."), + CNAME("autoconfig", "autoconfig.migadu.com.", TTL(3000)), + CNAME("key1._domainkey", "key1.radicle.xyz._domainkey.migadu.com."), + CNAME("key2._domainkey", "key2.radicle.xyz._domainkey.migadu.com."), + CNAME("key3._domainkey", "key3.radicle.xyz._domainkey.migadu.com."), + SRV("_autodiscover._tcp", 0, 1, 443, "autodiscover.migadu.com.", TTL(3000)), + SRV("_imaps._tcp", 0, 1, 993, "imap.migadu.com.", TTL(3000)), + SRV("_pop3s._tcp", 0, 1, 995, "pop.migadu.com.", TTL(3000)), + SRV("_submissions._tcp", 0, 1, 465, "smtp.migadu.com.", TTL(3000)), + TXT("_dmarc", "\"v=DMARC1; p=quarantine;\"", TTL(3000)), + TXT("@", "\"v=spf1 include:spf.migadu.com -all\""), + TXT("@", "\"hosted-email-verify=n3h3hb1x\""), + + + PTR("b._dns-sd._udp", "radicle.xyz."), + PTR("lb._dns-sd._udp", "radicle.xyz."), + PTR("_services._dns-sd._udp", "_radicle-node._tcp.radicle.xyz."), + + + A("files", "65.109.236.201"), + + + A("iris", "95.217.156.6"), + SSHFP("iris", 4, 1, "1ffe43af8f30c34373515fa24f1b9fe69532a9d5"), + SSHFP("iris", 4, 2, "715ce29a1ccdd7088b9fb40949ca186e736ff6d711163689560ffe54252c9d43"), + + ALIAS("1.eu.bootstrap", "iris"), + + PTR("_radicle-node._tcp", "iris._radicle-node._tcp.radicle.xyz."), + SRV("iris._radicle-node._tcp", 32767, 32767, 8776, "iris.radicle.xyz."), + TXT("iris._radicle-node._tcp", "\"nid=z6MkrLMMsiPWUcNPHcRajuMi9mDfYckSoJyPwwnknocNYPm7\""), + + + A("rosa", "5.161.85.124"), + SSHFP("rosa", 4, 1, "6ee4b941f49ece1601e238344f088f5a83712b91"), + SSHFP("rosa", 4, 2, "e2364a3e0f7728eaa53d40543f15e7c23409fe06e5b08c55d8f63ee00e963b0b"), + + ALIAS("1.us.bootstrap", "rosa"), + + PTR("_radicle-node._tcp", "rosa._radicle-node._tcp.radicle.xyz."), + SRV("rosa._radicle-node._tcp", 32767, 32767, 8776, "rosa.radicle.xyz."), + TXT("rosa._radicle-node._tcp", "\"nid=z6Mkmqogy2qEM2ummccUthFEaaHvyYmYBYh3dbe9W4ebScxo\""), + + + A("search", "178.238.227.79"), + + + A("seed", "65.108.87.205"), + SSHFP("seed", 4, 2, "ac7db28d3d05c52f3e2d67adca4654ce6766a1e8d7b6fab4c03b25ab435a613d"), + SSHFP("seed", 4, 1, "9033b89019264dbad5a744057166a5e1b7af92f7"), + + ALIAS("attic", "seed"), + ALIAS("grafana", "seed"), + ALIAS("logs", "seed"), + ALIAS("loki", "seed"), + ALIAS("metrics", "seed"), + ALIAS("vault", "seed"), + + // LOC("seed", "60 20 36.488 N 25 01 48.587 E 46m 10m 100m 100m"), + PTR("_radicle-node._tcp", "seed._radicle-node._tcp.radicle.xyz."), + SRV("seed._radicle-node._tcp", 32767, 32767, 8776, "seed.radicle.xyz."), + TXT("seed._radicle-node._tcp", "\"nid=z6MksmpU5b1dS7oaqF2bHXhQi1DWy2hB7Mh9CuN7y1DN6QSz\""), + + + // Ignore all records related to dynamic bootstrapping. + IGNORE("_radicle-node._tcp.bootstrap", "PTR", "**.*.bootstrap.radicle.xyz."), + IGNORE("**.*.bootstrap", "SRV,TXT"), +); diff --git a/flake.nix b/flake.nix index 3f35697..b747be6 100644 --- a/flake.nix +++ b/flake.nix @@ -172,7 +172,11 @@ devShells.${system}.default = pkgs.mkShell { inherit (self.checks.${system}.pre-commit) shellHook; - buildInputs = self.checks.${system}.pre-commit.enabledPackages; + buildInputs = + self.checks.${system}.pre-commit.enabledPackages + ++ (with pkgs; [ + dnscontrol + ]); }; formatter.${system} = pkgs.writeShellApplication { @@ -196,6 +200,11 @@ alejandra.enable = true; }; }; + dnscontrol = pkgs.runCommand "dnscontrol" {} '' + cd ${./dns} + ${pkgs.dnscontrol}/bin/dnscontrol check + touch $out + ''; } #// (mapAttrs' (name: value: nameValuePair "packages/${name}" value) self.packages.${system}) // (mapAttrs' (name: value: nameValuePair "nixosConfigurations/${name}" value.config.system.build.toplevel) self.nixosConfigurations);