CivStart Environment Setup Guide
This guide covers the setup and management of Development, Staging, and Production environments for the CivStart project.
Table of Contents
- Environment Overview
- Environment Configuration
- Development Environment
- Staging Environment
- Production Environment
- Database Migrations
- Troubleshooting
- Best Practices
Environment Overview
CivStart supports three environments:
| Environment | Purpose | Branch | Database Port | Backend Port | Admin Port | Redis Port |
|---|---|---|---|---|---|---|
| Development | Local development | any | 5433 | 3800 | 3802 | 6380 |
| Staging | Pre-production testing | develop | 5434 | 3100 | 3102 | 6381 |
| Production | Live application | main | 5432 | 3200 | 3002 | 6379 |
Architecture
- Frontend & Admin: Deployed to Vercel (auto-deploys from git branches)
- Backend: Dockerized NestJS API
- Database: PostgreSQL 16 with Prisma ORM
- Cache: Redis 7
- Auth: Clerk (separate keys per environment)
Environment Configuration
1. Set Up Environment Files
Each environment requires its own .env file:
# Create from template
cp .env.template .env # Development
cp .env.template .env.staging # Staging
cp .env.template .env.production # Production
Then customize each file with environment-specific values (see .env.template for all options).
2. Environment Variable Symlinks (Development Only)
For local development, this monorepo uses symlinks so all apps read from a single .env file:
CivStart/
├── .env # ← Root .env (development)
├── apps/
│ ├── frontend/
│ │ └── .env.local # ← Symlink to ../../.env
│ ├── admin/
│ │ └── .env.local # ← Symlink to ../../.env
│ └── backend/
│ └── .env.local # ← Symlink to ../../.env
Create symlinks:
# Automatic (recommended)
pnpm setup
# Or manually
./scripts/setup-env-symlinks.sh
Why symlinks?
- ✅ Single source of truth for environment variables
- ✅ No duplicate .env files across apps
- ✅ Automatic loading by Next.js and NestJS
- ✅ Works with all dev commands
3. Configure Environment Variables
Development (.env)
NODE_ENV=development
DATABASE_URL="postgresql://civstart:civstart_dev_password@localhost:5433/civstart_dev"
REDIS_URL="redis://localhost:6380"
CLERK_SECRET_KEY=sk_test_YOUR_DEV_KEY
Staging (.env.staging)
NODE_ENV=staging
DATABASE_URL="postgresql://civstart:YOUR_STAGING_PASSWORD@localhost:5434/civstart_staging"
REDIS_URL="redis://localhost:6381"
CLERK_SECRET_KEY=sk_test_YOUR_STAGING_KEY
NEXT_PUBLIC_API_URL=https://api-staging.civstart.ventures
Production (.env.production)
NODE_ENV=production
DATABASE_URL="postgresql://civstart:YOUR_STRONG_PASSWORD@localhost:5432/civstart_production"
REDIS_URL="redis://localhost:6379"
CLERK_SECRET_KEY=sk_live_YOUR_PRODUCTION_KEY
NEXT_PUBLIC_API_URL=https://api.civstart.ventures
Important: Never commit real credentials to version control!
4. Gitignore Configuration
Ensure these patterns are in .gitignore:
.env
.env.local
.env.staging
.env.production
apps/*/.env.local
Development Environment
Initial Setup
# Run the complete setup script
pnpm setup
# Or manually:
pnpm install
pnpm db:generate
pnpm docker:dev:up
pnpm db:migrate
Start Development Services
# Start database and Redis only
pnpm docker:dev:db
# Or start all dev services including pgAdmin
pnpm docker:dev:up
# Start application in watch mode
pnpm dev
# Or start specific apps
pnpm dev:frontend # Port 3801
pnpm dev:backend # Port 3800
pnpm dev:admin # Port 3802
Development Commands
# Database operations
pnpm db:generate # Generate Prisma client
pnpm db:push # Push schema changes
pnpm db:migrate # Run migrations
pnpm db:studio # Open Prisma Studio
# Docker operations
pnpm docker:dev:logs # View all logs
pnpm docker:dev:down # Stop services
pnpm docker:shell:db # PostgreSQL shell
# Testing
pnpm test # Run all tests
pnpm test:coverage # Run with coverage
pnpm validate # Full validation suite
Access Development Services
- Frontend: http://localhost:3801
- Backend: http://localhost:3800
- Admin: http://localhost:3802
- pgAdmin: http://localhost:5050 (admin@civstart.com / admin)
- Prisma Studio: Run
pnpm db:studio
Staging Environment
Staging is a production-like environment for testing before deployment.
Initial Setup
-
Create staging environment file:
cp .env.staging.example .env.staging -
Configure Clerk for staging:
- Go to https://dashboard.clerk.com
- Create a new application or use existing test instance
- Copy TEST API keys to
.env.staging
-
Update staging URLs in
.env.staging:NEXT_PUBLIC_API_URL=https://api-staging.civstart.ventures
NEXT_PUBLIC_APP_URL=https://staging.civstart.ventures
Start Staging Environment
# Build and start staging services
pnpm docker:staging:build
pnpm docker:staging:up
# Run database migrations
pnpm docker:staging:migrate
# View logs
pnpm docker:staging:logs
Staging Commands
# Container management
pnpm docker:staging:up # Start all staging services
pnpm docker:staging:down # Stop staging services
pnpm docker:staging:restart # Restart services
pnpm docker:staging:rebuild # Rebuild from scratch
# Logs and debugging
pnpm docker:staging:logs # All logs
pnpm docker:staging:logs:backend # Backend only
pnpm docker:staging:logs:admin # Admin only
pnpm docker:staging:logs:db # Database only
# Database access
pnpm docker:staging:shell:db # PostgreSQL shell
pnpm docker:staging:shell:backend # Backend container shell
# Cleanup
pnpm docker:staging:clean # Remove all staging containers and volumes
Staging Port Mapping
- PostgreSQL:
localhost:5434→postgres-staging:5432 - Redis:
localhost:6381→redis-staging:6379 - Backend API:
localhost:3100→backend-staging:3000 - Admin Panel:
localhost:3102→admin-staging:3002
Configure Vercel for Staging
-
Set up staging deployment:
- Go to Vercel dashboard
- Add your repository
- Configure preview deployments from
developbranch
-
Set environment variables in Vercel:
NEXT_PUBLIC_APP_ENV=staging
NEXT_PUBLIC_API_URL=https://api-staging.civstart.ventures
CLERK_SECRET_KEY=sk_test_...
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
Production Environment
Production is the live environment serving real users.
Prerequisites
- Production server with Docker installed
- Domain configured with DNS pointing to server
- SSL certificates (Let's Encrypt recommended)
- Backup system configured
- Monitoring and alerting setup
Initial Setup
-
Create production environment file:
cp .env.production.example .env.production -
Configure production credentials:
- Use strong, unique passwords for database
- Use LIVE Clerk keys (sklive..., pklive...)
- Set production API keys for all services
- Configure production domain URLs
-
Set up SSL/TLS (recommended: nginx reverse proxy with Let's Encrypt)
Deploy Production Environment
# Build production images
pnpm docker:production:build
# Start production services
pnpm docker:production:up
# Run database migrations
pnpm docker:production:migrate
# Verify health
curl http://localhost:3200/health
Production Commands
# Container management
pnpm docker:production:up # Start production services
pnpm docker:production:down # Stop production services
pnpm docker:production:restart # Restart services
pnpm docker:production:rebuild # Rebuild from scratch
# Logs and monitoring
pnpm docker:production:logs # All logs
pnpm docker:production:logs:backend # Backend only
pnpm docker:production:logs:admin # Admin only
pnpm docker:production:logs:db # Database only
# Database access (use with caution!)
pnpm docker:production:shell:db # PostgreSQL shell
pnpm docker:production:shell:backend # Backend container shell
# Backup and maintenance
pnpm docker:production:backup # Create backup
Production Port Mapping
- PostgreSQL:
localhost:5432→postgres-production:5432 - Redis:
localhost:6379→redis-production:6379 - Backend API:
localhost:3200→backend-production:3000 - Admin Panel:
localhost:3002→admin-production:3002
Configure Vercel for Production
-
Set up production deployment:
- Configure production deployments from
mainbranch - Enable automatic deployments
- Configure production deployments from
-
Set production environment variables in Vercel:
NEXT_PUBLIC_APP_ENV=production
NEXT_PUBLIC_API_URL=https://api.civstart.ventures
CLERK_SECRET_KEY=sk_live_...
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_...
Production Monitoring
The production Docker Compose includes:
- Health checks on all services (30s intervals)
- Restart policies (
unless-stopped) - Resource limits (2 CPU, 2GB RAM for backend)
- Optimized PostgreSQL settings for production workload
Monitor these metrics:
- Container health:
docker ps --format "table {{.Names}}\t{{.Status}}" - Resource usage:
docker stats - Database connections: Check PostgreSQL logs
- API response times: Backend
/healthendpoint
Database Migrations
Development Migrations
# Generate migration from schema changes
pnpm db:migrate
# Or use Docker
pnpm docker:migrate
Staging Migrations
# Run migrations in staging
pnpm docker:staging:migrate
# Verify migration
pnpm docker:staging:shell:db
# Then: SELECT * FROM _prisma_migrations;
Production Migrations
⚠️ Important: Always test migrations in staging first!
# 1. Backup production database first
pnpm docker:production:backup
# 2. Run migration
pnpm docker:production:migrate
# 3. Verify migration success
pnpm docker:production:shell:db
# Then: SELECT * FROM _prisma_migrations ORDER BY finished_at DESC LIMIT 5;
# 4. Test application functionality
curl http://localhost:3000/health
Migration Best Practices
- Always backup before migrating production
- Test migrations in staging first
- Review migration SQL before running
- Have rollback plan ready
- Monitor application after migration
- Use Prisma's migrate commands (not manual SQL)
Troubleshooting
Common Issues
Port Already in Use
# Check what's using the port
lsof -i :5432 # or :5433, :5434
# Kill the process
kill -9 <PID>
# Or use the helper script
./scripts/ensure-ports-free.sh
Database Connection Failed
# Check if PostgreSQL is running
docker ps | grep postgres
# Check logs
pnpm docker:dev:logs:db # Development
pnpm docker:staging:logs:db # Staging
pnpm docker:production:logs:db # Production
# Restart database
docker restart civstart-postgres-dev
Prisma Client Out of Sync
# Regenerate Prisma client
pnpm db:generate
# If using Docker, also regenerate in container
pnpm docker:staging:build
Migration Failed
# Check migration status
pnpm docker:staging:shell:db
SELECT * FROM _prisma_migrations WHERE success = false;
# Roll back if needed (staging only)
# Manually revert in production with extreme caution
Container Won't Start
# Check container logs
docker logs civstart-backend-staging
# Remove and recreate
pnpm docker:staging:down
pnpm docker:staging:clean
pnpm docker:staging:build
pnpm docker:staging:up
Environment Variables Not Loading (Development)
If environment variables aren't loading in development:
# 1. Check symlinks exist
ls -la apps/frontend/.env.local
ls -la apps/admin/.env.local
ls -la apps/backend/.env.local
# 2. Recreate symlinks if missing
./scripts/setup-env-symlinks.sh
# 3. Verify root .env file exists and has values
cat .env
# 4. Clear Next.js cache
rm -rf apps/frontend/.next apps/admin/.next
# 5. Restart dev server
pnpm dev
Health Checks
# Check all services are healthy
docker ps --format "table {{.Names}}\t{{.Status}}"
# Test backend health endpoint
curl http://localhost:3800/health # Dev
curl http://localhost:3100/health # Staging
curl http://localhost:3200/health # Production
# Test Redis connection
docker exec civstart-redis-dev redis-cli ping
Best Practices
Environment Isolation
- Never use production credentials in dev/staging
- Use separate Clerk applications for each environment
- Isolate data - don't connect dev to production databases
- Test with production-like data in staging, but anonymized
Deployment Workflow
Feature Branch → develop → Staging → main → Production
↓ ↓
Auto-deploy to Auto-deploy to
Staging Vercel Production Vercel
- Develop feature on feature branch
- Merge to
develop→ auto-deploys to staging - Test thoroughly in staging
- Merge to
main→ auto-deploys to production - Monitor production for issues
Security Checklist
- Strong, unique passwords for all production services
- SSL/TLS enabled for all public endpoints
- Firewall configured (only necessary ports open)
- Regular security updates for Docker images
- Secrets stored securely (never in git)
- Rate limiting configured
- CORS properly configured
- Audit logs enabled
Backup Strategy
- Automated daily backups of production database
- Retention policy: 30 days minimum
- Test restores regularly (monthly)
- Store backups off-site (different provider)
- Backup before deployments
- Document restore procedures
Monitoring
Recommended monitoring tools:
- Application: Sentry for error tracking
- Uptime: UptimeRobot or similar
- Logs: CloudWatch, Papertrail, or similar
- Metrics: Grafana + Prometheus
- Database: pgAdmin, DataDog
Set up alerts for:
- Service downtime
- High error rates
- Database connection pool exhaustion
- High memory/CPU usage
- Failed deployments
Quick Reference
Environment Commands Cheat Sheet
# Development
pnpm docker:dev:up && pnpm dev
# Staging
pnpm docker:staging:up
pnpm docker:staging:logs
# Production
pnpm docker:production:up
pnpm docker:production:logs
# All environments: check health
curl http://localhost:3800/health # Dev
curl http://localhost:3100/health # Staging
curl http://localhost:3200/health # Production
Port Reference
| Service | Dev | Staging | Production |
|---|---|---|---|
| PostgreSQL | 5433 | 5434 | 5432 |
| Redis | 6380 | 6381 | 6379 |
| Backend | 3800 | 3100 | 3200 |
| Admin | 3802 | 3102 | 3002 |
| Frontend | 3801 | Vercel | Vercel |
Getting Help
- Getting Started: See
README.mdfor quick start and installation - Architecture: See
ARCHITECTURE.mdfor system design and structure - Deployment: See
DEPLOYMENT.mdfor CI/CD and PM2 setup - Testing: See
TEST-CREDENTIALS.mdfor test environment setup - Database: Check
packages/database/README.md - Issues: Report bugs at GitHub Issues
Last Updated: 2025-10-23