# 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 ├── playbooks/ │ ├── setup-production-secrets.yml # Deploy secrets │ ├── deploy-update.yml # Deploy application updates │ ├── rollback.yml # Rollback deployments │ ├── setup-wireguard.yml # Setup WireGuard VPN server │ ├── add-wireguard-client.yml # Add WireGuard client │ └── README-WIREGUARD.md # WireGuard documentation ├── secrets/ │ ├── .gitignore # Prevent committing secrets │ └── production.vault.yml.example # Example vault file └── templates/ └── .env.production.j2 # Environment file template ## 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 ## 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 ``` ### 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. ## 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 ``` ## 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 git.michaelschiemer.de:5000 ``` ### Service Not Starting **Check service logs**: ```bash # SSH to production server ssh -i ~/.ssh/production deploy@94.16.110.151 # Check Docker service logs docker service logs app_app # Check stack status docker stack ps app ``` ## 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 Vault password is stored as Gitea Actions secret: `ANSIBLE_VAULT_PASSWORD` ## Inventory Variables All deployment variables are defined in `inventory/production.yml`: | Variable | Description | Default | |----------|-------------|---------| | `docker_registry` | Docker registry URL | git.michaelschiemer.de:5000 | | `app_name` | Application name | framework | | `app_domain` | Production domain | michaelschiemer.de | | `stack_name` | Docker stack name | app | | `compose_file` | Docker Compose file path | /home/deploy/docker-compose.prod.yml | | `secrets_path` | Secrets directory | /home/deploy/secrets | | `backups_path` | Backups directory | /home/deploy/backups | | `max_rollback_versions` | Backup retention | 5 | | `health_check_url` | Health check endpoint | https://michaelschiemer.de/health | ## 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