fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
268
deployment/ansible/playbooks/backup.yml
Normal file
268
deployment/ansible/playbooks/backup.yml
Normal file
@@ -0,0 +1,268 @@
|
||||
---
|
||||
- name: Create Comprehensive Backups
|
||||
hosts: production
|
||||
gather_facts: yes
|
||||
become: no
|
||||
|
||||
vars:
|
||||
backup_retention_days: "{{ backup_retention_days | default(7) }}"
|
||||
|
||||
pre_tasks:
|
||||
- name: Ensure backup directory exists
|
||||
file:
|
||||
path: "{{ backups_path }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
become: yes
|
||||
|
||||
- name: Create timestamp for backup
|
||||
set_fact:
|
||||
backup_timestamp: "{{ ansible_date_time.epoch }}"
|
||||
backup_date: "{{ ansible_date_time.date }}"
|
||||
backup_time: "{{ ansible_date_time.time }}"
|
||||
|
||||
- name: Create backup directory for this run
|
||||
file:
|
||||
path: "{{ backups_path }}/backup_{{ backup_date }}_{{ backup_time }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
register: backup_dir
|
||||
become: yes
|
||||
|
||||
- name: Set backup directory path
|
||||
set_fact:
|
||||
current_backup_dir: "{{ backup_dir.path }}"
|
||||
|
||||
tasks:
|
||||
- name: Backup PostgreSQL Database
|
||||
when: backup_postgresql | default(true) | bool
|
||||
block:
|
||||
- name: Check if PostgreSQL stack is running
|
||||
shell: docker compose -f {{ stacks_base_path }}/postgresql/docker-compose.yml ps --format json | jq -r '.[] | select(.Service=="postgres") | .State' | grep -q "running"
|
||||
register: postgres_running
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Get PostgreSQL container name
|
||||
shell: docker compose -f {{ stacks_base_path }}/postgresql/docker-compose.yml ps --format json | jq -r '.[] | select(.Service=="postgres") | .Name'
|
||||
register: postgres_container
|
||||
changed_when: false
|
||||
when: postgres_running.rc == 0
|
||||
|
||||
- name: Read PostgreSQL environment variables
|
||||
shell: |
|
||||
cd {{ stacks_base_path }}/postgresql
|
||||
grep -E "^POSTGRES_(DB|USER|PASSWORD)=" .env 2>/dev/null || echo ""
|
||||
register: postgres_env
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
no_log: true
|
||||
|
||||
- name: Extract PostgreSQL credentials
|
||||
set_fact:
|
||||
postgres_db: "{{ postgres_env.stdout | regex_search('POSTGRES_DB=([^\\n]+)', '\\1') | first | default('michaelschiemer') }}"
|
||||
postgres_user: "{{ postgres_env.stdout | regex_search('POSTGRES_USER=([^\\n]+)', '\\1') | first | default('postgres') }}"
|
||||
postgres_password: "{{ postgres_env.stdout | regex_search('POSTGRES_PASSWORD=([^\\n]+)', '\\1') | first | default('') }}"
|
||||
when: postgres_running.rc == 0
|
||||
no_log: true
|
||||
|
||||
- name: Create PostgreSQL backup
|
||||
shell: |
|
||||
cd {{ stacks_base_path }}/postgresql
|
||||
PGPASSWORD="{{ postgres_password }}" docker compose exec -T postgres pg_dump \
|
||||
-U {{ postgres_user }} \
|
||||
-d {{ postgres_db }} \
|
||||
--clean \
|
||||
--if-exists \
|
||||
--create \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
| gzip > {{ current_backup_dir }}/postgresql_${postgres_db}_{{ backup_date }}_{{ backup_time }}.sql.gz
|
||||
when: postgres_running.rc == 0
|
||||
no_log: true
|
||||
|
||||
- name: Verify PostgreSQL backup
|
||||
stat:
|
||||
path: "{{ current_backup_dir }}/postgresql_{{ postgres_db }}_{{ backup_date }}_{{ backup_time }}.sql.gz"
|
||||
register: postgres_backup_file
|
||||
when: postgres_running.rc == 0
|
||||
|
||||
- name: Display PostgreSQL backup status
|
||||
debug:
|
||||
msg: "PostgreSQL backup: {{ 'SUCCESS' if (postgres_running.rc == 0 and postgres_backup_file.stat.exists) else 'SKIPPED (PostgreSQL not running)' }}"
|
||||
|
||||
- name: Backup Application Data
|
||||
when: backup_application_data | default(true) | bool
|
||||
block:
|
||||
- name: Check if production stack is running
|
||||
shell: docker compose -f {{ stacks_base_path }}/production/docker-compose.base.yml -f {{ stacks_base_path }}/production/docker-compose.production.yml ps --format json | jq -r '.[] | select(.Service=="php") | .State' | grep -q "running"
|
||||
register: app_running
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Backup application storage directory
|
||||
archive:
|
||||
path: "{{ stacks_base_path }}/production/storage"
|
||||
dest: "{{ current_backup_dir }}/application_storage_{{ backup_date }}_{{ backup_time }}.tar.gz"
|
||||
format: gz
|
||||
when: app_running.rc == 0
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Backup application logs
|
||||
archive:
|
||||
path: "{{ stacks_base_path }}/production/storage/logs"
|
||||
dest: "{{ current_backup_dir }}/application_logs_{{ backup_date }}_{{ backup_time }}.tar.gz"
|
||||
format: gz
|
||||
when: app_running.rc == 0
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Backup application .env file
|
||||
copy:
|
||||
src: "{{ stacks_base_path }}/production/.env"
|
||||
dest: "{{ current_backup_dir }}/application_env_{{ backup_date }}_{{ backup_time }}.env"
|
||||
remote_src: yes
|
||||
when: app_running.rc == 0
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Display application backup status
|
||||
debug:
|
||||
msg: "Application data backup: {{ 'SUCCESS' if app_running.rc == 0 else 'SKIPPED (Application not running)' }}"
|
||||
|
||||
- name: Backup Gitea Data
|
||||
when: backup_gitea | default(true) | bool
|
||||
block:
|
||||
- name: Check if Gitea stack is running
|
||||
shell: docker compose -f {{ stacks_base_path }}/gitea/docker-compose.yml ps --format json | jq -r '.[] | select(.Service=="gitea") | .State' | grep -q "running"
|
||||
register: gitea_running
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Get Gitea volume name
|
||||
shell: docker compose -f {{ stacks_base_path }}/gitea/docker-compose.yml config --volumes | head -1
|
||||
register: gitea_volume
|
||||
changed_when: false
|
||||
when: gitea_running.rc == 0
|
||||
|
||||
- name: Backup Gitea volume
|
||||
shell: |
|
||||
docker run --rm \
|
||||
-v {{ gitea_volume.stdout }}:/source:ro \
|
||||
-v {{ current_backup_dir }}:/backup \
|
||||
alpine tar czf /backup/gitea_data_{{ backup_date }}_{{ backup_time }}.tar.gz -C /source .
|
||||
when: gitea_running.rc == 0 and gitea_volume.stdout != ""
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Display Gitea backup status
|
||||
debug:
|
||||
msg: "Gitea backup: {{ 'SUCCESS' if (gitea_running.rc == 0 and gitea_volume.stdout != '') else 'SKIPPED (Gitea not running)' }}"
|
||||
|
||||
- name: Backup Docker Registry Images (Optional)
|
||||
when: backup_registry | default(false) | bool
|
||||
block:
|
||||
- name: Check if registry stack is running
|
||||
shell: docker compose -f {{ stacks_base_path }}/registry/docker-compose.yml ps --format json | jq -r '.[] | select(.Service=="registry") | .State' | grep -q "running"
|
||||
register: registry_running
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: List registry images
|
||||
shell: |
|
||||
cd {{ stacks_base_path }}/registry
|
||||
docker compose exec -T registry registry garbage-collect --dry-run /etc/docker/registry/config.yml 2>&1 | grep -E "repository|tag" || echo "No images found"
|
||||
register: registry_images
|
||||
changed_when: false
|
||||
when: registry_running.rc == 0
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Save registry image list
|
||||
copy:
|
||||
content: "{{ registry_images.stdout }}"
|
||||
dest: "{{ current_backup_dir }}/registry_images_{{ backup_date }}_{{ backup_time }}.txt"
|
||||
when: registry_running.rc == 0 and registry_images.stdout != ""
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Display registry backup status
|
||||
debug:
|
||||
msg: "Registry backup: {{ 'SUCCESS' if registry_running.rc == 0 else 'SKIPPED (Registry not running)' }}"
|
||||
|
||||
- name: Create backup metadata
|
||||
copy:
|
||||
content: |
|
||||
Backup Date: {{ backup_date }} {{ backup_time }}
|
||||
Backup Timestamp: {{ backup_timestamp }}
|
||||
Host: {{ inventory_hostname }}
|
||||
|
||||
Components Backed Up:
|
||||
- PostgreSQL: {{ 'YES' if ((backup_postgresql | default(true) | bool) and (postgres_running.rc | default(1) == 0)) else 'NO' }}
|
||||
- Application Data: {{ 'YES' if ((backup_application_data | default(true) | bool) and (app_running.rc | default(1) == 0)) else 'NO' }}
|
||||
- Gitea: {{ 'YES' if ((backup_gitea | default(true) | bool) and (gitea_running.rc | default(1) == 0)) else 'NO' }}
|
||||
- Registry: {{ 'YES' if ((backup_registry | default(false) | bool) and (registry_running.rc | default(1) == 0)) else 'NO' }}
|
||||
|
||||
Backup Location: {{ current_backup_dir }}
|
||||
dest: "{{ current_backup_dir }}/backup_metadata.txt"
|
||||
mode: '0644'
|
||||
|
||||
- name: Verify backup files
|
||||
when: verify_backups | default(true) | bool
|
||||
block:
|
||||
- name: List all backup files
|
||||
find:
|
||||
paths: "{{ current_backup_dir }}"
|
||||
file_type: file
|
||||
register: backup_files
|
||||
|
||||
- name: Check backup file sizes
|
||||
stat:
|
||||
path: "{{ item.path }}"
|
||||
register: backup_file_stats
|
||||
loop: "{{ backup_files.files }}"
|
||||
|
||||
- name: Display backup summary
|
||||
debug:
|
||||
msg: |
|
||||
Backup Summary:
|
||||
- Total files: {{ backup_files.files | length }}
|
||||
- Total size: {{ backup_file_stats.results | map(attribute='stat.size') | sum | int / 1024 / 1024 }} MB
|
||||
- Location: {{ current_backup_dir }}
|
||||
|
||||
- name: Fail if no backup files created
|
||||
fail:
|
||||
msg: "No backup files were created in {{ current_backup_dir }}"
|
||||
when: backup_files.files | length == 0
|
||||
|
||||
- name: Cleanup old backups
|
||||
block:
|
||||
- name: Find old backup directories
|
||||
find:
|
||||
paths: "{{ backups_path }}"
|
||||
patterns: "backup_*"
|
||||
file_type: directory
|
||||
register: backup_dirs
|
||||
|
||||
- name: Calculate cutoff date
|
||||
set_fact:
|
||||
cutoff_timestamp: "{{ (ansible_date_time.epoch | int) - (backup_retention_days | int * 86400) }}"
|
||||
|
||||
- name: Remove old backup directories
|
||||
file:
|
||||
path: "{{ item.path }}"
|
||||
state: absent
|
||||
loop: "{{ backup_dirs.files }}"
|
||||
when: item.mtime | int < cutoff_timestamp | int
|
||||
become: yes
|
||||
|
||||
- name: Display cleanup summary
|
||||
debug:
|
||||
msg: "Cleaned up backups older than {{ backup_retention_days }} days"
|
||||
|
||||
post_tasks:
|
||||
- name: Display final backup status
|
||||
debug:
|
||||
msg: |
|
||||
==========================================
|
||||
Backup completed successfully!
|
||||
==========================================
|
||||
Backup location: {{ current_backup_dir }}
|
||||
Retention: {{ backup_retention_days }} days
|
||||
==========================================
|
||||
|
||||
Reference in New Issue
Block a user