Files
michaelschiemer/deployment/ansible
Michael Schiemer e66f98b84a Fix: Resolve recursive variable reference in Ansible playbooks
- Fix infinite loop in docker_registry_username/docker_registry_password variables
- Use _default suffix variables in production.yml to avoid recursion
- Make docker registry login optional (ignore_errors) for cases where auth isn't needed
- Fix line endings in deploy.sh script
2025-10-31 11:31:43 +01:00
..
2025-10-31 04:14:18 +01:00
2025-10-31 04:14:18 +01:00
2025-10-31 04:14:18 +01:00

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
  1. SSH Access:

    • SSH key configured at ~/.ssh/production
    • Key added to production server's authorized_keys for deploy user
  2. 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

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

# Create vault password file
echo "your-vault-password-here" > secrets/.vault_pass

# Secure the file
chmod 600 secrets/.vault_pass

3. Configure SSH Key

# 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:

ansible-playbook playbooks/setup-production-secrets.yml \
  --vault-password-file secrets/.vault_pass

Deploy Application Update

Automated via Gitea Actions - Or run manually:

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:

ansible-playbook playbooks/rollback.yml

Rollback to specific version:

ansible-playbook playbooks/rollback.yml \
  -e "rollback_to_version=2025-01-28T15-30-00"

Setup WireGuard VPN

First-time setup - Install WireGuard VPN server:

ansible-playbook -i inventory/production.yml playbooks/setup-wireguard.yml

Add a client:

ansible-playbook -i inventory/production.yml playbooks/add-wireguard-client.yml \
  -e "client_name=myclient"

Siehe playbooks/README-WIREGUARD.md für detaillierte Anleitung.

Ansible Vault Operations

View Encrypted File

ansible-vault view secrets/production.vault.yml \
  --vault-password-file secrets/.vault_pass

Edit Encrypted File

ansible-vault edit secrets/production.vault.yml \
  --vault-password-file secrets/.vault_pass

Change Vault Password

ansible-vault rekey secrets/production.vault.yml \
  --vault-password-file secrets/.vault_pass

Decrypt File (Temporarily)

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)

ansible-playbook playbooks/deploy-update.yml \
  --check \
  -e "image_tag=test"

Test Connection

ansible production -m ping

Verify Inventory

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:

# 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:

# 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:

# 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:

# 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

ssh -i ~/.ssh/production deploy@94.16.110.151 \
  "ls -lh /home/deploy/backups/"

Manual Backup

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