Add Gitea backup playbook using built-in dump command

Creates /opt/gitea-backups/ on the Gitea server and runs `gitea dump`
to produce a tar.gz archive of all repositories, MySQL database, config,
LFS data, and attachments. Retains last 5 backups and supports optional
fetch to Ansible controller via -e fetch_backup=true.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
directlx 2026-02-27 09:46:49 -05:00
parent 94180f6e8b
commit 4196ac3185
1 changed files with 115 additions and 0 deletions

115
playbooks/backup-gitea.yml Normal file
View File

@ -0,0 +1,115 @@
---
# Backup Gitea server using built-in dump command
#
# Usage:
# ansible-playbook playbooks/backup-gitea.yml
# ansible-playbook playbooks/backup-gitea.yml -e fetch_backup=true
# ansible-playbook playbooks/backup-gitea.yml -e keep_backups=7
#
# Options:
# fetch_backup: Copy backup archive to Ansible controller (default: false)
# keep_backups: Number of backups to retain on server (default: 5)
# backup_dir: Directory to store backups (default: /opt/gitea-backups)
- name: Backup Gitea
hosts: gitea
become: true
vars:
backup_dir: /opt/gitea-backups
gitea_bin: /home/git/gitea
gitea_config: /etc/gitea/app.ini
gitea_work_dir: /home/git
keep_backups: 5
fetch_backup: false
backup_filename: "gitea-backup-{{ ansible_date_time.date }}-{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}.tar.gz"
fetch_dest: "/tmp/gitea-backups"
tasks:
- name: Gather date/time facts
ansible.builtin.setup:
gather_subset:
- date_time
- name: Create backup directory
ansible.builtin.file:
path: "{{ backup_dir }}"
state: directory
owner: git
group: git
mode: "0750"
- name: Run gitea dump
ansible.builtin.command:
argv:
- "{{ gitea_bin }}"
- dump
- --config
- "{{ gitea_config }}"
- --work-path
- "{{ gitea_work_dir }}"
- --file
- "{{ backup_dir }}/{{ backup_filename }}"
- --type
- tar.gz
- --database
- mysql
- --skip-log
- --quiet
become_user: git
environment:
HOME: /home/git
USER: git
GITEA_WORK_DIR: "{{ gitea_work_dir }}"
register: gitea_dump_result
changed_when: true
- name: Verify backup file was created
ansible.builtin.stat:
path: "{{ backup_dir }}/{{ backup_filename }}"
register: backup_stat
- name: Fail if backup file missing
ansible.builtin.fail:
msg: "Backup file was not created at {{ backup_dir }}/{{ backup_filename }}"
when: not backup_stat.stat.exists
- name: Show backup file info
ansible.builtin.debug:
msg: "Backup created: {{ backup_dir }}/{{ backup_filename }} ({{ (backup_stat.stat.size / 1024 / 1024) | round(1) }} MB)"
- name: Find existing backups (sorted by name)
ansible.builtin.find:
paths: "{{ backup_dir }}"
patterns: "gitea-backup-*.tar.gz"
file_type: file
register: existing_backups
- name: Remove old backups (keep last {{ keep_backups }})
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ (existing_backups.files | sort(attribute='mtime')) [:-keep_backups] }}"
when: existing_backups.files | length > keep_backups
- name: Fetch backup to Ansible controller
ansible.builtin.fetch:
src: "{{ backup_dir }}/{{ backup_filename }}"
dest: "{{ fetch_dest }}/"
flat: true
when: fetch_backup | bool
- name: List all backups on server
ansible.builtin.find:
paths: "{{ backup_dir }}"
patterns: "gitea-backup-*.tar.gz"
file_type: file
register: all_backups
- name: Show backup summary
ansible.builtin.debug:
msg: |
Gitea backup complete.
Location: {{ backup_dir }}/{{ backup_filename }}
Size: {{ (backup_stat.stat.size / 1024 / 1024) | round(1) }} MB
Total backups stored: {{ all_backups.files | length }}
{% if fetch_backup | bool %}Fetched to: {{ fetch_dest }}/{{ backup_filename }}{% endif %}