NixDnsTemplate

Authoritative DNS + step-ca + ACME (DNS-01, provider-agnostic) + ddns-updater on NixOS. Emits config matching the host.dns.* option shape from nixos/modules/services/dns.nix.

public sealed class NixDnsTemplate : NixHostTemplate

1. Properties

1.1. AcmeContactEmail

ACME registration contact email. Required at emit time.

public string AcmeContactEmail { get; set; }

1.2. AcmeStaging

Use Let’s Encrypt staging endpoint. Default true (safe).

public bool AcmeStaging { get; set; }

1.3. AuthorizedKeys

Authorized SSH public keys (one per line).

public IReadOnlyList<string> AuthorizedKeys { get; set; }

1.4. CustomerDomain

Authoritative zone served by coredns. Required.

public string CustomerDomain { get; set; }

1.5. DiskDevice

Install-target block device (e.g. /dev/sda, /dev/vda).

public string DiskDevice { get; set; }

1.6. DnsProvider

DNS / ACME provider config (lego + ddns-updater). Required.

public DnsProviderOptions DnsProvider { get; set; }

1.7. DomainProvider

Dyndns provider (non-secret knobs) for ddns-updater. Independent of DnsProvider (works with zero ACME). Null ⇒ no dyndns block emitted. Secret rides in DomainProviderSecretPlain.

public DomainProviderOptions DomainProvider { get; set; }

1.8. DomainProviderSecretPlain

Materialised dyndns secret (decoded from the DomainProvider-tagged User at build time). Lab-grade plaintext in the nix store (mail-relay posture). Empty when no dyndns.

public string DomainProviderSecretPlain { get; set; }

1.9. ExtraARecords

Extra A records beyond Records. Key = subdomain (e.g. "mail"), value = LAN IP. Emitted into the same coredns attrset as Records. Used for non-machine A records (e.g. mail.<domain> pointing at the mail VM IP even when the machine is named something other than "Mail"). Empty = no extra records.

public IReadOnlyDictionary<string, string> ExtraARecords { get; set; }

1.10. Gateway

Default gateway for static IPv4. Auto-derived from StaticIPv4 (.1) when null.

public string Gateway { get; set; }

1.11. Hostname

Target hostname.

public MachineName Hostname { get; set; }

1.12. MailTcpForwards

Plain-TCP (L4) mail forwards on the DNS VM (single ingress). Key = nix attr name (also the entryPoint name), e.g. "smtp"/"submission"/"imaps". Maps to one TCP entryPoint + tcp router + tcp service per entry with TLS passthrough. 25 → PMG, 587/993 → mail VM. Empty = no TCP forwarding emitted (reverseProxy still drives 80/443 via ReverseProxyRoutes).

public IReadOnlyDictionary<string, MailTcpForward> MailTcpForwards { get; set; }

1.13. MxRecords

Explicit MX RRs served under the zone. One {Owner} IN MX {Priority} {Target}. line per entry in the coredns zone file. Empty = no explicit MX (dns.nix still emits a default auto-derived MX from the records map for backwards compat).

public IReadOnlyList<MxRecord> MxRecords { get; set; }

1.14. Nameservers

DNS servers used with static IPv4. Default falls back to gateway.

public IReadOnlyList<string> Nameservers { get; set; }

1.15. Password

Initial password applied to root + admin user (users.users.<name>.initialPassword). Defaults to the central NETSetup admin password so SSH key auth and console login both work with the same value across Windows/Nix/PMG provisioning.

public string Password { get; set; }

1.16. PublicHostnames

FQDNs to issue LE certs for (cert SANs). Typically {key}.{CustomerDomain} for each public-service record. Empty ⇒ dns.nix falls back to mail+pmg.

public IReadOnlyList<string> PublicHostnames { get; set; }

1.17. RecommendedCpuCores

Recommended runtime vCPU count. Default 2 (mail/dns/generic). Nextcloud overrides to 4 because php-fpm + nix-install closure builds saturate fewer cores.

public virtual uint RecommendedCpuCores { get; }

1.18. RecommendedDiskGib

Recommended VM disk size in GiB. Nextcloud needs ~256 (closure build space); dns/mail/pmg fit comfortably in 32. Default 32; concrete templates override.

public virtual int RecommendedDiskGib { get; }

1.19. RecommendedMemoryGib

Recommended runtime RAM in GiB. Default 8. Nextcloud and IPFS keep the same value explicitly (php-fpm / the ipfs daemon need the headroom at runtime as well).

public virtual int RecommendedMemoryGib { get; }

1.20. RecommendedSwapMib

Steady-state swapfile size in MiB written to /var/swapfile. Default 8192 (8 GiB). Tight RAM (Mail/Dns at 2 GiB) makes runtime OOM likely under load — swap is slow but keeps services alive. Nextcloud overrides to 16 GiB given larger working set.

public virtual int RecommendedSwapMib { get; }

1.21. Records

A records served under the zone. Key = subdomain (e.g. "mail", "nextcloud", "pmg", "mx"). Value = LAN IP, or empty string if unknown at provision time (DHCP). dns.nix filters empty values; ddns-updater pushes the runtime public IP.

public IReadOnlyDictionary<string, string> Records { get; set; }

1.22. ReverseProxyRoutes

Traefik routes on the DNS VM. Key = router/service name (must be a valid nix attr name). Empty = traefik disabled.

public IReadOnlyDictionary<string, ReverseProxyRoute> ReverseProxyRoutes { get; set; }

1.23. ReverseZones

Reverse DNS zones served by coredns. PTR records auto-derived in dns.nix by matching Records IPs against each zone CIDR (/24 only). Empty = no PTR served.

public IReadOnlyList<ReverseDnsZone> ReverseZones { get; set; }

1.24. StaticIPv4

Static IPv4 to assign to the primary NIC (e.g. "192.168.1.183"). Null/empty → DHCP.

public string StaticIPv4 { get; set; }

1.25. StaticIPv4Prefix

Static IPv4 prefix length when StaticIPv4 is set. Default /24.

public int StaticIPv4Prefix { get; set; }

1.26. TimeZone

IANA time zone.

public string TimeZone { get; set; }

1.27. UserName

Default admin user.

public string UserName { get; set; }

2. Methods

2.1. GenerateDefaultNix()

Host default.nix content. Concrete per template.

public override string GenerateDefaultNix()

Returns: string

2.2. GenerateFlakeNix()

flake.nix for this host.

public virtual string GenerateFlakeNix()

Returns: string

2.3. GenerateHardwareNix()

hardware.nix for this host.

public virtual string GenerateHardwareNix()

Returns: string

2.4. GenerateStaticNetworkBlock()

Returns the network nix snippet — ALWAYS emits host.system.network.dhcp.enable so individual templates must NOT repeat it (NixOS module eval treats duplicate attribute definitions within the same {} body as an "already defined" error, even when one is mkDefault and the other mkForce — priority modifiers only resolve cross-module conflicts, not intra-set duplicates). Emits the static-IPv4 block additionally when StaticIPv4 is set.

protected string GenerateStaticNetworkBlock()

Returns: string

2.5. GetRequiredSecrets(NETSetupConfig)

Extra sops secrets this template requires in the per-VM secrets.yaml (beyond the always-emitted luks password). Base returns none; concrete templates (e.g. NixIpfsTemplate) override to contribute nested/multiline entries.

public virtual IReadOnlyList<NixSecretEntry> GetRequiredSecrets(NETSetupConfig config)
Table 1. Parameters
Name Type Description

config

NETSetupConfig

Returns: IReadOnlyList<NixSecretEntry>