Skip to content

Troubleshooting

Brandon Johnson edited this page Sep 7, 2026 · 3 revisions

Troubleshooting

Start with the boot log. Obelo states what it decided at startup — the advertised mDNS address, the resolved transcode backend, the TLS configuration, the tailnet state. Most questions on this page are answered by one line of it.

docker logs obelo          # or: docker compose logs obelo
docker logs -f obelo       # follow

Setup and access

I missed the first-admin claim token. If setup is not complete, restart the server — it is printed on every start while the database has no users. Once the first admin exists, setup permanently closes and the token stops being printed; from then on, users are created by an admin from the users screen.

The web app loads a blank page. You are running a binary built with plain go build instead of make build. The React app is embedded into the binary with go:embed, and the bundle has to be built first. Use make build (or the Docker image).

I have to sign in again on a different address. Expected. http://192.168.1.50:8080 and https://obelo.tail1a2b.ts.net are different origins to a browser, and sessions do not cross origins. Native clients carry their own token and are unaffected.

Libraries and scanning

The scan finds nothing. Check the path is the one the server sees. In Docker that is the container path (/media/movies), not the host path (/srv/media/movies). This is the most common first-run mistake.

Files are found but identified wrongly. Identity comes from the file path and embedded tags, not from a metadata provider — see docs/naming-convention.md for what the parser expects. You can also correct a match by hand, and the correction survives later scans.

Titles vanished after a drive went offline. They are soft-deleted, not gone. Remount the drive and re-scan; the items and their watch state come back.

Nothing has artwork. Enrichment is off until you turn it on, and it needs both consent granted and at least one provider configured. With neither, Obelo makes zero outbound calls and every title shows un-enriched — which is working as designed, not a failure.

I set OBELO_TMDB_API_KEY and restarted, and nothing changed. Provider keys seed the database on first boot only. On an existing install, set it in the admin settings UI — where it also takes effect without a restart. See Configuration.

Playback

Everything transcodes and the CPU is pegged. Check the admin Transcoding tab for the resolved backend, then see Hardware Transcoding. Note the boot log's validation line — a configured backend that did not validate falls back to CPU libx264 with a warning, and keeps working.

The GPU block reads "unavailable". Expected without --gpus all, or on any non-NVENC backend. Telemetry comes from nvidia-smi, which the NVIDIA Container Toolkit injects. The rest of the tab still works.

The GPU works as root but not normally. The container user cannot open the render node. Add the host's render GID: --group-add "$(getent group render | cut -d: -f3)".

The fourth simultaneous stream is refused. OBELO_MAX_CONCURRENT_TRANSCODES defaults to 3. Only full transcodes count against it; direct play and remux are unmetered.

Playback stutters remotely but the LAN is fine. If you are on a tailnet, you have probably fallen back to a DERP relay — see Remote Access with Tailscale.

Discovery

Clients cannot find the server. In Docker, mDNS needs --network host — it is link-local multicast and does not cross a bridge. Then read the boot log's advertising … line. Full flow on LAN Discovery.

dns-sd -B _obelo._tcp local finds nothing on the same Mac as the server. A same-host artifact: macOS's mDNSResponder owns port 5353 and cannot see a second responder on that host. Test from a different machine.

TLS

The server refuses to start after enabling TLS. Deliberate in files mode — a missing, unreadable, or mismatched certificate is a typo you can fix in seconds, and starting anyway would leave you on plain HTTP believing you had TLS. The message names the wrong path. Also check that OBELO_TLS_LISTEN_ADDR differs from OBELO_LISTEN_ADDR.

acme mode starts but there is no certificate. By design: a certificate that cannot be obtained does not stop the server. It keeps serving plain HTTP, logs the reason, and retries. Common causes, in order: DNS not pointed yet, the port forward not set up, external port not exactly 443, CGNAT, or a rate limit from earlier failed attempts.

Nothing happens at boot in acme mode. Correct — issuance is triggered by the first HTTPS handshake for a listed name. Make that handshake from cellular, not house wifi; many routers will not hairpin a connection to your own public address.

Certificates are re-issued on every restart. OBELO_DATA_DIR/acme is not durable. Mount a volume — otherwise you will hit the CA's duplicate-certificate limit within days.

Rate-limited by Let's Encrypt. Production allows five failed authorizations per hostname per hour. Switch to the staging directory (OBELO_ACME_DIRECTORY=https://acme-staging-v02.api.letsencrypt.org/directory), get it working there — the browser warning from the untrusted staging root is the success signal — then switch back.

Remote access

features.tailscale is false. You are running a development build. The embedded node needs -tags tailscale, which the Docker image and make build-release carry and a plain make build does not.

Remote access worked for months and then stopped. Tailscale node keys expire after 180 days by default. Disable key expiry for the node in the Tailscale console; nothing in Obelo can extend it.

The full list is on Remote Access with Tailscale.

Linked servers

A link is unreachable. Their machine is not answering. Nothing is deleted — the libraries stay, badged unavailable, and their titles stay in Continue Watching. Press Sync now; if it persists, ask them. On the Tailscale machine-share path, a node key that expired after 180 days looks exactly like this from your side, and there is no way to see it from here.

A link is revoked. They deleted the linked-server user or its device. Your credential is dead and nothing retries, on purpose. Ask for a fresh invite and press Re-key — the libraries, their local ids and your watch state are all kept.

The invite would not redeem. Every refusal names the next move. "Expired", "already spent" and "unknown" are one message, and all three mean ask for a fresh one — including the case where the sharer pressed Generate invite a second time, which kills the first string.

No libraries arrived, but the link is connected. The sharer granted their linked-server user nothing. That is step 2 on their side; a linked-server user is created with no libraries deliberately.

"Stream limit reached" on one of their titles. Their server refused, not yours — the linked-server user is at its max streams cap and someone else in your household is already watching something of theirs.

Their 4K film plays at 1080p. Their playback ceiling, applied on their machine. Your server never re-encodes anything of theirs; it only carries the bytes, which is also why a relayed stream costs no slot against OBELO_MAX_CONCURRENT_TRANSCODES.

I cannot scan, edit, or enrich a linked library. By design — the other server is the authority for its own files. Renaming it locally is the one exception.

I cannot share a library I received. Also by design, and not a bug to work around. Sharing does not travel.

See Linked Servers for all of it.

Rate limits and client addresses

Everyone in the house shares one login-attempt budget. You are behind a proxy Obelo has not been told about, so every request appears to come from the proxy. Set OBELO_TRUSTED_PROXIES to the proxy's own address — see Reverse Proxy.

The server refuses to start naming an OBELO_TRUSTED_PROXIES entry. The entry is neither an IP address nor a CIDR prefix. Give the proxy's address, e.g. 127.0.0.1/32.


Data and backups

Back up OBELO_DATA_DIR/obelo.db. It holds your libraries, items, hand-edits, users, and watch history.

The caches (artwork/, subtitles/) rebuild themselves and are not worth backing up. acme/ is worth keeping and worth protecting — anyone who can read it can impersonate your server to every client in the house.

Filing a bug

Include the boot log, the build (GET /api/v1/server), how you are running it (Docker flags or compose file, with secrets removed), and what you expected instead. The boot log alone answers a surprising share of questions.

Obelo

Home

Getting started

Reference

Going further

Plugins

Sharing with another household

Reaching it from away

When it breaks

Clone this wiki locally