| 1 | --- |
| 2 | title: Configuration Reference |
| 3 | description: Complete reference for all Portal environment variables, CLI flags, and configuration files. |
| 4 | --- |
| 5 | |
| 6 | # Configuration Reference |
| 7 | |
| 8 | Complete reference for all Portal environment variables, CLI flags, and configuration files. |
| 9 | |
| 10 | ## Relay Server Environment Variables |
| 11 | |
| 12 | The relay server (`relay-server`) reads configuration from environment variables. Each variable corresponds to a CLI flag of the same shape (e.g. `PORTAL_URL` → `--portal-url`). CLI flags take precedence over environment variables when both are set. |
| 13 | |
| 14 | ### Core |
| 15 | |
| 16 | | Variable | Default | Type | Description | |
| 17 | |----------|---------|------|-------------| |
| 18 | | `PORTAL_URL` | `https://localhost:4017` | string | Public base URL of this relay server | |
| 19 | | `IDENTITY_PATH` | `./.portal-certs` | string | Directory path for relay identity, policy state, and TLS materials | |
| 20 | | `API_PORT` | `4017` | int | Admin/API server listen port | |
| 21 | | `SNI_PORT` | `443` | int | TCP SNI router listen port | |
| 22 | | `WIREGUARD_PORT` | `51820` | int | Public and listen UDP port for relay discovery overlay | |
| 23 | |
| 24 | ### Transport |
| 25 | |
| 26 | | Variable | Default | Type | Description | |
| 27 | |----------|---------|------|-------------| |
| 28 | | `MIN_PORT` | `0` | int | Inclusive minimum port for UDP and raw TCP transports (`0` = disabled) | |
| 29 | | `MAX_PORT` | `0` | int | Inclusive maximum port for UDP and raw TCP transports (`0` = disabled) | |
| 30 | | `UDP_ENABLED` | `false` | bool | Enable UDP relay transport; requires a valid `MIN_PORT`/`MAX_PORT` range | |
| 31 | | `TCP_ENABLED` | `false` | bool | Enable raw TCP port transport; requires a valid `MIN_PORT`/`MAX_PORT` range | |
| 32 | |
| 33 | ### Features |
| 34 | |
| 35 | | Variable | Default | Type | Description | |
| 36 | |----------|---------|------|-------------| |
| 37 | | `DISCOVERY` | `false` | bool | Serve relay discovery endpoints and poll discovery peers | |
| 38 | | `BOOTSTRAPS` | `""` | string | Additional bootstrap relay API URLs used for discovery expansion (comma-separated) | |
| 39 | |
| 40 | ### Payments |
| 41 | |
| 42 | | Variable | Default | Type | Description | |
| 43 | |----------|---------|------|-------------| |
| 44 | | `X402_ENABLED` | `false` | bool | Enable relay-owned Sui x402 facilitator endpoints under `/api/x402` for future control-plane payments | |
| 45 | | `X402_TESTNET` | `false` | bool | Use Sui testnet for relay-owned x402 facilitator payments; `false` uses Sui mainnet | |
| 46 | | `X402_PAY_TO` | `""` | string | Sui payment recipient address for relay-owned control-plane x402 resources | |
| 47 | |
| 48 | ### Proxy |
| 49 | |
| 50 | | Variable | Default | Type | Description | |
| 51 | |----------|---------|------|-------------| |
| 52 | | `TRUST_PROXY_HEADERS` | `false` | bool | Trust `X-Forwarded-*` and `X-Real-IP` headers from trusted proxies | |
| 53 | | `TRUSTED_PROXY_CIDRS` | `""` | string | Trusted proxy CIDR allowlist for forwarded headers (comma-separated); defaults to private/loopback ranges when `TRUST_PROXY_HEADERS` is enabled | |
| 54 | |
| 55 | ### TLS |
| 56 | |
| 57 | | Variable | Default | Type | Description | |
| 58 | |----------|---------|------|-------------| |
| 59 | | `ACME_DNS_PROVIDER` | `""` | string | DNS provider for managed DNS-01/A-record sync, ECH HTTPS records, and ENS gasless DNSSEC/TXT automation (`cloudflare` \| `gcloud` \| `hetzner` \| `njalla` \| `route53` \| `vultr`); leave empty to use manual `fullchain.pem`/`privatekey.pem` from `IDENTITY_PATH` | |
| 60 | | `ENS_GASLESS_ENABLED` | `false` | bool | Enable ENS gasless DNS import automation for the managed DNS zone and lease hostnames | |
| 61 | |
| 62 | ### Diagnostics |
| 63 | |
| 64 | | Variable | Default | Type | Description | |
| 65 | |----------|---------|------|-------------| |
| 66 | | `PPROF_ENABLED` | `false` | bool | Enable the relay pprof diagnostics HTTP server | |
| 67 | | `PPROF_ADDR` | `127.0.0.1:6060` | string | pprof listen address when enabled; keep it on loopback unless the port is protected | |
| 68 | |
| 69 | ### Admin |
| 70 | |
| 71 | | Variable | Default | Type | Description | |
| 72 | |----------|---------|------|-------------| |
| 73 | | `ADMIN_TOKEN` | | string | Bearer token source for relay admin and policy APIs; set a long random value for production relays | |
| 74 | |
| 75 | ### Frontend API Service |
| 76 | |
| 77 | The TypeScript API service reads these environment |
| 78 | variables: |
| 79 | |
| 80 | | Variable | Default | Type | Description | |
| 81 | |----------|---------|------|-------------| |
| 82 | | `PORT` | `8081` | int | Frontend API HTTP listen port | |
| 83 | | `PORTAL_API_BASE_URL` | `https://portal:4017` | string | Relay API base URL used to compose frontend-owned state | |
| 84 | | `LANDING_PAGE_ENABLED` | `false` | bool | Default landing page flag when no frontend state has been saved yet | |
| 85 | | `PORTAL_FRONTEND_STATE_PATH` | `""` | string | Optional JSON file path for persisted frontend-owned state; a Compose deployment can store this under `./.portal-certs/frontend-state/state.json` | |
| 86 | | `HEADLESS_SHELL_URL` | `""` | string | Headless Chrome CDP WebSocket URL; leave empty to disable generated thumbnails | |
| 87 | |
| 88 | ### Cloudflare |
| 89 | |
| 90 | | Variable | Default | Type | Description | |
| 91 | |----------|---------|------|-------------| |
| 92 | | `CLOUDFLARE_TOKEN` | | string | Cloudflare DNS API token; required when `ACME_DNS_PROVIDER=cloudflare` | |
| 93 | |
| 94 | ### Google Cloud |
| 95 | |
| 96 | | Variable | Aliases | Default | Type | Description | |
| 97 | |----------|---------|---------|------|-------------| |
| 98 | | `GCP_PROJECT_ID` | `GOOGLE_CLOUD_PROJECT`, `GCLOUD_PROJECT`, `GCE_PROJECT` | | string | Google Cloud project ID for Cloud DNS automation; auto-detected from ADC or GCE metadata when omitted | |
| 99 | | `GCP_MANAGED_ZONE` | `GCP_ZONE`, `GCE_ZONE_ID` | | string | Explicit Google Cloud DNS managed zone name or numeric ID override | |
| 100 | | `GOOGLE_APPLICATION_CREDENTIALS` | | | string | Path to GCP service account key file (standard ADC; used by the GCP client library) | |
| 101 | |
| 102 | ### Hetzner |
| 103 | |
| 104 | | Variable | Aliases | Default | Type | Description | |
| 105 | |----------|---------|---------|------|-------------| |
| 106 | | `HETZNER_API_TOKEN` | `HCLOUD_TOKEN` | | string | Hetzner Cloud API token for DNS automation; required when `ACME_DNS_PROVIDER=hetzner` | |
| 107 | |
| 108 | ### AWS |
| 109 | |
| 110 | | Variable | Aliases | Default | Type | Description | |
| 111 | |----------|---------|---------|------|-------------| |
| 112 | | `AWS_ACCESS_KEY_ID` | | | string | AWS access key ID for Route53 static credentials; uses the default AWS credential chain when omitted | |
| 113 | | `AWS_SECRET_ACCESS_KEY` | | | string | AWS secret access key for Route53 static credentials | |
| 114 | | `AWS_SESSION_TOKEN` | | | string | AWS session token for Route53 temporary credentials | |
| 115 | | `AWS_REGION` | `AWS_DEFAULT_REGION` | `us-east-1` | string | AWS region for Route53 and Route53-backed DNS-01 | |
| 116 | | `AWS_HOSTED_ZONE_ID` | | | string | Explicit Route53 hosted zone ID override | |
| 117 | | `AWS_DNSSEC_KMS_KEY_ARN` | | | string | AWS KMS key ARN used to create a Route53 DNSSEC key-signing key when needed | |
| 118 | |
| 119 | ### Vultr |
| 120 | |
| 121 | | Variable | Default | Type | Description | |
| 122 | |----------|---------|------|-------------| |
| 123 | | `VULTR_API_KEY` | | string | Vultr API key for DNS automation; required when `ACME_DNS_PROVIDER=vultr` | |
| 124 | |
| 125 | ### Njalla |
| 126 | |
| 127 | | Variable | Default | Type | Description | |
| 128 | |----------|---------|------|-------------| |
| 129 | | `NJALLA_TOKEN` | | string | Njalla API token for DNS automation; required when `ACME_DNS_PROVIDER=njalla` | |
| 130 | |
| 131 | --- |
| 132 | |
| 133 | ## Portal Tunnel CLI Flags |
| 134 | |
| 135 | The `portal expose` subcommand accepts the following flags. Flags that read from environment variables are noted in the **Env Var** column. |
| 136 | |
| 137 | ### Connection |
| 138 | |
| 139 | | Flag | Env Var | Type | Default | Description | |
| 140 | |------|---------|------|---------|-------------| |
| 141 | | `--relays` | | string | _(registry)_ | Additional Portal relay server API URLs (comma-separated; scheme omitted defaults to https) | |
| 142 | | `--discovery` | | bool | `true` | Include public registry relays and discover additional relay bootstraps | |
| 143 | | `--multi-hop` | `MULTI_HOP` | string | | Ordered multi-hop relay API URLs, comma-separated | |
| 144 | | `--multi-hop-depth` | `MULTI_HOP_DEPTH` | int | `0` | Automatically select one multi-hop route with this hop count; 0 or 1 disables multi-hop | |
| 145 | | `--max-active-relays` | `MAX_ACTIVE_RELAYS` | int | `3` | Maximum auto-selected relays to keep connected; explicit relays are always included | |
| 146 | | `--ban-mitm` | `BAN_MITM` | bool | `false` | Ban relay when the MITM self-probe detects TLS termination | |
| 147 | |
| 148 | ### Identity |
| 149 | |
| 150 | | Flag | Env Var | Type | Default | Description | |
| 151 | |------|---------|------|---------|-------------| |
| 152 | | `--identity-path` | `IDENTITY_PATH` | string | `identity.json` | Identity JSON file path | |
| 153 | | `--identity-json` | `IDENTITY_JSON` | string | | Identity JSON payload; overrides `--identity-path` contents and is persisted there when both are set | |
| 154 | |
| 155 | ### Lease |
| 156 | |
| 157 | | Flag | Env Var | Type | Default | Description | |
| 158 | |------|---------|------|---------|-------------| |
| 159 | | `--name` | | string | _(auto)_ | Public hostname prefix (single DNS label); auto-generated when omitted | |
| 160 | | `--description` | | string | | Service description metadata | |
| 161 | | `--tags` | | string | | Service tags metadata (comma-separated) | |
| 162 | | `--owner` | | string | | Service owner metadata | |
| 163 | | `--thumbnail` | | string | | Service thumbnail URL metadata | |
| 164 | | `--hide` | | bool | `false` | Hide service from relay listing screens | |
| 165 | | `--x402-pay-to` | | string | | Sui USDC payment recipient address for this tunnel | |
| 166 | | `--x402-testnet` | | bool | `false` | Use Sui testnet for tunnel x402 payments; default is Sui mainnet | |
| 167 | |
| 168 | ### Routing |
| 169 | |
| 170 | | Flag | Env Var | Type | Default | Description | |
| 171 | |------|---------|------|---------|-------------| |
| 172 | | `--http-route` | | string | | HTTP route mapping in `PATH=UPSTREAM [METHOD[,METHOD...]:USDC_AMOUNT]` form; repeat to aggregate multiple local HTTP services behind one public URL; route amounts require `--x402-pay-to` | |
| 173 | |
| 174 | ### Transport |
| 175 | |
| 176 | | Flag | Env Var | Type | Default | Description | |
| 177 | |------|---------|------|---------|-------------| |
| 178 | | `--udp` | `UDP_ENABLED` | bool | `false` | Enable public UDP relay in addition to the default stream path | |
| 179 | | `--udp-addr` | `UDP_ADDR` | string | | Local UDP target address for relayed datagrams (`host:port` or port only); defaults to the target when `--udp` is enabled | |
| 180 | | `--tcp` | `TCP_ENABLED` | bool | `false` | Request a dedicated TCP port on the relay for raw TCP services (no TLS; e.g., Minecraft, game servers) | |
| 181 | |
| 182 | The `portal list` subcommand accepts the following flags: |
| 183 | |
| 184 | | Flag | Type | Default | Description | |
| 185 | |------|------|---------|-------------| |
| 186 | | `--relays` | string | _(registry)_ | Additional Portal relay server API URLs (comma-separated) | |
| 187 | | `--default-relays` | bool | `true` | Include public registry relays | |
| 188 | |
| 189 | --- |
| 190 | |
| 191 | ## Configuration Files |
| 192 | |
| 193 | ### `config.toml` |
| 194 | |
| 195 | `portal agent run` reads the platform default `config.toml` and starts one managed process for all declared tunnels. Relative paths are resolved from the config file directory. The config file must exist before the agent is started. |
| 196 | |
| 197 | Default paths: |
| 198 | |
| 199 | | OS | Config | Default identity | |
| 200 | |----|--------|------------------| |
| 201 | | Linux user | `$XDG_CONFIG_HOME/portal-tunnel/agent/config.toml` or `~/.config/portal-tunnel/agent/config.toml` | `$XDG_DATA_HOME/portal-tunnel/agent/identity.json` or `~/.local/share/portal-tunnel/agent/identity.json` | |
| 202 | | Linux root | `/etc/portal-tunnel/agent/config.toml` | `/var/lib/portal-tunnel/agent/identity.json` | |
| 203 | | macOS user | `~/Library/Application Support/Portal Tunnel/Agent/config.toml` | `~/Library/Application Support/Portal Tunnel/Agent/identity.json` | |
| 204 | | macOS root | `/Library/Application Support/Portal Tunnel/Agent/config.toml` | `/Library/Application Support/Portal Tunnel/Agent/identity.json` | |
| 205 | | Windows | `%ProgramData%\Portal Tunnel\Agent\config.toml` | `%ProgramData%\Portal Tunnel\Agent\identity.json` | |
| 206 | |
| 207 | ```toml |
| 208 | [agent] |
| 209 | control_addr = "127.0.0.1:4018" |
| 210 | service_name = "portal-agent" |
| 211 | |
| 212 | [[tunnels]] |
| 213 | id = "web" |
| 214 | name = "myapp" |
| 215 | target = "127.0.0.1:3000" |
| 216 | relays = ["https://portal.example.com"] |
| 217 | discovery = false |
| 218 | description = "Managed web tunnel" |
| 219 | tags = ["web"] |
| 220 | |
| 221 | [[tunnels]] |
| 222 | id = "api" |
| 223 | name = "myapp" |
| 224 | x402_pay_to = "0x..." |
| 225 | x402_testnet = true |
| 226 | |
| 227 | [[tunnels.http_routes]] |
| 228 | prefix = "/api" |
| 229 | upstream = "http://127.0.0.1:3001" |
| 230 | methods = ["GET"] |
| 231 | amount = "0.01" |
| 232 | |
| 233 | [[tunnels.http_routes]] |
| 234 | prefix = "/" |
| 235 | upstream = "http://127.0.0.1:5173" |
| 236 | ``` |
| 237 | |
| 238 | Agent fields: |
| 239 | |
| 240 | | Field | Default | Description | |
| 241 | |-------|---------|-------------| |
| 242 | | `state_dir` | Platform default state directory | Stores the local control endpoint token and runtime state | |
| 243 | | `control_addr` | `127.0.0.1:4018` | Loopback-only local control API address | |
| 244 | | `service_name` | `portal-agent` | OS service name | |
| 245 | | `allowed_wallets` | empty | Wallet addresses allowed to read local agent status through wallet auth; empty allows any wallet on the loopback auth endpoint | |
| 246 | |
| 247 | The local agent dashboard and mutating control API calls use the bearer token in |
| 248 | the agent state directory. Wallet-authenticated agent requests are read-only and |
| 249 | can only read `/agent/status`. |
| 250 | |
| 251 | Tunnel fields mirror `portal expose` flags: |
| 252 | |
| 253 | | Field | Type | Description | |
| 254 | |-------|------|-------------| |
| 255 | | `id` | string | Stable tunnel ID used by the agent dashboard | |
| 256 | | `target` | string | Local TCP target, equivalent to the `portal expose <target>` argument | |
| 257 | | `http_routes` | table array | HTTP route mappings; cannot be combined with `target` or `udp` | |
| 258 | | `relays` | string array | Explicit relay API URLs | |
| 259 | | `discovery` | bool | Include registry and relay discovery expansion | |
| 260 | | `multi_hop` | string array | Ordered multi-hop relay path | |
| 261 | | `multi_hop_depth` | int | Automatically select one multi-hop route with this depth | |
| 262 | | `identity_path` | string | Tunnel identity JSON file path. When omitted, one tunnel uses the platform default `identity.json`; multiple tunnels use `<state-dir>/<tunnel-id>/identity.json` | |
| 263 | | `identity_json` | string | Identity JSON payload; overrides `identity_path` contents and is persisted there when both are set | |
| 264 | | `udp`, `udp_addr`, `tcp` | bool/string | UDP and raw TCP relay options | |
| 265 | | `description`, `tags`, `owner`, `thumbnail`, `hide` | mixed | Lease metadata shown by relays | |
| 266 | | `x402_pay_to` | string | Tunnel-owned Sui USDC x402 payment recipient for paid HTTP routes | |
| 267 | | `x402_testnet` | bool | Use Sui testnet for tunnel-owned x402 paid routes; omitted or `false` uses Sui mainnet | |
| 268 | | `http_routes[].amount` | string | Optional Sui USDC x402 amount, such as `0.01`, for one HTTP route prefix; requires `x402_pay_to` | |
| 269 | | `http_routes[].methods` | string array | Optional HTTP methods that require payment on that route; empty means every method | |
| 270 | |
| 271 | When any routed HTTP entry has `amount`, the tunnel also serves |
| 272 | `/x402/client.js` and `/x402/prepare` on the public tunnel origin. Browser |
| 273 | frontends served by another route in the same tunnel can import |
| 274 | `/x402/client.js` and use `x402Fetch()` to run the same Sui wallet payment flow |
| 275 | as the standalone payment app. Native clients use `/x402/prepare` directly and |
| 276 | send the signed payload as `X-PAYMENT`. Payment is still enforced by the tunnel |
| 277 | on the paid route prefix. Tunnel paid routes default to Sui mainnet and use Sui |
| 278 | testnet when `x402_testnet = true`. |
| 279 | |
| 280 | For a task-oriented walkthrough, see [Portal Agent](/portal-agent). |
| 281 | |
| 282 | ### `identity.json` |
| 283 | |
| 284 | Stores the secp256k1 identity used to sign tunnel sessions and relay descriptors. `portal expose` treats `--identity-path` as a direct JSON file path. `relay-server` treats `IDENTITY_PATH` as a state directory and stores this file at `IDENTITY_PATH/identity.json`. |
| 285 | |
| 286 | | Field | Type | Description | |
| 287 | |-------|------|-------------| |
| 288 | | `name` | string | Human-readable label for this identity | |
| 289 | | `address` | string | Derived EVM address used for SIWE and identity ownership | |
| 290 | | `public_key` | string | Compressed secp256k1 public key hex | |
| 291 | | `private_key` | string | secp256k1 private key hex; keep secret | |
| 292 | | `mnemonic` | string | BIP-39 mnemonic used to derive the secp256k1 identity key; keep secret | |
| 293 | | `derivation_path` | string | EVM derivation path for `mnemonic`; defaults to `m/44'/60'/0'/0/0` | |
| 294 | | `wireguard_public_key` | string | Relay-only WireGuard overlay public key when discovery is enabled | |
| 295 | | `wireguard_private_key` | string | Relay-only WireGuard overlay private key when discovery is enabled | |
| 296 | | `encrypted_client_hello_seed` | string | Relay-only HKDF salt for deriving the ECH HPKE private key; generated automatically when missing; keep secret | |
| 297 | |
| 298 | When `mnemonic` is present, Portal derives the private key at `derivation_path` |
| 299 | and preserves the mnemonic form when rewriting `identity.json`. The same |
| 300 | identity file or state directory can be reused across restarts to keep a stable |
| 301 | address. |
| 302 | |
| 303 | ### `policy.json` |
| 304 | |
| 305 | Persists relay policy state. Managed automatically by the relay on write; do not edit manually while the server is running. |
| 306 | |
| 307 | Relay policy settings are stored at `IDENTITY_PATH/policy.json`. |
| 308 | |
| 309 | --- |
| 310 | |
| 311 | ## ACME DNS Provider Configuration |
| 312 | |
| 313 | Set `ACME_DNS_PROVIDER` (or `--acme-dns-provider`) to one of the values below to enable DNS-backed automation. Portal uses the same provider for DNS-01 challenges, managed A records, ECH HTTPS records, and optional ENS gasless DNS records. |
| 314 | |
| 315 | When this variable is empty the relay server falls back to manually supplied `fullchain.pem` and `privatekey.pem` files in `IDENTITY_PATH`. |
| 316 | |
| 317 | For ENS gasless behavior and wallet authentication details, see [Wallet and ENS](/wallet-and-ens). |
| 318 | |
| 319 | ### Cloudflare (`cloudflare`) |
| 320 | |
| 321 | | Variable | Required | Description | |
| 322 | |----------|----------|-------------| |
| 323 | | `CLOUDFLARE_TOKEN` | Yes | Cloudflare DNS API token with `Zone:DNS:Edit` permission | |
| 324 | |
| 325 | ### Google Cloud DNS (`gcloud`) |
| 326 | |
| 327 | | Variable | Required | Description | |
| 328 | |----------|----------|-------------| |
| 329 | | `GCP_PROJECT_ID` | No | Google Cloud project ID; auto-detected from ADC or GCE metadata when omitted | |
| 330 | | `GCP_MANAGED_ZONE` | No | Cloud DNS managed zone name or numeric ID; inferred from the portal domain when omitted | |
| 331 | | `GOOGLE_APPLICATION_CREDENTIALS` | No | Path to a service account key JSON file; uses Application Default Credentials when omitted | |
| 332 | |
| 333 | ### AWS Route53 (`route53`) |
| 334 | |
| 335 | | Variable | Required | Description | |
| 336 | |----------|----------|-------------| |
| 337 | | `AWS_ACCESS_KEY_ID` | No | Access key ID; uses the default AWS credential chain (instance profile, env, `~/.aws/credentials`) when omitted | |
| 338 | | `AWS_SECRET_ACCESS_KEY` | No | Secret access key; required when `AWS_ACCESS_KEY_ID` is set | |
| 339 | | `AWS_SESSION_TOKEN` | No | Session token for temporary credentials | |
| 340 | | `AWS_REGION` | No | AWS region; defaults to `us-east-1` | |
| 341 | | `AWS_HOSTED_ZONE_ID` | No | Route53 hosted zone ID; inferred from the portal domain when omitted | |
| 342 | | `AWS_DNSSEC_KMS_KEY_ARN` | No | KMS key ARN for DNSSEC key-signing key creation | |
| 343 | |
| 344 | ### Hetzner DNS (`hetzner`) |
| 345 | |
| 346 | | Variable | Required | Description | |
| 347 | |----------|----------|-------------| |
| 348 | | `HETZNER_API_TOKEN` | Yes | Hetzner Cloud API token with DNS zone and RRSet write access | |
| 349 | |
| 350 | Note: Hetzner DNS does not support provider-side DNSSEC signing, so `ACME_DNS_PROVIDER=hetzner` supports ACME, A records, and HTTPS/ECH records, but not ENS gasless DNSSEC automation. |
| 351 | |
| 352 | ### Njalla DNS (`njalla`) |
| 353 | |
| 354 | | Variable | Required | Description | |
| 355 | |----------|----------|-------------| |
| 356 | | `NJALLA_TOKEN` | Yes | Njalla API token with DNS record write access | |
| 357 | |
| 358 | Note: Njalla supports managed ACME, A records, TXT records, and HTTPS/ECH records. Portal does not automate Njalla DNSSEC signing, so `ACME_DNS_PROVIDER=njalla` does not support ENS gasless DNSSEC automation. |
| 359 | |
| 360 | ### Vultr DNS (`vultr`) |
| 361 | |
| 362 | | Variable | Required | Description | |
| 363 | |----------|----------|-------------| |
| 364 | | `VULTR_API_KEY` | Yes | Vultr API key with DNS domain, record, and DNSSEC write access | |