Skip to content

Configuration Reference

plexd reads its configuration from a YAML file (default: /etc/plexd/config.yaml). The file is parsed by ParseConfig() in internal/agent/config.go, which performs three steps:

  1. Unmarshal the YAML into an AgentConfig struct
  2. ApplyDefaults for every zero-valued field
  3. Validate all sections (returns the first error encountered)

Precedence order (highest to lowest):

  1. CLI flags (--api, --mode, --log-level)
  2. applyEnvOverrides()PLEXD_* environment variables (see Environment Variables)
  3. Global env vars via envOrDefault() (PLEXD_CONFIG, PLEXD_LOG_LEVEL, PLEXD_API, PLEXD_MODE)
  4. Values in the YAML config file
  5. ApplyDefaults() for zero-valued fields

Top-Level Fields

FieldTypeDefaultDescription
modestringnodeOperating mode: node or bridge. Bridge mode enables bridge-specific subsystems when bridge.enabled: true.
log_levelstringinfoLog level: debug, info, warn, error
data_dirstring/var/lib/plexdDirectory for persistent agent data. Propagated to registration.data_dir and node_api.data_dir at runtime.

api

Control plane HTTP client configuration.

FieldTypeDefaultDescription
base_urlstring— (required)Control plane API base URL, e.g. https://api.plexsphere.com
tls_insecure_skip_verifyboolfalseDisable TLS certificate verification. WARNING: Only for development/testing.
connect_timeoutduration10sMaximum time to wait for a TCP connection
request_timeoutduration30sMaximum time for a complete HTTP request/response cycle
sse_idle_timeoutduration90sMaximum idle time on the SSE stream before reconnecting

Source: internal/api/config.go


registration

Node registration and bootstrap authentication.

FieldTypeDefaultDescription
token_filestring/etc/plexd/bootstrap-tokenPath to the bootstrap token file
token_envstringPLEXD_BOOTSTRAP_TOKENEnvironment variable name for the bootstrap token
token_valuestringDirect token value override
use_metadataboolfalseEnable cloud metadata service for registration
metadata_token_pathstring/plexd/bootstrap-tokenMetadata key path for the bootstrap token (e.g. IMDS)
metadata_timeoutduration2sMaximum time to wait for a metadata service response
hostnamestringOverride system hostname. Empty uses os.Hostname().
metadatamap[string]stringOptional key-value pairs for the registration request
max_retry_durationduration5mMaximum duration to retry registration

data_dir is propagated from the top-level data_dir at runtime. It does not appear in the YAML.

Source: internal/registration/config.go


heartbeat

Periodic heartbeat reporting to the control plane.

FieldTypeDefaultDescription
intervalduration30sHeartbeat send interval

node_id is set at runtime from the registration identity. It does not appear in the YAML.

Source: internal/agent/heartbeat.go


reconcile

State reconciliation loop.

FieldTypeDefaultDescription
intervalduration60sTime between reconciliation cycles. Minimum: 1s.

Source: internal/reconcile/config.go


node_api

Local node API server (Unix socket and optional HTTP).

FieldTypeDefaultDescription
socket_pathstring/var/run/plexd/api.sockPath to the Unix domain socket
http_enabledboolfalseEnable the optional HTTP listener
http_listenstring127.0.0.1:9100HTTP listen address
http_token_filestringPath to the HTTP bearer token file
debounce_periodduration5sDebounce period for coalescing events
shutdown_timeoutduration5sMaximum time to wait for graceful shutdown

data_dir and secret_auth_enabled are set at runtime by plexd up. They do not appear in the YAML.

Source: internal/nodeapi/config.go


actions

Remote action execution and hook management.

FieldTypeDefaultDescription
enabledbooltrueEnable action execution. Defaults to true via zero-value heuristic: if all numeric fields are zero, Enabled is set to true by ApplyDefaults().
hooks_dirstring/etc/plexd/hooksDirectory containing hook scripts
max_concurrentint5Maximum number of concurrent actions. Minimum: 1.
max_action_timeoutduration10mMaximum duration for a single action. Minimum: 10s.
max_output_bytesint641048576 (1 MiB)Maximum output size per action in bytes. Minimum: 1024.

Source: internal/actions/config.go


integrity

Binary and hook integrity verification.

FieldTypeDefaultDescription
enabledbooltrueEnable integrity verification. Defaults to true when verify_interval is zero.
binary_pathstringPath to the plexd binary to verify
hooks_dirstringDirectory containing hook scripts to verify. When empty, mirrors actions.hooks_dir.
verify_intervalduration5mInterval between integrity verification runs. Minimum: 30s.
watch_enabledbooltrueEnable inotify file watching. When enabled, file changes in hooks_dir trigger immediate checksum recomputation.

Source: internal/integrity/config.go


metrics

System metrics collection and reporting.

