Skip to content

Troubleshooting

Marc Pope edited this page Jul 26, 2026 · 2 revisions

Troubleshooting

Grouped by symptom. Most reports come down to one of the first three.

No devices appear

Almost always the client's API Server setting, not CortenDesk.

  1. On the client: Settings → Network. API Server must be the console URL, including scheme and port — the same address you open in a browser.
  2. The client must be able to reach it. Test from the machine itself.
  3. 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.

Devices flicker between online and offline

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.

Web client will not connect

Work through these in order.

  1. Are you on HTTPS? The in-browser client cannot work over plain http://. WebCodecs and Web Crypto are both restricted to secure contexts, so the browser blocks them. http://localhost is exempt. This is browser policy and there is no workaround. See Web client requires HTTPS.
  2. Are the wss:// URLs right? They must be reachable from the browser, not from the container. See Reverse proxy and TLS.
  3. Does your proxy forward WebSocket upgrades on /ws/id and /ws/relay?
  4. Check the browser console for a mixed-content or upgrade error — it names the failure directly.
  5. Browser support. The stream requires WebCodecs; use Chrome or Edge.

Testing WebSocket endpoints with curl over HTTPS is misleading. curl negotiates HTTP/2, where the Upgrade header has no meaning, so a perfectly healthy endpoint reports 502 or times out. Use openssl s_client and look for 101 Switching Protocols.

Cannot sign in

  • 2FA device lostphp artisan cortendesk:2fa-reset <username>
  • Emailed sign-in codes required but mail is brokenphp artisan cortendesk:email-verification off
  • Password sign-in hidden and the identity provider is down — set CORTENDESK_OIDC_DISABLED=true in 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.

Sign-in redirects back to the login page over HTTPS

Set SESSION_SECURE_COOKIE=true and make sure APP_URL uses https://.

Email is not sending

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.

Everyone appears to come from the same IP address

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_PROXIES yourself 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 stay "active" forever

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.

Logs grow forever

Retention is 0, which means keep everything, or the scheduler is not running. See above and Audit logs.

Permission errors on start, or "Please provide a valid cache path"

The /data volume is not writable. Recreate it rather than fixing ownership by hand.

Still stuck

Open an issue with your install method, version, and what you have already ruled out from this page.

Clone this wiki locally