Improve database connection configuration and documentation for SSL
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
Update `docker-compose.yml` and `server/db.ts` to allow dynamic configuration of PostgreSQL SSL connections via the `DATABASE_SSL` environment variable. Add `DOCKER-DATABASE-SSL-GUIDE.md` detailing SSL options and troubleshooting. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ceced2fc-aa46-458d-ba87-ddd4b7bb1518 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/659922a9-0087-461c-90dd-6d9a58b81d4d/ceced2fc-aa46-458d-ba87-ddd4b7bb1518/flNt5I4
This commit is contained in:
@@ -14,10 +14,6 @@ run = ["npm", "run", "start"]
|
|||||||
localPort = 5000
|
localPort = 5000
|
||||||
externalPort = 80
|
externalPort = 80
|
||||||
|
|
||||||
[[ports]]
|
|
||||||
localPort = 34805
|
|
||||||
externalPort = 4200
|
|
||||||
|
|
||||||
[[ports]]
|
[[ports]]
|
||||||
localPort = 35345
|
localPort = 35345
|
||||||
externalPort = 3002
|
externalPort = 3002
|
||||||
|
|||||||
@@ -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!
|
||||||
@@ -34,6 +34,9 @@ services:
|
|||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
DATABASE_URL: postgresql://${POSTGRES_USER:-taskflow}:${POSTGRES_PASSWORD:-taskflow_password}@postgres:5432/${POSTGRES_DB:-taskflow}
|
DATABASE_URL: postgresql://${POSTGRES_USER:-taskflow}:${POSTGRES_PASSWORD:-taskflow_password}@postgres:5432/${POSTGRES_DB:-taskflow}
|
||||||
PORT: 5000
|
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:
|
ports:
|
||||||
- "${APP_PORT:-5000}:5000"
|
- "${APP_PORT:-5000}:5000"
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
+13
-3
@@ -15,11 +15,21 @@ export function getDatabase() {
|
|||||||
throw new Error('DATABASE_URL environment variable is not set');
|
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({
|
pool = new Pool({
|
||||||
connectionString: databaseUrl,
|
connectionString: databaseUrl,
|
||||||
ssl: process.env.NODE_ENV === 'production'
|
ssl: sslConfig,
|
||||||
? { rejectUnauthorized: false } // Allow self-signed certificates in production
|
|
||||||
: false, // No SSL in development
|
|
||||||
});
|
});
|
||||||
|
|
||||||
db = drizzle(pool, { schema });
|
db = drizzle(pool, { schema });
|
||||||
|
|||||||
Reference in New Issue
Block a user