FieldTypeDefaultDescription
enabledbooltrueEnable metrics collection. Defaults to true via zero-value heuristic.
collect_intervalduration15sInterval between collection cycles. Minimum: 5s.
report_intervalduration60sInterval between reporting to the control plane. Minimum: 10s. Must be >= collect_interval.
batch_sizeint100Maximum number of metric points per report batch. Minimum: 1.
local_endpoint.urlstringHTTPS URL for a local metrics endpoint. Must use https:// scheme. Empty means not configured.
local_endpoint.secret_keystringAuthentication credential for the local endpoint. Required when url is set. Redacted in config dumps.
local_endpoint.tls_insecure_skip_verifyboolfalseDisable TLS certificate verification for the local endpoint.

For a step-by-step guide to configuring local endpoints, see Setting Up Local Endpoint Delivery.

Source: internal/metrics/config.go


log_fwd

Log collection and forwarding.

FieldTypeDefaultDescription
enabledbooltrueEnable log forwarding. Defaults to true via zero-value heuristic.
collect_intervalduration10sInterval between collection cycles. Minimum: 5s.
report_intervalduration30sInterval between reporting to the control plane. Must be >= collect_interval.
batch_sizeint200Maximum number of log entries per report batch. Minimum: 1.
file_patterns[]stringGlob patterns for file-based log collection, e.g. ["/var/log/app/*.log"]
filter.min_severitystringDrop log entries below this severity level (syslog severities: emerg, alert, crit, err, warning, notice, info, debug)
filter.include_units[]stringOnly pass entries matching one of these unit names
filter.exclude_units[]stringDrop entries matching any of these unit names. Takes precedence over include_units.
local_endpoint.urlstringHTTPS URL for a local log forwarding endpoint. Must use https:// scheme. Empty means not configured.
local_endpoint.secret_keystringAuthentication credential for the local endpoint. Required when url is set. Redacted in config dumps.
local_endpoint.tls_insecure_skip_verifyboolfalseDisable TLS certificate verification for the local endpoint.

For a step-by-step guide to configuring local endpoints, see Setting Up Local Endpoint Delivery.

Source: internal/logfwd/config.go, internal/logfwd/filter.go


audit_fwd

Audit event collection and forwarding.

FieldTypeDefaultDescription
enabledbooltrueEnable audit forwarding. Defaults to true via zero-value heuristic.
collect_intervalduration5sInterval between collection cycles. Minimum: 1s.
report_intervalduration15sInterval between reporting to the control plane. Must be >= collect_interval.
batch_sizeint500Maximum number of audit entries per report batch. Minimum: 1.
local_endpoint.urlstringHTTPS URL for a local audit forwarding endpoint. Must use https:// scheme. Empty means not configured.
local_endpoint.secret_keystringAuthentication credential for the local endpoint. Required when url is set. Redacted in config dumps.
local_endpoint.tls_insecure_skip_verifyboolfalseDisable TLS certificate verification for the local endpoint.

For a step-by-step guide to configuring local endpoints, see Setting Up Local Endpoint Delivery.

Source: internal/auditfwd/config.go


wireguard

WireGuard interface and peer management. See WireGuard Tunnel Management.

FieldTypeDefaultDescription
interface_namestringplexd0Name of the WireGuard interface
listen_portint51820UDP listen port for WireGuard
mtuint0MTU for the WireGuard interface. 0 means use system default.

Source: internal/wireguard/config.go


nat

STUN-based NAT traversal. See NAT Traversal via STUN.

FieldTypeDefaultDescription
enabledbooltrueEnable NAT traversal
stun_servers[]string(built-in list)List of STUN server addresses (host:port)
refresh_intervalduration60sInterval between STUN binding refreshes. Minimum: 10s.
timeoutduration5sPer-server STUN request timeout

Source: internal/nat/config.go


peer_exchange

Peer endpoint discovery and exchange. See Peer Endpoint Exchange.

Embeds nat.Config — inherits all NAT fields.

Source: internal/peerexchange/config.go


policy

Network policy enforcement and firewall rules. See Network Policy Enforcement.

FieldTypeDefaultDescription
enabledbooltrueEnable policy enforcement. Defaults to true when chain_name is empty (zero-value heuristic).
chain_namestringplexd-meshName of the nftables chain for policy rules

Source: internal/policy/config.go


tunnel

Secure tunnel access for services. See Secure Access Tunneling.

FieldTypeDefaultDescription
enabledbooltrueEnable secure access tunneling
max_sessionsint10Maximum concurrent tunnel sessions
default_timeoutduration30mDefault session timeout
ssh_listen_addrstringSSH server listen address. If empty, the SSH server is not started.
host_key_dirstringDirectory for the host key (defaults to data_dir)

Source: internal/tunnel/config.go


bridge

Gateway bridge mode operation. Active when mode: bridge and bridge.enabled: true. See Bridge Mode.

