-
Notifications
You must be signed in to change notification settings - Fork 4
Troubleshooting
Grouped by symptom. Most reports come down to one of the first three.
Almost always the client's API Server setting, not CortenDesk.
- On the client: Settings → Network. API Server must be the console URL, including scheme and port — the same address you open in a browser.
- The client must be able to reach it. Test from the machine itself.
- Wait one heartbeat, about 15 seconds.
If devices still do not appear:
- Is the approval gate on? With Settings → Server → require device approval enabled, new devices land in a pending tab and are invisible until approved. This looks exactly like nothing happening.
- Was the device deleted? A device in the recycle bin has its heartbeats deliberately ignored, so it will never come back on its own. Restore it.
- Key mismatch. A public key with a stray trailing newline or space fails exactly like a wrong key. Re-paste it with no surrounding whitespace.
Raise Settings → Server → online window (default 60 seconds). A device counts as offline once its last heartbeat is older than that, so lossy links can make devices appear to bounce.
Work through these in order.
-
Do the WebSocket URLs match the page's scheme?
CORTENDESK_WS_ID_URLandCORTENDESK_WS_RELAY_URLmust be reachable from the browser, not from the container, and must bewss://on an HTTPS console — a browser refusesws://from an HTTPS page as mixed content. Over plain HTTP, usews://. HTTPS itself is not required; see Web client and HTTPS. - Is the proxy reachable from the browser? See Reverse proxy and TLS.
-
Does your proxy forward WebSocket upgrades on
/ws/idand/ws/relay? - Check the browser console for a mixed-content or upgrade error — it names the failure directly.
- Browser support. The stream requires WebCodecs; use Chrome or Edge.
Testing WebSocket endpoints with
curlover HTTPS is misleading. curl negotiates HTTP/2, where theUpgradeheader has no meaning, so a perfectly healthy endpoint reports 502 or times out. Useopenssl s_clientand look for101 Switching Protocols.
-
2FA device lost —
php artisan cortendesk:2fa-reset <username> -
Emailed sign-in codes required but mail is broken —
php artisan cortendesk:email-verification off -
Password sign-in hidden and the identity provider is down — set
CORTENDESK_OIDC_DISABLED=truein the environment and restart. Note that a broken-but-still-configured provider does not restore the password form on its own. - Locked out by repeated failures — the sign-in limiter is per account and per address, and clears on its own within a minute.
See the command-line reference.
Set SESSION_SECURE_COOKIE=true and make sure APP_URL uses https://.
Use the test send in Settings → Email — it reports the provider's own error, which is usually conclusive. The two common causes:
- the from address is not one your relay permits, or
- credentials or encryption mode do not match what the relay expects.
Your reverse proxy is not trusted, so the app records the proxy's address instead of the real client's.
The default already trusts loopback and every private range
(127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16), which covers a proxy
on the same host or a Docker bridge. So you normally hit this in one of two
situations:
-
Your proxy reaches the app from a public address — Cloudflare, or an
external load balancer. Add its ranges to
TRUSTED_PROXIES. -
You set
TRUSTED_PROXIESyourself and left out the range your proxy actually arrives from.
Note that TRUSTED_PROXIES must be read at config-cache time, so set it as an
environment variable before the app starts rather than expecting a later change
to be picked up.
Left unfixed this is worse than a cosmetic issue: device last_online_ip is
wrong, and the per-address sign-in limiter treats every user as one address and
starts locking people out. See Reverse proxy and
TLS.
Sessions from machines that rebooted, dropped off the network or had their service stopped are closed by a scheduled sweep. If they accumulate, the scheduler is not running.
Docker runs it automatically. A manual install needs the cron entry:
* * * * * cd /path/to/cortendesk && php artisan schedule:run >> /dev/null 2>&1
The same cron entry drives log pruning, so if logs are also growing without bound, this is the cause.
Retention is 0, which means keep everything, or the scheduler is not running.
See above and Audit logs.
The /data volume is not writable. Recreate it rather than fixing ownership by
hand.
Open an issue with your install method, version, and what you have already ruled out from this page.