Troubleshooting
Start with the smallest failing layer: process, local listener, public TLS route, SAML flow, session, and finally the backend. Keep the instance name, timestamp, and error-page request ID available while investigating.
Protect diagnostic data
Logs can contain user identifiers, client addresses, complete request paths with query strings, referrers, and user agents. Never publish session cookies, SAML responses, passthrough tokens, the dynamic JSON file, or private keys.
Quick triage
| Symptom | First check |
|---|---|
| Service will not start | systemctl status and the first fatal log message |
| Public URL is unreachable | Local listener, edge proxy, DNS, and TLS certificate |
| Repeated redirects | domain, public Host, HTTPS, cookies, and system time |
| SAML error page | IdP metadata, Entity ID, ACS URL, signing, and NameID/attributes |
403 after SAML login | Email, sAMAccountName, or NameID is missing or empty |
502 Proxy Error | proxy.targetURL, backend reachability, and target TLS trust |
| “Loop Detected” | targetURL points back to PassBeyond or its public origin |
| Missing identity headers | Session validity, claim mappings, and direct backend access |
| Wrong client IP | Edge header overwrite and trustedProxies |
| Logout immediately logs in again | IdP session remains active or SLO is not advertised |
| Public route is unexpectedly open | passthroughPaths prefix or a valid passthrough token |
Collect a safe baseline
Replace myapp and the public hostname throughout these examples:
sudo systemctl status passbeyond@myapp.service
sudo journalctl -u passbeyond@myapp.service --since "15 minutes ago" --no-pager
sudo ss -ltnp | grep 8123
curl --fail --show-error https://myapp.example.com/saml/metadata.xml
curl --fail --show-error https://myapp.example.com/saml/certificate.crt \
| openssl x509 -noout -subject -issuer -serial -dates -fingerprint -sha256The metadata check proves basic HTTP availability, not a complete login or backend request. See Logging and monitoring for log categories and safe evidence collection.
Service does not start
Configuration file cannot be loaded
Typical messages include Failed to load configuration, Domain not set, or a YAML parsing error.
Check:
- the systemd instance name maps to
/etc/passbeyond/<instance>.yaml; - the file is readable by the
passbeyonduser; domain, one IdP metadata source,proxy.listenAddress, andproxy.targetURLare set;- indentation uses spaces and nested proxy settings are below
proxy; domaincontains a hostname withouthttps://or a path.
Test file access without printing the contents:
sudo -u passbeyond test -r /etc/passbeyond/myapp.yamlPassBeyond first attempts a complete environment configuration. An incomplete environment set falls back to YAML rather than merging with it. Review configuration loading when systemd overrides or container variables are present.
Dynamic configuration cannot be written
Messages such as Failed to save dynamic configuration usually indicate a missing directory, incorrect ownership, a read-only mount, or two instances using the same file.
sudo install -d -o passbeyond -g passbeyond -m 0750 /var/lib/passbeyond
sudo -u passbeyond test -w /var/lib/passbeyondEvery instance needs a unique configPath. Do not replace a dynamic file just to bypass a permission error: doing so rotates session and SAML keys.
Listener cannot start
bind: address already in use means another process or PassBeyond instance owns the configured address. Inspect it with:
sudo ss -ltnpGive each instance a unique proxy.listenAddress. A port below 1024 also requires privileges that the packaged service intentionally does not have.
IdP metadata problems
Remote metadata fails on first start
The first start needs either a successful idpMetadataURL download or an already valid cache. Verify DNS, outbound HTTPS, the remote status code, system CA trust, and any HTTPS_PROXY or NO_PROXY settings.
sudo -u passbeyond curl --fail --show-error \
https://sso.example.com/path/to/metadata.xml >/dev/nullPassBeyond accepts only an HTTP 200 response, uses a 30-second timeout, and reads at most 10 MiB. A truncated, HTML, or otherwise invalid response fails XML parsing.
Cached metadata is used
A startup warning that refresh failed but cached metadata was loaded is an availability fallback, not a healthy steady state. Restore access to the metadata endpoint and confirm a later SAML IdP metadata updated and cached log message.
Local metadata does not update
idpMetadataFile is read only during startup. Replace the file atomically, verify ownership, and restart the instance. Local mode does not use the remote cache or the 30-minute refresh loop.
Login redirect loop
A loop between the application and /__passbeyond-redirect usually means the application cookie is absent or rejected.
Check all of the following:
- The browser uses
https://and accepts cookies. domainexactly matches the public hostname.- The edge proxy preserves the public
Hostand overwritesX-Forwarded-Protowithhttps. - Server, IdP, proxy, and client clocks are synchronized.
- The browser does not exceed its cookie-size limit because of excessive claims or groups.
- The public request returns to the same hostname and HTTPS port used before login.
Inspect browser developer tools for __passbeyond_session. Do not copy its value into an issue or chat.
SAML authentication fails
Compare the IdP application with the endpoint reference:
| IdP setting | Expected value |
|---|---|
| Entity ID | https://<domain>/saml/metadata |
| ACS URL | https://<domain>/saml/acs |
| SLO URL | https://<domain>/saml/slo |
| NameID format | Transient |
Then verify:
- responses and assertions use the expected signing configuration;
- the IdP metadata contains the current signing certificates;
- encrypted assertions use the certificate currently served by PassBeyond;
samlRequestSigningmatches whether the IdP expects signed authentication requests;- the IdP sends email,
sAMAccountName, or a non-empty NameID; - the assertion validity window agrees with synchronized system time.
Use the request ID displayed on the error page to locate the corresponding SAML-ERROR log record.
SAML succeeds but PassBeyond returns 403
PassBeyond chooses the subject from email, then sAMAccountName, then SAML NameID. If all are empty, it responds with SAML session has no usable subject identifier.
Add one of the supported aliases from the claims reference. Prefer a stable email or account name. A transient NameID may change at the next authentication and is a poor backend identity by itself.
Backend returns 502
Test the target from the PassBeyond host or container network:
curl --fail --show-error http://127.0.0.1:8888/Check the scheme, host, port, DNS, firewall, and target certificate chain. Keep targetDisableSSLVerify: false; install the correct CA rather than permanently bypassing verification.
The error page request ID matches a PROXY-ERROR record containing the underlying network error.
Loop detected
PassBeyond adds X-Passbeyond-Instance-ID and rejects a request that returns to the same instance. This normally means proxy.targetURL points to:
- the public PassBeyond hostname;
- the edge proxy route that sends traffic back to PassBeyond;
- another proxy rule that loops to the same listener.
Point targetURL directly at the backend's private origin.
Backend headers are missing or unexpected
Confirm the request is authenticated rather than allowed through a passthrough rule. Then verify that the backend is reached only through PassBeyond.
PassBeyond removes its own session cookie and client-provided identity headers before adding trusted values. The backend should inspect headers case-insensitively. Multi-valued groups arrive as one comma-separated value.
If X-Passbeyond-User exists but an attribute header does not, compare the IdP's emitted attribute name with the claim aliases. Empty attributes are intentionally omitted.
For Basic-auth integration, proxy.useBasicAuth sends the subject with an empty password. It does not emulate a form login and may not work with applications that require a real password.
Client IP is incorrect
PassBeyond trusts X-Forwarded-For only when the direct peer matches proxy.trustedProxies. It uses the first forwarded address and then overwrites both X-Forwarded-For and X-Real-IP for the backend.
Avoid broad network ranges. Configure the exact edge proxy IP or narrow container subnet, and make the edge proxy overwrite client-supplied forwarding headers.
Passthrough access is too broad
passthroughPaths uses literal prefix matching. /api also matches /api-admin. Prefer a trailing slash such as /api/, test neighboring paths, and never configure /.
Passthrough tokens apply to the entire instance and use:
X-Passbeyond-Authorization: Bearer <token>Rotate a token immediately if it appears in a log, shell history, ticket, or diagnostic capture.
Logout behavior
/saml/slo always clears the local PassBeyond cookie. When the IdP advertises SLO, PassBeyond also starts or processes the IdP logout flow. Without an IdP SLO endpoint, the IdP session remains active and may immediately authenticate the browser again on the next request.
Logout cannot revoke a copied PassBeyond JWT. See Sessions.
Large sessions and headers
All mapped attributes and groups are stored in the browser JWT. Large group sets can exceed browser cookie or edge proxy header limits even though PassBeyond itself permits up to 1 MiB of request headers.
Reduce the attributes and groups emitted by the IdP. Typical symptoms are a missing cookie, 400/431 responses, or a login loop immediately after a successful assertion.
Preparing a support report
Include:
- PassBeyond version or package version;
- deployment type and operating system;
- IdP and backend product versions;
- exact UTC timestamp and request ID;
- sanitized relevant log lines;
- redacted static configuration with domains generalized if necessary;
- expected and actual behavior.
Never include the dynamic JSON file, cookies, SAML assertions, authorization headers, passthrough tokens, private keys, or complete metadata containing internal details.