12 KiB
MotoVaultPro GitLab CI/CD Deployment Guide
Complete guide for deploying MotoVaultPro using GitLab CI/CD with blue-green deployment and auto-rollback.
Table of Contents
- Architecture Overview
- Prerequisites
- Pipeline Stages
- Blue-Green Deployment
- CI/CD Variables Configuration
- Container Registry
- Deployment Process
- Rollback Procedures
- Maintenance Migrations
- Notifications
- Troubleshooting
Architecture Overview
MotoVaultPro uses a blue-green deployment strategy with automatic rollback:
+---------------------------------------------------+
| GitLab (CI/CD + Registry) |
+---------------------------------------------------+
| |
v v
+------------------+ +-----------------------+
| Build VPS | | Production Server |
| (Docker Runner) | | (Shell Runner) |
| Tags: build | | Tags: production |
+------------------+ +-----------+-----------+
| |
| Push images | Pull + Deploy
v v
+---------------------------------------------------+
| GitLab Container Registry |
| registry.motovaultpro.com/motovaultpro/ |
+---------------------------------------------------+
|
+---------------+---------------+
| |
+--------v--------+ +--------v--------+
| BLUE Stack | | GREEN Stack |
| mvp-frontend | | mvp-frontend |
| mvp-backend | | mvp-backend |
+-----------------+ +-----------------+
| |
+----------- Traefik -----------+
(weighted LB)
|
+---------------+---------------+
| |
+--------v--------+ +--------v--------+
| PostgreSQL | | Redis |
| (shared) | | (shared) |
+-----------------+ +-----------------+
Key Features
- Zero-downtime deployments: Traffic switches in under 5 seconds
- Instant rollback: Previous version remains running
- Automatic rollback: On health check failure
- Email notifications: Via Resend API
- Container registry: Self-hosted on GitLab (no Docker Hub)
Prerequisites
Server Requirements
| Server | Purpose | Specs | Runner Tags |
|---|---|---|---|
| Build VPS | Docker image builds | 2 CPU, 4GB RAM | build |
| Prod Server | Application hosting | 8GB+ RAM | production |
See BUILD-SERVER-SETUP.md for build server setup.
Software Requirements
- GitLab 18.6+
- Docker Engine 24.0+
- Docker Compose v2
- GitLab Runner (shell executor on both servers)
jqfor JSON processing
Pipeline Stages
The CI/CD pipeline consists of 7 stages:
validate -> build -> deploy-prepare -> deploy-switch -> verify -> [rollback] -> notify
| Stage | Runner | Purpose |
|---|---|---|
validate |
prod | Check prerequisites, determine target stack |
build |
build | Build and push images to GitLab registry |
deploy-prepare |
prod | Pull images, start inactive stack, health check |
deploy-switch |
prod | Switch Traefik traffic weights |
verify |
prod | Production health verification |
rollback |
prod | Auto-triggered on verify failure |
notify |
prod | Email success/failure notifications |
Pipeline Flow
[Push to main]
|
v
[validate] - Checks Docker, paths, registry
|
v
[build] - Builds backend + frontend images
| Pushes to registry.motovaultpro.com
v
[deploy-prepare] - Pulls new images
| Starts inactive stack (blue or green)
| Runs health checks
v
[deploy-switch] - Updates Traefik weights
| Switches traffic instantly
v
[verify] - External health check
| Container status verification
|
+--[SUCCESS]--> [notify-success] - Sends success email
|
+--[FAILURE]--> [rollback] - Switches back to previous stack
|
v
[notify-failure] - Sends failure email
Blue-Green Deployment
Stack Configuration
Both stacks share the same database layer:
| Component | Blue Stack | Green Stack | Shared |
|---|---|---|---|
| Frontend | mvp-frontend-blue |
mvp-frontend-green |
- |
| Backend | mvp-backend-blue |
mvp-backend-green |
- |
| PostgreSQL | - | - | mvp-postgres |
| Redis | - | - | mvp-redis |
| Traefik | - | - | mvp-traefik |
Traffic Routing
Traefik uses weighted services for traffic distribution:
# config/traefik/dynamic/blue-green.yml
services:
mvp-frontend-weighted:
weighted:
services:
- name: mvp-frontend-blue-svc
weight: 100 # Active
- name: mvp-frontend-green-svc
weight: 0 # Standby
Deployment State
State is tracked in config/deployment/state.json:
{
"active_stack": "blue",
"inactive_stack": "green",
"last_deployment": "2024-01-15T10:30:00Z",
"last_deployment_commit": "abc123",
"rollback_available": true
}
CI/CD Variables Configuration
Navigate to Settings > CI/CD > Variables in your GitLab project.
Required Variables
| Variable | Type | Protected | Purpose |
|---|---|---|---|
DEPLOY_NOTIFY_EMAIL |
Variable | Yes | Notification recipient |
VITE_AUTH0_DOMAIN |
Variable | No | Auth0 domain |
VITE_AUTH0_CLIENT_ID |
Variable | No | Auth0 client ID |
VITE_AUTH0_AUDIENCE |
Variable | No | Auth0 audience |
Secret Files
These use GitLab's File type and are injected via scripts/inject-secrets.sh:
| Variable | Type | Protected | Masked |
|---|---|---|---|
POSTGRES_PASSWORD |
File | Yes | Yes |
AUTH0_CLIENT_SECRET |
File | Yes | Yes |
GOOGLE_MAPS_API_KEY |
File | Yes | Yes |
GOOGLE_MAPS_MAP_ID |
File | Yes | No |
CF_DNS_API_TOKEN |
File | Yes | Yes |
RESEND_API_KEY |
File | Yes | Yes |
Registry Authentication
GitLab provides these automatically:
CI_REGISTRY_USER- Registry usernameCI_REGISTRY_PASSWORD- Registry tokenCI_REGISTRY- Registry URL
Container Registry
All images are hosted on the GitLab Container Registry to avoid Docker Hub rate limits.
Registry URL
registry.motovaultpro.com
Image Paths
| Image | Path |
|---|---|
| Backend | registry.motovaultpro.com/motovaultpro/backend:$TAG |
| Frontend | registry.motovaultpro.com/motovaultpro/frontend:$TAG |
| Mirrors | registry.motovaultpro.com/mirrors/ |
Base Image Mirrors
Mirror upstream images to avoid rate limits:
# Run manually or via scheduled pipeline
./scripts/ci/mirror-base-images.sh
Mirrored images:
node:20-alpinenginx:alpinepostgres:18-alpineredis:8.4-alpinetraefik:v3.6docker:24.0docker:24.0-dind
Deployment Process
Automatic Deployment
Deployments trigger automatically on push to main:
- Validate: Check prerequisites, determine target stack
- Build: Build images on dedicated build server
- Prepare: Start inactive stack, run health checks
- Switch: Update Traefik weights (instant)
- Verify: External health check
- Notify: Send email notification
Manual Deployment
- Go to CI/CD > Pipelines
- Click Run pipeline
- Select
mainbranch - Click Run pipeline
Deployment Timeline
| Phase | Duration |
|---|---|
| Validate | ~5s |
| Build | ~2 min |
| Deploy-prepare | ~30s |
| Deploy-switch | ~3s |
| Verify | ~30s |
| Total | ~3 min |
Rollback Procedures
Automatic Rollback
Triggers automatically when:
- Health check fails in
deploy-prepare verifystage fails after switch- Container becomes unhealthy within verification period
The pipeline runs scripts/ci/auto-rollback.sh which:
- Verifies previous stack is healthy
- Switches traffic back
- Sends notification
Manual Rollback
SSH to production server:
cd /opt/motovaultpro
# Check current state
cat config/deployment/state.json | jq .
# Switch to other stack
./scripts/ci/switch-traffic.sh blue # or green
Emergency Recovery
If both stacks are unhealthy:
# Stop everything
docker compose -f docker-compose.yml -f docker-compose.blue-green.yml down
# Restart shared services
docker compose up -d mvp-postgres mvp-redis mvp-traefik
# Wait for database
sleep 15
# Start one stack
export BACKEND_IMAGE=registry.motovaultpro.com/motovaultpro/backend:latest
export FRONTEND_IMAGE=registry.motovaultpro.com/motovaultpro/frontend:latest
docker compose -f docker-compose.yml -f docker-compose.blue-green.yml up -d \
mvp-frontend-blue mvp-backend-blue
# Switch traffic
./scripts/ci/switch-traffic.sh blue
Maintenance Migrations
For breaking database changes requiring downtime:
Via Pipeline (Recommended)
- Go to CI/CD > Pipelines
- Find the
maintenance-migrationjob - Click Play to trigger manually
Via Script
cd /opt/motovaultpro
# With backup
./scripts/ci/maintenance-migrate.sh backup
# Without backup
./scripts/ci/maintenance-migrate.sh
What Happens
- Sends maintenance notification
- Enables maintenance mode (stops traffic)
- Creates database backup (if requested)
- Runs migrations
- Restarts backends
- Restores traffic
- Sends completion notification
Notifications
Email notifications via Resend API for:
| Event | Subject |
|---|---|
success |
Deployment Successful |
failure |
Deployment Failed |
rollback |
Auto-Rollback Executed |
rollback_failed |
CRITICAL: Rollback Failed |
maintenance_start |
Maintenance Mode Started |
maintenance_end |
Maintenance Complete |
Configure recipient in GitLab CI/CD variables:
DEPLOY_NOTIFY_EMAIL = admin@example.com
Troubleshooting
Pipeline Fails at Build Stage
Check build server connectivity:
# On build server
sudo gitlab-runner verify
docker login registry.motovaultpro.com
Check disk space:
df -h
docker system prune -af
Pipeline Fails at Deploy-Prepare
Container won't start:
docker logs mvp-backend-blue --tail 100
docker logs mvp-frontend-blue --tail 100
Health check timeout:
# Increase timeout in .gitlab-ci.yml
HEALTH_CHECK_TIMEOUT: "90"
Traffic Not Switching
Check Traefik config:
cat config/traefik/dynamic/blue-green.yml
docker exec mvp-traefik traefik healthcheck
Check routing:
curl -I https://motovaultpro.com/api/health
Verify Stage Fails
Check external connectivity:
curl -sf https://motovaultpro.com/api/health
Check container health:
docker inspect --format='{{.State.Health.Status}}' mvp-backend-blue
Quick Reference
Important Paths
| Path | Description |
|---|---|
config/deployment/state.json |
Deployment state |
config/traefik/dynamic/blue-green.yml |
Traffic routing |
scripts/ci/ |
Deployment scripts |
Common Commands
# View current state
cat config/deployment/state.json | jq .
# Check container status
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Health}}"
# View logs
docker logs mvp-backend-blue -f
# Manual traffic switch
./scripts/ci/switch-traffic.sh green
# Run health check
./scripts/ci/health-check.sh blue
# Send test notification
./scripts/ci/notify.sh success "Test message"
Memory Budget (8GB Server)
| Component | RAM |
|---|---|
| Blue frontend | 512MB |
| Blue backend | 1GB |
| Green frontend | 512MB |
| Green backend | 1GB |
| PostgreSQL | 2GB |
| Redis | 512MB |
| Traefik | 128MB |
| System | 1.3GB |
| Total | ~7GB |