Hardening¶
The settings to check before an instance faces the internet.
- Keep
-debug-headersoff in production (it exposes upstream addressing). - Keep
-pprofoff unless actively profiling; it is admin-role and admin-scope gated but still needless attack surface when idle. - Leave
GPM_COOKIE_SECUREat itsautodefault. The session cookie becomesSecure(and__Host--prefixed) on its own once the request reaches gpm over TLS, arrives through a trusted proxy assertingX-Forwarded-Proto: https, orsettings.externalBaseURLis anhttps://URL, so a bootstrap login overhttp://127.0.0.1:8081works and the same deployment hardens itself the moment it is fronted. Set1to forceSecureeverywhere and0to force it off;0against anhttps://externalBaseURLis only sane for a deliberate LAN-only plain-HTTP admin listener beside the public URL. - Watch for
cookieSecure: insecure-publiconGET /api/capabilities. It means a session cookie was issued withoutSecureto a routable client address, so it is crossing untrusted networks in the clear; the SPA shows a banner and gpm logs a rate-limited warning.insecure-private(loopback or RFC 1918 / ULA) is the ordinary first-run and LAN case. - If a per-host SSO session may have been exposed (device theft, cookie
leak),
POST /api/sso/revoke(or the button under Settings) invalidates every outstanding SSO session at once; users re-authenticate at the IdP. - Raise the TLS floor once every client can do 1.3:
settings.tls.minVersion: "1.3"covers every host, every stream-terminate listener and an unknown SNI in one place, and any host still serving older clients can pintls.minTLSVersion: "1.2"for itself. - Run with
cap_drop: ALLandno-new-privileges, as in the Compose file. - Put the admin panel behind your ingress / a tunnel, not on the public internet.
- Prefer
${FILE:...}secrets (Docker secrets) over${ENV:...}so values don't show up in the process environment.
What the read-only user role cannot see¶
Handing out a viewer login is bounded by more than "no writes": three read
surfaces are redacted for any caller without the admin scope.
- Deployment paths.
GET /runtimeomitspathsandsecretFileRoots, so a viewer cannot read the config, certificate or session-database locations. - Notification and webhook targets.
GET /webhooks/statusandGET /notifications/statusreduce each URL toscheme://host/(redacted), so a token embedded in a webhook path is not a viewer-readable secret. - Raw upstream errors.
GET /healthreportsacme.lastErroras a classification plus the certificate name, never the provider's own message. - API tokens. The
userrole is*:readminus theapi-tokenssubject, in either direction, andGET /api/configdropsapiTokensfor the same caller.
Full table: What a non-admin caller does not see.