Security Hardening
Restrict management access, protect persistent state, and scope public controls so the deployment is safer to operate.
Use This When
Use this before exposing management beyond a private network, after adding agents, before publishing production hostnames, and during periodic self-hosting reviews.
Prerequisites
- p2pstream is running with persistent
CONFIG_DIR,/datain Compose. - You know whether management must be reachable by remote agents, remote admins, or both.
- You have a backup path for the persistent data directory.
Steps
Harden management access:
- Keep management HTTPS enabled.
- Keep
MANAGEMENT_BIND_ADDRESS=0.0.0.0when agents or admins connect from other hosts. - For a native process, set
MANAGEMENT_BIND_ADDRESS=127.0.0.1when a reverse proxy or SSH tunnel on the same host fronts management. In Compose, keep the container's listener reachable by Docker forwarding; useP2PSTREAM_MANAGEMENT_PUBLISH_ADDRESS=127.0.0.1to restrict the published host port. A proxy in a separate container needs a reachable container address, not that container's loopback. - Prefer firewall allowlists, VPN, or a private admin network for
8081. - Set
MANAGEMENT_PUBLIC_URLto the real management URL used by browsers and agents. - Set at least 32 characters of cryptographically random data as
MANAGEMENT_SETUP_TOKENbefore first setup, or capture the generated startup token from trusted logs. - If a reverse proxy fronts management, set
MANAGEMENT_TRUSTED_PROXY_CIDRSonly to that proxy's network ranges and choose the header/mode it actually enforces. Leave it empty for direct access; never trust a broad catch-all range. - Use
ENV=productionorMANAGEMENT_COOKIE_SECURE=truewhen management is accessed over HTTPS. - For API-only management, set
MANAGEMENT_UI_DISABLED=true; the ConnectRPC API and agent Yamux tunnel stay available.
Protect
/data:- Back up the full
CONFIG_DIR. - Restrict host, volume, and backup access to trusted administrators.
- Treat database write access as administrative access, because the local CLI can reset management credentials.
- Protect database backups as secrets; the SQLite database includes operational tokens and upstream credentials.
- Back up the full
Harden agents:
- Store generated agent tokens as secrets.
- Rotate tokens if a host or setup snippet leaks.
- Disable or delete unused agents.
- Use agent mTLS with
MANAGEMENT_TLS_CLIENT_CA_FILEwhen token-only auth is not enough. - Keep
AGENT_ALLOW_INSECURE_MANAGEMENTunset except for isolated development. - Set
AGENT_ALLOW_TARGETSor repeated--allow-targetflags for every required non-loopback destination. With no policy, the agent permits loopback only; useAGENT_ALLOW_ANY_TARGET=trueonly for intentionally unrestricted agents.
Harden public TLS and upstreams:
- Use ACME or trusted manual certificates for public hostnames.
- Avoid relying on fallback self-signed public HTTPS certificates.
- Leave target and forward-auth
tls_skip_verifyoff. It disables certificate-chain, hostname, and expiry checks; a network attacker can impersonate an upstream or an authentication provider. A private network alone does not authenticate the endpoint. - Back up
/data/certs/managementso agents can continue trusting the same management CA after restore. - Before trusting a remote environment's discovered certificate, compare its full SHA-256 fingerprint with the remote server over an independently trusted channel.
Scope WAF, rate-limit, shaper, and cache rules by host/path/method so broad policies do not catch unrelated traffic. Manage each policy type from its own tab under Traffic policy.
Under Traffic policy → Visitor identity, leave trusted-proxy sources disabled unless that source actually connects to the public listener. When enabling one, firewall the origin to the provider's published ranges for a preset or to the administrator-configured peer CIDRs for a custom proxy, so clients cannot bypass the trusted hop.
In the same section, prefer a dedicated single-IP header for custom proxies when the last trusted proxy overwrites it. Use chain parsing only when every trusted hop and its CIDRs are understood.
For geo allow-only rules, keep unknown-country handling on Apply rule unless an intentional fail-open path is required.
Destination and hostname trust
Administrators can configure private, loopback, and public upstreams and forward-auth services. This is required for private service publishing; URL validation is not a server egress allowlist. Treat management credentials as authority to reach the server's network. Use network egress controls where that authority must be constrained, and keep agent destination allowlists narrow. DNS names can resolve to new addresses during normal rotation and failover; direct upstream connections do not pin an address observed during configuration.
The proxy removes incoming forwarding headers and regenerates them from the request and trusted connection context. X-Forwarded-Host still represents a client-selected hostname. Origins must validate accepted hostnames and trust forwarding headers only from p2pstream. Configure explicit Site hostnames and review any remaining standalone catch-all routes during migration; creating one Site does not remove the other routes on a legacy listener.
An unknown TLS SNI can receive a self-signed fallback certificate. That certificate does not grant access to a route and is not trusted by ordinary clients. Provision certificates for the intended names and enforce routing and access policy independently of certificate selection.
Verification
Review:
/datais persistent and backed up.- Management is HTTPS.
- Management exposure is intentional and firewall/VPN rules match that decision.
- First-admin setup token handling is documented for operators.
MANAGEMENT_PUBLIC_URLis correct.- Unused listeners and agents are disabled or deleted.
- Every agent that needs non-loopback access has an explicit destination allowlist, or a documented reason for
AGENT_ALLOW_ANY_TARGET=true. - Tracing is disabled after troubleshooting.
Troubleshooting
| Symptom | Check |
|---|---|
Browser UI returns 404 | MANAGEMENT_UI_DISABLED=true intentionally disables only the browser UI. |
| Agents fail after restore | Restore the old management CA or update agent CA material. |
| Everyone hits one rate-limit bucket | A front proxy may hide client IPs; place p2pstream at the edge, use REMOTE_IP when possible, or use only trusted application headers. Do not key on client-supplied forwarding headers. |
| WAF does not stop network saturation | WAF is HTTP-layer only; use upstream DDoS/network protection. |
| Client-IP headers are spoofed | p2pstream ignores them unless the network peer matches an explicitly trusted source; do not trust broad or catch-all CIDRs. |
| GeoIP is inaccurate | Country data is approximate. Use it as a traffic policy signal, not identity or proof of physical presence. |