Add DDNS using cloudflare (replacing netgear DDNS)
diff --git a/flake.nix b/flake.nix
index caa0571..e6b6c6f 100644
--- a/flake.nix
+++ b/flake.nix
@@ -48,6 +48,7 @@
               ./modules/cache.nix
               ./modules/caddy.nix
               ./modules/clamav.nix
+              ./modules/cloudflare-ddns.nix
               ./modules/dmarc.nix
               ./modules/dnsmasq.nix
               ./modules/doas.nix
diff --git a/modules/cloudflare-ddns.nix b/modules/cloudflare-ddns.nix
new file mode 100644
index 0000000..3abd8a2
--- /dev/null
+++ b/modules/cloudflare-ddns.nix
@@ -0,0 +1,18 @@
+{ config, ... }: {
+  services.cloudflare-dyndns = {
+    enable = true;
+    proxied = false;
+    ipv4 = true;
+    ipv6 = false;
+    domains = [ "d1.a1.crawling.us" ];
+    apiTokenFile = config.sops.secrets.cloudflare_ddns__api_token.path;
+  };
+
+  sops.secrets.cloudflare_ddns__api_token = {
+    mode = "0600";
+    owner = config.users.users.root.name;
+    group = config.users.users.root.group;
+    sopsFile = ../secrets/cloudflare.env.bin;
+    format = "binary";
+  };
+}
diff --git a/secrets/cloudflare.env.bin b/secrets/cloudflare.env.bin
new file mode 100644
index 0000000..9c98cce
--- /dev/null
+++ b/secrets/cloudflare.env.bin
@@ -0,0 +1,28 @@
+{
+	"data": "ENC[AES256_GCM,data:yAvKBvjHqUyF10o5QqI4u7TJfbNicHQ7gc5bz+RNjL0cJr9Y3W1xOlzSVzU2VfSAsFUVP2Ug92uZrrgBeIs=,iv:ccB2mUP/3TnvsmaJP37VFSLPPDjw5DHZq2p1jQNIBN0=,tag:+AJBgtIR9x0WMFy1hEILHg==,type:str]",
+	"sops": {
+		"kms": null,
+		"gcp_kms": null,
+		"azure_kv": null,
+		"hc_vault": null,
+		"age": [
+			{
+				"recipient": "age15mv77dpnh5762gk5rsw2u79uza4tg8cu6r3nlwjudlzmdqqck3ss6mg9dy",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpL3E1Wmg3azVQa2lkeHZ3\nRzdROUpuc2FHd3kwVnBucFppYndUNGhBVGgwCjFlNXA4b3g1M0huSW9IRldzWklm\nZGpWQVhxYmZMd1FOMnhuR1prNk9mK2sKLS0tIDRUb1QzQzZGaEdVdDMwMExQckhT\nZFBhRWFaSzhOcE5ldlVCUitHbndNTDgK5S9Man2K208LE35zX3jaaepWSGttIdp/\neWP7tTfDDbw6bl43u6IjlQ8hqgvfSYTNnl5WHjijdU74HjeKzyyi9g==\n-----END AGE ENCRYPTED FILE-----\n"
+			},
+			{
+				"recipient": "age1m7k864feyuezllp2hj4edkccn36rthrvfw969j6f0l3c0mhh5emsnfx6pd",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIY1pibVA5eEhRdnpJL3dH\nUTZEYStiYXhMb1FQN2RkQitYcTUwSzkxVG4wCjRoeFJ2dnEyeDRZb1RwT1VEajBy\nbzRIZ25JWlhvUTFoTksyWHg0OXhmeWcKLS0tIDFoYVltNnVqNFl1TXpCM0I3a2xC\nRmY4dzI4RW44bFRaQmZqbnhxN0dqMGsK9Dt9LqO4M2YWmBfRwB1jowN18BlKMs7k\n0YStD3vflu7BAdwUyt6S+ZdKjuynfcBpC86D/q17IURCo3fTEmpcxw==\n-----END AGE ENCRYPTED FILE-----\n"
+			},
+			{
+				"recipient": "age1fxxnmkeuqhhct93c43pwkzhuzzq8857s5hye6pgfpku70kjn4ecqtamfqr",
+				"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaSXU1TURlMVRVS0paMlZo\nbTJiWllRT0c1V1BzOTBCQ0JubzFtc2NFb1NBCkN5Qy8rS3hoNzQvbmNPQjdWd2NI\nYUZvdXdYYkVqLzlMbHFIR0xGNjhncVEKLS0tIGV4Q2pKZzRLWngyRVNBN2dZbmxi\nc1kyVG1sd1hrdUYxZkFWMTNVQ01vZU0K9GemfZkMEfz6Sa+FmAX8Dl8LsDKpNsJL\n/sD4ZHu/EwVIxqsi1Roctx6lSOd4ZQNs1o7dSjSEzzwBH5pSUMMVow==\n-----END AGE ENCRYPTED FILE-----\n"
+			}
+		],
+		"lastmodified": "2023-08-20T22:16:06Z",
+		"mac": "ENC[AES256_GCM,data:jyRs+sCKlBWYebAfarkQS/J4CB5unoTLcQNmdB3QORkoiX1+GNysJo8YSqAgIt9V3BkTEaCfyb83MndNchzSDdwR00pp9H7tL+r5wU/fqOc8efKm4K/WbMzr48eBy30ybyPDjTNvyxk2cr5KHaT53c/9VUtaF1dabKsFgfGwMd4=,iv:WS23Oo1+sjRXZmWT7yG7NfpkkcDseQS2W/U1LVqJudI=,tag:rXR6efgFW0IYCC9awOQvMA==,type:str]",
+		"pgp": null,
+		"unencrypted_suffix": "_unencrypted",
+		"version": "3.7.3"
+	}
+}
\ No newline at end of file