add DNS zone by octodns

Signed-off-by: Kiara Grouwstra <kiara@procolix.eu>
This commit is contained in:
Kiara Grouwstra 2025-11-06 10:01:55 +01:00
parent 98b39012f0
commit 01277c4ea7
Signed by: kiara
SSH key fingerprint: SHA256:COspvLoLJ5WC5rFb9ZDe5urVCkK4LJZOsjfF4duRJFU
7 changed files with 256 additions and 1 deletions

View file

@ -0,0 +1,10 @@
{
targetMachines = [
"node"
];
pathToRoot = builtins.path {
path = ../../..;
name = "root";
};
pathFromRoot = "/deployment/check/octodns";
}

View file

@ -0,0 +1,21 @@
{
pkgs,
inputs,
sources,
}:
pkgs.testers.runNixOSTest {
imports = [
../common/nixosTest.nix
./nixosTest.nix
];
_module.args = {
inherit inputs sources;
modulesPath = "${builtins.toString pkgs.path}/nixos/modules";
};
inherit (import ./constants.nix)
targetMachines
pathToRoot
pathFromRoot
;
}

View file

@ -0,0 +1,39 @@
{
lib,
pkgs,
sources,
...
}:
let
inherit (pkgs.callPackage ../../utils.nix { }) evalOption;
domain = "thatsru.de";
inherit
(evalOption "octodns-zone"
(pkgs.callPackage ../../run {
inherit sources;
}).octodns-zone
{
inherit domain;
provider = "hetzner";
secretFiles.token = builtins.toString (
pkgs.writeText "hetzner-token" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
);
zone = {
NS = [ "ns.test.com." ];
A = [ "203.0.113.2" ];
};
}
)
validate
;
in
{
_class = "nixosTest";
name = "octodns";
extraTestScript = ''
deployer.succeed("""
${lib.getExe validate}
""")
'';
}

View file

@ -48,6 +48,10 @@
netbox-ips = import ./check/netbox-ips {
inherit inputs sources system;
};
octodns = import ./check/octodns {
inherit pkgs inputs sources;
};
};
};
}

View file

@ -15,7 +15,13 @@ let
str
submodule
;
inherit (pkgs.callPackage ../utils.nix { }) withPackages withEnv tfApply;
inherit (pkgs.callPackage ../utils.nix { })
mapKeys
withPackages
withEnv
withSecrets
tfApply
;
writeConfig =
{
system,
@ -630,4 +636,163 @@ in
};
});
};
octodns-zone = mkOption {
description = "Manage DNS records.";
type = submodule (
octodns-zone:
let
dns = pkgs.callPackage sources."dns.nix" { };
in
{
options = {
domain = mkOption {
type = types.str;
example = "example.tld";
};
secretFiles = mkOption {
type = types.attrsOf types.str;
description = "The files from which to read the secrets to use with the provider.";
example = {
token = "/path/to/token";
};
};
zone = mkOption {
# FIXME: error: The option `zones."domain.tld".__toString' is read-only, but it's set multiple times.
# type = dns.lib.types.zone;
description = "The zone data to use.";
example = {
NS = [ "ns.example.tld." ];
A = [ "12.34.56.78" ];
};
};
provider = mkOption {
type = types.str;
description = "The OctoDNS provider to use, see <https://octodns.readthedocs.io/en/latest/#providers>.";
example = "desec";
};
providers = mkOption {
type = types.attrsOf (
types.submodule {
options = {
class = mkOption {
type = types.str;
};
secrets = mkOption {
type = types.listOf types.str;
};
};
}
);
default = {
desec = {
class = "octodns_desec.DesecProvider";
secrets = [ "token" ];
};
hetzner = {
class = "octodns_hetzner.HetznerProvider";
secrets = [ "token" ];
};
};
};
package = mkOption {
type = types.package;
example = "The package of the OctoDNS provider to deploy to, see <https://search.nixos.org/packages?channel=unstable&query=octodns-providers>.";
default = pkgs.octodns-providers.${octodns-zone.config.provider};
};
packages = mkOption {
type = types.listOf types.package;
default = [
# https://github.com/NixOS/nixpkgs/issues/429294
(
(pkgs.callPackage "${sources.nixpkgs-unstable}/pkgs/by-name/oc/octodns/package.nix" { })
.withProviders
(_: [
pkgs.octodns-providers.bind
octodns-zone.config.package
])
)
];
};
conf = mkOption {
type = types.path;
default =
let
inherit (octodns-zone.config)
domain
zone
providers
provider
;
in
pkgs.writers.writeYAML "octodns-config.yaml" {
zones."${domain}." = {
sources = [ "config" ];
targets = [ provider ];
};
providers = {
"${provider}" =
let
inherit (providers."${provider}") class secrets;
in
{
inherit class;
}
// (lib.genAttrs secrets (k: "env/${lib.toUpper "${provider}_${k}"}"));
config = {
file_extension = "";
class = "octodns_bind.ZoneFileSource";
directory = pkgs.linkFarm "zones" {
"${domain}" = dns.util.writeZone domain (
# lib.recursiveUpdate
{
# fake SOA record to satisfy octodns
SOA = {
serial = 1970010100;
nameServer = "ns1.example.com";
adminEmail = "admin@example.com";
};
}
// zone
);
};
};
};
};
};
validate = mkOption {
type = types.package;
default =
let
inherit (octodns-zone.config)
packages
conf
provider
secretFiles
;
in
pkgs.writers.writeBashBin "octodns-validate.sh" (withPackages packages) ''
env ${withSecrets (mapKeys (k: lib.toUpper "${provider}_${k}") secretFiles)} \
octodns-validate --config ${conf} --all
'';
};
sync = mkOption {
type = types.package;
default =
let
inherit (octodns-zone.config)
packages
conf
provider
secretFiles
;
in
pkgs.writers.writeBashBin "octodns-sync.sh" (withPackages packages) ''
env ${withSecrets (mapKeys (k: lib.toUpper "${provider}_${k}") secretFiles)} \
octodns-sync --config ${conf} --doit
'';
};
};
}
);
};
}

View file

@ -64,6 +64,9 @@ rec {
withEnv = environment: toString (lib.mapAttrsToList (k: v: "${k}=\"${toBash v}\"") environment);
withSecrets =
environment: toString (lib.mapAttrsToList (k: v: "${k}=\"$(cat ${v})\"") (filterNull environment));
tfApply =
{
directory,

View file

@ -57,6 +57,19 @@
"url": "https://api.github.com/repos/nix-community/disko/tarball/v1.12.0",
"hash": "0wbx518d2x54yn4xh98cgm65wvj0gpy6nia6ra7ns4j63hx14fkq"
},
"dns.nix": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "nix-community",
"repo": "dns.nix"
},
"branch": "master",
"submodules": false,
"revision": "f3cb11f642d4fa6224e2b1ddfd2c3ba42e9ffea2",
"url": "https://github.com/nix-community/dns.nix/archive/f3cb11f642d4fa6224e2b1ddfd2c3ba42e9ffea2.tar.gz",
"hash": "1qjdgrn4sxa9n9wws4jg75dy1vnw761dglja8gdhvj8j2yxc27dd"
},
"flake-inputs": {
"type": "GitRelease",
"repository": {