- Add example secret files for `app_key`, `db_user_password`, and `redis_password`. - Introduce `local.vault.yml.example` for Ansible Vault encryption of local secrets. - Create migration and setup scripts for transitioning from `.env.local` to secrets files. - Update `docker-compose.local.yml` to adopt Docker Secrets and `_FILE` pattern for local configurations. - Add deployment playbooks and enhanced logging configurations for local development.
411 lines
16 KiB
Makefile
411 lines
16 KiB
Makefile
# ----------------------------------
|
|
# Projekt: michaelschiemer.de
|
|
# Docker & Ansible Makefile
|
|
# ----------------------------------
|
|
|
|
PROJECT_NAME = michaelschiemer
|
|
ENV ?= dev
|
|
|
|
# Docker Compose Konfiguration
|
|
COMPOSE_BASE = docker-compose.base.yml
|
|
COMPOSE_LOCAL = docker-compose.local.yml
|
|
COMPOSE_STAGING = docker-compose.staging.yml
|
|
COMPOSE_PRODUCTION = docker-compose.production.yml
|
|
COMPOSE_FILES = -f $(COMPOSE_BASE) -f $(COMPOSE_LOCAL)
|
|
|
|
# Standart Docker Compose Befehle (Lokale Entwicklung)
|
|
|
|
up: ## Startet alle Docker-Container (lokale Entwicklung)
|
|
docker compose $(COMPOSE_FILES) up -d
|
|
|
|
down: ## Stoppt alle Container
|
|
docker compose $(COMPOSE_FILES) down
|
|
|
|
build: ## Baut alle Docker-Images
|
|
docker compose $(COMPOSE_FILES) build
|
|
|
|
restart: ## Neustart aller Container
|
|
./bin/restart
|
|
|
|
logs: ## Zeigt Logs aus Docker
|
|
docker compose $(COMPOSE_FILES) logs -f
|
|
|
|
ps: ## Docker PS
|
|
docker compose $(COMPOSE_FILES) ps
|
|
|
|
reload: ## Dump Autoload & Restart PHP
|
|
docker compose $(COMPOSE_FILES) exec php composer dump-autoload -o
|
|
docker compose $(COMPOSE_FILES) restart php
|
|
|
|
# Local Development Secrets (via Ansible)
|
|
local-secrets: ## Setup Local Development Secrets via Ansible
|
|
ansible-playbook -i deployment/ansible/inventory/local.yml deployment/ansible/playbooks/setup-local-secrets.yml
|
|
|
|
# Staging Environment
|
|
up-staging: ## Startet Staging-Container
|
|
docker compose -f $(COMPOSE_BASE) -f $(COMPOSE_STAGING) up -d
|
|
|
|
down-staging: ## Stoppt Staging-Container
|
|
docker compose -f $(COMPOSE_BASE) -f $(COMPOSE_STAGING) down
|
|
|
|
logs-staging: ## Zeigt Staging-Logs
|
|
docker compose -f $(COMPOSE_BASE) -f $(COMPOSE_STAGING) logs -f
|
|
|
|
# Production Environment
|
|
up-production: ## Startet Production-Container (nur auf Server)
|
|
docker compose -f $(COMPOSE_BASE) -f $(COMPOSE_PRODUCTION) up -d
|
|
|
|
down-production: ## Stoppt Production-Container (nur auf Server)
|
|
docker compose -f $(COMPOSE_BASE) -f $(COMPOSE_PRODUCTION) down
|
|
|
|
logs-production: ## Zeigt Production-Logs (nur auf Server)
|
|
docker compose -f $(COMPOSE_BASE) -f $(COMPOSE_PRODUCTION) logs -f
|
|
|
|
flush-redis: ## Clear Redis cache (FLUSHALL)
|
|
docker exec redis redis-cli FLUSHALL
|
|
|
|
|
|
# Wähle dev- oder prod-PHP-Konfig je nach ENV
|
|
phpinfo:
|
|
@echo "Aktive PHP-Konfiguration: php.$(ENV).ini"
|
|
|
|
# Ansible Deployment
|
|
|
|
setup: ## Führt Ansible Setup aus
|
|
./bin/setup
|
|
|
|
deploy: ## Führt Ansible Deploy aus
|
|
./bin/deploy
|
|
|
|
test: ## Führt alle Tests mit PHP 8.4 aus
|
|
@echo "🧪 Running tests with PHP 8.4..."
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest
|
|
|
|
test-php85: ## Führt alle Tests mit PHP 8.5 aus (Development)
|
|
@echo "🧪 Running tests with PHP 8.5..."
|
|
docker exec php ./vendor/bin/pest
|
|
|
|
test-coverage: ## Führt Tests mit Coverage-Report aus (PHP 8.4)
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest --coverage
|
|
|
|
test-coverage-html: ## Generiert HTML Coverage-Report (PHP 8.4)
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest --coverage-html coverage-html
|
|
@echo "📊 Coverage-Report verfügbar unter: coverage-html/index.html"
|
|
|
|
test-unit: ## Führt nur Unit-Tests aus (PHP 8.4)
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest tests/Unit/
|
|
|
|
test-framework: ## Führt nur Framework-Tests aus (PHP 8.4)
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest tests/Framework/
|
|
|
|
test-domain: ## Führt nur Domain-Tests aus (PHP 8.4)
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest tests/Domain/
|
|
|
|
test-watch: ## Führt Tests im Watch-Modus aus (PHP 8.4)
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest --watch
|
|
|
|
test-parallel: ## Führt Tests parallel aus (PHP 8.4)
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest --parallel
|
|
|
|
test-profile: ## Profiling der langsamsten Tests (PHP 8.4)
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest --profile
|
|
|
|
test-filter: ## Führt spezifische Tests aus (PHP 8.4) (Usage: make test-filter FILTER="EventDispatcher")
|
|
docker compose $(COMPOSE_FILES) --profile test run --rm php-test ./vendor/bin/pest --filter="$(FILTER)"
|
|
|
|
# Security Checks
|
|
security-check: ## Führt Composer Security Audit aus
|
|
docker exec php composer security:audit
|
|
|
|
security-audit-json: ## Führt Security Audit mit JSON-Output aus
|
|
docker exec php composer security:audit-json
|
|
|
|
security-check-prod: ## Prüft nur Production-Dependencies auf Schwachstellen
|
|
docker exec php composer security:check
|
|
|
|
# Cleanup temporärer/metadaten-Dateien
|
|
clean: ## Entfernt temporäre Dateien
|
|
find . -type f -name "*Zone.Identifier" -delete
|
|
find . -type f -name "*.retry" -delete
|
|
|
|
clean-coverage: ## Entfernt Coverage-Reports
|
|
rm -rf coverage-html/ coverage-xml/ coverage.txt
|
|
@echo "🧹 Coverage-Reports entfernt"
|
|
|
|
|
|
static: ## Generate Static Files
|
|
./bin/generate-static.php
|
|
|
|
# Projektstatus
|
|
status: ## Zeigt Container-Status
|
|
@echo "Aktuelles Projekt: $(PROJECT_NAME)"
|
|
@echo "Umgebung: $(ENV)"
|
|
|
|
doctor: ## Prüft ob Komponenten installiert sind
|
|
@echo "🔍 Prüfe Voraussetzungen..."
|
|
@which docker > /dev/null || echo "❌ Docker fehlt"
|
|
@which ansible-playbook > /dev/null || echo "❌ Ansible fehlt"
|
|
@test -f .env || echo "⚠️ .env-Datei fehlt"
|
|
|
|
# Helfer: Automatische Zielübersicht
|
|
help: ## Zeigt diese Hilfe an
|
|
@echo ""
|
|
@echo "🛠 Verfügbare Make-Befehle:"
|
|
@grep -E '^[a-zA-Z_-]+:.*?## ' Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
|
|
@echo ""
|
|
|
|
|
|
console: ## Run console commands (Usage: make console ARGS="command arguments")
|
|
docker exec -it php php console.php $(ARGS)
|
|
|
|
|
|
|
|
composer: ## Use Composer
|
|
docker compose $(COMPOSE_FILES) exec php composer $(ARGS)
|
|
|
|
fix-perms: ## Fix permissions
|
|
sudo chown -R $(USER):$(USER) .
|
|
|
|
cs:
|
|
@$(MAKE) composer ARGS="cs"
|
|
|
|
cs-fix-file: ## Fix code style for a specific file
|
|
docker compose $(COMPOSE_FILES) exec -e PHP_CS_FIXER_IGNORE_ENV=1 php ./vendor/bin/php-cs-fixer fix $(subst \,/,$(FILE))
|
|
|
|
cs-fix: ## Fix code style for all PHP files
|
|
docker compose $(COMPOSE_FILES) exec -e PHP_CS_FIXER_IGNORE_ENV=1 php ./vendor/bin/php-cs-fixer fix
|
|
|
|
phpstan: ## Run PHPStan static analysis
|
|
@$(MAKE) composer ARGS="phpstan"
|
|
|
|
phpstan-baseline: ## Generate PHPStan baseline
|
|
@$(MAKE) composer ARGS="phpstan-baseline"
|
|
|
|
ssh: ## SSH-Verbindung zum Production-Server öffnen (nutzt ~/.ssh/config 'production')
|
|
@echo "🔌 Verbinde zum Production-Server..."
|
|
ssh production
|
|
|
|
ssh-production: ## SSH-Verbindung zum Production-Server öffnen
|
|
@echo "🔌 Verbinde zum Production-Server..."
|
|
ssh production
|
|
|
|
ssh-git: ## SSH-Verbindung zum Git-Server öffnen
|
|
@echo "🔌 Verbinde zum Git-Server..."
|
|
ssh git.michaelschiemer.de
|
|
|
|
ssh-status: ## Status der autossh-Services prüfen
|
|
@echo "📊 Prüfe autossh Service-Status..."
|
|
@systemctl --user status autossh-production.service --no-pager || echo "⚠️ autossh-production.service nicht aktiv"
|
|
@echo ""
|
|
@ps aux | grep autossh | grep -v grep || echo "⚠️ Keine autossh-Prozesse gefunden"
|
|
|
|
ssh-logs: ## Logs der autossh-Services anzeigen
|
|
@echo "📋 Zeige autossh Logs..."
|
|
@journalctl --user -u autossh-production.service -n 20 --no-pager || echo "⚠️ Keine Logs verfügbar"
|
|
|
|
setup-ssh: ## SSH-Schlüssel korrekt einrichten
|
|
mkdir -p ~/.ssh
|
|
cp /mnt/c/Users/Mike/.ssh/test.michaelschiemer.de ~/.ssh/staging
|
|
chmod 600 ~/.ssh/staging
|
|
@echo "SSH-Schlüssel für Staging korrekt eingerichtet"
|
|
|
|
setup-autossh: ## Autossh für persistente SSH-Verbindungen einrichten
|
|
@echo "🔧 Richte autossh für persistente SSH-Verbindungen ein..."
|
|
@bash scripts/setup-autossh.sh both
|
|
|
|
fix-ssh-perms: ## Korrigiert SSH-Schlüsselberechtigungen (veraltet)
|
|
chmod 600 /mnt/c/Users/Mike/.ssh/test.michaelschiemer.de
|
|
@echo "SSH-Schlüsselberechtigungen korrigiert"
|
|
|
|
health:
|
|
ansible-playbook ansible/check.yml
|
|
|
|
|
|
# Ansible Konfiguration
|
|
ANSIBLE_INVENTORY=deployment/ansible/inventory/production.yml
|
|
PLAYBOOK_DIR=deployment/ansible/playbooks/deploy
|
|
TAGS=
|
|
|
|
.PHONY: dev staging production setup-server check
|
|
|
|
# Deployment-Ziele
|
|
dev: ## Lokales Deployment (Development)
|
|
cd deployment/ansible && ansible-playbook -i inventory/production.yml playbooks/deploy/dev.yml --ask-become-pass $(if $(TAGS),--tags="$(TAGS)",)
|
|
|
|
staging: ## Staging-Deployment
|
|
cd deployment/ansible && ansible-playbook -i inventory/production.yml playbooks/deploy/staging.yml $(if $(TAGS),--tags="$(TAGS)",)
|
|
|
|
production: ## Produktions-Deployment
|
|
cd deployment/ansible && ansible-playbook -i inventory/production.yml playbooks/deploy/production.yml $(if $(TAGS),--tags="$(TAGS)",)
|
|
|
|
setup-server: ## Server-Grundkonfiguration
|
|
cd deployment/ansible && ansible-playbook -i inventory/production.yml playbooks/setup-infrastructure.yml $(if $(LIMIT),--limit="$(LIMIT)",) $(if $(TAGS),--tags="$(TAGS)",)
|
|
|
|
check: ## Serververbindung prüfen
|
|
cd deployment/ansible && ansible -i inventory/production.yml all -m ping $(if $(LIMIT),--limit="$(LIMIT)",)
|
|
|
|
# Beispielaufrufe:
|
|
# make staging TAGS="deploy,check"
|
|
# make setup-server LIMIT="staging" TAGS="docker"
|
|
|
|
# Production Update Commands
|
|
update-production: ## Update PHP files on production server
|
|
@echo "🚀 Updating PHP files on production server..."
|
|
@cd deployment && make application ENV=production
|
|
@echo "✅ Production update completed"
|
|
|
|
restart-production: ## Restart production PHP container only
|
|
@echo "🔄 Restarting production PHP container..."
|
|
@ssh -i ~/.ssh/production deploy@94.16.110.151 "cd /var/www/html && docker compose restart php"
|
|
@echo "✅ Production PHP container restarted"
|
|
|
|
deploy-production-quick: ## Quick production deployment via deployment Makefile
|
|
@echo "⚡ Quick production deployment..."
|
|
@cd deployment && make deploy-quick ENV=production
|
|
@echo "✅ Quick production deployment completed"
|
|
|
|
status-production: ## Check production deployment status
|
|
@echo "📊 Checking production status..."
|
|
@cd deployment && make status ENV=production
|
|
|
|
logs-production: ## Show production logs
|
|
@echo "📋 Showing production logs..."
|
|
@cd deployment && make logs-prod-php
|
|
|
|
logs-staging: ## Show staging-app container logs via SSH (container stdout/stderr)
|
|
@echo "📋 Showing staging-app container logs..."
|
|
@ssh -i ~/.ssh/production deploy@94.16.110.151 "cd ~/deployment/stacks/staging && docker compose logs -f staging-app"
|
|
|
|
logs-staging-php: ## Show PHP application logs from staging-app (log files)
|
|
@echo "📋 Showing PHP application logs from staging-app..."
|
|
@ssh -i ~/.ssh/production deploy@94.16.110.151 "docker exec -i staging-app tail -f /var/www/html/storage/logs/*.log 2>/dev/null || docker exec -i staging-app ls -la /var/www/html/storage/logs/ 2>/dev/null || echo 'Log directory /var/www/html/storage/logs/ not accessible'"
|
|
|
|
cache-clear-staging: ## Clear cache on staging server
|
|
@echo "🗑️ Clearing cache on staging server..."
|
|
@ssh -i ~/.ssh/production deploy@94.16.110.151 "cd ~/deployment/stacks/staging && docker compose exec staging-app php console.php cache:clear"
|
|
@echo "✅ Cache cleared on staging server"
|
|
|
|
cache-clear: ## Clear cache locally
|
|
@echo "🗑️ Clearing cache locally..."
|
|
docker exec php php console.php cache:clear
|
|
@echo "✅ Cache cleared locally"
|
|
|
|
# SSL Certificate Management (PHP Framework Integration)
|
|
ssl-init: ## Initialize Let's Encrypt certificates
|
|
@echo "🔒 Initializing SSL certificates..."
|
|
docker exec php php console.php ssl:init
|
|
|
|
ssl-init-staging: ## Initialize Let's Encrypt certificates (Staging/Testing)
|
|
@echo "🔒 Initializing SSL certificates (Staging Mode)..."
|
|
@echo "💡 Hint: Set LETSENCRYPT_STAGING=1 in .env for staging mode"
|
|
docker exec php php console.php ssl:init
|
|
|
|
ssl-test: ## Test SSL configuration
|
|
@echo "🔍 Testing SSL configuration..."
|
|
docker exec php php console.php ssl:test
|
|
|
|
ssl-renew: ## Manually renew certificates
|
|
@echo "🔄 Renewing SSL certificates..."
|
|
docker exec php php console.php ssl:renew
|
|
|
|
ssl-status: ## Check certificate status and expiry
|
|
@echo "📋 Certificate status:"
|
|
docker exec php php console.php ssl:status
|
|
|
|
ssl-backup: ## Backup Let's Encrypt certificates
|
|
@echo "💾 Backing up SSL certificates..."
|
|
@mkdir -p backups
|
|
docker run --rm \
|
|
-v certbot-conf:/etc/letsencrypt \
|
|
-v $(PWD)/backups:/backup \
|
|
alpine tar czf /backup/letsencrypt-$(shell date +%Y%m%d-%H%M%S).tar.gz /etc/letsencrypt
|
|
@echo "✅ Backup created in backups/"
|
|
|
|
push-staging: ## Pusht den aktuellen Stand nach origin/staging
|
|
git push origin HEAD:staging
|
|
|
|
# ENV File Management
|
|
env-base: ## Erstellt .env.base aus .env.example (gemeinsame Variablen)
|
|
@if [ ! -f .env.example ]; then \
|
|
echo "❌ .env.example nicht gefunden"; \
|
|
exit 1; \
|
|
fi
|
|
@if [ -f .env.base ]; then \
|
|
echo "⚠️ .env.base existiert bereits. Überschreiben? (j/n)"; \
|
|
read confirm; \
|
|
if [ "$$confirm" != "j" ]; then \
|
|
echo "❌ Abgebrochen"; \
|
|
exit 1; \
|
|
fi
|
|
fi
|
|
@echo "📝 Erstelle .env.base aus .env.example..."
|
|
@cp .env.example .env.base
|
|
@echo "✅ .env.base erstellt"
|
|
@echo "💡 Bearbeite .env.base und entferne environment-spezifische Variablen"
|
|
@echo "💡 Siehe ENV_SETUP.md für Details"
|
|
|
|
env-local: ## Erstellt .env.local für lokale Development-Overrides
|
|
@if [ -f .env.local ]; then \
|
|
echo "⚠️ .env.local existiert bereits. Überschreiben? (j/n)"; \
|
|
read confirm; \
|
|
if [ "$$confirm" != "j" ]; then \
|
|
echo "❌ Abgebrochen"; \
|
|
exit 1; \
|
|
fi
|
|
fi
|
|
@echo "📝 Erstelle .env.local..."
|
|
@if [ -f .env ]; then \
|
|
cp .env .env.local; \
|
|
echo "✅ .env.local erstellt aus .env"; \
|
|
else \
|
|
echo "APP_ENV=development" > .env.local; \
|
|
echo "APP_DEBUG=true" >> .env.local; \
|
|
echo "✅ .env.local erstellt (Minimal-Version)"; \
|
|
fi
|
|
@echo "💡 Bearbeite .env.local mit deinen lokalen Overrides"
|
|
@echo "💡 Siehe ENV_SETUP.md für Details"
|
|
|
|
env-check: ## Prüft .env.base auf Secrets (sollte keine enthalten)
|
|
@echo "🔍 Prüfe .env.base auf Secrets..."
|
|
@if [ ! -f .env.base ]; then \
|
|
echo "✅ .env.base existiert nicht (optional)"; \
|
|
exit 0; \
|
|
fi
|
|
@if grep -E "(PASSWORD|KEY|SECRET|TOKEN)" .env.base | grep -v "^#" | grep -v "=" | grep -v "^$$" > /dev/null; then \
|
|
echo "⚠️ Warnung: .env.base könnte Secrets enthalten:"; \
|
|
grep -E "(PASSWORD|KEY|SECRET|TOKEN)" .env.base | grep -v "^#" | grep -v "=" || true; \
|
|
echo "💡 Secrets sollten in .env.local oder Docker Secrets sein"; \
|
|
exit 1; \
|
|
else \
|
|
echo "✅ .env.base enthält keine Secrets"; \
|
|
fi
|
|
@echo ""
|
|
@echo "🔍 Prüfe docker-compose.base.yml auf hardcodierte Passwörter..."
|
|
@if grep -E "(PASSWORD|SECRET|TOKEN).*:-[^}]*[^}]}" docker-compose.base.yml | grep -v "^#" | grep -v "FILE=" > /dev/null 2>&1; then \
|
|
echo "⚠️ Warnung: docker-compose.base.yml enthält möglicherweise hardcodierte Passwörter:"; \
|
|
grep -E "(PASSWORD|SECRET|TOKEN).*:-[^}]*[^}]}" docker-compose.base.yml | grep -v "^#" | grep -v "FILE=" || true; \
|
|
echo "💡 Passwörter müssen explizit gesetzt werden, keine Fallbacks in Base-Datei"; \
|
|
exit 1; \
|
|
else \
|
|
echo "✅ docker-compose.base.yml enthält keine hardcodierten Passwörter"; \
|
|
fi
|
|
|
|
env-validate: ## Validiert ENV-Files (Base+Override Pattern)
|
|
@echo "🔍 Validiere ENV-Files..."
|
|
@if [ -f .env.base ]; then \
|
|
echo "✅ .env.base existiert"; \
|
|
else \
|
|
echo "⚠️ .env.base nicht gefunden (optional für Migration)"; \
|
|
fi
|
|
@if [ -f .env.local ]; then \
|
|
echo "✅ .env.local existiert"; \
|
|
else \
|
|
echo "⚠️ .env.local nicht gefunden"; \
|
|
fi
|
|
@if [ -f .env ] && [ ! -f .env.base ]; then \
|
|
echo "✅ Legacy .env verwendet (Fallback)"; \
|
|
fi
|
|
@echo "💡 Framework lädt: .env.base → .env.local → System ENV"
|
|
|
|
.PHONY: up down build restart logs ps phpinfo deploy setup clean clean-coverage status fix-ssh-perms setup-ssh setup-autossh ssh ssh-production ssh-git ssh-status ssh-logs test test-coverage test-coverage-html test-unit test-framework test-domain test-watch test-parallel test-profile test-filter security-check security-audit-json security-check-prod update-production restart-production deploy-production-quick status-production logs-production logs-staging logs-staging-php cache-clear-staging cache-clear ssl-init ssl-init-staging ssl-test ssl-renew ssl-status ssl-backup push-staging env-base env-local env-check env-validate
|