From c85db031dc11322218f228b4277825c356562302 Mon Sep 17 00:00:00 2001 From: Mohammad Rafiq Date: Wed, 9 Jul 2025 02:09:19 +0800 Subject: [PATCH] feat(nix): add dynamic DNS module using godns Adds support for updating Cloudflare DNS records using godns. --- nix/manifest.nix | 7 +++++ nix/modules/server/ddns.nix | 59 +++++++++++++++++++++++++++++++++++++ secrets/keys.yaml | 17 +++++++++++ 3 files changed, 83 insertions(+) create mode 100644 nix/modules/server/ddns.nix create mode 100644 secrets/keys.yaml diff --git a/nix/manifest.nix b/nix/manifest.nix index fd98d46..8f600de 100644 --- a/nix/manifest.nix +++ b/nix/manifest.nix @@ -31,6 +31,13 @@ root.drive = "/dev/disk/by-id/nvme-eui.002538d221b47b01"; }; extraCfg.server = { + ddns = { + enable = true; + domains = [ + "aenyrathia.wiki" + "slayment.com" + ]; + }; databases = { mongodb.enable = true; mysql.enable = true; diff --git a/nix/modules/server/ddns.nix b/nix/modules/server/ddns.nix new file mode 100644 index 0000000..40a03ea --- /dev/null +++ b/nix/modules/server/ddns.nix @@ -0,0 +1,59 @@ +{ lib, config, ... }: +let + inherit (lib.modules) mkIf; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) enum str listOf; + inherit (lib.lists) unique; + inherit (builtins) map; + inherit (config.flake.paths) secrets; +in +{ + flake.modules.nixos.default = + { config, ... }: + let + cfg = config.server.ddns; + mkDomain = domain_name: { + inherit domain_name; + sub_domains = [ + "@" + "*" + ]; + }; + in + { + options.server.ddns = { + enable = mkEnableOption ""; + type = mkOption { + type = enum [ "godns" ]; + default = "godns"; + }; + domains = mkOption { + type = listOf str; + default = [ ]; + }; + }; + + config = mkIf cfg.enable { + sops.secrets."keys/cloudflare".sopsFile = secrets + "/keys.yaml"; + services.godns = { + enable = if (cfg.type == "godns") then true else false; + loadCredential = [ "cf_token:${config.sops.secrets."keys/cloudflare".path}" ]; + settings = { + provider = "Cloudflare"; + login_token_file = "$CREDENTIALS_DIRECTORY/cf_token"; + # Sanitize the list of domains with unique so we can add to it with every service. + domains = map mkDomain (unique cfg.domains); + resolver = "1.1.1.1"; + ip_urls = [ + "https://wtfismyip.com/text" + "https://api.ipify.org" + "https://myip.biturl.top" + "https://api-ipv4.ip.sb/ip" + ]; + ip_type = "IPv4"; + interval = 300; + }; + }; + }; + }; +} diff --git a/secrets/keys.yaml b/secrets/keys.yaml new file mode 100644 index 0000000..7b3f094 --- /dev/null +++ b/secrets/keys.yaml @@ -0,0 +1,17 @@ +keys: + cloudflare: ENC[AES256_GCM,data:p2IISOuU/ShoifW5OFY/6Bi6PI0iIiQoBfnV512f2z84U9QS/KEhzA==,iv:5AkwtNAK8mD2DbvXCtTeNeIrpF/GIsSyOYxy8G4Jsqo=,tag:u2xJcRBR5WTMWdzupx4tbQ==,type:str] +sops: + age: + - recipient: age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmcTdPWURrK2w1QUZubVZo + VUMrcFFQU0UxdDU3OG9PdEUxcGs2bzZNcmg0Cm03cUlPZkRMK0ZXOTllV3BtZWFp + QXBPRWtOd0xjZC9BdGdmWnVoVGpHR1UKLS0tIEpaVXlSNkhpMVZnTFZWTFVEWTgv + T3VyZXZnaGZaMVBnVko2Tlc2S3FpdDQKRiHCOtkHKugfquQfYkk4o9SMtZlo1CqZ + 3i9+9Z516KS1+ERTklBUzZDBRZISY0c2nluO+tn71wnKAMIxetKryQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-07-08T18:05:51Z" + mac: ENC[AES256_GCM,data:YkQqkKw+OEKFtORp+WDwclazCk166JndSstoiJYbpdAKLxvEQLdScaGin7j0fIoeTCY1CytzAHAUt8iraZeHscIkPdz/3WGPOa23dt56ZEd+rK/OL+XIuOCsbz08+yVWgJWeeEeMZ8IinwA46kVVYI3+p4FxDBDXBvhl9x7+CG4=,iv:YHmM2mk2fKwefydYV29eEMaXlyHVKwyDZAHCnbnKb3Y=,tag:Ksb8N/1pnzDGpyGj8Z0fhg==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2