# Environment Variables Reference Complete guide to environment variables used in Flyer Crawler. ## Configuration by Environment ### Production **Location**: Gitea CI/CD secrets injected during deployment **Path**: `/var/www/flyer-crawler.projectium.com/` **Note**: No `.env` file exists - all variables come from CI/CD ### Test **Location**: Gitea CI/CD secrets + `.env.test` file **Path**: `/var/www/flyer-crawler-test.projectium.com/` **Note**: `.env.test` overrides for test-specific values ### Development Container **Location**: `.env.local` file in project root **Note**: Overrides default DSNs in `compose.dev.yml` ## Required Variables ### Database | Variable | Description | Example | | ------------------ | ---------------------------- | ------------------------------------------ | | `DB_HOST` | PostgreSQL host | `localhost` (dev), `projectium.com` (prod) | | `DB_PORT` | PostgreSQL port | `5432` | | `DB_USER_PROD` | Production database user | `flyer_crawler_prod` | | `DB_PASSWORD_PROD` | Production database password | (secret) | | `DB_DATABASE_PROD` | Production database name | `flyer-crawler-prod` | | `DB_USER_TEST` | Test database user | `flyer_crawler_test` | | `DB_PASSWORD_TEST` | Test database password | (secret) | | `DB_DATABASE_TEST` | Test database name | `flyer-crawler-test` | | `DB_USER` | Dev database user | `postgres` | | `DB_PASSWORD` | Dev database password | `postgres` | | `DB_NAME` | Dev database name | `flyer_crawler_dev` | **Note**: Production and test use separate `_PROD` and `_TEST` suffixed variables. Development uses unsuffixed variables. ### Redis | Variable | Description | Example | | --------------------- | ------------------------- | ------------------------------ | | `REDIS_URL` | Redis connection URL | `redis://localhost:6379` (dev) | | `REDIS_PASSWORD_PROD` | Production Redis password | (secret) | | `REDIS_PASSWORD_TEST` | Test Redis password | (secret) | ### Authentication | Variable | Description | Example | | ---------------------- | -------------------------- | -------------------------------- | | `JWT_SECRET` | JWT token signing key | (minimum 32 characters) | | `SESSION_SECRET` | Session encryption key | (minimum 32 characters) | | `GOOGLE_CLIENT_ID` | Google OAuth client ID | `xxx.apps.googleusercontent.com` | | `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | (secret) | | `GH_CLIENT_ID` | GitHub OAuth client ID | `xxx` | | `GH_CLIENT_SECRET` | GitHub OAuth client secret | (secret) | ### AI Services | Variable | Description | Example | | -------------------------------- | ---------------------------- | ----------- | | `VITE_GOOGLE_GENAI_API_KEY` | Google Gemini API key (prod) | `AIzaSy...` | | `VITE_GOOGLE_GENAI_API_KEY_TEST` | Google Gemini API key (test) | `AIzaSy...` | | `GOOGLE_MAPS_API_KEY` | Google Maps Geocoding API | `AIzaSy...` | ### Application | Variable | Description | Example | | -------------- | ------------------------ | ----------------------------------- | | `NODE_ENV` | Environment mode | `development`, `test`, `production` | | `PORT` | Backend server port | `3001` | | `FRONTEND_URL` | Frontend application URL | `http://localhost:5173` (dev) | ### Error Tracking | Variable | Description | Example | | ---------------------- | -------------------------------- | --------------------------- | | `SENTRY_DSN` | Sentry DSN (production) | `https://xxx@sentry.io/xxx` | | `VITE_SENTRY_DSN` | Frontend Sentry DSN (production) | `https://xxx@sentry.io/xxx` | | `SENTRY_DSN_TEST` | Sentry DSN (test) | `https://xxx@sentry.io/xxx` | | `VITE_SENTRY_DSN_TEST` | Frontend Sentry DSN (test) | `https://xxx@sentry.io/xxx` | | `SENTRY_AUTH_TOKEN` | Sentry API token for releases | (secret) | ## Optional Variables | Variable | Description | Default | | ------------------- | ----------------------- | ----------------- | | `LOG_LEVEL` | Logging verbosity | `info` | | `REDIS_TTL` | Cache TTL in seconds | `3600` | | `MAX_UPLOAD_SIZE` | Max file upload size | `10mb` | | `RATE_LIMIT_WINDOW` | Rate limit window (ms) | `900000` (15 min) | | `RATE_LIMIT_MAX` | Max requests per window | `100` | ## Configuration Files | File | Purpose | | ------------------------------------- | ------------------------------------------- | | `src/config/env.ts` | Zod schema validation - **source of truth** | | `ecosystem.config.cjs` | PM2 process manager config | | `.gitea/workflows/deploy-to-prod.yml` | Production deployment workflow | | `.gitea/workflows/deploy-to-test.yml` | Test deployment workflow | | `.env.example` | Template with all variables | | `.env.local` | Dev container overrides (not in git) | | `.env.test` | Test environment overrides (not in git) | ## Adding New Variables ### 1. Update Zod Schema Edit `src/config/env.ts`: ```typescript const envSchema = z.object({ // ... existing variables ... NEW_VARIABLE: z.string().min(1), }); ``` ### 2. Add to Gitea Secrets For prod/test environments: 1. Go to Gitea repository Settings > Secrets 2. Add `NEW_VARIABLE` with value 3. Add `NEW_VARIABLE_TEST` if test needs different value ### 3. Update Deployment Workflows Edit `.gitea/workflows/deploy-to-prod.yml`: ```yaml env: NEW_VARIABLE: ${{ secrets.NEW_VARIABLE }} ``` Edit `.gitea/workflows/deploy-to-test.yml`: ```yaml env: NEW_VARIABLE: ${{ secrets.NEW_VARIABLE_TEST }} ``` ### 4. Update PM2 Config Edit `ecosystem.config.cjs`: ```javascript module.exports = { apps: [ { env: { NEW_VARIABLE: process.env.NEW_VARIABLE, }, }, ], }; ``` ### 5. Update Documentation - Add to `.env.example` - Update this document - Document in relevant feature docs ## Security Best Practices ### Secrets Management - **NEVER** commit secrets to git - Use Gitea Secrets for prod/test - Use `.env.local` for dev (gitignored) - Rotate secrets regularly ### Secret Generation ```bash # Generate secure random secrets node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" ``` ### Database Users Each environment has its own PostgreSQL user: | Environment | User | Database | | ----------- | -------------------- | -------------------- | | Production | `flyer_crawler_prod` | `flyer-crawler-prod` | | Test | `flyer_crawler_test` | `flyer-crawler-test` | | Development | `postgres` | `flyer_crawler_dev` | **Setup Commands** (as postgres superuser): ```sql -- Production CREATE DATABASE "flyer-crawler-prod"; CREATE USER flyer_crawler_prod WITH PASSWORD 'secure-password'; ALTER DATABASE "flyer-crawler-prod" OWNER TO flyer_crawler_prod; \c "flyer-crawler-prod" ALTER SCHEMA public OWNER TO flyer_crawler_prod; GRANT CREATE, USAGE ON SCHEMA public TO flyer_crawler_prod; CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS postgis; CREATE EXTENSION IF NOT EXISTS pg_trgm; -- Test (similar commands with _test suffix) ``` ## Validation Environment variables are validated at startup via `src/config/env.ts`. If validation fails: 1. Check the error message for missing/invalid variables 2. Verify `.env.local` (dev) or Gitea Secrets (prod/test) 3. Ensure values match schema requirements (min length, format, etc.) ## Troubleshooting ### Variable Not Found ``` Error: Missing required environment variable: JWT_SECRET ``` **Solution**: Add the variable to your environment configuration. ### Invalid Value ``` Error: JWT_SECRET must be at least 32 characters ``` **Solution**: Generate a longer secret value. ### Wrong Environment Selected Check `NODE_ENV` is set correctly: - `development` - Local dev container - `test` - CI/CD test server - `production` - Production server ### Database Connection Issues Verify database credentials: ```bash # Development podman exec flyer-crawler-postgres psql -U postgres -d flyer_crawler_dev -c "SELECT 1;" # Production (via SSH) ssh root@projectium.com "psql -U flyer_crawler_prod -d flyer-crawler-prod -c 'SELECT 1;'" ``` ## Reference - **Validation Schema**: [src/config/env.ts](../../src/config/env.ts) - **Template**: [.env.example](../../.env.example) - **Deployment Workflows**: [.gitea/workflows/](../../.gitea/workflows/) - **PM2 Config**: [ecosystem.config.cjs](../../ecosystem.config.cjs) ## See Also - [QUICKSTART.md](QUICKSTART.md) - Quick setup guide - [INSTALL.md](INSTALL.md) - Detailed installation - [DEPLOYMENT.md](../operations/DEPLOYMENT.md) - Production deployment - [AUTHENTICATION.md](../architecture/AUTHENTICATION.md) - OAuth setup