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

- 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:
2025-11-09 14:46:15 +01:00
parent 85c369e846
commit 36ef2a1e2c
1366 changed files with 104925 additions and 28719 deletions

View File

@@ -0,0 +1,131 @@
---
# Update Gitea Configuration (app.ini)
- name: Verify Gitea container exists
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml ps {{ gitea_container_name }} | grep -q "{{ gitea_container_name }}"
register: gitea_exists
changed_when: false
failed_when: false
- name: Fail if Gitea container does not exist
ansible.builtin.fail:
msg: "Gitea container does not exist. Please deploy Gitea stack first."
when: gitea_exists.rc != 0
- name: Get database configuration from environment
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} env | grep -E "^GITEA__database__" || true
register: gitea_db_env
changed_when: false
failed_when: false
- name: Parse database configuration
ansible.builtin.set_fact:
gitea_db_type: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__DB_TYPE=([^\n]+)', '\\1') or ['postgres']) | first }}"
gitea_db_host: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__HOST=([^\n]+)', '\\1') or ['postgres:5432']) | first }}"
gitea_db_name: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__NAME=([^\n]+)', '\\1') or ['gitea']) | first }}"
gitea_db_user: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__USER=([^\n]+)', '\\1') or ['gitea']) | first }}"
gitea_db_passwd: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__PASSWD=([^\n]+)', '\\1') or ['gitea_password']) | first }}"
- name: Get Gitea server configuration from environment
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} env | grep -E "^GITEA__server__" || true
register: gitea_server_env
changed_when: false
failed_when: false
- name: Parse server configuration
ansible.builtin.set_fact:
gitea_domain_parsed: "{{ (gitea_server_env.stdout | default('') | regex_search('GITEA__server__DOMAIN=([^\n]+)', '\\1') or [gitea_domain | default('git.michaelschiemer.de')]) | first }}"
ssh_port_parsed: "{{ (gitea_server_env.stdout | default('') | regex_search('GITEA__server__SSH_PORT=([^\n]+)', '\\1') or ['2222']) | first }}"
- name: Set final configuration variables
ansible.builtin.set_fact:
gitea_domain: "{{ gitea_domain_parsed }}"
ssh_port: "{{ ssh_port_parsed }}"
ssh_listen_port: "{{ ssh_port_parsed }}"
- name: Extract database host and port
ansible.builtin.set_fact:
gitea_db_hostname: "{{ gitea_db_host.split(':')[0] }}"
gitea_db_port: "{{ (gitea_db_host.split(':')[1]) | default('5432') }}"
- name: Set Redis password
ansible.builtin.set_fact:
redis_password: "{{ vault_gitea_redis_password | default(vault_redis_password | default('gitea_redis_password')) }}"
- name: Generate app.ini from template
ansible.builtin.template:
src: "{{ gitea_app_ini_template | default('../../templates/gitea-app.ini.j2') }}"
dest: "{{ gitea_app_ini_path }}"
mode: '0644'
vars:
postgres_db: "{{ gitea_db_name }}"
postgres_user: "{{ gitea_db_user }}"
postgres_password: "{{ gitea_db_passwd }}"
gitea_domain: "{{ gitea_domain }}"
ssh_port: "{{ ssh_port }}"
ssh_listen_port: "{{ ssh_listen_port }}"
disable_registration: true
redis_password: "{{ redis_password }}"
- name: Copy app.ini to Gitea container
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml cp {{ gitea_app_ini_path }} {{ gitea_container_name }}:{{ gitea_app_ini_container_path }}
ignore_errors: yes
- name: Wait for container to be ready for exec
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} true
register: container_ready
until: container_ready.rc == 0
retries: "{{ gitea_config_retries | default(30) }}"
delay: "{{ gitea_config_delay | default(2) }}"
changed_when: false
- name: Set correct permissions on app.ini in container
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T --user git {{ gitea_container_name }} chown 1000:1000 {{ gitea_app_ini_container_path }} && \
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T --user git {{ gitea_container_name }} chmod 644 {{ gitea_app_ini_container_path }}
- name: Restart Gitea container
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml restart {{ gitea_container_name }}
register: gitea_restart
changed_when: gitea_restart.rc == 0
notify: wait for gitea
- name: Wait for Gitea to be ready after restart
ansible.builtin.uri:
url: "{{ gitea_url }}/api/healthz"
method: GET
status_code: [200]
validate_certs: false
timeout: "{{ gitea_health_check_timeout | default(10) }}"
register: gitea_health_after_restart
until: gitea_health_after_restart.status == 200
retries: "{{ gitea_restart_retries | default(30) }}"
delay: "{{ gitea_restart_delay | default(5) }}"
when: gitea_restart.changed | default(false)
changed_when: false
- name: Display success message
ansible.builtin.debug:
msg: |
========================================
Gitea Configuration Update Complete
========================================
Gitea configuration has been updated successfully!
Changes applied:
- Redis cache enabled (persistent, survives container restarts)
- Redis sessions enabled (better performance and scalability)
- Redis queue enabled (persistent job processing)
- Database connection pooling configured
- Connection limits set to prevent "Connection reset by peer" errors
Gitea should now be more stable and perform better with Redis.
========================================
when: gitea_show_status | default(true) | bool

