diff --git a/self-host/advanced/config-file.mdx b/self-host/advanced/config-file.mdx
index 9c2aead..a1ac9ae 100644
--- a/self-host/advanced/config-file.mdx
+++ b/self-host/advanced/config-file.mdx
@@ -511,6 +511,18 @@ This section contains the complete reference for all configuration options in `c
**Default**: `/var/dynamic/router_config.yml`
+
+ Additional fully-qualified domains that are always included in the list sent to the SNI proxy, alongside domains discovered from resources.
+
+ **Example**: `["static.example.com"]`
+
+ **Default**: `[]`
+
+
+ Useful for domains that need to be routable through the SNI proxy but aren't tied to a resource that Pangolin would otherwise discover automatically.
+
+
+
Supported site types for Traefik configuration.
@@ -907,6 +919,16 @@ This section contains the complete reference for all configuration options in `c
**Default**: `false`
+
+
+ Whether to hide the virtual API keys UI.
+
+ **Default**: `false`
+
+
+ When enabled, virtual API key management is hidden from the dashboard.
+
+
diff --git a/self-host/advanced/private-config-file.mdx b/self-host/advanced/private-config-file.mdx
index 807af32..5f13ff5 100644
--- a/self-host/advanced/private-config-file.mdx
+++ b/self-host/advanced/private-config-file.mdx
@@ -161,6 +161,142 @@ This section contains the complete reference for all configuration options in `p
+### DNS Server Configuration
+
+
+ Configuration for Pangolin's built-in authoritative DNS nameserver. This lets Pangolin answer DNS queries directly for domains delegated to it (via CNAME or NS delegation), issue ACME DNS-01 challenge responses, and resolve site tunnel subnet addresses.
+
+
+
+ Enables the authoritative DNS server. When `false` or omitted, no DNS listener is started.
+
+ ```yaml
+ dns:
+ enabled: true
+ ```
+
+
+
+ UDP port the authoritative DNS server listens on.
+
+ ```yaml
+ dns:
+ listen_port: 53
+ ```
+
+
+
+ The FQDN Pangolin advertises as itself when acting as a nameserver. Used as the `mname` in SOA responses and included in the NS record set returned for zones it is authoritative for. This is the hostname you point your domain's nameservers at when using NS-based domain delegation (e.g. `ns1.pangolin-ns.net`).
+
+ ```yaml
+ dns:
+ nameserver_name: "ns1.pangolin-ns.net"
+ ```
+
+
+
+ The domain suffix used for single-domain CNAME delegation. When an org adds a domain using the CNAME delegation type, Pangolin generates `{domainId}.{cname_extension}` and `_acme-challenge.{domainId}.{cname_extension}` targets to point your records at.
+
+ ```yaml
+ dns:
+ cname_extension: "cname.pangolin.net"
+ ```
+
+
+
+ Suffix used to resolve a site's WireGuard tunnel subnet address by DNS. A query for `{newtId}.{site_extension}` resolves to the tunnel subnet IP of the site running the Newt agent with that ID. This is used for site-to-cloud networking.
+
+ ```yaml
+ dns:
+ site_extension: "site.pangolin.net"
+ ```
+
+
+
+ Additional CNAME suffixes (besides `cname_extension`) that are treated the same way. Useful when Pangolin should respond to more than one CNAME delegation domain, such as for white-label/multi-brand deployments.
+
+ ```yaml
+ dns:
+ cname_alternate_extensions:
+ - "cname.example.com"
+ ```
+
+
+
+ Additional nameserver hostnames appended after `nameserver_name` in the NS record set Pangolin returns for a zone, and in the NS records shown when using NS-based domain delegation (e.g. `ns2.pangolin-ns.net`, `ns3.pangolin-ns.net`).
+
+ ```yaml
+ dns:
+ alternate_nameservers:
+ - "ns2.pangolin-ns.net"
+ - "ns3.pangolin-ns.net"
+ ```
+
+
+
+ Per-source-IP rate limiting for DNS queries. Queries exceeding these limits are refused.
+
+ ```yaml
+ dns:
+ rate_limit:
+ enabled: true
+ window_ms: 60000
+ max_requests: 1200
+ max_requests_per_query_type: 600
+ ```
+
+
+
+ Enables DNS query rate limiting.
+
+
+
+ The time window, in milliseconds, over which query counts are measured.
+
+
+
+ Maximum total DNS queries allowed per source IP within `window_ms`.
+
+
+
+ Maximum queries allowed per source IP, per DNS record type (A, TXT, NS, etc.), within `window_ms`.
+
+
+
+
+
+ Hardcoded DNS answers served by the authoritative DNS server, checked before database-backed lookups. Useful for fixed entries such as domain verification TXT records.
+
+ ```yaml
+ dns:
+ static_records:
+ - domain: "example.com"
+ type: "TXT"
+ value: "v=spf1 include:_spf.example.com ~all"
+ ttl: 300
+ ```
+
+
+
+ The domain name to match (case-insensitive).
+
+
+
+ The DNS record type. One of `TXT`, `CNAME`, `A`, or `NS`.
+
+
+
+ The value returned for this record.
+
+
+
+ Time-to-live, in seconds, for the returned record.
+
+
+
+
+
+
### Gerbil Tunnel Configuration
@@ -205,7 +341,7 @@ This section contains the complete reference for all configuration options in `p
- Use Pangolin DNS servers for client connections instead of external DNS servers for DNS delegation and CNAME setups. Used for clustering Pangolin nodes. REQUIRES EXTERNAL COMPONENTS. PLEASE CONTACT SUPPORT TO OBTAIN ACCESS BEFORE ENABLING.
+ Allow creating domains using CNAME and NS.
```yaml
flags:
@@ -215,6 +351,146 @@ This section contains the complete reference for all configuration options in `p
+### ACME Certificate Configuration
+
+
+ Configuration for Pangolin's self-hosted ACME client, which issues and renews TLS certificates directly using DNS-01 challenges served by Pangolin's own [authoritative DNS server](#dns-server-configuration), as an alternative to relying on Traefik's built-in ACME resolver.
+
+
+
+ Controls who is responsible for obtaining and renewing TLS certificates.
+
+ Possible values:
+ - `traefik`: (default) Traefik's built-in ACME resolver handles certificate issuance and renewal itself.
+ - `pangolin`: Pangolin issues and manages certificates itself via its self-hosted ACME client, using DNS-01 challenges. Requires `dns.enabled` and `acme.enable_acme_client` to both be `true`. ENSURE ONLY ONE NODE IN A CLUSTER HAS THE `acme.enable_acme_client` FLAG ENABLED, OTHERWISE MULTIPLE NODES WILL TRY TO ISSUE CERTIFICATES SIMULTANEOUSLY.
+
+ ```yaml
+ acme:
+ cert_mode: "pangolin"
+ ```
+
+
+
+ Enable the self-hosted ACME client and its certificate issuance/renewal jobs. Must be `true`, along with `cert_mode: "pangolin"`, for the certificate manager to start.
+
+ ```yaml
+ acme:
+ enable_acme_client: true
+ ```
+
+
+
+ Email address registered with the ACME account, used by the CA for expiry and policy notices.
+
+ ```yaml
+ acme:
+ contact_email: "admin@example.com"
+ ```
+
+
+
+ The ACME server directory URL Pangolin's client talks to.
+
+ ```yaml
+ acme:
+ acme_directory_url: "https://acme-staging-v02.api.letsencrypt.org/directory"
+ ```
+
+
+
+ Filesystem path where the ACME account's private key is stored. Generated automatically on first run if it doesn't exist.
+
+ ```yaml
+ acme:
+ acme_account_key_path: "./config/account.key"
+ ```
+
+
+
+ How long, in milliseconds, a DNS-01 challenge TXT record is considered valid and served by the authoritative DNS server before expiring.
+
+ ```yaml
+ acme:
+ challenge_ttl_ms: 300000
+ ```
+
+
+
+ How often, in milliseconds, Pangolin checks for certificates approaching expiry and renews them.
+
+ ```yaml
+ acme:
+ renewal_check_interval_ms: 3600000
+ ```
+
+
+
+ How often, in milliseconds, Pangolin checks for newly-needed certificates and issues them. Set much lower than `renewal_check_interval_ms` since new certificates are user-facing and blocking.
+
+ ```yaml
+ acme:
+ new_cert_check_interval_ms: 5000
+ ```
+
+
+
+ Shared rate limit on outbound calls Pangolin's client makes directly to the ACME server (create order, get authorizations, verify challenge, finalize, get certificate). Kept under Let's Encrypt's ~20 req/s limit.
+
+ ```yaml
+ acme:
+ acme_requests_per_second: 15
+ ```
+
+
+
+ How often, in milliseconds, Pangolin checks pending (not-yet-verified) domains' DNS records against live DNS to flip them to verified once the records are in place.
+
+ ```yaml
+ acme:
+ dns_check_interval_ms: 60000
+ ```
+
+
+
+ How often, in milliseconds, Pangolin runs a periodic pass re-checking already-verified domains, to catch removing or changing their DNS records after the fact.
+
+ ```yaml
+ acme:
+ domain_reverification_interval_ms: 3600000
+ ```
+
+
+
+ Minimum age, in milliseconds, a verified domain's last check must have before it becomes eligible for reverification. A given domain is reverified at most roughly this often, not on every reverification pass.
+
+ ```yaml
+ acme:
+ domain_reverification_window_ms: 259200000
+ ```
+
+
+
+ Maximum number of verified domains reverified per reverification pass, to bound database and DNS load per tick.
+
+ ```yaml
+ acme:
+ domain_reverification_batch_size: 20
+ ```
+
+
+
+ Upstream public DNS resolvers used to perform live lookups against real DNS (not Pangolin's own authoritative server) when validating or reverifying domain records. Resolvers are rotated across on each attempt so a single resolver's cache or propagation lag doesn't wrongly fail a check.
+
+ ```yaml
+ acme:
+ dns_resolvers:
+ - "8.8.8.8"
+ - "1.1.1.1"
+ ```
+
+
+
+
### Branding Configuration
Please refer to the [branding configuration documentation](/manage/branding).
\ No newline at end of file