FieldTypeDefaultDescription
enabledboolfalseEnable bridge mode
access_interfacestringeth1Access-side network interface
access_subnets[]stringSubnets routable via the access interface
enable_natboolfalseEnable NAT masquerading on the access interface
relay_enabledboolfalseEnable UDP relay for NAT traversal
relay_listen_portint51821Relay UDP listen port
max_relay_sessionsint100Maximum concurrent relay sessions
session_ttlduration5mRelay session TTL
ingress_enabledboolfalseEnable public ingress
max_ingress_rulesint20Maximum ingress rules
ingress_dial_timeoutduration10sTimeout for dialing backend targets
user_access_enabledboolfalseEnable user access VPN integration
user_access_interface_namestringwg-accessWireGuard interface for user access
user_access_listen_portint51822User access WireGuard listen port
max_access_peersint50Maximum user access peers
user_access_provider_typestringExternal VPN provider for user access: tailscale, netbird, or empty (disabled)
auth_key_envstringEnvironment variable name containing the auth key for the user access provider (e.g. PLEXD_TAILSCALE_AUTH_KEY)
site_to_site_enabledboolfalseEnable site-to-site VPN
site_to_site_interface_prefixstringwg-s2s-Prefix for site-to-site WireGuard interfaces
site_to_site_listen_portint51823Base listen port for site-to-site tunnels
max_site_to_site_tunnelsint10Maximum site-to-site tunnels
tunnel_providers[]stringTunnel provider types for site-to-site: ipsec, openvpn. Empty means WireGuard-only.
acme_enabledboolfalseEnable ACME TLS certificate management
acme_cache_dirstringDirectory for ACME certificate caching
acme_allowed_hosts[]stringHostnames allowed for ACME certificates
acme_emailstringACME account contact email
acme_directory_urlstringOverride ACME directory URL (default: Let's Encrypt production)

Source: internal/bridge/config.go


Complete Annotated Example

yaml
# /etc/plexd/config.yaml — Complete example with all sections

mode: node          # "node" or "bridge" (default: node)
log_level: info     # debug | info | warn | error (default: info)
data_dir: /var/lib/plexd  # persistent data directory (default: /var/lib/plexd)

api:
  base_url: https://api.plexsphere.com  # required
  tls_insecure_skip_verify: false
  connect_timeout: 10s
  request_timeout: 30s
  sse_idle_timeout: 90s

registration:
  token_file: /etc/plexd/bootstrap-token
  token_env: PLEXD_BOOTSTRAP_TOKEN
  # token_value: ""          # direct token override
  use_metadata: false
  metadata_token_path: /plexd/bootstrap-token
  metadata_timeout: 2s
  # hostname: ""             # empty = os.Hostname()
  # metadata: {}             # optional key-value pairs
  max_retry_duration: 5m

heartbeat:
  interval: 30s

reconcile:
  interval: 60s              # min: 1s

node_api:
  socket_path: /var/run/plexd/api.sock
  http_enabled: false
  http_listen: 127.0.0.1:9100
  # http_token_file: ""
  debounce_period: 5s
  shutdown_timeout: 5s

actions:
  enabled: true
  hooks_dir: /etc/plexd/hooks
  max_concurrent: 5          # min: 1
  max_action_timeout: 10m    # min: 10s
  max_output_bytes: 1048576  # min: 1024 (1 MiB)

integrity:
  enabled: true
  # binary_path: ""          # path to plexd binary
  # hooks_dir: ""            # empty = mirrors actions.hooks_dir
  verify_interval: 5m        # min: 30s
  watch_enabled: true

metrics:
  enabled: true
  collect_interval: 15s      # min: 5s
  report_interval: 60s       # min: 10s, >= collect_interval
  batch_size: 100            # min: 1
  # local_endpoint:
  #   url: https://metrics.local:9090/ingest
  #   secret_key: local-metrics-token
  #   tls_insecure_skip_verify: false

log_fwd:
  enabled: true
  collect_interval: 10s      # min: 5s
  report_interval: 30s       # >= collect_interval
  batch_size: 200            # min: 1
  # file_patterns:
  #   - /var/log/app/*.log
  # filter:
  #   min_severity: warning
  #   include_units:
  #     - sshd.service
  #   exclude_units:
  #     - cron.service
  # local_endpoint:
  #   url: https://logs.local:9090/ingest
  #   secret_key: local-logs-token
  #   tls_insecure_skip_verify: false

audit_fwd:
  enabled: true
  collect_interval: 5s       # min: 1s
  report_interval: 15s       # >= collect_interval
  batch_size: 500            # min: 1
  # local_endpoint:
  #   url: https://audit.local:9090/ingest
  #   secret_key: local-audit-token
  #   tls_insecure_skip_verify: false

wireguard:
  interface_name: plexd0
  listen_port: 51820
  # mtu: 0                  # 0 = system default

nat:
  enabled: true
  # stun_servers:            # default built-in list
  refresh_interval: 60s      # min: 10s
  timeout: 5s

peer_exchange:
  enabled: true
  refresh_interval: 60s
  timeout: 5s

policy:
  chain_name: plexd-mesh

tunnel:
  enabled: true
  max_sessions: 10
  default_timeout: 30m
  # ssh_listen_addr: ""       # empty = SSH server not started
  # host_key_dir: ""         # defaults to data_dir

# bridge:                    # uncomment for bridge mode
#   enabled: true
#   access_interface: eth1
#   access_subnets:
#     - 10.0.0.0/24
#   enable_nat: false
#   relay_enabled: false
#   ingress_enabled: false
#   user_access_enabled: false
#   site_to_site_enabled: false
#   acme_enabled: false

See Also