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
203
ansible/playbooks/backup.yml
Normal file
203
ansible/playbooks/backup.yml
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
---
|
||||
# Backup Forgejo data and database
|
||||
# Creates timestamped backups and optionally uploads to S3
|
||||
|
||||
- name: Backup Forgejo
|
||||
hosts: forgejo
|
||||
become: yes
|
||||
gather_facts: yes
|
||||
|
||||
vars_files:
|
||||
- vars/main.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
backup_timestamp: "{{ ansible_date_time.iso8601_basic_short }}"
|
||||
backup_filename: "forgejo-backup-{{ backup_timestamp }}.tar.gz"
|
||||
upload_to_s3: "{{ forgejo_backup_to_s3 | default(false) }}"
|
||||
|
||||
pre_tasks:
|
||||
- name: Display backup information
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
Creating backup: {{ backup_filename }}
|
||||
Upload to S3: {{ upload_to_s3 }}
|
||||
Backup path: {{ forgejo_backup_path }}
|
||||
|
||||
tasks:
|
||||
- name: Ensure backup directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ forgejo_backup_path }}"
|
||||
state: directory
|
||||
owner: "{{ forgejo_user }}"
|
||||
group: "{{ forgejo_group }}"
|
||||
mode: '0750'
|
||||
|
||||
- name: Create PostgreSQL backup
|
||||
community.postgresql.postgresql_db:
|
||||
name: "{{ forgejo_db_name }}"
|
||||
state: dump
|
||||
target: "{{ forgejo_backup_path }}/database-{{ backup_timestamp }}.sql"
|
||||
become_user: postgres
|
||||
when: forgejo_db_type == 'postgres'
|
||||
|
||||
- name: Compress database backup
|
||||
community.general.archive:
|
||||
path: "{{ forgejo_backup_path }}/database-{{ backup_timestamp }}.sql"
|
||||
dest: "{{ forgejo_backup_path }}/database-{{ backup_timestamp }}.sql.gz"
|
||||
format: gz
|
||||
remove: yes
|
||||
when: forgejo_db_type == 'postgres'
|
||||
|
||||
- name: Create Git repositories backup
|
||||
community.general.archive:
|
||||
path: "{{ forgejo_data_path }}/git"
|
||||
dest: "{{ forgejo_backup_path }}/repositories-{{ backup_timestamp }}.tar.gz"
|
||||
format: gz
|
||||
|
||||
- name: Backup configuration files
|
||||
community.general.archive:
|
||||
path:
|
||||
- "{{ forgejo_config_path }}"
|
||||
- "{{ forgejo_base_path }}/docker-compose.yml"
|
||||
dest: "{{ forgejo_backup_path }}/config-{{ backup_timestamp }}.tar.gz"
|
||||
format: gz
|
||||
|
||||
- name: Backup attachments and LFS
|
||||
community.general.archive:
|
||||
path:
|
||||
- "{{ forgejo_data_path }}/attachments"
|
||||
- "{{ forgejo_data_path }}/lfs"
|
||||
- "{{ forgejo_data_path }}/avatars"
|
||||
dest: "{{ forgejo_backup_path }}/data-{{ backup_timestamp }}.tar.gz"
|
||||
format: gz
|
||||
|
||||
- name: Create backup manifest
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ forgejo_backup_path }}/manifest-{{ backup_timestamp }}.json"
|
||||
content: |
|
||||
{
|
||||
"timestamp": "{{ ansible_date_time.iso8601 }}",
|
||||
"version": "{{ forgejo_version }}",
|
||||
"hostname": "{{ ansible_hostname }}",
|
||||
"database": "{{ forgejo_db_type }}",
|
||||
"files": {
|
||||
"database": "database-{{ backup_timestamp }}.sql.gz",
|
||||
"repositories": "repositories-{{ backup_timestamp }}.tar.gz",
|
||||
"config": "config-{{ backup_timestamp }}.tar.gz",
|
||||
"data": "data-{{ backup_timestamp }}.tar.gz"
|
||||
},
|
||||
"sizes": {}
|
||||
}
|
||||
mode: '0644'
|
||||
|
||||
- name: Get backup file sizes
|
||||
ansible.builtin.stat:
|
||||
path: "{{ forgejo_backup_path }}/{{ item }}"
|
||||
register: backup_files
|
||||
loop:
|
||||
- "database-{{ backup_timestamp }}.sql.gz"
|
||||
- "repositories-{{ backup_timestamp }}.tar.gz"
|
||||
- "config-{{ backup_timestamp }}.tar.gz"
|
||||
- "data-{{ backup_timestamp }}.tar.gz"
|
||||
|
||||
- name: Display backup sizes
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item.item }}: {{ (item.stat.size / 1024 / 1024) | round(2) }} MB"
|
||||
loop: "{{ backup_files.results }}"
|
||||
when: item.stat.exists
|
||||
|
||||
- name: Upload to S3
|
||||
when: upload_to_s3 and forgejo_enable_s3
|
||||
block:
|
||||
- name: Install AWS CLI
|
||||
ansible.builtin.pip:
|
||||
name: awscli
|
||||
state: present
|
||||
|
||||
- name: Upload database backup to S3
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
aws s3 cp {{ forgejo_backup_path }}/database-{{ backup_timestamp }}.sql.gz
|
||||
s3://{{ forgejo_backup_s3_bucket }}/backups/database-{{ backup_timestamp }}.sql.gz
|
||||
--endpoint-url {{ forgejo_s3_endpoint }}
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID: "{{ forgejo_s3_access_key }}"
|
||||
AWS_SECRET_ACCESS_KEY: "{{ forgejo_s3_secret_key }}"
|
||||
no_log: yes
|
||||
|
||||
- name: Upload repositories backup to S3
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
aws s3 cp {{ forgejo_backup_path }}/repositories-{{ backup_timestamp }}.tar.gz
|
||||
s3://{{ forgejo_backup_s3_bucket }}/backups/repositories-{{ 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 }}"
|
||||
no_log: yes
|
||||
|
||||
- name: Upload config backup to S3
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
aws s3 cp {{ forgejo_backup_path }}/config-{{ backup_timestamp }}.tar.gz
|
||||
s3://{{ forgejo_backup_s3_bucket }}/backups/config-{{ 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 }}"
|
||||
no_log: yes
|
||||
|
||||
- name: Upload manifest to S3
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
aws s3 cp {{ forgejo_backup_path }}/manifest-{{ backup_timestamp }}.json
|
||||
s3://{{ forgejo_backup_s3_bucket }}/backups/manifest-{{ backup_timestamp }}.json
|
||||
--endpoint-url {{ forgejo_s3_endpoint }}
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID: "{{ forgejo_s3_access_key }}"
|
||||
AWS_SECRET_ACCESS_KEY: "{{ forgejo_s3_secret_key }}"
|
||||
no_log: yes
|
||||
|
||||
- name: Clean up old backups
|
||||
ansible.builtin.shell: |
|
||||
find {{ forgejo_backup_path }} -name "*.tar.gz" -o -name "*.sql.gz" -o -name "*.json" | \
|
||||
grep -E "[0-9]{8}T[0-9]{6}" | \
|
||||
sort -r | \
|
||||
tail -n +{{ (forgejo_backup_retention_days | int * 4) + 1 }} | \
|
||||
xargs -r rm -f
|
||||
args:
|
||||
executable: /bin/bash
|
||||
when: forgejo_backup_retention_days is defined
|
||||
|
||||
post_tasks:
|
||||
- name: Calculate total backup size
|
||||
ansible.builtin.shell: |
|
||||
du -sh {{ forgejo_backup_path }} | cut -f1
|
||||
register: total_backup_size
|
||||
changed_when: false
|
||||
|
||||
- name: Display completion message
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Backup Complete!
|
||||
========================================
|
||||
|
||||
Timestamp: {{ backup_timestamp }}
|
||||
Location: {{ forgejo_backup_path }}
|
||||
Total size: {{ total_backup_size.stdout }}
|
||||
|
||||
Files created:
|
||||
- database-{{ backup_timestamp }}.sql.gz
|
||||
- repositories-{{ backup_timestamp }}.tar.gz
|
||||
- config-{{ backup_timestamp }}.tar.gz
|
||||
- data-{{ backup_timestamp }}.tar.gz
|
||||
- manifest-{{ backup_timestamp }}.json
|
||||
|
||||
{% if upload_to_s3 %}
|
||||
Uploaded to S3: {{ forgejo_backup_s3_bucket }}/backups/
|
||||
{% endif %}
|
||||
|
||||
Retention: {{ forgejo_backup_retention_days }} days
|
||||
========================================
|
||||
122
ansible/playbooks/deploy.yml
Normal file
122
ansible/playbooks/deploy.yml
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
# Deploy Forgejo Git Forge
|
||||
# This playbook deploys a complete Forgejo instance with PostgreSQL, Redis, Nginx, and SSL
|
||||
|
||||
- name: Deploy Forgejo
|
||||
hosts: forgejo
|
||||
become: yes
|
||||
gather_facts: yes
|
||||
|
||||
vars_files:
|
||||
- vars/main.yml
|
||||
- vars/secrets.yml # Ansible Vault encrypted
|
||||
|
||||
pre_tasks:
|
||||
- name: Verify Ansible version
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_version.full is version('2.14', '>=')
|
||||
fail_msg: "This playbook requires Ansible 2.14 or higher"
|
||||
success_msg: "Ansible version is compatible"
|
||||
|
||||
- name: Gather system facts
|
||||
ansible.builtin.setup:
|
||||
|
||||
- name: Check system requirements
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_memtotal_mb >= 3500
|
||||
- ansible_processor_vcpus >= 2
|
||||
fail_msg: "System does not meet minimum requirements (4GB RAM, 2 vCPUs)"
|
||||
success_msg: "System meets requirements"
|
||||
|
||||
- name: Display deployment information
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
Deploying Forgejo {{ forgejo_version }}
|
||||
Domain: {{ forgejo_domain }}
|
||||
Database: {{ forgejo_db_type }}
|
||||
HTTPS: {{ forgejo_enable_letsencrypt }}
|
||||
S3: {{ forgejo_enable_s3 }}
|
||||
|
||||
roles:
|
||||
- role: forgejo
|
||||
tags: ['forgejo']
|
||||
|
||||
post_tasks:
|
||||
- name: Display completion message
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Forgejo Deployment Complete!
|
||||
========================================
|
||||
|
||||
Access your Forgejo instance at:
|
||||
{{ forgejo_protocol }}://{{ forgejo_domain }}
|
||||
|
||||
SSH clone URL:
|
||||
git@{{ forgejo_domain }}:{{ forgejo_ssh_port }}
|
||||
|
||||
Admin credentials (if first install):
|
||||
Username: {{ forgejo_admin_username }}
|
||||
Password: (set in vault)
|
||||
|
||||
Next steps:
|
||||
1. Visit the web interface and complete setup
|
||||
2. Configure OAuth/LDAP if needed
|
||||
3. Set up CI/CD with Forgejo Actions
|
||||
4. Configure webhooks for integrations
|
||||
|
||||
Backup location: {{ forgejo_backup_path }}
|
||||
Logs: {{ forgejo_data_path }}/gitea/log
|
||||
|
||||
========================================
|
||||
|
||||
- name: Verify Forgejo is running
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:{{ forgejo_http_port }}"
|
||||
status_code: 200
|
||||
register: health_check
|
||||
until: health_check.status == 200
|
||||
retries: 5
|
||||
delay: 3
|
||||
|
||||
- name: Create deployment summary file
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ forgejo_base_path }}/DEPLOYMENT_INFO.txt"
|
||||
content: |
|
||||
Forgejo Deployment Information
|
||||
==============================
|
||||
|
||||
Deployment Date: {{ ansible_date_time.iso8601 }}
|
||||
Forgejo Version: {{ forgejo_version }}
|
||||
Ansible User: {{ ansible_user }}
|
||||
|
||||
Server Details:
|
||||
- Hostname: {{ ansible_hostname }}
|
||||
- IP Address: {{ ansible_default_ipv4.address }}
|
||||
- OS: {{ ansible_distribution }} {{ ansible_distribution_version }}
|
||||
- RAM: {{ ansible_memtotal_mb }} MB
|
||||
- CPUs: {{ ansible_processor_vcpus }}
|
||||
|
||||
Configuration:
|
||||
- Domain: {{ forgejo_domain }}
|
||||
- HTTP Port: {{ forgejo_http_port }}
|
||||
- SSH Port: {{ forgejo_ssh_port }}
|
||||
- Database: {{ forgejo_db_type }}
|
||||
- Redis: {{ forgejo_use_redis }}
|
||||
- LFS: {{ forgejo_enable_lfs }}
|
||||
|
||||
Paths:
|
||||
- Base: {{ forgejo_base_path }}
|
||||
- Data: {{ forgejo_data_path }}
|
||||
- Config: {{ forgejo_config_path }}
|
||||
- Backups: {{ forgejo_backup_path }}
|
||||
|
||||
Maintenance Commands:
|
||||
- Restart: docker compose -f {{ forgejo_base_path }}/docker-compose.yml restart
|
||||
- Logs: docker logs forgejo
|
||||
- Backup: /usr/local/bin/forgejo_backup.sh
|
||||
- Update: docker compose -f {{ forgejo_base_path }}/docker-compose.yml pull && docker compose up -d
|
||||
mode: '0644'
|
||||
become: yes
|
||||
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.
|
||||
========================================
|
||||
133
ansible/playbooks/update.yml
Normal file
133
ansible/playbooks/update.yml
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
---
|
||||
# Update Forgejo to latest version
|
||||
# This playbook safely updates Forgejo with automatic backup
|
||||
|
||||
- name: Update Forgejo
|
||||
hosts: forgejo
|
||||
become: yes
|
||||
gather_facts: yes
|
||||
|
||||
vars_files:
|
||||
- vars/main.yml
|
||||
- vars/secrets.yml
|
||||
|
||||
vars:
|
||||
backup_before_update: true
|
||||
skip_backup: false # Override with --extra-vars "skip_backup=true"
|
||||
|
||||
pre_tasks:
|
||||
- name: Display update information
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
Updating Forgejo from {{ forgejo_version }}
|
||||
Backup will be created: {{ backup_before_update and not skip_backup }}
|
||||
|
||||
- name: Check current Forgejo version
|
||||
ansible.builtin.command:
|
||||
cmd: docker exec forgejo forgejo --version
|
||||
register: current_version
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Display current version
|
||||
ansible.builtin.debug:
|
||||
msg: "Current version: {{ current_version.stdout if current_version.rc == 0 else 'Unable to determine' }}"
|
||||
|
||||
tasks:
|
||||
- name: Create pre-update backup
|
||||
when: backup_before_update and not skip_backup
|
||||
block:
|
||||
- name: Run backup script
|
||||
ansible.builtin.command:
|
||||
cmd: /usr/local/bin/forgejo_backup.sh
|
||||
register: backup_result
|
||||
|
||||
- name: Display backup result
|
||||
ansible.builtin.debug:
|
||||
msg: "Backup completed: {{ backup_result.stdout_lines[-1] if backup_result.stdout_lines else 'No output' }}"
|
||||
|
||||
- name: Stop Forgejo service
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ forgejo_base_path }}"
|
||||
state: stopped
|
||||
|
||||
- name: Pull latest Forgejo image
|
||||
community.docker.docker_image:
|
||||
name: "{{ forgejo_docker_image }}:{{ forgejo_version }}"
|
||||
source: pull
|
||||
force_source: yes
|
||||
|
||||
- name: Update Docker Compose file if needed
|
||||
ansible.builtin.template:
|
||||
src: ../roles/forgejo/templates/docker-compose.yml.j2
|
||||
dest: "{{ forgejo_base_path }}/docker-compose.yml"
|
||||
owner: "{{ forgejo_user }}"
|
||||
group: "{{ forgejo_group }}"
|
||||
mode: '0640'
|
||||
|
||||
- name: Start Forgejo service
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ forgejo_base_path }}"
|
||||
state: present
|
||||
pull: always
|
||||
|
||||
- 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: Check updated version
|
||||
ansible.builtin.command:
|
||||
cmd: docker exec forgejo forgejo --version
|
||||
register: updated_version
|
||||
changed_when: false
|
||||
|
||||
- name: Display updated version
|
||||
ansible.builtin.debug:
|
||||
msg: "Updated version: {{ updated_version.stdout }}"
|
||||
|
||||
- name: Run database migrations
|
||||
ansible.builtin.command:
|
||||
cmd: docker exec forgejo forgejo migrate
|
||||
register: migrate_result
|
||||
changed_when: "'No migration needed' not in migrate_result.stdout"
|
||||
|
||||
- name: Display migration result
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ migrate_result.stdout_lines }}"
|
||||
|
||||
post_tasks:
|
||||
- name: Verify Forgejo health
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:{{ forgejo_http_port }}/api/healthz"
|
||||
status_code: 200
|
||||
return_content: yes
|
||||
register: health
|
||||
|
||||
- name: Display health status
|
||||
ansible.builtin.debug:
|
||||
msg: "Forgejo health check: {{ health.content }}"
|
||||
|
||||
- name: Update deployment info
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ forgejo_base_path }}/DEPLOYMENT_INFO.txt"
|
||||
regexp: '^Last Update:'
|
||||
line: "Last Update: {{ ansible_date_time.iso8601 }} - {{ forgejo_version }}"
|
||||
insertafter: '^Deployment Date:'
|
||||
|
||||
- name: Display completion message
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Forgejo Update Complete!
|
||||
========================================
|
||||
|
||||
Previous version: {{ current_version.stdout if current_version.rc == 0 else 'Unknown' }}
|
||||
Current version: {{ updated_version.stdout }}
|
||||
|
||||
The service is running and healthy.
|
||||
========================================
|
||||
64
ansible/playbooks/vars/main.yml
Normal file
64
ansible/playbooks/vars/main.yml
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
# Main variables for Forgejo deployment
|
||||
# NOTE: Domain-specific settings should be in inventory/production/hosts.yml
|
||||
# Variables here are lower-priority defaults only.
|
||||
|
||||
# Forgejo version (can be overridden in inventory)
|
||||
# forgejo_version: "9.0.2"
|
||||
|
||||
# Protocol for public URLs (https recommended)
|
||||
forgejo_protocol: https
|
||||
|
||||
# System configuration
|
||||
forgejo_user: git
|
||||
forgejo_group: git
|
||||
forgejo_uid: 1100
|
||||
forgejo_gid: 1100
|
||||
|
||||
# Installation paths
|
||||
forgejo_base_path: /opt/forgejo
|
||||
forgejo_data_path: "{{ forgejo_base_path }}/data"
|
||||
forgejo_config_path: "{{ forgejo_base_path }}/config"
|
||||
|
||||
# Network ports
|
||||
forgejo_http_port: 3000
|
||||
forgejo_ssh_port: 2222
|
||||
|
||||
# Database configuration
|
||||
forgejo_db_type: postgres
|
||||
forgejo_db_host: localhost
|
||||
forgejo_db_port: 5432
|
||||
forgejo_db_name: forgejo
|
||||
forgejo_db_user: forgejo
|
||||
|
||||
# Redis configuration
|
||||
forgejo_use_redis: true
|
||||
redis_host: localhost
|
||||
redis_port: 6379
|
||||
|
||||
# SSL/TLS configuration
|
||||
forgejo_enable_letsencrypt: true
|
||||
letsencrypt_email: "admin@{{ forgejo_domain }}"
|
||||
|
||||
# Features (can be overridden in inventory)
|
||||
forgejo_enable_lfs: true
|
||||
forgejo_enable_2fa: true
|
||||
# forgejo_disable_registration - set in inventory
|
||||
# forgejo_require_signin_view - set in inventory
|
||||
|
||||
# Backup configuration
|
||||
forgejo_enable_backups: true
|
||||
forgejo_backup_schedule: "0 2 * * *"
|
||||
forgejo_backup_retention_days: 30
|
||||
|
||||
# Monitoring
|
||||
forgejo_enable_prometheus: false
|
||||
|
||||
# Email configuration
|
||||
forgejo_enable_email: false
|
||||
|
||||
# S3 configuration
|
||||
forgejo_enable_s3: false
|
||||
|
||||
# Security
|
||||
forgejo_log_level: Info
|
||||
40
ansible/playbooks/vars/secrets.yml.example
Normal file
40
ansible/playbooks/vars/secrets.yml.example
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
# Ansible Vault Encrypted Secrets
|
||||
#
|
||||
# IMPORTANT: Do NOT commit secrets.yml to git, even if encrypted!
|
||||
# The .gitignore is configured to exclude it, but always verify.
|
||||
#
|
||||
# To set up:
|
||||
# 1. cp secrets.yml.example secrets.yml
|
||||
# 2. Edit secrets.yml with your actual values
|
||||
# 3. ansible-vault encrypt secrets.yml
|
||||
# 4. Verify: git status should NOT show secrets.yml
|
||||
#
|
||||
# To edit encrypted secrets: ansible-vault edit secrets.yml
|
||||
|
||||
# Database passwords
|
||||
vault_forgejo_db_password: "CHANGE_ME_STRONG_PASSWORD_HERE"
|
||||
|
||||
# Admin account
|
||||
vault_forgejo_admin_password: "CHANGE_ME_ADMIN_PASSWORD_HERE"
|
||||
|
||||
# Secret keys (generate with: openssl rand -base64 32)
|
||||
vault_forgejo_secret_key: "CHANGE_ME_SECRET_KEY_64_CHARS_MINIMUM_XXXXXXXXXXXXXXXXX"
|
||||
vault_forgejo_internal_token: "CHANGE_ME_INTERNAL_TOKEN_XXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
vault_forgejo_jwt_secret: "CHANGE_ME_JWT_SECRET_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
|
||||
# Metrics token (if prometheus enabled)
|
||||
vault_forgejo_metrics_token: "CHANGE_ME_METRICS_TOKEN_XXXXXXXXX"
|
||||
|
||||
# Email password (if email enabled)
|
||||
vault_email_password: ""
|
||||
|
||||
# S3 credentials (if S3 enabled)
|
||||
vault_s3_access_key: ""
|
||||
vault_s3_secret_key: ""
|
||||
|
||||
# Notes:
|
||||
# - Generate strong passwords: openssl rand -base64 32
|
||||
# - Never commit unencrypted secrets to version control
|
||||
# - Keep a secure backup of your vault password
|
||||
# - Rotate secrets regularly
|
||||
Loading…
Add table
Add a link
Reference in a new issue