All configuration lives in a single docker/.env file (or surfsense/.env if you used the install script). Copy .env.example to .env and edit the values you need.
Only set these if serving SurfSense on a real domain via a reverse proxy (Caddy, Nginx, Cloudflare Tunnel, etc.). Leave commented out for standard localhost deployments.
Variable
Description
NEXT_FRONTEND_URL
Public frontend URL (e.g. https://app.yourdomain.com)
BACKEND_URL
Public backend URL for OAuth callbacks (e.g. https://api.yourdomain.com)
NEXT_PUBLIC_FASTAPI_BACKEND_URL
Backend URL used by the frontend (e.g. https://api.yourdomain.com)
NEXT_PUBLIC_ELECTRIC_URL
Electric SQL URL used by the frontend (e.g. https://electric.yourdomain.com)
All services start automatically with docker compose up -d.
The backend includes a health check. Dependent services (workers, frontend) wait until the API is fully ready before starting. You can monitor startup progress with docker compose ps (look for (health: starting) → (healthy)).
# View logs (all services)docker compose logs -f# View logs for a specific servicedocker compose logs -f backenddocker compose logs -f electric# Stop all servicesdocker compose down# Restart a specific servicedocker compose restart backend# Stop and remove all containers + volumes (destructive!)docker compose down -v
Ports already in use: Change the relevant *_PORT variable in .env and restart.
Permission errors on Linux: You may need to prefix docker commands with sudo.
Electric SQL not connecting: Check docker compose logs electric. If it shows domain does not exist: db, ensure ELECTRIC_DATABASE_URL is not set to a stale value in .env.
Real-time updates not working in browser: Open DevTools → Console and look for [Electric] errors. Check that NEXT_PUBLIC_ELECTRIC_URL matches the running Electric SQL address.
Line ending issues on Windows: Run git config --global core.autocrlf true before cloning.