Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
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
stagingbranch - 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
- Traefik Stack Running (shared with production)
- PostgreSQL Staging Stack Running (separate from production)
cd ../postgresql-staging docker compose up -d - DNS Configuration:
staging.michaelschiemer.depoints to server IP - Docker Networks:
docker network create traefik-public # Shared with production docker network create staging-internal # Staging-only docker network create postgres-staging-internal # Staging database network
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 - using separate staging database stack
DB_DATABASE=michaelschiemer_staging
DB_HOST=postgres-staging
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 (postgres-production) | michaelschiemer_staging (postgres-staging) |
| Database Stack | postgresql-production (separate) | postgresql-staging (separate) |
| Volumes | app-* | staging-* |
| Network | app-internal | staging-internal |
Workflow
- Development: Feature branch → merge to
staging - Auto-Build: Push to
stagingtriggersbuild-image.yml - Auto-Deploy: Successful build auto-deploys to staging (via
deploy-staging.yml) - Testing: Test on https://staging.michaelschiemer.de
- Production: Merge
staging→main→ 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