View File

@@ -0,0 +1,258 @@
---
# Setup Gitea Repository
- name: Set repository variables from parameters
ansible.builtin.set_fact:
repo_name: "{{ gitea_repo_name | default('michaelschiemer') }}"
repo_owner: "{{ gitea_repo_owner | default('michael') }}"
repo_private: "{{ gitea_repo_private | default(false) | bool }}"
repo_description: "{{ gitea_repo_description | default('Main application repository') }}"
repo_auto_init: "{{ gitea_repo_auto_init | default(false) | bool }}"
configure_git_remote: "{{ gitea_configure_git_remote | default(true) | bool }}"
git_repo_path: "{{ gitea_git_repo_path | default('/home/michael/dev/michaelschiemer') }}"
- name: Verify Gitea is accessible
ansible.builtin.uri:
url: "{{ gitea_url }}"
method: GET
status_code: [200, 302, 502]
validate_certs: false
timeout: "{{ gitea_health_check_timeout | default(10) }}"
register: gitea_health
failed_when: false
- name: Debug Gitea health status
ansible.builtin.debug:
msg: "Gitea health check returned status: {{ gitea_health.status }}"
when: gitea_show_status | default(true) | bool
- name: Fail if Gitea is not accessible
ansible.builtin.fail:
msg: "Gitea is not accessible at {{ gitea_url }}. Status: {{ gitea_health.status }}. Please check if Gitea is running."
when: gitea_health.status not in [200, 302, 502]
- name: Check if API token exists in vault
ansible.builtin.set_fact:
has_vault_token: "{{ vault_git_token is defined and vault_git_token | length > 0 }}"
no_log: true
- name: Get or create Gitea API token
ansible.builtin.uri:
url: "{{ gitea_url }}/api/v1/users/{{ gitea_admin_username }}/tokens"
method: POST
user: "{{ gitea_admin_username }}"
password: "{{ gitea_admin_password }}"
body_format: json
body:
name: "ansible-repo-setup-{{ ansible_date_time.epoch }}"
scopes:
- write:repository
- read:repository
- admin:repo
status_code: [201, 400, 401, 502]
validate_certs: false
force_basic_auth: yes
register: api_token_result
failed_when: false
when: not has_vault_token
no_log: true
- name: Extract API token from response
ansible.builtin.set_fact:
gitea_api_token: "{{ api_token_result.json.sha1 | default('') }}"
when:
- not has_vault_token
- api_token_result.status == 201
- api_token_result.json.sha1 is defined
no_log: true
- name: Use existing API token from vault
ansible.builtin.set_fact:
gitea_api_token: "{{ vault_git_token }}"
when: has_vault_token
no_log: true
- name: Set flag to use basic auth if token creation failed
ansible.builtin.set_fact:
use_basic_auth: "{{ gitea_api_token | default('') | length == 0 }}"
no_log: true
- name: Fail if no authentication method available
ansible.builtin.fail:
msg: "Could not create or retrieve Gitea API token, and admin credentials are not available. Please create a token manually or set vault_git_token in vault."
when:
- use_basic_auth | bool
- gitea_admin_password | default('') | length == 0
- name: Initialize repo_check variable
ansible.builtin.set_fact:
repo_check: {"status": 0}
when: repo_check is not defined
- name: Check if repository already exists (with token)
ansible.builtin.uri:
url: "{{ gitea_url }}/api/v1/repos/{{ repo_owner }}/{{ repo_name }}"
method: GET
headers:
Authorization: "token {{ gitea_api_token }}"
status_code: [200, 404, 502]
validate_certs: false
timeout: "{{ gitea_health_check_timeout | default(10) }}"
register: repo_check_token
when: not use_basic_auth
failed_when: false
- name: Set repo_check from token result
ansible.builtin.set_fact:
repo_check: "{{ repo_check_token }}"
when:
- not use_basic_auth
- repo_check_token is defined
- name: Check if repository already exists (with basic auth)
ansible.builtin.uri:
url: "{{ gitea_url }}/api/v1/repos/{{ repo_owner }}/{{ repo_name }}"
method: GET
user: "{{ gitea_admin_username }}"
password: "{{ gitea_admin_password }}"
status_code: [200, 404, 502]
validate_certs: false
force_basic_auth: yes
timeout: "{{ gitea_health_check_timeout | default(10) }}"
register: repo_check_basic
when: use_basic_auth
failed_when: false
no_log: true
- name: Set repo_check from basic auth result
ansible.builtin.set_fact:
repo_check: "{{ repo_check_basic }}"
when:
- use_basic_auth
- repo_check_basic is defined
- name: Debug repo_check status
ansible.builtin.debug:
msg: "Repository check - Status: {{ repo_check.status | default('undefined') }}, use_basic_auth: {{ use_basic_auth | default('undefined') }}"
when: gitea_show_status | default(true) | bool
- name: Create repository in Gitea (with token)
ansible.builtin.uri:
url: "{{ gitea_url }}/api/v1/user/repos"
method: POST
headers:
Authorization: "token {{ gitea_api_token }}"
Content-Type: "application/json"
body_format: json
body:
name: "{{ repo_name }}"
description: "{{ repo_description }}"
private: "{{ repo_private }}"
auto_init: "{{ repo_auto_init }}"
status_code: [201, 409, 502]
validate_certs: false
timeout: "{{ gitea_health_check_timeout | default(10) }}"
register: repo_create_result
when:
- (repo_check.status | default(0)) in [404, 502, 0] or (gitea_force_create_repo | default(false) | bool)
- not use_basic_auth
failed_when: false
- name: Create repository in Gitea (with basic auth)
ansible.builtin.uri:
url: "{{ gitea_url }}/api/v1/user/repos"
method: POST
user: "{{ gitea_admin_username }}"
password: "{{ gitea_admin_password }}"
body_format: json
body:
name: "{{ repo_name }}"
description: "{{ repo_description }}"
private: "{{ repo_private }}"
auto_init: "{{ repo_auto_init }}"
status_code: [201, 409]
validate_certs: false
force_basic_auth: yes
timeout: "{{ gitea_health_check_timeout | default(10) }}"
register: repo_create_result
when:
- ((repo_check.status | default(0)) != 200) or (gitea_force_create_repo | default(false) | bool)
- use_basic_auth
no_log: true
- name: Debug repository creation result
ansible.builtin.debug:
msg: "Repository creation - Status: {{ repo_create_result.status | default('undefined') }}, Response: {{ repo_create_result.json | default('no json') }}"
when:
- repo_create_result is defined
- gitea_show_status | default(true) | bool
failed_when: false
- name: Display repository creation result
ansible.builtin.debug:
msg: "Repository {{ repo_owner }}/{{ repo_name }} already exists or was created successfully"
when: repo_check.status | default(0) == 200 or (repo_create_result is defined and repo_create_result.status | default(0) == 201)
- name: Get repository clone URL
ansible.builtin.set_fact:
repo_clone_url: "{{ gitea_url | replace('https://', '') | replace('http://', '') }}/{{ repo_owner }}/{{ repo_name }}.git"
repo_https_url: "https://{{ gitea_admin_username }}:{{ gitea_api_token }}@{{ gitea_url | replace('https://', '') | replace('http://', '') }}/{{ repo_owner }}/{{ repo_name }}.git"
- name: Check if Git repository exists locally
ansible.builtin.stat:
path: "{{ git_repo_path }}/.git"
register: git_repo_exists
when: configure_git_remote | bool
delegate_to: localhost
run_once: true
- name: Configure Git remote (local)
ansible.builtin.command: >
git remote set-url origin {{ repo_clone_url }}
args:
chdir: "{{ git_repo_path }}"
register: git_remote_result
when:
- configure_git_remote | bool
- git_repo_path is defined
- git_repo_exists.stat.exists
delegate_to: localhost
run_once: true
changed_when: git_remote_result.rc == 0
failed_when: false
- name: Add Git remote if it doesn't exist
ansible.builtin.command: >
git remote add origin {{ repo_clone_url }}
args:
chdir: "{{ git_repo_path }}"
register: git_remote_add_result
when:
- configure_git_remote | bool
- git_repo_path is defined
- git_repo_exists.stat.exists
- git_remote_result.rc != 0
delegate_to: localhost
run_once: true
changed_when: git_remote_add_result.rc == 0
failed_when: false
- name: Display success message
ansible.builtin.debug:
msg:
- "========================================"
- "✅ Repository created successfully!"
- "========================================"
- "Repository URL: {{ gitea_url }}/{{ repo_owner }}/{{ repo_name }}"
- "Clone URL: {{ repo_clone_url }}"
- ""
- "Next steps:"
- "1. Push your code: git push -u origin staging"
- "2. Monitor pipeline: {{ gitea_url }}/{{ repo_owner }}/{{ repo_name }}/actions"
- ""
- "Note: If you need to push, you may need to authenticate with:"
- " Username: {{ gitea_admin_username }}"
- " Password: (use vault_gitea_admin_password or create a Personal Access Token)"
- "========================================"
when: gitea_show_status | default(true) | bool

