docs: document runtime env vars and same-origin proxy access

This commit is contained in:
Anish Sarkar 2026-06-16 02:12:11 +05:30
parent 2fb0f0c050
commit 34a49df8a3
5 changed files with 48 additions and 47 deletions

View file

@ -30,6 +30,9 @@ SECRET_KEY=replace_me_with_a_random_string
# Auth type: LOCAL (email/password) or GOOGLE (OAuth) # Auth type: LOCAL (email/password) or GOOGLE (OAuth)
AUTH_TYPE=LOCAL AUTH_TYPE=LOCAL
# Deployment mode: self-hosted enables local filesystem connectors; cloud hides them.
DEPLOYMENT_MODE=self-hosted
# Allow new user registrations (TRUE or FALSE) # Allow new user registrations (TRUE or FALSE)
# REGISTRATION_ENABLED=TRUE # REGISTRATION_ENABLED=TRUE
@ -45,9 +48,8 @@ EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# How You Access SurfSense # How You Access SurfSense
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Default local URL: http://localhost:3929 # One public URL. Browser traffic stays same-origin and Caddy routes internally.
# Most local installs can leave this unchanged. SURFSENSE_PUBLIC_URL=http://localhost:3929
# SURFSENSE_PUBLIC_URL=http://localhost:3929
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public Ports # Public Ports
@ -57,8 +59,8 @@ EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
# #
# Local default: LISTEN_HTTP_PORT=3929 # Local default: LISTEN_HTTP_PORT=3929
# Domain default: LISTEN_HTTP_PORT=80 and LISTEN_HTTPS_PORT=443 # Domain default: LISTEN_HTTP_PORT=80 and LISTEN_HTTPS_PORT=443
# LISTEN_HTTP_PORT=3929 LISTEN_HTTP_PORT=3929
# LISTEN_HTTPS_PORT=443 LISTEN_HTTPS_PORT=443
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Custom Domain / HTTPS # Custom Domain / HTTPS
@ -67,8 +69,8 @@ EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
# Set it to your domain to enable automatic HTTPS: # Set it to your domain to enable automatic HTTPS:
# SURFSENSE_SITE_ADDRESS=surf.example.com # SURFSENSE_SITE_ADDRESS=surf.example.com
# CERT_EMAIL=you@example.com # CERT_EMAIL=you@example.com
# SURFSENSE_SITE_ADDRESS=:80 SURFSENSE_SITE_ADDRESS=:80
# CERT_EMAIL= CERT_EMAIL=
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Advanced Reverse Proxy Settings # Advanced Reverse Proxy Settings
@ -78,18 +80,13 @@ EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
# #
# CERT_ACME_CA=https://acme-v02.api.letsencrypt.org/directory # CERT_ACME_CA=https://acme-v02.api.letsencrypt.org/directory
# CERT_ACME_DNS= # CERT_ACME_DNS=
# If a CDN/load balancer sits in front of Caddy, narrow this to that proxy's CIDRs.
# TRUSTED_PROXIES=0.0.0.0/0 # TRUSTED_PROXIES=0.0.0.0/0
# SURFSENSE_MAX_BODY_SIZE=5GB # SURFSENSE_MAX_BODY_SIZE=5GB
# #
# These browser-facing URLs are derived from SURFSENSE_PUBLIC_URL in # Browser API and Zero URLs are same-origin relative behind bundled Caddy.
# docker-compose.yml: # Next.js server-side calls use Docker DNS through SURFSENSE_BACKEND_INTERNAL_URL
# NEXT_FRONTEND_URL=${SURFSENSE_PUBLIC_URL} # set internally by docker-compose.yml. Usually do not override it.
# BACKEND_URL=${SURFSENSE_PUBLIC_URL}
# NEXT_PUBLIC_FASTAPI_BACKEND_URL=${SURFSENSE_PUBLIC_URL}
# NEXT_PUBLIC_ZERO_CACHE_URL=${SURFSENSE_PUBLIC_URL}/zero
#
# Internal service-to-service URL. Usually do not change.
# FASTAPI_BACKEND_INTERNAL_URL=http://backend:8000
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Zero-cache (real-time sync) # Zero-cache (real-time sync)
@ -485,10 +482,9 @@ NOLOGIN_MODE_ENABLED=FALSE
# FRONTEND_PORT=3000 # FRONTEND_PORT=3000
# ZERO_CACHE_PORT=4848 # ZERO_CACHE_PORT=4848
# -- Frontend build args (dev compose only) -- # -- Frontend runtime flags (prod and dev compose) --
# In dev, the frontend is built from source and these are passed as build args. # The frontend reads these at request time in Docker; no NEXT_PUBLIC_* rebuild
# In prod, runtime values are derived from AUTH_TYPE, ETL_SERVICE, and # or startup substitution is required.
# SURFSENSE_PUBLIC_URL. # AUTH_TYPE=LOCAL
# NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE=LOCAL # ETL_SERVICE=DOCLING
# NEXT_PUBLIC_ETL_SERVICE=DOCLING # DEPLOYMENT_MODE=self-hosted
# NEXT_PUBLIC_DEPLOYMENT_MODE=self-hosted

