Skip to content

Parallel Environments Implementation Report

⚠️ Historical doc. References infrastructure/scripts/ci-deploy.sh and make deploy-{shared,qual,prod} — both retired in Riff #50 (2026-04-30). Current deploy doctrine: GitLab CI auto-deploys qual on push to main; prod is a manual CI job (Riff #10). See docs/reference/makefile.md for the current Makefile surface.

Date: 2025-01-03
Status: ✅ Configuration Complete


Executive Summary

This report documents the changes made to enable qualification and production environments to run in parallel on the same server, sharing the existing Traefik instance while maintaining complete security and isolation.

Key Achievement: Both environments can now run simultaneously without conflicts, sharing only the Traefik reverse proxy for routing.


Changes Made

1. Network Configuration

Qualification Environment (infrastructure/compose/qualification.yml)

  • ✅ Changed po-traefik-publictraefik (external, existing network)
  • ✅ All internal networks already have -qual suffix
  • ✅ All services already have -qual suffix

Production Environment (infrastructure/compose/production.yml)

  • ✅ Changed po-traefik-publictraefik (external, existing network)
  • ✅ Changed all networks from external to bridge with -prod suffix:
  • po-postgres-networkpo-postgres-network-prod
  • po-redis-networkpo-redis-network-prod
  • po-rabbitmq-networkpo-rabbitmq-network-prod
  • po-elasticsearch-networkpo-elasticsearch-network-prod
  • po-internalpo-internal-prod

2. Infrastructure Services

Production Environment

Added infrastructure services with -prod suffix: - ✅ postgres-prod (container: po-postgres-prod) - ✅ redis-prod (container: po-redis-prod) - ✅ rabbitmq-prod (container: po-rabbitmq-prod) - ✅ elasticsearch-prod (container: po-elasticsearch-prod)

Note: Qualification environment already had infrastructure services defined.

3. Service Naming

Production Environment

All services updated to include -prod suffix: - ✅ public-fo-prod - ✅ strapi-cms-prod - ✅ api-gateway-prod - ✅ keycloak-prod - ✅ auth-service-prod - ✅ user-management-prod - ✅ booking-service-prod - ✅ experience-service-prod - ✅ payment-service-prod - ✅ notification-service-prod - ✅ search-service-prod - ✅ analytics-service-prod - ✅ file-service-prod - ✅ review-service-prod

4. Volume Naming

Production Environment

All volumes updated to include -prod suffix: - ✅ strapi-uploads-prod - ✅ postgres-data-prod - ✅ redis-data-prod - ✅ rabbitmq-data-prod - ✅ elasticsearch-data-prod

5. Environment Variable Updates

Production Environment

All service hostnames updated to include -prod suffix: - ✅ DATABASE_HOST=postgres-prod - ✅ REDIS_URL=redis://redis-prod:6379 - ✅ RABBITMQ_URL=amqp://...@rabbitmq-prod:5672/portugal_odyssey_prod - ✅ ELASTICSEARCH_URL=http://elasticsearch-prod:9200 - ✅ All inter-service URLs updated (e.g., USER_SERVICE_URL=http://user-management-prod:3000)

6. Dependency Updates

Production Environment

All depends_on references updated: - ✅ postgrespostgres-prod - ✅ redisredis-prod - ✅ rabbitmqrabbitmq-prod - ✅ elasticsearchelasticsearch-prod - ✅ keycloakkeycloak-prod - ✅ All service dependencies updated

7. Deployment Scripts

infrastructure/scripts/ci-deploy.sh

  • ✅ Removed separate infrastructure deployment step
  • ✅ Updated to use single compose file (infrastructure services included)
  • ✅ Simplified deployment flow

8. CI/CD Configuration

.gitlab-ci/infrastructure.yml

  • ✅ Updated E2E test job to not use infrastructure.yml
  • ✅ Deployment jobs use correct compose files

Compatibility with Existing Services

Traefik Instance (/opt/traefik-standalone)

Status: ✅ NO CHANGES REQUIRED

Compatibility: - New services use existing traefik network - Traefik auto-discovers services via Docker labels - Router names are unique - Domain names are different - SSL certificates managed by existing Let's Encrypt

Existing Webapp (/opt/experiencias100fim)

Status: ✅ NO CHANGES REQUIRED

Compatibility: - Different container naming (experiencias100fim-* vs po-*-qual/po-*-prod) - Different Traefik router names (x100f-* vs po-*-qual/po-*-prod) - Different domains (*.codecomedy.dev vs *.portugalodyssey.pt) - Same traefik network (compatible) - No port conflicts (all use internal networking)


Isolation Strategy

