PORTAL v2

Configuration Reference

Complete reference for all Portal environment variables, CLI flags, and configuration files.

Relay Server Environment Variables

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.

Core

VariableDefaultTypeDescription
PORTAL_URLhttps://localhost:4017stringPublic base URL of this relay server
IDENTITY_PATH./.portal-certsstringDirectory path for relay identity, admin state, and TLS materials
API_PORT4017intAdmin/API server listen port
SNI_PORT443intTCP SNI router listen port
WIREGUARD_PORT51820intPublic and listen UDP port for relay discovery overlay

Transport

VariableDefaultTypeDescription
MIN_PORT0intInclusive minimum port for UDP and raw TCP transports (0 = disabled)
MAX_PORT0intInclusive maximum port for UDP and raw TCP transports (0 = disabled)
UDP_ENABLEDfalseboolEnable UDP relay transport; requires a valid MIN_PORT/MAX_PORT range
TCP_ENABLEDfalseboolEnable raw TCP port transport; requires a valid MIN_PORT/MAX_PORT range

Features

VariableDefaultTypeDescription
LANDING_PAGE_ENABLEDfalseboolEnable the landing page by default when no admin setting has been saved yet
DISCOVERYfalseboolServe relay discovery endpoints and poll discovery peers
BOOTSTRAPS""stringAdditional bootstrap relay API URLs used for discovery expansion (comma-separated)

Proxy

VariableDefaultTypeDescription
TRUST_PROXY_HEADERSfalseboolTrust X-Forwarded-* and X-Real-IP headers from trusted proxies
TRUSTED_PROXY_CIDRS""stringTrusted proxy CIDR allowlist for forwarded headers (comma-separated); defaults to private/loopback ranges when TRUST_PROXY_HEADERS is enabled

TLS

VariableDefaultTypeDescription
ACME_DNS_PROVIDER""stringDNS provider for managed DNS-01/A-record sync, ECH HTTPS records, and ENS gasless DNSSEC/TXT automation (cloudflare | gcloud | hetzner | route53 | vultr); leave empty to use manual fullchain.pem/privatekey.pem from IDENTITY_PATH
ENS_GASLESS_ENABLEDfalseboolEnable ENS gasless DNS import automation for the managed DNS zone and lease hostnames

Admin