View file

@ -1,18 +1,17 @@
NEXT_PUBLIC_FASTAPI_BACKEND_URL=http://localhost:8000 # Optional packaged-client override. Leave unset in Docker so browser requests
# use same-origin relative URLs behind Caddy.
# NEXT_PUBLIC_FASTAPI_BACKEND_URL=http://localhost:8000
# Server-only. Internal backend URL used by Next.js server code. # Server-only. Internal backend URL used by Next.js server code.
FASTAPI_BACKEND_INTERNAL_URL=https://your-internal-backend.example.com SURFSENSE_BACKEND_INTERNAL_URL=http://backend:8000
NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE=LOCAL or GOOGLE AUTH_TYPE=LOCAL
NEXT_PUBLIC_ETL_SERVICE=UNSTRUCTURED or LLAMACLOUD or DOCLING ETL_SERVICE=DOCLING
NEXT_PUBLIC_ZERO_CACHE_URL=http://localhost:4848 DEPLOYMENT_MODE=self-hosted
# Contact Form Vars (optional) # Contact Form Vars (optional)
DATABASE_URL=postgresql://postgres:[YOUR-PASSWORD]@db.sdsf.supabase.co:5432/postgres DATABASE_URL=postgresql://postgres:[YOUR-PASSWORD]@db.sdsf.supabase.co:5432/postgres
# Deployment mode (optional)
NEXT_PUBLIC_DEPLOYMENT_MODE="self-hosted" or "cloud"
# PostHog analytics (optional, leave empty to disable) # PostHog analytics (optional, leave empty to disable)
NEXT_PUBLIC_POSTHOG_KEY= NEXT_PUBLIC_POSTHOG_KEY=

View file

