diff --git a/playbooks/backup-gitea.yml b/playbooks/backup-gitea.yml new file mode 100644 index 0000000..f5ff189 --- /dev/null +++ b/playbooks/backup-gitea.yml @@ -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 %}