VariableDefaultTypeDescription
HEADLESS_SHELL_URL""stringHeadless Chrome CDP WebSocket URL for thumbnail generation (e.g. ws://headless-shell:9222)

Diagnostics

VariableDefaultTypeDescription
PPROF_ENABLEDfalseboolEnable the relay pprof diagnostics HTTP server
PPROF_ADDR127.0.0.1:6060stringpprof listen address when enabled; keep it on loopback unless the port is protected

Cloudflare

VariableDefaultTypeDescription
CLOUDFLARE_TOKENstringCloudflare DNS API token; required when ACME_DNS_PROVIDER=cloudflare

Google Cloud

VariableAliasesDefaultTypeDescription
GCP_PROJECT_IDGOOGLE_CLOUD_PROJECT, GCLOUD_PROJECT, GCE_PROJECTstringGoogle Cloud project ID for Cloud DNS automation; auto-detected from ADC or GCE metadata when omitted
GCP_MANAGED_ZONEGCP_ZONE, GCE_ZONE_IDstringExplicit Google Cloud DNS managed zone name or numeric ID override
GOOGLE_APPLICATION_CREDENTIALSstringPath to GCP service account key file (standard ADC; used by the GCP client library)

Hetzner

VariableAliasesDefaultTypeDescription
HETZNER_API_TOKENHCLOUD_TOKENstringHetzner Cloud API token for DNS automation; required when ACME_DNS_PROVIDER=hetzner

AWS

VariableAliasesDefaultTypeDescription
AWS_ACCESS_KEY_IDstringAWS access key ID for Route53 static credentials; uses the default AWS credential chain when omitted
AWS_SECRET_ACCESS_KEYstringAWS secret access key for Route53 static credentials
AWS_SESSION_TOKENstringAWS session token for Route53 temporary credentials
AWS_REGIONAWS_DEFAULT_REGIONus-east-1stringAWS region for Route53 and Route53-backed DNS-01
AWS_HOSTED_ZONE_IDstringExplicit Route53 hosted zone ID override
AWS_DNSSEC_KMS_KEY_ARNstringAWS KMS key ARN used to create a Route53 DNSSEC key-signing key when needed

Vultr

VariableDefaultTypeDescription
VULTR_API_KEYstringVultr API key for DNS automation; required when ACME_DNS_PROVIDER=vultr

Portal Tunnel CLI Flags

The portal expose subcommand accepts the following flags. Flags that read from environment variables are noted in the Env Var column.

Connection

FlagEnv VarTypeDefaultDescription
--relaysstring(registry)Additional Portal relay server API URLs (comma-separated; scheme omitted defaults to https)
--discoverybooltrueInclude public registry relays and discover additional relay bootstraps
--multi-hopMULTI_HOPstringOrdered multi-hop relay API URLs, comma-separated
--multi-hop-depthMULTI_HOP_DEPTHint0Automatically select one multi-hop route with this hop count; 0 or 1 disables multi-hop
--max-active-relaysMAX_ACTIVE_RELAYSint3Maximum auto-selected relays to keep connected; explicit relays are always included
--ban-mitmBAN_MITMbooltrueBan relay when the MITM self-probe detects TLS termination

Identity

FlagEnv VarTypeDefaultDescription
--identity-pathIDENTITY_PATHstringidentity.jsonIdentity JSON file path
--identity-jsonIDENTITY_JSONstringIdentity JSON payload; overrides --identity-path contents and is persisted there when both are set

Lease

FlagEnv VarTypeDefaultDescription
--namestring(auto)Public hostname prefix (single DNS label); auto-generated when omitted
--descriptionstringService description metadata
--tagsstringService tags metadata (comma-separated)
--ownerstringService owner metadata
--thumbnailstringService thumbnail URL metadata
--hideboolfalseHide service from relay listing screens

Routing

FlagEnv VarTypeDefaultDescription
--http-routestringHTTP route mapping in PATH=UPSTREAM form; repeat to aggregate multiple local HTTP services behind one public URL

Transport

FlagEnv VarTypeDefaultDescription
--udpUDP_ENABLEDboolfalseEnable public UDP relay in addition to the default stream path
--udp-addrUDP_ADDRstringLocal UDP target address for relayed datagrams (host:port or port only); defaults to the target when --udp is enabled
--tcpTCP_ENABLEDboolfalseRequest a dedicated TCP port on the relay for raw TCP services (no TLS; e.g., Minecraft, game servers)

The portal list subcommand accepts the following flags:

FlagTypeDefaultDescription
--relaysstring(registry)Additional Portal relay server API URLs (comma-separated)
--default-relaysbooltrueInclude public registry relays

Configuration Files

config.toml

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.

Default paths:

OSConfigDefault identity
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
Linux root/etc/portal-tunnel/agent/config.toml/var/lib/portal-tunnel/agent/identity.json
macOS user~/Library/Application Support/Portal Tunnel/Agent/config.toml~/Library/Application Support/Portal Tunnel/Agent/identity.json
macOS root/Library/Application Support/Portal Tunnel/Agent/config.toml/Library/Application Support/Portal Tunnel/Agent/identity.json
Windows%ProgramData%\Portal Tunnel\Agent\config.toml%ProgramData%\Portal Tunnel\Agent\identity.json
[agent]
control_addr = "127.0.0.1:4018"
service_name = "portal-agent"

[[tunnels]]
id = "web"
name = "myapp"
target = "127.0.0.1:3000"
relays = ["https://portal.example.com"]
discovery = false
description = "Managed web tunnel"
tags = ["web"]

[[tunnels]]
id = "frontend-api"
name = "myapp"

[[tunnels.http_routes]]
prefix = "/api"
upstream = "http://127.0.0.1:3001"

[[tunnels.http_routes]]
prefix = "/"
upstream = "http://127.0.0.1:5173"

Agent fields:

FieldDefaultDescription
state_dirPlatform default state directoryStores the local control endpoint token and runtime state
control_addr127.0.0.1:4018Loopback-only local control API address
service_nameportal-agentOS service name
allowed_walletsemptyWallet addresses allowed to read local agent status through wallet auth; empty allows any wallet on the loopback auth endpoint

The local agent dashboard and mutating control API calls use the bearer token in the agent state directory. Wallet-authenticated agent requests are read-only and can only read /v1/agent/status.

Tunnel fields mirror portal expose flags:

FieldTypeDescription
idstringStable tunnel ID used by the agent dashboard
targetstringLocal TCP target, equivalent to the portal expose <target> argument
http_routestable arrayHTTP route mappings; cannot be combined with target or udp
relaysstring arrayExplicit relay API URLs
discoveryboolInclude registry and relay discovery expansion
multi_hopstring arrayOrdered multi-hop relay path
multi_hop_depthintAutomatically select one multi-hop route with this depth
identity_pathstringTunnel identity JSON file path. When omitted, one tunnel uses the platform default identity.json; multiple tunnels use <state-dir>/<tunnel-id>/identity.json
identity_jsonstringIdentity JSON payload; overrides identity_path contents and is persisted there when both are set
udp, udp_addr, tcpbool/stringUDP and raw TCP relay options
description, tags, owner, thumbnail, hidemixedLease metadata shown by relays

For a task-oriented walkthrough, see Portal Agent.

identity.json

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.

FieldTypeDescription
namestringHuman-readable label for this identity
addressstringDerived EVM address used for SIWE and identity ownership
public_keystringCompressed secp256k1 public key hex
private_keystringsecp256k1 private key hex; keep secret
wireguard_public_keystringRelay-only WireGuard overlay public key when discovery is enabled
wireguard_private_keystringRelay-only WireGuard overlay private key when discovery is enabled
encrypted_client_hello_seedstringRelay-only HKDF salt for deriving the ECH HPKE private key; generated automatically when missing; keep secret

The same identity file or state directory can be reused across restarts to keep a stable address.

admin_settings.json

Persists admin-panel state for the relay server. Managed automatically by the relay on write; do not edit manually while the server is running.

Relay admin settings are stored at IDENTITY_PATH/admin_settings.json.


ACME DNS Provider Configuration

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.

When this variable is empty the relay server falls back to manually supplied fullchain.pem and privatekey.pem files in IDENTITY_PATH.

For ENS gasless behavior and wallet authentication details, see Wallet and ENS.

Cloudflare (cloudflare)

VariableRequiredDescription
CLOUDFLARE_TOKENYesCloudflare DNS API token with Zone:DNS:Edit permission

Google Cloud DNS (gcloud)

VariableRequiredDescription
GCP_PROJECT_IDNoGoogle Cloud project ID; auto-detected from ADC or GCE metadata when omitted
GCP_MANAGED_ZONENoCloud DNS managed zone name or numeric ID; inferred from the portal domain when omitted
GOOGLE_APPLICATION_CREDENTIALSNoPath to a service account key JSON file; uses Application Default Credentials when omitted

AWS Route53 (route53)

VariableRequiredDescription
AWS_ACCESS_KEY_IDNoAccess key ID; uses the default AWS credential chain (instance profile, env, ~/.aws/credentials) when omitted
AWS_SECRET_ACCESS_KEYNoSecret access key; required when AWS_ACCESS_KEY_ID is set
AWS_SESSION_TOKENNoSession token for temporary credentials
AWS_REGIONNoAWS region; defaults to us-east-1
AWS_HOSTED_ZONE_IDNoRoute53 hosted zone ID; inferred from the portal domain when omitted
AWS_DNSSEC_KMS_KEY_ARNNoKMS key ARN for DNSSEC key-signing key creation

Hetzner DNS (hetzner)

VariableRequiredDescription
HETZNER_API_TOKENYesHetzner Cloud API token with DNS zone and RRSet write access

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.

Vultr DNS (vultr)

VariableRequiredDescription
VULTR_API_KEYYesVultr API key with DNS domain, record, and DNSSEC write access