- Fix upstream configuration in staging-nginx container - Verbessere sed-Befehle zur automatischen Korrektur der PHP-FPM Upstream-Definition - Behebt 502 Bad Gateway Fehler durch korrekte Verbindung zu staging-app:9000
379 lines
11 KiB
Markdown
379 lines
11 KiB
Markdown
# Ansible Deployment Configuration
|
||
|
||
This directory contains Ansible playbooks and configuration for deploying the Custom PHP Framework to production.
|
||
|
||
## Directory Structure
|
||
|
||
```
|
||
deployment/ansible/
|
||
├── ansible.cfg # Ansible configuration
|
||
├── inventory/
|
||
│ ├── production.yml # Production server inventory
|
||
│ └── local.yml # Local testing inventory
|
||
├── playbooks/
|
||
│ ├── deploy-update.yml # Deploy application updates
|
||
│ ├── system-maintenance.yml # Betriebssystem-Updates & Wartung
|
||
│ ├── rollback.yml # Rollback deployments
|
||
│ ├── setup-infrastructure.yml # Provision core stacks
|
||
│ ├── setup-production-secrets.yml # Deploy secrets
|
||
│ ├── setup-wireguard.yml # Setup WireGuard VPN server
|
||
│ ├── add-wireguard-client.yml # Add WireGuard client
|
||
│ ├── sync-code.yml # Git-based code sync
|
||
│ └── README-WIREGUARD.md # WireGuard documentation
|
||
├── scripts/ # Helper scripts for secrets & credentials
|
||
├── roles/ # Reusable roles (e.g. application stack)
|
||
├── secrets/
|
||
│ ├── .gitignore # Prevent committing secrets
|
||
│ └── production.vault.yml.example # Example vault file
|
||
└── templates/
|
||
├── application.env.j2 # Application stack environment
|
||
├── gitea-app.ini.j2 # Gitea configuration
|
||
├── minio.env.j2 # MinIO environment
|
||
├── monitoring.env.j2 # Monitoring stack environment
|
||
├── wireguard-client.conf.j2 # WireGuard client config
|
||
└── wireguard-server.conf.j2 # WireGuard server config
|
||
|
||
## Roles
|
||
|
||
Stack-spezifische Aufgaben liegen in `roles/` (z. B. `application`, `traefik`, `registry`). Playbooks wie `setup-infrastructure.yml` importieren diese Rollen direkt. Die Application-Rolle kann mit Variablen wie `application_sync_files=false` oder `application_compose_recreate="always"` konfiguriert werden (siehe `playbooks/deploy-update.yml` als Beispiel). Die neue `system`-Rolle hält Betriebssystem-Pakete aktuell und konfiguriert optionale Unattended-Upgrades bevor Docker-Stacks neu gestartet werden.
|
||
|
||
## Prerequisites
|
||
|
||
1. **Ansible Installed**:
|
||
```bash
|
||
pip install ansible
|
||
```
|
||
|
||
2. **SSH Access**:
|
||
- SSH key configured at `~/.ssh/production`
|
||
- Key added to production server's authorized_keys for `deploy` user
|
||
|
||
3. **Ansible Vault Password**:
|
||
- Create `.vault_pass` file in `secrets/` directory
|
||
- Add vault password to this file (one line)
|
||
- File is gitignored for security
|
||
- 📖 **Detaillierte Dokumentation:** [docs/guides/vault-password.md](../docs/guides/vault-password.md)
|
||
|
||
## Setup Instructions
|
||
|
||
### 1. Create Production Secrets
|
||
|
||
```bash
|
||
cd deployment/ansible/secrets
|
||
|
||
# Copy example file
|
||
cp production.vault.yml.example production.vault.yml
|
||
|
||
# Edit with your actual secrets
|
||
nano production.vault.yml
|
||
|
||
# Encrypt the file
|
||
ansible-vault encrypt production.vault.yml
|
||
# Enter vault password when prompted
|
||
```
|
||
|
||
### 2. Store Vault Password
|
||
|
||
```bash
|
||
# Create vault password file
|
||
echo "your-vault-password-here" > secrets/.vault_pass
|
||
|
||
# Secure the file
|
||
chmod 600 secrets/.vault_pass
|
||
```
|
||
|
||
**📖 Für detaillierte Informationen:** Siehe [docs/guides/vault-password.md](../docs/guides/vault-password.md)
|
||
|
||
### 3. Configure SSH Key
|
||
|
||
```bash
|
||
# Generate SSH key if needed
|
||
ssh-keygen -t ed25519 -f ~/.ssh/production -C "ansible-deploy"
|
||
|
||
# Copy public key to production server
|
||
ssh-copy-id -i ~/.ssh/production.pub deploy@94.16.110.151
|
||
```
|
||
|
||
## Running Playbooks
|
||
|
||
### Deploy Production Secrets
|
||
|
||
**First-time setup** - Deploy secrets to production server:
|
||
|
||
```bash
|
||
ansible-playbook playbooks/setup-production-secrets.yml \
|
||
--vault-password-file secrets/.vault_pass
|
||
```
|
||
|
||
### Deploy Application Update
|
||
|
||
**Automated via Gitea Actions** - Or run manually:
|
||
|
||
```bash
|
||
ansible-playbook playbooks/deploy-update.yml \
|
||
-e "image_tag=sha-abc123" \
|
||
-e "git_commit_sha=abc123" \
|
||
-e "deployment_timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||
-e "docker_registry_username=gitea-user" \
|
||
-e "docker_registry_password=your-registry-password"
|
||
```
|
||
|
||
### Rollback Deployment
|
||
|
||
**Rollback to previous version**:
|
||
|
||
```bash
|
||
ansible-playbook playbooks/rollback.yml
|
||
```
|
||
|
||
**Rollback to specific version**:
|
||
|
||
```bash
|
||
ansible-playbook playbooks/rollback.yml \
|
||
-e "rollback_to_version=2025-01-28T15-30-00"
|
||
```
|
||
|
||
### Setup WireGuard VPN
|
||
|
||
**First-time setup** - Install WireGuard VPN server:
|
||
|
||
```bash
|
||
ansible-playbook -i inventory/production.yml playbooks/setup-wireguard.yml
|
||
```
|
||
|
||
**Add a client**:
|
||
|
||
```bash
|
||
ansible-playbook -i inventory/production.yml playbooks/add-wireguard-client.yml \
|
||
-e "client_name=myclient"
|
||
```
|
||
|
||
Siehe [playbooks/README-WIREGUARD.md](playbooks/README-WIREGUARD.md) für detaillierte Anleitung.
|
||
|
||
### System Maintenance ausführen
|
||
|
||
Führt die `system`-Rolle aus, aktualisiert Paketquellen, führt OS-Upgrades durch und aktiviert optional Unattended-Upgrades.
|
||
|
||
```bash
|
||
ansible-playbook -i inventory/production.yml \
|
||
playbooks/system-maintenance.yml
|
||
```
|
||
|
||
Tipp: Mit `--check` lässt sich zunächst ein Dry-Run starten, um anstehende Updates zu prüfen.
|
||
|
||
## Ansible Vault Operations
|
||
|
||
### View Encrypted File
|
||
|
||
```bash
|
||
ansible-vault view secrets/production.vault.yml \
|
||
--vault-password-file secrets/.vault_pass
|
||
```
|
||
|
||
### Edit Encrypted File
|
||
|
||
```bash
|
||
ansible-vault edit secrets/production.vault.yml \
|
||
--vault-password-file secrets/.vault_pass
|
||
```
|
||
|
||
### Change Vault Password
|
||
|
||
```bash
|
||
ansible-vault rekey secrets/production.vault.yml \
|
||
--vault-password-file secrets/.vault_pass
|
||
```
|
||
|
||
### Decrypt File (Temporarily)
|
||
|
||
```bash
|
||
ansible-vault decrypt secrets/production.vault.yml \
|
||
--vault-password-file secrets/.vault_pass
|
||
|
||
# DO NOT COMMIT DECRYPTED FILE!
|
||
|
||
# Re-encrypt when done
|
||
ansible-vault encrypt secrets/production.vault.yml \
|
||
--vault-password-file secrets/.vault_pass
|
||
```
|
||
|
||
## Testing Playbooks
|
||
|
||
### Test with Check Mode (Dry Run)
|
||
|
||
```bash
|
||
ansible-playbook playbooks/deploy-update.yml \
|
||
--check \
|
||
-e "image_tag=test"
|
||
```
|
||
|
||
### Test Connection
|
||
|
||
```bash
|
||
ansible production -m ping
|
||
```
|
||
|
||
### Verify Inventory
|
||
|
||
```bash
|
||
ansible-inventory --list -y
|
||
```
|
||
|
||
### System Maintenance Dry Run
|
||
|
||
```bash
|
||
ansible-playbook -i inventory/production.yml \
|
||
playbooks/system-maintenance.yml \
|
||
--check
|
||
```
|
||
|
||
## Security Best Practices
|
||
|
||
1. **Never commit unencrypted secrets**
|
||
- `production.vault.yml` must be encrypted
|
||
- `.vault_pass` is gitignored
|
||
- Use `.example` files for documentation
|
||
|
||
2. **Rotate secrets regularly**
|
||
- Update vault file
|
||
- Re-run `setup-production-secrets.yml`
|
||
- Restart affected services
|
||
|
||
3. **Limit SSH key access**
|
||
- Use separate SSH key for Ansible
|
||
- Limit key to `deploy` user only
|
||
- Consider IP restrictions
|
||
|
||
4. **Vault password security**
|
||
- Store vault password in secure password manager
|
||
- Don't share via insecure channels
|
||
- Use different passwords for dev/staging/prod
|
||
|
||
## Troubleshooting
|
||
|
||
### Vault Decryption Failed
|
||
|
||
**Error**: `Decryption failed (no vault secrets were found)`
|
||
|
||
**Solution**:
|
||
```bash
|
||
# Verify vault password is correct
|
||
ansible-vault view secrets/production.vault.yml \
|
||
--vault-password-file secrets/.vault_pass
|
||
|
||
# If password is wrong, you'll need the original password to decrypt
|
||
```
|
||
|
||
### SSH Connection Failed
|
||
|
||
**Error**: `Failed to connect to the host`
|
||
|
||
**Solutions**:
|
||
```bash
|
||
# Test SSH connection manually
|
||
ssh -i ~/.ssh/production deploy@94.16.110.151
|
||
|
||
# Check SSH key permissions
|
||
chmod 600 ~/.ssh/production
|
||
chmod 644 ~/.ssh/production.pub
|
||
|
||
# Verify SSH key is added to server
|
||
ssh-copy-id -i ~/.ssh/production.pub deploy@94.16.110.151
|
||
```
|
||
|
||
### Docker Registry Authentication Failed
|
||
|
||
**Error**: `unauthorized: authentication required`
|
||
|
||
**Solution**:
|
||
```bash
|
||
# Verify registry credentials in vault file
|
||
ansible-vault view secrets/production.vault.yml \
|
||
--vault-password-file secrets/.vault_pass
|
||
|
||
# Test registry login manually on production server
|
||
docker login registry.michaelschiemer.de
|
||
```
|
||
|
||
### Service Not Starting
|
||
|
||
**Check service logs**:
|
||
```bash
|
||
# SSH to production server
|
||
ssh -i ~/.ssh/production deploy@94.16.110.151
|
||
|
||
# Check Docker Compose service logs
|
||
docker compose -f {{ app_stack_path }}/docker-compose.yml logs app
|
||
docker compose -f {{ app_stack_path }}/docker-compose.yml logs nginx
|
||
|
||
# Check stack status
|
||
docker compose -f {{ app_stack_path }}/docker-compose.yml ps
|
||
```
|
||
|
||
## CI/CD Integration
|
||
|
||
These playbooks are automatically executed by Gitea Actions workflows:
|
||
|
||
- **`.gitea/workflows/production-deploy.yml`** - Calls `deploy-update.yml` on push to main
|
||
- **`.gitea/workflows/update-production-secrets.yml`** - Calls `setup-production-secrets.yml` on manual trigger
|
||
- **`.gitea/workflows/system-maintenance.yml`** - Führt `system-maintenance.yml` geplant oder manuell aus, um Pakete aktuell zu halten
|
||
|
||
Vault password is stored as Gitea Actions secret: `ANSIBLE_VAULT_PASSWORD`
|
||
|
||
## Inventory Variables
|
||
|
||
All zentralen Variablen werden in `group_vars/production.yml` gepflegt und können bei Bedarf im Inventory überschrieben werden. Häufig verwendete Werte:
|
||
|
||
| Variable | Beschreibung | Standardwert |
|
||
|----------|--------------|--------------|
|
||
| `deploy_user_home` | Home-Verzeichnis des Deploy-Users | `/home/deploy` |
|
||
| `stacks_base_path` | Basispfad für Docker Compose Stacks | `/home/deploy/deployment/stacks` |
|
||
| `app_stack_path` | Pfad zum Application Stack | `/home/deploy/deployment/stacks/application` |
|
||
| `backups_path` | Ablageort für Deployment-Backups | `/home/deploy/deployment/backups` |
|
||
| `docker_registry` | Interner Registry-Endpunkt (lokal) | `localhost:5000` |
|
||
| `docker_registry_external` | Externer Registry-Endpunkt | `registry.michaelschiemer.de` |
|
||
| `app_domain` | Produktions-Domain | `michaelschiemer.de` |
|
||
| `health_check_url` | Health-Check Endpoint | `https://michaelschiemer.de/health` |
|
||
| `max_rollback_versions` | Anzahl vorgehaltener Backups | `5` |
|
||
| `system_update_packages` | Aktiviert OS-Paketupdates via `system`-Rolle | `true` |
|
||
| `system_apt_upgrade` | Wert für `apt upgrade` (z. B. `dist`) | `dist` |
|
||
| `system_enable_unattended_upgrades` | Aktiviert `unattended-upgrades` | `true` |
|
||
| `system_enable_unattended_reboot` | Steuert automatische Reboots nach Updates | `false` |
|
||
| `system_unattended_reboot_time` | Reboot-Zeitfenster (wenn aktiviert) | `02:00` |
|
||
| `system_enable_unattended_timer` | Aktiviert Systemd-Timer für apt | `true` |
|
||
| `system_enable_docker_prune` | Führt nach Updates `docker system prune` aus | `false` |
|
||
|
||
## Backup Management
|
||
|
||
Backups are automatically created before each deployment:
|
||
|
||
- **Location**: `/home/deploy/backups/`
|
||
- **Retention**: Last 5 versions kept
|
||
- **Contents**:
|
||
- `current_image.txt` - Previously deployed image
|
||
- `stack_status.txt` - Stack status before deployment
|
||
- `deployment_metadata.txt` - Deployment details
|
||
|
||
### List Available Backups
|
||
|
||
```bash
|
||
ssh -i ~/.ssh/production deploy@94.16.110.151 \
|
||
"ls -lh /home/deploy/backups/"
|
||
```
|
||
|
||
### Manual Backup
|
||
|
||
```bash
|
||
ansible-playbook playbooks/deploy-update.yml \
|
||
--tags backup \
|
||
-e "image_tag=current"
|
||
```
|
||
|
||
## Support
|
||
|
||
For issues with:
|
||
- **Playbooks**: Check this README and playbook comments
|
||
- **Vault**: See Ansible Vault documentation
|
||
- **Deployment**: Review Gitea Actions logs
|
||
- **Production**: SSH to server and check Docker logs
|