@ -26,12 +26,14 @@ The following `.env` variables are **only used by the dev compose file** (they h
| `PGADMIN_DEFAULT_EMAIL` | pgAdmin login email | `admin@surfsense.com` | | `PGADMIN_DEFAULT_EMAIL` | pgAdmin login email | `admin@surfsense.com` |
| `PGADMIN_DEFAULT_PASSWORD` | pgAdmin login password | `surfsense` | | `PGADMIN_DEFAULT_PASSWORD` | pgAdmin login password | `surfsense` |
| `REDIS_PORT` | Exposed Redis port (internal-only in prod) | `6379` | | `REDIS_PORT` | Exposed Redis port (internal-only in prod) | `6379` |
| `NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE` | Frontend build arg for auth type | `LOCAL` | | `AUTH_TYPE` | Runtime auth mode | `LOCAL` |
| `NEXT_PUBLIC_ETL_SERVICE` | Frontend build arg for ETL service | `DOCLING` | | `ETL_SERVICE` | Runtime document parsing service | `DOCLING` |
| `NEXT_PUBLIC_ZERO_CACHE_URL` | Frontend build arg for Zero-cache URL | `http://localhost:4848` | | `DEPLOYMENT_MODE` | Runtime deployment mode | `self-hosted` |
| `NEXT_PUBLIC_DEPLOYMENT_MODE` | Frontend build arg for deployment mode | `self-hosted` | | `ZERO_CACHE_PORT` | Exposed zero-cache port for debugging | `4848` |
In the production compose file, the `NEXT_PUBLIC_*` frontend variables are automatically derived from `AUTH_TYPE`, `ETL_SERVICE`, and the port settings. In the dev compose file, they are passed as build args since the frontend is built from source. In the production compose file, the frontend reads `AUTH_TYPE`, `ETL_SERVICE`,
and `DEPLOYMENT_MODE` at request time. Browser API and Zero traffic are
same-origin relative through bundled Caddy.
Production Docker exposes only the bundled Caddy proxy by default; dev compose Production Docker exposes only the bundled Caddy proxy by default; dev compose
keeps direct service ports so contributors can inspect and restart individual keeps direct service ports so contributors can inspect and restart individual
services without going through the proxy. services without going through the proxy.

View file

@ -35,7 +35,7 @@ zero-cache is included in the Docker Compose setup. The key environment variable
| `SURFSENSE_PUBLIC_URL` | Public SurfSense origin used by the browser | `http://localhost:3929` | | `SURFSENSE_PUBLIC_URL` | Public SurfSense origin used by the browser | `http://localhost:3929` |
| `ZERO_ADMIN_PASSWORD` | Password for the zero-cache admin UI and `/statz` endpoint | `surfsense-zero-admin` | | `ZERO_ADMIN_PASSWORD` | Password for the zero-cache admin UI and `/statz` endpoint | `surfsense-zero-admin` |
| `ZERO_UPSTREAM_DB` | PostgreSQL connection URL for replication | Built from `DB_*` vars | | `ZERO_UPSTREAM_DB` | PostgreSQL connection URL for replication | Built from `DB_*` vars |
| `NEXT_PUBLIC_ZERO_CACHE_URL` | URL the frontend uses to connect to zero-cache | `${SURFSENSE_PUBLIC_URL}/zero` | | `/zero` | Same-origin browser path Caddy routes to zero-cache | `${SURFSENSE_PUBLIC_URL}/zero` |
| `ZERO_APP_PUBLICATIONS` | PostgreSQL publication restricting which tables are replicated | `zero_publication` | | `ZERO_APP_PUBLICATIONS` | PostgreSQL publication restricting which tables are replicated | `zero_publication` |
| `ZERO_NUM_SYNC_WORKERS` | Number of view-sync worker processes. Must be ≤ `ZERO_UPSTREAM_MAX_CONNS` and ≤ `ZERO_CVR_MAX_CONNS` | `4` | | `ZERO_NUM_SYNC_WORKERS` | Number of view-sync worker processes. Must be ≤ `ZERO_UPSTREAM_MAX_CONNS` and ≤ `ZERO_CVR_MAX_CONNS` | `4` |
| `ZERO_UPSTREAM_MAX_CONNS` | Max connections to upstream PostgreSQL for mutations | `20` | | `ZERO_UPSTREAM_MAX_CONNS` | Max connections to upstream PostgreSQL for mutations | `20` |
@ -64,7 +64,7 @@ If running the frontend outside Docker (e.g. `pnpm dev`), you need:
``` ```
Run `uv run alembic upgrade head` from `surfsense_backend/` **before** starting this container so the `zero_publication` exists. Run `uv run alembic upgrade head` from `surfsense_backend/` **before** starting this container so the `zero_publication` exists.
2. **`NEXT_PUBLIC_ZERO_CACHE_URL`** set in `surfsense_web/.env` (default: `http://localhost:4848`). 2. If the frontend is not behind bundled Caddy, set `NEXT_PUBLIC_ZERO_CACHE_URL=http://localhost:4848` before building/running the frontend so the browser connects directly to zero-cache.
3. **`wal_level = logical`** in your PostgreSQL config (see [Manual Installation → Configure PostgreSQL for Zero Sync](/docs/manual-installation#3-configure-postgresql-for-zero-sync)). 3. **`wal_level = logical`** in your PostgreSQL config (see [Manual Installation → Configure PostgreSQL for Zero Sync](/docs/manual-installation#3-configure-postgresql-for-zero-sync)).
For the full manual setup walkthrough, see the [Manual Installation guide](/docs/manual-installation). For the full manual setup walkthrough, see the [Manual Installation guide](/docs/manual-installation).
@ -114,7 +114,7 @@ Zero syncs the following tables for real-time features:
- **zero-cache not starting**: Check `docker compose logs zero-cache`. Ensure PostgreSQL has `wal_level=logical` (configured in `postgresql.conf`). - **zero-cache not starting**: Check `docker compose logs zero-cache`. Ensure PostgreSQL has `wal_level=logical` (configured in `postgresql.conf`).
- **"Insufficient upstream connections" error**: zero-cache defaults `ZERO_NUM_SYNC_WORKERS` to the number of CPU cores, which can exceed connection pool limits on high-core machines. Lower `ZERO_NUM_SYNC_WORKERS` or raise `ZERO_UPSTREAM_MAX_CONNS` / `ZERO_CVR_MAX_CONNS` in your `.env`. - **"Insufficient upstream connections" error**: zero-cache defaults `ZERO_NUM_SYNC_WORKERS` to the number of CPU cores, which can exceed connection pool limits on high-core machines. Lower `ZERO_NUM_SYNC_WORKERS` or raise `ZERO_UPSTREAM_MAX_CONNS` / `ZERO_CVR_MAX_CONNS` in your `.env`.
- **Frontend not syncing**: Open DevTools → Console and check for WebSocket connection errors. In production Docker, verify `NEXT_PUBLIC_ZERO_CACHE_URL` resolves to `${SURFSENSE_PUBLIC_URL}/zero`. - **Frontend not syncing**: Open DevTools → Console and check for WebSocket connection errors. In production Docker, verify Caddy serves `${SURFSENSE_PUBLIC_URL}/zero`. In manual local development, verify `NEXT_PUBLIC_ZERO_CACHE_URL` points at the running zero-cache port.
- **Stale data after restart**: zero-cache rebuilds its SQLite replica from PostgreSQL on startup. This may take a moment for large databases. - **Stale data after restart**: zero-cache rebuilds its SQLite replica from PostgreSQL on startup. This may take a moment for large databases.
## Learn More ## Learn More

View file

@ -546,7 +546,10 @@ cd ../docker
docker compose -f docker-compose.deps-only.yml up -d docker compose -f docker-compose.deps-only.yml up -d
``` ```
The deps-only stack exposes zero-cache on port `4848` by default. Keep `NEXT_PUBLIC_ZERO_CACHE_URL=http://localhost:4848` in your `surfsense_web/.env`. The deps-only stack exposes zero-cache on port `4848` by default. If your
frontend is not behind a reverse proxy that serves `/zero`, set
`NEXT_PUBLIC_ZERO_CACHE_URL=http://localhost:4848` before building/running the
frontend.
## Frontend Setup ## Frontend Setup
@ -577,12 +580,13 @@ Copy-Item -Path .env.example -Destination .env
Edit the `.env` file and set: Edit the `.env` file and set:
| ENV VARIABLE | DESCRIPTION | | ENV VARIABLE | DESCRIPTION |
| ------------------------------- | ------------------------------------------- | | --- | --- |
| NEXT_PUBLIC_FASTAPI_BACKEND_URL | Backend URL (e.g., `http://localhost:8000`) | | `SURFSENSE_BACKEND_INTERNAL_URL` | Backend URL used by Next.js server routes, e.g. `http://localhost:8000` or `http://backend:8000` in Docker |
| NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE | Same value as set in backend AUTH_TYPE i.e `GOOGLE` for OAuth with Google, `LOCAL` for email/password authentication | | `AUTH_TYPE` | Same value as backend auth type: `GOOGLE` for OAuth with Google, `LOCAL` for email/password authentication |
| NEXT_PUBLIC_ETL_SERVICE | Document parsing service (should match backend ETL_SERVICE): `UNSTRUCTURED`, `LLAMACLOUD`, or `DOCLING` - affects supported file formats in upload interface | | `ETL_SERVICE` | Document parsing service (should match backend ETL_SERVICE): `UNSTRUCTURED`, `LLAMACLOUD`, or `DOCLING`; affects supported file formats in the upload interface |
| NEXT_PUBLIC_ZERO_CACHE_URL | URL for Zero-cache real-time sync service (e.g., `http://localhost:4848`) | | `DEPLOYMENT_MODE` | `self-hosted` or `cloud`; controls self-hosted-only connector visibility |
| `NEXT_PUBLIC_ZERO_CACHE_URL` | Only needed when the browser cannot reach Zero through same-origin `/zero`, e.g. manual local dev at `http://localhost:4848` |
### 2. Install Dependencies ### 2. Install Dependencies
@ -693,7 +697,7 @@ To verify your installation:
- **Authentication Problems**: Check your Google OAuth configuration and ensure redirect URIs are set correctly - **Authentication Problems**: Check your Google OAuth configuration and ensure redirect URIs are set correctly
- **LLM Errors**: Confirm your LLM API keys are valid and the selected models are accessible - **LLM Errors**: Confirm your LLM API keys are valid and the selected models are accessible
- **File Upload Failures**: Validate your ETL service API key (Unstructured.io or LlamaCloud) or ensure Docling is properly configured - **File Upload Failures**: Validate your ETL service API key (Unstructured.io or LlamaCloud) or ensure Docling is properly configured
- **Real-time updates not working / stale UI**: Verify zero-cache is running (`curl http://localhost:4848/keepalive` returns 200). Open browser DevTools → Console and look for WebSocket errors. Confirm `NEXT_PUBLIC_ZERO_CACHE_URL` in `surfsense_web/.env` matches the running zero-cache address. - **Real-time updates not working / stale UI**: Verify zero-cache is running (`curl http://localhost:4848/keepalive` returns 200). Open browser DevTools → Console and look for WebSocket errors. In default Docker, confirm `/zero` is routed by Caddy. In manual local development, confirm `NEXT_PUBLIC_ZERO_CACHE_URL` in `surfsense_web/.env` matches the running zero-cache address.
- **Zero-cache stuck on `Unknown or invalid publications. Specified: [zero_publication]`**: You skipped (or never ran) `uv run alembic upgrade head` from `surfsense_backend/`. Run it, then restart the zero-cache container with `docker restart surfsense-zero-cache`. - **Zero-cache stuck on `Unknown or invalid publications. Specified: [zero_publication]`**: You skipped (or never ran) `uv run alembic upgrade head` from `surfsense_backend/`. Run it, then restart the zero-cache container with `docker restart surfsense-zero-cache`.
- **Zero-cache crashes with `_zero.tableMetadata` errors**: A previous run left a half-built SQLite replica behind. Stop the container, remove the volume, and start fresh: `docker rm -f surfsense-zero-cache && docker volume rm surfsense-zero-cache && docker run -d ...` (re-run the command from [Zero-Cache Setup](#zero-cache-setup)). - **Zero-cache crashes with `_zero.tableMetadata` errors**: A previous run left a half-built SQLite replica behind. Stop the container, remove the volume, and start fresh: `docker rm -f surfsense-zero-cache && docker volume rm surfsense-zero-cache && docker run -d ...` (re-run the command from [Zero-Cache Setup](#zero-cache-setup)).
- **`wal_level` is not set to `logical`**: zero-cache requires logical replication. Set `wal_level = logical` in `postgresql.conf`, restart PostgreSQL, and verify with `SHOW wal_level;` in psql. - **`wal_level` is not set to `logical`**: zero-cache requires logical replication. Set `wal_level = logical` in `postgresql.conf`, restart PostgreSQL, and verify with `SHOW wal_level;` in psql.