Docs · Deploy
Serve Watchpost with Caddy
Keep Watchpost private on loopback and let Caddy obtain certificates and terminate public HTTPS.
Start Watchpost
./watchpost --listen 127.0.0.1:8080 --secure-cookiesThe secure-cookie option is required when HTTPS terminates at the proxy. It can also be set with WATCHPOST_SECURE_COOKIES=1.
Caddyfile
watchpost.example.com {
reverse_proxy 127.0.0.1:8080
}Central Watchpost does not use forwarded client-IP or scheme headers for authorization, so no trusted-proxy list is needed or implemented. Its deployment boundary is loopback binding, TLS termination at the proxy, the original Host being preserved, secure cookies, and firewall or network policy. Do not publish port 8080.
Agent remote administration
Remote access to the Watchpost Agent website is optional advanced functionality. The safest documented deployment keeps the agent bound to loopback behind a same-machine reverse proxy. First-run setup over that exposed interface is gated by a temporary bootstrap token supplied through a protected operator-controlled file.
token_dir="${XDG_RUNTIME_DIR:?XDG_RUNTIME_DIR is required}/watchpost-agent"
install -d -m 700 "$token_dir"
umask 077
openssl rand -hex 24 > "$token_dir/setup-token"
WATCHPOST_AGENT_SETUP_TOKEN_FILE="$token_dir/setup-token" \
WATCHPOST_AGENT_SECURE_COOKIES=1 \
WATCHPOST_AGENT_TRUSTED_PROXIES=127.0.0.0/8 \
WATCHPOST_AGENT_ALLOW_CIDRS=192.0.2.0/24 \
watchpost-agent --listen 127.0.0.1:8090agent.example.com {
reverse_proxy 127.0.0.1:8090
}With this loopback listener no non-loopback bind opt-in is needed. XDG_RUNTIME_DIR is a private per-user runtime directory owned by the account that runs Watchpost Agent; the token directory is created mode 700 and the token is written with umask 077, so the file is readable by the agent service account and by no other ordinary user. Only its hash is persisted, the token expires, and it is consumed atomically with first-administrator creation; a supplied token enforces the gate even on loopback. The authorized operator reads the raw token from the protected file over an operator-controlled channel (for example the SSH session) to complete initial setup. After the agent has provisioned the hashed bootstrap token, the source file can be removed (rm "$token_dir/setup-token"); removing it does not remove the already provisioned hash. The token is never returned by any API.
For a system-service deployment, create the directory and file with the same user and group as the service account at install time, never as a root-owned file the service cannot read:
install -d -m 700 -o watchpost-agent -g watchpost-agent /run/watchpost-agent
umask 077
openssl rand -hex 24 > /run/watchpost-agent/setup-token
chown watchpost-agent:watchpost-agent /run/watchpost-agent/setup-tokenEvery header and setting matters: WATCHPOST_AGENT_TRUSTED_PROXIES=127.0.0.0/8 names the same-machine Caddy as the trusted proxy peer whose forwarded scheme, host, and client-address headers may be honoured. Configure the actual proxy-to-agent network, never arbitrary public ranges. WATCHPOST_AGENT_ALLOW_CIDRS/WATCHPOST_AGENT_DENY_CIDRS restrict verified client addresses separately, and WATCHPOST_AGENT_SECURE_COOKIES=1 keeps cookies HTTPS-only. Headers from any peer outside the trusted set are ignored, so a client cannot spoof its origin.
Reverse proxy on another machine (advanced)
A reverse proxy on a different host requires a non-loopback agent listener, explicit opt-in, and a different trust model. Present it only as a separately reviewed deployment:
token_dir="${XDG_RUNTIME_DIR:?XDG_RUNTIME_DIR is required}/watchpost-agent"
install -d -m 700 "$token_dir"
umask 077
openssl rand -hex 24 > "$token_dir/setup-token"
WATCHPOST_AGENT_EXPOSE=1 \
WATCHPOST_AGENT_SETUP_TOKEN_FILE="$token_dir/setup-token" \
WATCHPOST_AGENT_SECURE_COOKIES=1 \
WATCHPOST_AGENT_TRUSTED_PROXIES=203.0.113.5/32 \
WATCHPOST_AGENT_ALLOW_CIDRS=192.0.2.0/24 \
watchpost-agent --listen 10.0.0.7:8090Here WATCHPOST_AGENT_EXPOSE=1 is required because the listener is no longer loopback, and the agent prints a prominent warning. WATCHPOST_AGENT_TRUSTED_PROXIES must name the actual proxy host (for example 203.0.113.5/32), the listener must be reachable only from that proxy, and host firewall policy must be narrowed to the proxy address. The bootstrap token, secure cookies, and client CIDRs apply exactly as in the loopback example. Do not reuse 127.0.0.0/8 here; it would not describe the real peer.
Verify
curl -fsS https://watchpost.example.com/readyzDo not publish port 8080 or 8090. Keep backends bound to their intended interfaces and restrict them with host firewall policy.