diff --git a/hbd/server/configio.py b/hbd/server/configio.py
index 1787259..6924c84 100644
--- a/hbd/server/configio.py
+++ b/hbd/server/configio.py
@@ -88,6 +88,12 @@ def apply_structured_section(data, section: str, values: dict) -> None:
for key in _SERVER_KEYS:
if key in values:
data[key] = values[key]
+ elif section == "dns":
+ for key in _DNS_KEYS:
+ if key in values:
+ data[key] = values[key]
+ else:
+ data.pop(key, None)
elif section == "users":
data["users"] = values
elif section == "hosts":
diff --git a/hbd/server/http.py b/hbd/server/http.py
index 06b27f9..7c33fa2 100644
--- a/hbd/server/http.py
+++ b/hbd/server/http.py
@@ -1304,9 +1304,15 @@ async def start(
attrs.pop("client_secret", None)
data["oauth"] = new_oauth
- for section in ("notification_channels", "dns"):
- if section in payload:
- configio_mod.apply_yaml_section(data, section, payload[section])
+ if "notification_channels" in payload:
+ configio_mod.apply_yaml_section(data, "notification_channels", payload["notification_channels"])
+
+ if "dns" in payload:
+ dns_payload = payload["dns"]
+ if isinstance(dns_payload, str):
+ configio_mod.apply_yaml_section(data, "dns", dns_payload)
+ else:
+ configio_mod.apply_structured_section(data, "dns", dns_payload)
if "thresholds" in payload:
tc = payload["thresholds"]
diff --git a/hbd/server/settings.py b/hbd/server/settings.py
index 1b8d90f..4ebc51f 100644
--- a/hbd/server/settings.py
+++ b/hbd/server/settings.py
@@ -398,10 +398,18 @@ def get_settings_sections(config: dict, threshold_checker=None) -> list:
{
"id": "dns",
"title": "Dynamic DNS",
- "description": "nsupdate-based DNS registration — edit raw YAML.",
- "section_mode": "yaml",
+ "description": "nsupdate-based DNS registration via nsupdate(8).",
+ "section_mode": "form",
"api_section": "dns",
- "fields": [],
+ "fields": [
+ field("nsupdate_bin", "nsupdate binary", "path",
+ "Path to the nsupdate binary.", editable=True),
+ field("rndc_key", "RNDC key file", "path",
+ "Path to the rndc key file used to authenticate DNS updates.", editable=True),
+ field("dyndomains", "Dynamic domains", "list",
+ "Domains updated via nsupdate when a host with dyndns: true reports in.",
+ editable=True),
+ ],
},
{
"id": "users",
diff --git a/hbd/server/templates/settings.html b/hbd/server/templates/settings.html
index 2c056be..0033919 100644
--- a/hbd/server/templates/settings.html
+++ b/hbd/server/templates/settings.html
@@ -820,6 +820,11 @@
+ {% elif f.type == 'list' %}
+
{% else %}
s.trim()).filter(Boolean);
} else {
_staged[apiSection][key] = el.value;
}