Skip to content
Documentation

Troubleshooting

Most problems fall into a handful of shapes. These are the ones people actually hit, with what to check first.

A brand-new install shows a login form, not the setup wizard

PANEL_API_URL is wrong, and this is what it looks like on a first boot.

The panel asks Core whether an admin exists yet. When that call fails it cannot tell, so it falls back to the login page - and you have no account to log in with. Nothing looks broken, which is what makes it hard.

Open the browser console. A 404 on /api/setup/status confirms it. Set PANEL_API_URL to the Core URL a browser can reach, ending in /api (http://<host>:25500/api without a reverse proxy), redeploy and reload.

The panel loads but every request fails

Same cause, later. PANEL_API_URL must be the public Core API URL as the browser sees it, ending in /api. An internal Docker hostname works from inside a container and never from a browser.

Leave it empty only behind a reverse proxy that routes /api to Core.

CORS errors

Core compares the browser's origin literally. https://panel.example.com and https://panel.example.com/ are different strings, and so are http and https. Compare the configured value with what the browser actually sends, character by character.

The console appears frozen

The proxy is buffering. Console output is a streaming response, and a proxy that waits for the response to finish will wait forever. See Reverse proxy.

Valkey will not start

It starts with --aclfile and refuses to run against a missing file. Both stacks in Deployment write that file in the redis service's own entrypoint, so this means either the entrypoint was edited out or REDIS_PASSWORD is unset on that service - an empty password produces an ACL line Valkey rejects.

A Valkey that starts but refuses Core is the other half: the password on the redis service and Core's REDIS_PASSWORD have to be the same value, with no spaces in it.

A node shows offline, or degraded

Check the status page in the admin area first. It distinguishes two things that look alike:

  • offline - the node's heartbeat stopped. The machine or its connection is gone.
  • degraded - the heartbeat is fine, but the control channel to Core is down. The machine is alive and cannot take commands. The page names the reason.

The most common reason for the second is a transport mismatch: GRPC_TLS_ENABLED is on at one end and off at the other. It defaults to on, so a node that was configured before that default changed needs a fresh deploy snippet. See Configuration.

A node will not join

Joining is gated before authentication. If the address allowlist or the join toggle rejects the machine, you get a refusal that has nothing to do with your token being valid. Check the admission settings in the panel first.

The enrolment token is single-use. If a join half-succeeded, generate a fresh snippet rather than re-running the old one.

A setting has no effect

Two candidates, in this order.

The variable is not in the compose file. A .env entry only expands where the compose file references ${VAR}. Confirm with docker compose config.

The variable is set but empty. An empty value overrides the code default; it does not fall back to it. Remove the line entirely instead of leaving it blank.

A Swarm update deployed nothing

docker service update with the same image tag is a no-op. It prints "converged" and changes nothing. Pin a digest or use a new tag, then verify the behaviour actually changed.

Beam transfers are slow

It is not taking the LAN fast path. Beam tries transports in order and takes the first that works, so a slow transfer means the first one was unavailable:

  • On the same network as the node: publish port 25523 in the node's ports: block. Unpublished, there is no direct path to find.
  • Behind NAT, from outside: the LAN path cannot traverse NAT. Either port-forward 25523, or accept the slower hop - a pinned connection to the node on a self-hosted install, the relay with the managed edge.

A node with no pinned certificate fingerprint offers no direct transport at all, by design. Beam will not dial something it cannot verify.

Windows warns about an unknown publisher

Expected. Beam's executable is not Authenticode-signed. Take it only from the official releases page; every automatic update afterwards is signature-verified and fails closed.