Add Template to deploy forgejo.
This template allows deploying a forgejo en either Scaleway or Hetzner (untested) without much knowledge about them. It DOES require knowledge about Terragrunt and ansible. A wizard of sorts is provided but it will not guarantee success without some knowledge about the underlying technology.
This commit is contained in:
parent
a9f546f92a
commit
822e42dbb8
48 changed files with 6846 additions and 2 deletions
234
ansible/playbooks/restore.yml
Normal file
234
ansible/playbooks/restore.yml
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
---
|
||||
# Restore Forgejo from backup
|
||||
# Restores database, repositories, configuration, and data
|
||||
|
||||
- name: Restore Forgejo from Backup
|
||||
hosts: forgejo
|
||||
become: yes
|
||||
gather_facts: yes
|
||||
|
||||
vars_files:
|
||||
- vars/main.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
# Must be provided via --extra-vars
|
||||
backup_timestamp: ""
|
||||
backup_source: "local" # local or s3
|
||||
force_restore: false
|
||||
|
||||
pre_tasks:
|
||||
- name: Validate backup timestamp
|
||||
ansible.builtin.fail:
|
||||
msg: "Please provide backup_timestamp via --extra-vars 'backup_timestamp=20240115T120000'"
|
||||
when: backup_timestamp == ""
|
||||
|
||||
- name: Display restore information
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
WARNING: This will restore Forgejo data
|
||||
========================================
|
||||
|
||||
Backup timestamp: {{ backup_timestamp }}
|
||||
Source: {{ backup_source }}
|
||||
|
||||
This operation will:
|
||||
1. Stop Forgejo service
|
||||
2. Restore database
|
||||
3. Restore repositories
|
||||
4. Restore configuration
|
||||
5. Restart services
|
||||
|
||||
Current data will be backed up first.
|
||||
|
||||
- name: Confirm restore operation
|
||||
ansible.builtin.pause:
|
||||
prompt: "Type 'yes' to continue with restore"
|
||||
register: restore_confirm
|
||||
when: not force_restore
|
||||
|
||||
- name: Validate confirmation
|
||||
ansible.builtin.fail:
|
||||
msg: "Restore cancelled by user"
|
||||
when: not force_restore and restore_confirm.user_input != 'yes'
|
||||
|
||||
tasks:
|
||||
- name: Create pre-restore backup
|
||||
ansible.builtin.include_tasks: backup.yml
|
||||
vars:
|
||||
backup_filename: "pre-restore-{{ ansible_date_time.iso8601_basic_short }}.tar.gz"
|
||||
|
||||
- name: Download backup from S3 if needed
|
||||
when: backup_source == 's3'
|
||||
block:
|
||||
- name: Create temporary download directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ forgejo_backup_path }}/restore-temp"
|
||||
state: directory
|
||||
mode: '0750'
|
||||
|
||||
- name: Download backups from S3
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
aws s3 cp s3://{{ forgejo_backup_s3_bucket }}/backups/{{ item }}-{{ backup_timestamp }}.tar.gz
|
||||
{{ forgejo_backup_path }}/{{ item }}-{{ backup_timestamp }}.tar.gz
|
||||
--endpoint-url {{ forgejo_s3_endpoint }}
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID: "{{ forgejo_s3_access_key }}"
|
||||
AWS_SECRET_ACCESS_KEY: "{{ forgejo_s3_secret_key }}"
|
||||
loop:
|
||||
- database
|
||||
- repositories
|
||||
- config
|
||||
- data
|
||||
no_log: yes
|
||||
|
||||
- name: Verify backup files exist
|
||||
ansible.builtin.stat:
|
||||
path: "{{ forgejo_backup_path }}/{{ item }}-{{ backup_timestamp }}.tar.gz"
|
||||
register: backup_files
|
||||
loop:
|
||||
- repositories
|
||||
- config
|
||||
- data
|
||||
failed_when: not backup_files.results | map(attribute='stat.exists') | list | min
|
||||
|
||||
- name: Verify database backup exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ forgejo_backup_path }}/database-{{ backup_timestamp }}.sql.gz"
|
||||
register: db_backup
|
||||
failed_when: not db_backup.stat.exists
|
||||
|
||||
- name: Stop Forgejo service
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ forgejo_base_path }}"
|
||||
state: stopped
|
||||
|
||||
- name: Restore PostgreSQL database
|
||||
when: forgejo_db_type == 'postgres'
|
||||
block:
|
||||
- name: Drop existing database
|
||||
community.postgresql.postgresql_db:
|
||||
name: "{{ forgejo_db_name }}"
|
||||
state: absent
|
||||
become_user: postgres
|
||||
|
||||
- name: Recreate database
|
||||
community.postgresql.postgresql_db:
|
||||
name: "{{ forgejo_db_name }}"
|
||||
encoding: UTF8
|
||||
lc_collate: en_US.UTF-8
|
||||
lc_ctype: en_US.UTF-8
|
||||
template: template0
|
||||
state: present
|
||||
become_user: postgres
|
||||
|
||||
- name: Decompress database backup
|
||||
ansible.builtin.command:
|
||||
cmd: gunzip -c {{ forgejo_backup_path }}/database-{{ backup_timestamp }}.sql.gz
|
||||
register: db_dump
|
||||
|
||||
- name: Restore database
|
||||
community.postgresql.postgresql_db:
|
||||
name: "{{ forgejo_db_name }}"
|
||||
state: restore
|
||||
target: "{{ forgejo_backup_path }}/database-{{ backup_timestamp }}.sql"
|
||||
become_user: postgres
|
||||
|
||||
- name: Clear existing repositories
|
||||
ansible.builtin.file:
|
||||
path: "{{ forgejo_data_path }}/git"
|
||||
state: absent
|
||||
|
||||
- name: Restore repositories
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ forgejo_backup_path }}/repositories-{{ backup_timestamp }}.tar.gz"
|
||||
dest: "{{ forgejo_data_path }}"
|
||||
remote_src: yes
|
||||
owner: "{{ forgejo_user }}"
|
||||
group: "{{ forgejo_group }}"
|
||||
|
||||
- name: Restore configuration
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ forgejo_backup_path }}/config-{{ backup_timestamp }}.tar.gz"
|
||||
dest: "{{ forgejo_base_path }}"
|
||||
remote_src: yes
|
||||
owner: "{{ forgejo_user }}"
|
||||
group: "{{ forgejo_group }}"
|
||||
|
||||
- name: Restore data files
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ forgejo_backup_path }}/data-{{ backup_timestamp }}.tar.gz"
|
||||
dest: "{{ forgejo_data_path }}"
|
||||
remote_src: yes
|
||||
owner: "{{ forgejo_user }}"
|
||||
group: "{{ forgejo_group }}"
|
||||
|
||||
- name: Set correct permissions
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
owner: "{{ forgejo_user }}"
|
||||
group: "{{ forgejo_group }}"
|
||||
recurse: yes
|
||||
loop:
|
||||
- "{{ forgejo_data_path }}/git"
|
||||
- "{{ forgejo_data_path }}/attachments"
|
||||
- "{{ forgejo_data_path }}/lfs"
|
||||
- "{{ forgejo_config_path }}"
|
||||
|
||||
- name: Start Forgejo service
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ forgejo_base_path }}"
|
||||
state: present
|
||||
|
||||
- name: Wait for Forgejo to be ready
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:{{ forgejo_http_port }}"
|
||||
status_code: 200
|
||||
register: health_check
|
||||
until: health_check.status == 200
|
||||
retries: 30
|
||||
delay: 2
|
||||
|
||||
- name: Run integrity checks
|
||||
ansible.builtin.command:
|
||||
cmd: docker exec forgejo forgejo doctor check --all
|
||||
register: integrity_check
|
||||
failed_when: false
|
||||
|
||||
- name: Display integrity check results
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ integrity_check.stdout_lines }}"
|
||||
|
||||
post_tasks:
|
||||
- name: Verify Forgejo health
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:{{ forgejo_http_port }}/api/healthz"
|
||||
status_code: 200
|
||||
register: health
|
||||
|
||||
- name: Clean up temporary files
|
||||
ansible.builtin.file:
|
||||
path: "{{ forgejo_backup_path }}/restore-temp"
|
||||
state: absent
|
||||
when: backup_source == 's3'
|
||||
|
||||
- name: Display completion message
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Restore Complete!
|
||||
========================================
|
||||
|
||||
Restored from backup: {{ backup_timestamp }}
|
||||
|
||||
Forgejo is now running with restored data.
|
||||
|
||||
Please verify:
|
||||
1. Login works correctly
|
||||
2. Repositories are accessible
|
||||
3. All data is present
|
||||
|
||||
Original data was backed up before restore.
|
||||
========================================
|
||||
Loading…
Add table
Add a link
Reference in a new issue