Compare commits
1 commit
bfb923e841
...
217bacb958
Author | SHA1 | Date | |
---|---|---|---|
217bacb958 |
8 changed files with 240 additions and 232 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -409,12 +409,6 @@ version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "humantime"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -755,9 +749,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "1.0.3"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96"
|
checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
|
@ -1183,7 +1177,6 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"clap-verbosity-flag",
|
"clap-verbosity-flag",
|
||||||
"http",
|
"http",
|
||||||
"humantime",
|
|
||||||
"insta",
|
"insta",
|
||||||
"miette",
|
"miette",
|
||||||
"ring",
|
"ring",
|
||||||
|
|
|
@ -23,7 +23,6 @@ clap-verbosity-flag = { version = "3", default-features = false, features = [
|
||||||
"tracing",
|
"tracing",
|
||||||
] }
|
] }
|
||||||
http = "1"
|
http = "1"
|
||||||
humantime = "2.2.0"
|
|
||||||
miette = { version = "7", features = ["fancy"] }
|
miette = { version = "7", features = ["fancy"] }
|
||||||
ring = { version = "0.17", features = ["std"] }
|
ring = { version = "0.17", features = ["std"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
|
@ -3,18 +3,10 @@
|
||||||
imports = [
|
imports = [
|
||||||
inputs.treefmt-nix.flakeModule
|
inputs.treefmt-nix.flakeModule
|
||||||
./package.nix
|
./package.nix
|
||||||
|
./module.nix
|
||||||
./tests.nix
|
./tests.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
flake.nixosModules =
|
|
||||||
let
|
|
||||||
webnsupdate = ../module.nix;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
default = webnsupdate;
|
|
||||||
inherit webnsupdate;
|
|
||||||
};
|
|
||||||
|
|
||||||
perSystem =
|
perSystem =
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
|
|
222
flake-modules/module.nix
Normal file
222
flake-modules/module.nix
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
let
|
||||||
|
module =
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.services.webnsupdate;
|
||||||
|
inherit (lib)
|
||||||
|
mkOption
|
||||||
|
mkEnableOption
|
||||||
|
mkPackageOption
|
||||||
|
types
|
||||||
|
;
|
||||||
|
format = pkgs.formats.json { };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# imports = [
|
||||||
|
# (lib.mkRenamedOptionModule
|
||||||
|
# [ "services" "webnsupdate" "passwordFile" ]
|
||||||
|
# [ "services" "webnsupdate" "settings" "password_file" ]
|
||||||
|
# )
|
||||||
|
# (lib.mkRenamedOptionModule
|
||||||
|
# [ "services" "webnsupdate" "keyFile" ]
|
||||||
|
# [ "services" "webnsupdate" "settings" "key_file" ]
|
||||||
|
# )
|
||||||
|
# (lib.mkRemovedOptionModule [ "services" "webnsupdate" "allowedIPVersion" ] ''
|
||||||
|
# This option was replaced with 'services.webnsupdate.settings.ip_type' which defaults to Both.
|
||||||
|
# '')
|
||||||
|
# (lib.mkRemovedOptionModule [ "services" "webnsupdate" "bindIp" ] ''
|
||||||
|
# This option was replaced with 'services.webnsupdate.settings.address' which defaults to 127.0.0.1:5353.
|
||||||
|
# '')
|
||||||
|
# (lib.mkRemovedOptionModule [ "services" "webnsupdate" "bindPort" ] ''
|
||||||
|
# This option was replaced with 'services.webnsupdate.settings.address' which defaults to 127.0.0.1:5353.
|
||||||
|
# '')
|
||||||
|
# (lib.mkRemovedOptionModule [ "services" "webnsupdate" "records" ] ''
|
||||||
|
# This option was replaced with 'services.webnsupdate.settings.records' which defaults to [].
|
||||||
|
# '')
|
||||||
|
# (lib.mkRemovedOptionModule [ "services" "webnsupdate" "recordsFile" ] ''
|
||||||
|
# This option was replaced with 'services.webnsupdate.settings.records' which defaults to [].
|
||||||
|
# '')
|
||||||
|
# (lib.mkRemovedOptionModule [ "services" "webnsupdate" "ttl" ] ''
|
||||||
|
# This option was replaced with 'services.webnsupdate.settings.ttl' which defaults to 600s.
|
||||||
|
# '')
|
||||||
|
# ];
|
||||||
|
|
||||||
|
options.services.webnsupdate = mkOption {
|
||||||
|
description = "An HTTP server for nsupdate.";
|
||||||
|
default = { };
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkEnableOption "webnsupdate";
|
||||||
|
extraArgs = mkOption {
|
||||||
|
description = ''
|
||||||
|
Extra arguments to be passed to the webnsupdate server command.
|
||||||
|
'';
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "--ip-source" ];
|
||||||
|
};
|
||||||
|
package = mkPackageOption pkgs "webnsupdate" { };
|
||||||
|
settings = mkOption {
|
||||||
|
description = "The webnsupdate JSON configuration";
|
||||||
|
default = { };
|
||||||
|
type = types.submodule {
|
||||||
|
freeformType = format.type;
|
||||||
|
options = {
|
||||||
|
address = mkOption {
|
||||||
|
description = ''
|
||||||
|
IP address and port to bind to.
|
||||||
|
|
||||||
|
Setting it to anything other than localhost is very
|
||||||
|
insecure as `webnsupdate` only supports plain HTTP and
|
||||||
|
should always be behind a reverse proxy.
|
||||||
|
'';
|
||||||
|
type = types.str;
|
||||||
|
default = "127.0.0.1:5353";
|
||||||
|
example = "[::1]:5353";
|
||||||
|
};
|
||||||
|
ip_type = mkOption {
|
||||||
|
description = ''The allowed IP versions to accept updates from.'';
|
||||||
|
type = types.enum [
|
||||||
|
"Both"
|
||||||
|
"Ipv4Only"
|
||||||
|
"Ipv6Only"
|
||||||
|
];
|
||||||
|
default = "Both";
|
||||||
|
example = "Ipv4Only";
|
||||||
|
};
|
||||||
|
password_file = mkOption {
|
||||||
|
description = ''
|
||||||
|
The file where the password is stored.
|
||||||
|
|
||||||
|
This file can be created by running `webnsupdate mkpasswd $USERNAME $PASSWORD`.
|
||||||
|
'';
|
||||||
|
type = types.path;
|
||||||
|
example = "/secrets/webnsupdate.pass";
|
||||||
|
};
|
||||||
|
key_file = mkOption {
|
||||||
|
description = ''
|
||||||
|
The TSIG key that `nsupdate` should use.
|
||||||
|
|
||||||
|
This file will be passed to `nsupdate` through the `-k` option, so look
|
||||||
|
at `man 8 nsupdate` for information on the key's format.
|
||||||
|
'';
|
||||||
|
type = types.path;
|
||||||
|
example = "/secrets/webnsupdate.key";
|
||||||
|
};
|
||||||
|
ttl = mkOption {
|
||||||
|
description = "The TTL that should be set on the zone records created by `nsupdate`.";
|
||||||
|
default = {
|
||||||
|
secs = 600;
|
||||||
|
};
|
||||||
|
example = {
|
||||||
|
secs = 600;
|
||||||
|
nanos = 50000;
|
||||||
|
};
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
secs = mkOption {
|
||||||
|
description = "The TTL (in seconds) that should be set on the zone records created by `nsupdate`.";
|
||||||
|
example = 3600;
|
||||||
|
};
|
||||||
|
nanos = mkOption {
|
||||||
|
description = "The TTL (in nanoseconds) that should be set on the zone records created by `nsupdate`.";
|
||||||
|
default = 0;
|
||||||
|
example = 50000;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
records = mkOption {
|
||||||
|
description = ''
|
||||||
|
The fqdn of records that should be updated.
|
||||||
|
|
||||||
|
Empty lines will be ignored, but whitespace will not be.
|
||||||
|
'';
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [
|
||||||
|
"example.com."
|
||||||
|
"example.org."
|
||||||
|
"ci.example.org."
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
user = mkOption {
|
||||||
|
description = "The user to run as.";
|
||||||
|
type = types.str;
|
||||||
|
default = "named";
|
||||||
|
};
|
||||||
|
group = mkOption {
|
||||||
|
description = "The group to run as.";
|
||||||
|
type = types.str;
|
||||||
|
default = "named";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config =
|
||||||
|
let
|
||||||
|
configFile = format.generate "webnsupdate.json" cfg.settings;
|
||||||
|
args = lib.strings.escapeShellArgs ([ "--config=${configFile}" ] ++ cfg.extraArgs);
|
||||||
|
cmd = "${lib.getExe cfg.package} ${args}";
|
||||||
|
in
|
||||||
|
lib.mkIf cfg.enable {
|
||||||
|
# FIXME: re-enable once I stop using the patched version of bind
|
||||||
|
# warnings =
|
||||||
|
# lib.optional (!config.services.bind.enable) "`webnsupdate` is expected to be used alongside `bind`. This is an unsupported configuration.";
|
||||||
|
|
||||||
|
systemd.services.webnsupdate = {
|
||||||
|
description = "Web interface for nsupdate.";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [
|
||||||
|
"network.target"
|
||||||
|
"bind.service"
|
||||||
|
];
|
||||||
|
preStart = "${lib.getExe cfg.package} verify ${configFile}";
|
||||||
|
path = [ pkgs.dig ];
|
||||||
|
startLimitIntervalSec = 60;
|
||||||
|
environment.DATA_DIR = "%S/webnsupdate";
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = [ cmd ];
|
||||||
|
Type = "exec";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "10s";
|
||||||
|
# User and group
|
||||||
|
User = cfg.user;
|
||||||
|
Group = cfg.group;
|
||||||
|
# Runtime directory and mode
|
||||||
|
RuntimeDirectory = "webnsupdate";
|
||||||
|
RuntimeDirectoryMode = "0750";
|
||||||
|
# Cache directory and mode
|
||||||
|
CacheDirectory = "webnsupdate";
|
||||||
|
CacheDirectoryMode = "0750";
|
||||||
|
# Logs directory and mode
|
||||||
|
LogsDirectory = "webnsupdate";
|
||||||
|
LogsDirectoryMode = "0750";
|
||||||
|
# State directory and mode
|
||||||
|
StateDirectory = "webnsupdate";
|
||||||
|
StateDirectoryMode = "0750";
|
||||||
|
# New file permissions
|
||||||
|
UMask = "0027";
|
||||||
|
# Security
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
ProtectHome = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
flake.nixosModules = {
|
||||||
|
default = module;
|
||||||
|
webnsupdate = module;
|
||||||
|
};
|
||||||
|
}
|
18
flake.lock
generated
18
flake.lock
generated
|
@ -2,11 +2,11 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"crane": {
|
"crane": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1742317686,
|
"lastModified": 1741481578,
|
||||||
"narHash": "sha256-ScJYnUykEDhYeCepoAWBbZWx2fpQ8ottyvOyGry7HqE=",
|
"narHash": "sha256-JBTSyJFQdO3V8cgcL08VaBUByEU6P5kXbTJN6R0PFQo=",
|
||||||
"owner": "ipetkov",
|
"owner": "ipetkov",
|
||||||
"repo": "crane",
|
"repo": "crane",
|
||||||
"rev": "66cb0013f9a99d710b167ad13cbd8cc4e64f2ddb",
|
"rev": "bb1c9567c43e4434f54e9481eb4b8e8e0d50f0b5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -37,11 +37,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1742069588,
|
"lastModified": 1741851582,
|
||||||
"narHash": "sha256-C7jVfohcGzdZRF6DO+ybyG/sqpo1h6bZi9T56sxLy+k=",
|
"narHash": "sha256-cPfs8qMccim2RBgtKGF+x9IBCduRvd/N5F4nYpU0TVE=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "c80f6a7e10b39afcc1894e02ef785b1ad0b0d7e5",
|
"rev": "6607cf789e541e7873d40d3a8f7815ea92204f32",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -82,11 +82,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1742303424,
|
"lastModified": 1739829690,
|
||||||
"narHash": "sha256-2R7cGdcA2npQQcIWu2cTlU63veTzwVZe78BliIuJT00=",
|
"narHash": "sha256-mL1szCeIsjh6Khn3nH2cYtwO5YXG6gBiTw1A30iGeDU=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "treefmt-nix",
|
"repo": "treefmt-nix",
|
||||||
"rev": "b3b938ab8ba2e8a0ce9ee9b30ccfa5e903ae5753",
|
"rev": "3d0579f5cc93436052d94b73925b48973a104204",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
162
module.nix
162
module.nix
|
@ -1,162 +0,0 @@
|
||||||
{ lib, pkgs, ... }@args:
|
|
||||||
let
|
|
||||||
cfg = args.config.services.webnsupdate;
|
|
||||||
inherit (lib)
|
|
||||||
mkOption
|
|
||||||
mkEnableOption
|
|
||||||
mkPackageOption
|
|
||||||
types
|
|
||||||
;
|
|
||||||
format = pkgs.formats.json { };
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.services.webnsupdate = mkOption {
|
|
||||||
description = "An HTTP server for nsupdate.";
|
|
||||||
default = { };
|
|
||||||
type = types.submodule {
|
|
||||||
options = {
|
|
||||||
enable = mkEnableOption "webnsupdate";
|
|
||||||
extraArgs = mkOption {
|
|
||||||
description = ''
|
|
||||||
Extra arguments to be passed to the webnsupdate server command.
|
|
||||||
'';
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
example = [ "--ip-source" ];
|
|
||||||
};
|
|
||||||
package = mkPackageOption pkgs "webnsupdate" { };
|
|
||||||
settings = mkOption {
|
|
||||||
description = "The webnsupdate JSON configuration";
|
|
||||||
default = { };
|
|
||||||
type = types.submodule {
|
|
||||||
freeformType = format.type;
|
|
||||||
options = {
|
|
||||||
address = mkOption {
|
|
||||||
description = ''
|
|
||||||
IP address and port to bind to.
|
|
||||||
|
|
||||||
Setting it to anything other than localhost is very
|
|
||||||
insecure as `webnsupdate` only supports plain HTTP and
|
|
||||||
should always be behind a reverse proxy.
|
|
||||||
'';
|
|
||||||
type = types.str;
|
|
||||||
default = "127.0.0.1:5353";
|
|
||||||
example = "[::1]:5353";
|
|
||||||
};
|
|
||||||
ip_type = mkOption {
|
|
||||||
description = ''The allowed IP versions to accept updates from.'';
|
|
||||||
type = types.enum [
|
|
||||||
"Both"
|
|
||||||
"Ipv4Only"
|
|
||||||
"Ipv6Only"
|
|
||||||
];
|
|
||||||
default = "Both";
|
|
||||||
example = "Ipv4Only";
|
|
||||||
};
|
|
||||||
password_file = mkOption {
|
|
||||||
description = ''
|
|
||||||
The file where the password is stored.
|
|
||||||
|
|
||||||
This file can be created by running `webnsupdate mkpasswd $USERNAME $PASSWORD`.
|
|
||||||
'';
|
|
||||||
type = types.path;
|
|
||||||
example = "/secrets/webnsupdate.pass";
|
|
||||||
};
|
|
||||||
key_file = mkOption {
|
|
||||||
description = ''
|
|
||||||
The TSIG key that `nsupdate` should use.
|
|
||||||
|
|
||||||
This file will be passed to `nsupdate` through the `-k` option, so look
|
|
||||||
at `man 8 nsupdate` for information on the key's format.
|
|
||||||
'';
|
|
||||||
type = types.path;
|
|
||||||
example = "/secrets/webnsupdate.key";
|
|
||||||
};
|
|
||||||
ttl = mkOption {
|
|
||||||
description = "The TTL that should be set on the zone records created by `nsupdate`.";
|
|
||||||
default = "10m";
|
|
||||||
example = "60s";
|
|
||||||
type = types.str;
|
|
||||||
};
|
|
||||||
records = mkOption {
|
|
||||||
description = ''
|
|
||||||
The fqdn of records that should be updated.
|
|
||||||
|
|
||||||
Empty lines will be ignored, but whitespace will not be.
|
|
||||||
'';
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
example = [
|
|
||||||
"example.com."
|
|
||||||
"example.org."
|
|
||||||
"ci.example.org."
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
user = mkOption {
|
|
||||||
description = "The user to run as.";
|
|
||||||
type = types.str;
|
|
||||||
default = "named";
|
|
||||||
};
|
|
||||||
group = mkOption {
|
|
||||||
description = "The group to run as.";
|
|
||||||
type = types.str;
|
|
||||||
default = "named";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config =
|
|
||||||
let
|
|
||||||
configFile = format.generate "webnsupdate.json" cfg.settings;
|
|
||||||
args = lib.strings.escapeShellArgs ([ "--config=${configFile}" ] ++ cfg.extraArgs);
|
|
||||||
cmd = "${lib.getExe cfg.package} ${args}";
|
|
||||||
in
|
|
||||||
lib.mkIf cfg.enable {
|
|
||||||
# FIXME: re-enable once I stop using the patched version of bind
|
|
||||||
# warnings =
|
|
||||||
# lib.optional (!config.services.bind.enable) "`webnsupdate` is expected to be used alongside `bind`. This is an unsupported configuration.";
|
|
||||||
|
|
||||||
systemd.services.webnsupdate = {
|
|
||||||
description = "Web interface for nsupdate.";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [
|
|
||||||
"network.target"
|
|
||||||
"bind.service"
|
|
||||||
];
|
|
||||||
preStart = "${lib.getExe cfg.package} verify ${configFile}";
|
|
||||||
path = [ pkgs.dig ];
|
|
||||||
startLimitIntervalSec = 60;
|
|
||||||
environment.DATA_DIR = "%S/webnsupdate";
|
|
||||||
serviceConfig = {
|
|
||||||
ExecStart = [ cmd ];
|
|
||||||
Type = "exec";
|
|
||||||
Restart = "on-failure";
|
|
||||||
RestartSec = "10s";
|
|
||||||
# User and group
|
|
||||||
User = cfg.user;
|
|
||||||
Group = cfg.group;
|
|
||||||
# Runtime directory and mode
|
|
||||||
RuntimeDirectory = "webnsupdate";
|
|
||||||
RuntimeDirectoryMode = "0750";
|
|
||||||
# Cache directory and mode
|
|
||||||
CacheDirectory = "webnsupdate";
|
|
||||||
CacheDirectoryMode = "0750";
|
|
||||||
# Logs directory and mode
|
|
||||||
LogsDirectory = "webnsupdate";
|
|
||||||
LogsDirectoryMode = "0750";
|
|
||||||
# State directory and mode
|
|
||||||
StateDirectory = "webnsupdate";
|
|
||||||
StateDirectoryMode = "0750";
|
|
||||||
# New file permissions
|
|
||||||
UMask = "0027";
|
|
||||||
# Security
|
|
||||||
NoNewPrivileges = true;
|
|
||||||
ProtectHome = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -2,6 +2,7 @@ use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use axum_client_ip::SecureClientIpSource;
|
use axum_client_ip::SecureClientIpSource;
|
||||||
|
@ -74,12 +75,8 @@ pub struct Password {
|
||||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct Records {
|
pub struct Records {
|
||||||
/// Time To Live (in seconds) to set on the DNS records
|
/// Time To Live (in seconds) to set on the DNS records
|
||||||
#[serde(
|
#[serde(default = "default_ttl")]
|
||||||
default = "default_ttl",
|
pub ttl: Duration,
|
||||||
serialize_with = "humantime_ser",
|
|
||||||
deserialize_with = "humantime_de"
|
|
||||||
)]
|
|
||||||
pub ttl: humantime::Duration,
|
|
||||||
|
|
||||||
/// List of domain names for which to update the IP when an update is requested
|
/// List of domain names for which to update the IP when an update is requested
|
||||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
|
@ -127,10 +124,6 @@ pub struct Config {
|
||||||
/// Records Configuration
|
/// Records Configuration
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub records: Records,
|
pub records: Records,
|
||||||
|
|
||||||
/// The config schema (used for lsp completions)
|
|
||||||
#[serde(default, rename = "$schema", skip_serializing)]
|
|
||||||
pub _schema: serde::de::IgnoredAny,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
@ -186,8 +179,8 @@ pub struct Invalid {
|
||||||
|
|
||||||
// --- Default Values (sadly serde doesn't have a way to specify a constant as a default value) ---
|
// --- Default Values (sadly serde doesn't have a way to specify a constant as a default value) ---
|
||||||
|
|
||||||
fn default_ttl() -> humantime::Duration {
|
fn default_ttl() -> Duration {
|
||||||
super::DEFAULT_TTL.into()
|
super::DEFAULT_TTL
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_salt() -> Box<str> {
|
fn default_salt() -> Box<str> {
|
||||||
|
@ -206,35 +199,6 @@ fn default_ip_type() -> IpType {
|
||||||
IpType::Both
|
IpType::Both
|
||||||
}
|
}
|
||||||
|
|
||||||
fn humantime_de<'de, D>(de: D) -> Result<humantime::Duration, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
struct Visitor;
|
|
||||||
impl serde::de::Visitor<'_> for Visitor {
|
|
||||||
type Value = humantime::Duration;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(formatter, "a duration (e.g. 5s)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error,
|
|
||||||
{
|
|
||||||
v.parse().map_err(E::custom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
de.deserialize_str(Visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn humantime_ser<S>(duration: &humantime::Duration, ser: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: serde::Serializer,
|
|
||||||
{
|
|
||||||
ser.serialize_str(&duration.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_values_config_snapshot() {
|
fn default_values_config_snapshot() {
|
||||||
let config: Config = serde_json::from_str("{}").unwrap();
|
let config: Config = serde_json::from_str("{}").unwrap();
|
||||||
|
|
|
@ -175,7 +175,7 @@ impl AppState<'static> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let state = AppState {
|
let state = AppState {
|
||||||
ttl: **ttl,
|
ttl: *ttl,
|
||||||
records,
|
records,
|
||||||
// Load keyfile
|
// Load keyfile
|
||||||
key_file: key_file
|
key_file: key_file
|
||||||
|
|
Loading…
Add table
Reference in a new issue