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
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:
82
deployment/ansible/roles/traefik/tasks/deploy.yml
Normal file
82
deployment/ansible/roles/traefik/tasks/deploy.yml
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
- name: Check for existing Traefik containers
|
||||
shell: docker ps -a --filter "name=traefik" --format "{{ '{{' }}.ID{{ '}}' }}"
|
||||
register: existing_traefik_containers
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Stop and remove existing Traefik containers
|
||||
shell: docker stop {{ item }} && docker rm {{ item }}
|
||||
loop: "{{ existing_traefik_containers.stdout_lines }}"
|
||||
when: existing_traefik_containers.stdout_lines | length > 0
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Check if ports 80 and 443 are in use
|
||||
shell: |
|
||||
if sudo ss -tlnp 'sport = :80' 2>/dev/null | grep -q LISTEN; then
|
||||
echo "port_80_in_use"
|
||||
fi
|
||||
if sudo ss -tlnp 'sport = :443' 2>/dev/null | grep -q LISTEN; then
|
||||
echo "port_443_in_use"
|
||||
fi
|
||||
register: port_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Display port status
|
||||
debug:
|
||||
msg:
|
||||
- "Port 80 status: {{ 'IN USE' if 'port_80_in_use' in port_check.stdout else 'FREE' }}"
|
||||
- "Port 443 status: {{ 'IN USE' if 'port_443_in_use' in port_check.stdout else 'FREE' }}"
|
||||
- "Note: docker-proxy listening on ports is normal when Traefik container is running"
|
||||
|
||||
- name: Warn if ports are blocked by non-docker processes
|
||||
debug:
|
||||
msg: "WARNING: Ports 80/443 appear to be in use. This may prevent Traefik from starting. Check with: sudo ss -tlnp 'sport = :80'"
|
||||
when: ('port_80_in_use' in port_check.stdout or 'port_443_in_use' in port_check.stdout) and existing_traefik_containers.stdout_lines | length == 0
|
||||
|
||||
- name: Check if acme.json exists
|
||||
stat:
|
||||
path: "{{ traefik_stack_path }}/acme.json"
|
||||
register: acme_json_stat
|
||||
|
||||
- name: Remove acme.json if it's a directory (should be a file)
|
||||
shell: |
|
||||
if [ -d "{{ traefik_stack_path }}/acme.json" ]; then
|
||||
rm -rf "{{ traefik_stack_path }}/acme.json"
|
||||
fi
|
||||
become: yes
|
||||
when: acme_json_stat.stat.exists and acme_json_stat.stat.isdir
|
||||
|
||||
- name: Ensure Traefik acme.json exists and has correct permissions
|
||||
file:
|
||||
path: "{{ traefik_stack_path }}/acme.json"
|
||||
state: touch
|
||||
mode: '0600'
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
become: yes
|
||||
when: not acme_json_stat.stat.exists or (acme_json_stat.stat.exists and acme_json_stat.stat.isdir)
|
||||
|
||||
- name: Deploy Traefik stack
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ traefik_stack_path }}"
|
||||
state: present
|
||||
pull: always
|
||||
register: traefik_compose_result
|
||||
|
||||
- name: Check Traefik container status
|
||||
shell: |
|
||||
docker compose -f {{ traefik_stack_path }}/docker-compose.yml ps traefik | grep -Eiq "Up|running"
|
||||
register: traefik_state
|
||||
changed_when: false
|
||||
until: traefik_state.rc == 0
|
||||
retries: "{{ ((traefik_wait_timeout | int) + (traefik_wait_interval | int) - 1) // (traefik_wait_interval | int) }}"
|
||||
delay: "{{ traefik_wait_interval | int }}"
|
||||
failed_when: traefik_state.rc != 0
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Record Traefik deployment facts
|
||||
set_fact:
|
||||
traefik_stack_changed: "{{ traefik_compose_result.changed | default(false) }}"
|
||||
traefik_log_hint: ""
|
||||
135
deployment/ansible/roles/traefik/tasks/logs.yml
Normal file
135
deployment/ansible/roles/traefik/tasks/logs.yml
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
# Check Traefik Logs and ACME Challenge Status
|
||||
|
||||
- name: Check if Traefik stack directory exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ traefik_stack_path }}"
|
||||
register: traefik_stack_exists
|
||||
|
||||
- name: Fail if Traefik stack directory does not exist
|
||||
ansible.builtin.fail:
|
||||
msg: "Traefik stack directory not found at {{ traefik_stack_path }}"
|
||||
when: not traefik_stack_exists.stat.exists
|
||||
|
||||
- name: Get recent Traefik logs
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose logs {{ traefik_container_name }} --tail={{ traefik_logs_tail | default(100) }} 2>&1
|
||||
register: traefik_logs
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Check for ACME challenge errors in container logs
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose logs {{ traefik_container_name }} 2>&1 | grep -iE "acme.*challenge|Cannot retrieve.*ACME" | tail -{{ traefik_logs_error_tail | default(20) }} || echo "No ACME challenge errors found in recent logs"
|
||||
register: acme_errors
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Check for ACME challenge errors in log file
|
||||
ansible.builtin.shell: |
|
||||
tail -n {{ traefik_logs_tail | default(100) }} {{ traefik_stack_path }}/logs/traefik.log 2>/dev/null | grep -iE "acme.*challenge|Cannot retrieve.*ACME" | tail -{{ traefik_logs_error_tail | default(20) }} || echo "No ACME challenge errors found in log file"
|
||||
register: acme_errors_file
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Get logs from last N minutes
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose logs {{ traefik_container_name }} --since {{ traefik_logs_since_minutes | default(10) }}m 2>&1 | tail -{{ traefik_logs_recent_tail | default(50) }}
|
||||
register: recent_logs
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: traefik_logs_since_minutes is defined
|
||||
|
||||
- name: Count ACME challenge errors in last hour
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose logs {{ traefik_container_name }} --since 1h 2>&1 | grep -c "Cannot retrieve.*ACME challenge" || echo "0"
|
||||
register: acme_error_count
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Display ACME challenge error summary
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Traefik ACME Challenge Status
|
||||
========================================
|
||||
ACME Errors (last hour): {{ acme_error_count.stdout }}
|
||||
========================================
|
||||
|
||||
{% if acme_error_count.stdout | int > 0 %}
|
||||
⚠️ ACME challenge errors still occurring
|
||||
{% else %}
|
||||
✅ No ACME challenge errors in the last hour!
|
||||
{% endif %}
|
||||
when: traefik_show_status | default(true) | bool
|
||||
|
||||
- name: Display ACME challenge errors from container logs
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
ACME Challenge Errors (Container Logs):
|
||||
========================================
|
||||
{{ acme_errors.stdout }}
|
||||
========================================
|
||||
when: traefik_show_status | default(true) | bool
|
||||
|
||||
- name: Display ACME challenge errors from log file
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
ACME Challenge Errors (Log File):
|
||||
========================================
|
||||
{{ acme_errors_file.stdout }}
|
||||
========================================
|
||||
when: traefik_show_status | default(true) | bool
|
||||
|
||||
- name: Display recent Traefik logs
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Recent Traefik Logs (last {{ traefik_logs_since_minutes | default(10) }} minutes):
|
||||
========================================
|
||||
{{ recent_logs.stdout | default('No recent logs') }}
|
||||
========================================
|
||||
when:
|
||||
- traefik_logs_since_minutes is defined
|
||||
- traefik_show_status | default(true) | bool
|
||||
|
||||
- name: Display all Traefik logs
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Traefik Container Logs (last {{ traefik_logs_tail | default(100) }} lines):
|
||||
========================================
|
||||
{{ traefik_logs.stdout | default('No logs available') }}
|
||||
========================================
|
||||
when:
|
||||
- traefik_show_all_logs | default(false) | bool
|
||||
- traefik_show_status | default(true) | bool
|
||||
|
||||
- name: Display final summary
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Summary
|
||||
========================================
|
||||
{% if acme_error_count.stdout | int == 0 %}
|
||||
✅ SUCCESS: No ACME challenge errors in the last hour!
|
||||
|
||||
The Traefik configuration fix appears to be working. Monitor the logs
|
||||
for the next certificate renewal attempt (usually hourly) to confirm.
|
||||
{% else %}
|
||||
⚠️ WARNING: {{ acme_error_count.stdout }} ACME challenge errors found in the last hour.
|
||||
|
||||
The errors may be from before the configuration fix was applied.
|
||||
Monitor the logs for the next certificate renewal attempt to see if
|
||||
the errors have stopped.
|
||||
{% endif %}
|
||||
========================================
|
||||
when: traefik_show_status | default(true) | bool
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
- name: Deploy Traefik stack
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ traefik_stack_path }}"
|
||||
state: present
|
||||
pull: always
|
||||
register: traefik_compose_result
|
||||
|
||||
- name: Check Traefik container status
|
||||
shell: |
|
||||
docker compose -f {{ traefik_stack_path }}/docker-compose.yml ps traefik | grep -Eiq "Up|running"
|
||||
register: traefik_state
|
||||
changed_when: false
|
||||
until: traefik_state.rc == 0
|
||||
retries: "{{ ((traefik_wait_timeout | int) + (traefik_wait_interval | int) - 1) // (traefik_wait_interval | int) }}"
|
||||
delay: "{{ traefik_wait_interval | int }}"
|
||||
failed_when: traefik_state.rc != 0
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Record Traefik deployment facts
|
||||
set_fact:
|
||||
traefik_stack_changed: "{{ traefik_compose_result.changed | default(false) }}"
|
||||
traefik_log_hint: ""
|
||||
113
deployment/ansible/roles/traefik/tasks/restart.yml
Normal file
113
deployment/ansible/roles/traefik/tasks/restart.yml
Normal file
@@ -0,0 +1,113 @@
|
||||
---
|
||||
# Restart and Recreate Traefik Container Tasks
|
||||
# Supports both restart (force-recreate) and full recreate (down + up)
|
||||
|
||||
- name: Check if Traefik stack directory exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ traefik_stack_path }}"
|
||||
register: traefik_stack_exists
|
||||
|
||||
- name: Fail if Traefik stack directory does not exist
|
||||
ansible.builtin.fail:
|
||||
msg: "Traefik stack directory not found at {{ traefik_stack_path }}"
|
||||
when: not traefik_stack_exists.stat.exists
|
||||
|
||||
- name: Check Traefik container status before restart
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose ps {{ traefik_container_name }} --format json
|
||||
register: traefik_status_before
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Display Traefik status before restart
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
================================================================================
|
||||
Traefik Container Status (Before Restart):
|
||||
{{ traefik_status_before.stdout | default('Container not found or Docker not running') }}
|
||||
================================================================================
|
||||
when: traefik_show_status | default(true) | bool
|
||||
|
||||
- name: Recreate Traefik container to apply new configuration
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose up -d --force-recreate {{ traefik_container_name }}
|
||||
register: traefik_restart
|
||||
changed_when: traefik_restart.rc == 0
|
||||
when: traefik_restart_action | default('restart') == 'restart'
|
||||
notify: wait for traefik
|
||||
|
||||
- name: Stop and remove Traefik container (full recreate)
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose down {{ traefik_container_name }}
|
||||
register: traefik_down
|
||||
changed_when: traefik_down.rc == 0
|
||||
when: traefik_restart_action | default('restart') == 'recreate'
|
||||
|
||||
- name: Create new Traefik container with updated configuration (full recreate)
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose up -d {{ traefik_container_name }}
|
||||
register: traefik_up
|
||||
changed_when: traefik_up.rc == 0
|
||||
when: traefik_restart_action | default('restart') == 'recreate'
|
||||
notify: wait for traefik
|
||||
|
||||
- name: Wait for Traefik to be ready
|
||||
ansible.builtin.wait_for:
|
||||
timeout: "{{ traefik_restart_wait_timeout | default(30) }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Check Traefik container status after restart
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose ps {{ traefik_container_name }} --format json
|
||||
register: traefik_status_after
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Check Traefik health endpoint
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose exec -T {{ traefik_container_name }} traefik healthcheck --ping 2>&1 || echo "HEALTH_CHECK_FAILED"
|
||||
register: traefik_health
|
||||
ignore_errors: yes
|
||||
changed_when: false
|
||||
when: traefik_check_health | default(true) | bool
|
||||
|
||||
- name: Check if ACME challenge router is in labels (for recreate action)
|
||||
ansible.builtin.shell: |
|
||||
cd {{ traefik_stack_path }}
|
||||
docker compose ps {{ traefik_container_name }} --format json | jq -r '.[0].Labels' | grep -i 'acme-challenge' || echo "NO_ACME_ROUTER"
|
||||
register: acme_router_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: traefik_restart_action | default('restart') == 'recreate'
|
||||
|
||||
- name: Display final status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
========================================
|
||||
Traefik Restart Summary
|
||||
========================================
|
||||
Action: {{ traefik_restart_action | default('restart') | upper }}
|
||||
Container Status: {% if 'State":"running' in (traefik_status_after.stdout | default('')) %}✅ RUNNING{% else %}❌ NOT RUNNING{% endif %}
|
||||
{% if traefik_check_health | default(true) | bool %}
|
||||
Health Check: {% if 'HEALTH_CHECK_FAILED' not in (traefik_health.stdout | default('')) %}✅ HEALTHY{% else %}❌ UNHEALTHY or TIMEOUT{% endif %}
|
||||
{% endif %}
|
||||
{% if traefik_restart_action | default('restart') == 'recreate' %}
|
||||
ACME Challenge Router: {% if 'NO_ACME_ROUTER' in acme_router_check.stdout %}✅ REMOVED (correct!){% else %}⚠️ Still present in labels{% endif %}
|
||||
{% endif %}
|
||||
Restart Action: {% if (traefik_restart.changed | default(false)) or (traefik_up.changed | default(false)) %}🔄 Container restarted{% else %}ℹ️ No restart needed{% endif %}
|
||||
========================================
|
||||
{% if 'State":"running' in (traefik_status_after.stdout | default('')) %}
|
||||
✅ Traefik is running!
|
||||
{% else %}
|
||||
❌ Traefik is not running. Check logs for details:
|
||||
docker logs {{ traefik_container_name }}
|
||||
{% endif %}
|
||||
========================================
|
||||
when: traefik_show_status | default(true) | bool
|
||||
|
||||
Reference in New Issue
Block a user