Files
michaelschiemer/deployment/stacks/staging

Staging Stack - Staging Environment

Overview

Separate staging environment for testing features before production deployment.

URL: https://staging.michaelschiemer.de

Features:

  • Separate containers and volumes from production
  • Auto-deployment from staging branch
  • Shared Traefik network (same SSL certificates)
  • Separate Redis instance
  • Can use separate database or share with production

Services

  • staging-app (PHP-FPM) - Application runtime
  • staging-nginx (Nginx) - Web server for staging.michaelschiemer.de
  • staging-redis (Redis 7) - Separate cache/session/queue backend
  • staging-queue-worker - Background job processor
  • staging-scheduler - Cron job executor

Prerequisites

  1. Traefik Stack Running (shared with production)
  2. DNS Configuration: staging.michaelschiemer.de points to server IP
  3. Docker Networks:
    docker network create traefik-public  # Shared with production
    docker network create staging-internal  # Staging-only
    

Configuration

1. Create Environment File

cp .env.example .env

2. Configure Environment Variables

# Staging-specific
APP_ENV=staging
APP_DEBUG=true
APP_URL=https://staging.michaelschiemer.de

# Database (can use separate staging DB or share)
DB_DATABASE=michaelschiemer_staging
DB_HOST=postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=<password>

# Redis (separate instance)
# Note: REDIS_PASSWORD is loaded from Docker Secret via REDIS_PASSWORD_FILE
# See secrets/redis_password.txt file
CACHE_PREFIX=staging

# Git
GIT_REPOSITORY_URL=https://git.michaelschiemer.de/michael/michaelschiemer.git
GIT_BRANCH=staging
# Note: GIT_TOKEN is loaded from Docker Secret via GIT_TOKEN_FILE
# See secrets/git_token.txt file

Deployment

Initial Setup

The staging environment uses docker-compose.staging.yml in the repository root, which is used as an override for docker-compose.base.yml.

# Create staging stack directory on server
mkdir -p ~/deployment/stacks/staging

# Copy docker-compose files from repository
cp docker-compose.base.yml ~/deployment/stacks/staging/
cp docker-compose.staging.yml ~/deployment/stacks/staging/

# Create secrets directory and files
mkdir -p ~/deployment/stacks/staging/secrets
# Create secret files (redis_password.txt, db_user_password.txt, app_key.txt, etc.)
# These files should contain the actual secret values

# Ensure networks exist
docker network create traefik-public 2>/dev/null || true
docker network create staging-internal 2>/dev/null || true

# Start staging stack
cd ~/deployment/stacks/staging
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml up -d

Auto-Deployment

Automatic: Push to staging branch triggers build, then auto-deploys to staging.

Manual: Use "Deploy to Staging" workflow in Gitea Actions.

Verify Deployment

# Check container status
cd ~/deployment/stacks/staging
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml ps

# Test staging URL
curl https://staging.michaelschiemer.de/health

# View logs
docker compose logs -f staging-app
docker compose logs -f staging-nginx

Differences from Production

Aspect Production Staging
Domain michaelschiemer.de staging.michaelschiemer.de
Branch main staging
APP_ENV production staging
APP_DEBUG false true
Redis Separate instance Separate instance
Database michaelschiemer michaelschiemer_staging
Volumes app-* staging-*
Network app-internal staging-internal

Workflow

  1. Development: Feature branch → merge to staging
  2. Auto-Build: Push to staging triggers build-image.yml
  3. Auto-Deploy: Successful build auto-deploys to staging (via deploy-staging.yml)
  4. Testing: Test on https://staging.michaelschiemer.de
  5. Production: Merge stagingmain → deploy to production

Troubleshooting

Staging not accessible

# Check Traefik routing
docker logs traefik | grep staging

# Verify container is running
docker ps | grep staging

# Check nginx logs
docker logs staging-nginx

Code not updating

# Force code pull in staging-app
docker exec staging-app bash -c "cd /var/www/html && git pull origin staging"
cd ~/deployment/stacks/staging
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml restart staging-app staging-nginx

Cleanup

To remove staging environment:

cd ~/deployment/stacks/staging
docker compose -f docker-compose.base.yml -f docker-compose.staging.yml down -v  # Removes volumes too
docker network rm staging-internal