Configuration¶
The Simulator HTTP Server is configured by a single YAML file. On the
shipped RPM the systemd unit passes
/etc/pdns-pf/simulator-server.yaml to the binary, and a
/etc/pdns-pf/simulator-server.example.yaml template ships
alongside it.
Environment variables in the YAML are always expanded before parsing:
$VAR and ${VAR} references get replaced with their values from the
service's environment. This is the recommended way to inject secrets
(for example, an API key) from a systemd drop-in rather than hard-coding
them in the file. There is no CLI flag to turn this off.
Unknown YAML keys are rejected — a typo in a field name will refuse to start the service rather than be silently ignored.
Every config option is documented on this page. Use your browser's in-page search (Ctrl/⌘-F) to jump straight to the field you care about.
Top-level structure¶
The YAML has four top-level sections. All four are optional in the
strict parsing sense, but in practice every deployment sets at least
http.address (so there is a predictable metrics endpoint to scrape)
and lua (to point at the actual filter engine script).
| Parameter | Type | Default | Description |
|---|---|---|---|
http |
HTTP |
{} |
HTTP server for the REST API, status page, Prometheus /metrics, and pprof. The server is started even when http.address is empty. |
nats |
NATS |
{} |
Optional NATS transport. Enabled when nats.itsy.url (or the NATS_URL env var) is set. |
lua |
Lua |
{workers: 1, file: "/usr/share/pdns-pf-lua-dist/share/lua/5.1/pdns-pf/simulator/server.lua"} |
Lua worker pool that runs the filter engine. |
log |
Log |
{format: logfmt} |
Logging format and level. |
Deprecation policy¶
None. Every field on this page is current as of this release. The service has no deprecated or removed config fields to migrate away from.
Full example¶
The file below is the example template shipped alongside the RPM. It
is the smallest reasonable configuration: HTTP on a fixed port, NATS
enabled, one Lua worker, and debug-level logging. The per-section
reference below it is authoritative.
Click to expand the shipped example
http:
# http address for the simulator API
address: ":8671"
tls: {}
api_keys: []
nats:
# As defined by: https://github.com/PowerDNS/itsy
itsy:
url: "nats://nats:4222"
# Optional prefix, if not set it will default to svc meaning
# subjects will look like svc.simulator.abc
prefix: "pdnspf"
topologies: []
meta: {}
tls: {}
lua:
workers: 1
file: "/platform-filter/pdns-pf/simulator/server.lua"
log:
format: "logfmt"
level: "debug"
http¶
The http section controls the internal webserver that exposes the
REST API, the HTML status page at /, the Prometheus /metrics
endpoint, and the Go net/http/pprof profiling handlers. All four share
the same bind address; there is no way to split them onto different
listeners.
The current binary always starts the webserver. If http.address is
left empty, the address is passed through to Go's net/http server;
that server uses :http (port 80) for an empty address. This is not a
headless or NATS-only mode, and it may fail under the shipped non-root
systemd service because binding port 80 normally requires elevated
privileges. Set an explicit address such as :8671 or
127.0.0.1:8671 so the listener is predictable. There is currently no
configuration switch that disables the HTTP listener entirely.
API key enforcement¶
When api_keys is non-empty, the three API endpoints that talk to the
Lua side — /api/v1/domain, /api/v1/simulate, and
/api/v1/codemappings — require the caller to present a valid key.
Keys must be sent in the X-API-Key HTTP header. A missing key returns
401 Unauthorized; an unknown key returns the same status.
The status page, /api/v1/info, /metrics, and the pprof handlers are
not behind the API key check, so a Prometheus scraper does not need
to know any keys.
When api_keys is left empty, the API is open to anyone who can reach
the address. In a deployment where the service is exposed beyond
localhost, populate this list, and inject the keys from an environment
variable rather than committing them to the YAML. If a proxy uses this
simulator as a remote decision backend, set that proxy's API key
setting to one of these keys. For the current OpenResty proxy, that
setting is proxyremoteapikey:
HTTP fields¶
| Parameter | Type | Default | Description |
|---|---|---|---|
address |
string |
"" |
Bind address in host:port form (e.g. :8671 for all interfaces, 127.0.0.1:8671 for local only). Empty is passed to Go net/http, which listens on :http (port 80); it does not disable the webserver. |
tls |
tlsconfig.Config |
{} |
PowerDNS go-tlsconfig block. Leave as {} for plain HTTP; populate to enable HTTPS. |
api_keys |
[]string |
[] |
Accepted API keys for the three Lua-backed endpoints. Empty leaves the API open. See API key enforcement. |
Example:
See Operations → Observability for the list of served endpoints.
nats¶
The nats section enables the NATS transport. When nats.itsy.url is
set (or the NATS_URL environment variable is set at startup), the
service connects to NATS via the
itsy library and serves the same
request types it serves over HTTP. When both are empty, the NATS
goroutine never starts and the instance is HTTP-only.
NATS and HTTP can be enabled together. They share the same Lua worker pool, so requests on either transport queue up on the same workers.
itsy¶
Nested NATS connection config, passed through to itsy. The most commonly-touched fields are listed here; see the full itsy reference for all fields including environment variable overrides.
| Parameter | Type | Default | Description |
|---|---|---|---|
url |
string |
"" |
NATS server URL, e.g. nats://nats:4222 or tls://nats.example.com:4222. Empty leaves NATS disabled unless NATS_URL is set in the environment. |
prefix |
string |
"svc" |
Subject prefix used for all itsy-managed subjects. The simulator's transport subjects are <prefix>.simulator.domain, <prefix>.simulator.simulate, <prefix>.simulator.codemappings, and <prefix>.simulator.info. |
topologies |
[]string |
[] |
Advanced NATS topology config (dotted strings like eu.amsterdam.az1). Leave empty unless you have specific requirements. |
meta |
map[string]string |
{} |
Free-form metadata attached to this NATS service registration, visible to NATS monitoring tooling. |
tls |
tlsconfig.Config |
{} |
TLS config for the NATS connection. Populate to enable authenticated/encrypted transport. |
Example:
lua¶
The lua section controls the pool of LuaJIT workers that run the
actual filter engine. Each worker is an independent LuaJIT state with
its own copy of the filter code; the Go side dispatches incoming
requests across the pool.
Picking the worker count¶
workers: 1 is enough for an Admin Portal that only fires a query when
an operator clicks a button. Raise it when the service is also serving
automated workloads — bulk simulation runs, regression suites, a NATS
topology with several callers, or proxies using it as a remote decision
backend — that would otherwise queue behind a single worker.
Each additional worker independently keeps its own copy of the filter engine's working set in memory; the cost is roughly linear in process RSS. There is no benefit to going beyond the number of CPUs the service can use.
Lua file path¶
lua.file points at the entry-point script the workers load. On a
shipped deployment this is the file the pdns-pf-simulator RPM
installs at
/usr/share/pdns-pf-lua-dist/share/lua/5.1/pdns-pf/simulator/server.lua.
If the file does not load (missing file, Lua parse error, missing required module), worker startup fails and the service exits with the relevant error logged. There is no fallback path.
Lua fields¶
| Parameter | Type | Default | Description |
|---|---|---|---|
workers |
int |
1 |
Number of independent LuaJIT workers. See Picking the worker count. |
file |
string |
/usr/share/pdns-pf-lua-dist/share/lua/5.1/pdns-pf/simulator/server.lua |
Filesystem path to the Lua entry point. |
Example:
log¶
The log section picks the output format and level for the service's
logs. Logs go to standard error, which under the default systemd unit
is captured by the journal under the pdns-pf-simulator-server
identifier.
| Parameter | Type | Default | Description |
|---|---|---|---|
format |
string |
logfmt |
Log output format. Accepted values: logfmt (structured key=value, easy to grep) or json. |
level |
string |
info |
Log level. Accepted values: debug, info, warn, error. The --debug CLI flag overrides this to debug at startup. |
Example: