summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flake.nix17
-rw-r--r--module.nix97
-rw-r--r--package.nix29
3 files changed, 143 insertions, 0 deletions
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..03c9d0d
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,17 @@
+{
+ description = "ddnnss - dynamic domain no-name system service";
+
+ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
+
+ outputs = { self, nixpkgs }:
+ let
+ forAll = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ];
+ in
+ {
+ nixosModules.default = import ./module.nix;
+
+ packages = forAll (system:
+ let pkgs = import nixpkgs { inherit system; };
+ in { default = pkgs.callPackage ./package.nix { }; });
+ };
+}
diff --git a/module.nix b/module.nix
new file mode 100644
index 0000000..b227085
--- /dev/null
+++ b/module.nix
@@ -0,0 +1,97 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+
+let
+ inherit (lib)
+ getExe
+ literalExpression
+ mkEnableOption
+ mkIf
+ mkOption
+ types
+ ;
+
+ cfg = config.services.ddnnss;
+
+ ddnnss = pkgs.callPackage ./package.nix { };
+
+ configFile = pkgs.writeText "ddnnss.json" (builtins.toJSON cfg.settings);
+in
+{
+ options.services.ddnnss = {
+ enable = mkEnableOption "ddnnss";
+
+ interval = mkOption {
+ type = types.str;
+ default = "5min";
+ description = ''
+ How often to run an update cycle.
+ '';
+ };
+
+ settings = mkOption {
+ type = types.attrs;
+ description = ''
+ The ddnnss configuration.
+ Any key values expand environment variables.
+ '';
+ example = literalExpression ''
+ {
+ records = [{
+ zone = "rnrd.eu";
+ name = "silly";
+ type = "AAAA";
+ provider = "bunny-rnrd";
+ source = "icanhazip";
+ }];
+ providers.bunny-rnrd = {
+ kind = "bunny";
+ keyFile = "$CREDENTIALS_DIRECTORY/bunny-dns";
+ };
+ sources.icanhazip = { kind = "icanhazip"; };
+ }
+ '';
+ };
+
+ credentials = mkOption {
+ type = types.attrsOf types.path;
+ default = { };
+ description = ''
+ Secrets exposed to ddnnss during the cycle, as systemd credentials.
+ '';
+ example = literalExpression ''
+ { bunny-dns = config.age.secrets.bunny-dns.path; }
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.ddnnss = {
+ description = "ddnnss dynamic dns update cycle";
+ after = [ "network-online.target" ];
+ wants = [ "network-online.target" ];
+
+ serviceConfig = {
+ Type = "oneshot";
+ DynamicUser = true;
+ LoadCredential = lib.mapAttrsToList
+ (name: path: "${name}:${path}") cfg.credentials;
+ ExecStart = "${getExe ddnnss} -config ${configFile}";
+ };
+ };
+
+ systemd.timers.ddnnss = {
+ wantedBy = [ "timers.target" ];
+ timerConfig = {
+ # wait 2 minutes from the start, with 30 second jitter.
+ OnBootSec = "2min";
+ RandomizedDelaySec = "30s";
+ OnUnitActiveSec = cfg.interval;
+ };
+ };
+ };
+}
diff --git a/package.nix b/package.nix
new file mode 100644
index 0000000..2ab0d95
--- /dev/null
+++ b/package.nix
@@ -0,0 +1,29 @@
+{
+ lib,
+ buildGoModule,
+}:
+
+buildGoModule {
+ pname = "ddnnss";
+ version = "1.0";
+
+ src = lib.fileset.toSource {
+ root = ./.;
+ fileset = lib.fileset.unions [
+ ./go.mod
+ ./main.go
+ ./config.go
+ ./source
+ ./provider
+ ];
+ };
+
+ # stdlib only.
+ vendorHash = null;
+
+ meta = {
+ description = "dynamic domain no-name system service";
+ homepage = "https://git.rnrd.eu/ddnnss";
+ mainProgram = "ddnnss";
+ };
+}