comprehensive documentation review + test fixes
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 2m15s
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 2m15s
This commit is contained in:
@@ -2,134 +2,259 @@
|
||||
|
||||
Complete guide to environment variables used in Flyer Crawler.
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Minimum Required Variables (Development)
|
||||
|
||||
| Variable | Example | Purpose |
|
||||
| ---------------- | ------------------------ | -------------------- |
|
||||
| `DB_HOST` | `localhost` | PostgreSQL host |
|
||||
| `DB_USER` | `postgres` | PostgreSQL username |
|
||||
| `DB_PASSWORD` | `postgres` | PostgreSQL password |
|
||||
| `DB_NAME` | `flyer_crawler_dev` | Database name |
|
||||
| `REDIS_URL` | `redis://localhost:6379` | Redis connection URL |
|
||||
| `JWT_SECRET` | (32+ character string) | JWT signing key |
|
||||
| `GEMINI_API_KEY` | `AIzaSy...` | Google Gemini API |
|
||||
|
||||
### Source of Truth
|
||||
|
||||
The Zod schema at `src/config/env.ts` is the authoritative source for all environment variables. If a variable is not in this file, it is not used by the application.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
| Aspect | Details |
|
||||
| -------- | ------------------------------------------ |
|
||||
| Location | Gitea CI/CD secrets injected at deployment |
|
||||
| Path | `/var/www/flyer-crawler.projectium.com/` |
|
||||
| File | No `.env` file - all from CI/CD secrets |
|
||||
|
||||
### 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
|
||||
| Aspect | Details |
|
||||
| -------- | --------------------------------------------- |
|
||||
| Location | Gitea CI/CD secrets + `.env.test` overrides |
|
||||
| Path | `/var/www/flyer-crawler-test.projectium.com/` |
|
||||
| File | `.env.test` for test-specific values |
|
||||
|
||||
### Development Container
|
||||
|
||||
**Location**: `.env.local` file in project root
|
||||
**Note**: Overrides default DSNs in `compose.dev.yml`
|
||||
| Aspect | Details |
|
||||
| -------- | --------------------------------------- |
|
||||
| Location | `.env.local` file in project root |
|
||||
| Priority | Overrides defaults in `compose.dev.yml` |
|
||||
| File | `.env.local` (gitignored) |
|
||||
|
||||
## Required Variables
|
||||
---
|
||||
|
||||
### Database
|
||||
## Complete Variable Reference
|
||||
|
||||
| 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` |
|
||||
### Database Configuration
|
||||
|
||||
**Note**: Production and test use separate `_PROD` and `_TEST` suffixed variables. Development uses unsuffixed variables.
|
||||
| Variable | Required | Default | Description |
|
||||
| ------------- | -------- | ------- | ----------------- |
|
||||
| `DB_HOST` | Yes | - | PostgreSQL host |
|
||||
| `DB_PORT` | No | `5432` | PostgreSQL port |
|
||||
| `DB_USER` | Yes | - | Database username |
|
||||
| `DB_PASSWORD` | Yes | - | Database password |
|
||||
| `DB_NAME` | Yes | - | Database name |
|
||||
|
||||
### Redis
|
||||
**Environment-Specific Variables** (Gitea Secrets):
|
||||
|
||||
| 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) |
|
||||
| Variable | Environment | Description |
|
||||
| ------------------ | ----------- | ------------------------ |
|
||||
| `DB_USER_PROD` | Production | Production database user |
|
||||
| `DB_PASSWORD_PROD` | Production | Production database pass |
|
||||
| `DB_DATABASE_PROD` | Production | Production database name |
|
||||
| `DB_USER_TEST` | Test | Test database user |
|
||||
| `DB_PASSWORD_TEST` | Test | Test database password |
|
||||
| `DB_DATABASE_TEST` | Test | Test database name |
|
||||
|
||||
### Redis Configuration
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
| ---------------- | -------- | ------- | ------------------------- |
|
||||
| `REDIS_URL` | Yes | - | Redis connection URL |
|
||||
| `REDIS_PASSWORD` | No | - | Redis password (optional) |
|
||||
|
||||
**URL Format**: `redis://[user:password@]host:port`
|
||||
|
||||
**Examples**:
|
||||
|
||||
```bash
|
||||
# Development (no auth)
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# Production (with auth)
|
||||
REDIS_URL=redis://:${REDIS_PASSWORD_PROD}@localhost:6379
|
||||
```
|
||||
|
||||
### 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) |
|
||||
| Variable | Required | Min Length | Description |
|
||||
| ---------------------- | -------- | ---------- | ----------------------- |
|
||||
| `JWT_SECRET` | Yes | 32 chars | JWT token signing key |
|
||||
| `JWT_SECRET_PREVIOUS` | No | - | Previous key (rotation) |
|
||||
| `GOOGLE_CLIENT_ID` | No | - | Google OAuth client ID |
|
||||
| `GOOGLE_CLIENT_SECRET` | No | - | Google OAuth secret |
|
||||
| `GITHUB_CLIENT_ID` | No | - | GitHub OAuth client ID |
|
||||
| `GITHUB_CLIENT_SECRET` | No | - | GitHub OAuth secret |
|
||||
|
||||
**Generate Secure Secret**:
|
||||
|
||||
```bash
|
||||
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
||||
```
|
||||
|
||||
### 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...` |
|
||||
| Variable | Required | Description |
|
||||
| ---------------------------- | -------- | -------------------------------- |
|
||||
| `GEMINI_API_KEY` | Yes\* | Google Gemini API key |
|
||||
| `GEMINI_RPM` | No | Rate limit (default: 5) |
|
||||
| `AI_PRICE_QUALITY_THRESHOLD` | No | Quality threshold (default: 0.5) |
|
||||
|
||||
### Application
|
||||
\*Required for flyer processing. Application works without it but cannot extract flyer data.
|
||||
|
||||
| Variable | Description | Example |
|
||||
| -------------- | ------------------------ | ----------------------------------- |
|
||||
| `NODE_ENV` | Environment mode | `development`, `test`, `production` |
|
||||
| `PORT` | Backend server port | `3001` |
|
||||
| `FRONTEND_URL` | Frontend application URL | `http://localhost:5173` (dev) |
|
||||
**Get API Key**: [Google AI Studio](https://aistudio.google.com/app/apikey)
|
||||
|
||||
### Error Tracking
|
||||
### Google Services
|
||||
|
||||
| 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) |
|
||||
| Variable | Required | Description |
|
||||
| ---------------------- | -------- | -------------------------------- |
|
||||
| `GOOGLE_MAPS_API_KEY` | No | Google Maps Geocoding API |
|
||||
| `GOOGLE_CLIENT_ID` | No | OAuth (see Authentication above) |
|
||||
| `GOOGLE_CLIENT_SECRET` | No | OAuth (see Authentication above) |
|
||||
|
||||
## Optional Variables
|
||||
### UPC Lookup APIs
|
||||
|
||||
| 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` |
|
||||
| Variable | Required | Description |
|
||||
| ------------------------ | -------- | ---------------------- |
|
||||
| `UPC_ITEM_DB_API_KEY` | No | UPC Item DB API key |
|
||||
| `BARCODE_LOOKUP_API_KEY` | No | Barcode Lookup API key |
|
||||
|
||||
### Application Settings
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
| -------------- | -------- | ------------- | ------------------------ |
|
||||
| `NODE_ENV` | No | `development` | Environment mode |
|
||||
| `PORT` | No | `3001` | Backend server port |
|
||||
| `FRONTEND_URL` | No | - | Frontend URL (CORS) |
|
||||
| `BASE_URL` | No | - | API base URL |
|
||||
| `STORAGE_PATH` | No | (see below) | Flyer image storage path |
|
||||
|
||||
**NODE_ENV Values**: `development`, `test`, `staging`, `production`
|
||||
|
||||
**Default STORAGE_PATH**: `/var/www/flyer-crawler.projectium.com/flyer-images`
|
||||
|
||||
### Email/SMTP Configuration
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
| ----------------- | -------- | ------- | ----------------------- |
|
||||
| `SMTP_HOST` | No | - | SMTP server hostname |
|
||||
| `SMTP_PORT` | No | `587` | SMTP server port |
|
||||
| `SMTP_USER` | No | - | SMTP username |
|
||||
| `SMTP_PASS` | No | - | SMTP password |
|
||||
| `SMTP_SECURE` | No | `false` | Use TLS |
|
||||
| `SMTP_FROM_EMAIL` | No | - | From address for emails |
|
||||
|
||||
**Note**: Email functionality degrades gracefully if not configured.
|
||||
|
||||
### Worker Configuration
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ------------------------------------- | ------- | ---------------------------- |
|
||||
| `WORKER_CONCURRENCY` | `1` | Main worker concurrency |
|
||||
| `WORKER_LOCK_DURATION` | `30000` | Lock duration (ms) |
|
||||
| `EMAIL_WORKER_CONCURRENCY` | `10` | Email worker concurrency |
|
||||
| `ANALYTICS_WORKER_CONCURRENCY` | `1` | Analytics worker concurrency |
|
||||
| `CLEANUP_WORKER_CONCURRENCY` | `10` | Cleanup worker concurrency |
|
||||
| `WEEKLY_ANALYTICS_WORKER_CONCURRENCY` | `1` | Weekly analytics concurrency |
|
||||
|
||||
### Error Tracking (Bugsink/Sentry)
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
| --------------------- | -------- | -------- | ------------------------------- |
|
||||
| `SENTRY_DSN` | No | - | Backend Sentry DSN |
|
||||
| `SENTRY_ENABLED` | No | `true` | Enable error tracking |
|
||||
| `SENTRY_ENVIRONMENT` | No | NODE_ENV | Environment name for errors |
|
||||
| `SENTRY_DEBUG` | No | `false` | Enable Sentry SDK debug logging |
|
||||
| `VITE_SENTRY_DSN` | No | - | Frontend Sentry DSN |
|
||||
| `VITE_SENTRY_ENABLED` | No | `true` | Enable frontend error tracking |
|
||||
| `VITE_SENTRY_DEBUG` | No | `false` | Frontend SDK debug logging |
|
||||
|
||||
**DSN Format**: `http://[key]@[host]:[port]/[project_id]`
|
||||
|
||||
**Dev Container DSNs**:
|
||||
|
||||
```bash
|
||||
# Backend (internal)
|
||||
SENTRY_DSN=http://<key>@localhost:8000/1
|
||||
|
||||
# Frontend (via nginx proxy)
|
||||
VITE_SENTRY_DSN=https://<key>@localhost/bugsink-api/2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration Files
|
||||
|
||||
| File | Purpose |
|
||||
| ------------------------------------- | ------------------------------------------- |
|
||||
| `src/config/env.ts` | Zod schema validation - **source of truth** |
|
||||
| `ecosystem.config.cjs` | PM2 process manager config |
|
||||
| `ecosystem.config.cjs` | PM2 process manager (production) |
|
||||
| `ecosystem.dev.config.cjs` | PM2 process manager (development) |
|
||||
| `.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
|
||||
### Checklist
|
||||
|
||||
1. [ ] **Update Zod Schema** - Edit `src/config/env.ts`
|
||||
2. [ ] **Add to Gitea Secrets** - For prod/test environments
|
||||
3. [ ] **Update Deployment Workflows** - `.gitea/workflows/*.yml`
|
||||
4. [ ] **Update PM2 Config** - `ecosystem.config.cjs`
|
||||
5. [ ] **Update .env.example** - Template for developers
|
||||
6. [ ] **Update this document** - Add to appropriate section
|
||||
|
||||
### Step-by-Step
|
||||
|
||||
#### 1. Update Zod Schema
|
||||
|
||||
Edit `src/config/env.ts`:
|
||||
|
||||
```typescript
|
||||
const envSchema = z.object({
|
||||
// ... existing variables ...
|
||||
NEW_VARIABLE: z.string().min(1),
|
||||
newSection: z.object({
|
||||
newVariable: z.string().min(1, 'NEW_VARIABLE is required'),
|
||||
}),
|
||||
});
|
||||
|
||||
// In loadEnvVars():
|
||||
newSection: {
|
||||
newVariable: process.env.NEW_VARIABLE,
|
||||
},
|
||||
```
|
||||
|
||||
### 2. Add to Gitea Secrets
|
||||
|
||||
For prod/test environments:
|
||||
#### 2. Add to Gitea Secrets
|
||||
|
||||
1. Go to Gitea repository Settings > Secrets
|
||||
2. Add `NEW_VARIABLE` with value
|
||||
2. Add `NEW_VARIABLE` with production value
|
||||
3. Add `NEW_VARIABLE_TEST` if test needs different value
|
||||
|
||||
### 3. Update Deployment Workflows
|
||||
#### 3. Update Deployment Workflows
|
||||
|
||||
Edit `.gitea/workflows/deploy-to-prod.yml`:
|
||||
|
||||
@@ -145,7 +270,7 @@ env:
|
||||
NEW_VARIABLE: ${{ secrets.NEW_VARIABLE_TEST }}
|
||||
```
|
||||
|
||||
### 4. Update PM2 Config
|
||||
#### 4. Update PM2 Config
|
||||
|
||||
Edit `ecosystem.config.cjs`:
|
||||
|
||||
@@ -161,31 +286,36 @@ module.exports = {
|
||||
};
|
||||
```
|
||||
|
||||
### 5. Update Documentation
|
||||
|
||||
- Add to `.env.example`
|
||||
- Update this document
|
||||
- Document in relevant feature docs
|
||||
---
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### Secrets Management
|
||||
### Do
|
||||
|
||||
- **NEVER** commit secrets to git
|
||||
- Use Gitea Secrets for prod/test
|
||||
- Use `.env.local` for dev (gitignored)
|
||||
- Generate secrets with cryptographic randomness
|
||||
- Rotate secrets regularly
|
||||
- Use environment-specific database users
|
||||
|
||||
### Do Not
|
||||
|
||||
- Commit secrets to git
|
||||
- Use short or predictable secrets
|
||||
- Share secrets across environments
|
||||
- Log sensitive values
|
||||
|
||||
### Secret Generation
|
||||
|
||||
```bash
|
||||
# Generate secure random secrets
|
||||
# Generate secure random secrets (64 hex characters)
|
||||
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
||||
|
||||
# Example output:
|
||||
# a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
|
||||
```
|
||||
|
||||
### Database Users
|
||||
|
||||
Each environment has its own PostgreSQL user:
|
||||
### Database Users by Environment
|
||||
|
||||
| Environment | User | Database |
|
||||
| ----------- | -------------------- | -------------------- |
|
||||
@@ -193,44 +323,61 @@ Each environment has its own PostgreSQL user:
|
||||
| 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:
|
||||
Environment variables are validated at startup via `src/config/env.ts`.
|
||||
|
||||
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.)
|
||||
### Startup Validation
|
||||
|
||||
If validation fails, you will see:
|
||||
|
||||
```text
|
||||
╔════════════════════════════════════════════════════════════════╗
|
||||
║ CONFIGURATION ERROR - APPLICATION STARTUP ║
|
||||
╚════════════════════════════════════════════════════════════════╝
|
||||
|
||||
The following environment variables are missing or invalid:
|
||||
|
||||
- database.host: DB_HOST is required
|
||||
- auth.jwtSecret: JWT_SECRET must be at least 32 characters
|
||||
|
||||
Please check your .env file or environment configuration.
|
||||
```
|
||||
|
||||
### Debugging Configuration
|
||||
|
||||
```bash
|
||||
# Check what variables are set (dev container)
|
||||
podman exec flyer-crawler-dev env | grep -E "^(DB_|REDIS_|JWT_|SENTRY_)"
|
||||
|
||||
# Test database connection
|
||||
podman exec flyer-crawler-postgres psql -U postgres -d flyer_crawler_dev -c "SELECT 1;"
|
||||
|
||||
# Test Redis connection
|
||||
podman exec flyer-crawler-redis redis-cli ping
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Variable Not Found
|
||||
|
||||
```
|
||||
```text
|
||||
Error: Missing required environment variable: JWT_SECRET
|
||||
```
|
||||
|
||||
**Solution**: Add the variable to your environment configuration.
|
||||
**Solutions**:
|
||||
|
||||
1. Check `.env.local` exists and has the variable
|
||||
2. Verify variable name matches schema exactly
|
||||
3. Restart the application after changes
|
||||
|
||||
### Invalid Value
|
||||
|
||||
```
|
||||
```text
|
||||
Error: JWT_SECRET must be at least 32 characters
|
||||
```
|
||||
|
||||
@@ -240,32 +387,36 @@ Error: JWT_SECRET must be at least 32 characters
|
||||
|
||||
Check `NODE_ENV` is set correctly:
|
||||
|
||||
- `development` - Local dev container
|
||||
- `test` - CI/CD test server
|
||||
- `production` - Production server
|
||||
| Value | Purpose |
|
||||
| ------------- | ---------------------- |
|
||||
| `development` | Local dev container |
|
||||
| `test` | CI/CD test server |
|
||||
| `staging` | Pre-production testing |
|
||||
| `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;'"
|
||||
# If connection fails, check:
|
||||
# 1. Container is running: podman ps
|
||||
# 2. DB_HOST matches container network
|
||||
# 3. DB_PASSWORD is correct
|
||||
```
|
||||
|
||||
## 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
|
||||
## Related Documentation
|
||||
|
||||
- [QUICKSTART.md](QUICKSTART.md) - Quick setup guide
|
||||
- [INSTALL.md](INSTALL.md) - Detailed installation
|
||||
- [DEV-CONTAINER.md](../development/DEV-CONTAINER.md) - Dev container setup
|
||||
- [DEPLOYMENT.md](../operations/DEPLOYMENT.md) - Production deployment
|
||||
- [AUTHENTICATION.md](../architecture/AUTHENTICATION.md) - OAuth setup
|
||||
- [ADR-007](../adr/0007-configuration-and-secrets-management.md) - Configuration decisions
|
||||
|
||||
---
|
||||
|
||||
Last updated: January 2026
|
||||
|
||||
Reference in New Issue
Block a user