diff --git a/.replit b/.replit index 3ed3034..a572720 100644 --- a/.replit +++ b/.replit @@ -14,10 +14,6 @@ run = ["npm", "run", "start"] localPort = 5000 externalPort = 80 -[[ports]] -localPort = 34805 -externalPort = 4200 - [[ports]] localPort = 35345 externalPort = 3002 diff --git a/DOCKER-DATABASE-SSL-GUIDE.md b/DOCKER-DATABASE-SSL-GUIDE.md new file mode 100644 index 0000000..aebf4ac --- /dev/null +++ b/DOCKER-DATABASE-SSL-GUIDE.md @@ -0,0 +1,300 @@ +# PostgreSQL SSL Configuration Guide 🔒 + +## The Issue + +PostgreSQL servers have different SSL requirements: +- Some **require** SSL encryption +- Some **support** SSL but don't require it +- Some **don't support** SSL at all + +Your TaskFlow application now supports all three scenarios via the `DATABASE_SSL` environment variable. + +## How to Configure + +### Option 1: No SSL (Default) + +Use this for: +- ✅ Local PostgreSQL (docker-compose postgres container) +- ✅ PostgreSQL servers without SSL configured +- ✅ Development environments + +**Configuration:** +```yaml +# docker-compose.yml or .env +DATABASE_SSL= # Leave unset or empty +``` + +**Or simply omit the variable entirely.** + +### Option 2: SSL with Self-Signed Certificates + +Use this for: +- ✅ PostgreSQL servers with self-signed certificates +- ✅ Internal/private PostgreSQL servers with SSL +- ✅ Cloud PostgreSQL with SSL enabled + +**Configuration:** +```yaml +# docker-compose.yml or .env +DATABASE_SSL=true +``` + +### Option 3: SSL with Valid CA Certificates + +Use this for: +- ✅ PostgreSQL servers with CA-signed certificates +- ✅ Public cloud databases (AWS RDS, Google Cloud SQL, etc.) +- ✅ Maximum security requirements + +**Configuration:** +```yaml +# docker-compose.yml or .env +DATABASE_SSL=require +``` + +## How to Determine Which Option You Need + +### Test Method 1: Check Error Messages + +**Error: "no encryption" or "requires SSL"** +→ Use `DATABASE_SSL=true` + +**Error: "does not support SSL"** +→ Use `DATABASE_SSL=` (unset) or leave blank + +**Error: "certificate verify failed"** +→ Your server has invalid cert, use `DATABASE_SSL=true` + +**No errors, but want encryption** +→ Try `DATABASE_SSL=true` + +### Test Method 2: Try Connection + +```bash +# Test without SSL +psql "postgresql://user:pass@host:5432/db?sslmode=disable" + +# Test with SSL +psql "postgresql://user:pass@host:5432/db?sslmode=require" +``` + +If the second command works, use `DATABASE_SSL=true` or `DATABASE_SSL=require`. + +## Deployment Scenarios + +### Scenario 1: Using docker-compose.yml (Local PostgreSQL) + +The included PostgreSQL container **does not** have SSL configured. + +**Use:** +```yaml +environment: + DATABASE_URL: postgresql://taskflow:taskflow_password@postgres:5432/taskflow + DATABASE_SSL: # Leave empty (no SSL) +``` + +**Deploy:** +```bash +docker-compose up -d +``` + +### Scenario 2: External PostgreSQL (No SSL) + +Your own PostgreSQL server without SSL. + +**Use:** +```yaml +environment: + DATABASE_URL: postgresql://user:password@your-postgres-server:5432/taskflow + DATABASE_SSL: # Leave empty (no SSL) +``` + +### Scenario 3: External PostgreSQL (With SSL) + +Your own PostgreSQL server with SSL enabled. + +**Use:** +```yaml +environment: + DATABASE_URL: postgresql://user:password@your-postgres-server:5432/taskflow + DATABASE_SSL: true # Enable SSL +``` + +### Scenario 4: Cloud PostgreSQL (AWS RDS, etc.) + +Cloud-hosted databases typically require SSL. + +**Use:** +```yaml +environment: + DATABASE_URL: postgresql://user:password@your-rds-endpoint.amazonaws.com:5432/taskflow + DATABASE_SSL: true # Enable SSL +``` + +## For Your Current Setup + +Based on the error "The server does not support SSL connections", your PostgreSQL server **does not have SSL configured**. + +**Solution:** + +1. **Option A: Keep SSL Disabled (Recommended)** + ```bash + # Don't set DATABASE_SSL or set it to empty + DATABASE_SSL= + ``` + +2. **Option B: Enable SSL on Your PostgreSQL Server** + + If you need encryption, configure your PostgreSQL server to support SSL: + + ```bash + # On your PostgreSQL server + # Edit postgresql.conf + ssl = on + ssl_cert_file = 'server.crt' + ssl_key_file = 'server.key' + + # Restart PostgreSQL + systemctl restart postgresql + ``` + +## How the Code Works + +```typescript +// server/db.ts +let sslConfig: any = false; // Default: no SSL + +if (process.env.DATABASE_SSL === 'true') { + sslConfig = { rejectUnauthorized: false }; // SSL with self-signed certs +} else if (process.env.DATABASE_SSL === 'require') { + sslConfig = { rejectUnauthorized: true }; // SSL with valid certs only +} + +pool = new Pool({ + connectionString: databaseUrl, + ssl: sslConfig, +}); +``` + +## Quick Fix for Your Deployment + +**Update your deployment configuration:** + +```yaml +# If using docker-compose +environment: + - DATABASE_URL=postgresql://taskflow:password@your-host:5432/taskflow + - DATABASE_SSL= # Empty = no SSL + +# Or in your shell/environment +export DATABASE_SSL= +``` + +**Then redeploy:** + +```bash +git add . +git commit -m "Configure PostgreSQL SSL settings" +git push + +# After Drone CI builds +docker pull registry.local.nothaft.cloud/taskflow:latest +docker-compose up -d +``` + +## Expected Success Output + +``` +serving on port 5000 +Checking database schema... +✓ Database schema is up to date +✓ Created default labels +✓ Database initialized successfully +``` + +## Troubleshooting + +### Still Getting SSL Errors? + +1. **Check your DATABASE_URL** + ```bash + echo $DATABASE_URL + # Should not have sslmode parameter + ``` + +2. **Verify DATABASE_SSL is not set** + ```bash + echo $DATABASE_SSL + # Should be empty + ``` + +3. **Test connection manually** + ```bash + psql "$DATABASE_URL" + ``` + +### Connection Refused + +- ✅ Check PostgreSQL is running +- ✅ Check firewall allows port 5432 +- ✅ Check DATABASE_URL has correct host/port + +### Authentication Failed + +- ✅ Check username in DATABASE_URL +- ✅ Check password in DATABASE_URL +- ✅ Check database exists +- ✅ Check user has permissions + +## Security Considerations + +### When to Use SSL + +**Use SSL when:** +- ✅ Connecting over the internet +- ✅ Connecting across networks you don't control +- ✅ Regulatory compliance requires encryption +- ✅ Handling sensitive data + +**SSL not required when:** +- ✅ PostgreSQL and app on same machine +- ✅ Both on same private network +- ✅ Using docker-compose with same network +- ✅ Local development + +### Self-Signed vs CA Certificates + +**`DATABASE_SSL=true` (self-signed)** +- Pro: Works with any SSL certificate +- Con: Doesn't verify server identity +- Use: Internal/private servers + +**`DATABASE_SSL=require` (CA-signed)** +- Pro: Verifies server identity +- Con: Requires valid certificate +- Use: Public cloud, production + +## Production Ready! 🎉 + +Your TaskFlow application now supports: + +✅ **Any PostgreSQL configuration** +✅ **SSL or no SSL** +✅ **Self-signed or CA certificates** +✅ **Flexible deployment options** + +**Status: Production Ready!** 🚀 + +## Summary + +| PostgreSQL Type | DATABASE_SSL Setting | Use Case | +|----------------|---------------------|----------| +| Local docker-compose | _(unset)_ | Default setup | +| Internal server (no SSL) | _(unset)_ | Private network | +| Internal server (with SSL) | `true` | Encrypted internal | +| Cloud database | `true` | AWS RDS, etc. | +| High security | `require` | Valid cert only | + +--- + +**Next Step:** Set `DATABASE_SSL` appropriately for your PostgreSQL server and redeploy! diff --git a/docker-compose.yml b/docker-compose.yml index 7b5bce5..fb8de1a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,6 +34,9 @@ services: NODE_ENV: production DATABASE_URL: postgresql://${POSTGRES_USER:-taskflow}:${POSTGRES_PASSWORD:-taskflow_password}@postgres:5432/${POSTGRES_DB:-taskflow} PORT: 5000 + # DATABASE_SSL options: 'true' (SSL with self-signed), 'require' (SSL with valid cert), or unset (no SSL) + # For local postgres container, leave unset. For external PostgreSQL, set as needed. + DATABASE_SSL: ${DATABASE_SSL:-} ports: - "${APP_PORT:-5000}:5000" depends_on: diff --git a/server/db.ts b/server/db.ts index 85c5592..a2b8d66 100644 --- a/server/db.ts +++ b/server/db.ts @@ -15,11 +15,21 @@ export function getDatabase() { throw new Error('DATABASE_URL environment variable is not set'); } + // Configure SSL based on DATABASE_SSL environment variable + // Values: 'true', 'false', or 'require' + // Default: false (no SSL) + let sslConfig: any = false; + + if (process.env.DATABASE_SSL === 'true') { + sslConfig = { rejectUnauthorized: false }; // SSL with self-signed certs + } else if (process.env.DATABASE_SSL === 'require') { + sslConfig = { rejectUnauthorized: true }; // SSL with valid certs only + } + // Otherwise defaults to false (no SSL) + pool = new Pool({ connectionString: databaseUrl, - ssl: process.env.NODE_ENV === 'production' - ? { rejectUnauthorized: false } // Allow self-signed certificates in production - : false, // No SSL in development + ssl: sslConfig, }); db = drizzle(pool, { schema });