Work out which layer is failing
Most reports fall into one of four layers. Identify the layer first:
# 1. Is the stack up?
docker compose -f docker-compose.prod.yml ps
# 2. Is the API healthy?
curl -fsS https://shellius.example.com/api/health
# 3. Is the host reporting in?
# Portal → the server → last heartbeat
# 4. Is sshd refusing the certificate?
# On the host: journalctl -u ssh --since '10 min ago'The stack will not start
A service restarts in a loop. Read its logs before anything else:
docker compose -f docker-compose.prod.yml logs backend --tail=100The API exits on boot complaining about configuration. Shellius refuses to start with placeholder secrets. Confirm JWT_SECRET, JWT_REFRESH_SECRET, SERVER_ENCRYPTION_KEY, and AGENT_SHARED_SECRET are all real generated values and not the examples.
Migrations fail on first boot. Usually the database was not ready yet. Check Postgres is healthy, then restart the API. If the database has partially migrated, read the error before retrying — do not delete the volume on a deployment that has real data in it.
Sign-in problems
Login works but every API call is rejected. Almost always CORS_ORIGIN or FRONTEND_URL not matching the URL you are actually using, including the scheme and port. They must be the public URL, not the container name.
Sessions drop immediately. If you changed JWT_SECRET, every existing token is invalid. That is expected — sign in again.
SSO returns to the login page. Confirm the redirect URI registered with your identity provider exactly matches the one Shellius shows under Administration → Single sign-on.
Certificate and connection problems
Permission denied (publickey) after bootstrapping. Run through these in order:
sudo sshd -ton the host — is the config valid?- Does
/etc/ssh/shellius_ca.pubmatch the CA public key in the portal? If the CA was rotated after bootstrapping, re-bootstrap the host. - Can the host reach the API?
check-principalsfails closed, so if the call fails no principals are returned and the connection is refused. - Does the certificate's principal match a Unix account the policy granted?
Access was granted but the connection is still refused. Check the certificate has not expired, and that the request is still approved rather than revoked or expired. check-principals re-validates on every connection, so a revocation takes effect immediately.
It worked yesterday and not today. Certificates expire by design. Request access again.
Host never reports reachable
Check the heartbeat timer on the host:
systemctl status shellius-heartbeat.timer
journalctl -u shellius-heartbeat --since '1 hour ago'Then confirm outbound HTTPS to your API hostname works from the host, including through any egress proxy or firewall. Shellius needs no inbound ports on the target, but it does need outbound.
RDP problems
The RDP session fails to open. Check guacd is healthy in the compose stack, and that the target is reachable from the guacd container rather than from your laptop.
Credentials are rejected. RDP passwords are injected server-side and never shown in the portal, so a wrong password has to be fixed on the server record.
Web terminal problems
It connects and then hangs. This is usually a reverse proxy that is not forwarding WebSocket upgrade headers. If you put your own proxy in front of Shellius, it must pass Upgrade and Connection through for the terminal path.
Collecting information for a bug report
docker compose -f docker-compose.prod.yml ps
docker compose -f docker-compose.prod.yml logs backend --tail=200Redact secrets before posting. Never include private keys, certificate contents, tokens, passwords, or a full .env file in an issue.