9.3 KiB
MotoVaultPro CI/CD Deployment Guide
Complete guide for deploying MotoVaultPro using Gitea Actions with staging-first deployment and manual production approval.
Table of Contents
- Architecture Overview
- Prerequisites
- Workflow Structure
- Deployment Process
- Secrets and Variables
- Container Registry
- Rollback Procedures
- Maintenance Migrations
- Troubleshooting
Architecture Overview
MotoVaultPro uses a staging-first deployment strategy with manual approval:
+---------------------------------------------------+
| Gitea (git.motovaultpro.com) |
| +--------------------+ +--------------------+ |
| | Gitea Actions | | Package Registry | |
| +--------------------+ +--------------------+ |
+---------------------------------------------------+
| |
v v
+-------------------+ +--------------------+
| Build/Staging VPS | | Production Server |
| (mvp-build) | | (mvp-prod) |
| act_runner | | act_runner |
+--------+----------+ +----------+---------+
| |
v v
staging.motovaultpro.com motovaultpro.com
(Full Stack) (Blue-Green)
Key Features
- Staging-first: All changes verified on staging before production
- Manual approval: Production deploy requires manual trigger
- Blue-green production: Zero-downtime deployments
- Auto-rollback: Automatic rollback on health check failure
- Email notifications: Via Resend API
Prerequisites
Server Requirements
| Server | Purpose | Specs | Runner Label |
|---|---|---|---|
| Build/Staging VPS | Build + Staging | 4 CPU, 8GB RAM | mvp-build |
| Prod Server | Production | 8GB+ RAM | mvp-prod |
See BUILD-SERVER-SETUP.md for setup instructions.
Software Requirements
- Gitea 1.21+ with Actions enabled
- Docker Engine 24.0+
- Docker Compose v2
- act_runner (Gitea Actions runner)
jqfor JSON processing
Workflow Structure
Two-Workflow Strategy
| Workflow | Trigger | Purpose |
|---|---|---|
staging.yaml |
Push to main | Build, deploy to staging, verify |
production.yaml |
Manual (workflow_dispatch) | Deploy to production |
Staging Workflow (Automatic)
[Push to main]
|
v
[build] -------- Build images, push to registry
|
v
[deploy-staging] - Deploy full stack to staging
|
v
[verify-staging] - Health checks
|
+--[FAIL]--> [notify-staging-failure]
|
v
[notify-staging-ready] - Email with production deploy link
Production Workflow (Manual)
[Manual Trigger] - User clicks "Run workflow"
|
v
[validate] - Check prerequisites, determine stack
|
v
[deploy-prod] - Blue-green deployment
|
v
[verify-prod] - External health checks
|
+--[FAIL]--> [rollback] --> [notify-failure]
|
v
[notify-success]
Deployment Process
1. Push to Main Branch
When you push to main:
- Staging workflow triggers automatically
- Images are built and pushed to Gitea Package Registry
- Full stack deploys to staging.motovaultpro.com
- Health checks verify staging works
- Email notification sent with production deploy link
2. Review Staging
After receiving the "Staging Ready" email:
- Visit https://staging.motovaultpro.com
- Test functionality
- Review logs if needed:
docker logs mvp-backend-staging
3. Deploy to Production
When ready to deploy:
- Go to
git.motovaultpro.com/egullickson/motovaultpro/actions - Select "Deploy to Production" workflow
- Click "Run workflow"
- Optionally specify image tag (defaults to
latest) - Click "Run workflow" to confirm
4. Monitor Production Deploy
The production workflow will:
- Determine target stack (blue or green)
- Pull and start the new stack
- Run health checks
- Switch traffic
- Verify external health
- Auto-rollback if verification fails
- Send email notification
Secrets and Variables
Secrets Configuration
Navigate to: git.motovaultpro.com/egullickson/motovaultpro/settings/actions/secrets
| Secret | Description |
|---|---|
REGISTRY_USER |
Gitea username (egullickson) |
REGISTRY_PASSWORD |
Gitea access token |
POSTGRES_PASSWORD |
Production PostgreSQL password |
STAGING_POSTGRES_PASSWORD |
Staging PostgreSQL password |
AUTH0_CLIENT_SECRET |
Auth0 secret |
AUTH0_MANAGEMENT_CLIENT_ID |
Auth0 Management API ID |
AUTH0_MANAGEMENT_CLIENT_SECRET |
Auth0 Management API secret |
GOOGLE_MAPS_API_KEY |
Google Maps key |
GOOGLE_MAPS_MAP_ID |
Google Maps Map ID |
CF_DNS_API_TOKEN |
Cloudflare DNS token |
RESEND_API_KEY |
Resend email API key |
Variables Configuration
Navigate to: git.motovaultpro.com/egullickson/motovaultpro/settings/actions/variables
| Variable | Value |
|---|---|
DEPLOY_NOTIFY_EMAIL |
Notification recipient |
VITE_AUTH0_DOMAIN |
motovaultpro.us.auth0.com |
VITE_AUTH0_CLIENT_ID |
Auth0 client ID |
VITE_AUTH0_AUDIENCE |
https://api.motovaultpro.com |
Container Registry
All images are hosted on Gitea Package Registry.
Registry URL
git.motovaultpro.com
Image Paths
| Image | Path |
|---|---|
| Backend | git.motovaultpro.com/egullickson/backend:$TAG |
| Frontend | git.motovaultpro.com/egullickson/frontend:$TAG |
| Mirrors | git.motovaultpro.com/egullickson/mirrors/ |
Base Image Mirrors
Run the mirror workflow to avoid Docker Hub rate limits:
- Go to Actions tab
- Select "Mirror Base Images"
- Click "Run workflow"
Mirrored images:
node:20-alpinenginx:alpinepostgres:18-alpineredis:8.4-alpinetraefik:v3.6
Rollback Procedures
Automatic Rollback
Production workflow auto-rolls back when:
- Health check fails after traffic switch
- Container becomes unhealthy during verification
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:
cd /opt/motovaultpro
# 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=git.motovaultpro.com/egullickson/backend:latest
export FRONTEND_IMAGE=git.motovaultpro.com/egullickson/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 Gitea Actions
- Go to Actions tab
- Select "Maintenance Migration"
- Click "Run workflow"
- Choose whether to create backup
- Click "Run workflow"
Via Script
cd /opt/motovaultpro
# With backup
./scripts/ci/maintenance-migrate.sh backup
# Without backup
./scripts/ci/maintenance-migrate.sh
Troubleshooting
Staging Workflow Failures
Build fails:
# On build server
docker system df
docker system prune -af
Deploy fails:
docker logs mvp-backend-staging
docker logs mvp-frontend-staging
Production Workflow Failures
Health check timeout:
# Check containers
docker ps
docker logs mvp-backend-blue # or green
Traffic not switching:
# Check Traefik config
cat config/traefik/dynamic/blue-green.yml
docker exec mvp-traefik traefik healthcheck
Runner Issues
Runner offline:
sudo systemctl status act_runner
sudo journalctl -u act_runner -f
Permission denied:
sudo usermod -aG docker act_runner
sudo systemctl restart act_runner
Quick Reference
Workflow Locations
| Workflow | File |
|---|---|
| Staging | .gitea/workflows/staging.yaml |
| Production | .gitea/workflows/production.yaml |
| Maintenance | .gitea/workflows/maintenance.yaml |
| Mirror Images | .gitea/workflows/mirror-images.yaml |
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 deployment state
cat config/deployment/state.json | jq .
# Check containers
docker ps --format "table {{.Names}}\t{{.Status}}"
# 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
Email Notifications
| Event | Trigger |
|---|---|
| Staging Ready | Staging verified successfully |
| Success | Production deployed successfully |
| Failure | Deployment or verification failed |
| Rollback | Auto-rollback executed |
| Maintenance | Migration started/completed |