Server does not start
- Run
docker compose logs -fand check missing env vars first (SERVER_TOKEN,COMMUNITY_PUBLIC_URL, LiveKit keys). - Verify Postgres connectivity and database exists.
- Confirm migrations path is correct if overridden.
Cannot connect from internet
- Forward ports
80,443,7880,7881, and UDP50000-50060. - Open the same ports in host firewall/security group.
- Confirm DNS points to the current public IP.
- Cannot forward ports at all (CGNAT, a router you do not control)? Put a VPS in front with a WireGuard tunnel.
TLS or domain errors
- Ensure the hostname in
CaddyfilematchesCOMMUNITY_PUBLIC_URL. - Make sure ports
80/443are reachable so certificate issuance can complete. - If using custom certs, check mounted file paths and restart Caddy.
App says the certificate changed
Offgrid on a bare IP address, with no domain. Let's Encrypt will not issue for an IP, so Caddy has to use its own CA. Desktop and mobile ask you to confirm the fingerprint on first connect and then pin it, so a certificate that rotates behind their back reads as an attack and the connection is blocked.
- Do not use a bare
tls internal. The internal CA's default certificate lives only 12 hours, so the app blocks the connection after the first renewal. - Give both the API and the
:7880LiveKit site block a long-lived certificate:tls { issuer internal { lifetime 2160h } }. - Put
pki { ca local { intermediate_lifetime 8760h } }in a global block at the top of theCaddyfile. - The
setup.sh/setup.ps1scripts write all of this for you. This only bites a hand-writtenCaddyfile. - Already pinned the short-lived cert? Fix the
Caddyfile, restart Caddy, then remove and re-add the server in the app so it pins the new one.
The web client cannot do this at all: browsers do not let page JavaScript decide certificate trust. A self-signed Offgrid server needs a manual browser exception, or is desktop and mobile only.
Login or auth fails on community server
- Use a valid JWT in
Authorization: Bearer ...; community-server has no local login endpoint. - Verify
CORE_SERVER_URLis correct and community can fetch/auth/jwk. - If server registration fails, validate
SERVER_TOKENand upstream reachability.
Client calls https://localhost (wrong API host)
- Clients use the
api_urlstored in Core for your server. It comes from community-serverCOMMUNITY_PUBLIC_URLat startup registration. - Set
COMMUNITY_PUBLIC_URLto your real public URL, restart the community-server container, then reopen the app (or switch server) so it refetchesapi_url. - Do not rely on compose defaults for public URL — your
.envmust set the correct domain.
Voice/video issues
- Confirm LiveKit key/secret pair matches both `.env` and `livekit.prod.yaml`.
- Check
wss://...:7880is reachable and proxied. - For strict NAT/firewalls, ensure TURN-related ports are open:
3478/udp(TURN/UDP) and5349/tcp(TURN/TLS). - Some users can't hear each other / one-way audio on join: ensure
5349/tcp(TURN/TLS) is open and reachable. Setup enables TURN/TLS automatically; without a working relay, clients on UDP-blocked or symmetric-NAT networks connect but don't receive some participants' audio.
If issues persist, verify networking, firewall, and TLS settings in your deployment environment.