What you are actually running
Rereflect is made up of four services that cooperate through a shared network: the Next.js frontend, the FastAPI backend, a Celery worker that processes background jobs, and a Redis broker that connects them. PostgreSQL stores everything durable. All five pieces are described in a single docker-compose.yml that ships with the repository.
Docker Compose handles starting these in the right order, wiring the internal DNS so they can reach each other by name, and giving you a single command to bring the whole stack up or down. If you have Docker Desktop or the Docker Engine plus the Compose plugin installed, you already have everything you need.
- frontend — Next.js 16 app, listens on port 3000.
- backend-api — FastAPI server, listens on port 8000.
- worker — Celery worker, no external port, reads from Redis.
- redis — Broker for background tasks, listens on port 6379 (internal).
- db — PostgreSQL 16, listens on port 5432 (internal by default).
Environment variables you need to set
Before starting the stack you need a .env file. The repository includes a .env.example with every supported variable and a comment describing each one. The mandatory ones for a minimal deployment are small in number.
The two most important values are SECRET_KEY and LLM_ENCRYPTION_KEY. SECRET_KEY signs JWT tokens for your users — generate it with a secure random generator and keep it secret. LLM_ENCRYPTION_KEY encrypts any LLM API keys your users store in the app — it must be exactly 32 bytes encoded as URL-safe base64. Set SELF_HOSTED=true so the app does not try to call Rereflect's own backend for licence checks.
- SECRET_KEY — random string used to sign JWT sessions. Generate with: python -c "import secrets; print(secrets.token_hex(32))"
- LLM_ENCRYPTION_KEY — 32-byte base64 key for encrypting stored LLM credentials. Generate with: python -c "import secrets, base64; print(base64.urlsafe_b64encode(secrets.token_bytes(32)).decode())"
- SELF_HOSTED=true — required flag that enables the self-hosted mode and disables cloud licence checks.
- DATABASE_URL — PostgreSQL connection string. The compose file sets a default using the bundled db service; override it to point at an external database.
- REDIS_URL — Redis connection string. Defaults to the bundled Redis container; override for an external broker.
LLM configuration is optional at this stage. Without it, Rereflect uses VADER for local sentiment analysis. You can add an LLM key later through the settings UI once the stack is running.
Starting the stack
Once your .env file is in place, bringing up Rereflect is a single command from the repository root. Docker Compose will pull the images on first run, then start each service in dependency order.
A few things to watch for on first start: the backend runs Alembic migrations automatically before accepting traffic, so there will be a brief pause before the API responds. The Celery worker waits for Redis to be ready before it starts consuming jobs, which Compose handles through a health check in the compose file. If either service logs a connectivity error in the first ten seconds, that is normal startup sequencing — wait for everything to settle.
- docker compose up -d — starts all services detached.
- docker compose logs -f backend-api — stream backend logs to watch migration progress.
- docker compose ps — confirm all services are in state "running" or "healthy".
- docker compose down — stops and removes containers but preserves volumes (your data survives).
- docker compose down -v — stops everything and deletes volumes (full reset, data is gone).
After the stack is healthy, open http://localhost:3000 in a browser. You should see the Rereflect signup page. Create your first account — the first registered user becomes the owner of the initial organization.
Exposing Rereflect to the internet
By default the stack only binds to localhost. To reach it from other machines — or to serve it publicly — you need a reverse proxy in front of the frontend and API. Nginx, Caddy, and Traefik all work well. The key points: proxy :3000 for the frontend, proxy :8000 for the API (or configure the API_URL environment variable in the frontend to point directly at a public API address), and terminate TLS at the proxy layer.
If you are running on a server with a domain, Caddy handles TLS certificate provisioning automatically with a minimal configuration. Nginx is a reasonable choice if you are comfortable writing server blocks. The compose file does not force either choice — pick whichever fits your existing infrastructure.
- Do not expose PostgreSQL or Redis ports publicly — they are internal services.
- Set CORS_ORIGINS in your .env to match the domain(s) the frontend will be served from.
- If using Caddy, a two-directive Caddyfile with reverse_proxy to the respective ports is sufficient for HTTPS on a domain you control.
Keeping the stack updated
Rereflect is open source and ships new versions as tagged Docker images. To update, pull the new images and restart the stack. Alembic migrations run automatically on restart, so schema changes apply without a manual step.
The safe update sequence is: pull new images, stop the stack, bring it back up. Because Alembic migrations are transactional, an interrupted update leaves the database in its previous valid state. Read the release notes before updating if a release includes a note about breaking migrations or required manual steps.
Pinning image tags in your compose file (rather than using latest) gives you explicit control over when you take updates and lets you roll back by editing a single line.