333 lines
8.1 KiB
Markdown
333 lines
8.1 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
|
|
├── 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
|