Symptom Cause / fix
Browser/curl rejects the cert Server is on ACME staging (untrusted). Switch off staging + restart, or use curl -k for testing. (Switching staging→production now moves the cached staging cert aside automatically so production re-issues.)
New domain shows a cert warning at first, but works in an incognito window (then your normal profile "catches up") A browser reached the URL before issuance/DNS settled and cached the failure. The client now verifies a browser-trusted certificate is actually being served before it prints Tunnel live — wait for that line, then hard-reload the tab (Cmd/Ctrl-Shift-R) to clear the cached error.
404 no tunnel configured No frontend exists for that Host. Create one (serve).
502 tunnel offline The frontend exists but no client is connected. Start the client; it auto-reconnects.
403 Blocked host (Rails/Django/etc.) Your app rejects the public hostname. Add it to the framework's allowed-hosts (e.g. Rails config.hosts).
First request to a new domain is slow / fails Cert is issuing on demand; ensure DNS points at the server and :80/:443 are reachable.
Too many requests (429) Repeated bad API keys/tokens trigger a temporary per-IP lockout. Wait, then use the correct credential.
Client in Docker logs cannot reach local target SEIKAN_TARGET is dialled from inside the client container. Use the target's service/container name and the port it listens on in that network (app:80), with the client attached to that network — not an address on the docker host. If the target really is a process on the host, host.docker.internal needs extra_hosts: ["host.docker.internal:host-gateway"] (Linux; Docker Desktop has it) and a process not bound to 127.0.0.1 alone.
TCP frontend says "Tunnel live", but its public port refuses connections The port has to be published by the server container as well: it must fall inside both SEIKAN_TCP_RANGE and the ports: range mapped for the server. A port outside the published range binds fine inside the container and is simply unreachable from outside.
Container exits immediately: a frontend for … already exists, and this client key does not own it Another client key owns that domain or port. The server lists a key only its own frontends, so it won't appear in seikan list either — find it in the admin UI (Clients), or point this container somewhere else.
Container restarts every ~30s with unauthorized SEIKAN_API_KEY is wrong or was revoked. The container exits rather than retrying (retrying a bad key just locks the address out), so restart: unless-stopped turns it into a slow loop — fix the key and the next restart picks it up.
SEIKAN_DOMAIN seems to be ignored SEIKAN_TOKEN is also set. A pre-minted token already identifies its frontend, so it and SEIKAN_API_KEY are alternatives; the key wins and the container logs a warning saying the token was ignored.
Two containers keep taking a tunnel from each other Both were given the same domain or port. Each start rotates the connect token, invalidating the other's — run exactly one container per frontend. The one that loses exits with a message naming this cause.
seikan forward connects but every relayed connection is refused/closed No provider is currently connected for that peer frontend — start seikan serve --peer on the box with the actual service. forward itself doesn't need the provider up to connect, only to relay a real connection through.
seikan forward/serve --peer says the token is the wrong role A peer frontend has two independent tokens. serve --peer needs the provider token; forward needs the consumer token (printed once at creation, never re-shown). Using the other one is rejected rather than silently misbehaving.