Operations¶
This page covers running the proxy on a deployed box: the systemd unit, the command-line flags, and what the logs tell you.
Service control¶
The shipped RPM installs the systemd unit pdns-pf-proxy-tcp.service, which runs
the binary as /usr/bin/pdns-pf-proxy-tcp --config /etc/pdns-pf/proxy-tcp.yaml run
under the unprivileged pdns-proxy-tcp user. It is granted
CAP_NET_BIND_SERVICE so it can bind privileged ports (80, 443) without running
as root.
systemctl status pdns-pf-proxy-tcp
journalctl -u pdns-pf-proxy-tcp -f
systemctl restart pdns-pf-proxy-tcp
There is no config reload: the proxy reads its configuration once at startup, so
a config change requires a restart. On SIGINT or SIGTERM the proxy stops
accepting new connections immediately, gives existing connections a short grace
period to finish, then force-closes whatever remains.
Config location¶
The unit passes /etc/pdns-pf/proxy-tcp.yaml. The example template ships as
/etc/pdns-pf/proxy-tcp.example.yaml. See the Configuration
page for the full reference.
Subcommands¶
The binary has three subcommands:
| Subcommand | Purpose |
|---|---|
run |
Start the proxy listeners and serve until shutdown. |
check |
Validate the effective configuration and exit without starting listeners. |
version |
Print the build version. |
Use check to validate a config before restarting the service:
Command-line flags¶
The proxy can run entirely from flags, with YAML optional. The persistent flags work with any subcommand and override the matching YAML values after the file loads.
| Flag | Default | Purpose |
|---|---|---|
--config, -c |
"" |
YAML config file to load before applying flag overrides. |
--decision-backend |
nats |
Remote decision backend: none, nats, or http. |
--simulator-http-url |
"" |
Base URL for the http backend, e.g. http://127.0.0.1:8080. |
--debug |
false |
Force debug log level. |
--log-level |
connection |
Log level: debug, connection, info, warn, or error. |
--log-format |
human |
Log format: human, logfmt, or json. |
The run subcommand adds flags that create listeners. Repeating an address flag
adds more listeners.
| Flag | Default | Purpose |
|---|---|---|
--http-address |
— | Append a plain HTTP listener. Repeatable. |
--https-address |
— | Append an HTTPS listener. Repeatable. |
--http-proxy-protocol-address |
— | Append an HTTP listener that requires HAProxy PROXY protocol v1. Repeatable. |
--https-proxy-protocol-address |
— | Append an HTTPS listener that requires HAProxy PROXY protocol v1. Repeatable. |
--socks5-address |
— | Append a SOCKS5 listener. Repeatable. |
--status-address |
"" |
Serve the status page and Prometheus metrics on this address. Empty disables it. Overrides status.address. |
--dev-listeners |
false |
Shorthand for --http-address=:9980, --https-address=:9943, and --socks5-address=:9990, and serves the status page on 127.0.0.1:9919 with the per-connection table enabled. |
--vhost |
"" |
Static vhost for listeners created by the flags above. |
--proxy-profile |
0 |
Static profile number for listeners created by the flags above. |
--fail-open |
false |
Allow proxying when the decision backend fails, for listeners created by the flags above. |
The --vhost, --proxy-profile, and --fail-open flags apply only to listeners
created on the command line, not to listeners defined in YAML.
Observability¶
The proxy's observability surface is its structured logs plus an optional HTTP server that exposes a status page and Prometheus metrics.
Logging uses log/slog. In a terminal the human format is colorized and
easy to read; logfmt and json are machine-parseable for log shipping. The
default connection level keeps the per-session lifecycle logs on without the
volume of full debug output.
Per-connection logs¶
Each connection produces a summary line when it closes, carrying the request ID, client address, target host, upstream IP and port, the time spent in each stage, the bytes transferred each way, and the decision rule that allowed or blocked it. The request ID is highlighted in terminal output so a single session is easy to follow.
Periodic activity stats¶
Every tcp.active_stats_interval (default 10s) the proxy logs one summary line
of current activity:
- active connection count, split into pre-proxy and proxying connections
- connections added and closed during the interval
- bytes in and out during the interval, and the average rate each way
Accepted-but-not-yet-proxying connections are counted too, so a flood of stalled
or idle connections is visible. When an interval has no activity the proxy logs
one line noting that periodic stats are muted, then stays quiet until traffic
resumes. Set active_stats_interval to 0 to disable these summaries entirely
while keeping the per-connection logs.
Status and metrics server¶
When status.address is set, the proxy starts a plain
HTTP server with three endpoints:
| Path | Purpose |
|---|---|
/metrics |
Prometheus metrics. See the Metrics page. |
/healthz |
Liveness probe. Returns 200 OK. |
/ |
Summary status page: version, uptime, active connection counts, and Go runtime stats. |
The server is disabled by default. Configure it under status,
or pass --status-address on the run command.
--dev-listeners enables it on 127.0.0.1:9919.
Warning
Setting status.connections: true adds a
per-connection table to the status page that exposes client addresses and
destination hosts, and snapshots every active connection on each page load.
Keep it off in production. --dev-listeners turns it on, so bind the dev
status server to localhost only.
SOCKS5 listener¶
A SOCKS5 listener accepts only CONNECT requests to ports 80 and 443, then
routes on the HTTP Host or TLS SNI that follows rather than the SOCKS
destination address. It applies the same filtering as the HTTP and HTTPS
listeners, so it is a convenient way to send a client through the filter without
configuring routing for every host.
Warning
The SOCKS5 listener performs no authentication. Anyone who can reach its bind address can proxy through it. Bind it to a trusted interface or protect it with a firewall — never expose it to the public Internet.
Pausing a subscriber¶
The proxy accepts a runtime command over NATS to close a subscriber's live sessions and optionally reject new ones for a short window. See Pause control.