urmi-ai/docs/ENVIRONMENT.md
2026-10-02 11:22:40 +05:30

260 lines
8.8 KiB
Markdown

# Urmi environment configuration
This document tracks every environment variable, where it lives, and how it flows through local development and Docker.
## Quick start
### Docker Compose (recommended)
```bash
cp .env.example .env
# Edit .env — at minimum set AUTH_SECRET; add Google vars if using Google sign-in
docker compose up --build
```
### Run services outside Docker
```bash
# Terminal 1 — Postgres must already be running (e.g. via compose)
cp backend/.env.example backend/.env
# Terminal 2
cd backend && pip install -r requirements.txt && uvicorn app.main:app --reload
# Terminal 3
cp frontend/.env.example frontend/.env
cd frontend && npm install && npm run dev
```
---
## Env file locations
| File | Used by | Purpose |
|------|---------|---------|
| `.env` (repo root) | Docker Compose | Auth secrets + Google OAuth for the backend container |
| `.env.example` (repo root) | You | Template for Compose |
| `backend/.env` | FastAPI (local run) | Full backend config when not using Compose |
| `backend/.env.example` | You | Template for local backend |
| `frontend/.env` | Vite (local run) | Browser API URL |
| `frontend/.env.example` | You | Template for local frontend |
**There is no committed `.env` file.** Only `.env.example` templates are checked in. Copy the relevant example before running.
---
## How variables flow
### Docker Compose path
```text
.env (repo root)
│
├─► docker-compose.yml ${VAR} substitution
│
└─► backend container environment
│
└─► pydantic Settings in backend/app/config.py
```
Compose **loads** the root `.env` for `${VAR}` substitution in the compose file automatically. The backend service also mounts `.env` via `env_file` when the file exists (`required: false` — stack starts without it).
| Compose env var | Backend setting | Default if unset |
|-----------------|-----------------|------------------|
| `DATABASE_URL` | `database_url` | `postgresql+psycopg://urmi:urmi@postgres:5432/urmi` |
| `FRONTEND_ORIGIN` | `frontend_origin` | `http://localhost:5173` |
| `AUTH_SECRET` | `auth_secret` | `urmi-local-development-secret-change-me` |
| `AUTH_COOKIE_SECURE` | `auth_cookie_secure` | `false` |
| `GOOGLE_CLIENT_ID` | `google_client_id` | empty |
| `GOOGLE_CLIENT_SECRET` | `google_client_secret` | empty |
| `GOOGLE_REDIRECT_URI` | `google_redirect_uri` | `http://localhost:8000/api/v1/auth/google/callback` |
| `ULTRONSMS_BASE_URL` | `ultronsms_base_url` | `https://ultronsms.com` |
| `ULTRONSMS_USER` | `ultronsms_user` | empty |
| `ULTRONSMS_PASSWORD` | `ultronsms_password` | empty |
Frontend in Compose:
| Compose env var | Used by | Default |
|-----------------|---------|---------|
| `VITE_API_URL` | `frontend/src/lib/api.ts` | `http://localhost:8000` |
Postgres in Compose (not read by backend config today — fixed in compose):
| Compose env var | Value |
|-----------------|-------|
| `POSTGRES_DB` | `urmi` |
| `POSTGRES_USER` | `urmi` |
| `POSTGRES_PASSWORD` | `urmi` |
Host port mapping: Postgres is exposed on **5433** (not 5432) to avoid clashing with a local Postgres install.
### Local backend path (no Docker for API)
```text
backend/.env ──or── ../.env (repo root)
│
└─► pydantic Settings (backend/app/config.py)
```
When running from `backend/`:
```bash
uvicorn app.main:app --reload
```
Settings are loaded from environment variables. Pydantic also reads:
1. `backend/.env`
2. `../.env` (repo root)
**Important:** Use host port **5433** in `DATABASE_URL` when Postgres runs via Compose but the API runs on the host:
```text
DATABASE_URL=postgresql+psycopg://urmi:urmi@localhost:5433/urmi
```
Inside the backend container, use the internal service name and port 5432:
```text
DATABASE_URL=postgresql+psycopg://urmi:urmi@postgres:5432/urmi
```
### Local frontend path (no Docker for UI)
```text
frontend/.env
│
└─► VITE_API_URL ──► import.meta.env.VITE_API_URL
```
Vite bakes `VITE_*` variables at dev/build time. Restart the dev server after changing `frontend/.env`.
---
## Backend variables (reference)
Defined in `backend/app/config.py`.
| Variable | Required | Default | Notes |
|----------|----------|---------|-------|
| `APP_NAME` | No | `Urmi API` | OpenAPI title |
| `ENVIRONMENT` | No | `development` | Informational |
| `DATABASE_URL` | Yes* | localhost URL | *Required for real DB access |
| `FRONTEND_ORIGIN` | Yes | `http://localhost:5173` | CORS + OAuth redirect target |
| `AUTH_SECRET` | **Yes in prod** | weak dev default | Signs session JWT cookies |
| `AUTH_COOKIE_SECURE` | No | `false` | Set `true` when served over HTTPS |
| `ACCESS_TOKEN_MINUTES` | No | `10080` (7 days) | Session lifetime |
| `GOOGLE_CLIENT_ID` | For Google login | empty | OAuth client ID |
| `GOOGLE_CLIENT_SECRET` | For Google login | empty | OAuth client secret |
| `GOOGLE_REDIRECT_URI` | For Google login | localhost callback | Must match Google Console |
Pydantic accepts both `SCREAMING_SNAKE` env names and lowercase field names.
---
## Frontend variables (reference)
| Variable | Required | Default | Notes |
|----------|----------|---------|-------|
| `VITE_API_URL` | No | `http://localhost:8000` | All API calls + Google OAuth start URL |
---
## Authentication env checklist
### Email / password only (works out of the box)
- [ ] Copy `.env.example` → `.env` at repo root (Compose) or `backend/.env.example` → `backend/.env` (local API)
- [ ] Set a strong `AUTH_SECRET` before any shared/staging deploy
- [ ] Ensure `FRONTEND_ORIGIN` matches the URL you open in the browser
### Google sign-in
- [ ] Create a **Web application** OAuth client in [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
- [ ] Authorized redirect URI:
```text
http://localhost:8000/api/v1/auth/google/callback
```
- [ ] Set in `.env` / `backend/.env`:
```text
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GOOGLE_REDIRECT_URI=http://localhost:8000/api/v1/auth/google/callback
```
- [ ] Restart backend after changing auth env vars
- [ ] `FRONTEND_ORIGIN` must match where users land after OAuth (default `http://localhost:5173`)
If Google vars are empty, the **Continue with Google** button returns `503 Google sign-in is not configured`.
---
## Infrastructure services (Compose)
These are configured in `docker-compose.yml` today. The backend does **not** consume them yet — documented here for when they are wired.
| Service | Profile | Key env | Host ports |
|---------|---------|---------|------------|
| Postgres | core | `POSTGRES_*` | 5433 → 5432 |
| Redis | core | none | 6379 |
| Kafka | `data-plane` | `KAFKA_CFG_*` | 9092 |
| ClickHouse | `analytics` | none | 8123, 9000 |
| MinIO | `object-storage` | `MINIO_ROOT_USER`, `MINIO_ROOT_PASSWORD` | 9001, 9002 |
Start optional profiles:
```bash
docker compose --profile data-plane --profile analytics --profile object-storage up
```
### Planned backend env (not implemented yet)
| Variable | Purpose |
|----------|---------|
| `REDIS_URL` | Rate limits, OTP state, cache |
| `KAFKA_BOOTSTRAP_SERVERS` | Event bus |
| `CLICKHOUSE_URL` | Analytics ingest |
| `S3_ENDPOINT`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, `S3_BUCKET` | Object storage (MinIO locally) |
---
## Production notes
1. **Never commit `.env`** — only `.env.example` templates.
2. **Rotate `AUTH_SECRET`** — invalidates all sessions when changed.
3. **Set `AUTH_COOKIE_SECURE=true`** behind HTTPS.
4. **Use strong Postgres credentials** — replace compose defaults.
5. **Update `FRONTEND_ORIGIN` and `GOOGLE_REDIRECT_URI`** for your production domain.
6. **Frontend build:** pass `VITE_API_URL` at build time for production API host.
---
## Troubleshooting
| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| `/api/v1/auth/me` 401 after login | Cookie not sent | Same-site: frontend and API origins must work with `credentials: 'include'`; check CORS `FRONTEND_ORIGIN` |
| Google button 503 | Missing OAuth vars | Set `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`, restart backend |
| Google redirect error | Redirect URI mismatch | Match `GOOGLE_REDIRECT_URI` exactly in Google Console |
| Backend can't connect to DB (local API) | Wrong host/port | Use `localhost:5433` when Postgres runs in Docker |
| Backend can't connect to DB (container) | Wrong host | Use `postgres:5432`, not `localhost` |
| Frontend calls wrong API | Stale Vite env | Set `VITE_API_URL` in `frontend/.env`, restart `npm run dev` |
| Changes to root `.env` ignored | Compose not restarted | `docker compose up -d --build backend` |
---
## Maintenance log
| Date | Change |
|------|--------|
| 2026-08-30 | Initial env doc; added `backend/.env.example`, `frontend/.env.example`; expanded root `.env.example` |
When adding new env-dependent features, update:
1. `backend/app/config.py` (or relevant service config)
2. Matching `.env.example` file(s)
3. `docker-compose.yml` if Compose should pass the variable
4. This document