View File

@@ -0,0 +1,329 @@
---
# Gitea Runner Management Tasks
# Supports both fix (diagnose) and register actions
- name: Check if Gitea runner directory exists
ansible.builtin.stat:
path: "{{ gitea_runner_path }}"
register: runner_dir_exists
- name: Fail if runner directory does not exist
ansible.builtin.fail:
msg: "Gitea runner directory not found at {{ gitea_runner_path }}"
when: not runner_dir_exists.stat.exists
- name: Check if runner container is running
ansible.builtin.shell: |
docker ps --format json | jq -r 'select(.Names == "{{ gitea_runner_container_name }}") | .State'
register: runner_container_state
changed_when: false
failed_when: false
- name: Display runner container status
ansible.builtin.debug:
msg: |
Runner Container Status: {{ runner_container_state.stdout | default('NOT RUNNING') }}
when: gitea_runner_show_status | default(true) | bool
- name: Check if .runner file exists
ansible.builtin.stat:
path: "{{ gitea_runner_path }}/data/.runner"
register: runner_file_exists
- name: Read .runner file content (if exists)
ansible.builtin.slurp:
src: "{{ gitea_runner_path }}/data/.runner"
register: runner_file_content
when: runner_file_exists.stat.exists
changed_when: false
- name: Display .runner file content
ansible.builtin.debug:
msg: |
Runner Registration File Content:
{{ runner_file_content.content | b64decode | default('File not found') }}
when:
- runner_file_exists.stat.exists
- gitea_runner_show_status | default(true) | bool
- name: Check for GitHub URLs in .runner file
ansible.builtin.shell: |
grep -i "github.com" "{{ gitea_runner_path }}/data/.runner" 2>/dev/null || echo "NO_GITHUB_URLS"
register: github_urls_check
when: runner_file_exists.stat.exists
changed_when: false
failed_when: false
- name: Display GitHub URLs check result
ansible.builtin.debug:
msg: |
GitHub URLs in .runner file: {{ github_urls_check.stdout }}
when: gitea_runner_show_status | default(true) | bool
- name: Check runner logs for incorrect URLs
ansible.builtin.shell: |
docker logs {{ gitea_runner_container_name }} --tail=100 2>&1 | grep -E "(github.com|instance|repo)" || echo "NO_MATCHES"
register: runner_logs_check
changed_when: false
failed_when: false
- name: Display runner logs analysis
ansible.builtin.debug:
msg: |
Runner Logs Analysis (last 100 lines):
{{ runner_logs_check.stdout }}
when: gitea_runner_show_status | default(true) | bool
- name: Check .env file for GITEA_INSTANCE_URL
ansible.builtin.shell: |
grep "^GITEA_INSTANCE_URL=" "{{ gitea_runner_path }}/.env" 2>/dev/null || echo "NOT_FOUND"
register: env_instance_url
changed_when: false
failed_when: false
- name: Display GITEA_INSTANCE_URL from .env
ansible.builtin.debug:
msg: |
GITEA_INSTANCE_URL in .env: {{ env_instance_url.stdout }}
when: gitea_runner_show_status | default(true) | bool
- name: Check if .env has correct Gitea URL
ansible.builtin.set_fact:
env_has_correct_url: "{{ env_instance_url.stdout is defined and gitea_instance_url in env_instance_url.stdout }}"
- name: Check if runner needs re-registration (for fix action)
ansible.builtin.set_fact:
runner_needs_reregistration: >-
{%- if not runner_file_exists.stat.exists -%}
true
{%- elif 'github.com' in (github_urls_check.stdout | default('')) -%}
true
{%- elif not env_has_correct_url -%}
true
{%- else -%}
false
{%- endif -%}
when: gitea_runner_action | default('fix') == 'fix'
- name: Display re-registration decision
ansible.builtin.debug:
msg: |
Runner Re-registration Needed: {{ runner_needs_reregistration | bool }}
Reasons:
- Runner file exists: {{ runner_file_exists.stat.exists }}
- Contains GitHub URLs: {{ 'github.com' in (github_urls_check.stdout | default('')) }}
- .env has correct URL: {{ env_has_correct_url | bool }}
when:
- gitea_runner_action | default('fix') == 'fix'
- gitea_runner_show_status | default(true) | bool
- name: Fail if registration token is not provided (for register action)
ansible.builtin.fail:
msg: "gitea_runner_registration_token must be provided via -e 'gitea_runner_registration_token=<token>'"
when:
- gitea_runner_action | default('fix') == 'register'
- gitea_runner_registration_token | string | trim == ''
- name: Stop runner container before re-registration (fix action)
ansible.builtin.shell: |
cd {{ gitea_runner_path }}
docker compose stop {{ gitea_runner_container_name }}
when:
- gitea_runner_action | default('fix') == 'fix'
- runner_needs_reregistration | bool
register: stop_runner
changed_when: stop_runner.rc == 0
- name: Stop runner container if running (register action)
ansible.builtin.shell: |
cd {{ gitea_runner_path }}
docker compose stop {{ gitea_runner_container_name }}
when: gitea_runner_action | default('fix') == 'register'
register: stop_result
changed_when: stop_result.rc == 0
failed_when: false
- name: Backup existing .runner file
ansible.builtin.copy:
src: "{{ gitea_runner_path }}/data/.runner"
dest: "{{ gitea_runner_path }}/data/.runner.backup.{{ ansible_date_time.epoch }}"
remote_src: yes
when:
- runner_file_exists.stat.exists
- (gitea_runner_action | default('fix') == 'register') or (runner_needs_reregistration | bool)
ignore_errors: yes
- name: Remove existing .runner file
ansible.builtin.file:
path: "{{ gitea_runner_path }}/data/.runner"
state: absent
when:
- (gitea_runner_action | default('fix') == 'register') or (runner_needs_reregistration | bool)
- name: Update .env file with correct GITEA_INSTANCE_URL (fix action)
ansible.builtin.lineinfile:
path: "{{ gitea_runner_path }}/.env"
regexp: '^GITEA_INSTANCE_URL='
line: "GITEA_INSTANCE_URL={{ gitea_instance_url }}"
create: yes
when:
- gitea_runner_action | default('fix') == 'fix'
- runner_needs_reregistration | bool
register: env_updated
- name: Update .env file with correct configuration (register action)
ansible.builtin.lineinfile:
path: "{{ gitea_runner_path }}/.env"
regexp: '^{{ item.key }}='
line: "{{ item.key }}={{ item.value }}"
create: yes
loop:
- { key: 'GITEA_INSTANCE_URL', value: '{{ gitea_instance_url }}' }
- { key: 'GITEA_RUNNER_REGISTRATION_TOKEN', value: '{{ gitea_runner_registration_token }}' }
- { key: 'GITEA_RUNNER_NAME', value: '{{ gitea_runner_name }}' }
- { key: 'GITEA_RUNNER_LABELS', value: '{{ gitea_runner_labels }}' }
when: gitea_runner_action | default('fix') == 'register'
no_log: true
- name: Display instructions for manual re-registration (fix action)
ansible.builtin.debug:
msg: |
========================================
Runner Re-registration Required
========================================
The runner needs to be re-registered with the correct Gitea instance URL.
Steps to re-register:
1. Get a new registration token from Gitea:
{{ gitea_instance_url }}/admin/actions/runners
Click "Create New Runner" and copy the token
2. Update .env file with the token:
GITEA_RUNNER_REGISTRATION_TOKEN=<your-token>
3. Re-register the runner:
cd {{ gitea_runner_path }}
./register.sh
Or use Ansible to set the token and register:
ansible-playbook -i inventory/production.yml \
playbooks/register-gitea-runner.yml \
-e "gitea_runner_registration_token=<your-token>"
========================================
when:
- gitea_runner_action | default('fix') == 'fix'
- runner_needs_reregistration | bool
- gitea_runner_show_status | default(true) | bool
- name: Start runner services (register action)
ansible.builtin.shell: |
cd {{ gitea_runner_path }}
docker compose up -d
when: gitea_runner_action | default('fix') == 'register'
register: start_services
changed_when: start_services.rc == 0
- name: Wait for services to be ready (register action)
ansible.builtin.pause:
seconds: "{{ gitea_runner_wait_seconds | default(5) }}"
when: gitea_runner_action | default('fix') == 'register'
- name: Register runner with correct Gitea instance (register action)
ansible.builtin.shell: |
cd {{ gitea_runner_path }}
docker compose exec -T {{ gitea_runner_container_name }} act_runner register \
--instance "{{ gitea_instance_url }}" \
--token "{{ gitea_runner_registration_token }}" \
--name "{{ gitea_runner_name }}" \
--labels "{{ gitea_runner_labels }}"
when: gitea_runner_action | default('fix') == 'register'
register: register_result
no_log: true
changed_when: register_result.rc == 0
- name: Display registration result (register action)
ansible.builtin.debug:
msg: |
Runner Registration Result:
{{ register_result.stdout | default('No output') }}
when:
- gitea_runner_action | default('fix') == 'register'
- register_result.rc == 0
- gitea_runner_show_status | default(true) | bool
- name: Verify .runner file was created (register action)
ansible.builtin.stat:
path: "{{ gitea_runner_path }}/data/.runner"
register: runner_file_created
when: gitea_runner_action | default('fix') == 'register'
- name: Check .runner file for correct instance URL (register action)
ansible.builtin.shell: |
grep -i "{{ gitea_instance_url }}" "{{ gitea_runner_path }}/data/.runner" 2>/dev/null || echo "URL_NOT_FOUND"
register: runner_url_check
when:
- gitea_runner_action | default('fix') == 'register'
- runner_file_created.stat.exists
changed_when: false
- name: Check .runner file for GitHub URLs (register action)
ansible.builtin.shell: |
grep -i "github.com" "{{ gitea_runner_path }}/data/.runner" 2>/dev/null || echo "NO_GITHUB_URLS"
register: runner_github_check
when:
- gitea_runner_action | default('fix') == 'register'
- runner_file_created.stat.exists
changed_when: false
- name: Display final status (fix action)
ansible.builtin.debug:
msg: |
========================================
Gitea Runner Configuration Status
========================================
Runner Directory: {{ gitea_runner_path }}
Container Running: {{ 'YES' if runner_container_state.stdout == 'running' else 'NO' }}
Runner File Exists: {{ 'YES' if runner_file_exists.stat.exists else 'NO' }}
Contains GitHub URLs: {{ 'YES' if 'github.com' in (github_urls_check.stdout | default('')) else 'NO' }}
.env has correct URL: {{ 'YES' if env_has_correct_url else 'NO' }}
Re-registration Needed: {{ 'YES' if runner_needs_reregistration | bool else 'NO' }}
========================================
{% if not runner_needs_reregistration | bool %}
✅ Runner configuration looks correct!
{% else %}
⚠️ Runner needs to be re-registered with correct Gitea URL
{% endif %}
when:
- gitea_runner_action | default('fix') == 'fix'
- gitea_runner_show_status | default(true) | bool
- name: Display final status (register action)
ansible.builtin.debug:
msg: |
========================================
Gitea Runner Registration Status
========================================
Registration: {{ '✅ SUCCESS' if register_result.rc == 0 else '❌ FAILED' }}
Runner File Created: {{ '✅ YES' if runner_file_created.stat.exists else '❌ NO' }}
Contains Correct URL: {{ '✅ YES' if 'URL_NOT_FOUND' not in runner_url_check.stdout else '❌ NO' }}
Contains GitHub URLs: {{ '❌ YES' if 'NO_GITHUB_URLS' not in runner_github_check.stdout else '✅ NO' }}
========================================
{% if register_result.rc == 0 and runner_file_created.stat.exists %}
✅ Runner registered successfully with {{ gitea_instance_url }}!
Check runner status:
{{ gitea_instance_url }}/admin/actions/runners
{% else %}
❌ Registration failed. Check logs:
docker logs {{ gitea_runner_container_name }}
{% endif %}
when:
- gitea_runner_action | default('fix') == 'register'
- gitea_runner_show_status | default(true) | bool

