A centralized reverse proxy microservice for managing multiple domains and subdomains with automatic SSL certificate management via Let's Encrypt.
✅ Migration Complete (October 31, 2024): SSL certificates and Let's Encrypt data have been migrated from statex-infrastructure to this nginx-microservice. The certificates/ directory now contains:
- Let's Encrypt certificates from
statex-infrastructure/letsencrypt/ - Let's Encrypt account data from
statex-infrastructure/letsencrypt-persistent/ - Webroot content from
statex-infrastructure/webroot/
All SSL management is now centralized in this microservice.
- 🚀 DNS-Based Container Discovery: Automatically discovers containers via Docker DNS
- 🔒 Automatic SSL Certificates: Smart certificate requesting and renewal via Let's Encrypt
- 📁 Host-First Storage: All files stored on host filesystem for reliability
- 🔄 Dynamic Configuration: Add domains by simply adding config files
- 📊 Certificate Caching: Reduces Let's Encrypt API calls by caching certificates locally
- 🤖 Automated Renewal: Certificates renewed automatically via systemd timer or cron
- 📝 Comprehensive Logging: Access and error logs for all domains
- 🎯 Container Independence: Nginx starts and runs independently of container state - configs generated from registry, not container state
- 📋 Automatic Service Registry: Service registry files are automatically created/updated during deployment
- 🏠 Default Landing Page: Automatically sets up a professional welcome page with SSL certificate on new deployments
- 🔀 API Routes Registration: Universal system for registering custom API routes that bypass generic
/api/interception
This service is production-ready and should NOT be modified directly.
- ✅ Allowed: Use scripts from this service's directory
- ❌ NOT Allowed: Modify code, configuration, or infrastructure directly
⚠️ Permission Required: If you need to modify something, ask for permission first
DO NOT create service-registry.json files in individual service codebases!
- Service registry files are automatically created and managed by the deployment script (
deploy-smart.sh) - They are stored in
nginx-microservice/service-registry/directory - The deployment script auto-detects service configuration from docker-compose files and environment variables
- Nginx configurations are automatically generated from service registry files
For complete documentation, see Service Registry Documentation.
nginx-microservice/
├── nginx/ # Nginx configuration and Dockerfile
├── certbot/ # Certbot scripts for certificate management
├── scripts/ # Management scripts (add-domain, remove-domain, etc.)
│ ├── common/ # Modular utility functions (registry, state, config, nginx, etc.)
│ ├── blue-green/ # Blue/green deployment scripts
│ └── ... # Service management scripts
├── certificates/ # SSL certificates (host storage)
├── logs/ # Log files (host storage)
└── webroot/ # Let's Encrypt challenge files
The scripts are organized into a modular architecture for maintainability:
Common Modules (scripts/common/):
output.sh- Unified output formatting (colors, status messages)registry.sh- Service registry functions (load, query)state.sh- State management (blue/green state tracking)config.sh- Config generation (upstream blocks, proxy locations)nginx.sh- Nginx management (validation, testing, reloading)containers.sh- Container management (port checking, container cleanup)network.sh- Network functions (HTTPS checks)diagnostics.sh- Diagnostic functionsfault-tolerance.sh- Tiered failure handling (infrastructure vs applications)
Blue/Green Utilities (scripts/blue-green/utils.sh):
- Acts as a module loader that sources all common modules
- Provides blue/green specific logging (
log_message) - Maintains backward compatibility with existing scripts
Benefits:
- ✅ Modular: Functions organized by concern (registry, state, config, etc.)
- ✅ Maintainable: Small, focused modules instead of one large file
- ✅ Reusable: Common functions can be used across all scripts
- ✅ Testable: Each module can be tested independently
- ✅ Backward Compatible: Existing scripts continue working via
utils.shloader
Infrastructure Service (reverse proxy and SSL termination)
| Service | Port | Description |
|---|---|---|
| Nginx HTTP | 80 | HTTP reverse proxy (exposed on host) |
| Nginx HTTPS | 443 | HTTPS reverse proxy with SSL termination (exposed on host) |
Note:
- Ports 80 and 443 are exposed on all interfaces (0.0.0.0) for external access
- Nginx acts as reverse proxy for all services in the ecosystem
- Nginx connects to application services via Docker DNS using container ports (not host ports)
- SSL certificates managed automatically via Let's Encrypt/Certbot
git clone <repository-url>
cd nginx-microservice
cp .env.example .env
# Edit .env with your settingsdocker compose up -d./scripts/add-domain.sh statex.cz statex.cz 3000./scripts/setup-cert-renewal.sh./scripts/add-domain.sh <domain> <container-name> [port] [email]Examples:
# Basic usage
./scripts/add-domain.sh example.com my-app
# With custom port
./scripts/add-domain.sh example.com my-app 3602
# With custom email
./scripts/add-domain.sh example.com my-app 3000 admin@example.com
# Subdomain
./scripts/add-domain.sh subdomain.example.com my-app 3000./scripts/remove-domain.sh <domain> [--remove-cert]Examples:
# Remove domain config only
./scripts/remove-domain.sh example.com
# Remove domain config and certificate
./scripts/remove-domain.sh example.com --remove-cert./scripts/list-domains.sh./scripts/reload-nginx.shNote: The restart-nginx.sh script automatically syncs containers and symlinks before restarting. It prefers reload over restart when nginx is already running to avoid breaking existing connections.
The system includes an automated synchronization mechanism that ensures nginx configuration symlinks point to the correct active containers (blue/green) and generates configs from the service registry.
Important: Nginx is independent of container state - it can start and run even when containers are not running. Nginx will return 502 errors until containers become available, which is acceptable behavior. When containers start, nginx automatically connects to them.
Automatic Sync (Recommended):
# restart-nginx.sh automatically syncs before restarting
./scripts/restart-nginx.shManual Sync:
# Sync containers and symlinks (no restart)
./scripts/sync-containers-and-nginx.sh
# Sync and restart nginx
./scripts/sync-containers-and-nginx.sh --restart-nginxWhat it does:
- Scans all services in the registry
- Generates nginx configs from registry (independent of container state)
- Checks which containers are running (blue, green, or both) - for informational purposes
- Updates symlinks to point to the expected color (from state) or running containers
- Optionally starts missing containers (using deploy-smart.sh) - not required
- Validates nginx configuration (may fail if nginx container is not running, which is acceptable)
- Optionally reloads/restarts nginx
Symlink Logic:
- If containers match expected color → Symlink stays as-is ✅
- If containers don't match → Updates symlink to match running containers
- If no containers running → Keeps expected color, optionally tries to start them
Key Principle: Configs are generated from the service registry, not from container state. Nginx can start and run with configs pointing to non-existent containers - it will return 502 errors until containers are available.
For detailed information, see Container and Nginx Synchronization Guide.
# Request certificate
docker compose run --rm certbot /scripts/request-cert.sh <domain> [email]
# Check certificate expiry
docker compose run --rm certbot /scripts/check-cert-expiry.sh [domain]
# Renew certificates
docker compose run --rm certbot /scripts/renew-cert.shKey Principle: Nginx is independent of container state. This means:
- ✅ Nginx can start even when no containers are running
- ✅ Configs are generated from the service registry, not from container state
- ✅ Nginx will return 502 errors until containers become available (acceptable behavior)
- ✅ Nginx automatically connects to containers when they start
- ✅ No dependency - containers can start/stop independently of nginx
- ✅ Config Validation: New configs are validated before being applied - invalid configs are rejected and nginx continues running with existing valid configs
Nginx resolves hostnames at runtime via DNS, not at startup. This allows:
- Config Generation: Upstream blocks are always generated from the service registry, regardless of whether containers exist
- Config Validation: New configs are generated to a staging directory, validated in isolation with existing configs, and only applied if validation passes
- Independent Startup: Nginx starts successfully even if upstreams point to non-existent containers
- Runtime Resolution: When containers start, nginx automatically resolves their hostnames and connects
- Graceful Degradation: Nginx returns 502 errors for unavailable upstreams until containers are ready
- Fail-Safe: Invalid configs are rejected and moved to
conf.d/rejected/directory - nginx continues running with existing valid configs
- No startup dependencies: Nginx doesn't wait for containers to start
- Flexible deployment: Containers can be started/stopped without affecting nginx
- Zero-downtime: Nginx stays running during container deployments
- Simplified operations: No need to coordinate nginx and container startup
- Config Safety: Invalid configs are automatically rejected - one bad config won't break all services
The system includes a robust validation mechanism that ensures nginx always runs:
- Staging Directory: New configs are generated to
nginx/conf.d/staging/first - Isolated Validation: Each new config is tested with all existing valid configs to ensure compatibility
- Safe Application: Only validated configs are moved to
nginx/conf.d/blue-green/ - Rejection Handling: Invalid configs are moved to
nginx/conf.d/rejected/with timestamps for debugging - Nginx Resilience: Nginx continues running with existing valid configs even if new configs fail validation
Example: If you add a new service with a config that has a syntax error or conflicts with existing configs:
- The invalid config is rejected and moved to
rejected/directory - Nginx continues running with all existing valid configs
- RabbitMQ, database, and logging servers remain unaffected
- You can fix the config and try again
For more details, see the Container and Nginx Synchronization Guide.
Edit .env file:
# Let's Encrypt Configuration
CERTBOT_EMAIL=admin@example.com # Email for Let's Encrypt (default: admin@example.com)
CERTBOT_STAGING=false # Use staging environment (for testing)
# Docker Network Configuration
NETWORK_NAME=nginx-network # Docker network name
# Production Paths (Environment-Specific)
PRODUCTION_BASE_PATH=/home/statex # Base directory where services are deployed (e.g., /home/statex, /home/alfares)
DATABASE_SERVER_PATH=/home/statex/database-server # Full path to database-server (or ../database-server for relative)
# Docker Volumes Base Path (Environment-Specific)
DOCKER_VOLUMES_BASE_PATH=/srv/storagebox/alfares/docker-volumes/nginx-microservice # Base path for Docker volumes
# Multi-Domain Service Configuration
MULTI_DOMAIN_SERVICE_NAME=statex # Service name that handles multiple domains (default: statex)
# Default Domain Suffix (Optional)
DEFAULT_DOMAIN_SUFFIX=example.com # Optional: Default domain suffix for auto-generated domainsImportant Configuration Notes:
-
PRODUCTION_BASE_PATH: REQUIRED for multi-environment support. Set this to your server's base directory (e.g.,
/home/alfaresfor alfares server,/home/statexfor statex server). This is used to locate service directories. All scripts use this variable from.env- if not set, they will default to/home/statexfor backward compatibility only. -
DATABASE_SERVER_PATH: Full path to the database-server directory. Can be absolute (e.g.,
/home/alfares/database-serveror/home/statex/database-server) or relative (e.g.,../database-server). If not set, it will default to${PRODUCTION_BASE_PATH}/database-server. -
DOCKER_VOLUMES_BASE_PATH: REQUIRED for multi-environment support. Set this to match your server's storage location for Docker volumes (logs, etc.). For example:
- Alfares:
/srv/storagebox/alfares/docker-volumes/nginx-microservice - Statex:
/srv/storagebox/statex/docker-volumes/nginx-microserviceIf not set, docker-compose.yml will default to/srv/storagebox/statex/docker-volumes/nginx-microservicefor backward compatibility only.
- Alfares:
-
MULTI_DOMAIN_SERVICE_NAME: If you have a service that handles multiple domains (like the statex service), set this to that service name. Defaults to "statex" for backward compatibility.
-
DEFAULT_DOMAIN_SUFFIX: Optional. Used for:
- Fallback when a service's domain cannot be detected from its
.envfile - Default landing page: Automatically sets up a default landing page with SSL certificate for this domain on new deployments
- It's recommended to explicitly set the
DOMAINvariable in each service's.envfile instead of relying on auto-generation
- Fallback when a service's domain cannot be detected from its
Multi-Environment Setup: To use this codebase on different servers (e.g., "alfares" vs "statex"), simply set PRODUCTION_BASE_PATH and DOCKER_VOLUMES_BASE_PATH in your .env file. All scripts automatically load these values from .env and use them instead of hardcoded paths.
The nginx-microservice automatically sets up a default landing page with SSL certificate during initial deployment. This provides a professional welcome page when no applications are configured yet.
How it works:
- On first startup, the system automatically detects the default domain from:
DEFAULT_DOMAIN_SUFFIXenvironment variable (if set)- System hostname/FQDN (fallback)
- Creates a service registry entry for "default-landing" (no services configured)
- Automatically requests SSL certificate from Let's Encrypt
- Generates nginx configuration serving the default landing page
- The landing page is replaced automatically when you deploy your first application
Benefits:
- ✅ Professional welcome page on new server deployments
- ✅ Automatic SSL certificate provisioning
- ✅ Zero configuration required - works out of the box
- ✅ Automatically replaced when applications are deployed
Example:
If you set DEFAULT_DOMAIN_SUFFIX=alfares.cz in .env, the default landing page will be available at https://alfares.cz immediately after nginx starts.
Domain configurations are stored in nginx/conf.d/ directory. Each domain has its own .conf file.
The configuration template (nginx/templates/domain.conf.template) includes:
- HTTP to HTTPS redirect
- SSL/TLS configuration
- Security headers
- Rate limiting
- Proxy configuration with DNS-based container discovery
- Same Docker Network: All containers must be on the
nginx-network - Container Names: Use container names (not service names) for DNS discovery
- Port Exposure: Containers must expose ports internally on the network
Example docker-compose.yml for your application:
services:
my-app:
image: my-app:latest
container_name: my-app
networks:
- nginx-network
# ... other configConnect existing container to network:
docker network connect nginx-network <container-name>Nginx-microservice intercepts ALL /api/* routes by default and routes them to backend services or API gateway. However, some services (like Next.js frontends) have their own API routes that should be handled by specific containers.
Universal Solution: Create nginx-api-routes.conf in your service directory to register custom API routes.
How it works:
- Create config file:
{service}/nginx/nginx-api-routes.conf(or{service}/nginx-api-routes.conf) - List your routes: One route per line, starting with
/api/or/ - Automatic registration: Routes are automatically registered during deployment via
deploy-smart.sh - Automatic routing: System automatically routes to:
- Frontend container (if service has frontend)
- Backend/first service (if service doesn't have frontend)
Example config file (statex/nginx/nginx-api-routes.conf):
# API Routes Configuration
# Routes are automatically routed to frontend (if service has frontend)
# or backend/first service (if service doesn't have frontend)
/api/users/collect-contact
/api/notifications/prototype-request
/api/contact/collect
During deployment:
./scripts/blue-green/deploy-smart.sh statexThe deployment script automatically:
- Reads
nginx-api-routes.conffrom your service directory - Adds routes to service registry JSON
- Generates nginx location blocks BEFORE generic
/api/block - Routes are matched by specificity (most specific first)
Benefits:
- ✅ Universal: Works for all services (frontend, backend, API gateway)
- ✅ Automatic: No manual nginx config editing required
- ✅ Version controlled: Config file stored in service codebase
- ✅ Zero downtime: Routes registered during normal deployment cycle
For complete documentation, see API Routes Registration Guide.
Certificates are stored in a three-tier system for reliability and persistence:
-
Host filesystem (Primary):
./certificates/<domain>/- This is the primary storage location on the host
- Files persist across container restarts and recreations
- Contains actual certificate files (not symlinks)
-
Certbot container:
/etc/letsencrypt/live/<domain>/- Symlinks pointing to
/etc/letsencrypt/archive/<domain>/ - Used by certbot for certificate management
- Volume mount:
./certificates→/etc/letsencryptin certbot container
- Symlinks pointing to
-
Nginx container:
/etc/nginx/certs/<domain>/- Read-only access to certificates for SSL configuration
- Volume mount:
./certificates→/etc/nginx/certsin nginx container
Important: The request-cert.sh script automatically copies certificates from certbot's location to the host filesystem (./certificates/<domain>/). This ensures:
- Nginx can access certificates reliably
- Certificates survive container restarts
- Files are stored on persistent host storage
Each domain has two certificate files in ./certificates/<domain>/:
-
fullchain.pem: Complete certificate chain- Contains: Domain certificate + intermediate certificates
- Required for SSL/TLS handshake
- Permissions:
644(readable by nginx)
-
privkey.pem: Private key- Must be kept secure and never exposed
- Required for SSL/TLS encryption
- Permissions:
600(only readable by owner)
When requesting a certificate (via add-domain.sh or manually):
-
Check existing certificate: Script checks if certificate exists in
./certificates/<domain>/ -
Validate expiration: If certificate exists, checks if it expires in < 30 days
-
Request new certificate: If needed, requests from Let's Encrypt using webroot validation
- Certbot places challenge file in
/var/www/html/.well-known/acme-challenge/ - Nginx serves this file to prove domain ownership
- Let's Encrypt validates and issues certificate
- Certbot places challenge file in
-
Copy to host:
request-cert.shcopies certificate files to./certificates/<domain>/- Uses
cp -Lto follow symlinks and copy actual files - Sets proper file permissions (644 for fullchain, 600 for privkey)
- Uses
-
Nginx configuration: Update nginx config to reference:
ssl_certificate /etc/nginx/certs/<domain>/fullchain.pem; ssl_certificate_key /etc/nginx/certs/<domain>/privkey.pem;
-
Reload nginx: Certificate is immediately available after nginx reload
Let's Encrypt certificates are valid for 90 days. Renewal should happen when < 30 days remain.
Automatic Renewal:
- Systemd: Daily check via timer (if configured)
- Cron: Daily at 3:00 AM (if configured)
- Renewal automatically triggers nginx reload
Manual Renewal:
# Renew all certificates
docker compose run --rm certbot /scripts/renew-cert.sh
# Renew specific domain
docker compose run --rm certbot /scripts/request-cert.sh <domain>Check Certificate Expiry:
# Check specific domain
docker compose run --rm certbot /scripts/check-cert-expiry.sh <domain>
# Check certificate on host
openssl x509 -enddate -noout -in certificates/<domain>/fullchain.pemSymptom: nginx: [emerg] cannot load certificate "/etc/nginx/certs/<domain>/fullchain.pem"
Solution:
-
Verify certificate exists on host:
ls -la certificates/<domain>/ -
If missing, copy from certbot container:
docker exec nginx-certbot sh -c 'mkdir -p /etc/letsencrypt/<domain> && cp -L /etc/letsencrypt/live/<domain>/fullchain.pem /etc/letsencrypt/<domain>/ && cp -L /etc/letsencrypt/live/<domain>/privkey.pem /etc/letsencrypt/<domain>/ && chmod 644 /etc/letsencrypt/<domain>/fullchain.pem && chmod 600 /etc/letsencrypt/<domain>/privkey.pem'
-
Verify nginx config references correct path:
/etc/nginx/certs/<domain>/fullchain.pem
Common causes:
- DNS not pointing to server:
dig <domain>should return server IP - Port 80 not accessible: Let's Encrypt needs HTTP access for validation
- Rate limiting: Let's Encrypt has rate limits (50 certs/week per domain)
Debug steps:
# Check DNS
dig <domain>
# Test HTTP access
curl http://<domain>/.well-known/acme-challenge/test
# Check certbot logs
docker compose logs certbot
# Use staging environment for testing
CERTBOT_STAGING=true docker compose run --rm certbot /scripts/request-cert.sh <domain>Symptom: Browser shows "Certificate has expired" error
Solution:
# Renew certificate
docker compose run --rm certbot /scripts/request-cert.sh <domain>
# Verify new certificate
openssl x509 -enddate -noout -in certificates/<domain>/fullchain.pem
# Reload nginx
docker compose exec nginx nginx -s reload- Nginx Access Logs:
logs/nginx/access.log - Nginx Error Logs:
logs/nginx/error.log - Certbot Logs:
logs/certbot/certbot.log - Renewal Logs:
logs/certbot/renewal.log(if using cron)
# Nginx logs
docker compose logs nginx
# Certbot logs
docker compose logs certbot
# Follow logs
docker compose logs -f nginx# Request certificate manually
docker compose run --rm certbot /scripts/request-cert.sh <domain>
# Check certificate status
docker compose run --rm certbot /scripts/check-cert-expiry.sh <domain># Verify container is on the network
docker network inspect nginx-network
# Connect container to network
docker network connect nginx-network <container-name>
# Test container accessibility
docker run --rm --network nginx-network alpine/curl:latest curl http://<container-name>:<port># Test configuration
docker compose exec nginx nginx -t
# View error logs
docker compose logs nginx | grep error# Check renewal status (systemd)
sudo systemctl status nginx-certbot-renew.timer
# Check renewal logs (systemd)
sudo journalctl -u nginx-certbot-renew.service
# Check renewal logs (cron)
cat logs/certbot/renewal.logSet in .env:
CERTBOT_STAGING=trueEdit domain config files in nginx/conf.d/ or modify the template in nginx/templates/domain.conf.template.
- Certificate Private Keys: Stored with 600 permissions
- Config Files: Stored with 644 permissions
- No Secrets in Git:
.envfile is gitignored - Rate Limiting: Configured per domain to prevent abuse
- Security Headers: HSTS, X-Frame-Options, CSP, etc.
MIT License
Copyright (c) 2025 Sergej
See LICENSE file for details.
The nginx-microservice includes a zero-downtime blue/green deployment system for services.
All services are now standardized and managed through the blue/green deployment system:
- ai-microservice - AI microservice
- auth-microservice - Authentication service
- database-server - Database infrastructure (shared)
- logging-microservice - Centralized logging service
- nginx-microservice - This reverse proxy service
- notifications-microservice - Notification service
- payments-microservice - Payment processing service
- allegro - Allegro sales platform management
- crypto-ai-agent - Crypto AI agent application
- flipflop - flipflop platform
- statex - Main statex platform application
All services have dependencies that must be respected when starting the system. See Service Dependencies Guide for complete details.
Quick Start - All Services:
# Start all services in correct dependency order
./scripts/start-all-services.sh
# Start only infrastructure (database - nginx always starts)
./scripts/start-all-services.sh --skip-microservices --skip-applications
# Start only microservices (assumes infrastructure is running)
./scripts/start-all-services.sh --skip-infrastructure --skip-applications
# Start only applications (assumes infrastructure and microservices are running)
./scripts/start-all-services.sh --skip-infrastructure --skip-microservices
# Start a single service
./scripts/start-all-services.sh --service <service-name>Individual Scripts (for debugging and maintenance):
# Start nginx only (always runs first - mandatory)
./scripts/start-nginx.sh
# Start infrastructure only (database-server)
./scripts/start-infrastructure.sh
# Start microservices only
./scripts/start-microservices.sh
./scripts/start-microservices.sh --service <service-name>
# Start applications only
./scripts/start-applications.sh
./scripts/start-applications.sh --service <service-name>Startup Order:
- Nginx (Phase 1 - always runs): nginx-network → nginx-microservice
- Infrastructure (Phase 2): database-server (postgres + redis)
- Microservices (Phase 3): logging-microservice → auth-microservice → payments-microservice → notifications-microservice → ai-microservice
- Applications (Phase 4): allegro → crypto-ai-agent → statex → flipflop
Fault Tolerance:
- Infrastructure & Microservices: Zero tolerance - system exits if these fail (critical services)
- Applications: Fault tolerant - applications can fail independently without stopping the system
- If an application fails to start, other applications continue running normally
Note: Nginx is the primary service and must always start. There is no --skip-nginx flag. Nginx will be restarted/reloaded when new services are added, which serves as an additional test point.
# Deploy a service (full cycle) - RECOMMENDED: Use deploy-smart.sh for better performance
./scripts/blue-green/deploy-smart.sh crypto-ai-agent
# For heavy applications (flipflop with 10+ services), deploy-smart.sh only rebuilds changed services
# This significantly speeds up deployment time
# Manual rollback if needed
./scripts/blue-green/rollback.sh crypto-ai-agent
# Check deployment status
cat state/crypto-ai-agent.json | jq .- ✅ Zero-downtime deployments: Switch traffic with < 2 seconds downtime
- ✅ Automatic rollback: Auto-rollback on health check failure
- ✅ Health monitoring: Continuous health checks during deployment
- ✅ Centralized management: All deployments managed from one place
- ✅ Service registry: Easy service configuration via JSON
For detailed documentation, see:
- Blue/Green Deployment Guide - Complete usage guide
- Service Registry Format - How to configure services
- Troubleshooting - Common issues and solutions
Blue/Green Deployment Scripts (in scripts/blue-green/):
deploy-smart.sh- RECOMMENDED: Full deployment cycle (only rebuilds changed services)prepare-green-smart.sh- RECOMMENDED: Build and start new deployment (only rebuilds changed services)switch-traffic.sh- Switch traffic to new color (uses modern symlink-based switching)migrate-to-symlinks.sh- Migrate services to symlink-based blue/green systemhealth-check.sh- Check service healthrollback.sh- Rollback to previous deploymentcleanup.sh- Remove old deployment
Service Startup Scripts (in scripts/):
start-all-services.sh- MASTER SCRIPT: Starts all services in dependency order (calls the 4 phase scripts)start-nginx.sh- Phase 1: Starts nginx-network and nginx-microservice (always runs first - mandatory)start-infrastructure.sh- Phase 2: Starts database-server (postgres + redis)start-microservices.sh- Phase 3: Starts all microservicesstart-applications.sh- Phase 4: Starts all applications
Nginx Management Scripts (in scripts/):
restart-nginx.sh- RECOMMENDED: Restarts nginx (automatically syncs containers and symlinks first)sync-containers-and-nginx.sh- Syncs containers and symlinks, optionally restarts nginxreload-nginx.sh- Reloads nginx configuration (lightweight, no restart)status-all-services.sh- Shows status of all services and containersdiagnose.sh- RECOMMENDED: Comprehensive diagnostic tool for all containers (replaces old diagnose-nginx-restart.sh and diagnose-nginx-502.sh)
Note: The blue/green system uses a modern symlink-based approach where each service has separate blue and green config files ({domain}.blue.conf and {domain}.green.conf), with a symlink ({domain}.conf) pointing to the active environment. This replaces the legacy file-modification approach.
The system automatically ensures that nginx configuration symlinks point to the correct active containers before restarting nginx. This is critical for blue/green deployments:
Key Features:
- ✅ Automatic symlink management: Symlinks automatically point to running containers
- ✅ Container detection: Detects which color (blue/green) has running containers
- ✅ Auto-start missing containers: Starts missing containers using deploy-smart.sh
- ✅ Safe nginx restart: Validates configuration before restarting
- ✅ Integrated with restart-nginx.sh: Automatically syncs before restart
Usage:
# Recommended: restart-nginx.sh automatically syncs
./scripts/restart-nginx.sh
# Manual sync (no restart)
./scripts/sync-containers-and-nginx.sh
# Manual sync and restart
./scripts/sync-containers-and-nginx.sh --restart-nginxHow it works:
- Checks all services in the registry
- Detects which containers are running (blue/green)
- Updates symlinks to match running containers
- Starts missing containers if needed
- Validates nginx configuration
- Restarts nginx (if requested)
For complete documentation, see:
- Blue/Green Deployment Guide - Complete usage guide
- Container and Nginx Synchronization Guide - Symlink and container sync details
For issues and questions, please open an issue on GitHub.