Network Isolation

Shared Network: traefik (external) - Used by: Traefik, all frontend services, all services with Traefik labels - Purpose: Allow Traefik to route to services

Qualification Internal Networks (isolated): - po-postgres-network-qual - po-redis-network-qual - po-rabbitmq-network-qual - po-elasticsearch-network-qual - po-internal-qual

Production Internal Networks (isolated): - po-postgres-network-prod - po-redis-network-prod - po-rabbitmq-network-prod - po-elasticsearch-network-prod - po-internal-prod

Container Isolation

  • Qualification: All containers have -qual suffix
  • Production: All containers have -prod suffix
  • No naming conflicts possible

Volume Isolation

  • Qualification: All volumes have -qual suffix
  • Production: All volumes have -prod suffix
  • Complete data isolation between environments

Database Isolation

  • Qualification: Separate PostgreSQL instance (po-postgres-qual)
  • Production: Separate PostgreSQL instance (po-postgres-prod)
  • Different database names and credentials

Traefik Routing Isolation

  • Qualification: Router names end with -qual (e.g., public-fo-qual)
  • Production: Router names end with -prod (e.g., public-fo-prod)
  • Domain-based routing ensures no cross-environment access

Deployment Instructions

Initial Setup

  1. Verify Traefik Network:

    docker network ls | grep traefik
    # If missing: docker network create traefik
    

  2. Deploy Qualification:

    cd /opt/po-platform
    docker compose -f infrastructure/compose/qualification.yml \
                   --env-file .env.qual up -d
    

  3. Verify Qualification:

    docker ps | grep po-.*-qual
    curl -I https://api-qual.portugalodyssey.pt/health
    

  4. Deploy Production (while qual is running):

    docker compose -f infrastructure/compose/production.yml \
                   --env-file .env.prod up -d
    

  5. Verify Both Running:

    docker ps | grep po-
    # Should see both qual and prod containers
    

CI/CD Deployment

The GitLab CI/CD pipeline will: 1. Build Docker images 2. Push to GitLab Container Registry 3. SSH to server 4. Pull images 5. Deploy using ci-deploy.sh script


Verification Checklist

After deployment, verify:

  • [ ] Traefik network exists and is accessible
  • [ ] Qualification containers running (docker ps | grep po-.*-qual)
  • [ ] Production containers running (docker ps | grep po-.*-prod)
  • [ ] No container name conflicts (docker ps --format '{{.Names}}' | sort | uniq -d - should be empty)
  • [ ] No volume name conflicts (docker volume ls --format '{{.Name}}' | sort | uniq -d - should be empty)
  • [ ] Qualification endpoints accessible
  • [ ] Production endpoints accessible
  • [ ] Existing webapp still working
  • [ ] Network isolation verified
  • [ ] Traefik routing all services correctly
  • [ ] Health checks passing

Files Modified

Compose Files

  • infrastructure/compose/qualification.yml - Network update
  • infrastructure/compose/production.yml - Comprehensive updates
  • infrastructure/compose/infrastructure.yml - Network reference update

Scripts

  • infrastructure/scripts/ci-deploy.sh - Simplified deployment

CI/CD

  • .gitlab-ci/infrastructure.yml - E2E test update

Documentation

  • docs/parallel-environments-setup.md - Setup guide
  • docs/server-migration-checklist.md - Migration checklist
  • docs/existing-services-compatibility.md - Compatibility report
  • docs/changes-summary.md - Changes summary
  • docs/ci-cd-implementation-guide.md - Updated for same server
  • docs/ci-cd-strategy.md - Updated deployment strategy

Next Steps

  1. Review Configuration: Review all compose files and verify settings
  2. Set Environment Variables: Configure .env.qual and .env.prod files
  3. Test Qualification Deployment: Deploy qualification first and verify
  4. Test Production Deployment: Deploy production while qual is running
  5. Verify Isolation: Confirm environments are properly isolated
  6. Monitor Resources: Monitor server resources with both environments running
  7. Update DNS: Ensure all DNS records point to correct domains

Important Notes

  1. Same Server: Both qual and prod use the same server. Set DEPLOY_QUAL_HOST and DEPLOY_PROD_HOST to the same value in GitLab variables.

  2. Traefik: The existing Traefik instance will automatically discover and route to new services. No configuration changes needed.

  3. Existing Services: No changes required to existing Traefik or webapp. They will continue working as-is.

  4. Isolation: Complete isolation is achieved via Docker networks, container names, volumes, and domain-based routing.

  5. Resource Usage: Monitor server resources as running both environments will increase usage.


Last Updated: 2025-01-03
Status: ✅ Ready for Deployment