View File

@@ -0,0 +1,287 @@
---
# Setup Gitea Initial Configuration
- name: Verify Gitea container exists
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml ps {{ gitea_container_name }} | grep -q "{{ gitea_container_name }}"
register: gitea_exists
changed_when: false
failed_when: false
- name: Fail if Gitea container does not exist
ansible.builtin.fail:
msg: "Gitea container does not exist. Please deploy Gitea stack first using: ansible-playbook -i inventory/production.yml playbooks/setup-infrastructure.yml --tags gitea"
when: gitea_exists.rc != 0
- name: Wait for Gitea to be ready
ansible.builtin.uri:
url: "{{ gitea_url }}/api/healthz"
method: GET
status_code: [200, 404]
validate_certs: false
timeout: "{{ gitea_health_check_timeout | default(10) }}"
register: gitea_health
until: gitea_health.status == 200
retries: "{{ gitea_setup_health_retries | default(30) }}"
delay: "{{ gitea_setup_health_delay | default(5) }}"
ignore_errors: yes
changed_when: false
when: not (gitea_force_update_app_ini | default(false) | bool)
- name: Check if Gitea is already configured
ansible.builtin.uri:
url: "{{ gitea_url }}"
method: GET
status_code: [200, 302, 502]
validate_certs: false
timeout: "{{ gitea_health_check_timeout | default(10) }}"
follow_redirects: none
return_content: yes
register: gitea_main_check
changed_when: false
failed_when: false
- name: Check if app.ini exists in container
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} test -f {{ gitea_app_ini_container_path }}
register: gitea_app_ini_exists
changed_when: false
failed_when: false
- name: Check if INSTALL_LOCK is set
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} grep -q "INSTALL_LOCK = true" {{ gitea_app_ini_container_path }} 2>/dev/null || echo "not_set"
register: gitea_install_lock_check
changed_when: false
failed_when: false
when: gitea_app_ini_exists.rc == 0
- name: Determine if Gitea needs setup
ansible.builtin.set_fact:
gitea_needs_setup: "{{ (gitea_force_update_app_ini | default(false) | bool) or ('installation' in (gitea_main_check.content | default('') | lower) or 'initial configuration' in (gitea_main_check.content | default('') | lower)) or (gitea_app_ini_exists.rc != 0) or (gitea_install_lock_check.stdout | default('') | trim == 'not_set') }}"
gitea_already_configured: "{{ not (gitea_force_update_app_ini | default(false) | bool) and 'installation' not in (gitea_main_check.content | default('') | lower) and 'initial configuration' not in (gitea_main_check.content | default('') | lower) and gitea_app_ini_exists.rc == 0 and gitea_install_lock_check.stdout | default('') | trim != 'not_set' }}"
- name: Display setup status
ansible.builtin.debug:
msg: |
Gitea Setup Status:
- Main page status: {{ gitea_main_check.status }}
- app.ini exists: {{ gitea_app_ini_exists.rc == 0 }}
- INSTALL_LOCK set: {{ gitea_install_lock_check.stdout | default('unknown') }}
- Force update: {{ gitea_force_update_app_ini | default(false) }}
- Already configured: {{ gitea_already_configured }}
- Needs setup: {{ gitea_needs_setup }}
when: gitea_show_status | default(true) | bool
- name: Fail if admin password is not set
ansible.builtin.fail:
msg: |
Gitea admin password is not set in vault.
Please set vault_gitea_admin_password in:
- deployment/ansible/secrets/production.vault.yml
To set it, run:
ansible-vault edit secrets/production.vault.yml --vault-password-file secrets/.vault_pass
Then add:
vault_gitea_admin_password: "your-secure-password"
when:
- gitea_needs_setup | bool
- gitea_admin_password | default('') | trim == ''
- name: Get Gitea database configuration from environment
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} env | grep -E "^GITEA__database__" || true
register: gitea_db_env
changed_when: false
failed_when: false
when: gitea_needs_setup | bool
- name: Parse database configuration
ansible.builtin.set_fact:
gitea_db_type: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__DB_TYPE=([^\n]+)', '\\1') or ['postgres']) | first }}"
gitea_db_host: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__HOST=([^\n]+)', '\\1') or ['postgres:5432']) | first }}"
gitea_db_name: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__NAME=([^\n]+)', '\\1') or ['gitea']) | first }}"
gitea_db_user: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__USER=([^\n]+)', '\\1') or ['gitea']) | first }}"
gitea_db_passwd: "{{ (gitea_db_env.stdout | default('') | regex_search('GITEA__database__PASSWD=([^\n]+)', '\\1') or ['gitea_password']) | first }}"
when: gitea_needs_setup | bool
- name: Extract database host and port
ansible.builtin.set_fact:
gitea_db_hostname: "{{ gitea_db_host.split(':')[0] }}"
gitea_db_port: "{{ (gitea_db_host.split(':')[1]) | default('5432') }}"
when: gitea_needs_setup | bool
- name: Get Gitea server configuration from environment
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} env | grep -E "^GITEA__server__" || true
register: gitea_server_env
changed_when: false
failed_when: false
when: gitea_needs_setup | bool
- name: Parse server configuration
ansible.builtin.set_fact:
gitea_domain_config: "{{ (gitea_server_env.stdout | default('') | regex_search('GITEA__server__DOMAIN=([^\n]+)', '\\1') or [gitea_domain]) | first }}"
gitea_root_url: "{{ (gitea_server_env.stdout | default('') | regex_search('GITEA__server__ROOT_URL=([^\n]+)', '\\1') or ['https://' + gitea_domain + '/']) | first }}"
gitea_ssh_domain: "{{ (gitea_server_env.stdout | default('') | regex_search('GITEA__server__SSH_DOMAIN=([^\n]+)', '\\1') or [gitea_domain]) | first }}"
gitea_ssh_port: "{{ (gitea_server_env.stdout | default('') | regex_search('GITEA__server__SSH_PORT=([^\n]+)', '\\1') or ['2222']) | first }}"
when: gitea_needs_setup | bool
- name: Get Gitea service configuration from environment
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} env | grep -E "^GITEA__service__" || true
register: gitea_service_env
changed_when: false
failed_when: false
when: gitea_needs_setup | bool
- name: Parse service configuration
ansible.builtin.set_fact:
gitea_disable_registration: "{{ (gitea_service_env.stdout | default('') | regex_search('GITEA__service__DISABLE_REGISTRATION=([^\n]+)', '\\1') or ['true']) | first | lower }}"
when: gitea_needs_setup | bool
- name: Generate app.ini file
ansible.builtin.template:
src: "{{ gitea_app_ini_template | default('../../templates/gitea-app.ini.j2') }}"
dest: "{{ gitea_app_ini_path }}"
mode: '0644'
vars:
gitea_domain: "{{ gitea_domain_config }}"
postgres_db: "{{ gitea_db_name }}"
postgres_user: "{{ gitea_db_user }}"
postgres_password: "{{ gitea_db_passwd }}"
disable_registration: "{{ gitea_disable_registration == 'true' }}"
ssh_port: "{{ gitea_ssh_port | int }}"
ssh_listen_port: 22
when: gitea_needs_setup | bool
- name: Copy app.ini to Gitea container
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml cp {{ gitea_app_ini_path }} {{ gitea_container_name }}:{{ gitea_app_ini_container_path }}
when: gitea_needs_setup | bool
ignore_errors: yes
- name: Wait for container to be ready for exec
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} true
register: container_ready
until: container_ready.rc == 0
retries: "{{ gitea_config_retries | default(30) }}"
delay: "{{ gitea_config_delay | default(2) }}"
when:
- gitea_needs_setup | bool
- not (gitea_force_update_app_ini | default(false) | bool)
changed_when: false
ignore_errors: yes
- name: Set correct permissions on app.ini in container
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} chown 1000:1000 {{ gitea_app_ini_container_path }} && \
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} chmod 644 {{ gitea_app_ini_container_path }}
when: gitea_needs_setup | bool
ignore_errors: yes
- name: Restart Gitea container
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml restart {{ gitea_container_name }}
when: gitea_needs_setup | bool
register: gitea_restart
changed_when: gitea_restart.rc == 0
notify: wait for gitea
- name: Wait for Gitea to be ready after restart
ansible.builtin.uri:
url: "{{ gitea_url }}/api/healthz"
method: GET
status_code: [200]
validate_certs: false
timeout: "{{ gitea_health_check_timeout | default(10) }}"
register: gitea_health_after_restart
until: gitea_health_after_restart.status == 200
retries: "{{ gitea_restart_retries | default(30) }}"
delay: "{{ gitea_restart_delay | default(5) }}"
when:
- not (gitea_force_update_app_ini | default(false) | bool)
- gitea_restart.changed | default(false)
changed_when: false
ignore_errors: yes
- name: Wait for database to be initialized
ansible.builtin.pause:
seconds: "{{ gitea_setup_db_wait | default(10) }}"
when: gitea_needs_setup | bool
- name: Check if admin user already exists
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T {{ gitea_container_name }} \
gitea admin user list --admin | grep -q "{{ gitea_admin_username }}" || echo "not_found"
register: gitea_admin_exists
changed_when: false
failed_when: false
when: gitea_needs_setup | bool
- name: Create admin user
ansible.builtin.shell: |
docker compose -f {{ gitea_stack_path }}/docker-compose.yml exec -T --user git {{ gitea_container_name }} \
gitea admin user create \
--username "{{ gitea_admin_username }}" \
--password "{{ gitea_admin_password }}" \
--email "{{ gitea_admin_email }}" \
--admin \
--must-change-password=false
register: gitea_admin_create_result
when:
- gitea_needs_setup | bool
- gitea_admin_exists.stdout | default('') | trim == 'not_found'
failed_when: gitea_admin_create_result.rc != 0 and 'already exists' not in (gitea_admin_create_result.stderr | default(''))
no_log: true
- name: Verify Gitea is accessible
ansible.builtin.uri:
url: "{{ gitea_url }}"
method: GET
status_code: [200, 302]
validate_certs: false
timeout: "{{ gitea_health_check_timeout | default(10) }}"
follow_redirects: none
register: gitea_access_check
when: gitea_needs_setup | bool
- name: Display success message
ansible.builtin.debug:
msg: |
========================================
✅ Gitea Initial Setup Complete!
========================================
Configuration:
- app.ini created with INSTALL_LOCK = true
- Admin user created: {{ gitea_admin_username }}
- Email: {{ gitea_admin_email }}
Next steps:
1. Access Gitea: {{ gitea_url }}
2. Login with:
- Username: {{ gitea_admin_username }}
- Password: (from vault: vault_gitea_admin_password)
3. Configure Gitea Actions Runner (if needed):
- Go to: {{ gitea_url }}/admin/actions/runners
- Get registration token
- Register runner using: deployment/gitea-runner/register.sh
========================================
when:
- gitea_needs_setup | bool
- gitea_show_status | default(true) | bool
- name: Display already configured message
ansible.builtin.debug:
msg: |
========================================
Gitea is already configured.
========================================
No setup needed. Access Gitea at: {{ gitea_url }}
========================================
when:
- gitea_already_configured | bool
- gitea_show_status | default(true) | bool