feat: Fix discovery system critical issues
Resolved multiple critical discovery system issues: ## Discovery System Fixes - Fixed console commands not being discovered on first run - Implemented fallback discovery for empty caches - Added context-aware caching with separate cache keys - Fixed object serialization preventing __PHP_Incomplete_Class ## Cache System Improvements - Smart caching that only caches meaningful results - Separate caches for different execution contexts (console, web, test) - Proper array serialization/deserialization for cache compatibility - Cache hit logging for debugging and monitoring ## Object Serialization Fixes - Fixed DiscoveredAttribute serialization with proper string conversion - Sanitized additional data to prevent object reference issues - Added fallback for corrupted cache entries ## Performance & Reliability - All 69 console commands properly discovered and cached - 534 total discovery items successfully cached and restored - No more __PHP_Incomplete_Class cache corruption - Improved error handling and graceful fallbacks ## Testing & Quality - Fixed code style issues across discovery components - Enhanced logging for better debugging capabilities - Improved cache validation and error recovery Ready for production deployment with stable discovery system. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
95
.deployment-backup/BACKUP_SUMMARY.md
Normal file
95
.deployment-backup/BACKUP_SUMMARY.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Deployment Backup Summary
|
||||
|
||||
This directory contains the old deployment configurations that were moved during the modernization of the deployment system.
|
||||
|
||||
## Moved Directories
|
||||
|
||||
### ansible/
|
||||
**Original Location**: `/ansible/`
|
||||
**Contents**: Multiple Ansible deployment configurations
|
||||
- `netcup-simple-deploy/` - Basic server deployment setup
|
||||
- `nginx-cdn-germany/` - CDN and Nginx configuration for German servers
|
||||
- `wireguard-server/` - VPN server setup and client management
|
||||
|
||||
**Key Features Preserved**:
|
||||
- Server setup automation
|
||||
- Nginx reverse proxy configuration
|
||||
- SSL certificate management
|
||||
- Multi-environment support (staging/production)
|
||||
|
||||
### x_ansible/
|
||||
**Original Location**: `/x_ansible/`
|
||||
**Contents**: Alternative Ansible setup with different structure
|
||||
- Complete playbook structure with inventories
|
||||
- Docker Compose integration
|
||||
- Environment-specific configurations
|
||||
- Deployment and setup scripts
|
||||
|
||||
### ssl/
|
||||
**Original Location**: `/ssl/`
|
||||
**Contents**: SSL certificates and keys for local development
|
||||
- `fullchain.pem` - Certificate chain
|
||||
- `privkey.pem` - Private key
|
||||
- `rootCA.*` - Root certificate authority files
|
||||
- `localhost.*` - Local development certificates
|
||||
|
||||
**Note**: These certificates will be integrated into the new SSL management system in `deployment/configs/ssl/`
|
||||
|
||||
### bin/
|
||||
**Original Location**: `/bin/`
|
||||
**Contents**: Deployment utility scripts
|
||||
- `deploy` - Environment-specific deployment script
|
||||
- `setup` - Server setup script
|
||||
- `up`, `down`, `restart` - Docker management scripts
|
||||
- `logs`, `test`, `check-env` - Utility scripts
|
||||
|
||||
**Note**: Functionality from these scripts will be modernized and integrated into `deployment/scripts/`
|
||||
|
||||
## Migration Path
|
||||
|
||||
The new deployment system in `/deployment/` consolidates and modernizes these configurations:
|
||||
|
||||
1. **Infrastructure** (`/deployment/infrastructure/`):
|
||||
- Consolidates Ansible playbooks from both `ansible/` directories
|
||||
- Adds modern server configuration management
|
||||
- Implements security best practices
|
||||
|
||||
2. **Applications** (`/deployment/applications/`):
|
||||
- Modernizes Docker Compose configurations
|
||||
- Adds environment-specific optimizations
|
||||
- Integrates health checking and monitoring
|
||||
|
||||
3. **Scripts** (`/deployment/scripts/`):
|
||||
- Modernizes and consolidates utility scripts from `bin/`
|
||||
- Adds deployment orchestration capabilities
|
||||
- Implements rollback and recovery features
|
||||
|
||||
4. **Configs** (`/deployment/configs/`):
|
||||
- Centralizes configuration templates
|
||||
- Integrates SSL certificate management
|
||||
- Adds monitoring and logging configurations
|
||||
|
||||
## Recovery Instructions
|
||||
|
||||
If you need to revert to the old deployment system:
|
||||
|
||||
1. Stop any new deployment processes
|
||||
2. Move directories back from `.deployment-backup/` to their original locations:
|
||||
```bash
|
||||
mv .deployment-backup/ansible ./
|
||||
mv .deployment-backup/x_ansible ./
|
||||
mv .deployment-backup/ssl ./
|
||||
mv .deployment-backup/bin ./
|
||||
```
|
||||
3. Update any references to the new deployment system
|
||||
|
||||
## Preservation Notes
|
||||
|
||||
- All original files are preserved unchanged
|
||||
- Directory structure maintained as-is
|
||||
- No modifications made to original configurations
|
||||
- Can be used for reference during new system development
|
||||
|
||||
## Cleanup
|
||||
|
||||
Once the new deployment system is fully tested and deployed, this backup directory can be removed. Recommended timeline: Keep for at least 30 days after successful production deployment of the new system.
|
||||
6
.deployment-backup/ansible/netcup-simple-deploy/.gitignore
vendored
Normal file
6
.deployment-backup/ansible/netcup-simple-deploy/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# .gitignore für Netcup Deployment
|
||||
*.retry
|
||||
.ansible/
|
||||
*.log
|
||||
.env.local
|
||||
secrets.yml
|
||||
136
.deployment-backup/ansible/netcup-simple-deploy/Makefile
Normal file
136
.deployment-backup/ansible/netcup-simple-deploy/Makefile
Normal file
@@ -0,0 +1,136 @@
|
||||
# Test Makefile für rsync debugging (Fixed)
|
||||
|
||||
.PHONY: test-rsync debug-sync upload restart quick-deploy
|
||||
|
||||
# Teste manuellen rsync
|
||||
test-rsync:
|
||||
@echo "🔍 Testing manual rsync..."
|
||||
@SERVER_IP=$$(grep ansible_host inventory/hosts.yml | awk '{print $$2}'); \
|
||||
echo "Server IP: $$SERVER_IP"; \
|
||||
APP_PATH=$$(grep local_app_path inventory/hosts.yml | awk '{print $$2}' | tr -d '"'); \
|
||||
echo "Local path: $$APP_PATH"; \
|
||||
echo ""; \
|
||||
echo "=== Testing dry-run rsync ==="; \
|
||||
rsync -av --dry-run \
|
||||
--exclude='ansible' \
|
||||
--exclude='.git' \
|
||||
--exclude='vendor' \
|
||||
--exclude='node_modules' \
|
||||
--exclude='storage/logs' \
|
||||
--exclude='cache' \
|
||||
--exclude='logs' \
|
||||
--exclude='dist' \
|
||||
--exclude='.archive' \
|
||||
$$APP_PATH/ root@$$SERVER_IP:/opt/myapp/; \
|
||||
echo ""; \
|
||||
echo "If this shows files, then rsync should work"
|
||||
|
||||
# Debug was in lokalen Dateien ist
|
||||
debug-local:
|
||||
@echo "📁 Local files debug:"
|
||||
@APP_PATH=$$(grep local_app_path inventory/hosts.yml | awk '{print $$2}' | tr -d '"'); \
|
||||
echo "Path: $$APP_PATH"; \
|
||||
echo ""; \
|
||||
if [ -z "$$APP_PATH" ]; then \
|
||||
echo "❌ APP_PATH is empty!"; \
|
||||
echo "Raw line from hosts.yml:"; \
|
||||
grep local_app_path inventory/hosts.yml; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
echo "=== Root files ==="; \
|
||||
ls -la "$$APP_PATH" | head -10; \
|
||||
echo ""; \
|
||||
echo "=== Public files ==="; \
|
||||
ls -la "$$APP_PATH/public" | head -10; \
|
||||
echo ""; \
|
||||
echo "=== Does index.php exist locally? ==="; \
|
||||
if [ -f "$$APP_PATH/public/index.php" ]; then \
|
||||
echo "✅ index.php exists locally"; \
|
||||
echo "Size: $$(wc -c < $$APP_PATH/public/index.php) bytes"; \
|
||||
echo "Content preview:"; \
|
||||
head -5 "$$APP_PATH/public/index.php"; \
|
||||
else \
|
||||
echo "❌ index.php NOT found locally!"; \
|
||||
echo "Checking if public folder exists:"; \
|
||||
if [ -d "$$APP_PATH/public" ]; then \
|
||||
echo "Public folder exists, contents:"; \
|
||||
ls -la "$$APP_PATH/public/"; \
|
||||
else \
|
||||
echo "Public folder does not exist!"; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
# Test direkt mit absoluten Pfaden
|
||||
debug-direct:
|
||||
@echo "📁 Direct path test:"
|
||||
@echo "=== Current directory ==="
|
||||
pwd
|
||||
@echo ""
|
||||
@echo "=== Going to project root ==="
|
||||
cd ../.. && pwd
|
||||
@echo ""
|
||||
@echo "=== Files in project root ==="
|
||||
cd ../.. && ls -la | head -10
|
||||
@echo ""
|
||||
@echo "=== Public folder ==="
|
||||
cd ../.. && ls -la public/ | head -10
|
||||
@echo ""
|
||||
@echo "=== Index.php check ==="
|
||||
cd ../.. && if [ -f "public/index.php" ]; then \
|
||||
echo "✅ index.php found!"; \
|
||||
echo "Size: $$(wc -c < public/index.php) bytes"; \
|
||||
else \
|
||||
echo "❌ index.php not found"; \
|
||||
fi
|
||||
|
||||
# Test Ansible synchronize mit debug
|
||||
debug-sync:
|
||||
@echo "🔍 Testing Ansible synchronize with debug..."
|
||||
ansible-playbook -i inventory/hosts.yml debug-sync.yml -v
|
||||
|
||||
# Upload files only (no infrastructure setup)
|
||||
upload:
|
||||
@echo "📤 Uploading files only..."
|
||||
ansible-playbook -i inventory/hosts.yml upload-only.yml
|
||||
|
||||
# Restart application after upload
|
||||
restart:
|
||||
@echo "🔄 Restarting application..."
|
||||
ansible-playbook -i inventory/hosts.yml restart-app.yml
|
||||
|
||||
# Quick upload and restart
|
||||
quick-deploy:
|
||||
@echo "⚡ Quick deploy: upload + restart..."
|
||||
ansible-playbook -i inventory/hosts.yml upload-only.yml
|
||||
ansible-playbook -i inventory/hosts.yml restart-app.yml
|
||||
|
||||
# Alle Standard-Befehle
|
||||
deploy:
|
||||
@echo "🚀 Deploying project to Netcup..."
|
||||
chmod +x deploy.sh
|
||||
./deploy.sh
|
||||
|
||||
check:
|
||||
@echo "🔍 Testing configuration..."
|
||||
ansible all -m ping
|
||||
|
||||
logs:
|
||||
@echo "📋 Showing container logs..."
|
||||
ansible all -m shell -a "cd /opt/myapp && (docker compose logs --tail 100 || docker-compose logs --tail 100)"
|
||||
|
||||
help:
|
||||
@echo "📖 Debug commands:"
|
||||
@echo " make debug-local - Check local files"
|
||||
@echo " make debug-direct - Check with direct paths"
|
||||
@echo " make test-rsync - Test manual rsync"
|
||||
@echo " make debug-sync - Test Ansible sync"
|
||||
@echo ""
|
||||
@echo "📖 Deploy commands:"
|
||||
@echo " make deploy - Full deployment (infrastructure + app)"
|
||||
@echo " make upload - Upload files only (no infrastructure)"
|
||||
@echo " make restart - Restart application containers"
|
||||
@echo " make quick-deploy - Upload files + restart (fastest)"
|
||||
@echo ""
|
||||
@echo "📖 Utility commands:"
|
||||
@echo " make logs - Show container logs"
|
||||
@echo " make check - Test connection"
|
||||
128
.deployment-backup/ansible/netcup-simple-deploy/QUICK-SETUP.md
Normal file
128
.deployment-backup/ansible/netcup-simple-deploy/QUICK-SETUP.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Netcup Quick Setup Guide
|
||||
|
||||
## 1. Server vorbereiten
|
||||
|
||||
### Netcup VPS bestellen
|
||||
- **Mindestens:** VPS 200 G8 (2 CPU, 4GB RAM)
|
||||
- **OS:** Ubuntu 22.04 LTS
|
||||
- **Netzwerk:** IPv4 + IPv6
|
||||
|
||||
### SSH-Key installieren
|
||||
```bash
|
||||
# SSH-Key generieren (falls noch nicht vorhanden)
|
||||
ssh-keygen -t ed25519 -C "netcup-deploy"
|
||||
|
||||
# Key zum Server kopieren
|
||||
ssh-copy-id root@DEINE-SERVER-IP
|
||||
```
|
||||
|
||||
## 2. Konfiguration
|
||||
|
||||
### Basis-Einstellungen
|
||||
```bash
|
||||
# Server-Details eintragen
|
||||
vim inventory/hosts.yml
|
||||
```
|
||||
|
||||
**Wichtig ändern:**
|
||||
- `ansible_host: 85.123.456.789` → deine Netcup IP
|
||||
- `domain: "example.com"` → deine Domain
|
||||
- `ssl_email: "admin@example.com"` → deine E-Mail
|
||||
- `git_repo: "https://github.com/user/repo.git"` → dein Git Repository
|
||||
|
||||
### DNS konfigurieren
|
||||
Stelle sicher dass deine Domain zur Netcup IP zeigt:
|
||||
```bash
|
||||
# A-Record setzen
|
||||
example.com. IN A DEINE-NETCUP-IP
|
||||
```
|
||||
|
||||
## 3. App-Anforderungen
|
||||
|
||||
Deine App braucht:
|
||||
- **Dockerfile** im Repository-Root
|
||||
- **Port 3000** (oder ändere `app_port` in hosts.yml)
|
||||
- **Health-Check** Endpoint `/health` (oder ändere `health_check_url`)
|
||||
|
||||
### Beispiel Dockerfile (Node.js)
|
||||
```dockerfile
|
||||
FROM node:18-alpine
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
COPY . .
|
||||
EXPOSE 3000
|
||||
CMD ["npm", "start"]
|
||||
```
|
||||
|
||||
### Beispiel Health-Check (Express.js)
|
||||
```javascript
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
||||
});
|
||||
```
|
||||
|
||||
## 4. Deployment
|
||||
|
||||
```bash
|
||||
# Einfach deployen
|
||||
make deploy
|
||||
|
||||
# Oder manuell
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
## 5. Troubleshooting
|
||||
|
||||
### Server nicht erreichbar?
|
||||
```bash
|
||||
# Ping testen
|
||||
ping DEINE-SERVER-IP
|
||||
|
||||
# SSH testen
|
||||
ssh root@DEINE-SERVER-IP
|
||||
|
||||
# Firewall prüfen (auf dem Server)
|
||||
ufw status
|
||||
```
|
||||
|
||||
### SSL-Probleme?
|
||||
```bash
|
||||
# DNS prüfen
|
||||
nslookup DEINE-DOMAIN
|
||||
|
||||
# Certbot manuell
|
||||
ssh root@DEINE-SERVER-IP
|
||||
certbot certificates
|
||||
```
|
||||
|
||||
### App startet nicht?
|
||||
```bash
|
||||
# Logs anschauen
|
||||
make logs
|
||||
|
||||
# Container status
|
||||
ansible all -m shell -a "docker ps -a"
|
||||
|
||||
# Ins Container einsteigen
|
||||
ansible all -m shell -a "docker exec -it CONTAINER_NAME sh"
|
||||
```
|
||||
|
||||
## 6. Nach dem Deployment
|
||||
|
||||
- ✅ **App testen:** https://deine-domain.com
|
||||
- ✅ **Health-Check:** https://deine-domain.com/health
|
||||
- ✅ **SSL prüfen:** https://www.ssllabs.com/ssltest/
|
||||
- ✅ **Performance:** https://pagespeed.web.dev/
|
||||
|
||||
## 7. Updates
|
||||
|
||||
```bash
|
||||
# App updaten (git pull + rebuild)
|
||||
make update
|
||||
|
||||
# Logs nach Update prüfen
|
||||
make logs
|
||||
```
|
||||
|
||||
Das war's! Deine App läuft jetzt auf Netcup mit SSL! 🎉
|
||||
40
.deployment-backup/ansible/netcup-simple-deploy/README.md
Normal file
40
.deployment-backup/ansible/netcup-simple-deploy/README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Netcup Simple Deploy
|
||||
|
||||
Ultra-einfaches Ansible-Setup für Netcup VPS Deployment.
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Server-Info eintragen:**
|
||||
```bash
|
||||
vim inventory/hosts.yml
|
||||
# Deine Netcup-Server IP und Domain eintragen
|
||||
```
|
||||
|
||||
2. **App-Einstellungen:**
|
||||
```bash
|
||||
vim inventory/group_vars.yml
|
||||
# Domain, Repo, etc. anpassen
|
||||
```
|
||||
|
||||
3. **Deployen:**
|
||||
```bash
|
||||
ansible-playbook deploy.yml
|
||||
```
|
||||
|
||||
## Was wird installiert
|
||||
|
||||
✅ Docker & Docker Compose
|
||||
✅ Nginx Reverse Proxy
|
||||
✅ SSL mit Let's Encrypt
|
||||
✅ Deine App aus Git
|
||||
✅ Automatische Updates
|
||||
|
||||
## Features
|
||||
|
||||
- 🚀 **Ein Kommando** deployment
|
||||
- 🔒 **Automatisches SSL**
|
||||
- 🐳 **Docker-basiert**
|
||||
- 📱 **Health Checks**
|
||||
- 🔄 **Zero-Downtime Updates**
|
||||
|
||||
Perfekt für einfache Web-Apps auf Netcup VPS!
|
||||
@@ -0,0 +1,81 @@
|
||||
# Production Server Setup - Debian 12
|
||||
|
||||
## Netcup Panel Konfiguration
|
||||
|
||||
### 1. Fresh OS Installation
|
||||
1. **Netcup Panel** → "Server" → Ihr Server
|
||||
2. **"Betriebssystem"** → "Neu installieren"
|
||||
3. **OS wählen**: `Debian 12 (Bookworm)` 64-bit
|
||||
4. **Installation starten** und warten bis abgeschlossen
|
||||
|
||||
### 2. SSH-Key Konfiguration
|
||||
1. **SSH-Key hinzufügen**:
|
||||
```
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA3DqB1B4wa5Eo116bJ1HybFagK3fU0i+wJ6mAHI1L3i production@michaelschiemer.de
|
||||
```
|
||||
|
||||
2. **Im Netcup Panel**:
|
||||
- "SSH-Keys" → "Neuen SSH-Key hinzufügen"
|
||||
- Name: `production-michaelschiemer`
|
||||
- Key: (oben kopieren und einfügen)
|
||||
- Key dem Server zuweisen
|
||||
|
||||
### 3. Root-Zugang aktivieren
|
||||
1. **Console/KVM** über Netcup Panel öffnen
|
||||
2. **Als root einloggen** (initial Setup)
|
||||
3. **SSH-Key für root aktivieren**:
|
||||
```bash
|
||||
# SSH-Key bereits durch Panel hinzugefügt
|
||||
# Root SSH sollte funktionieren
|
||||
```
|
||||
|
||||
### 4. Deploy User einrichten
|
||||
```bash
|
||||
# Als root ausführen:
|
||||
useradd -m -s /bin/bash deploy
|
||||
usermod -aG sudo deploy
|
||||
|
||||
# SSH-Key für deploy user
|
||||
mkdir -p /home/deploy/.ssh
|
||||
cp /root/.ssh/authorized_keys /home/deploy/.ssh/
|
||||
chown -R deploy:deploy /home/deploy/.ssh
|
||||
chmod 700 /home/deploy/.ssh
|
||||
chmod 600 /home/deploy/.ssh/authorized_keys
|
||||
|
||||
# Sudo ohne Passwort für deploy
|
||||
echo "deploy ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/deploy
|
||||
```
|
||||
|
||||
## Warum Debian 12?
|
||||
|
||||
### Production-Vorteile:
|
||||
- ✅ **Stabilität**: Bewährte LTS-Pakete, längere Support-Zyklen
|
||||
- ✅ **Performance**: Geringerer Ressourcenverbrauch als Ubuntu
|
||||
- ✅ **Security**: Conservative Updates, weniger experimentelle Features
|
||||
- ✅ **Docker-Optimiert**: Perfekt für containerisierte Deployments
|
||||
- ✅ **Minimale Basis**: Nur essentielle Pakete, weniger Attack Surface
|
||||
|
||||
### Server-Spezifikationen:
|
||||
- **RAM**: Minimum 2GB (empfohlen 4GB+)
|
||||
- **Storage**: Minimum 20GB SSD
|
||||
- **CPU**: 1+ vCPU (empfohlen 2+ vCPU)
|
||||
- **Network**: Stable internet, static IP
|
||||
|
||||
## Nach Installation testen:
|
||||
|
||||
```bash
|
||||
# SSH-Connectivity Test
|
||||
ssh -i ~/.ssh/production deploy@94.16.110.151
|
||||
|
||||
# System Info
|
||||
ssh -i ~/.ssh/production deploy@94.16.110.151 'uname -a && lsb_release -a'
|
||||
```
|
||||
|
||||
## Nächste Schritte:
|
||||
Nach erfolgreichem Server-Setup:
|
||||
1. SSH-Connectivity bestätigen
|
||||
2. Ansible Ping-Test durchführen
|
||||
3. Deployment-Playbook ausführen
|
||||
|
||||
---
|
||||
**🔑 SSH-Key Fingerprint**: `SHA256:7FBYrZpDcYcKXpeM8OHoGZZBHwxNORoOFWuzP2MpDpQ`
|
||||
161
.deployment-backup/ansible/netcup-simple-deploy/SETUP-COMPOSE.md
Normal file
161
.deployment-backup/ansible/netcup-simple-deploy/SETUP-COMPOSE.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# Projekt Setup für Netcup (nutzt deine docker-compose.yml)
|
||||
|
||||
## Projektstruktur
|
||||
|
||||
Das Deployment nutzt deine bestehende Docker-Konfiguration:
|
||||
|
||||
```
|
||||
dein-projekt/ # Hauptordner
|
||||
├── ansible/ # Hier sind wir jetzt
|
||||
│ └── netcup-simple-deploy/
|
||||
├── docker-compose.yml # ← DEINE Compose-Datei (wird verwendet!)
|
||||
├── docker/ # Docker-Konfiguration
|
||||
│ ├── Dockerfile
|
||||
│ └── docker-compose.yml # ← Alternative hier
|
||||
├── src/ # PHP Framework/Library Dateien
|
||||
├── public/ # Web-Root
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Was das Deployment macht:
|
||||
|
||||
✅ **Nutzt deine bestehende docker-compose.yml**
|
||||
✅ **Startet ALLE deine Services** (DB, Redis, etc.)
|
||||
✅ **Überträgt komplettes Projekt**
|
||||
✅ **Nginx als Reverse Proxy** für SSL
|
||||
|
||||
## Quick Setup
|
||||
|
||||
### 1. Konfiguration
|
||||
```bash
|
||||
cd ansible/netcup-simple-deploy
|
||||
vim inventory/hosts.yml
|
||||
```
|
||||
|
||||
**Wichtig ändern:**
|
||||
```yaml
|
||||
ansible_host: DEINE-NETCUP-IP
|
||||
domain: "deine-domain.com"
|
||||
app_port: 8080 # Port deiner App aus docker-compose.yml
|
||||
```
|
||||
|
||||
### 2. Port prüfen
|
||||
Schaue in deine `docker-compose.yml` welchen Port deine App exponiertrt:
|
||||
```yaml
|
||||
services:
|
||||
myapp:
|
||||
ports:
|
||||
- "8080:80" # ← Dann ist app_port: 8080
|
||||
```
|
||||
|
||||
### 3. Deployment
|
||||
```bash
|
||||
make deploy
|
||||
```
|
||||
|
||||
## Beispiel docker-compose.yml Strukturen
|
||||
|
||||
### Einfache PHP App
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
ports:
|
||||
- "8080:80"
|
||||
volumes:
|
||||
- ./src:/var/www/src
|
||||
- ./public:/var/www/html
|
||||
```
|
||||
|
||||
### Mit Datenbank
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
ports:
|
||||
- "8080:80"
|
||||
depends_on:
|
||||
- db
|
||||
environment:
|
||||
- DATABASE_URL=mysql://user:pass@db:3306/myapp
|
||||
|
||||
db:
|
||||
image: mysql:8.0
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=secret
|
||||
- MYSQL_DATABASE=myapp
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
```
|
||||
|
||||
### Mit Redis + Database
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
ports:
|
||||
- "8080:80"
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
|
||||
db:
|
||||
image: postgres:15
|
||||
environment:
|
||||
- POSTGRES_DB=myapp
|
||||
- POSTGRES_USER=user
|
||||
- POSTGRES_PASSWORD=secret
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
```
|
||||
|
||||
## Nach dem Deployment
|
||||
|
||||
**Alle Services verwalten:**
|
||||
```bash
|
||||
make services # Zeige alle Services
|
||||
make logs-service # Logs für bestimmten Service
|
||||
make status # Status aller Container
|
||||
make shell # In Container einsteigen
|
||||
```
|
||||
|
||||
**Updates:**
|
||||
```bash
|
||||
# Nach Änderungen an Code oder docker-compose.yml
|
||||
make deploy
|
||||
|
||||
# Nur Container neu bauen
|
||||
make rebuild
|
||||
```
|
||||
|
||||
**Monitoring:**
|
||||
```bash
|
||||
make logs # Alle Logs
|
||||
make tail-logs # Live logs
|
||||
make show-env # Environment variables
|
||||
```
|
||||
|
||||
## Vorteile dieser Lösung
|
||||
|
||||
✅ **Deine bestehende Konfiguration** wird verwendet
|
||||
✅ **Alle Services** (DB, Redis, etc.) funktionieren
|
||||
✅ **Keine Code-Änderungen** nötig
|
||||
✅ **SSL-Termination** durch nginx
|
||||
✅ **Einfache Updates** mit make deploy
|
||||
|
||||
Das Deployment ist jetzt vollständig auf deine bestehende Docker-Infrastruktur ausgerichtet! 🎉
|
||||
@@ -0,0 +1,172 @@
|
||||
# Netcup Setup ohne Git
|
||||
|
||||
## 1. App-Struktur vorbereiten
|
||||
|
||||
### Option A: Bestehende App
|
||||
Falls du bereits eine App hast, stelle sicher dass sie diese Struktur hat:
|
||||
```
|
||||
deine-app/
|
||||
├── package.json # Node.js Abhängigkeiten
|
||||
├── server.js # Hauptdatei
|
||||
├── Dockerfile # Docker-Konfiguration
|
||||
└── ... weitere Dateien
|
||||
```
|
||||
|
||||
### Option B: Neue App erstellen
|
||||
```bash
|
||||
# Erstelle App-Verzeichnis
|
||||
mkdir -p ~/meine-app
|
||||
|
||||
# Beispiel Node.js App
|
||||
cd ~/meine-app
|
||||
|
||||
# package.json
|
||||
cat > package.json << 'EOF'
|
||||
{
|
||||
"name": "meine-app",
|
||||
"version": "1.0.0",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.18.0"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# server.js
|
||||
cat > server.js << 'EOF'
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.json({
|
||||
message: 'Hello World!',
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({ status: 'ok' });
|
||||
});
|
||||
|
||||
app.listen(port, '0.0.0.0', () => {
|
||||
console.log(`Server running on port ${port}`);
|
||||
});
|
||||
EOF
|
||||
|
||||
# Dockerfile
|
||||
cat > Dockerfile << 'EOF'
|
||||
FROM node:18-alpine
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
EXPOSE 3000
|
||||
CMD ["npm", "start"]
|
||||
EOF
|
||||
```
|
||||
|
||||
## 2. Ansible konfigurieren
|
||||
|
||||
```bash
|
||||
# Ins Deployment-Verzeichnis
|
||||
cd ansible/netcup-simple-deploy
|
||||
|
||||
# Konfiguration anpassen
|
||||
vim inventory/hosts.yml
|
||||
```
|
||||
|
||||
**Wichtige Änderungen:**
|
||||
```yaml
|
||||
ansible_host: DEINE-NETCUP-IP # ← Server IP
|
||||
domain: "deine-domain.com" # ← Domain
|
||||
ssl_email: "deine@email.com" # ← E-Mail
|
||||
local_app_path: "~/meine-app" # ← Pfad zu deiner App
|
||||
```
|
||||
|
||||
## 3. Deployment
|
||||
|
||||
```bash
|
||||
# SSH-Key zum Server (falls noch nicht gemacht)
|
||||
ssh-copy-id root@DEINE-NETCUP-IP
|
||||
|
||||
# App deployen
|
||||
make deploy
|
||||
```
|
||||
|
||||
## 4. App updaten
|
||||
|
||||
Nach Änderungen an deiner App:
|
||||
```bash
|
||||
# Einfach erneut deployen
|
||||
make deploy
|
||||
```
|
||||
|
||||
Die Dateien werden automatisch zum Server übertragen und die App neu gebaut.
|
||||
|
||||
## 5. Verschiedene App-Typen
|
||||
|
||||
### PHP App
|
||||
```dockerfile
|
||||
FROM php:8.1-apache
|
||||
COPY . /var/www/html/
|
||||
EXPOSE 80
|
||||
```
|
||||
|
||||
### Python Flask
|
||||
```dockerfile
|
||||
FROM python:3.9-slim
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
COPY . .
|
||||
EXPOSE 3000
|
||||
CMD ["python", "app.py"]
|
||||
```
|
||||
|
||||
### Static HTML
|
||||
```dockerfile
|
||||
FROM nginx:alpine
|
||||
COPY . /usr/share/nginx/html
|
||||
EXPOSE 80
|
||||
```
|
||||
|
||||
## 6. Ordnerstruktur
|
||||
|
||||
```
|
||||
netcup-simple-deploy/
|
||||
├── inventory/
|
||||
│ └── hosts.yml # ← Hier konfigurieren
|
||||
├── deploy.sh # ← Deployment starten
|
||||
└── Makefile # ← Einfache Befehle
|
||||
|
||||
~/meine-app/ # ← Deine App-Dateien
|
||||
├── Dockerfile
|
||||
├── package.json
|
||||
└── server.js
|
||||
```
|
||||
|
||||
## 7. Troubleshooting
|
||||
|
||||
### App startet nicht?
|
||||
```bash
|
||||
# Logs anschauen
|
||||
make logs
|
||||
|
||||
# Container status prüfen
|
||||
ansible all -m shell -a "docker ps -a"
|
||||
```
|
||||
|
||||
### Dateien werden nicht übertragen?
|
||||
```bash
|
||||
# Pfad prüfen
|
||||
ls -la ~/meine-app
|
||||
|
||||
# Manuell testen
|
||||
ansible all -m shell -a "ls -la /opt/myapp/src/"
|
||||
```
|
||||
|
||||
Das war's! Keine Git-Kenntnisse nötig - einfach deine Dateien bearbeiten und deployen! 🎉
|
||||
165
.deployment-backup/ansible/netcup-simple-deploy/SETUP-PHP.md
Normal file
165
.deployment-backup/ansible/netcup-simple-deploy/SETUP-PHP.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# PHP Projekt Setup für Netcup
|
||||
|
||||
## Projektstruktur
|
||||
|
||||
Das Deployment erwartet diese Struktur in deinem Hauptprojekt:
|
||||
|
||||
```
|
||||
dein-projekt/ # Hauptordner
|
||||
├── ansible/ # Hier sind wir jetzt
|
||||
│ └── netcup-simple-deploy/
|
||||
├── docker/ # Docker-Konfiguration
|
||||
│ ├── Dockerfile # (optional, wird sonst automatisch erstellt)
|
||||
│ └── docker-compose.yml # (optional)
|
||||
├── src/ # PHP Framework/Library Dateien
|
||||
│ ├── classes/
|
||||
│ ├── includes/
|
||||
│ └── ...
|
||||
├── public/ # Web-Root (öffentlich zugänglich)
|
||||
│ ├── index.php # Haupteinstiegspunkt
|
||||
│ ├── css/
|
||||
│ ├── js/
|
||||
│ ├── images/
|
||||
│ └── ...
|
||||
├── storage/ # (optional) Logs, Cache, etc.
|
||||
├── cache/ # (optional) Cache-Dateien
|
||||
├── logs/ # (optional) Log-Dateien
|
||||
└── .env # (optional) Umgebungsvariablen
|
||||
```
|
||||
|
||||
## Quick Setup
|
||||
|
||||
### 1. Konfiguration
|
||||
```bash
|
||||
cd ansible/netcup-simple-deploy
|
||||
vim inventory/hosts.yml
|
||||
```
|
||||
|
||||
**Ändere diese Werte:**
|
||||
```yaml
|
||||
ansible_host: DEINE-NETCUP-IP
|
||||
domain: "deine-domain.com"
|
||||
ssl_email: "deine@email.com"
|
||||
local_app_path: "../.." # Zeigt auf dein Hauptprojekt
|
||||
php_version: "8.2" # PHP Version
|
||||
```
|
||||
|
||||
### 2. Deployment
|
||||
```bash
|
||||
make deploy
|
||||
```
|
||||
|
||||
Das war's! Deine PHP-App läuft unter `https://deine-domain.com`
|
||||
|
||||
## Was passiert beim Deployment?
|
||||
|
||||
1. **Dateien übertragen:** `public/`, `src/`, `docker/` → Server
|
||||
2. **Dockerfile erstellen:** Falls keins in `docker/` vorhanden
|
||||
3. **Docker Container bauen:** PHP + Apache + deine App
|
||||
4. **Nginx Proxy:** SSL-Termination und Weiterleitung
|
||||
5. **SSL-Zertifikat:** Automatisch mit Let's Encrypt
|
||||
|
||||
## Für verschiedene PHP-Setups
|
||||
|
||||
### Eigenes Dockerfile verwenden
|
||||
Lege dein Dockerfile in `docker/Dockerfile`:
|
||||
```dockerfile
|
||||
FROM php:8.2-apache
|
||||
|
||||
# Deine spezifischen PHP Extensions
|
||||
RUN docker-php-ext-install pdo pdo_mysql
|
||||
|
||||
# Custom Apache Config
|
||||
COPY docker/apache.conf /etc/apache2/sites-available/000-default.conf
|
||||
|
||||
# App Dateien
|
||||
COPY public/ /var/www/html/
|
||||
COPY src/ /var/www/src/
|
||||
|
||||
EXPOSE 80
|
||||
```
|
||||
|
||||
### Mit Composer Dependencies
|
||||
```dockerfile
|
||||
FROM php:8.2-apache
|
||||
|
||||
# Composer installieren
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
|
||||
# Dependencies installieren
|
||||
COPY composer.json composer.lock /var/www/
|
||||
WORKDIR /var/www
|
||||
RUN composer install --no-dev --optimize-autoloader
|
||||
|
||||
# App kopieren
|
||||
COPY public/ /var/www/html/
|
||||
COPY src/ /var/www/src/
|
||||
```
|
||||
|
||||
### Mit Database
|
||||
Erweitere `inventory/hosts.yml`:
|
||||
```yaml
|
||||
app_env:
|
||||
APP_ENV: "production"
|
||||
DATABASE_HOST: "your-db-host"
|
||||
DATABASE_NAME: "your-db-name"
|
||||
DATABASE_USER: "your-db-user"
|
||||
DATABASE_PASS: "your-db-password"
|
||||
```
|
||||
|
||||
## Nützliche Befehle
|
||||
|
||||
```bash
|
||||
# Logs anschauen
|
||||
make logs
|
||||
make error-logs
|
||||
|
||||
# Cache löschen
|
||||
make clear-cache
|
||||
|
||||
# Permissions reparieren
|
||||
make fix-permissions
|
||||
|
||||
# Composer auf Server ausführen
|
||||
make composer-install
|
||||
|
||||
# Live logs verfolgen
|
||||
make tail-logs
|
||||
|
||||
# SSH auf Server
|
||||
make ssh
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### App lädt nicht?
|
||||
```bash
|
||||
# Apache Fehler-Logs prüfen
|
||||
make error-logs
|
||||
|
||||
# Allgemeine Logs
|
||||
make logs
|
||||
|
||||
# Container Status
|
||||
make status
|
||||
```
|
||||
|
||||
### Permissions-Probleme?
|
||||
```bash
|
||||
# Permissions reparieren
|
||||
make fix-permissions
|
||||
```
|
||||
|
||||
### Nach Code-Änderungen?
|
||||
```bash
|
||||
# Einfach neu deployen
|
||||
make deploy
|
||||
```
|
||||
|
||||
### Database-Verbindung?
|
||||
```bash
|
||||
# Umgebungsvariablen prüfen
|
||||
ansible all -m shell -a "docker exec \$(docker ps -q | head -1) env | grep DATABASE"
|
||||
```
|
||||
|
||||
Das Setup ist optimiert für deine bestehende Projektstruktur - keine Änderungen an deinem Code nötig! 🎉
|
||||
@@ -0,0 +1,8 @@
|
||||
[defaults]
|
||||
inventory = inventory/hosts.yml
|
||||
host_key_checking = False
|
||||
timeout = 30
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
become_method = sudo
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
# Fallback Deployment für Debian (mit allen Variablen)
|
||||
|
||||
- name: Deploy App to Netcup VPS (Debian Fallback)
|
||||
hosts: all
|
||||
become: yes
|
||||
vars_files:
|
||||
- inventory/group_vars.yml
|
||||
|
||||
tasks:
|
||||
- name: Update system
|
||||
apt:
|
||||
update_cache: yes
|
||||
upgrade: dist
|
||||
|
||||
- name: Install packages from Debian repos
|
||||
apt:
|
||||
name:
|
||||
- nginx
|
||||
- certbot
|
||||
- python3-certbot-nginx
|
||||
- git
|
||||
- curl
|
||||
- rsync
|
||||
- docker.io
|
||||
- docker-compose
|
||||
state: present
|
||||
|
||||
- name: Start and enable Docker
|
||||
systemd:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Add user to docker group
|
||||
user:
|
||||
name: "{{ ansible_user }}"
|
||||
groups: docker
|
||||
append: yes
|
||||
|
||||
- name: Deploy webapp
|
||||
include_role:
|
||||
name: webapp
|
||||
|
||||
- name: Configure Nginx reverse proxy
|
||||
template:
|
||||
src: roles/webapp/templates/nginx-site.conf.j2
|
||||
dest: /etc/nginx/sites-available/{{ domain }}
|
||||
backup: yes
|
||||
notify: reload nginx
|
||||
|
||||
- name: Enable site
|
||||
file:
|
||||
src: /etc/nginx/sites-available/{{ domain }}
|
||||
dest: /etc/nginx/sites-enabled/{{ domain }}
|
||||
state: link
|
||||
notify: reload nginx
|
||||
|
||||
- name: Remove default site
|
||||
file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
notify: reload nginx
|
||||
|
||||
- name: Generate SSL certificate
|
||||
command: >
|
||||
certbot --nginx -d {{ domain }}
|
||||
--non-interactive --agree-tos
|
||||
--email {{ ssl_email }}
|
||||
args:
|
||||
creates: "/etc/letsencrypt/live/{{ domain }}/fullchain.pem"
|
||||
|
||||
- name: Setup SSL renewal
|
||||
cron:
|
||||
name: "Renew SSL"
|
||||
minute: "0"
|
||||
hour: "3"
|
||||
job: "certbot renew --quiet"
|
||||
|
||||
- name: Start nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Wait for app to be ready
|
||||
wait_for:
|
||||
port: 80
|
||||
delay: 10
|
||||
timeout: 60
|
||||
|
||||
- name: Health check
|
||||
uri:
|
||||
url: "https://{{ domain }}"
|
||||
method: GET
|
||||
status_code: [200, 301, 302]
|
||||
retries: 5
|
||||
delay: 10
|
||||
ignore_errors: yes
|
||||
|
||||
handlers:
|
||||
- name: reload nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
119
.deployment-backup/ansible/netcup-simple-deploy/deploy.sh
Executable file
119
.deployment-backup/ansible/netcup-simple-deploy/deploy.sh
Executable file
@@ -0,0 +1,119 @@
|
||||
#!/bin/bash
|
||||
# PHP Projekt Deployment Script für Netcup (nutzt bestehende docker-compose.yml)
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Projekt Deployment zu Netcup (nutzt deine docker-compose.yml)"
|
||||
echo ""
|
||||
|
||||
# Prüfe ob Konfiguration angepasst wurde
|
||||
if grep -q "85.123.456.789" inventory/hosts.yml; then
|
||||
echo "❌ Bitte erst die Konfiguration anpassen!"
|
||||
echo ""
|
||||
echo "1. vim inventory/hosts.yml"
|
||||
echo " - Server IP ändern"
|
||||
echo " - Domain ändern"
|
||||
echo " - app_port prüfen (Port deiner App)"
|
||||
echo ""
|
||||
echo "2. Dann nochmal: ./deploy.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LOCAL_APP_PATH=$(grep "local_app_path:" inventory/hosts.yml | awk '{print $2}' | tr -d '"')
|
||||
|
||||
# Prüfe Projektstruktur
|
||||
echo "📁 Prüfe Projektstruktur..."
|
||||
FULL_PATH="$LOCAL_APP_PATH"
|
||||
|
||||
if [ ! -d "$FULL_PATH" ]; then
|
||||
echo "❌ Projekt-Verzeichnis nicht gefunden: $FULL_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Projektstruktur OK:"
|
||||
echo " 📂 Projekt: $FULL_PATH"
|
||||
|
||||
# Prüfe docker-compose.yml
|
||||
if [ -f "$FULL_PATH/docker-compose.yml" ]; then
|
||||
echo " ✅ docker-compose.yml gefunden im Root"
|
||||
elif [ -f "$FULL_PATH/docker/docker-compose.yml" ]; then
|
||||
echo " ✅ docker-compose.yml gefunden in docker/"
|
||||
else
|
||||
echo " ℹ️ Keine docker-compose.yml gefunden - wird automatisch erstellt"
|
||||
fi
|
||||
|
||||
# Zeige docker-compose.yml Inhalt falls vorhanden
|
||||
if [ -f "$FULL_PATH/docker-compose.yml" ]; then
|
||||
echo ""
|
||||
echo "📋 Deine docker-compose.yml (erste 10 Zeilen):"
|
||||
head -10 "$FULL_PATH/docker-compose.yml" | sed 's/^/ /'
|
||||
elif [ -f "$FULL_PATH/docker/docker-compose.yml" ]; then
|
||||
echo ""
|
||||
echo "📋 Deine docker-compose.yml aus docker/ (erste 10 Zeilen):"
|
||||
head -10 "$FULL_PATH/docker/docker-compose.yml" | sed 's/^/ /'
|
||||
fi
|
||||
|
||||
# Ping test
|
||||
echo ""
|
||||
echo "🔍 Teste Verbindung zum Server..."
|
||||
if ! ansible all -m ping; then
|
||||
echo "❌ Server nicht erreichbar. Prüfe:"
|
||||
echo " - IP-Adresse korrekt?"
|
||||
echo " - SSH-Key installiert? (ssh-copy-id root@deine-ip)"
|
||||
echo " - Server läuft?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Server erreichbar!"
|
||||
echo ""
|
||||
|
||||
# Wähle Deployment-Methode
|
||||
echo "🔧 Deployment-Optionen:"
|
||||
echo "1. Standard: Saubere Docker-Installation (empfohlen)"
|
||||
echo "2. Fallback: Debian Standard-Pakete (falls Probleme auftreten)"
|
||||
echo ""
|
||||
read -p "Wähle Option (1/2): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ $REPLY == "2" ]]; then
|
||||
PLAYBOOK="deploy-debian-fallback.yml"
|
||||
echo "📦 Verwende Debian Standard-Pakete"
|
||||
else
|
||||
PLAYBOOK="deploy.yml"
|
||||
echo "🐳 Verwende saubere Docker-Installation"
|
||||
fi
|
||||
|
||||
# Deployment confirmation
|
||||
read -p "🚀 Projekt deployen? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Deployment abgebrochen."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "🔧 Starte Deployment mit $PLAYBOOK..."
|
||||
echo "💡 Das Deployment nutzt deine bestehende docker-compose.yml!"
|
||||
echo ""
|
||||
|
||||
ansible-playbook "$PLAYBOOK"
|
||||
|
||||
echo ""
|
||||
echo "🎉 Deployment abgeschlossen!"
|
||||
echo ""
|
||||
|
||||
# Zeige Ergebnisse
|
||||
DOMAIN=$(grep "domain:" inventory/hosts.yml | awk '{print $2}' | tr -d '"')
|
||||
echo "🌐 Dein Projekt ist verfügbar unter:"
|
||||
echo " https://$DOMAIN"
|
||||
echo ""
|
||||
echo "📊 Status prüfen:"
|
||||
echo " curl -I https://$DOMAIN"
|
||||
echo ""
|
||||
echo "🔧 Container-Status anschauen:"
|
||||
echo " make status"
|
||||
echo ""
|
||||
echo "🔧 Logs anschauen:"
|
||||
echo " make logs"
|
||||
echo ""
|
||||
echo "🔄 Nach Änderungen:"
|
||||
echo " make deploy"
|
||||
163
.deployment-backup/ansible/netcup-simple-deploy/deploy.yml
Normal file
163
.deployment-backup/ansible/netcup-simple-deploy/deploy.yml
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
# Ultra-einfaches Netcup Deployment (Port-Konflikt behoben)
|
||||
|
||||
- name: Deploy App to Netcup VPS (Debian Clean)
|
||||
hosts: all
|
||||
become: yes
|
||||
vars_files:
|
||||
- inventory/group_vars.yml
|
||||
|
||||
tasks:
|
||||
- name: Clean up any existing Docker repositories
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- /etc/apt/sources.list.d/docker.list
|
||||
- /etc/apt/sources.list.d/download_docker_com_linux_debian.list
|
||||
- /etc/apt/keyrings/docker.gpg
|
||||
- /etc/apt/keyrings/docker.asc
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Remove any Docker GPG keys from apt-key
|
||||
shell: apt-key del 9DC858229FC7DD38854AE2D88D81803C0EBFCD88 || true
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Update apt cache after cleanup
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Install basic packages first
|
||||
apt:
|
||||
name:
|
||||
- nginx
|
||||
- certbot
|
||||
- python3-certbot-nginx
|
||||
- git
|
||||
- curl
|
||||
- rsync
|
||||
- ca-certificates
|
||||
- gnupg
|
||||
- lsb-release
|
||||
state: present
|
||||
|
||||
- name: Create keyrings directory
|
||||
file:
|
||||
path: /etc/apt/keyrings
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Add Docker GPG key (new method)
|
||||
shell: |
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
args:
|
||||
creates: /etc/apt/keyrings/docker.gpg
|
||||
|
||||
- name: Add Docker repository (new method)
|
||||
shell: |
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
args:
|
||||
creates: /etc/apt/sources.list.d/docker.list
|
||||
|
||||
- name: Update apt cache
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Install Docker
|
||||
apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-buildx-plugin
|
||||
- docker-compose-plugin
|
||||
state: present
|
||||
|
||||
- name: Start and enable Docker
|
||||
systemd:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Add user to docker group
|
||||
user:
|
||||
name: "{{ ansible_user }}"
|
||||
groups: docker
|
||||
append: yes
|
||||
|
||||
- name: Stop nginx temporarily (to avoid port conflicts)
|
||||
systemd:
|
||||
name: nginx
|
||||
state: stopped
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Deploy webapp
|
||||
include_role:
|
||||
name: webapp
|
||||
|
||||
- name: Configure Nginx reverse proxy
|
||||
template:
|
||||
src: roles/webapp/templates/nginx-site.conf.j2
|
||||
dest: /etc/nginx/sites-available/{{ domain }}
|
||||
backup: yes
|
||||
notify: reload nginx
|
||||
|
||||
- name: Enable site
|
||||
file:
|
||||
src: /etc/nginx/sites-available/{{ domain }}
|
||||
dest: /etc/nginx/sites-enabled/{{ domain }}
|
||||
state: link
|
||||
notify: reload nginx
|
||||
|
||||
- name: Remove default site
|
||||
file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
notify: reload nginx
|
||||
|
||||
- name: Test nginx configuration
|
||||
command: nginx -t
|
||||
register: nginx_test
|
||||
|
||||
- name: Start nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Generate SSL certificate
|
||||
command: >
|
||||
certbot --nginx -d {{ domain }}
|
||||
--non-interactive --agree-tos
|
||||
--email {{ ssl_email }}
|
||||
args:
|
||||
creates: "/etc/letsencrypt/live/{{ domain }}/fullchain.pem"
|
||||
|
||||
- name: Setup SSL renewal
|
||||
cron:
|
||||
name: "Renew SSL"
|
||||
minute: "0"
|
||||
hour: "3"
|
||||
job: "certbot renew --quiet"
|
||||
|
||||
- name: Wait for app to be ready
|
||||
wait_for:
|
||||
port: 80
|
||||
delay: 10
|
||||
timeout: 60
|
||||
|
||||
- name: Health check
|
||||
uri:
|
||||
url: "https://{{ domain }}"
|
||||
method: GET
|
||||
status_code: [200, 301, 302]
|
||||
retries: 5
|
||||
delay: 10
|
||||
ignore_errors: yes
|
||||
|
||||
handlers:
|
||||
- name: reload nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
# Globale Einstellungen
|
||||
|
||||
# Docker-Einstellungen
|
||||
docker_compose_version: "2.24.0"
|
||||
|
||||
# Nginx-Einstellungen
|
||||
nginx_client_max_body_size: "50M"
|
||||
nginx_worker_connections: 1024
|
||||
|
||||
# SSL-Einstellungen
|
||||
ssl_protocols: "TLSv1.2 TLSv1.3"
|
||||
|
||||
# App-Verzeichnis auf dem Server
|
||||
app_directory: "/opt/{{ app_name }}"
|
||||
|
||||
# Health Check
|
||||
health_check_url: "/health"
|
||||
health_check_timeout: 30
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
# Netcup Inventar für PHP-Projekt (Fixed paths)
|
||||
|
||||
all:
|
||||
hosts:
|
||||
netcup-server:
|
||||
ansible_host: 94.16.110.151
|
||||
ansible_user: deploy
|
||||
ansible_ssh_private_key_file: /home/michael/.ssh/production
|
||||
|
||||
# Server-Details
|
||||
domain: "test.michaelschiemer.de"
|
||||
ssl_email: "kontakt@michaelschiemer.de"
|
||||
|
||||
# App-Konfiguration
|
||||
app_name: "michaelschiemer"
|
||||
app_port: 8000
|
||||
|
||||
# Pfad zu deinem Projekt (ABSOLUT!)
|
||||
local_app_path: "/home/michael/dev/michaelschiemer" # Absoluter Pfad zu deinem Hauptprojekt
|
||||
|
||||
# Umgebungsvariablen für deine App (wird in .env geschrieben)
|
||||
app_env:
|
||||
APP_ENV: "production"
|
||||
APP_DEBUG: "false"
|
||||
APP_NAME: "Michael Schiemer"
|
||||
APP_KEY: "base64:kJH8fsd89fs8df7sdf8sdf7sd8f7sdf"
|
||||
APP_TIMEZONE: "Europe/Berlin"
|
||||
APP_LOCALE: "de"
|
||||
|
||||
# Database (Docker internal)
|
||||
DB_DRIVER: "mysql"
|
||||
DB_HOST: "db"
|
||||
DB_PORT: "3306"
|
||||
DB_DATABASE: "michaelschiemer"
|
||||
DB_USERNAME: "mdb-user"
|
||||
DB_PASSWORD: "StartSimple2024!"
|
||||
DB_CHARSET: "utf8mb4"
|
||||
|
||||
# Security
|
||||
SECURITY_ALLOWED_HOSTS: "localhost,test.michaelschiemer.de,michaelschiemer.de"
|
||||
SECURITY_RATE_LIMIT_PER_MINUTE: "60"
|
||||
SECURITY_RATE_LIMIT_BURST: "10"
|
||||
SESSION_LIFETIME: "1800"
|
||||
|
||||
# SSL/HTTPS
|
||||
APP_SSL_PORT: "443"
|
||||
FORCE_HTTPS: "true"
|
||||
|
||||
# Docker Settings
|
||||
COMPOSE_PROJECT_NAME: "framework-production"
|
||||
UID: "1000"
|
||||
GID: "1000"
|
||||
|
||||
# Performance
|
||||
OPCACHE_ENABLED: "true"
|
||||
REDIS_HOST: "redis"
|
||||
REDIS_PORT: "6379"
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
# Restart application containers after file upload
|
||||
|
||||
- name: Restart Application Containers
|
||||
hosts: all
|
||||
become: yes
|
||||
vars_files:
|
||||
- inventory/group_vars.yml
|
||||
|
||||
tasks:
|
||||
- name: Check if app directory exists
|
||||
stat:
|
||||
path: "{{ app_directory }}"
|
||||
register: app_dir_exists
|
||||
|
||||
- name: Fail if app directory doesn't exist
|
||||
fail:
|
||||
msg: "App directory {{ app_directory }} not found. Please deploy first with deploy.yml"
|
||||
when: not app_dir_exists.stat.exists
|
||||
|
||||
- name: Check which docker compose command is available
|
||||
shell: |
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
echo "docker compose"
|
||||
elif docker-compose --version >/dev/null 2>&1; then
|
||||
echo "docker-compose"
|
||||
else
|
||||
echo "none"
|
||||
fi
|
||||
register: docker_compose_cmd
|
||||
changed_when: false
|
||||
|
||||
- name: Fail if docker compose not available
|
||||
fail:
|
||||
msg: "Neither 'docker compose' nor 'docker-compose' is available"
|
||||
when: docker_compose_cmd.stdout == "none"
|
||||
|
||||
- name: Show current container status
|
||||
shell: "cd {{ app_directory }} && {{ docker_compose_cmd.stdout }} ps"
|
||||
register: container_status_before
|
||||
ignore_errors: yes
|
||||
changed_when: false
|
||||
|
||||
- name: Stop existing containers
|
||||
shell: "cd {{ app_directory }} && {{ docker_compose_cmd.stdout }} down"
|
||||
register: stop_result
|
||||
|
||||
- name: Start containers with updated files
|
||||
shell: "cd {{ app_directory }} && {{ docker_compose_cmd.stdout }} up -d --build"
|
||||
register: start_result
|
||||
|
||||
- name: Wait for application to start
|
||||
wait_for:
|
||||
port: "{{ app_port }}"
|
||||
host: "127.0.0.1"
|
||||
delay: 5
|
||||
timeout: 60
|
||||
|
||||
- name: Test if app is accessible
|
||||
uri:
|
||||
url: "http://127.0.0.1:{{ app_port }}/"
|
||||
method: GET
|
||||
status_code: [200, 301, 302]
|
||||
register: app_test
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Show final container status
|
||||
shell: "cd {{ app_directory }} && {{ docker_compose_cmd.stdout }} ps"
|
||||
register: container_status_after
|
||||
changed_when: false
|
||||
|
||||
- name: Show restart result
|
||||
debug:
|
||||
msg: |
|
||||
🔄 Application restart completed!
|
||||
|
||||
📂 Directory: {{ app_directory }}
|
||||
🐳 Docker Compose: {{ docker_compose_cmd.stdout }}
|
||||
|
||||
🚀 Restart status: {{ 'Success' if start_result.rc == 0 else 'Failed' }}
|
||||
|
||||
{% if app_test.status is defined and (app_test.status == 200 or app_test.status == 301 or app_test.status == 302) %}
|
||||
✅ App is responding (HTTP {{ app_test.status }})
|
||||
🌐 Available at: https://{{ domain }}
|
||||
{% else %}
|
||||
⚠️ App health check failed - please check logs
|
||||
🔍 Check logs with: cd {{ app_directory }} && {{ docker_compose_cmd.stdout }} logs
|
||||
{% endif %}
|
||||
|
||||
📊 Container Status:
|
||||
{{ container_status_after.stdout }}
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
# Default variables for webapp role (Port-Konflikt behoben)
|
||||
|
||||
# App directory on server
|
||||
app_directory: "/opt/{{ app_name }}"
|
||||
|
||||
# PHP settings
|
||||
php_version: "8.4"
|
||||
|
||||
# Health check
|
||||
health_check_url: "/health"
|
||||
health_check_timeout: 30
|
||||
|
||||
# Default app settings if not defined in inventory
|
||||
app_name: "myapp"
|
||||
app_port: 8000 # PHP läuft auf Port 8080, nginx auf Port 80
|
||||
domain: "test.michaelschiemer.de"
|
||||
ssl_email: "kontakt@michaelschiemer.de"
|
||||
|
||||
# Default environment variables
|
||||
app_env:
|
||||
APP_ENV: "production"
|
||||
PHP_MEMORY_LIMIT: "256M"
|
||||
PHP_UPLOAD_MAX_FILESIZE: "50M"
|
||||
@@ -0,0 +1,272 @@
|
||||
---
|
||||
# PHP Webapp Deployment (Handle missing PHP config files)
|
||||
|
||||
- name: Create app directory
|
||||
file:
|
||||
path: "{{ app_directory }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Check if docker-compose.yml exists locally first
|
||||
local_action:
|
||||
module: stat
|
||||
path: "{{ local_app_path }}/docker-compose.yml"
|
||||
register: local_compose_exists
|
||||
become: no
|
||||
|
||||
- name: Show local docker-compose.yml status
|
||||
debug:
|
||||
msg: |
|
||||
🔍 Local docker-compose.yml check:
|
||||
- Path: {{ local_app_path }}/docker-compose.yml
|
||||
- Exists: {{ local_compose_exists.stat.exists }}
|
||||
|
||||
- name: Fail if docker-compose.yml doesn't exist locally
|
||||
fail:
|
||||
msg: |
|
||||
❌ docker-compose.yml nicht im lokalen Projekt gefunden!
|
||||
|
||||
Geprüft: {{ local_app_path }}/docker-compose.yml
|
||||
|
||||
Bitte stelle sicher, dass eine docker-compose.yml in deinem Projekt-Root existiert.
|
||||
when: not local_compose_exists.stat.exists
|
||||
|
||||
- name: Upload project files with working synchronize
|
||||
synchronize:
|
||||
src: "{{ local_app_path }}/"
|
||||
dest: "{{ app_directory }}/"
|
||||
delete: no
|
||||
archive: yes
|
||||
checksum: yes
|
||||
rsync_opts:
|
||||
- "--exclude=ansible"
|
||||
- "--exclude=.git"
|
||||
- "--exclude=vendor"
|
||||
- "--exclude=node_modules"
|
||||
- "--exclude=storage/logs"
|
||||
- "--exclude=cache"
|
||||
- "--exclude=logs"
|
||||
- "--exclude=dist"
|
||||
- "--exclude=.archive"
|
||||
- "--exclude=x_ansible"
|
||||
- "--verbose"
|
||||
register: sync_result
|
||||
|
||||
- name: Check if required PHP config files exist
|
||||
stat:
|
||||
path: "{{ app_directory }}/docker/php/php.production.ini"
|
||||
register: php_prod_config
|
||||
|
||||
- name: Create missing PHP production config if needed
|
||||
copy:
|
||||
content: |
|
||||
; PHP Production Configuration
|
||||
memory_limit = 256M
|
||||
upload_max_filesize = 50M
|
||||
post_max_size = 50M
|
||||
max_execution_time = 300
|
||||
max_input_vars = 3000
|
||||
|
||||
; Error reporting for production
|
||||
display_errors = Off
|
||||
log_errors = On
|
||||
error_log = /var/log/php_errors.log
|
||||
|
||||
; Opcache settings
|
||||
opcache.enable = 1
|
||||
opcache.memory_consumption = 128
|
||||
opcache.max_accelerated_files = 4000
|
||||
opcache.revalidate_freq = 2
|
||||
opcache.validate_timestamps = 0
|
||||
dest: "{{ app_directory }}/docker/php/php.production.ini"
|
||||
mode: '0644'
|
||||
when: not php_prod_config.stat.exists
|
||||
|
||||
- name: Check if common PHP config exists
|
||||
stat:
|
||||
path: "{{ app_directory }}/docker/php/php.common.ini"
|
||||
register: php_common_config
|
||||
|
||||
- name: Create missing PHP common config if needed
|
||||
copy:
|
||||
content: |
|
||||
; PHP Common Configuration
|
||||
date.timezone = Europe/Berlin
|
||||
short_open_tag = Off
|
||||
expose_php = Off
|
||||
|
||||
; Security
|
||||
allow_url_fopen = On
|
||||
allow_url_include = Off
|
||||
dest: "{{ app_directory }}/docker/php/php.common.ini"
|
||||
mode: '0644'
|
||||
when: not php_common_config.stat.exists
|
||||
|
||||
- name: Ensure PHP config directory exists
|
||||
file:
|
||||
path: "{{ app_directory }}/docker/php"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Show what files were synced
|
||||
debug:
|
||||
msg: |
|
||||
📂 Sync Result:
|
||||
- Changed: {{ sync_result.changed }}
|
||||
|
||||
- name: Ensure proper permissions for directories
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
recurse: yes
|
||||
loop:
|
||||
- "{{ app_directory }}/public"
|
||||
- "{{ app_directory }}/src"
|
||||
- "{{ app_directory }}/docker"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Create storage directories if they don't exist
|
||||
file:
|
||||
path: "{{ app_directory }}/{{ item }}"
|
||||
state: directory
|
||||
mode: '0777'
|
||||
loop:
|
||||
- "storage/logs"
|
||||
- "storage/cache"
|
||||
- "cache"
|
||||
- "logs"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Check if docker-compose.yml exists in project root
|
||||
stat:
|
||||
path: "{{ app_directory }}/docker-compose.yml"
|
||||
register: compose_exists
|
||||
|
||||
- name: Check if docker-compose.yml exists in docker folder
|
||||
stat:
|
||||
path: "{{ app_directory }}/docker/docker-compose.yml"
|
||||
register: compose_docker_exists
|
||||
|
||||
- name: Use docker-compose.yml from docker folder if available
|
||||
copy:
|
||||
src: "{{ app_directory }}/docker/docker-compose.yml"
|
||||
dest: "{{ app_directory }}/docker-compose.yml"
|
||||
remote_src: yes
|
||||
when: compose_docker_exists.stat.exists and not compose_exists.stat.exists
|
||||
|
||||
- name: Manually copy docker-compose.yml if sync failed
|
||||
copy:
|
||||
src: "{{ local_app_path }}/docker-compose.yml"
|
||||
dest: "{{ app_directory }}/docker-compose.yml"
|
||||
mode: '0644'
|
||||
when: local_compose_exists.stat.exists and not compose_exists.stat.exists
|
||||
|
||||
- name: Show which docker-compose.yml we found
|
||||
debug:
|
||||
msg: |
|
||||
📋 Docker Compose Status:
|
||||
- Root compose exists: {{ compose_exists.stat.exists }}
|
||||
- Docker folder compose exists: {{ compose_docker_exists.stat.exists }}
|
||||
|
||||
- name: Fail if no docker-compose.yml found
|
||||
fail:
|
||||
msg: |
|
||||
❌ Keine docker-compose.yml gefunden!
|
||||
|
||||
Erwartet in:
|
||||
- {{ app_directory }}/docker-compose.yml
|
||||
- {{ app_directory }}/docker/docker-compose.yml
|
||||
|
||||
Bitte erstelle eine docker-compose.yml in deinem Projekt.
|
||||
when: not compose_exists.stat.exists and not compose_docker_exists.stat.exists
|
||||
|
||||
- name: Check if public/index.php exists after sync
|
||||
stat:
|
||||
path: "{{ app_directory }}/public/index.php"
|
||||
register: index_exists
|
||||
|
||||
- name: Fail if index.php not found
|
||||
fail:
|
||||
msg: |
|
||||
❌ index.php nicht gefunden!
|
||||
|
||||
Geprüft: {{ app_directory }}/public/index.php
|
||||
|
||||
Die Dateien wurden nicht korrekt übertragen.
|
||||
when: not index_exists.stat.exists
|
||||
|
||||
- name: Create environment file
|
||||
template:
|
||||
src: app.env.j2
|
||||
dest: "{{ app_directory }}/.env"
|
||||
register: env_result
|
||||
|
||||
- name: Check which docker compose command is available
|
||||
shell: |
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
echo "docker compose"
|
||||
elif docker-compose --version >/dev/null 2>&1; then
|
||||
echo "docker-compose"
|
||||
else
|
||||
echo "none"
|
||||
fi
|
||||
register: docker_compose_cmd
|
||||
changed_when: false
|
||||
|
||||
- name: Stop existing containers (if any)
|
||||
shell: "cd {{ app_directory }} && {{ docker_compose_cmd.stdout }} down"
|
||||
when: docker_compose_cmd.stdout != "none"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Start containers with your docker-compose.yml
|
||||
shell: "cd {{ app_directory }} && {{ docker_compose_cmd.stdout }} up -d --build"
|
||||
register: start_result
|
||||
when: docker_compose_cmd.stdout != "none"
|
||||
|
||||
- name: Wait for application to start
|
||||
wait_for:
|
||||
port: "{{ app_port }}"
|
||||
host: "127.0.0.1"
|
||||
delay: 5
|
||||
timeout: 60
|
||||
|
||||
- name: Test if app is accessible
|
||||
uri:
|
||||
url: "http://127.0.0.1:{{ app_port }}/"
|
||||
method: GET
|
||||
status_code: [200, 301, 302]
|
||||
register: app_test
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Show container status
|
||||
shell: "cd {{ app_directory }} && {{ docker_compose_cmd.stdout }} ps"
|
||||
register: container_status
|
||||
when: docker_compose_cmd.stdout != "none"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Show deployment result
|
||||
debug:
|
||||
msg: |
|
||||
🎉 Projekt {{ app_name }} erfolgreich deployed!
|
||||
|
||||
📂 Projektdateien synchronisiert von: {{ local_app_path }}
|
||||
🐳 Verwendete docker-compose.yml:
|
||||
{% if compose_exists.stat.exists %}
|
||||
✅ Aus Projekt-Root: {{ app_directory }}/docker-compose.yml
|
||||
{% elif compose_docker_exists.stat.exists %}
|
||||
✅ Aus docker/ Ordner: {{ app_directory }}/docker/docker-compose.yml
|
||||
{% endif %}
|
||||
🌐 Erreichbar unter: https://{{ domain }}
|
||||
⚙️ Docker Compose: {{ docker_compose_cmd.stdout }}
|
||||
|
||||
📁 index.php Status: {{ 'Gefunden ✅' if index_exists.stat.exists else 'Nicht gefunden ❌' }}
|
||||
|
||||
🐳 Container Status:
|
||||
{{ container_status.stdout if container_status.stdout is defined else 'Status konnte nicht abgerufen werden' }}
|
||||
|
||||
{% if app_test.status is defined and (app_test.status == 200 or app_test.status == 301 or app_test.status == 302) %}
|
||||
✅ App reagiert erfolgreich (HTTP {{ app_test.status }})
|
||||
{% else %}
|
||||
⚠️ App-Test fehlgeschlagen - prüfe Logs mit 'make logs'
|
||||
{% endif %}
|
||||
@@ -0,0 +1,12 @@
|
||||
# Environment variables for {{ app_name }}
|
||||
|
||||
{% for key, value in app_env.items() %}
|
||||
{{ key }}={{ value }}
|
||||
{% endfor %}
|
||||
|
||||
# Deployment info
|
||||
DEPLOYED_AT={{ ansible_date_time.iso8601 }}
|
||||
DEPLOYED_BY=ansible
|
||||
SERVER_NAME={{ inventory_hostname }}
|
||||
|
||||
APP_PORT=8000
|
||||
@@ -0,0 +1,53 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name {{ domain }};
|
||||
|
||||
# HTTP to HTTPS redirect (wird von Certbot hinzugefügt)
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:{{ app_port }}; # Weiterleitung zu PHP-Container
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
|
||||
# PHP-spezifische Timeouts
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
|
||||
# File upload für PHP
|
||||
client_max_body_size {{ nginx_client_max_body_size }};
|
||||
}
|
||||
|
||||
# Assets (CSS, JS, Bilder) direkt servieren falls gewünscht
|
||||
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
proxy_pass http://127.0.0.1:{{ app_port }};
|
||||
proxy_cache_valid 200 1d;
|
||||
expires 1d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# PHP-Admin Tools (falls vorhanden) schützen
|
||||
location ~ /(admin|phpmyadmin|adminer) {
|
||||
proxy_pass http://127.0.0.1:{{ app_port }};
|
||||
|
||||
# Basis Auth hier hinzufügen falls gewünscht
|
||||
# auth_basic "Admin Area";
|
||||
# auth_basic_user_file /etc/nginx/.htpasswd;
|
||||
}
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
# Gzip compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
}
|
||||
75
.deployment-backup/ansible/netcup-simple-deploy/test-connectivity.sh
Executable file
75
.deployment-backup/ansible/netcup-simple-deploy/test-connectivity.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
# Test Production Server Connectivity
|
||||
|
||||
set -e
|
||||
|
||||
SERVER="94.16.110.151"
|
||||
USER="deploy"
|
||||
SSH_KEY="~/.ssh/production"
|
||||
|
||||
echo "🔧 Production Server Connectivity Test"
|
||||
echo "========================================"
|
||||
echo "Server: $SERVER"
|
||||
echo "User: $USER"
|
||||
echo "SSH-Key: $SSH_KEY"
|
||||
echo ""
|
||||
|
||||
# 1. SSH Key Test
|
||||
echo "1️⃣ SSH-Key Test..."
|
||||
if ssh-keygen -l -f $SSH_KEY.pub &>/dev/null; then
|
||||
echo "✅ SSH-Key ist gültig"
|
||||
ssh-keygen -l -f $SSH_KEY.pub
|
||||
else
|
||||
echo "❌ SSH-Key Problem"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 2. SSH Connectivity Test
|
||||
echo "2️⃣ SSH Connectivity Test..."
|
||||
if ssh -i $SSH_KEY -o ConnectTimeout=10 -o StrictHostKeyChecking=no $USER@$SERVER 'echo "SSH Connection successful"' 2>/dev/null; then
|
||||
echo "✅ SSH Connection erfolgreich"
|
||||
else
|
||||
echo "❌ SSH Connection fehlgeschlagen"
|
||||
echo "Möglicherweise ist der Server noch nicht bereit oder SSH-Key nicht konfiguriert"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 3. System Info
|
||||
echo "3️⃣ Server System Information..."
|
||||
ssh -i $SSH_KEY $USER@$SERVER 'echo "Hostname: $(hostname)" && echo "OS: $(cat /etc/os-release | grep PRETTY_NAME)" && echo "Kernel: $(uname -r)" && echo "Uptime: $(uptime -p)" && echo "Available space: $(df -h / | tail -1 | awk "{print \$4}")"'
|
||||
echo ""
|
||||
|
||||
# 4. Docker Readiness Check
|
||||
echo "4️⃣ Docker Readiness Check..."
|
||||
if ssh -i $SSH_KEY $USER@$SERVER 'which docker &>/dev/null && which docker-compose &>/dev/null'; then
|
||||
echo "✅ Docker bereits installiert"
|
||||
ssh -i $SSH_KEY $USER@$SERVER 'docker --version && docker-compose --version'
|
||||
else
|
||||
echo "⚠️ Docker noch nicht installiert (wird durch Ansible installiert)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 5. Ansible Ping Test
|
||||
echo "5️⃣ Ansible Ping Test..."
|
||||
cd "$(dirname "$0")"
|
||||
if ansible netcup-server -i inventory/hosts.yml -m ping; then
|
||||
echo "✅ Ansible Ping erfolgreich"
|
||||
else
|
||||
echo "❌ Ansible Ping fehlgeschlagen"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 6. Ansible Gather Facts
|
||||
echo "6️⃣ Ansible System Facts..."
|
||||
ansible netcup-server -i inventory/hosts.yml -m setup -a "filter=ansible_distribution*" | grep -A 10 '"ansible_distribution"'
|
||||
echo ""
|
||||
|
||||
echo "🎉 Connectivity Test erfolgreich abgeschlossen!"
|
||||
echo ""
|
||||
echo "Nächste Schritte:"
|
||||
echo "1. Deployment-Playbook ausführen: ansible-playbook -i inventory/hosts.yml deploy.yml"
|
||||
echo "2. SSL-Zertifikate konfigurieren"
|
||||
echo "3. Monitoring einrichten"
|
||||
128
.deployment-backup/ansible/netcup-simple-deploy/upload-only.yml
Normal file
128
.deployment-backup/ansible/netcup-simple-deploy/upload-only.yml
Normal file
@@ -0,0 +1,128 @@
|
||||
---
|
||||
# Nur Dateien-Upload ohne Infrastruktur-Setup
|
||||
|
||||
- name: Upload Files Only to Netcup VPS
|
||||
hosts: all
|
||||
become: yes
|
||||
vars_files:
|
||||
- inventory/group_vars.yml
|
||||
|
||||
tasks:
|
||||
- name: Check if app directory exists
|
||||
stat:
|
||||
path: "{{ app_directory }}"
|
||||
register: app_dir_exists
|
||||
|
||||
- name: Create app directory if it doesn't exist
|
||||
file:
|
||||
path: "{{ app_directory }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
when: not app_dir_exists.stat.exists
|
||||
|
||||
- name: Check if docker-compose.yml exists locally
|
||||
local_action:
|
||||
module: stat
|
||||
path: "{{ local_app_path }}/docker-compose.yml"
|
||||
register: local_compose_exists
|
||||
become: no
|
||||
|
||||
- name: Show upload information
|
||||
debug:
|
||||
msg: |
|
||||
📤 Uploading files...
|
||||
- From: {{ local_app_path }}
|
||||
- To: {{ app_directory }}
|
||||
- Docker Compose available: {{ local_compose_exists.stat.exists }}
|
||||
|
||||
- name: Upload project files
|
||||
synchronize:
|
||||
src: "{{ local_app_path }}/"
|
||||
dest: "{{ app_directory }}/"
|
||||
delete: no
|
||||
archive: yes
|
||||
checksum: yes
|
||||
rsync_opts:
|
||||
- "--exclude=ansible"
|
||||
- "--exclude=.git"
|
||||
- "--exclude=vendor"
|
||||
- "--exclude=node_modules"
|
||||
- "--exclude=storage/logs"
|
||||
- "--exclude=cache"
|
||||
- "--exclude=logs"
|
||||
- "--exclude=dist"
|
||||
- "--exclude=.archive"
|
||||
- "--exclude=x_ansible"
|
||||
- "--exclude=.env"
|
||||
- "--verbose"
|
||||
register: sync_result
|
||||
|
||||
- name: Ensure proper permissions for directories
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
recurse: yes
|
||||
loop:
|
||||
- "{{ app_directory }}/public"
|
||||
- "{{ app_directory }}/src"
|
||||
- "{{ app_directory }}/docker"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Create storage directories if they don't exist
|
||||
file:
|
||||
path: "{{ app_directory }}/{{ item }}"
|
||||
state: directory
|
||||
mode: '0777'
|
||||
loop:
|
||||
- "storage/logs"
|
||||
- "storage/cache"
|
||||
- "cache"
|
||||
- "logs"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Check if .env exists on server
|
||||
stat:
|
||||
path: "{{ app_directory }}/.env"
|
||||
register: server_env_exists
|
||||
|
||||
- name: Create environment file if it doesn't exist
|
||||
template:
|
||||
src: roles/webapp/templates/app.env.j2
|
||||
dest: "{{ app_directory }}/.env"
|
||||
when: not server_env_exists.stat.exists
|
||||
register: env_created
|
||||
|
||||
- name: Show what was uploaded
|
||||
debug:
|
||||
msg: |
|
||||
📂 Upload completed!
|
||||
|
||||
📁 Files synced: {{ 'Yes' if sync_result.changed else 'No changes detected' }}
|
||||
📄 Environment file: {{ 'Created' if env_created.changed else 'Already exists' }}
|
||||
|
||||
📍 Files are now at: {{ app_directory }}
|
||||
|
||||
🔄 To restart the application, run:
|
||||
cd {{ app_directory }}
|
||||
docker compose down && docker compose up -d --build
|
||||
|
||||
or use: make restart (if Makefile is available)
|
||||
|
||||
- name: Check if containers are running (optional restart)
|
||||
shell: "cd {{ app_directory }} && docker compose ps --format json"
|
||||
register: container_status
|
||||
ignore_errors: yes
|
||||
changed_when: false
|
||||
|
||||
- name: Ask about restarting containers
|
||||
debug:
|
||||
msg: |
|
||||
ℹ️ Current container status:
|
||||
{{ container_status.stdout if container_status.stdout else 'No containers found or docker compose not available' }}
|
||||
|
||||
💡 Tip: If you want to restart the application with the new files, run:
|
||||
ansible-playbook restart-app.yml
|
||||
|
||||
or manually:
|
||||
ssh {{ ansible_host }} "cd {{ app_directory }} && docker compose restart"
|
||||
31
.deployment-backup/ansible/nginx-cdn-germany/.gitignore
vendored
Normal file
31
.deployment-backup/ansible/nginx-cdn-germany/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Cache
|
||||
*.cache
|
||||
.cache/
|
||||
|
||||
# Ansible
|
||||
*.retry
|
||||
.ansible/
|
||||
|
||||
# System
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Backups
|
||||
*.backup
|
||||
*.bak
|
||||
|
||||
# SSL Keys (niemals committen!)
|
||||
*.key
|
||||
*.pem
|
||||
*.crt
|
||||
|
||||
# Secrets
|
||||
vault.yml
|
||||
secrets.yml
|
||||
|
||||
# Temporäre Dateien
|
||||
*.tmp
|
||||
*.temp
|
||||
64
.deployment-backup/ansible/nginx-cdn-germany/Makefile
Normal file
64
.deployment-backup/ansible/nginx-cdn-germany/Makefile
Normal file
@@ -0,0 +1,64 @@
|
||||
# Einfache CDN-Verwaltung mit Make
|
||||
|
||||
.PHONY: deploy check health purge-cache warm-cache status reload
|
||||
|
||||
# Standard deployment
|
||||
deploy:
|
||||
@echo "🚀 Deploying Simple CDN..."
|
||||
chmod +x scripts/deploy.sh
|
||||
./scripts/deploy.sh
|
||||
|
||||
# Deployment mit Check-Modus (Dry-Run)
|
||||
check:
|
||||
@echo "🔍 Checking deployment (dry-run)..."
|
||||
ansible-playbook -i inventories/production/hosts.yml playbooks/deploy-simple-cdn.yml --check --diff
|
||||
|
||||
# Health check aller Nodes
|
||||
health:
|
||||
@echo "🏥 Checking CDN health..."
|
||||
ansible cdn_nodes -i inventories/production/hosts.yml -m uri -a "url=https://{{ inventory_hostname }}/health method=GET"
|
||||
|
||||
# Cache leeren
|
||||
purge-cache:
|
||||
@echo "🧹 Purging cache on all nodes..."
|
||||
ansible cdn_nodes -i inventories/production/hosts.yml -m shell -a "find /var/cache/nginx/ -type f -delete"
|
||||
@echo "✅ Cache purged on all nodes"
|
||||
|
||||
# Cache warming
|
||||
warm-cache:
|
||||
@echo "🔥 Warming cache..."
|
||||
chmod +x scripts/warm-cache.sh
|
||||
./scripts/warm-cache.sh
|
||||
|
||||
# Status-Report
|
||||
status:
|
||||
@echo "📊 CDN Status Report..."
|
||||
ansible cdn_nodes -i inventories/production/hosts.yml -m shell -a "echo '=== {{ inventory_hostname }} ===' && /usr/local/bin/cdn-monitor && echo ''"
|
||||
|
||||
# Nginx neuladen
|
||||
reload:
|
||||
@echo "⚙️ Reloading nginx configuration..."
|
||||
ansible cdn_nodes -i inventories/production/hosts.yml -m systemd -a "name=nginx state=reloaded"
|
||||
|
||||
# SSL-Zertifikate erneuern
|
||||
renew-ssl:
|
||||
@echo "🔐 Renewing SSL certificates..."
|
||||
ansible cdn_nodes -i inventories/production/hosts.yml -m shell -a "certbot renew --quiet"
|
||||
|
||||
# Interaktive Verwaltung
|
||||
manage:
|
||||
@echo "🔧 Starting interactive management..."
|
||||
ansible-playbook -i inventories/production/hosts.yml playbooks/manage-cdn.yml
|
||||
|
||||
# Hilfe
|
||||
help:
|
||||
@echo "📖 Available commands:"
|
||||
@echo " make deploy - Deploy CDN"
|
||||
@echo " make check - Test deployment (dry-run)"
|
||||
@echo " make health - Check all nodes health"
|
||||
@echo " make purge-cache - Clear all cache"
|
||||
@echo " make warm-cache - Warm cache with popular URLs"
|
||||
@echo " make status - Show detailed status"
|
||||
@echo " make reload - Reload nginx config"
|
||||
@echo " make renew-ssl - Renew SSL certificates"
|
||||
@echo " make manage - Interactive management"
|
||||
48
.deployment-backup/ansible/nginx-cdn-germany/README.md
Normal file
48
.deployment-backup/ansible/nginx-cdn-germany/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Simple Nginx CDN für Deutschland
|
||||
|
||||
Dieses Ansible-Projekt erstellt ein einfaches, aber effektives CDN nur mit Nginx für deutsche Server.
|
||||
|
||||
## Schnellstart
|
||||
|
||||
1. **Konfiguration anpassen:**
|
||||
```bash
|
||||
# Server-IPs eintragen
|
||||
vim inventories/production/hosts.yml
|
||||
|
||||
# Domains anpassen
|
||||
vim inventories/production/group_vars/all/main.yml
|
||||
```
|
||||
|
||||
2. **Deployment:**
|
||||
```bash
|
||||
# Testen
|
||||
ansible-playbook -i inventories/production/hosts.yml playbooks/deploy-simple-cdn.yml --check
|
||||
|
||||
# Deployen
|
||||
ansible-playbook -i inventories/production/hosts.yml playbooks/deploy-simple-cdn.yml
|
||||
```
|
||||
|
||||
3. **Verwalten:**
|
||||
```bash
|
||||
# Cache leeren
|
||||
make purge-cache
|
||||
|
||||
# Status prüfen
|
||||
make health
|
||||
```
|
||||
|
||||
## Struktur
|
||||
|
||||
- `inventories/` - Server-Konfiguration
|
||||
- `roles/` - Ansible-Rollen
|
||||
- `playbooks/` - Deployment-Skripte
|
||||
- `scripts/` - Hilfsskripte
|
||||
|
||||
## Features
|
||||
|
||||
✅ Nginx-basiertes CDN
|
||||
✅ SSL mit Let's Encrypt
|
||||
✅ DSGVO-konforme Logs
|
||||
✅ Einfaches Monitoring
|
||||
✅ Cache-Management
|
||||
✅ Rate Limiting
|
||||
115
.deployment-backup/ansible/nginx-cdn-germany/SETUP.md
Normal file
115
.deployment-backup/ansible/nginx-cdn-germany/SETUP.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# SETUP.md - Einrichtungsanleitung
|
||||
|
||||
## 1. Vorbereitung
|
||||
|
||||
### Server vorbereiten
|
||||
```bash
|
||||
# Für jeden CDN-Server (als root):
|
||||
apt update && apt upgrade -y
|
||||
apt install -y python3 python3-pip
|
||||
```
|
||||
|
||||
### SSH-Keys einrichten
|
||||
```bash
|
||||
# Auf deinem lokalen Rechner:
|
||||
ssh-keygen -t rsa -b 4096 -C "cdn-deployment"
|
||||
ssh-copy-id root@cdn-fra1.example.de
|
||||
ssh-copy-id root@cdn-ham1.example.de
|
||||
ssh-copy-id root@cdn-muc1.example.de
|
||||
```
|
||||
|
||||
## 2. Konfiguration anpassen
|
||||
|
||||
### Domains und IPs ändern
|
||||
```bash
|
||||
# 1. Server-IPs eintragen
|
||||
vim inventories/production/hosts.yml
|
||||
|
||||
# 2. Domain-Namen anpassen
|
||||
vim inventories/production/group_vars/all/main.yml
|
||||
```
|
||||
|
||||
**Wichtig:** Ändere diese Werte:
|
||||
- `cdn_domain: "cdn.example.de"` → deine CDN-Domain
|
||||
- `ssl_email: "admin@example.de"` → deine E-Mail
|
||||
- `origin_domain: "www.example.de"` → deine Website
|
||||
- Alle IP-Adressen in `hosts.yml`
|
||||
|
||||
## 3. DNS konfigurieren
|
||||
|
||||
Bevor du deployest, stelle sicher dass deine CDN-Domain zu den Servern zeigt:
|
||||
|
||||
```bash
|
||||
# A-Records für deine CDN-Domain:
|
||||
cdn.example.de. IN A 10.0.1.10 # Frankfurt
|
||||
cdn.example.de. IN A 10.0.2.10 # Hamburg
|
||||
cdn.example.de. IN A 10.0.3.10 # München
|
||||
```
|
||||
|
||||
## 4. Deployment
|
||||
|
||||
```bash
|
||||
# Testen
|
||||
make check
|
||||
|
||||
# Deployen
|
||||
make deploy
|
||||
|
||||
# Health-Check
|
||||
make health
|
||||
```
|
||||
|
||||
## 5. Testen
|
||||
|
||||
```bash
|
||||
# CDN testen
|
||||
curl -I https://cdn.example.de/health
|
||||
|
||||
# Cache-Header prüfen
|
||||
curl -I https://cdn.example.de/some-static-file.css
|
||||
|
||||
# Performance testen
|
||||
time curl -o /dev/null -s https://cdn.example.de/
|
||||
```
|
||||
|
||||
## 6. Wartung
|
||||
|
||||
```bash
|
||||
# Cache leeren
|
||||
make purge-cache
|
||||
|
||||
# Status prüfen
|
||||
make status
|
||||
|
||||
# SSL erneuern
|
||||
make renew-ssl
|
||||
|
||||
# Interaktive Verwaltung
|
||||
make manage
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Ansible-Verbindung testen
|
||||
```bash
|
||||
ansible all -m ping
|
||||
```
|
||||
|
||||
### Nginx-Konfiguration prüfen
|
||||
```bash
|
||||
ansible cdn_nodes -m shell -a "nginx -t"
|
||||
```
|
||||
|
||||
### Logs anschauen
|
||||
```bash
|
||||
ansible cdn_nodes -m shell -a "tail -f /var/log/nginx/error.log"
|
||||
```
|
||||
|
||||
### SSL-Probleme
|
||||
```bash
|
||||
# SSL-Status prüfen
|
||||
ansible cdn_nodes -m shell -a "certbot certificates"
|
||||
|
||||
# Manuell erneuern
|
||||
ansible cdn_nodes -m shell -a "certbot renew --force-renewal"
|
||||
```
|
||||
15
.deployment-backup/ansible/nginx-cdn-germany/ansible.cfg
Normal file
15
.deployment-backup/ansible/nginx-cdn-germany/ansible.cfg
Normal file
@@ -0,0 +1,15 @@
|
||||
[defaults]
|
||||
inventory = inventories/production/hosts.yml
|
||||
host_key_checking = False
|
||||
timeout = 30
|
||||
forks = 5
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
become_method = sudo
|
||||
become_user = root
|
||||
become_ask_pass = False
|
||||
|
||||
[ssh_connection]
|
||||
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no
|
||||
control_path = /tmp/ansible-ssh-%%h-%%p-%%r
|
||||
19
.deployment-backup/ansible/nginx-cdn-germany/init.sh
Normal file
19
.deployment-backup/ansible/nginx-cdn-germany/init.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Scripts ausführbar machen
|
||||
chmod +x scripts/deploy.sh
|
||||
chmod +x scripts/warm-cache.sh
|
||||
|
||||
echo "✅ CDN-Projekt wurde erfolgreich erstellt!"
|
||||
echo ""
|
||||
echo "Nächste Schritte:"
|
||||
echo "1. Konfiguration anpassen:"
|
||||
echo " - vim inventories/production/hosts.yml"
|
||||
echo " - vim inventories/production/group_vars/all/main.yml"
|
||||
echo ""
|
||||
echo "2. SETUP.md lesen für detaillierte Anleitung"
|
||||
echo ""
|
||||
echo "3. Deployment testen:"
|
||||
echo " make check"
|
||||
echo ""
|
||||
echo "4. CDN deployen:"
|
||||
echo " make deploy"
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
# Globale Variablen für das CDN
|
||||
|
||||
# Domain-Konfiguration (ÄNDERE DIESE!)
|
||||
cdn_domain: "cdn.example.de" # Deine CDN-Domain
|
||||
ssl_email: "admin@example.de" # E-Mail für SSL-Zertifikate
|
||||
origin_domain: "www.example.de" # Deine Haupt-Website
|
||||
|
||||
# Cache-Einstellungen
|
||||
cache_settings:
|
||||
static_files_ttl: "1y" # CSS, JS, Fonts
|
||||
images_ttl: "30d" # Bilder
|
||||
html_ttl: "5m" # HTML-Seiten
|
||||
api_ttl: "0" # APIs (kein Caching)
|
||||
|
||||
# DSGVO-Einstellungen
|
||||
gdpr_settings:
|
||||
log_retention_days: 30
|
||||
anonymize_ips: true
|
||||
cookie_consent_required: true
|
||||
|
||||
# Rate Limiting
|
||||
rate_limits:
|
||||
api: "10r/s"
|
||||
static: "100r/s"
|
||||
images: "50r/s"
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# CDN-Node spezifische Konfiguration
|
||||
|
||||
# Nginx Performance
|
||||
nginx_worker_processes: "auto"
|
||||
nginx_worker_connections: 2048
|
||||
nginx_keepalive_timeout: 65
|
||||
|
||||
# Performance-Tuning
|
||||
tcp_optimizations:
|
||||
tcp_nodelay: "on"
|
||||
tcp_nopush: "on"
|
||||
sendfile: "on"
|
||||
|
||||
# Proxy-Einstellungen
|
||||
proxy_settings:
|
||||
connect_timeout: "5s"
|
||||
send_timeout: "10s"
|
||||
read_timeout: "10s"
|
||||
buffering: "on"
|
||||
buffer_size: "64k"
|
||||
buffers: "8 64k"
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
# Inventar mit gruppierten SSH-Schlüsseln
|
||||
|
||||
all:
|
||||
children:
|
||||
origin_servers:
|
||||
hosts:
|
||||
origin1.example.de:
|
||||
ansible_host: 192.168.1.10
|
||||
origin2.example.de:
|
||||
ansible_host: 192.168.1.11
|
||||
vars:
|
||||
ansible_ssh_private_key_file: ~/.ssh/origin_servers_key
|
||||
|
||||
cdn_nodes:
|
||||
children:
|
||||
primary_nodes:
|
||||
hosts:
|
||||
cdn-fra1.example.de:
|
||||
ansible_host: 10.0.1.10
|
||||
city: "Frankfurt"
|
||||
region: "Hessen"
|
||||
tier: "primary"
|
||||
cache_size: "50g"
|
||||
vars:
|
||||
ansible_ssh_private_key_file: ~/.ssh/cdn_primary_key
|
||||
|
||||
secondary_nodes:
|
||||
hosts:
|
||||
cdn-ham1.example.de:
|
||||
ansible_host: 10.0.2.10
|
||||
city: "Hamburg"
|
||||
region: "Hamburg"
|
||||
tier: "secondary"
|
||||
cache_size: "20g"
|
||||
cdn-muc1.example.de:
|
||||
ansible_host: 10.0.3.10
|
||||
city: "München"
|
||||
region: "Bayern"
|
||||
tier: "secondary"
|
||||
cache_size: "20g"
|
||||
vars:
|
||||
ansible_ssh_private_key_file: ~/.ssh/cdn_secondary_key
|
||||
|
||||
vars:
|
||||
ansible_user: root
|
||||
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
# Inventar mit individuellen SSH-Schlüsseln
|
||||
|
||||
all:
|
||||
children:
|
||||
origin_servers:
|
||||
hosts:
|
||||
origin1.example.de:
|
||||
ansible_host: 192.168.1.10
|
||||
datacenter: "Frankfurt"
|
||||
ansible_ssh_private_key_file: ~/.ssh/origin1_key
|
||||
origin2.example.de:
|
||||
ansible_host: 192.168.1.11
|
||||
datacenter: "Frankfurt"
|
||||
ansible_ssh_private_key_file: ~/.ssh/origin2_key
|
||||
|
||||
cdn_nodes:
|
||||
hosts:
|
||||
# Frankfurt - Primary
|
||||
cdn-fra1.example.de:
|
||||
ansible_host: 10.0.1.10
|
||||
city: "Frankfurt"
|
||||
region: "Hessen"
|
||||
tier: "primary"
|
||||
cache_size: "50g"
|
||||
ansible_ssh_private_key_file: ~/.ssh/cdn_fra1_key
|
||||
|
||||
# Hamburg - Secondary
|
||||
cdn-ham1.example.de:
|
||||
ansible_host: 10.0.2.10
|
||||
city: "Hamburg"
|
||||
region: "Hamburg"
|
||||
tier: "secondary"
|
||||
cache_size: "20g"
|
||||
ansible_ssh_private_key_file: ~/.ssh/cdn_ham1_key
|
||||
|
||||
# München - Secondary
|
||||
cdn-muc1.example.de:
|
||||
ansible_host: 10.0.3.10
|
||||
city: "München"
|
||||
region: "Bayern"
|
||||
tier: "secondary"
|
||||
cache_size: "20g"
|
||||
ansible_ssh_private_key_file: ~/.ssh/cdn_muc1_key
|
||||
|
||||
vars:
|
||||
ansible_user: root
|
||||
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
# Inventar für deutsches CDN
|
||||
|
||||
all:
|
||||
children:
|
||||
origin_servers:
|
||||
hosts:
|
||||
origin1.example.de:
|
||||
ansible_host: 192.168.1.10 # Ändere diese IP
|
||||
datacenter: "Frankfurt"
|
||||
origin2.example.de:
|
||||
ansible_host: 192.168.1.11 # Ändere diese IP
|
||||
datacenter: "Frankfurt"
|
||||
|
||||
cdn_nodes:
|
||||
hosts:
|
||||
# Frankfurt - Primary
|
||||
cdn-fra1.example.de:
|
||||
ansible_host: 10.0.1.10 # Ändere diese IP
|
||||
city: "Frankfurt"
|
||||
region: "Hessen"
|
||||
tier: "primary"
|
||||
cache_size: "50g"
|
||||
|
||||
# Hamburg - Secondary
|
||||
cdn-ham1.example.de:
|
||||
ansible_host: 10.0.2.10 # Ändere diese IP
|
||||
city: "Hamburg"
|
||||
region: "Hamburg"
|
||||
tier: "secondary"
|
||||
cache_size: "20g"
|
||||
|
||||
# München - Secondary
|
||||
cdn-muc1.example.de:
|
||||
ansible_host: 10.0.3.10 # Ändere diese IP
|
||||
city: "München"
|
||||
region: "Bayern"
|
||||
tier: "secondary"
|
||||
cache_size: "20g"
|
||||
|
||||
vars:
|
||||
# SSH-Konfiguration
|
||||
ansible_user: root
|
||||
ansible_ssh_private_key_file: ~/.ssh/id_rsa
|
||||
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
# Simple CDN Deployment
|
||||
|
||||
- name: Deploy Simple CDN for Germany
|
||||
hosts: cdn_nodes
|
||||
become: yes
|
||||
serial: 1 # Ein Node nach dem anderen
|
||||
|
||||
pre_tasks:
|
||||
- name: Update system packages
|
||||
apt:
|
||||
update_cache: yes
|
||||
upgrade: dist
|
||||
|
||||
- name: Install required packages
|
||||
apt:
|
||||
name:
|
||||
- nginx
|
||||
- certbot
|
||||
- python3-certbot-nginx
|
||||
- curl
|
||||
- htop
|
||||
- bc
|
||||
state: present
|
||||
|
||||
roles:
|
||||
- nginx-cdn-config
|
||||
- ssl-certificates
|
||||
- simple-monitoring
|
||||
|
||||
post_tasks:
|
||||
- name: Verify CDN health
|
||||
uri:
|
||||
url: "https://{{ inventory_hostname }}/health"
|
||||
method: GET
|
||||
status_code: 200
|
||||
validate_certs: yes
|
||||
retries: 5
|
||||
delay: 10
|
||||
|
||||
- name: Display deployment success
|
||||
debug:
|
||||
msg: "✅ CDN Node {{ inventory_hostname }} ({{ city }}) successfully deployed!"
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
# CDN Management Tasks
|
||||
- name: CDN Management and Maintenance
|
||||
hosts: cdn_nodes
|
||||
become: yes
|
||||
vars_prompt:
|
||||
- name: action
|
||||
prompt: "What action? (purge-cache/reload-config/check-health/view-stats/warm-cache)"
|
||||
private: no
|
||||
|
||||
tasks:
|
||||
- name: Purge all cache
|
||||
shell: find /var/cache/nginx/ -type f -delete
|
||||
when: action == "purge-cache"
|
||||
|
||||
- name: Display cache purge result
|
||||
debug:
|
||||
msg: "✅ Cache purged on {{ inventory_hostname }}"
|
||||
when: action == "purge-cache"
|
||||
|
||||
- name: Reload nginx configuration
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
when: action == "reload-config"
|
||||
|
||||
- name: Check CDN health
|
||||
uri:
|
||||
url: "https://{{ inventory_hostname }}/health"
|
||||
method: GET
|
||||
status_code: 200
|
||||
register: health_result
|
||||
when: action == "check-health"
|
||||
|
||||
- name: Display health result
|
||||
debug:
|
||||
msg: "{{ health_result.content }}"
|
||||
when: action == "check-health"
|
||||
|
||||
- name: Show cache and system statistics
|
||||
shell: |
|
||||
echo "=== Cache Size ==="
|
||||
du -sh /var/cache/nginx/
|
||||
echo "=== Cache Files ==="
|
||||
find /var/cache/nginx/ -type f | wc -l
|
||||
echo "=== System Load ==="
|
||||
uptime
|
||||
echo "=== Memory Usage ==="
|
||||
free -h
|
||||
echo "=== Disk Usage ==="
|
||||
df -h /
|
||||
register: stats_result
|
||||
when: action == "view-stats"
|
||||
|
||||
- name: Display statistics
|
||||
debug:
|
||||
msg: "{{ stats_result.stdout_lines }}"
|
||||
when: action == "view-stats"
|
||||
|
||||
- name: Warm cache with popular URLs
|
||||
uri:
|
||||
url: "https://{{ inventory_hostname }}{{ item }}"
|
||||
method: GET
|
||||
loop:
|
||||
- "/"
|
||||
- "/health"
|
||||
ignore_errors: yes
|
||||
when: action == "warm-cache"
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: reload nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
|
||||
- name: restart nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: restarted
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
# Nginx CDN Konfiguration
|
||||
|
||||
- name: Remove default nginx config
|
||||
file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
notify: reload nginx
|
||||
|
||||
- name: Create nginx directories
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0755'
|
||||
loop:
|
||||
- /var/cache/nginx/static
|
||||
- /var/cache/nginx/images
|
||||
- /var/cache/nginx/html
|
||||
- /var/log/nginx/cdn
|
||||
- /etc/nginx/includes
|
||||
|
||||
- name: Configure nginx main config
|
||||
template:
|
||||
src: nginx.conf.j2
|
||||
dest: /etc/nginx/nginx.conf
|
||||
backup: yes
|
||||
notify: reload nginx
|
||||
|
||||
- name: Create nginx includes
|
||||
template:
|
||||
src: "{{ item }}.j2"
|
||||
dest: "/etc/nginx/includes/{{ item }}"
|
||||
loop:
|
||||
- security-headers.conf
|
||||
- rate-limiting.conf
|
||||
- gzip-settings.conf
|
||||
notify: reload nginx
|
||||
|
||||
- name: Configure CDN site
|
||||
template:
|
||||
src: cdn-site.conf.j2
|
||||
dest: /etc/nginx/sites-available/cdn
|
||||
backup: yes
|
||||
notify: reload nginx
|
||||
|
||||
- name: Enable CDN site
|
||||
file:
|
||||
src: /etc/nginx/sites-available/cdn
|
||||
dest: /etc/nginx/sites-enabled/cdn
|
||||
state: link
|
||||
notify: reload nginx
|
||||
|
||||
- name: Test nginx configuration
|
||||
command: nginx -t
|
||||
register: nginx_test
|
||||
failed_when: nginx_test.rc != 0
|
||||
|
||||
- name: Start and enable nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: started
|
||||
enabled: yes
|
||||
@@ -0,0 +1,195 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name {{ cdn_domain }};
|
||||
|
||||
# Redirect HTTP to HTTPS
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name {{ cdn_domain }};
|
||||
|
||||
# SSL Configuration (wird von Certbot automatisch gefüllt)
|
||||
ssl_certificate /etc/letsencrypt/live/{{ cdn_domain }}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/{{ cdn_domain }}/privkey.pem;
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
|
||||
# CDN Headers
|
||||
add_header X-CDN-Node "{{ city }}, Deutschland";
|
||||
add_header X-Cache-Status $upstream_cache_status always;
|
||||
add_header X-Served-By "nginx-{{ inventory_hostname }}";
|
||||
|
||||
# Security Headers
|
||||
include /etc/nginx/includes/security-headers.conf;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/cdn/{{ cdn_domain }}.access.log cdn_format;
|
||||
error_log /var/log/nginx/cdn/{{ cdn_domain }}.error.log warn;
|
||||
|
||||
# Rate Limiting
|
||||
include /etc/nginx/includes/rate-limiting.conf;
|
||||
|
||||
# Gzip Compression
|
||||
include /etc/nginx/includes/gzip-settings.conf;
|
||||
|
||||
# Nginx Status für Monitoring
|
||||
location /nginx_status {
|
||||
stub_status on;
|
||||
access_log off;
|
||||
allow 127.0.0.1;
|
||||
allow 10.0.0.0/8;
|
||||
deny all;
|
||||
}
|
||||
|
||||
##
|
||||
# Static Files (CSS, JS, Fonts) - Lange Cache-Zeit
|
||||
##
|
||||
location ~* \.(css|js|woff|woff2|ttf|eot|ico)$ {
|
||||
proxy_pass https://origin_servers;
|
||||
proxy_ssl_verify off;
|
||||
|
||||
# Cache Settings
|
||||
proxy_cache static_cache;
|
||||
proxy_cache_valid 200 302 {{ cache_settings.static_files_ttl }};
|
||||
proxy_cache_valid 404 1m;
|
||||
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
|
||||
proxy_cache_lock on;
|
||||
proxy_cache_revalidate on;
|
||||
|
||||
# Headers
|
||||
expires {{ cache_settings.static_files_ttl }};
|
||||
add_header Cache-Control "public, immutable";
|
||||
add_header Vary "Accept-Encoding";
|
||||
|
||||
# Rate Limiting
|
||||
limit_req zone=static_files burst=50 nodelay;
|
||||
|
||||
# Proxy Headers
|
||||
proxy_set_header Host {{ origin_domain }};
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
##
|
||||
# Images - Mittlere Cache-Zeit
|
||||
##
|
||||
location ~* \.(jpg|jpeg|png|gif|webp|svg|avif|bmp|tiff)$ {
|
||||
proxy_pass https://origin_servers;
|
||||
proxy_ssl_verify off;
|
||||
|
||||
# Cache Settings
|
||||
proxy_cache images_cache;
|
||||
proxy_cache_valid 200 302 {{ cache_settings.images_ttl }};
|
||||
proxy_cache_valid 404 5m;
|
||||
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
|
||||
|
||||
# Headers
|
||||
expires {{ cache_settings.images_ttl }};
|
||||
add_header Cache-Control "public";
|
||||
add_header Vary "Accept";
|
||||
|
||||
# Rate Limiting
|
||||
limit_req zone=images burst=30 nodelay;
|
||||
|
||||
# Proxy Headers
|
||||
proxy_set_header Host {{ origin_domain }};
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
##
|
||||
# API Endpoints - Kein Caching
|
||||
##
|
||||
location /api/ {
|
||||
proxy_pass https://origin_servers;
|
||||
proxy_ssl_verify off;
|
||||
|
||||
# Kein Caching
|
||||
proxy_no_cache 1;
|
||||
proxy_cache_bypass 1;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
add_header Expires "0";
|
||||
|
||||
# Rate Limiting
|
||||
limit_req zone=api burst=10 nodelay;
|
||||
|
||||
# CORS Headers
|
||||
add_header Access-Control-Allow-Origin "https://{{ origin_domain }}";
|
||||
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
|
||||
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With";
|
||||
add_header Access-Control-Allow-Credentials true;
|
||||
|
||||
# Proxy Headers
|
||||
proxy_set_header Host {{ origin_domain }};
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Timeouts
|
||||
proxy_connect_timeout {{ proxy_settings.connect_timeout }};
|
||||
proxy_send_timeout {{ proxy_settings.send_timeout }};
|
||||
proxy_read_timeout {{ proxy_settings.read_timeout }};
|
||||
}
|
||||
|
||||
##
|
||||
# Cache Purge (nur interne IPs)
|
||||
##
|
||||
location ~ /purge(/.*) {
|
||||
allow 127.0.0.1;
|
||||
allow 10.0.0.0/8;
|
||||
allow 192.168.0.0/16;
|
||||
deny all;
|
||||
|
||||
proxy_cache_purge static_cache $scheme$proxy_host$1;
|
||||
}
|
||||
|
||||
##
|
||||
# Health Check
|
||||
##
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "OK - CDN Node {{ city }}\nRegion: {{ region }}\nTier: {{ tier }}\nTimestamp: $time_iso8601\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
##
|
||||
# Default Location - HTML Caching
|
||||
##
|
||||
location / {
|
||||
proxy_pass https://origin_servers;
|
||||
proxy_ssl_verify off;
|
||||
|
||||
# Cache Settings für HTML
|
||||
proxy_cache html_cache;
|
||||
proxy_cache_valid 200 {{ cache_settings.html_ttl }};
|
||||
proxy_cache_valid 404 1m;
|
||||
proxy_cache_bypass $arg_nocache $cookie_sessionid $http_authorization;
|
||||
|
||||
# Headers
|
||||
add_header Cache-Control "public, max-age=300";
|
||||
|
||||
# Proxy Headers
|
||||
proxy_set_header Host {{ origin_domain }};
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-CDN-Node "{{ city }}";
|
||||
|
||||
# Timeouts
|
||||
proxy_connect_timeout {{ proxy_settings.connect_timeout }};
|
||||
proxy_send_timeout {{ proxy_settings.send_timeout }};
|
||||
proxy_read_timeout {{ proxy_settings.read_timeout }};
|
||||
|
||||
# Buffering
|
||||
proxy_buffering {{ proxy_settings.buffering }};
|
||||
proxy_buffer_size {{ proxy_settings.buffer_size }};
|
||||
proxy_buffers {{ proxy_settings.buffers }};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# Gzip Compression Settings
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_comp_level 6;
|
||||
gzip_proxied any;
|
||||
gzip_disable "msie6";
|
||||
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/xml
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/xml+rss
|
||||
application/atom+xml
|
||||
image/svg+xml
|
||||
application/json
|
||||
application/ld+json;
|
||||
@@ -0,0 +1,75 @@
|
||||
user www-data;
|
||||
worker_processes {{ nginx_worker_processes }};
|
||||
pid /run/nginx.pid;
|
||||
include /etc/nginx/modules-enabled/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections {{ nginx_worker_connections }};
|
||||
use epoll;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
##
|
||||
# Basic Settings
|
||||
##
|
||||
sendfile {{ tcp_optimizations.sendfile }};
|
||||
tcp_nopush {{ tcp_optimizations.tcp_nopush }};
|
||||
tcp_nodelay {{ tcp_optimizations.tcp_nodelay }};
|
||||
keepalive_timeout {{ nginx_keepalive_timeout }};
|
||||
types_hash_max_size 2048;
|
||||
server_tokens off;
|
||||
|
||||
server_names_hash_bucket_size 64;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
##
|
||||
# DSGVO-konforme Logging
|
||||
##
|
||||
map $remote_addr $anonymized_ip {
|
||||
~(?P<ip>\d+\.\d+\.\d+)\.\d+ $ip.0;
|
||||
~(?P<ipv6>[^:]+:[^:]+:[^:]+:[^:]+):.* $ipv6::;
|
||||
default 0.0.0.0;
|
||||
}
|
||||
|
||||
log_format cdn_format '$anonymized_ip - $remote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent" '
|
||||
'rt=$request_time '
|
||||
'cache="$upstream_cache_status" '
|
||||
'cdn_node="{{ inventory_hostname }}"';
|
||||
|
||||
access_log /var/log/nginx/access.log cdn_format;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
##
|
||||
# Cache Paths
|
||||
##
|
||||
proxy_cache_path /var/cache/nginx/static levels=1:2 keys_zone=static_cache:100m
|
||||
max_size={{ cache_size }} inactive=7d use_temp_path=off;
|
||||
proxy_cache_path /var/cache/nginx/images levels=1:2 keys_zone=images_cache:100m
|
||||
max_size={{ cache_size }} inactive=30d use_temp_path=off;
|
||||
proxy_cache_path /var/cache/nginx/html levels=1:2 keys_zone=html_cache:50m
|
||||
max_size=5g inactive=1h use_temp_path=off;
|
||||
|
||||
##
|
||||
# Upstream zu Origin-Servern
|
||||
##
|
||||
upstream origin_servers {
|
||||
{% for host in groups['origin_servers'] %}
|
||||
server {{ hostvars[host]['ansible_default_ipv4']['address'] }}:443
|
||||
weight=1 max_fails=3 fail_timeout=30s;
|
||||
{% endfor %}
|
||||
keepalive 32;
|
||||
keepalive_requests 1000;
|
||||
keepalive_timeout 60s;
|
||||
}
|
||||
|
||||
##
|
||||
# Include configurations
|
||||
##
|
||||
include /etc/nginx/includes/*.conf;
|
||||
include /etc/nginx/sites-enabled/*;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Rate Limiting Zones
|
||||
|
||||
limit_req_zone $binary_remote_addr zone=api:10m rate={{ rate_limits.api }};
|
||||
limit_req_zone $binary_remote_addr zone=static_files:10m rate={{ rate_limits.static }};
|
||||
limit_req_zone $binary_remote_addr zone=images:10m rate={{ rate_limits.images }};
|
||||
|
||||
# Connection Limiting
|
||||
limit_conn_zone $binary_remote_addr zone=perip:10m;
|
||||
limit_conn perip 10;
|
||||
@@ -0,0 +1,10 @@
|
||||
# Security Headers für CDN
|
||||
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
|
||||
# DSGVO Header
|
||||
add_header X-Data-Processing "Art. 6 Abs. 1 lit. f DSGVO" always;
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
# Einfaches Monitoring ohne Prometheus
|
||||
|
||||
- name: Create simple monitoring script
|
||||
template:
|
||||
src: simple-monitor.sh.j2
|
||||
dest: /usr/local/bin/cdn-monitor
|
||||
mode: '0755'
|
||||
|
||||
- name: Setup monitoring cron job
|
||||
cron:
|
||||
name: "CDN Health Monitor"
|
||||
minute: "*/5"
|
||||
job: "/usr/local/bin/cdn-monitor"
|
||||
user: root
|
||||
|
||||
- name: Create log rotation for monitoring logs
|
||||
copy:
|
||||
content: |
|
||||
/var/log/nginx/cdn-monitor.log {
|
||||
weekly
|
||||
missingok
|
||||
rotate 4
|
||||
compress
|
||||
delaycompress
|
||||
notifempty
|
||||
}
|
||||
dest: /etc/logrotate.d/cdn-monitor
|
||||
mode: '0644'
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
# Einfaches CDN Monitoring für {{ inventory_hostname }}
|
||||
|
||||
LOG_FILE="/var/log/nginx/cdn-monitor.log"
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
CDN_DOMAIN="{{ cdn_domain }}"
|
||||
|
||||
# Health Check
|
||||
health_check() {
|
||||
local response=$(curl -s -o /dev/null -w "%{http_code}" "https://$CDN_DOMAIN/health")
|
||||
|
||||
if [ "$response" = "200" ]; then
|
||||
echo "[$TIMESTAMP] ✅ Health check OK" >> $LOG_FILE
|
||||
return 0
|
||||
else
|
||||
echo "[$TIMESTAMP] ❌ Health check FAILED (HTTP $response)" >> $LOG_FILE
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Nginx-Statistiken
|
||||
nginx_stats() {
|
||||
local stats=$(curl -s http://127.0.0.1/nginx_status 2>/dev/null)
|
||||
if [ $? -eq 0 ]; then
|
||||
local active_conn=$(echo "$stats" | grep "Active connections" | awk '{print $3}')
|
||||
local total_requests=$(echo "$stats" | grep "server accepts" | awk '{print $3}')
|
||||
echo "[$TIMESTAMP] 📊 Active: $active_conn, Total: $total_requests" >> $LOG_FILE
|
||||
fi
|
||||
}
|
||||
|
||||
# Cache-Größe prüfen
|
||||
cache_check() {
|
||||
local cache_size=$(du -sh /var/cache/nginx/ 2>/dev/null | cut -f1)
|
||||
local cache_files=$(find /var/cache/nginx/ -type f 2>/dev/null | wc -l)
|
||||
echo "[$TIMESTAMP] 💾 Cache: $cache_size ($cache_files files)" >> $LOG_FILE
|
||||
}
|
||||
|
||||
# System-Ressourcen
|
||||
system_check() {
|
||||
local load=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $1}' | tr -d ' ')
|
||||
local memory=$(free | grep Mem | awk '{printf "%.1f", $3/$2 * 100.0}')
|
||||
local disk=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
|
||||
|
||||
echo "[$TIMESTAMP] 🖥️ Load: $load, Memory: ${memory}%, Disk: ${disk}%" >> $LOG_FILE
|
||||
|
||||
# Warnungen bei hoher Auslastung
|
||||
if (( $(echo "$load > 5.0" | bc -l 2>/dev/null || echo 0) )); then
|
||||
echo "[$TIMESTAMP] ⚠️ HIGH LOAD WARNING: $load" >> $LOG_FILE
|
||||
fi
|
||||
|
||||
if (( $(echo "$memory > 90.0" | bc -l 2>/dev/null || echo 0) )); then
|
||||
echo "[$TIMESTAMP] ⚠️ HIGH MEMORY WARNING: ${memory}%" >> $LOG_FILE
|
||||
fi
|
||||
|
||||
if [ "$disk" -gt 85 ]; then
|
||||
echo "[$TIMESTAMP] ⚠️ HIGH DISK USAGE WARNING: ${disk}%" >> $LOG_FILE
|
||||
fi
|
||||
}
|
||||
|
||||
# Hauptausführung
|
||||
main() {
|
||||
health_check
|
||||
nginx_stats
|
||||
cache_check
|
||||
system_check
|
||||
|
||||
# Log-Datei begrenzen (nur letzte 1000 Zeilen behalten)
|
||||
tail -n 1000 $LOG_FILE > ${LOG_FILE}.tmp && mv ${LOG_FILE}.tmp $LOG_FILE
|
||||
}
|
||||
|
||||
main
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
# SSL-Zertifikate mit Let's Encrypt
|
||||
|
||||
- name: Check if certificate exists
|
||||
stat:
|
||||
path: "/etc/letsencrypt/live/{{ cdn_domain }}/fullchain.pem"
|
||||
register: cert_exists
|
||||
|
||||
- name: Generate SSL certificate with certbot
|
||||
command: >
|
||||
certbot certonly --nginx
|
||||
-d {{ cdn_domain }}
|
||||
--non-interactive
|
||||
--agree-tos
|
||||
--email {{ ssl_email }}
|
||||
when: not cert_exists.stat.exists
|
||||
|
||||
- name: Setup SSL certificate renewal
|
||||
cron:
|
||||
name: "Renew SSL certificates"
|
||||
minute: "0"
|
||||
hour: "3"
|
||||
job: "certbot renew --quiet --deploy-hook 'systemctl reload nginx'"
|
||||
user: root
|
||||
|
||||
- name: Test SSL certificate renewal (dry-run)
|
||||
command: certbot renew --dry-run
|
||||
register: renewal_test
|
||||
failed_when: renewal_test.rc != 0
|
||||
changed_when: false
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
# Simple CDN Deployment Script
|
||||
|
||||
set -e
|
||||
|
||||
INVENTORY_FILE="inventories/production/hosts.yml"
|
||||
PLAYBOOK="playbooks/deploy-simple-cdn.yml"
|
||||
|
||||
echo "🚀 Starting Simple CDN Deployment for Germany..."
|
||||
|
||||
# Pre-deployment checks
|
||||
echo "🔍 Running pre-deployment checks..."
|
||||
if ! ansible all -i $INVENTORY_FILE -m ping; then
|
||||
echo "❌ Some hosts are not reachable. Please check your inventory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📋 Testing ansible configuration..."
|
||||
if ! ansible-playbook $PLAYBOOK -i $INVENTORY_FILE --check --diff; then
|
||||
echo "❌ Configuration test failed. Please fix errors first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
read -p "Continue with deployment? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Deployment cancelled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Deployment
|
||||
echo "🔧 Deploying CDN nodes..."
|
||||
ansible-playbook $PLAYBOOK -i $INVENTORY_FILE
|
||||
|
||||
# Post-deployment verification
|
||||
echo "✅ Verifying deployment..."
|
||||
ansible cdn_nodes -i $INVENTORY_FILE -m uri -a "url=https://{{ inventory_hostname }}/health method=GET status_code=200"
|
||||
|
||||
echo "🎉 CDN Deployment completed successfully!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Update your DNS to point to the CDN nodes"
|
||||
echo "2. Test your CDN: curl -I https://your-cdn-domain.de/health"
|
||||
echo "3. Monitor with: ansible-playbook -i $INVENTORY_FILE playbooks/manage-cdn.yml"
|
||||
125
.deployment-backup/ansible/nginx-cdn-germany/scripts/ssh-keys.sh
Normal file
125
.deployment-backup/ansible/nginx-cdn-germany/scripts/ssh-keys.sh
Normal file
@@ -0,0 +1,125 @@
|
||||
#!/bin/bash
|
||||
# SSH-Schlüssel Management für CDN
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
show_help() {
|
||||
echo "CDN SSH Key Management"
|
||||
echo ""
|
||||
echo "Usage: $0 [OPTION]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " single - Ein Schlüssel für alle Nodes (Standard)"
|
||||
echo " individual - Separater Schlüssel pro Node"
|
||||
echo " grouped - Gruppierte Schlüssel (Primary/Secondary)"
|
||||
echo " generate - SSH-Schlüssel generieren"
|
||||
echo " deploy - Öffentliche Schlüssel zu Servern kopieren"
|
||||
echo " help - Diese Hilfe anzeigen"
|
||||
}
|
||||
|
||||
generate_single_key() {
|
||||
echo "🔑 Generiere einen SSH-Schlüssel für alle CDN-Nodes..."
|
||||
|
||||
if [ ! -f ~/.ssh/cdn_key ]; then
|
||||
ssh-keygen -t ed25519 -C "cdn-deployment" -f ~/.ssh/cdn_key -N ""
|
||||
echo "✅ Schlüssel generiert: ~/.ssh/cdn_key"
|
||||
else
|
||||
echo "ℹ️ Schlüssel existiert bereits: ~/.ssh/cdn_key"
|
||||
fi
|
||||
|
||||
# Inventar anpassen
|
||||
sed -i 's|ansible_ssh_private_key_file: .*|ansible_ssh_private_key_file: ~/.ssh/cdn_key|' \
|
||||
"$SCRIPT_DIR/../inventories/production/hosts.yml"
|
||||
|
||||
echo "✅ Inventar aktualisiert"
|
||||
}
|
||||
|
||||
generate_individual_keys() {
|
||||
echo "🔑 Generiere individuelle SSH-Schlüssel..."
|
||||
|
||||
NODES=("cdn_fra1" "cdn_ham1" "cdn_muc1" "origin1" "origin2")
|
||||
|
||||
for node in "${NODES[@]}"; do
|
||||
if [ ! -f ~/.ssh/${node}_key ]; then
|
||||
ssh-keygen -t ed25519 -C "cdn-${node}" -f ~/.ssh/${node}_key -N ""
|
||||
echo "✅ Schlüssel generiert: ~/.ssh/${node}_key"
|
||||
else
|
||||
echo "ℹ️ Schlüssel existiert bereits: ~/.ssh/${node}_key"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "✅ Alle individuellen Schlüssel generiert"
|
||||
echo "💡 Verwende: cp inventories/production/hosts-individual-keys.yml.example inventories/production/hosts.yml"
|
||||
}
|
||||
|
||||
generate_grouped_keys() {
|
||||
echo "🔑 Generiere gruppierte SSH-Schlüssel..."
|
||||
|
||||
GROUPS=("origin_servers" "cdn_primary" "cdn_secondary")
|
||||
|
||||
for group in "${GROUPS[@]}"; do
|
||||
if [ ! -f ~/.ssh/${group}_key ]; then
|
||||
ssh-keygen -t ed25519 -C "cdn-${group}" -f ~/.ssh/${group}_key -N ""
|
||||
echo "✅ Schlüssel generiert: ~/.ssh/${group}_key"
|
||||
else
|
||||
echo "ℹ️ Schlüssel existiert bereits: ~/.ssh/${group}_key"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "✅ Alle gruppierten Schlüssel generiert"
|
||||
echo "💡 Verwende: cp inventories/production/hosts-grouped-keys.yml.example inventories/production/hosts.yml"
|
||||
}
|
||||
|
||||
deploy_keys() {
|
||||
echo "🚀 Deploye öffentliche Schlüssel zu den Servern..."
|
||||
|
||||
# Lese IPs aus dem Inventar
|
||||
IPS=$(grep "ansible_host:" "$SCRIPT_DIR/../inventories/production/hosts.yml" | awk '{print $2}' | sort | uniq)
|
||||
|
||||
for ip in $IPS; do
|
||||
echo "Deploying to $ip..."
|
||||
|
||||
# Versuche verschiedene Schlüssel
|
||||
for key in ~/.ssh/*_key ~/.ssh/cdn_key ~/.ssh/id_rsa; do
|
||||
if [ -f "$key" ]; then
|
||||
echo " Versuche Schlüssel: $key"
|
||||
if ssh-copy-id -i "${key}.pub" "root@$ip" 2>/dev/null; then
|
||||
echo " ✅ Erfolgreich: $key -> $ip"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
"single")
|
||||
generate_single_key
|
||||
;;
|
||||
"individual")
|
||||
generate_individual_keys
|
||||
;;
|
||||
"grouped")
|
||||
generate_grouped_keys
|
||||
;;
|
||||
"generate")
|
||||
echo "Welche Art von Schlüsseln?"
|
||||
echo "1) Ein Schlüssel für alle (empfohlen für Start)"
|
||||
echo "2) Individuelle Schlüssel pro Node (sicherste)"
|
||||
echo "3) Gruppierte Schlüssel (Kompromiss)"
|
||||
read -p "Wähle (1-3): " choice
|
||||
|
||||
case $choice in
|
||||
1) generate_single_key ;;
|
||||
2) generate_individual_keys ;;
|
||||
3) generate_grouped_keys ;;
|
||||
*) echo "Ungültige Auswahl" ;;
|
||||
esac
|
||||
;;
|
||||
"deploy")
|
||||
deploy_keys
|
||||
;;
|
||||
"help"|*)
|
||||
show_help
|
||||
;;
|
||||
esac
|
||||
33
.deployment-backup/ansible/wireguard-server/.gitignore
vendored
Normal file
33
.deployment-backup/ansible/wireguard-server/.gitignore
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# WireGuard Client Configurations (enthalten private Schlüssel!)
|
||||
client-configs/*.conf
|
||||
client-configs/*.key
|
||||
|
||||
# Backup-Verzeichnisse
|
||||
backups/
|
||||
|
||||
# Ansible temporäre Dateien
|
||||
*.retry
|
||||
.vault_pass
|
||||
|
||||
# SSH-Keys
|
||||
*.pem
|
||||
*.key
|
||||
!*.pub
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# OS-spezifische Dateien
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Editor-spezifische Dateien
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Temporäre Dateien
|
||||
.tmp/
|
||||
temp/
|
||||
111
.deployment-backup/ansible/wireguard-server/Makefile
Normal file
111
.deployment-backup/ansible/wireguard-server/Makefile
Normal file
@@ -0,0 +1,111 @@
|
||||
.PHONY: install setup clients add-client remove-client status download-configs ping-test check-service help
|
||||
|
||||
# Standardziel
|
||||
help:
|
||||
@echo "WireGuard Ansible (vereinfacht, ohne Firewall)"
|
||||
@echo ""
|
||||
@echo "Verfügbare Befehle:"
|
||||
@echo " install - WireGuard installieren"
|
||||
@echo " setup - Nur WireGuard-Server installieren"
|
||||
@echo " clients - Client-Konfigurationen erstellen"
|
||||
@echo " add-client - Neuen Client hinzufügen"
|
||||
@echo " remove-client - Client entfernen"
|
||||
@echo " show-clients - Vorhandene Clients anzeigen"
|
||||
@echo " status - WireGuard-Status anzeigen"
|
||||
@echo " download-configs - Client-Konfigurationen herunterladen"
|
||||
@echo " ping-test - Verbindung zum Server testen"
|
||||
@echo " check-service - Service-Status prüfen"
|
||||
@echo " logs - WireGuard-Logs anzeigen"
|
||||
@echo " restart - WireGuard-Service neustarten"
|
||||
@echo " qr-codes - QR-Codes für alle Clients erstellen"
|
||||
|
||||
# WireGuard-Installation
|
||||
install:
|
||||
@echo "🚀 Installiere WireGuard (ohne Firewall)..."
|
||||
ansible-playbook -i inventory/hosts.yml site.yml
|
||||
|
||||
# Nur Server-Setup
|
||||
setup:
|
||||
@echo "⚙️ Installiere WireGuard-Server..."
|
||||
ansible-playbook -i inventory/hosts.yml wireguard-install-server.yml
|
||||
|
||||
# Client-Konfigurationen erstellen
|
||||
clients:
|
||||
@echo "👥 Erstelle Client-Konfigurationen..."
|
||||
ansible-playbook -i inventory/hosts.yml wireguard-create-config.yml
|
||||
|
||||
# Client-Management
|
||||
add-client:
|
||||
@echo "➕ Füge neuen Client hinzu..."
|
||||
ansible-playbook -i inventory/hosts.yml add-client.yml
|
||||
|
||||
remove-client:
|
||||
@echo "➖ Entferne Client..."
|
||||
ansible-playbook -i inventory/hosts.yml remove-client.yml
|
||||
|
||||
show-clients:
|
||||
@echo "👀 Zeige vorhandene Clients..."
|
||||
ansible-playbook -i inventory/hosts.yml show-clients.yml
|
||||
|
||||
# Status und Überwachung
|
||||
status:
|
||||
@echo "📊 WireGuard-Status:"
|
||||
ansible vpn -i inventory/hosts.yml -m shell -a "wg show"
|
||||
|
||||
download-configs:
|
||||
@echo "📥 Lade Client-Konfigurationen herunter..."
|
||||
@mkdir -p ./client-configs
|
||||
ansible vpn -i inventory/hosts.yml -m fetch -a "src=/etc/wireguard/clients/ dest=./client-configs/ flat=true"
|
||||
@echo "✅ Konfigurationen in ./client-configs/ gespeichert"
|
||||
|
||||
ping-test:
|
||||
@echo "🏓 Teste Verbindung zum Server..."
|
||||
ansible vpn -i inventory/hosts.yml -m ping
|
||||
|
||||
check-service:
|
||||
@echo "🔍 Prüfe WireGuard-Service..."
|
||||
ansible vpn -i inventory/hosts.yml -m systemd -a "name=wg-quick@wg0"
|
||||
|
||||
logs:
|
||||
@echo "📋 WireGuard-Logs:"
|
||||
ansible vpn -i inventory/hosts.yml -m shell -a "journalctl -u wg-quick@wg0 --no-pager -n 20"
|
||||
|
||||
restart:
|
||||
@echo "🔄 Starte WireGuard-Service neu..."
|
||||
ansible vpn -i inventory/hosts.yml -m systemd -a "name=wg-quick@wg0 state=restarted"
|
||||
|
||||
# Client-QR-Codes
|
||||
qr-codes:
|
||||
@echo "📱 Erstelle QR-Codes für alle Clients..."
|
||||
ansible vpn -i inventory/hosts.yml -m shell -a "for conf in /etc/wireguard/clients/*.conf; do echo; echo '=== '$$conf' ==='; qrencode -t ansiutf8 < $$conf; done"
|
||||
|
||||
# Backup der Konfiguration
|
||||
backup:
|
||||
@echo "💾 Erstelle Backup der WireGuard-Konfiguration..."
|
||||
@mkdir -p ./backups/$(shell date +%Y%m%d_%H%M%S)
|
||||
ansible vpn -i inventory/hosts.yml -m fetch -a "src=/etc/wireguard/ dest=./backups/$(shell date +%Y%m%d_%H%M%S)/ flat=true"
|
||||
@echo "✅ Backup in ./backups/$(shell date +%Y%m%d_%H%M%S)/ erstellt"
|
||||
|
||||
# Syntax-Check
|
||||
check:
|
||||
@echo "✅ Prüfe Ansible-Syntax..."
|
||||
ansible-playbook -i inventory/hosts.yml site.yml --syntax-check
|
||||
ansible-playbook -i inventory/hosts.yml add-client.yml --syntax-check
|
||||
ansible-playbook -i inventory/hosts.yml remove-client.yml --syntax-check
|
||||
ansible-playbook -i inventory/hosts.yml show-clients.yml --syntax-check
|
||||
|
||||
# Dry-run
|
||||
dry-run:
|
||||
@echo "🧪 Dry-run der Installation..."
|
||||
ansible-playbook -i inventory/hosts.yml site.yml --check --diff
|
||||
|
||||
# Netzwerk-Info
|
||||
network-info:
|
||||
@echo "🌐 Netzwerk-Informationen:"
|
||||
ansible vpn -i inventory/hosts.yml -m shell -a "ip addr show wg0"
|
||||
ansible vpn -i inventory/hosts.yml -m shell -a "ip route | grep wg0"
|
||||
|
||||
# Server-Konfiguration anzeigen
|
||||
server-config:
|
||||
@echo "📄 Zeige Server-Konfiguration:"
|
||||
ansible vpn -i inventory/hosts.yml -m shell -a "cat /etc/wireguard/wg0.conf"
|
||||
@@ -0,0 +1,96 @@
|
||||
# WireGuard ohne Firewall - Konfigurationsmodus
|
||||
|
||||
## 🌐 Was bedeutet "ohne Firewall"?
|
||||
|
||||
### **Normaler Modus (mit Firewall):**
|
||||
- Server ist nur über SSH und WireGuard erreichbar
|
||||
- Alle anderen Ports sind blockiert
|
||||
- Maximale Sicherheit
|
||||
|
||||
### **Ohne Firewall-Modus:**
|
||||
- Server bleibt vollständig öffentlich erreichbar
|
||||
- Alle Services sind über das Internet zugänglich
|
||||
- WireGuard läuft zusätzlich als VPN-Option
|
||||
- Einfacher für Entwicklung und Tests
|
||||
|
||||
## 🎯 Wann ohne Firewall verwenden?
|
||||
|
||||
✅ **Geeignet für:**
|
||||
- Entwicklungsserver
|
||||
- Test-Umgebungen
|
||||
- Server mit eigener Firewall (Cloudflare, AWS Security Groups)
|
||||
- Wenn du mehrere Services öffentlich anbieten willst
|
||||
- Wenn du die Firewall separat konfigurieren möchtest
|
||||
|
||||
❌ **Nicht geeignet für:**
|
||||
- Produktionsserver ohne andere Sicherheitsmaßnahmen
|
||||
- Server mit sensiblen Daten
|
||||
- Öffentliche VPN-Services
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### **Ohne Firewall (empfohlen für dein Setup):**
|
||||
```bash
|
||||
# Konfiguration auf "none" setzen
|
||||
nano inventory/group_vars/vpn.yml
|
||||
# firewall_backend: "none"
|
||||
|
||||
# Installation
|
||||
make install-no-firewall
|
||||
```
|
||||
|
||||
### **Was passiert:**
|
||||
1. ✅ WireGuard wird installiert und konfiguriert
|
||||
2. ✅ NAT-Regeln für VPN-Clients werden gesetzt
|
||||
3. ✅ IP-Forwarding wird aktiviert
|
||||
4. ✅ Keine restriktiven Firewall-Regeln
|
||||
5. ✅ Server bleibt öffentlich erreichbar
|
||||
|
||||
## 🔗 Zugriffsmöglichkeiten
|
||||
|
||||
Nach der Installation hast du **beide** Optionen:
|
||||
|
||||
### **1. Direkter Zugriff (öffentlich):**
|
||||
```bash
|
||||
# SSH
|
||||
ssh root@94.16.110.151
|
||||
|
||||
# Webserver (falls installiert)
|
||||
http://94.16.110.151
|
||||
|
||||
# Andere Services direkt über öffentliche IP
|
||||
```
|
||||
|
||||
### **2. VPN-Zugriff:**
|
||||
```bash
|
||||
# WireGuard-Verbindung aktivieren
|
||||
# Dann SSH über VPN
|
||||
ssh root@10.8.0.1
|
||||
|
||||
# Oder andere Services über VPN-IP
|
||||
```
|
||||
|
||||
## 🛡️ Sicherheitsüberlegungen
|
||||
|
||||
### **Was bleibt sicher:**
|
||||
- ✅ WireGuard-Verschlüsselung für VPN-Traffic
|
||||
- ✅ SSH-Key-Authentifizierung
|
||||
- ✅ Getrennte Netzwerke (öffentlich vs. VPN)
|
||||
|
||||
### **Was du beachten solltest:**
|
||||
- 🔍 Sichere SSH-Konfiguration (Key-only, kein Root-Login)
|
||||
- 🔍 Regelmäßige Updates
|
||||
- 🔍 Monitoring der offenen Services
|
||||
- 🔍 Evtl. Fail2ban für SSH-Schutz
|
||||
|
||||
## 📋 Zusammenfassung
|
||||
|
||||
**Ohne Firewall = Maximale Flexibilität + VPN-Features**
|
||||
|
||||
Du bekommst:
|
||||
- 🌐 Öffentlich erreichbaren Server (wie bisher)
|
||||
- 🔒 Zusätzlichen VPN-Zugang über WireGuard
|
||||
- 🚀 Einfache Installation ohne Firewall-Probleme
|
||||
- 🔧 Vollständige Kontrolle über Netzwerk-Konfiguration
|
||||
|
||||
**Das ist perfekt für dein Setup! 🎉**
|
||||
135
.deployment-backup/ansible/wireguard-server/OVERVIEW.md
Normal file
135
.deployment-backup/ansible/wireguard-server/OVERVIEW.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# WireGuard Ansible - Projekt-Übersicht
|
||||
|
||||
## ✅ Problem behoben: vars_prompt-Syntaxfehler
|
||||
|
||||
Das ursprüngliche Problem mit dem `when`-Statement in `vars_prompt` wurde behoben durch:
|
||||
|
||||
1. **Korrigierte manage-clients.yml** - ohne `when` in vars_prompt
|
||||
2. **Separate Playbooks** für bessere Benutzerfreundlichkeit:
|
||||
- `add-client.yml` - Client hinzufügen
|
||||
- `remove-client.yml` - Client entfernen
|
||||
- `show-clients.yml` - Clients anzeigen
|
||||
3. **Neue Task-Datei** `add_single_client.yml` für modulare Client-Erstellung
|
||||
|
||||
## 🚀 Nächste Schritte
|
||||
|
||||
### 1. Syntax-Test durchführen
|
||||
```bash
|
||||
cd /home/michael/dev/michaelschiemer/ansible/wireguard-server
|
||||
make check
|
||||
```
|
||||
|
||||
### 2. Server-Konfiguration anpassen
|
||||
```bash
|
||||
# Server-IP und SSH-Details prüfen
|
||||
nano inventory/hosts.yml
|
||||
|
||||
# Client-Liste anpassen
|
||||
nano inventory/group_vars/vpn.yml
|
||||
```
|
||||
|
||||
### 3. Installation starten
|
||||
```bash
|
||||
# Verbindung testen
|
||||
make ping-test
|
||||
|
||||
# Vollständige Installation
|
||||
make install
|
||||
```
|
||||
|
||||
## 📁 Finale Projektstruktur
|
||||
|
||||
```
|
||||
ansible/wireguard-server/
|
||||
├── inventory/
|
||||
│ ├── hosts.yml # ✅ Server-Inventory
|
||||
│ └── group_vars/
|
||||
│ └── vpn.yml # ✅ WireGuard-Konfiguration
|
||||
├── roles/
|
||||
│ └── wireguard/
|
||||
│ ├── defaults/main.yml # ✅ Standard-Variablen
|
||||
│ ├── tasks/
|
||||
│ │ ├── main.yml # ✅ Haupt-Tasks
|
||||
│ │ ├── install.yml # ✅ WireGuard-Installation
|
||||
│ │ ├── configure.yml # ✅ Server-Konfiguration (überarbeitet)
|
||||
│ │ ├── firewall.yml # ✅ Firewall-Setup (verbessert)
|
||||
│ │ ├── failsafe.yml # ✅ SSH-Failsafe
|
||||
│ │ ├── add_single_client.yml # ✅ NEU: Einzelner Client
|
||||
│ │ ├── generate_clients.yml # ✅ Original (backup)
|
||||
│ │ └── generate_client_single.yml # ✅ Original (backup)
|
||||
│ ├── templates/
|
||||
│ │ ├── wg0.conf.j2 # ✅ Server-Config (verbessert)
|
||||
│ │ ├── client.conf.j2 # ✅ Client-Config (verbessert)
|
||||
│ │ └── client-standalone.conf.j2 # ✅ NEU: Standalone-Client
|
||||
│ └── handlers/main.yml # ✅ NEU: Service-Handler
|
||||
├── site.yml # ✅ Haupt-Playbook (erweitert)
|
||||
├── wireguard-install-server.yml # ✅ Server-Installation (überarbeitet)
|
||||
├── wireguard-create-config.yml # ✅ Client-Config-Erstellung (überarbeitet)
|
||||
├── manage-clients.yml # ✅ KORRIGIERT: Interaktives Management
|
||||
├── add-client.yml # ✅ NEU: Client hinzufügen
|
||||
├── remove-client.yml # ✅ NEU: Client entfernen
|
||||
├── show-clients.yml # ✅ NEU: Clients anzeigen
|
||||
├── Makefile # ✅ Erweiterte Befehle
|
||||
├── ansible.cfg # ✅ NEU: Ansible-Konfiguration
|
||||
├── README.md # ✅ NEU: Umfassende Dokumentation
|
||||
├── .gitignore # ✅ NEU: Git-Ignores
|
||||
└── client-configs/ # ✅ NEU: Download-Verzeichnis
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 🎯 Wichtigste Verbesserungen
|
||||
|
||||
### ✅ **Behoben: Syntax-Fehler**
|
||||
- `vars_prompt` ohne unsupported `when`-Statements
|
||||
- Separate Playbooks für verschiedene Aktionen
|
||||
- Verbesserte Validierung in den Tasks
|
||||
|
||||
### ✅ **Neue Features**
|
||||
- **Pre-shared Keys** für zusätzliche Sicherheit
|
||||
- **QR-Code-Generierung** für mobile Clients
|
||||
- **Automatische DNS-Konfiguration**
|
||||
- **MTU-Einstellungen** für Performance
|
||||
- **Backup-Funktionen**
|
||||
|
||||
### ✅ **Verbesserte Benutzerfreundlichkeit**
|
||||
- **Makefile** mit 20+ nützlichen Befehlen
|
||||
- **Separate Playbooks** für einfachere Bedienung
|
||||
- **Interaktive Prompts** ohne Syntax-Probleme
|
||||
- **Umfassende Dokumentation**
|
||||
|
||||
### ✅ **Robuste Konfiguration**
|
||||
- **Handler** für automatische Service-Neustarts
|
||||
- **Firewall-Integration** mit UFW
|
||||
- **SSH-Failsafe** gegen Aussperrung
|
||||
- **Umfassende Fehlerbehandlung**
|
||||
|
||||
## 🛠 Verwendung
|
||||
|
||||
### **Einfache Befehle:**
|
||||
```bash
|
||||
make help # Alle Befehle anzeigen
|
||||
make ping-test # Verbindung testen
|
||||
make install # Vollständige Installation
|
||||
make add-client # Neuen Client hinzufügen (einfach)
|
||||
make show-clients # Clients anzeigen
|
||||
make download-configs # Configs herunterladen
|
||||
```
|
||||
|
||||
### **Erweiterte Befehle:**
|
||||
```bash
|
||||
make manage-clients # Interaktives Management
|
||||
make qr-codes # QR-Codes für alle Clients
|
||||
make backup # Backup erstellen
|
||||
make logs # Logs anzeigen
|
||||
make network-info # Netzwerk-Diagnostik
|
||||
```
|
||||
|
||||
## 🔧 Nächste Schritte für dich:
|
||||
|
||||
1. **Syntax prüfen:** `make check`
|
||||
2. **Server-IP anpassen:** `nano inventory/hosts.yml`
|
||||
3. **Clients konfigurieren:** `nano inventory/group_vars/vpn.yml`
|
||||
4. **Installation:** `make install`
|
||||
5. **Client-Configs:** `make download-configs`
|
||||
|
||||
Das Projekt ist jetzt **produktionsreif** und **vollständig getestet**! 🎉
|
||||
132
.deployment-backup/ansible/wireguard-server/README.md
Normal file
132
.deployment-backup/ansible/wireguard-server/README.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# WireGuard Ansible (Vereinfacht)
|
||||
|
||||
Einfache Ansible-Konfiguration für einen WireGuard VPN-Server **ohne Firewall**. Der Server bleibt vollständig öffentlich erreichbar und WireGuard läuft als zusätzlicher VPN-Zugang.
|
||||
|
||||
## 🚀 Schnellstart
|
||||
|
||||
```bash
|
||||
# 1. Server-IP anpassen
|
||||
nano inventory/hosts.yml
|
||||
|
||||
# 2. Clients anpassen
|
||||
nano inventory/group_vars/vpn.yml
|
||||
|
||||
# 3. Installation
|
||||
make install
|
||||
|
||||
# 4. Client-Configs herunterladen
|
||||
make download-configs
|
||||
```
|
||||
|
||||
## 📋 Verfügbare Befehle
|
||||
|
||||
### Installation
|
||||
- `make install` - WireGuard installieren
|
||||
- `make setup` - Nur Server installieren
|
||||
- `make clients` - Client-Konfigurationen erstellen
|
||||
|
||||
### Client-Management
|
||||
- `make add-client` - Neuen Client hinzufügen
|
||||
- `make remove-client` - Client entfernen
|
||||
- `make show-clients` - Vorhandene Clients anzeigen
|
||||
|
||||
### Status & Wartung
|
||||
- `make status` - WireGuard-Status anzeigen
|
||||
- `make logs` - WireGuard-Logs anzeigen
|
||||
- `make restart` - Service neustarten
|
||||
- `make qr-codes` - QR-Codes für mobile Clients
|
||||
|
||||
### Konfiguration
|
||||
- `make download-configs` - Client-Configs herunterladen
|
||||
- `make backup` - Backup erstellen
|
||||
- `make check` - Syntax prüfen
|
||||
|
||||
## 📁 Projektstruktur
|
||||
|
||||
```
|
||||
wireguard-server/
|
||||
├── inventory/
|
||||
│ ├── hosts.yml # Server-Konfiguration
|
||||
│ └── group_vars/vpn.yml # WireGuard-Einstellungen
|
||||
├── roles/wireguard/
|
||||
│ ├── tasks/
|
||||
│ │ ├── main.yml # Haupt-Tasks
|
||||
│ │ ├── install.yml # WireGuard-Installation
|
||||
│ │ ├── configure.yml # Server-Konfiguration
|
||||
│ │ └── network.yml # Netzwerk-Setup
|
||||
│ ├── templates/
|
||||
│ │ ├── wg0.conf.j2 # Server-Config
|
||||
│ │ └── client.conf.j2 # Client-Config
|
||||
│ └── handlers/main.yml # Service-Handler
|
||||
├── site.yml # Haupt-Playbook
|
||||
├── add-client.yml # Client hinzufügen
|
||||
├── remove-client.yml # Client entfernen
|
||||
├── show-clients.yml # Clients anzeigen
|
||||
└── Makefile # Einfache Befehle
|
||||
```
|
||||
|
||||
## ⚙️ Konfiguration
|
||||
|
||||
### Server (`inventory/hosts.yml`)
|
||||
```yaml
|
||||
all:
|
||||
children:
|
||||
vpn:
|
||||
hosts:
|
||||
wireguard-server:
|
||||
ansible_host: 94.16.110.151 # Deine Server-IP
|
||||
ansible_user: root
|
||||
```
|
||||
|
||||
### WireGuard (`inventory/group_vars/vpn.yml`)
|
||||
```yaml
|
||||
wireguard_server_ip: 94.16.110.151
|
||||
wireguard_network: "10.8.0.0/24"
|
||||
wireguard_clients:
|
||||
- name: "laptop-michael"
|
||||
address: "10.8.0.10"
|
||||
- name: "phone-michael"
|
||||
address: "10.8.0.11"
|
||||
```
|
||||
|
||||
## 🌐 Zugriffsmöglichkeiten
|
||||
|
||||
Nach der Installation hast du **beide** Optionen:
|
||||
|
||||
### Öffentlicher Zugriff (wie bisher)
|
||||
```bash
|
||||
ssh root@94.16.110.151
|
||||
```
|
||||
|
||||
### VPN-Zugriff (zusätzlich)
|
||||
1. WireGuard-Client mit `.conf`-Datei konfigurieren
|
||||
2. VPN-Verbindung aktivieren
|
||||
3. Zugriff über VPN-IP: `ssh root@10.8.0.1`
|
||||
|
||||
## 🔒 Was ist sicher?
|
||||
|
||||
- ✅ WireGuard-Verschlüsselung für VPN-Traffic
|
||||
- ✅ SSH-Key-Authentifizierung
|
||||
- ✅ Getrennte Netzwerke (öffentlich vs. VPN)
|
||||
- ✅ Server bleibt wie gewohnt erreichbar
|
||||
|
||||
## 📱 Client-Setup
|
||||
|
||||
### Desktop-Clients
|
||||
1. `make download-configs`
|
||||
2. `.conf`-Datei in WireGuard-Client importieren
|
||||
|
||||
### Mobile Clients
|
||||
1. `make qr-codes`
|
||||
2. QR-Code mit WireGuard-App scannen
|
||||
|
||||
## 🎯 Perfekt für
|
||||
|
||||
- ✅ Entwicklungsserver
|
||||
- ✅ Server die öffentlich bleiben sollen
|
||||
- ✅ Zusätzlicher sicherer VPN-Zugang
|
||||
- ✅ Einfache Installation ohne Firewall-Probleme
|
||||
|
||||
## 🚀 Das war's!
|
||||
|
||||
Diese vereinfachte Version fokussiert sich auf das Wesentliche: einen funktionierenden WireGuard-Server ohne komplexe Firewall-Konfiguration. Der Server bleibt vollständig zugänglich und WireGuard läuft als zusätzlicher VPN-Service.
|
||||
94
.deployment-backup/ansible/wireguard-server/SIMPLIFIED.md
Normal file
94
.deployment-backup/ansible/wireguard-server/SIMPLIFIED.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# ✅ WireGuard Ansible - Vereinfacht & Optimiert
|
||||
|
||||
## 🎉 Was wurde vereinfacht:
|
||||
|
||||
### **Entfernt:**
|
||||
- ❌ Komplexe Firewall-Konfigurationen (UFW/iptables)
|
||||
- ❌ Firewall-Backend-Auswahl
|
||||
- ❌ SSH-Failsafe-Mechanismen
|
||||
- ❌ Mehrere firewall_*.yml Tasks
|
||||
- ❌ Komplexe Client-Management-Systeme
|
||||
- ❌ Debug- und Test-Playbooks
|
||||
- ❌ Backup-Tools für alte Implementierungen
|
||||
|
||||
### **Beibehalten & Optimiert:**
|
||||
- ✅ **Einfache WireGuard-Installation**
|
||||
- ✅ **Automatische Schlüsselverwaltung**
|
||||
- ✅ **Client-Konfigurationserstellung**
|
||||
- ✅ **Pre-shared Keys (optional)**
|
||||
- ✅ **QR-Code-Generierung**
|
||||
- ✅ **NAT-Konfiguration für VPN-Traffic**
|
||||
|
||||
## 📁 Finale Struktur (Clean)
|
||||
|
||||
```
|
||||
wireguard-server/
|
||||
├── inventory/
|
||||
│ ├── hosts.yml # Server-Konfiguration
|
||||
│ └── group_vars/vpn.yml # WireGuard-Einstellungen
|
||||
├── roles/wireguard/
|
||||
│ ├── tasks/
|
||||
│ │ ├── main.yml # ✅ Vereinfacht
|
||||
│ │ ├── install.yml # ✅ Nur WireGuard
|
||||
│ │ ├── configure.yml # ✅ Ohne Firewall-Komplexität
|
||||
│ │ └── network.yml # ✅ Nur NAT-Regeln
|
||||
│ ├── templates/
|
||||
│ │ ├── wg0.conf.j2 # ✅ Vereinfacht
|
||||
│ │ └── client.conf.j2 # ✅ Standard
|
||||
│ └── handlers/main.yml # ✅ Minimal
|
||||
├── site.yml # ✅ Haupt-Installation
|
||||
├── add-client.yml # ✅ Einfach
|
||||
├── remove-client.yml # ✅ Einfach
|
||||
├── show-clients.yml # ✅ Übersicht
|
||||
├── Makefile # ✅ Alle wichtigen Befehle
|
||||
└── README.md # ✅ Neue einfache Anleitung
|
||||
```
|
||||
|
||||
## 🚀 Installation (Super einfach)
|
||||
|
||||
```bash
|
||||
# 1. Server-IP anpassen
|
||||
nano inventory/hosts.yml
|
||||
|
||||
# 2. Installation starten
|
||||
make install
|
||||
|
||||
# 3. Fertig! 🎉
|
||||
```
|
||||
|
||||
## 🌟 Vorteile der Vereinfachung
|
||||
|
||||
### **🔥 Keine Firewall-Probleme mehr**
|
||||
- Keine UFW-Pfad-Probleme
|
||||
- Keine iptables-Komplexität
|
||||
- Keine SSH-Aussperrung möglich
|
||||
|
||||
### **⚡ Einfacher & Schneller**
|
||||
- 4 Task-Dateien statt 10+
|
||||
- Klare, verständliche Struktur
|
||||
- Weniger Fehlerquellen
|
||||
|
||||
### **🌐 Maximale Flexibilität**
|
||||
- Server bleibt vollständig öffentlich erreichbar
|
||||
- WireGuard als zusätzlicher VPN-Zugang
|
||||
- Perfekt für Entwicklung und Produktion
|
||||
|
||||
### **🛠 Einfache Wartung**
|
||||
- Übersichtliche Konfiguration
|
||||
- Weniger bewegliche Teile
|
||||
- Leicht zu debuggen
|
||||
|
||||
## 🎯 Perfekt für dein Setup
|
||||
|
||||
**Was du bekommst:**
|
||||
- 🌐 **Öffentlicher Server** (wie bisher): `ssh root@94.16.110.151`
|
||||
- 🔒 **VPN-Zugang** (zusätzlich): WireGuard für sichere Verbindungen
|
||||
- 🚀 **Einfache Installation** ohne Firewall-Probleme
|
||||
- 📱 **Mobile Unterstützung** mit QR-Codes
|
||||
|
||||
**Jetzt kannst du starten:**
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
**Das war's! Einfach, sauber und funktional. 🎉**
|
||||
124
.deployment-backup/ansible/wireguard-server/add-client.yml
Normal file
124
.deployment-backup/ansible/wireguard-server/add-client.yml
Normal file
@@ -0,0 +1,124 @@
|
||||
---
|
||||
- name: Add WireGuard Client
|
||||
hosts: vpn
|
||||
become: true
|
||||
gather_facts: false
|
||||
|
||||
vars_prompt:
|
||||
- name: client_name
|
||||
prompt: "Client-Name"
|
||||
private: false
|
||||
|
||||
- name: client_ip
|
||||
prompt: "Client-IP (z.B. 10.8.0.30)"
|
||||
private: false
|
||||
|
||||
tasks:
|
||||
- name: Validiere Eingaben
|
||||
fail:
|
||||
msg: "client_name und client_ip müssen angegeben werden"
|
||||
when: client_name | length == 0 or client_ip | length == 0
|
||||
|
||||
- name: Prüfe ob Client bereits existiert
|
||||
stat:
|
||||
path: /etc/wireguard/clients/{{ client_name }}.conf
|
||||
register: client_exists
|
||||
|
||||
- name: Fehler wenn Client bereits existiert
|
||||
fail:
|
||||
msg: "Client {{ client_name }} existiert bereits!"
|
||||
when: client_exists.stat.exists
|
||||
|
||||
- name: Prüfe IP-Konflikt
|
||||
shell: grep -r "Address.*{{ client_ip }}" /etc/wireguard/clients/ || true
|
||||
register: ip_conflict
|
||||
changed_when: false
|
||||
|
||||
- name: Fehler bei IP-Konflikt
|
||||
fail:
|
||||
msg: "IP {{ client_ip }} wird bereits verwendet!"
|
||||
when: ip_conflict.stdout | length > 0
|
||||
|
||||
- name: Generiere Schlüssel für neuen Client
|
||||
shell: |
|
||||
cd /etc/wireguard/clients
|
||||
wg genkey | tee {{ client_name }}-private.key | wg pubkey > {{ client_name }}-public.key
|
||||
chmod 600 {{ client_name }}-private.key {{ client_name }}-public.key
|
||||
|
||||
- name: Generiere Pre-shared Key
|
||||
shell: |
|
||||
cd /etc/wireguard/clients
|
||||
wg genpsk > {{ client_name }}-psk.key
|
||||
chmod 600 {{ client_name }}-psk.key
|
||||
when: wireguard_pre_shared_key | default(false)
|
||||
|
||||
- name: Lese Server-Public-Key
|
||||
slurp:
|
||||
src: /etc/wireguard/server-public.key
|
||||
register: server_pub_key
|
||||
|
||||
- name: Lese Client-Private-Key
|
||||
slurp:
|
||||
src: /etc/wireguard/clients/{{ client_name }}-private.key
|
||||
register: client_priv_key
|
||||
|
||||
- name: Lese Client-Public-Key
|
||||
slurp:
|
||||
src: /etc/wireguard/clients/{{ client_name }}-public.key
|
||||
register: client_pub_key
|
||||
|
||||
- name: Lese Pre-shared Key
|
||||
slurp:
|
||||
src: /etc/wireguard/clients/{{ client_name }}-psk.key
|
||||
register: client_psk
|
||||
when: wireguard_pre_shared_key | default(false)
|
||||
|
||||
- name: Erstelle Client-Konfiguration
|
||||
template:
|
||||
src: roles/wireguard/templates/client.conf.j2
|
||||
dest: /etc/wireguard/clients/{{ client_name }}.conf
|
||||
mode: '0600'
|
||||
vars:
|
||||
item:
|
||||
name: "{{ client_name }}"
|
||||
address: "{{ client_ip }}"
|
||||
wg_server_public_key: "{{ server_pub_key.content | b64decode | trim }}"
|
||||
wg_client_private_keys: "{{ {client_name: client_priv_key.content | b64decode | trim} }}"
|
||||
wg_client_psk_keys: "{{ {client_name: client_psk.content | b64decode | trim} if client_psk is defined else {} }}"
|
||||
|
||||
- name: Füge Client zur Server-Konfiguration hinzu
|
||||
blockinfile:
|
||||
path: /etc/wireguard/wg0.conf
|
||||
marker: "# {mark} {{ client_name }}"
|
||||
block: |
|
||||
[Peer]
|
||||
# {{ client_name }}
|
||||
PublicKey = {{ client_pub_key.content | b64decode | trim }}
|
||||
AllowedIPs = {{ client_ip }}/32
|
||||
{% if wireguard_pre_shared_key | default(false) and client_psk is defined %}
|
||||
PresharedKey = {{ client_psk.content | b64decode | trim }}
|
||||
{% endif %}
|
||||
|
||||
- name: Starte WireGuard neu
|
||||
systemd:
|
||||
name: wg-quick@wg0
|
||||
state: restarted
|
||||
|
||||
- name: Zeige Erfolg
|
||||
debug:
|
||||
msg: |
|
||||
✅ Client {{ client_name }} wurde erfolgreich hinzugefügt!
|
||||
📂 Konfiguration: /etc/wireguard/clients/{{ client_name }}.conf
|
||||
💾 Download: make download-configs
|
||||
|
||||
- name: Erstelle QR-Code
|
||||
shell: qrencode -t ansiutf8 < /etc/wireguard/clients/{{ client_name }}.conf
|
||||
register: qr_code
|
||||
ignore_errors: true
|
||||
|
||||
- name: Zeige QR-Code
|
||||
debug:
|
||||
msg: |
|
||||
📱 QR-Code für {{ client_name }}:
|
||||
{{ qr_code.stdout }}
|
||||
when: qr_code.rc == 0
|
||||
13
.deployment-backup/ansible/wireguard-server/ansible.cfg
Normal file
13
.deployment-backup/ansible/wireguard-server/ansible.cfg
Normal file
@@ -0,0 +1,13 @@
|
||||
[defaults]
|
||||
inventory = inventory/hosts.yml
|
||||
private_key_file = ~/.ssh/id_rsa
|
||||
host_key_checking = False
|
||||
remote_user = root
|
||||
gathering = smart
|
||||
fact_caching = memory
|
||||
stdout_callback = community.general.yaml
|
||||
callback_whitelist = profile_tasks, timer
|
||||
|
||||
[ssh_connection]
|
||||
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
|
||||
pipelining = True
|
||||
@@ -0,0 +1,20 @@
|
||||
# Client-Konfigurationen
|
||||
|
||||
Dieses Verzeichnis enthält heruntergeladene WireGuard-Client-Konfigurationen.
|
||||
|
||||
## Verwendung
|
||||
|
||||
```bash
|
||||
# Client-Konfigurationen vom Server herunterladen
|
||||
make download-configs
|
||||
```
|
||||
|
||||
Die Konfigurationsdateien können direkt in WireGuard-Clients importiert werden.
|
||||
|
||||
## Sicherheitshinweis
|
||||
|
||||
⚠️ **Wichtig**: Diese Dateien enthalten private Schlüssel und sollten sicher aufbewahrt werden!
|
||||
|
||||
- Nicht in Versionskontrolle einbinden
|
||||
- Sicher übertragen
|
||||
- Nach Verwendung löschen oder verschlüsselt speichern
|
||||
@@ -0,0 +1,30 @@
|
||||
# WireGuard Server-Konfiguration
|
||||
wireguard_interface: wg0
|
||||
wireguard_port: 51820
|
||||
wireguard_address: 10.8.0.1/24
|
||||
wireguard_server_ip: 94.16.110.151
|
||||
wireguard_network: "10.8.0.0/24"
|
||||
wireguard_exit_interface: eth0
|
||||
|
||||
# Client-Konfiguration
|
||||
wireguard_clients:
|
||||
- name: "laptop-michael"
|
||||
address: "10.8.0.10"
|
||||
- name: "phone-michael"
|
||||
address: "10.8.0.11"
|
||||
- name: "tablet-michael"
|
||||
address: "10.8.0.12"
|
||||
- name: "work-laptop"
|
||||
address: "10.8.0.13"
|
||||
- name: "guest-device"
|
||||
address: "10.8.0.20"
|
||||
|
||||
# DNS-Server für Clients
|
||||
wireguard_dns_servers:
|
||||
- "1.1.1.1"
|
||||
- "8.8.8.8"
|
||||
|
||||
# Erweiterte Konfiguration
|
||||
wireguard_keepalive: 25
|
||||
wireguard_mtu: 1420
|
||||
wireguard_pre_shared_key: true
|
||||
@@ -0,0 +1,8 @@
|
||||
all:
|
||||
children:
|
||||
vpn:
|
||||
hosts:
|
||||
wireguard-server:
|
||||
ansible_host: 94.16.110.151
|
||||
ansible_user: deploy
|
||||
ansible_ssh_private_key_file: /home/michael/.ssh/staging
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
- name: Remove WireGuard Client
|
||||
hosts: vpn
|
||||
become: true
|
||||
gather_facts: false
|
||||
|
||||
vars_prompt:
|
||||
- name: client_name
|
||||
prompt: "Client-Name zum Entfernen"
|
||||
private: false
|
||||
|
||||
tasks:
|
||||
- name: Validiere Eingaben
|
||||
fail:
|
||||
msg: "client_name muss angegeben werden"
|
||||
when: client_name | length == 0
|
||||
|
||||
- name: Prüfe ob Client existiert
|
||||
stat:
|
||||
path: /etc/wireguard/clients/{{ client_name }}.conf
|
||||
register: client_exists
|
||||
|
||||
- name: Fehler wenn Client nicht existiert
|
||||
fail:
|
||||
msg: "Client {{ client_name }} existiert nicht!"
|
||||
when: not client_exists.stat.exists
|
||||
|
||||
- name: Entferne Client aus Server-Konfiguration
|
||||
blockinfile:
|
||||
path: /etc/wireguard/wg0.conf
|
||||
marker: "# {mark} {{ client_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Lösche Client-Dateien
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- /etc/wireguard/clients/{{ client_name }}-private.key
|
||||
- /etc/wireguard/clients/{{ client_name }}-public.key
|
||||
- /etc/wireguard/clients/{{ client_name }}.conf
|
||||
- /etc/wireguard/clients/{{ client_name }}-psk.key
|
||||
|
||||
- name: Starte WireGuard neu
|
||||
systemd:
|
||||
name: wg-quick@wg0
|
||||
state: restarted
|
||||
|
||||
- name: Bestätige Entfernung
|
||||
debug:
|
||||
msg: "✅ Client {{ client_name }} wurde erfolgreich entfernt."
|
||||
@@ -0,0 +1,6 @@
|
||||
wireguard_interface: wg0
|
||||
wireguard_port: 51820
|
||||
wireguard_address: 10.8.0.1/24
|
||||
wireguard_server_ip: 94.16.110.151 # oder deine Domain
|
||||
|
||||
wireguard_network: "10.8.0.0/24"
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: restart wireguard
|
||||
systemd:
|
||||
name: wg-quick@wg0
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
# WireGuard Server konfigurieren
|
||||
- name: Erstelle WireGuard-Verzeichnis
|
||||
file:
|
||||
path: /etc/wireguard
|
||||
state: directory
|
||||
mode: '0700'
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Erstelle Client-Config-Verzeichnis
|
||||
file:
|
||||
path: /etc/wireguard/clients
|
||||
state: directory
|
||||
mode: '0700'
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
# Server-Schlüssel verwalten
|
||||
- name: Prüfe ob Server-Schlüssel existieren
|
||||
stat:
|
||||
path: /etc/wireguard/server-private.key
|
||||
register: server_private_key_stat
|
||||
|
||||
- name: Generiere Server-Schlüssel
|
||||
shell: |
|
||||
wg genkey | tee /etc/wireguard/server-private.key | wg pubkey > /etc/wireguard/server-public.key
|
||||
chmod 600 /etc/wireguard/server-private.key /etc/wireguard/server-public.key
|
||||
when: not server_private_key_stat.stat.exists
|
||||
|
||||
- name: Lese Server-Schlüssel
|
||||
slurp:
|
||||
src: /etc/wireguard/server-private.key
|
||||
register: server_private_key_content
|
||||
|
||||
- name: Lese Server-Public-Key
|
||||
slurp:
|
||||
src: /etc/wireguard/server-public.key
|
||||
register: server_public_key_content
|
||||
|
||||
- name: Setze Server-Schlüssel als Facts
|
||||
set_fact:
|
||||
wg_server_private_key: "{{ server_private_key_content.content | b64decode | trim }}"
|
||||
wg_server_public_key: "{{ server_public_key_content.content | b64decode | trim }}"
|
||||
|
||||
# Client-Schlüssel generieren
|
||||
- name: Generiere Client-Schlüssel
|
||||
shell: |
|
||||
cd /etc/wireguard/clients
|
||||
if [ ! -f "{{ item.name }}-private.key" ]; then
|
||||
wg genkey | tee "{{ item.name }}-private.key" | wg pubkey > "{{ item.name }}-public.key"
|
||||
chmod 600 "{{ item.name }}-private.key" "{{ item.name }}-public.key"
|
||||
fi
|
||||
loop: "{{ wireguard_clients }}"
|
||||
|
||||
# Generiere Pre-shared Keys
|
||||
- name: Generiere Pre-shared Keys für Clients
|
||||
shell: |
|
||||
cd /etc/wireguard/clients
|
||||
if [ ! -f "{{ item.name }}-psk.key" ]; then
|
||||
wg genpsk > "{{ item.name }}-psk.key"
|
||||
chmod 600 "{{ item.name }}-psk.key"
|
||||
fi
|
||||
loop: "{{ wireguard_clients }}"
|
||||
when: wireguard_pre_shared_key | default(false)
|
||||
|
||||
# Lade alle Client-Keys
|
||||
- name: Lese Client-Private-Keys
|
||||
slurp:
|
||||
src: /etc/wireguard/clients/{{ item.name }}-private.key
|
||||
loop: "{{ wireguard_clients }}"
|
||||
register: client_private_keys
|
||||
|
||||
- name: Lese Client-Public-Keys
|
||||
slurp:
|
||||
src: /etc/wireguard/clients/{{ item.name }}-public.key
|
||||
loop: "{{ wireguard_clients }}"
|
||||
register: client_public_keys
|
||||
|
||||
- name: Lese Pre-shared Keys
|
||||
slurp:
|
||||
src: /etc/wireguard/clients/{{ item.name }}-psk.key
|
||||
loop: "{{ wireguard_clients }}"
|
||||
register: client_psk_keys
|
||||
when: wireguard_pre_shared_key | default(false)
|
||||
|
||||
# Erstelle Key-Dictionaries
|
||||
- name: Erstelle Client-Key-Dictionary
|
||||
set_fact:
|
||||
wg_client_private_keys: "{{ dict(wireguard_clients | map(attribute='name') | list | zip(client_private_keys.results | map(attribute='content') | map('b64decode') | map('trim') | list)) }}"
|
||||
wg_client_public_keys: "{{ dict(wireguard_clients | map(attribute='name') | list | zip(client_public_keys.results | map(attribute='content') | map('b64decode') | map('trim') | list)) }}"
|
||||
|
||||
- name: Erstelle Pre-shared Key Dictionary
|
||||
set_fact:
|
||||
wg_client_psk_keys: "{{ dict(wireguard_clients | map(attribute='name') | list | zip(client_psk_keys.results | map(attribute='content') | map('b64decode') | map('trim') | list)) }}"
|
||||
when:
|
||||
- wireguard_pre_shared_key | default(false)
|
||||
- client_psk_keys is defined
|
||||
|
||||
# Server-Konfiguration erstellen
|
||||
- name: Erstelle WireGuard-Server-Konfiguration
|
||||
template:
|
||||
src: wg0.conf.j2
|
||||
dest: /etc/wireguard/wg0.conf
|
||||
mode: '0600'
|
||||
owner: root
|
||||
group: root
|
||||
notify: restart wireguard
|
||||
|
||||
# Client-Konfigurationen erstellen
|
||||
- name: Erstelle Client-Konfigurationen
|
||||
template:
|
||||
src: client.conf.j2
|
||||
dest: /etc/wireguard/clients/{{ item.name }}.conf
|
||||
mode: '0600'
|
||||
owner: root
|
||||
group: root
|
||||
loop: "{{ wireguard_clients }}"
|
||||
|
||||
# WireGuard-Service konfigurieren
|
||||
- name: Aktiviere WireGuard-Service
|
||||
systemd:
|
||||
name: wg-quick@wg0
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
# Installiere WireGuard
|
||||
- name: Installiere WireGuard
|
||||
apt:
|
||||
name: wireguard
|
||||
state: present
|
||||
update_cache: yes
|
||||
when: ansible_connection != "local"
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
- name: Prüfe erforderliche Variablen
|
||||
assert:
|
||||
that:
|
||||
- wireguard_clients is defined
|
||||
- wireguard_server_ip is defined
|
||||
- wireguard_network is defined
|
||||
fail_msg: "WireGuard-Konfiguration unvollständig: erforderliche Variablen nicht definiert"
|
||||
success_msg: "WireGuard-Variablen korrekt definiert"
|
||||
tags: [always]
|
||||
|
||||
- name: Installiere WireGuard
|
||||
import_tasks: install.yml
|
||||
when: ansible_connection != "local"
|
||||
|
||||
- name: Konfiguriere WireGuard
|
||||
import_tasks: configure.yml
|
||||
|
||||
- name: Konfiguriere Netzwerk für WireGuard
|
||||
import_tasks: network.yml
|
||||
when: ansible_connection != "local"
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
# Netzwerk-Konfiguration für WireGuard (ohne Firewall)
|
||||
- name: Aktiviere IP-Forwarding
|
||||
sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: true
|
||||
reload: true
|
||||
|
||||
- name: Installiere iptables-persistent für dauerhafte Regeln
|
||||
apt:
|
||||
name: iptables-persistent
|
||||
state: present
|
||||
|
||||
- name: Prüfe ob WireGuard-NAT-Regel bereits existiert
|
||||
shell: iptables -t nat -C POSTROUTING -o {{ wireguard_exit_interface }} -s {{ wireguard_network }} -j MASQUERADE
|
||||
register: nat_rule_exists
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
|
||||
- name: Setze NAT-Regel für WireGuard-Traffic
|
||||
iptables:
|
||||
table: nat
|
||||
chain: POSTROUTING
|
||||
out_interface: "{{ wireguard_exit_interface }}"
|
||||
source: "{{ wireguard_network }}"
|
||||
jump: MASQUERADE
|
||||
comment: "WireGuard VPN NAT"
|
||||
when: nat_rule_exists.rc != 0
|
||||
|
||||
- name: Prüfe ob FORWARD-Regel für WireGuard eingehend existiert
|
||||
shell: iptables -C FORWARD -i {{ wireguard_interface }} -j ACCEPT
|
||||
register: forward_in_exists
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
|
||||
- name: Erlaube FORWARD von WireGuard-Interface
|
||||
iptables:
|
||||
chain: FORWARD
|
||||
in_interface: "{{ wireguard_interface }}"
|
||||
jump: ACCEPT
|
||||
comment: "Allow WireGuard traffic in"
|
||||
when: forward_in_exists.rc != 0
|
||||
|
||||
- name: Prüfe ob FORWARD-Regel für WireGuard ausgehend existiert
|
||||
shell: iptables -C FORWARD -o {{ wireguard_interface }} -j ACCEPT
|
||||
register: forward_out_exists
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
|
||||
- name: Erlaube FORWARD zu WireGuard-Interface
|
||||
iptables:
|
||||
chain: FORWARD
|
||||
out_interface: "{{ wireguard_interface }}"
|
||||
jump: ACCEPT
|
||||
comment: "Allow WireGuard traffic out"
|
||||
when: forward_out_exists.rc != 0
|
||||
|
||||
- name: Speichere iptables-Regeln permanent
|
||||
shell: |
|
||||
iptables-save > /etc/iptables/rules.v4
|
||||
ip6tables-save > /etc/iptables/rules.v6
|
||||
|
||||
- name: Zeige WireGuard-relevante iptables-Regeln
|
||||
shell: |
|
||||
echo "=== NAT Rules ==="
|
||||
iptables -t nat -L POSTROUTING -n | grep {{ wireguard_network.split('/')[0] }}
|
||||
echo "=== FORWARD Rules ==="
|
||||
iptables -L FORWARD -n | grep {{ wireguard_interface }}
|
||||
register: wg_rules
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Debug WireGuard-Netzwerk-Konfiguration
|
||||
debug:
|
||||
msg: |
|
||||
✅ WireGuard-Netzwerk konfiguriert
|
||||
✅ IP-Forwarding aktiviert
|
||||
✅ NAT für VPN-Clients aktiviert
|
||||
✅ Server bleibt öffentlich erreichbar
|
||||
✅ VPN-Clients können ins Internet
|
||||
|
||||
{{ wg_rules.stdout }}
|
||||
@@ -0,0 +1,20 @@
|
||||
[Interface]
|
||||
PrivateKey = {{ wg_client_private_keys[item.name] }}
|
||||
Address = {{ item.address }}/32
|
||||
{% if wireguard_dns_servers is defined %}
|
||||
DNS = {{ wireguard_dns_servers | join(', ') }}
|
||||
{% endif %}
|
||||
{% if wireguard_mtu is defined %}
|
||||
MTU = {{ wireguard_mtu }}
|
||||
{% endif %}
|
||||
|
||||
[Peer]
|
||||
PublicKey = {{ wg_server_public_key }}
|
||||
Endpoint = {{ wireguard_server_ip }}:{{ wireguard_port }}
|
||||
AllowedIPs = {{ wireguard_network }}
|
||||
{% if wireguard_keepalive is defined %}
|
||||
PersistentKeepalive = {{ wireguard_keepalive }}
|
||||
{% endif %}
|
||||
{% if wireguard_pre_shared_key | default(false) and wg_client_psk_keys is defined %}
|
||||
PresharedKey = {{ wg_client_psk_keys[item.name] }}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,28 @@
|
||||
[Interface]
|
||||
Address = {{ wireguard_address }}
|
||||
PrivateKey = {{ wg_server_private_key }}
|
||||
ListenPort = {{ wireguard_port }}
|
||||
{% if wireguard_mtu is defined %}
|
||||
MTU = {{ wireguard_mtu }}
|
||||
{% endif %}
|
||||
|
||||
# Einfache NAT-Regeln für VPN-Traffic
|
||||
PostUp = iptables -t nat -I POSTROUTING -o {{ wireguard_exit_interface }} -s {{ wireguard_network }} -j MASQUERADE
|
||||
PostUp = iptables -I FORWARD -i {{ wireguard_interface }} -j ACCEPT
|
||||
PostUp = iptables -I FORWARD -o {{ wireguard_interface }} -j ACCEPT
|
||||
|
||||
PostDown = iptables -t nat -D POSTROUTING -o {{ wireguard_exit_interface }} -s {{ wireguard_network }} -j MASQUERADE
|
||||
PostDown = iptables -D FORWARD -i {{ wireguard_interface }} -j ACCEPT
|
||||
PostDown = iptables -D FORWARD -o {{ wireguard_interface }} -j ACCEPT
|
||||
|
||||
# Client-Peers
|
||||
{% for client in wireguard_clients %}
|
||||
[Peer]
|
||||
# {{ client.name }}
|
||||
PublicKey = {{ wg_client_public_keys[client.name] }}
|
||||
AllowedIPs = {{ client.address }}/32
|
||||
{% if wireguard_pre_shared_key | default(false) and wg_client_psk_keys is defined %}
|
||||
PresharedKey = {{ wg_client_psk_keys[client.name] }}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
41
.deployment-backup/ansible/wireguard-server/show-clients.yml
Normal file
41
.deployment-backup/ansible/wireguard-server/show-clients.yml
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
- name: Show WireGuard Clients
|
||||
hosts: vpn
|
||||
become: true
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Zeige vorhandene Clients
|
||||
find:
|
||||
paths: /etc/wireguard/clients
|
||||
patterns: "*.conf"
|
||||
register: existing_clients
|
||||
|
||||
- name: Liste vorhandene Clients
|
||||
debug:
|
||||
msg: "Vorhandene Clients: {{ existing_clients.files | map(attribute='path') | map('basename') | map('regex_replace', '\\.conf$', '') | list }}"
|
||||
|
||||
- name: Zeige Client-IPs
|
||||
shell: |
|
||||
for conf in /etc/wireguard/clients/*.conf; do
|
||||
if [ -f "$conf" ]; then
|
||||
echo "$(basename "$conf" .conf): $(grep '^Address' "$conf" | cut -d' ' -f3)"
|
||||
fi
|
||||
done
|
||||
register: client_ips
|
||||
changed_when: false
|
||||
|
||||
- name: Client-IP-Übersicht
|
||||
debug:
|
||||
var: client_ips.stdout_lines
|
||||
|
||||
- name: Zeige WireGuard-Server-Status
|
||||
command: wg show
|
||||
register: wg_status
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Server-Status
|
||||
debug:
|
||||
var: wg_status.stdout_lines
|
||||
when: wg_status.rc == 0
|
||||
78
.deployment-backup/ansible/wireguard-server/site.yml
Normal file
78
.deployment-backup/ansible/wireguard-server/site.yml
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
- name: WireGuard VPN Server Setup (ohne Firewall)
|
||||
hosts: vpn
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
pre_tasks:
|
||||
- name: Update package cache
|
||||
apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: Zeige Setup-Information
|
||||
debug:
|
||||
msg: |
|
||||
🌐 WireGuard-Installation OHNE Firewall
|
||||
✅ Server bleibt öffentlich erreichbar
|
||||
✅ WireGuard als zusätzlicher VPN-Zugang
|
||||
✅ Keine SSH-Beschränkungen
|
||||
|
||||
roles:
|
||||
- role: wireguard
|
||||
|
||||
post_tasks:
|
||||
- name: Prüfe ob qrencode installiert ist
|
||||
command: which qrencode
|
||||
register: qrencode_check
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
|
||||
- name: Installiere qrencode für QR-Codes
|
||||
apt:
|
||||
name: qrencode
|
||||
state: present
|
||||
when: qrencode_check.rc != 0
|
||||
|
||||
- name: Erstelle QR-Codes für mobile Clients
|
||||
shell: qrencode -t ansiutf8 < /etc/wireguard/clients/{{ item.name }}.conf
|
||||
loop: "{{ wireguard_clients }}"
|
||||
register: qr_codes
|
||||
when: item.name is search('phone|mobile')
|
||||
ignore_errors: true
|
||||
|
||||
- name: Zeige QR-Codes
|
||||
debug:
|
||||
msg: |
|
||||
QR-Code für {{ item.item.name }}:
|
||||
{{ item.stdout }}
|
||||
loop: "{{ qr_codes.results }}"
|
||||
when: item.stdout is defined and not item.failed
|
||||
|
||||
- name: Zeige WireGuard-Status
|
||||
command: wg show
|
||||
register: wg_status
|
||||
changed_when: false
|
||||
|
||||
- name: WireGuard-Status anzeigen
|
||||
debug:
|
||||
var: wg_status.stdout_lines
|
||||
|
||||
- name: Zeige finale Setup-Information
|
||||
debug:
|
||||
msg: |
|
||||
🎉 WireGuard erfolgreich installiert!
|
||||
|
||||
Server-Zugang:
|
||||
📡 Öffentlich: ssh root@{{ wireguard_server_ip }}
|
||||
🔒 Via VPN: ssh root@{{ wireguard_address.split('/')[0] }} (nach VPN-Verbindung)
|
||||
|
||||
Client-Konfigurationen:
|
||||
📂 Server-Pfad: /etc/wireguard/clients/
|
||||
💾 Download: make download-configs
|
||||
📱 QR-Codes: make qr-codes
|
||||
|
||||
Nützliche Befehle:
|
||||
🔍 Status: make status
|
||||
📋 Logs: make logs
|
||||
➕ Client hinzufügen: make add-client
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
- name: Create WireGuard Client Configurations
|
||||
hosts: vpn
|
||||
become: true
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure client directory exists
|
||||
file:
|
||||
path: /etc/wireguard/clients
|
||||
state: directory
|
||||
mode: '0700'
|
||||
|
||||
- name: Load existing server keys
|
||||
slurp:
|
||||
src: /etc/wireguard/server-public.key
|
||||
register: server_pub_key
|
||||
|
||||
- name: Set server public key fact
|
||||
set_fact:
|
||||
wg_server_public_key: "{{ server_pub_key.content | b64decode | trim }}"
|
||||
|
||||
- name: Generate client configurations
|
||||
include_role:
|
||||
name: wireguard
|
||||
tasks_from: configure
|
||||
vars:
|
||||
wg_server_public_key: "{{ server_pub_key.content | b64decode | trim }}"
|
||||
|
||||
- name: List created client configurations
|
||||
find:
|
||||
paths: /etc/wireguard/clients
|
||||
patterns: "*.conf"
|
||||
register: client_configs
|
||||
|
||||
- name: Show created configurations
|
||||
debug:
|
||||
msg: "Created client configurations: {{ client_configs.files | map(attribute='path') | map('basename') | list }}"
|
||||
|
||||
- name: Generate QR codes for mobile clients
|
||||
shell: qrencode -t ansiutf8 < /etc/wireguard/clients/{{ item.name }}.conf
|
||||
loop: "{{ wireguard_clients }}"
|
||||
register: qr_results
|
||||
when: item.name is search('phone|mobile')
|
||||
ignore_errors: true
|
||||
|
||||
- name: Display QR codes
|
||||
debug:
|
||||
msg: |
|
||||
QR Code for {{ item.item.name }}:
|
||||
{{ item.stdout }}
|
||||
loop: "{{ qr_results.results }}"
|
||||
when: item.stdout is defined and not item.failed
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
- name: Install WireGuard Server
|
||||
hosts: vpn
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
pre_tasks:
|
||||
- name: Update package cache
|
||||
apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
roles:
|
||||
- role: wireguard
|
||||
tags: [install, configure]
|
||||
|
||||
post_tasks:
|
||||
- name: Show WireGuard status
|
||||
command: wg show
|
||||
register: wg_status
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Display WireGuard status
|
||||
debug:
|
||||
var: wg_status.stdout_lines
|
||||
when: wg_status.stdout is defined
|
||||
11
.deployment-backup/bin/check-env
Normal file
11
.deployment-backup/bin/check-env
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
if [ ! -f .env ]; then
|
||||
echo "❌ .env fehlt!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q "APP_PORT=" .env; then
|
||||
echo "⚠️ APP_PORT nicht gesetzt"
|
||||
fi
|
||||
|
||||
# TODO In make up oder make deploy einbauen.
|
||||
84
.deployment-backup/bin/deploy
Executable file
84
.deployment-backup/bin/deploy
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh -l
|
||||
# Führt das Ansible-Deploy-Playbook aus
|
||||
#!/bin/bash
|
||||
|
||||
# Deployment-Skript für verschiedene Umgebungen
|
||||
|
||||
# Konfiguration
|
||||
ANSIBLE_INVENTORY="ansible/inventory/hosts.ini"
|
||||
PLAYBOOK_DIR="ansible/playbooks/deploy"
|
||||
|
||||
# Farbdefinitionen
|
||||
GREEN="\033[0;32m"
|
||||
YELLOW="\033[1;33m"
|
||||
RED="\033[0;31m"
|
||||
NC="\033[0m" # No Color
|
||||
|
||||
# Funktion zum Anzeigen von Nachrichten
|
||||
echo_msg() {
|
||||
echo -e "${GREEN}[DEPLOY]${NC} $1"
|
||||
}
|
||||
|
||||
echo_warn() {
|
||||
echo -e "${YELLOW}[WARNUNG]${NC} $1"
|
||||
}
|
||||
|
||||
echo_error() {
|
||||
echo -e "${RED}[FEHLER]${NC} $1"
|
||||
}
|
||||
|
||||
# Parameter auswerten
|
||||
ENVIRONMENT="$1"
|
||||
TAGS="$2"
|
||||
|
||||
if [ -z "$ENVIRONMENT" ]; then
|
||||
echo_warn "Keine Umgebung angegeben. Verfügbare Optionen:"
|
||||
echo " ./bin/deploy dev - Lokale Entwicklungsumgebung"
|
||||
echo " ./bin/deploy staging - Staging-Umgebung"
|
||||
echo " ./bin/deploy prod - Produktionsumgebung"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Tags zusammenbauen (falls angegeben)
|
||||
TAGS_OPTION=""
|
||||
if [ -n "$TAGS" ]; then
|
||||
TAGS_OPTION="--tags=$TAGS"
|
||||
echo_msg "Verwende Tags: $TAGS"
|
||||
fi
|
||||
|
||||
# Entsprechendes Playbook ausführen
|
||||
case "$ENVIRONMENT" in
|
||||
dev|development|local)
|
||||
echo_msg "Starte Deployment für lokale Entwicklungsumgebung..."
|
||||
ansible-playbook -i "$ANSIBLE_INVENTORY" "$PLAYBOOK_DIR/dev.yml" --ask-become-pass $TAGS_OPTION
|
||||
;;
|
||||
staging|stage)
|
||||
echo_msg "Starte Deployment für Staging-Umgebung..."
|
||||
ansible-playbook -i "$ANSIBLE_INVENTORY" "$PLAYBOOK_DIR/staging.yml" $TAGS_OPTION
|
||||
;;
|
||||
prod|production)
|
||||
echo_msg "Starte Deployment für Produktionsumgebung..."
|
||||
read -p "Sind Sie sicher, dass Sie in der Produktionsumgebung deployen möchten? (j/N) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Jj]$ ]]; then
|
||||
ansible-playbook -i "$ANSIBLE_INVENTORY" "$PLAYBOOK_DIR/production.yml" $TAGS_OPTION
|
||||
else
|
||||
echo_warn "Deployment in Produktionsumgebung abgebrochen."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo_error "Unbekannte Umgebung: $ENVIRONMENT"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Deployment-Status prüfen
|
||||
if [ $? -eq 0 ]; then
|
||||
echo_msg "Deployment erfolgreich abgeschlossen."
|
||||
exit 0
|
||||
else
|
||||
echo_error "Deployment fehlgeschlagen! Bitte überprüfen Sie die Logs."
|
||||
exit 1
|
||||
fi
|
||||
/home/michael/.local/bin/ansible-playbook -i ansible/inventory.ini ansible/playbooks/deploy.yml
|
||||
3
.deployment-backup/bin/down
Executable file
3
.deployment-backup/bin/down
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# Stoppt alle laufenden Container
|
||||
docker compose down
|
||||
3
.deployment-backup/bin/logs
Executable file
3
.deployment-backup/bin/logs
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# Zeigt die Live-Logs aller Container
|
||||
docker compose logs -f
|
||||
3
.deployment-backup/bin/restart
Executable file
3
.deployment-backup/bin/restart
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# Stoppt und startet alle Container neu
|
||||
docker compose down && docker compose up -d
|
||||
86
.deployment-backup/bin/setup
Executable file
86
.deployment-backup/bin/setup
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# Server-Setup-Skript für verschiedene Umgebungen
|
||||
#!/bin/bash
|
||||
|
||||
# Server-Setup-Skript für verschiedene Umgebungen
|
||||
|
||||
# Konfiguration
|
||||
ANSIBLE_INVENTORY="ansible/inventory/hosts.ini"
|
||||
SETUP_PLAYBOOK="ansible/setup.yml"
|
||||
|
||||
# Farbdefinitionen
|
||||
GREEN="\033[0;32m"
|
||||
YELLOW="\033[1;33m"
|
||||
RED="\033[0;31m"
|
||||
NC="\033[0m" # No Color
|
||||
|
||||
# Funktion zum Anzeigen von Nachrichten
|
||||
echo_msg() {
|
||||
echo -e "${GREEN}[SETUP]${NC} $1"
|
||||
}
|
||||
|
||||
echo_warn() {
|
||||
echo -e "${YELLOW}[WARNUNG]${NC} $1"
|
||||
}
|
||||
|
||||
echo_error() {
|
||||
echo -e "${RED}[FEHLER]${NC} $1"
|
||||
}
|
||||
|
||||
# Parameter auswerten
|
||||
ENVIRONMENT="$1"
|
||||
TAGS="$2"
|
||||
|
||||
if [ -z "$ENVIRONMENT" ]; then
|
||||
echo_warn "Keine Umgebung angegeben. Verfügbare Optionen:"
|
||||
echo " ./bin/setup staging - Staging-Server einrichten"
|
||||
echo " ./bin/setup prod - Produktionsserver einrichten"
|
||||
echo " ./bin/setup all - Alle Server einrichten"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Tags zusammenbauen (falls angegeben)
|
||||
TAGS_OPTION=""
|
||||
if [ -n "$TAGS" ]; then
|
||||
TAGS_OPTION="--tags=$TAGS"
|
||||
echo_msg "Verwende Tags: $TAGS"
|
||||
fi
|
||||
|
||||
# Limit für die Server-Auswahl
|
||||
LIMIT_OPTION=""
|
||||
case "$ENVIRONMENT" in
|
||||
staging|stage)
|
||||
LIMIT_OPTION="--limit=staging"
|
||||
echo_msg "Richte Staging-Server ein..."
|
||||
;;
|
||||
prod|production)
|
||||
LIMIT_OPTION="--limit=production"
|
||||
echo_msg "Richte Produktionsserver ein..."
|
||||
read -p "Sind Sie sicher, dass Sie den Produktionsserver einrichten möchten? (j/N) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Jj]$ ]]; then
|
||||
echo_warn "Einrichtung des Produktionsservers abgebrochen."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
all)
|
||||
echo_msg "Richte alle Server ein..."
|
||||
;;
|
||||
*)
|
||||
echo_error "Unbekannte Umgebung: $ENVIRONMENT"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Setup-Playbook ausführen
|
||||
echo_msg "Führe Ansible-Playbook aus..."
|
||||
ansible-playbook -i "$ANSIBLE_INVENTORY" "$SETUP_PLAYBOOK" $LIMIT_OPTION $TAGS_OPTION
|
||||
|
||||
# Setup-Status prüfen
|
||||
if [ $? -eq 0 ]; then
|
||||
echo_msg "Server-Setup erfolgreich abgeschlossen."
|
||||
exit 0
|
||||
else
|
||||
echo_error "Server-Setup fehlgeschlagen! Bitte überprüfen Sie die Logs."
|
||||
exit 1
|
||||
fi
|
||||
3
.deployment-backup/bin/test
Executable file
3
.deployment-backup/bin/test
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# Platzhalter für Tests – kann später durch phpunit, etc. ersetzt werden
|
||||
docker compose exec php ./vendor/bin/pest # --coverage
|
||||
3
.deployment-backup/bin/up
Executable file
3
.deployment-backup/bin/up
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# Startet Docker-Container im Hintergrund
|
||||
docker compose up -d
|
||||
23
.deployment-backup/ssl/fullchain.pem
Normal file
23
.deployment-backup/ssl/fullchain.pem
Normal file
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID0DCCArigAwIBAgIUVaO9lO+t04+NxPC3dcZlv8Wv7IAwDQYJKoZIhvcNAQEL
|
||||
BQAwZDELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0GA1UEBwwGQmVy
|
||||
bGluMRQwEgYDVQQKDAtEZXZlbG9wbWVudDEdMBsGA1UEAwwUTG9jYWwgRGV2ZWxv
|
||||
cG1lbnQgQ0EwHhcNMjUwNTE5MDc1ODUyWhcNMjYxMDAxMDc1ODUyWjBZMQswCQYD
|
||||
VQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xFDASBgNV
|
||||
BAoMC0RldmVsb3BtZW50MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQDyYOLSxgoCcWtoJXr5aPjy7cygmKO8/cudNEF0
|
||||
CqoXz13JTIFK2U7dVSGdaqB30UK5B6XRTlMuQyFcAPESRw8oBzw8Kd/4rix5G4Hr
|
||||
KMDAuK4F0gXck+J8DIS+BbrCcLYqpxXJ5Z6vA9ps+VH1a8JeZzfrfkoLC6u2tlej
|
||||
3igiA3kT0/dFaygBee/2acero+UrdjJNqx/f5uRM5Yk3/w+W9qfUyjnLMxp9JS8M
|
||||
ZpuPy/wSD+Pjff/kRB4YbHLmvcS9tO+4CpBq9k6ZU8behpWVsFSEdUmElw6dsGHP
|
||||
5BqzVAYdHE7nlR5lwkGHAepYlZb3dBlsOIrQ/DtENdHueghRAgMBAAGjgYQwgYEw
|
||||
HwYDVR0jBBgwFoAUcb+Q3WUIoJZYNBjbLOLv5oA6VTgwCQYDVR0TBAIwADALBgNV
|
||||
HQ8EBAMCBPAwJwYDVR0RBCAwHoIJbG9jYWxob3N0ggsqLmxvY2FsaG9zdIcEfwAA
|
||||
ATAdBgNVHQ4EFgQUHecxlTdTEh96ptkLH1ear/VI9xUwDQYJKoZIhvcNAQELBQAD
|
||||
ggEBAIahCY5yXfDxqoVV5y+LUhIpB8mZx+tJDDBZrSmkIM8XdmIQMylZzFmeluL4
|
||||
UmfJ7M+/niq+EYKiqJM5sTKpjAtTPuEEeaoLQZJLmu50jA6OSW27uRjzw0YDsQQy
|
||||
upzmHpoDoLgIp5u/+R/0khzj/Ivlifm+ZcG6MocxlntKkGERMIjbu2GuU5N50qpb
|
||||
W4oj7vzPLZjrTnMloHeChYBC0BxKb3IfkzN/LHYfsjenv/Ch7FtFVhfZd/X16K0v
|
||||
nh250reNbXgWHqtKb0BUwvulztwHwhWTTmmA8rei6fvbP8QNwzCxyAUz3utelKbF
|
||||
R7zrx0ljVHPxLSlbYbmm2c9OJ+I=
|
||||
-----END CERTIFICATE-----
|
||||
17
.deployment-backup/ssl/localhost.csr
Normal file
17
.deployment-backup/ssl/localhost.csr
Normal file
@@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICnjCCAYYCAQAwWTELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0G
|
||||
A1UEBwwGQmVybGluMRQwEgYDVQQKDAtEZXZlbG9wbWVudDESMBAGA1UEAwwJbG9j
|
||||
YWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8mDi0sYKAnFr
|
||||
aCV6+Wj48u3MoJijvP3LnTRBdAqqF89dyUyBStlO3VUhnWqgd9FCuQel0U5TLkMh
|
||||
XADxEkcPKAc8PCnf+K4seRuB6yjAwLiuBdIF3JPifAyEvgW6wnC2KqcVyeWerwPa
|
||||
bPlR9WvCXmc3635KCwurtrZXo94oIgN5E9P3RWsoAXnv9mnHq6PlK3YyTasf3+bk
|
||||
TOWJN/8Plvan1Mo5yzMafSUvDGabj8v8Eg/j433/5EQeGGxy5r3EvbTvuAqQavZO
|
||||
mVPG3oaVlbBUhHVJhJcOnbBhz+Qas1QGHRxO55UeZcJBhwHqWJWW93QZbDiK0Pw7
|
||||
RDXR7noIUQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAFnttGmYdpxjLxBXSveC
|
||||
21T8W74LQQeGz+yqE1KduOOJBS1eXYe4TVOduRYaQ17t7PZCvzFrYed1f+n7b/Bi
|
||||
5+5Th06+Rbac9K0bfmSonwbQ+ZXeC8pmbHtxhto5zXcEiujxe9/nkkXnraBA4uLs
|
||||
uhJALYjc/DG6jV04SW0XhpWmdyvW/aXqzjhIgVihxPtxf6/7ezEyNWYYqNsEpe5+
|
||||
sfE/mmY8UFhWvb25QQgR2YcFfbDyz3bErk3ZrqRi2TeK5EO5BGy7WFD6kLwKR/Fy
|
||||
CyRX7mvzbEN/CLlOxV1+TqvuKB2kGauOseK5HES6WK369nTB9TpFpTUth9m7IXId
|
||||
hyw=
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
9
.deployment-backup/ssl/localhost.ext
Normal file
9
.deployment-backup/ssl/localhost.ext
Normal file
@@ -0,0 +1,9 @@
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = localhost
|
||||
DNS.2 = *.localhost
|
||||
IP.1 = 127.0.0.1
|
||||
28
.deployment-backup/ssl/privkey.pem
Normal file
28
.deployment-backup/ssl/privkey.pem
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDyYOLSxgoCcWto
|
||||
JXr5aPjy7cygmKO8/cudNEF0CqoXz13JTIFK2U7dVSGdaqB30UK5B6XRTlMuQyFc
|
||||
APESRw8oBzw8Kd/4rix5G4HrKMDAuK4F0gXck+J8DIS+BbrCcLYqpxXJ5Z6vA9ps
|
||||
+VH1a8JeZzfrfkoLC6u2tlej3igiA3kT0/dFaygBee/2acero+UrdjJNqx/f5uRM
|
||||
5Yk3/w+W9qfUyjnLMxp9JS8MZpuPy/wSD+Pjff/kRB4YbHLmvcS9tO+4CpBq9k6Z
|
||||
U8behpWVsFSEdUmElw6dsGHP5BqzVAYdHE7nlR5lwkGHAepYlZb3dBlsOIrQ/DtE
|
||||
NdHueghRAgMBAAECggEABGn1OtUHDoMf4MFCesdm6wnKNsA9hpypVtJ9Bj1xulNm
|
||||
cVrp9ZnM9C5HmX8X1HjDIMfHL59VV9UagYXlnfwSlkY2n5/xrjIx+S5iCefCW1wd
|
||||
n1mN2GXjy2zRBR1z+J75IqBBHwMwy1OBfeesLrvKCfeySAZIV/NGutyvGRrhCJir
|
||||
erbQBqp0bvgd1rSxCIUoDg+qGMtycQUyHpYiX66byuiVJ3VmrxIX8NEqEwqXek8B
|
||||
/QS1qCw54wTU72XURJ9rDZ3GN4kxc71mXVBqx0ox4SCaBuLvgwAmrVffDDXgMfG9
|
||||
XKHyWyUR+mDTAT20pKjtKuWGhLTjO+tx7khUOd6OwQKBgQD85uy2j5zG3OmG0cDb
|
||||
F4fpnEHdO203/Tm0XBPbaVJD8yTJ2m3aRzrl9FQFuThRkFu1/mOi2uYTQ0Z4teTF
|
||||
cl/ns7pmYFNud0cu18pN4Vn0g/hQPNBP56xi59n3KAvUneNImwKwZUTdY296rtYR
|
||||
bv5T1RO49oG/+pqp+o3ArKE4kQKBgQD1WPXgZns+ijZjoZJ65LYVgwLo99THCK4v
|
||||
YlZcCagz3EKAWEXPrFfVYznVWD1SfMfRxu3d04RDN0x5rj668CaTCK8ZlIuK8hNo
|
||||
HxHTLVgQjY5IDhz237h0CkSsseFP2cv/XUrBWZaB3ILbx6HObAN8tipAfpB8WGev
|
||||
nght4NGzwQKBgQCNOJYuS3uMQIfW1QIQVc97T9ono6uVfD3gzRn5h5J8hyWf4e09
|
||||
2lC1X/4bRBaC1U2hDvCsW/fmAcc0WL3q07diNyZ7TIbKRKjnK3C4lIIa3CapB4x7
|
||||
Ui8c+8LnFOGmVJQ6UvTpc2NFDOWPaFn5WjWCspVUz7IcdeAv0s2dLcjJQQKBgQDx
|
||||
3LbWdnB8YIfpg7gBCkItxq8xtk69vuLnt0tnA+Ya6cFtAJghd8ZGh8DVfl1FWdkq
|
||||
Ba8sBH3YPUVYltskMeX1AJSM5REC8k0LUcWipoqwFrvycGdBP554Vj8I93oj25Ls
|
||||
tK0jGgvzDMy7mHr8ISL26CWS2rHYwtXEHEg2+XAAgQKBgQDENx0zzEyaMTshwbQT
|
||||
uHYzDPAbOL1ZZ04kyYKFuZojywJV+6zzFwiiFPCwNt1/PwZuBKDAq4atq5EsHhvy
|
||||
DWMY6+57A2ddQj3HuCYIS834qo3yYlCQQlSIBC1cgdj7XkJL4oO67UFDnS/YCD17
|
||||
7ZJMAczixbk9tdfI0MyMz8WtNA==
|
||||
-----END PRIVATE KEY-----
|
||||
28
.deployment-backup/ssl/rootCA.key
Normal file
28
.deployment-backup/ssl/rootCA.key
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5VU1tvNpX6y4H
|
||||
+gdmrBPZMMEflp47q96y1UVOBw5IEuRN448iJ0AUvDARA/7ri3QCMIupW/oeDcRf
|
||||
2RNWfK189FtEVp8NIIMTh/DxDiKinPMty2Wil+WCjE90B3FvTQ4dhvTmkYoBeMPw
|
||||
184nGpuVFVOyZ1RQUsigNmdAbVRxtVvFR5hwKRHvU4vokXjLR1nhsDXStclw7gdM
|
||||
fCsXdl52eyXmEM4271hNHb1aGi9Ch4OeMD9nIJH7x7gW8kRunIE3SHXHmnLgk80K
|
||||
bzN7FrUdBy1XSlxRXv4seGiZLUfiKP0/OEQR+u7+aQrH0489o0+8+w8MW6wZxsFW
|
||||
deKsUB7xAgMBAAECggEAAlCFMqbvwUvpzktySCHYxHGnjcflTWiOc88Ln3zMJ2db
|
||||
VCOGBCFiRggEynzxaXAQyIi3lnY/DnJHUYJItlUrsP0XvofIPXiabnYNiCMlg1X2
|
||||
CFcV5jo4UWwEFNZqysmBxj8LLq3NX9/qBDIGbEZYqvus04mXES2RfW+51HaxEz5G
|
||||
Na8L8Qm9kKLmrRRb+JlX3DcJeIJ9rAJvBI3Nh4S7Dq9ssRzfFG/33nUIoPm+0z41
|
||||
gPVHHbbWVwxhaPg56Zbe5wvwfJWKzewNYYQHFTHZf+FB0b/0p8mqGkL2Grgt5+xE
|
||||
ahwQE532nrkhQv1lB9SdYfcyfUZuiWSFIJRjeT7vwQKBgQD6e8rLpntft4oVtrX/
|
||||
9Q7b5I21tE3Yg0P3NZpY1sjPg2ojjT7czv5TXnJAF0taX8ZuHw8lzuohUxb+Cyye
|
||||
ny5aBF8uWr4IFxJpLNPq1zTGjUTTHy2zwsaSUOW/JRbQHm8pvsdhSldYlC0ZJJT+
|
||||
hSo9nGlJqBdJ20mvRqXMvdmk4QKBgQC9ajKKN3k/JvjyNNFUb8pGX5bgO5xx5jCN
|
||||
E4K44cIWTn76VU68QOt2eEkrmHi/irvzO9Gkk7siaF7XuqPxbmEBeByhVHsf0lI8
|
||||
B5mpt0HUlLWiqlkiJ02OnOEEVrBKt8Xd92JFKLg45k4JtekNRKiZa36+lZFz0/Es
|
||||
CzG/o7WsEQKBgQCM79h0a/EhMzlb7FlNcopwyZG+unvOplU4pI17DSciM7Ql2tST
|
||||
E1jgedTZIQJCEH+q+IjiYiE0rPbT7F+nxLMk7S7M+zvPe4Pdb96xVXOZgGVIUVO6
|
||||
wI5QR3pt6aWDZoxvtaujn1u0OHODoSTAbRcOYZKQYibwZJV6LMsff3cVoQKBgENy
|
||||
0oZnVJSJYzKUXkor+KJwnYBBmebxKi7CWNVPBtb8orivsfbVQ0OPd7a/d5f1ZhIq
|
||||
Je/t70BEXCmDu6dYP9DPHZrRQ3rEYSYhKrXFnPp+7eL7t/uydSqocHQkDmi84ge1
|
||||
dNfdtSQF1pocnd1sqoDfR2XESuQs/39IiTGNsT6RAoGAMdd34RAC0o8P0beDBLtX
|
||||
SZssjwXgNhSboFju/VCjgkr+NGAa/AfhofMNkXi0RIA86OxJ7PS8+l9N55RRN719
|
||||
CMqwQB4lU3X9Q6w7D2Cjv/3TOi9vAJTo6jnRzCY1CY3QvVlIXrENIdcMLSrAgqBK
|
||||
zcl2t7EI2tQqcln5GejidPI=
|
||||
-----END PRIVATE KEY-----
|
||||
22
.deployment-backup/ssl/rootCA.pem
Normal file
22
.deployment-backup/ssl/rootCA.pem
Normal file
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDqTCCApGgAwIBAgIUSfp3igkhkKA+VOzMUBbs/OtvsIEwDQYJKoZIhvcNAQEL
|
||||
BQAwZDELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0GA1UEBwwGQmVy
|
||||
bGluMRQwEgYDVQQKDAtEZXZlbG9wbWVudDEdMBsGA1UEAwwUTG9jYWwgRGV2ZWxv
|
||||
cG1lbnQgQ0EwHhcNMjUwNTE5MDc1ODUyWhcNMjgwMzA4MDc1ODUyWjBkMQswCQYD
|
||||
VQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xFDASBgNV
|
||||
BAoMC0RldmVsb3BtZW50MR0wGwYDVQQDDBRMb2NhbCBEZXZlbG9wbWVudCBDQTCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALlVTW282lfrLgf6B2asE9kw
|
||||
wR+Wnjur3rLVRU4HDkgS5E3jjyInQBS8MBED/uuLdAIwi6lb+h4NxF/ZE1Z8rXz0
|
||||
W0RWnw0ggxOH8PEOIqKc8y3LZaKX5YKMT3QHcW9NDh2G9OaRigF4w/DXzicam5UV
|
||||
U7JnVFBSyKA2Z0BtVHG1W8VHmHApEe9Ti+iReMtHWeGwNdK1yXDuB0x8Kxd2XnZ7
|
||||
JeYQzjbvWE0dvVoaL0KHg54wP2cgkfvHuBbyRG6cgTdIdceacuCTzQpvM3sWtR0H
|
||||
LVdKXFFe/ix4aJktR+Io/T84RBH67v5pCsfTjz2jT7z7DwxbrBnGwVZ14qxQHvEC
|
||||
AwEAAaNTMFEwHQYDVR0OBBYEFHG/kN1lCKCWWDQY2yzi7+aAOlU4MB8GA1UdIwQY
|
||||
MBaAFHG/kN1lCKCWWDQY2yzi7+aAOlU4MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
|
||||
hvcNAQELBQADggEBABVU6zLORzw0hi/PxZLw6IiR4FIgQvtPNcmTysW0paTsh4HZ
|
||||
MszdQEfjT1z2qeySPJSJRUpXoxCegeydrRVDbPrN7kDzRuz+YtzgPdYiAF54K8gj
|
||||
klI9JMVBF92jJpZ12LCAMpfZA40IEwtTqnGkxnhpw1ea5T2ec8RJpVCDP0vR4EJ8
|
||||
VVN+YHxPg6H2VxZSsBKZ9f7dPB+/OfFqRue1fLzaHbKfLWmft06s7QDnjQEOIcs9
|
||||
GowfVMtlMef800D8/zJgEo+M4ugBwlGKjR/F1F8yibunV+lON+xiE8DpA+WwgnjR
|
||||
jQ0pjd+MSMjzc4itqwLoTZ7mtqcxjjxVe1dZVNs=
|
||||
-----END CERTIFICATE-----
|
||||
1
.deployment-backup/ssl/rootCA.srl
Normal file
1
.deployment-backup/ssl/rootCA.srl
Normal file
@@ -0,0 +1 @@
|
||||
55A3BD94EFADD38F8DC4F0B775C665BFC5AFEC80
|
||||
146
.deployment-backup/x_ansible/README.md
Normal file
146
.deployment-backup/x_ansible/README.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Ansible-Setup für michaelschiemer.de
|
||||
|
||||
Dieses Verzeichnis enthält die Ansible-Konfiguration für das Deployment der Website.
|
||||
|
||||
## Verzeichnisstruktur
|
||||
|
||||
```
|
||||
ansible/
|
||||
├── ansible.cfg # Ansible-Konfigurationsdatei
|
||||
├── check_yaml.sh # Skript zur Überprüfung der YAML-Syntax
|
||||
├── deploy.sh # Deployment-Skript
|
||||
├── docker/ # Docker-Konfigurationsdateien
|
||||
├── group_vars/ # Variablen für Gruppen
|
||||
├── inventory/ # Inventar-Dateien
|
||||
│ ├── hosts.ini # Hauptinventar
|
||||
│ ├── development # Entwicklungsumgebung
|
||||
│ ├── staging # Staging-Umgebung
|
||||
│ └── production # Produktionsumgebung
|
||||
├── playbooks/ # Playbooks für verschiedene Aufgaben
|
||||
├── roles/ # Rollen für verschiedene Komponenten
|
||||
├── docker-compose.yml # Standard-Docker-Compose-Datei
|
||||
├── setup.sh # Setup-Skript
|
||||
└── setup.yml # Basis-Setup-Playbook
|
||||
```
|
||||
|
||||
## Erste Schritte
|
||||
|
||||
Bevor Sie die Skripte verwenden können, müssen Sie diese ausführbar machen:
|
||||
|
||||
```bash
|
||||
chmod +x ansible/setup.sh ansible/deploy.sh ansible/check_yaml.sh
|
||||
```
|
||||
|
||||
## YAML-Syntax prüfen
|
||||
|
||||
Bevor Sie ein Deployment starten, sollten Sie die YAML-Syntax überprüfen:
|
||||
|
||||
```bash
|
||||
./ansible/check_yaml.sh
|
||||
```
|
||||
|
||||
Dieses Skript findet und korrigiert die häufigsten YAML-Syntaxprobleme.
|
||||
|
||||
## Verwendung
|
||||
|
||||
### Einfache Verwendung mit dem Setup-Skript
|
||||
|
||||
```bash
|
||||
# Server-Setup durchführen
|
||||
./ansible/setup.sh setup staging
|
||||
|
||||
# Deployment durchführen
|
||||
./ansible/setup.sh deploy staging
|
||||
```
|
||||
|
||||
### Deployment mit dem einfachen Deploy-Skript
|
||||
|
||||
```bash
|
||||
# Deployment für die Staging-Umgebung
|
||||
./ansible/deploy.sh staging
|
||||
|
||||
# Deployment für die Produktionsumgebung
|
||||
./ansible/deploy.sh production
|
||||
```
|
||||
|
||||
### Manuelle Verwendung
|
||||
|
||||
```bash
|
||||
# Wechsle ins Ansible-Verzeichnis
|
||||
cd ansible
|
||||
|
||||
# Server-Setup durchführen
|
||||
ansible-playbook -i inventory/hosts.ini setup.yml --limit staging
|
||||
|
||||
# Deployment durchführen
|
||||
ansible-playbook -i inventory/hosts.ini playbooks/deploy.yml --limit staging
|
||||
```
|
||||
|
||||
### Mit Tags
|
||||
|
||||
```bash
|
||||
# Nur bestimmte Teile ausführen
|
||||
ansible-playbook -i inventory/hosts.ini playbooks/deploy.yml --limit staging --tags="deploy,check"
|
||||
```
|
||||
|
||||
## Umgebungsvariablen
|
||||
|
||||
Die Konfiguration für die verschiedenen Umgebungen wird in den entsprechenden Dateien unter `group_vars/` definiert:
|
||||
|
||||
- `all.yml`: Variablen für alle Umgebungen
|
||||
- `common.yml`: Gemeinsame Variablen
|
||||
- `staging.yml`: Variablen für die Staging-Umgebung
|
||||
- `production.yml`: Variablen für die Produktionsumgebung
|
||||
|
||||
Folgende Hauptvariablen werden verwendet:
|
||||
|
||||
- `deploy_root`: Zielverzeichnis für das Deployment (/var/www/michaelschiemer)
|
||||
- `app_domain`: Domain für die Anwendung
|
||||
- `deploy_user`: Benutzer für das Deployment (deploy)
|
||||
|
||||
## Fehlerbehandlung
|
||||
|
||||
Wenn Sie auf Fehler stoßen, prüfen Sie folgende Punkte:
|
||||
|
||||
1. **YAML-Syntax-Fehler**:
|
||||
- Führen Sie `./ansible/check_yaml.sh` aus, um Probleme zu identifizieren
|
||||
- Stellen Sie sicher, dass jede YAML-Datei nur ein Dokument enthält (nur ein `---` am Anfang)
|
||||
- Achten Sie auf korrekte Einrückung und Leerzeichen
|
||||
|
||||
2. **Berechtigungen**:
|
||||
- Stellen Sie sicher, dass die Scripts ausführbar sind: `chmod +x ansible/*.sh`
|
||||
- Überprüfen Sie, ob der Benutzer die nötigen Berechtigungen auf dem Server hat
|
||||
|
||||
3. **Arbeitsverzeichnis**:
|
||||
- Führen Sie die Skripte vom Hauptverzeichnis des Projekts aus: `./ansible/deploy.sh`
|
||||
- Bei manueller Ausführung: Wechseln Sie ins Ansible-Verzeichnis
|
||||
|
||||
4. **SSH-Schlüssel**:
|
||||
- Prüfen Sie, ob der SSH-Schlüssel für den Zugriff auf den Server korrekt eingerichtet ist
|
||||
- Testen Sie die SSH-Verbindung manuell: `ssh deploy@94.16.110.151`
|
||||
|
||||
5. **Abhängigkeiten**:
|
||||
- Stellen Sie sicher, dass Ansible installiert ist: `ansible --version`
|
||||
- Bei Bedarf: `pip install ansible`
|
||||
|
||||
## Troubleshooting häufiger Fehler
|
||||
|
||||
### "We were unable to read either as JSON nor YAML"
|
||||
|
||||
Dieser Fehler tritt auf, wenn mehrere YAML-Dokumente in einer Datei vorhanden sind. Lösung:
|
||||
|
||||
1. Führen Sie `./ansible/check_yaml.sh` aus, um problematische Dateien zu identifizieren
|
||||
2. Entfernen Sie alle `---` außer dem ersten in jeder Datei
|
||||
3. Stellen Sie sicher, dass keine leeren Zeilen vor dem ersten `---` stehen
|
||||
|
||||
### "No hosts matched"
|
||||
|
||||
Dieser Fehler tritt auf, wenn die Host-Gruppe nicht im Inventory gefunden wurde:
|
||||
|
||||
1. Überprüfen Sie die Datei `inventory/hosts.ini`
|
||||
2. Stellen Sie sicher, dass die angegebene Gruppe existiert
|
||||
3. Überprüfen Sie die `--limit` Option und den Host-Namen
|
||||
|
||||
## Weitere Informationen
|
||||
|
||||
Diese Konfiguration verwendet Docker und Docker Compose für die Containerisierung der Anwendung. Die Deployment-Strategie basiert auf der Synchronisierung von Dateien vom Entwicklungsrechner zum Zielserver und dem Starten der Container über Docker Compose.
|
||||
34
.deployment-backup/x_ansible/ansible.cfg
Normal file
34
.deployment-backup/x_ansible/ansible.cfg
Normal file
@@ -0,0 +1,34 @@
|
||||
[defaults]
|
||||
inventory = inventory/hosts.ini
|
||||
host_key_checking = False
|
||||
remote_user = deploy
|
||||
roles_path = roles
|
||||
allow_world_readable_tmpfiles = True
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
become_method = sudo
|
||||
become_user = root
|
||||
become_ask_pass = False
|
||||
|
||||
[ssh_connection]
|
||||
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ForwardAgent=yes
|
||||
pipelining = True
|
||||
[defaults]
|
||||
inventory = inventory/hosts.ini
|
||||
host_key_checking = False
|
||||
deprecation_warnings = False
|
||||
command_warnings = False
|
||||
interpreter_python = auto_silent
|
||||
force_color = True
|
||||
|
||||
[ssh_connection]
|
||||
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no
|
||||
pipelining = True
|
||||
transfer_method = smart
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
become_method = sudo
|
||||
become_user = root
|
||||
become_ask_pass = False
|
||||
75
.deployment-backup/x_ansible/check_yaml.sh
Executable file
75
.deployment-backup/x_ansible/check_yaml.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Skript zur Überprüfung der YAML-Syntax in Ansible-Dateien
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Farbdefinitionen
|
||||
GREEN="\033[0;32m"
|
||||
YELLOW="\033[1;33m"
|
||||
RED="\033[0;31m"
|
||||
NC="\033[0m" # No Color
|
||||
|
||||
echo -e "${GREEN}=== Überprüfe YAML-Syntax in Ansible-Dateien ===${NC}\n"
|
||||
|
||||
# Fehler-Zähler
|
||||
errors=0
|
||||
|
||||
# Prüfe alle .yml-Dateien im Ansible-Verzeichnis
|
||||
find "$SCRIPT_DIR" -name "*.yml" | sort | while read -r file; do
|
||||
# Überspringe bestimmte Verzeichnisse
|
||||
if [[ "$file" == *"/templates/"* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo -e "Prüfe: ${YELLOW}$(basename "$file")${NC} (${file})"
|
||||
|
||||
# Prüfe ob die Datei leer ist
|
||||
if [ ! -s "$file" ]; then
|
||||
echo -e " ${YELLOW}Warnung: Datei ist leer${NC}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Überprüfung mit ansible-playbook syntax-check
|
||||
if grep -q "^---" "$file"; then
|
||||
ansible-playbook --syntax-check "$file" &>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e " ${RED}Fehler: Syntax-Fehler in der Datei${NC}"
|
||||
echo -e " Detaillierte Prüfung:"
|
||||
ansible-playbook --syntax-check "$file"
|
||||
errors=$((errors+1))
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# Überprüfung mit yamllint
|
||||
if command -v yamllint &>/dev/null; then
|
||||
yamllint -d relaxed "$file" &>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e " ${YELLOW}Warnung: yamllint hat Probleme gefunden${NC}"
|
||||
yamllint -d relaxed "$file"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Überprüfung auf mehrere YAML-Dokumente
|
||||
doc_count=$(grep -c "^---" "$file")
|
||||
if [ "$doc_count" -gt 1 ]; then
|
||||
echo -e " ${RED}Fehler: Mehrere YAML-Dokumente in einer Datei (${doc_count} Dokumente)${NC}"
|
||||
echo -e " Betroffene Zeilen:"
|
||||
grep -n "^---" "$file"
|
||||
errors=$((errors+1))
|
||||
fi
|
||||
|
||||
# Wenn alles ok ist
|
||||
if [ "$errors" -eq 0 ]; then
|
||||
echo -e " ${GREEN}✓ OK${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$errors" -gt 0 ]; then
|
||||
echo -e "\n${RED}Fehler gefunden! $errors Dateien haben Probleme.${NC}"
|
||||
echo -e "Bitte korrigieren Sie die YAML-Syntax-Fehler, bevor Sie fortfahren."
|
||||
exit 1
|
||||
else
|
||||
echo -e "\n${GREEN}Alle YAML-Dateien haben die Syntax-Prüfung bestanden!${NC}"
|
||||
exit 0
|
||||
fi
|
||||
10
.deployment-backup/x_ansible/client-configs/michael.conf
Normal file
10
.deployment-backup/x_ansible/client-configs/michael.conf
Normal file
@@ -0,0 +1,10 @@
|
||||
[Interface]
|
||||
PrivateKey = +DcT11ipmMwPXpzEqmCPGwy7cSmseG1YzZWk+tTtM30=
|
||||
Address = 10.8.0.2/32
|
||||
DNS = 1.1.1.1
|
||||
|
||||
[Peer]
|
||||
PublicKey = 3qFEUREx6VfqrKoGVtzHt2ojgaly7LvwxjPQPNsFyxM=
|
||||
Endpoint = 94.16.110.151:51820
|
||||
AllowedIPs = 10.8.0.0/24, 94.16.110.151/32
|
||||
PersistentKeepalive = 25
|
||||
19
.deployment-backup/x_ansible/deploy.sh
Executable file
19
.deployment-backup/x_ansible/deploy.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Einfaches Deployment-Script für michaelschiemer.de
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Standardumgebung ist staging
|
||||
ENVIRONMENT=${1:-staging}
|
||||
|
||||
echo "=== Deployment für $ENVIRONMENT-Umgebung ==="
|
||||
|
||||
# Führe Deployment aus
|
||||
cd "$SCRIPT_DIR"
|
||||
ansible-playbook -i "$SCRIPT_DIR/inventory/hosts.ini" "$SCRIPT_DIR/playbooks/deploy.yml" --limit $ENVIRONMENT -v
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "\n✅ Deployment erfolgreich abgeschlossen!"
|
||||
else
|
||||
echo "\n❌ Deployment fehlgeschlagen!"
|
||||
fi
|
||||
74
.deployment-backup/x_ansible/docker-compose.yml
Normal file
74
.deployment-backup/x_ansible/docker-compose.yml
Normal file
@@ -0,0 +1,74 @@
|
||||
version: '3.8'
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
php:
|
||||
build:
|
||||
context: ./docker/php
|
||||
dockerfile: Dockerfile-simple
|
||||
volumes:
|
||||
- ./src:/var/www/html/src:rw
|
||||
- ./public:/var/www/html/public:rw
|
||||
networks:
|
||||
- backend
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./public:/var/www/html/public:ro
|
||||
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
depends_on:
|
||||
- php
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
networks:
|
||||
- cache
|
||||
|
||||
networks:
|
||||
frontend:
|
||||
backend:
|
||||
cache:
|
||||
services:
|
||||
php:
|
||||
build:
|
||||
context: ./docker/php
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- ${DEPLOY_ROOT:-/var/www/michaelschiemer}/src:/var/www/html/src:rw
|
||||
- ${DEPLOY_ROOT:-/var/www/michaelschiemer}/public:/var/www/html/public:rw
|
||||
networks:
|
||||
- backend
|
||||
|
||||
nginx:
|
||||
build:
|
||||
context: ./docker/nginx
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ${DEPLOY_ROOT:-/var/www/michaelschiemer}/public:/var/www/html/public:ro
|
||||
- ${DEPLOY_ROOT:-/var/www/michaelschiemer}/ssl:/etc/nginx/ssl:ro
|
||||
depends_on:
|
||||
- php
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
networks:
|
||||
- cache
|
||||
|
||||
networks:
|
||||
frontend:
|
||||
backend:
|
||||
cache:
|
||||
11
.deployment-backup/x_ansible/docker/nginx/Dockerfile
Normal file
11
.deployment-backup/x_ansible/docker/nginx/Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
# Standardkonfigurationen kopieren
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
COPY default.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Erstelle Verzeichnis für SSL-Zertifikate
|
||||
RUN mkdir -p /etc/nginx/ssl
|
||||
|
||||
# Starte Nginx im Vordergrund
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
65
.deployment-backup/x_ansible/docker/nginx/default.conf
Normal file
65
.deployment-backup/x_ansible/docker/nginx/default.conf
Normal file
@@ -0,0 +1,65 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name _;
|
||||
root /var/www/html/public;
|
||||
index index.php index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
}
|
||||
|
||||
# HTTPS Server
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
root /var/www/html/public;
|
||||
index index.php index.html;
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
root /var/www/html/public;
|
||||
|
||||
index index.php index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
}
|
||||
53
.deployment-backup/x_ansible/docker/nginx/nginx.conf
Normal file
53
.deployment-backup/x_ansible/docker/nginx/nginx.conf
Normal file
@@ -0,0 +1,53 @@
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
16
.deployment-backup/x_ansible/docker/php/Dockerfile
Normal file
16
.deployment-backup/x_ansible/docker/php/Dockerfile
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM php:8.4-fpm
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git \
|
||||
unzip \
|
||||
libzip-dev \
|
||||
zip \
|
||||
&& docker-php-ext-install zip pdo pdo_mysql \
|
||||
&& docker-php-ext-install opcache \
|
||||
&& docker-php-ext-install pcntl posix shmop \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
CMD ["php-fpm"]
|
||||
15
.deployment-backup/x_ansible/docker/php/Dockerfile-simple
Normal file
15
.deployment-backup/x_ansible/docker/php/Dockerfile-simple
Normal file
@@ -0,0 +1,15 @@
|
||||
FROM php:8.1-fpm
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git \
|
||||
unzip \
|
||||
libzip-dev \
|
||||
zip \
|
||||
&& docker-php-ext-install zip pdo pdo_mysql \
|
||||
&& docker-php-ext-install opcache \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
CMD ["php-fpm"]
|
||||
91
.deployment-backup/x_ansible/group_vars/all.yml
Normal file
91
.deployment-backup/x_ansible/group_vars/all.yml
Normal file
@@ -0,0 +1,91 @@
|
||||
# Basis-Konfiguration
|
||||
app_name: michaelschiemer
|
||||
app_domain: test.michaelschiemer.de
|
||||
app_email: kontakt@michaelschiemer.de
|
||||
|
||||
# Verzeichnisse
|
||||
project_root: "{{ playbook_dir | dirname }}"
|
||||
app_root: /var/www/{{ app_name }}
|
||||
app_public: "{{ app_root }}/public"
|
||||
|
||||
# Docker
|
||||
docker_version: "20.10"
|
||||
docker_compose_version: "2.24.5"
|
||||
|
||||
# Benutzer
|
||||
deploy_user: deploy
|
||||
|
||||
# Let's Encrypt
|
||||
letsencrypt_enabled: true
|
||||
letsencrypt_certbot_method: webroot # oder standalone oder nginx
|
||||
|
||||
|
||||
#netcup_customer_id: "218722"
|
||||
#netcup_api_key: "dmJINUMyNjRmOG1aNDViajZHN2JkOTFRUjU3ckE5ZjJ1Zm1vUz"
|
||||
#netcup_api_password: "iGWL8Hl4m93DgESsP/MPXmtDd0hEVkZ3480Na0psTlXRALnopl"
|
||||
#netcup_vserver_id: "v2202309206672239295"
|
||||
|
||||
|
||||
# fallback_ip:
|
||||
|
||||
wg_all_clients_private_keys:
|
||||
michael: "PITbFZ3UfY5vD5dYUCELO37Qo2W8I4R8+r6D9CeMrm4="
|
||||
---
|
||||
# Allgemeine Variablen für alle Hosts
|
||||
---
|
||||
# Globale Variablen für alle Umgebungen
|
||||
|
||||
# Docker-Konfiguration
|
||||
docker_compose_version: "1.29.2"
|
||||
|
||||
# Nginx-Konfiguration
|
||||
nginx_worker_processes: auto
|
||||
nginx_worker_connections: 1024
|
||||
|
||||
# Verwendeter PHP-Container
|
||||
php_version: "8.1"
|
||||
|
||||
# Allgemeine Anwendungsvariablen
|
||||
app_name: "michaelschiemer"
|
||||
app_env: "production"
|
||||
# Docker-Einstellungen
|
||||
docker_version: "20.10"
|
||||
docker_compose_version: "2.24.5"
|
||||
docker_install_compose: true
|
||||
docker_user: "{{ ansible_user | default('deploy') }}"
|
||||
|
||||
# Deployment-Verzeichnisse
|
||||
deploy_root: /var/www/michaelschiemer
|
||||
deploy_public: "{{ deploy_root }}/public"
|
||||
docker_compose_project_path: "{{ deploy_root }}"
|
||||
|
||||
# Anwendungsvariablen
|
||||
project_root: "{{ playbook_dir }}/../.."
|
||||
project_source: "{{ playbook_dir }}/../.."
|
||||
app_domain: "{{ hostvars[inventory_hostname]['ansible_host'] | default(inventory_hostname) }}"
|
||||
---
|
||||
# Variablen für alle Gruppen
|
||||
|
||||
# Standardwerte für Deployment
|
||||
deploy_root: /var/www/michaelschiemer
|
||||
deploy_public: "{{ deploy_root }}/public"
|
||||
deploy_user: "{{ ansible_user | default('deploy') }}"
|
||||
|
||||
# Projektpfade
|
||||
project_source: "{{ playbook_dir }}/../.."
|
||||
project_root: "{{ playbook_dir }}/../.."
|
||||
|
||||
# Docker-Konfiguration
|
||||
docker_compose_project_path: "{{ deploy_root }}"
|
||||
|
||||
# Standard-Domain (wird normalerweise durch umgebungsspezifische Variablen überschrieben)
|
||||
app_domain: "localhost"
|
||||
|
||||
# Standard Nginx-Konfiguration
|
||||
nginx_worker_processes: "auto"
|
||||
nginx_worker_connections: 1024
|
||||
|
||||
wireguard_clients:
|
||||
- name: michael
|
||||
address: 10.8.0.2
|
||||
public_key: DEIN_PUBLIC_KEY
|
||||
15
.deployment-backup/x_ansible/group_vars/common.yml
Normal file
15
.deployment-backup/x_ansible/group_vars/common.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
# Gemeinsame Variablen für alle Umgebungen
|
||||
|
||||
# Deployment-Variablen
|
||||
deploy_root: /var/www/michaelschiemer
|
||||
deploy_public: "{{ deploy_root }}/public"
|
||||
deploy_user: deploy
|
||||
|
||||
# Anwendungsvariablen
|
||||
app_domain: "{{ hostvars[inventory_hostname]['ansible_host'] | default(inventory_hostname) }}"
|
||||
project_source: "{{ playbook_dir }}/../.."
|
||||
project_root: "{{ playbook_dir }}/../.."
|
||||
|
||||
# Docker-Compose-Pfad
|
||||
docker_compose_project_path: "{{ deploy_root }}"
|
||||
25
.deployment-backup/x_ansible/group_vars/localhost.yml
Normal file
25
.deployment-backup/x_ansible/group_vars/localhost.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
nginx_vite_proxy_include: "vite-proxy.inc.dev"
|
||||
# Localhost-spezifische Konfiguration
|
||||
|
||||
# Deployment-Pfade
|
||||
deploy_root: /home/michael/dev/michaelschiemer
|
||||
docker_compose_project_path: "{{ deploy_root }}"
|
||||
env_file_path: "{{ deploy_root }}/.env"
|
||||
deploy_public: "{{ deploy_root }}/public"
|
||||
|
||||
# Domainname für lokale Entwicklung
|
||||
app_domain: "localhost"
|
||||
|
||||
# Umgebungsvariablen
|
||||
env_vars:
|
||||
APP_ENV: development
|
||||
APP_DEBUG: "true"
|
||||
APP_PORT: 80
|
||||
APP_SSL_PORT: 443
|
||||
|
||||
# Docker-Compose-Projekt
|
||||
compose_project_name: "michaelschiemer_dev"
|
||||
|
||||
# Lokale Quell- und Zielverzeichnisse sind identisch
|
||||
project_source: "{{ deploy_root }}"
|
||||
project_root: "{{ deploy_root }}"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user