Skip to content

Environment Management

This document covers environment URLs, infrastructure details, configurations, and management practices.

Environment URLs

Development

QA

Production

Infrastructure Costs

Monthly Breakdown

  • DigitalOcean Droplets: $24 total
    • Dev/QA shared: $6/month (s-1vcpu-1gb)
    • Production: $6/month (s-1vcpu-1gb)
  • Neon Database: $0 (free tier - 0.5GB)
  • Cloudflare: $0 (free tier)
  • Domains: ~$2/month
  • Total: ~$26/month

Droplet Specifications

  • Size: 1 vCPU, 2GB RAM, 50GB SSD
  • OS: Ubuntu 22.04 LTS
  • Region: Toronto (tor1)

Service Locations

Backend (DigitalOcean)

  • AdonisJS API
  • Redis cache
  • PostgreSQL (dev/qa only - local container)
  • Caddy proxy

Frontend (Cloudflare Pages)

  • React web app
  • Next.js marketing site

Database

Development/QA

  • Local PostgreSQL container
  • Separate databases per environment

Production (Neon)

  • Managed PostgreSQL service
  • Automatic backups
  • Connection pooling
  • Free tier (0.5GB storage)

Environment Variables

All environment configuration is managed through env.deploy.yml:

yaml
# Common pattern for all environments
{ ENV }:
  server:
    PORT: 3333
    DATABASE_URL: from_secrets # Becomes {ENV}_SERVER_DATABASE_URL
    NODE_ENV: '{environment}'
  webapp:
    API_URL: 'https://{env}-api.jubiloop.ca'

Environment-Specific Settings

Development:

  • Debug logging enabled
  • Relaxed rate limits (1000/hour)
  • CORS allows localhost
  • Verbose error messages

QA:

  • Production-like settings
  • Standard rate limits (500/hour)
  • CORS restricted to QA domains
  • Structured error logging

Production:

  • Minimal logging
  • Strict rate limits (100/hour)
  • CORS limited to production domains
  • Generic error messages
  • Neon PostgreSQL connection string
  • Backups enabled on droplet

External Service Configuration

Payment Processing (Stripe)

EnvironmentModeWebhook Endpoint
DevelopmentTest modedev-api.jubiloop.ca/webhooks/stripe
QATest modeqa-api.jubiloop.ca/webhooks/stripe
ProductionLive modeapi.jubiloop.ca/webhooks/stripe

Email Service

The platform uses a comprehensive Email Infrastructure with:

EnvironmentResend (Transactional)Brevo (Marketing)
DevelopmentSandbox modeTest lists
QALimited sendingSandbox campaigns
ProductionFull sendingLive campaigns

File Storage (Cloudflare R2)

EnvironmentBucketAccess
Developmentjubiloop-devPublic read for testing
QAjubiloop-qaRestricted access
Productionjubiloop-prodSigned URLs only

Database Management

Development & QA

  • Shared PostgreSQL container on same droplet
  • Separate databases: jubiloop_dev and jubiloop_qa
  • Can be reset anytime
  • Test data seeding scripts available

Production

  • Neon managed PostgreSQL
  • Automated daily backups
  • Point-in-time recovery
  • Connection pooling via pgBouncer

Environment Promotion

Development → QA

  1. Code Freeze: Feature complete on develop
  2. Create PR: From develop to qa
  3. Automated Checks:
    • Tests must pass
    • Linting must pass
    • Build must succeed
  4. Manual Review: Code review required
  5. Merge: Triggers automatic deployment

QA → Production

  1. QA Sign-off: All test cases passed
  2. Create PR: From qa to main
  3. Final Checks:
    • No critical bugs
    • Performance acceptable
    • Security scan passed
  4. Approval: Requires admin approval
  5. Deploy: Merge triggers deployment
  6. Verify: Post-deployment checks

Rollback Procedures

Quick Rollback (< 5 minutes)

bash
# Via GitHub Actions
# 1. Go to Actions tab
# 2. Select "Deploy" workflow
# 3. Click "Run workflow"
# 4. Select previous commit SHA

Database Rollback

For database changes:

  1. Migrations are reversible
  2. Run rollback migration
  3. Deploy previous code version

Environment Isolation

Network Level

  • No cross-environment communication
  • Separate Redis instances
  • Independent service deployments

Data Level

  • No production data in dev/QA
  • Separate secret keys
  • Different API credentials

Access Control

  • Production app requires Zero Trust auth (temporary)
  • Production marketing site is public
  • QA requires Zero Trust auth for all frontend apps
  • Dev requires Zero Trust auth for all frontend apps
  • API endpoints protected by session auth (not Zero Trust)

Monitoring by Environment

Development

  • Basic health checks
  • Docker logs
  • Local debugging tools

QA

  • Uptime monitoring
  • Performance metrics
  • Error tracking (when Sentry added)

Production

  • 24/7 uptime monitoring
  • Real-time alerts
  • Performance tracking
  • Error tracking with Sentry (planned)

Common Tasks

Refresh Dev/QA Database

bash
# SSH to dev-qa server
ssh deploy@dev-qa.jubiloop.ca

# Backup current data (optional)
docker exec postgres pg_dump jubiloop_dev > backup.sql

# Reset database
docker exec postgres psql -c "DROP DATABASE jubiloop_dev;"
docker exec postgres psql -c "CREATE DATABASE jubiloop_dev;"

# Run migrations
docker exec server npm run migration:run

Check Environment Health

bash
# Check all services
curl https://dev-api.jubiloop.ca/health
curl https://qa-api.jubiloop.ca/health
curl https://api.jubiloop.ca/health

View Logs

bash
# Development/QA
ssh deploy@dev-qa.jubiloop.ca
docker logs server-dev -f
docker logs server-qa -f

# Production
ssh deploy@<production-ip>  # Get IP from terraform output
docker logs server -f

Troubleshooting

Environment Not Deploying

  1. Check GitHub Actions for errors
  2. Verify branch protection rules
  3. Check secrets are set correctly
  4. Ensure Docker registry is accessible

Wrong Environment Variables

  1. Check env.deploy.yml is correct
  2. Run npm run generate:env locally
  3. Verify GitHub Secrets match
  4. Restart containers after changes

Database Connection Issues

  1. Check DATABASE_URL is correct
  2. Verify firewall rules
  3. Check connection pool limits
  4. Review PostgreSQL logs

Built with ❤️ by the Jubiloop team