chore: update staging branch with current changes
This commit is contained in:
@@ -866,7 +866,6 @@ jobs:
|
|||||||
SELECTED_IMAGE="$DEFAULT_IMAGE"
|
SELECTED_IMAGE="$DEFAULT_IMAGE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
STACK_PATH_DISPLAY="~/deployment/stacks/staging"
|
|
||||||
STACK_PATH_DISPLAY="~/deployment/stacks/staging"
|
STACK_PATH_DISPLAY="~/deployment/stacks/staging"
|
||||||
|
|
||||||
SELECTED_TAG="${SELECTED_IMAGE##*:}"
|
SELECTED_TAG="${SELECTED_IMAGE##*:}"
|
||||||
|
|||||||
40
deployment/ansible/playbooks/check-docker-compose-logs.yml
Normal file
40
deployment/ansible/playbooks/check-docker-compose-logs.yml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
- name: Check Docker Compose Logs for JSON Output
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Get recent docker compose logs for staging-app (JSON format check)
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Last 100 lines of staging-app logs ==="
|
||||||
|
docker compose logs --tail=100 staging-app 2>&1 | tail -50
|
||||||
|
echo ""
|
||||||
|
echo "=== Checking for JSON logs ==="
|
||||||
|
docker compose logs --tail=200 staging-app 2>&1 | grep -E '^{"|^\{' | head -5 || echo "No JSON logs found (or logs are in plain text)"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: compose_logs
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display compose logs
|
||||||
|
debug:
|
||||||
|
msg: "{{ compose_logs.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Get all recent logs from all staging services
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== All staging services logs (last 30 lines each) ==="
|
||||||
|
docker compose logs --tail=30 2>&1
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: all_logs
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display all logs
|
||||||
|
debug:
|
||||||
|
msg: "{{ all_logs.stdout_lines }}"
|
||||||
|
when: all_logs.stdout_lines is defined
|
||||||
78
deployment/ansible/playbooks/check-php-files-and-workers.yml
Normal file
78
deployment/ansible/playbooks/check-php-files-and-workers.yml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
---
|
||||||
|
- name: Check PHP Files and PHP-FPM Workers
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check if public/index.php exists
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Check public/index.php ==="
|
||||||
|
docker compose exec -T staging-app ls -la /var/www/html/public/index.php 2>&1 || echo "index.php not found"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check public directory ==="
|
||||||
|
docker compose exec -T staging-app ls -la /var/www/html/public/ 2>&1 | head -20 || echo "public directory not found"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check if code directory exists ==="
|
||||||
|
docker compose exec -T staging-app ls -la /var/www/html/ 2>&1 | head -20 || echo "Code directory not found"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: file_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display file check results
|
||||||
|
debug:
|
||||||
|
msg: "{{ file_check.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check PHP-FPM worker processes in detail
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== All processes in staging-app ==="
|
||||||
|
docker compose exec -T staging-app ps aux 2>&1 || echo "Could not get processes"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check PHP-FPM master and worker processes ==="
|
||||||
|
docker compose exec -T staging-app sh -c "ps aux | grep -E '[p]hp|[f]pm' || echo 'No PHP-FPM processes found'" || echo "Process check failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: process_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display process check results
|
||||||
|
debug:
|
||||||
|
msg: "{{ process_check.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Test PHP execution directly
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Test PHP CLI ==="
|
||||||
|
docker compose exec -T staging-app php -v 2>&1 || echo "PHP CLI failed"
|
||||||
|
echo ""
|
||||||
|
echo "=== Test if we can include index.php ==="
|
||||||
|
docker compose exec -T staging-app php -r "if(file_exists('/var/www/html/public/index.php')) { echo 'index.php exists\n'; } else { echo 'index.php NOT FOUND\n'; }" 2>&1 || echo "PHP test failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: php_test
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display PHP test results
|
||||||
|
debug:
|
||||||
|
msg: "{{ php_test.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check PHP-FPM pool status using status page
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Try to get PHP-FPM status ==="
|
||||||
|
docker compose exec -T staging-app sh -c "SCRIPT_NAME=/status SCRIPT_FILENAME=/status REQUEST_METHOD=GET timeout 2 php -r \"\\\$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (socket_connect(\\\$socket, '127.0.0.1', 9000)) { socket_write(\\\$socket, 'GET /status HTTP/1.0\\r\\nHost: localhost\\r\\n\\r\\n'); \\\$response = socket_read(\\\$socket, 1024); echo \\\$response; socket_close(\\\$socket); } else { echo 'Could not connect to PHP-FPM'; }\" 2>&1" || echo "Status check failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: fpm_status
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display PHP-FPM status
|
||||||
|
debug:
|
||||||
|
msg: "{{ fpm_status.stdout_lines }}"
|
||||||
80
deployment/ansible/playbooks/check-phpfpm-config.yml
Normal file
80
deployment/ansible/playbooks/check-phpfpm-config.yml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
---
|
||||||
|
- name: Check PHP-FPM Configuration in Detail
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check PHP-FPM pool configuration
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== PHP-FPM www.conf listen configuration ==="
|
||||||
|
docker compose exec -T staging-app cat /usr/local/etc/php-fpm.d/www.conf 2>&1 | grep -E "(listen|listen.allowed_clients|listen.owner|listen.group|listen.mode|pm)" | head -20
|
||||||
|
echo ""
|
||||||
|
echo "=== Check PHP-FPM processes ==="
|
||||||
|
docker compose exec -T staging-app ps aux | grep php-fpm || echo "No php-fpm processes found"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check PHP-FPM status page ==="
|
||||||
|
docker compose exec -T staging-app sh -c "SCRIPT_NAME=/status SCRIPT_FILENAME=/status REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000 2>&1 || echo 'Status check failed'"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: phpfpm_config
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display PHP-FPM configuration
|
||||||
|
debug:
|
||||||
|
msg: "{{ phpfpm_config.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check what interface PHP-FPM is listening on
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Check listening interface ==="
|
||||||
|
docker compose exec -T staging-app netstat -tlnp 2>/dev/null | grep 9000 || \
|
||||||
|
docker compose exec -T staging-app ss -tlnp 2>/dev/null | grep 9000 || \
|
||||||
|
echo "Could not check listening interface"
|
||||||
|
echo ""
|
||||||
|
echo "=== Try to connect from nginx using FastCGI protocol ==="
|
||||||
|
docker compose exec -T staging-nginx sh -c "echo -e 'REQUEST_METHOD=GET\nSCRIPT_FILENAME=/var/www/html/public/index.php\n' | cgi-fcgi -bind -connect staging-app:9000 2>&1 | head -20" || echo "FastCGI test failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: listen_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display listening interface check
|
||||||
|
debug:
|
||||||
|
msg: "{{ listen_check.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check PHP-FPM error logs
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== PHP-FPM error log ==="
|
||||||
|
docker compose exec -T staging-app tail -50 /var/log/php-fpm.log 2>&1 || \
|
||||||
|
docker compose exec -T staging-app tail -50 /usr/local/var/log/php-fpm.log 2>&1 || \
|
||||||
|
docker compose logs --tail=100 staging-app 2>&1 | grep -iE "(fpm|error|warning)" | tail -20 || \
|
||||||
|
echo "No PHP-FPM error logs found"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: phpfpm_errors
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display PHP-FPM errors
|
||||||
|
debug:
|
||||||
|
msg: "{{ phpfpm_errors.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Test actual request from outside
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Test request from nginx to PHP-FPM ==="
|
||||||
|
docker compose exec -T staging-nginx sh -c "curl -v http://127.0.0.1/ 2>&1 | head -30" || echo "Request test failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: request_test
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display request test
|
||||||
|
debug:
|
||||||
|
msg: "{{ request_test.stdout_lines }}"
|
||||||
66
deployment/ansible/playbooks/check-staging-php-logs.yml
Normal file
66
deployment/ansible/playbooks/check-staging-php-logs.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
- name: Check Staging PHP Logs in Volume
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check PHP log files in staging-app container
|
||||||
|
shell: |
|
||||||
|
echo "=== Checking log directory in staging-app container ==="
|
||||||
|
docker exec staging-app ls -lah /var/www/html/storage/logs/ 2>&1 || echo "Could not list logs directory"
|
||||||
|
echo ""
|
||||||
|
echo "=== Recent PHP error logs ==="
|
||||||
|
docker exec staging-app tail -50 /var/www/html/storage/logs/php-errors.log 2>&1 | tail -30 || echo "Could not read php-errors.log"
|
||||||
|
echo ""
|
||||||
|
echo "=== Recent application logs ==="
|
||||||
|
docker exec staging-app find /var/www/html/storage/logs -name "*.log" -type f -exec ls -lh {} \; 2>&1 | head -20 || echo "Could not find log files"
|
||||||
|
echo ""
|
||||||
|
echo "=== Staging log file (if exists) ==="
|
||||||
|
docker exec staging-app tail -50 /var/www/html/storage/logs/staging.log 2>&1 | tail -30 || echo "staging.log not found or empty"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check log volume mount ==="
|
||||||
|
docker exec staging-app df -h /var/www/html/storage/logs 2>&1 || echo "Could not check volume"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: php_logs_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display PHP logs check results
|
||||||
|
debug:
|
||||||
|
msg: "{{ php_logs_check.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check if we can access log volume directly
|
||||||
|
shell: |
|
||||||
|
echo "=== Docker volume inspect ==="
|
||||||
|
docker volume inspect staging-logs 2>&1 || echo "Volume not found"
|
||||||
|
echo ""
|
||||||
|
echo "=== Try to access volume through temporary container ==="
|
||||||
|
docker run --rm -v staging-logs:/logs alpine ls -lah /logs 2>&1 | head -30 || echo "Could not access volume"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: volume_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display volume check results
|
||||||
|
debug:
|
||||||
|
msg: "{{ volume_check.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check PHP configuration for logging
|
||||||
|
shell: |
|
||||||
|
echo "=== PHP error_log setting ==="
|
||||||
|
docker exec staging-app php -i | grep -E "(error_log|log_errors)" || echo "Could not get PHP config"
|
||||||
|
echo ""
|
||||||
|
echo "=== PHP-FPM error log location ==="
|
||||||
|
docker exec staging-app grep -E "(error_log|catch_workers_output)" /usr/local/etc/php-fpm.d/www.conf | head -5 || echo "Could not read PHP-FPM config"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: php_config_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display PHP configuration
|
||||||
|
debug:
|
||||||
|
msg: "{{ php_config_check.stdout_lines }}"
|
||||||
@@ -1,96 +1,108 @@
|
|||||||
---
|
---
|
||||||
- name: Diagnose Staging 502 Error
|
- name: Diagnose Staging 502 Bad Gateway Error
|
||||||
hosts: production
|
hosts: production
|
||||||
gather_facts: yes
|
gather_facts: yes
|
||||||
become: no
|
become: no
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Check Nginx error logs
|
- name: Check nginx error logs for 502 errors
|
||||||
shell: |
|
shell: |
|
||||||
cd ~/deployment/stacks/staging && docker compose logs --tail=50 staging-nginx 2>&1 | grep -iE "(error|502|bad gateway|php|fpm)" || echo "No errors found in nginx logs"
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Nginx Error Logs (Last 50 lines) ==="
|
||||||
|
docker compose logs --tail=50 staging-nginx 2>&1 | grep -iE "(error|502|bad gateway|php|fpm|upstream)" || echo "No obvious errors in logs"
|
||||||
args:
|
args:
|
||||||
executable: /bin/bash
|
executable: /bin/bash
|
||||||
register: nginx_errors
|
register: nginx_errors
|
||||||
changed_when: false
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display nginx errors
|
||||||
|
debug:
|
||||||
|
msg: "{{ nginx_errors.stdout_lines }}"
|
||||||
|
|
||||||
- name: Check PHP-FPM status in staging-app
|
- name: Check PHP-FPM status in staging-app
|
||||||
shell: |
|
shell: |
|
||||||
cd ~/deployment/stacks/staging && docker compose exec -T staging-app php-fpm-healthcheck 2>&1 || echo "PHP-FPM healthcheck failed"
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== PHP-FPM Status Check ==="
|
||||||
|
docker compose exec -T staging-app php-fpm-healthcheck 2>&1 || echo "PHP-FPM healthcheck failed"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check if PHP-FPM is running ==="
|
||||||
|
docker compose exec -T staging-app ps aux | grep -E "php-fpm|php" | head -10 || echo "Could not check processes"
|
||||||
args:
|
args:
|
||||||
executable: /bin/bash
|
executable: /bin/bash
|
||||||
register: php_fpm_status
|
register: php_fpm_status
|
||||||
changed_when: false
|
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
- name: Test PHP-FPM connection from nginx container
|
|
||||||
shell: |
|
|
||||||
cd ~/deployment/stacks/staging && docker compose exec -T staging-nginx sh -c "nc -zv staging-app 9000 2>&1 || echo 'Connection test failed'" || echo "Connection test failed"
|
|
||||||
args:
|
|
||||||
executable: /bin/bash
|
|
||||||
register: connection_test
|
|
||||||
changed_when: false
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Check if PHP-FPM is listening
|
|
||||||
shell: |
|
|
||||||
cd ~/deployment/stacks/staging && docker compose exec -T staging-app sh -c "netstat -tlnp 2>/dev/null | grep 9000 || ss -tlnp 2>/dev/null | grep 9000 || echo 'Port 9000 not found'" || echo "Could not check ports"
|
|
||||||
args:
|
|
||||||
executable: /bin/bash
|
|
||||||
register: php_fpm_port
|
|
||||||
changed_when: false
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Check staging-app process list
|
|
||||||
shell: |
|
|
||||||
cd ~/deployment/stacks/staging && docker compose exec -T staging-app sh -c "ps aux | grep -E '(php-fpm|nginx)' | head -20" || echo "Could not get process list"
|
|
||||||
args:
|
|
||||||
executable: /bin/bash
|
|
||||||
register: processes
|
|
||||||
changed_when: false
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Check network connectivity
|
|
||||||
shell: |
|
|
||||||
cd ~/deployment/stacks/staging && docker compose exec -T staging-nginx sh -c "ping -c 2 staging-app 2>&1 || echo 'Ping failed'" || echo "Network test failed"
|
|
||||||
args:
|
|
||||||
executable: /bin/bash
|
|
||||||
register: network_test
|
|
||||||
changed_when: false
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Check if /var/www/html/public/index.php exists
|
|
||||||
shell: |
|
|
||||||
cd ~/deployment/stacks/staging && docker compose exec -T staging-nginx sh -c "test -f /var/www/html/public/index.php && echo 'index.php exists' || echo 'index.php NOT FOUND'" || echo "Could not check file"
|
|
||||||
args:
|
|
||||||
executable: /bin/bash
|
|
||||||
register: index_php_check
|
|
||||||
changed_when: false
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Display Nginx error logs
|
|
||||||
debug:
|
|
||||||
msg: "{{ nginx_errors.stdout_lines }}"
|
|
||||||
|
|
||||||
- name: Display PHP-FPM status
|
- name: Display PHP-FPM status
|
||||||
debug:
|
debug:
|
||||||
msg: "{{ php_fpm_status.stdout_lines }}"
|
msg: "{{ php_fpm_status.stdout_lines }}"
|
||||||
|
|
||||||
- name: Display connection test
|
- name: Test PHP-FPM connection from nginx container
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Test connection from nginx to PHP-FPM ==="
|
||||||
|
docker compose exec -T staging-nginx sh -c "nc -zv staging-app 9000 2>&1 || echo 'Connection test failed'" || echo "Connection test failed"
|
||||||
|
echo ""
|
||||||
|
echo "=== Try curl from nginx to PHP-FPM ==="
|
||||||
|
docker compose exec -T staging-nginx sh -c "curl -v http://staging-app:9000 2>&1 | head -20" || echo "Curl test failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: connection_test
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display connection test results
|
||||||
debug:
|
debug:
|
||||||
msg: "{{ connection_test.stdout_lines }}"
|
msg: "{{ connection_test.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check nginx configuration for PHP-FPM upstream
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Nginx Configuration ==="
|
||||||
|
docker compose exec -T staging-nginx cat /etc/nginx/conf.d/default.conf 2>&1 | grep -A 10 -B 5 "staging-app\|9000\|fastcgi_pass" || echo "Could not read nginx config"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: nginx_config
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display nginx configuration
|
||||||
|
debug:
|
||||||
|
msg: "{{ nginx_config.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check if PHP-FPM is listening on port 9000
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Check PHP-FPM port 9000 ==="
|
||||||
|
docker compose exec -T staging-app sh -c "netstat -tlnp 2>/dev/null | grep 9000 || ss -tlnp 2>/dev/null | grep 9000 || echo 'Port 9000 not found'" || echo "Could not check ports"
|
||||||
|
echo ""
|
||||||
|
echo "=== PHP-FPM pool config ==="
|
||||||
|
docker compose exec -T staging-app cat /usr/local/etc/php-fpm.d/www.conf 2>&1 | grep -E "(listen|listen.allowed_clients)" | head -5 || echo "Could not read PHP-FPM config"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: php_fpm_port
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
- name: Display PHP-FPM port check
|
- name: Display PHP-FPM port check
|
||||||
debug:
|
debug:
|
||||||
msg: "{{ php_fpm_port.stdout_lines }}"
|
msg: "{{ php_fpm_port.stdout_lines }}"
|
||||||
|
|
||||||
- name: Display processes
|
- name: Check network connectivity between containers
|
||||||
debug:
|
shell: |
|
||||||
msg: "{{ processes.stdout_lines }}"
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Network connectivity ==="
|
||||||
|
docker compose exec -T staging-nginx ping -c 2 staging-app 2>&1 || echo "Ping failed"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check docker networks ==="
|
||||||
|
docker network inspect staging-internal 2>&1 | grep -A 5 "staging-app\|staging-nginx" || echo "Could not inspect network"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: network_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
- name: Display network test
|
- name: Display network check
|
||||||
debug:
|
debug:
|
||||||
msg: "{{ network_test.stdout_lines }}"
|
msg: "{{ network_check.stdout_lines }}"
|
||||||
|
|
||||||
- name: Display index.php check
|
|
||||||
debug:
|
|
||||||
msg: "{{ index_php_check.stdout_lines }}"
|
|
||||||
|
|||||||
125
deployment/ansible/playbooks/diagnose-staging-logs.yml
Normal file
125
deployment/ansible/playbooks/diagnose-staging-logs.yml
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
---
|
||||||
|
- name: Diagnose Staging Logs Issue
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check if staging stack directory exists
|
||||||
|
shell: |
|
||||||
|
test -d ~/deployment/stacks/staging && echo "? Directory exists" || echo "? Directory missing"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: dir_check
|
||||||
|
|
||||||
|
- name: Display directory check result
|
||||||
|
debug:
|
||||||
|
msg: "{{ dir_check.stdout }}"
|
||||||
|
|
||||||
|
- name: Check if docker-compose.yml exists
|
||||||
|
shell: |
|
||||||
|
test -f ~/deployment/stacks/staging/docker-compose.yml && echo "? docker-compose.yml exists" || echo "? docker-compose.yml missing"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: compose_check
|
||||||
|
|
||||||
|
- name: Display compose file check result
|
||||||
|
debug:
|
||||||
|
msg: "{{ compose_check.stdout }}"
|
||||||
|
|
||||||
|
- name: List staging directory contents
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging && ls -la
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: dir_contents
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display directory contents
|
||||||
|
debug:
|
||||||
|
msg: "{{ dir_contents.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check Docker Compose version
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging && docker compose version
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: compose_version
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display Docker Compose version
|
||||||
|
debug:
|
||||||
|
msg: "{{ compose_version.stdout }}"
|
||||||
|
|
||||||
|
- name: Check if containers exist
|
||||||
|
shell: |
|
||||||
|
docker ps -a | grep staging || echo "No staging containers found"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: container_list
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display container list
|
||||||
|
debug:
|
||||||
|
msg: "{{ container_list.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Try docker compose ps (this is where it might fail)
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging && docker compose ps
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: compose_ps
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display docker compose ps result
|
||||||
|
debug:
|
||||||
|
msg: "{{ compose_ps.stdout_lines }}"
|
||||||
|
msg_also: "{{ compose_ps.stderr_lines }}"
|
||||||
|
|
||||||
|
- name: Try docker compose logs directly (without service name)
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging && docker compose logs --tail=50 2>&1 | head -100
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: compose_logs_generic
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display generic compose logs
|
||||||
|
debug:
|
||||||
|
msg: "{{ (compose_logs_generic.stdout_lines | default([])) + (compose_logs_generic.stderr_lines | default([])) }}"
|
||||||
|
|
||||||
|
- name: Try individual container logs using docker logs
|
||||||
|
shell: |
|
||||||
|
docker logs staging-app --tail=50 2>&1 || echo "? Could not get staging-app logs"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: direct_app_logs
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display direct staging-app logs
|
||||||
|
debug:
|
||||||
|
msg: "{{ direct_app_logs.stdout_lines }}"
|
||||||
|
msg_also: "{{ direct_app_logs.stderr_lines }}"
|
||||||
|
|
||||||
|
- name: Check current working directory permissions
|
||||||
|
shell: |
|
||||||
|
ls -ld ~/deployment/stacks/staging && pwd && whoami
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: perm_check
|
||||||
|
|
||||||
|
- name: Display permission check
|
||||||
|
debug:
|
||||||
|
msg: "{{ perm_check.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check if we can read docker-compose.yml
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging && head -20 docker-compose.yml
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: compose_read
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display docker-compose.yml content (first 20 lines)
|
||||||
|
debug:
|
||||||
|
msg: "{{ (compose_read.stdout_lines | default([])) + (compose_read.stderr_lines | default([])) }}"
|
||||||
79
deployment/ansible/playbooks/fix-nginx-upstream.yml
Normal file
79
deployment/ansible/playbooks/fix-nginx-upstream.yml
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
- name: Fix Nginx Upstream Configuration
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check which nginx config files exist
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Check nginx config files ==="
|
||||||
|
docker compose exec -T staging-nginx find /etc/nginx -name "*.conf" -type f 2>&1 | head -20
|
||||||
|
echo ""
|
||||||
|
echo "=== Check sites-enabled ==="
|
||||||
|
docker compose exec -T staging-nginx ls -la /etc/nginx/sites-enabled/ 2>&1 || echo "sites-enabled not found"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check sites-available ==="
|
||||||
|
docker compose exec -T staging-nginx ls -la /etc/nginx/sites-available/ 2>&1 || echo "sites-available not found"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check nginx.conf includes ==="
|
||||||
|
docker compose exec -T staging-nginx grep -E "include|conf.d|sites" /etc/nginx/nginx.conf 2>&1 | head -10
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: nginx_config_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display nginx config check
|
||||||
|
debug:
|
||||||
|
msg: "{{ nginx_config_check.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Find all fastcgi_pass directives
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Search for fastcgi_pass in all config files ==="
|
||||||
|
docker compose exec -T staging-nginx grep -r "fastcgi_pass" /etc/nginx/ 2>&1 || echo "Could not search"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: fastcgi_pass_search
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display fastcgi_pass search
|
||||||
|
debug:
|
||||||
|
msg: "{{ fastcgi_pass_search.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Fix all fastcgi_pass to use staging-app:9000
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Fix fastcgi_pass in all config files ==="
|
||||||
|
docker compose exec -T staging-nginx sh -c "find /etc/nginx -name '*.conf' -type f -exec sed -i 's|fastcgi_pass 127.0.0.1:9000;|fastcgi_pass staging-app:9000;|g' {} \;" || echo "Fix failed"
|
||||||
|
docker compose exec -T staging-nginx sh -c "find /etc/nginx -name '*.conf' -type f -exec sed -i 's|fastcgi_pass localhost:9000;|fastcgi_pass staging-app:9000;|g' {} \;" || echo "Fix failed"
|
||||||
|
docker compose exec -T staging-nginx sh -c "find /etc/nginx -name '*.conf' -type f -exec sed -i 's|fastcgi_pass php-upstream;|fastcgi_pass staging-app:9000;|g' {} \;" || echo "Note: php-upstream should stay as is"
|
||||||
|
echo "=== Verify fix ==="
|
||||||
|
docker compose exec -T staging-nginx grep -r "fastcgi_pass" /etc/nginx/ 2>&1 | grep -v "staging-app" || echo "All fastcgi_pass now use staging-app"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: fix_result
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display fix result
|
||||||
|
debug:
|
||||||
|
msg: "{{ fix_result.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Reload nginx to apply changes
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
docker compose exec -T staging-nginx nginx -t 2>&1 || echo "Config test failed"
|
||||||
|
docker compose restart staging-nginx || echo "Restart failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: nginx_reload
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display nginx reload result
|
||||||
|
debug:
|
||||||
|
msg: "{{ nginx_reload.stdout_lines }}"
|
||||||
36
deployment/ansible/playbooks/fix-phpfpm-config.yml
Normal file
36
deployment/ansible/playbooks/fix-phpfpm-config.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
- name: Check and Fix PHP-FPM Configuration
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check PHP-FPM www.conf configuration for allowed_clients
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== PHP-FPM www.conf listen.allowed_clients ==="
|
||||||
|
docker compose exec -T staging-app cat /usr/local/etc/php-fpm.d/www.conf 2>&1 | grep -E "(listen|allowed_clients|listen\.owner|listen\.group|listen\.mode)" | head -15
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: fpm_config
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display PHP-FPM config
|
||||||
|
debug:
|
||||||
|
msg: "{{ fpm_config.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Check nginx error log for specific PHP-FPM errors
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Nginx Error Log (all lines) ==="
|
||||||
|
docker compose logs --tail=200 staging-nginx 2>&1 | grep -iE "(502|bad gateway|upstream|php|fpm|connection)" || echo "No specific errors found"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: nginx_error_log
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display nginx error log
|
||||||
|
debug:
|
||||||
|
msg: "{{ nginx_error_log.stdout_lines }}"
|
||||||
57
deployment/ansible/playbooks/fix-sites-available-default.yml
Normal file
57
deployment/ansible/playbooks/fix-sites-available-default.yml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
- name: Fix sites-available/default upstream configuration
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check php-upstream definition in sites-available/default
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Check upstream definition ==="
|
||||||
|
docker compose exec -T staging-nginx grep -A 3 "upstream php-upstream" /etc/nginx/sites-available/default 2>&1 || echo "No upstream found"
|
||||||
|
echo ""
|
||||||
|
echo "=== Full sites-available/default file ==="
|
||||||
|
docker compose exec -T staging-nginx cat /etc/nginx/sites-available/default 2>&1
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: upstream_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display upstream check
|
||||||
|
debug:
|
||||||
|
msg: "{{ upstream_check.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Fix php-upstream in sites-available/default
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Fix php-upstream definition ==="
|
||||||
|
docker compose exec -T staging-nginx sed -i 's|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || echo "Fix 127.0.0.1 failed"
|
||||||
|
docker compose exec -T staging-nginx sed -i 's|server localhost:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || echo "Fix localhost failed"
|
||||||
|
echo ""
|
||||||
|
echo "=== Verify fix ==="
|
||||||
|
docker compose exec -T staging-nginx grep -A 3 "upstream php-upstream" /etc/nginx/sites-available/default 2>&1 || echo "No upstream found"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: fix_upstream
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display fix result
|
||||||
|
debug:
|
||||||
|
msg: "{{ fix_upstream.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Reload nginx
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
docker compose exec -T staging-nginx nginx -t && docker compose restart staging-nginx || echo "Reload failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: reload_nginx
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display reload result
|
||||||
|
debug:
|
||||||
|
msg: "{{ reload_nginx.stdout_lines }}"
|
||||||
28
deployment/ansible/playbooks/quick-staging-logs-check.yml
Normal file
28
deployment/ansible/playbooks/quick-staging-logs-check.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: Quick Staging Logs Check
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Quick container status check
|
||||||
|
shell: |
|
||||||
|
echo "=== Method 1: Direct docker ps ==="
|
||||||
|
docker ps --filter "name=staging" || echo "No staging containers found"
|
||||||
|
echo ""
|
||||||
|
echo "=== Method 2: Docker compose ps ==="
|
||||||
|
cd ~/deployment/stacks/staging && docker compose ps 2>&1 || echo "Docker compose failed"
|
||||||
|
echo ""
|
||||||
|
echo "=== Method 3: Direct logs access ==="
|
||||||
|
docker logs staging-app --tail=30 2>&1 | tail -20 || echo "Could not get staging-app logs"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: quick_check
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display results
|
||||||
|
debug:
|
||||||
|
msg: "{{ (quick_check.stdout_lines | default([])) + (quick_check.stderr_lines | default([])) }}"
|
||||||
|
when: quick_check is defined
|
||||||
|
failed_when: false
|
||||||
46
deployment/ansible/playbooks/test-fastcgi-directly.yml
Normal file
46
deployment/ansible/playbooks/test-fastcgi-directly.yml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
- name: Test FastCGI Connection Directly
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install cgi-fcgi in nginx container and test FastCGI
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Test FastCGI with a simple request ==="
|
||||||
|
# Create a simple test script
|
||||||
|
docker compose exec -T staging-nginx sh -c "echo -e 'REQUEST_METHOD=GET\nSCRIPT_FILENAME=/var/www/html/public/index.php\nSERVER_NAME=test\n' > /tmp/fcgi-test.txt && cat /tmp/fcgi-test.txt" || echo "Could not create test file"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check nginx error log directly ==="
|
||||||
|
docker compose exec -T staging-nginx tail -100 /var/log/nginx/error.log 2>&1 || echo "Error log not found at /var/log/nginx/error.log"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check nginx access log ==="
|
||||||
|
docker compose exec -T staging-nginx tail -50 /var/log/nginx/access.log 2>&1 | tail -20 || echo "Access log not found"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: fcgi_test
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display FastCGI test results
|
||||||
|
debug:
|
||||||
|
msg: "{{ fcgi_test.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Make a real HTTP request and capture full response
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Make HTTP request from nginx container ==="
|
||||||
|
docker compose exec -T staging-nginx curl -v http://127.0.0.1/ 2>&1 || echo "Request failed"
|
||||||
|
echo ""
|
||||||
|
echo "=== Check what nginx sees ==="
|
||||||
|
docker compose exec -T staging-nginx sh -c "timeout 2 tail -f /var/log/nginx/error.log 2>&1 & sleep 1 && curl -s http://127.0.0.1/ > /dev/null && sleep 1" || echo "Log check failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: http_test
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display HTTP test results
|
||||||
|
debug:
|
||||||
|
msg: "{{ http_test.stdout_lines }}"
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
- name: Test Staging Container Access and Logs
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check if we can access containers directly
|
||||||
|
shell: |
|
||||||
|
# Try direct docker commands first
|
||||||
|
echo "=== Direct Docker Container Check ==="
|
||||||
|
docker ps -a --filter "name=staging"
|
||||||
|
echo ""
|
||||||
|
echo "=== Try docker logs directly ==="
|
||||||
|
docker logs staging-app --tail=20 2>&1 || echo "Could not access staging-app logs"
|
||||||
|
echo ""
|
||||||
|
echo "=== Try docker logs for staging-nginx ==="
|
||||||
|
docker logs staging-nginx --tail=20 2>&1 || echo "Could not access staging-nginx logs"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: direct_access
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display direct access results
|
||||||
|
debug:
|
||||||
|
msg: "{{ (direct_access.stdout_lines | default([])) + (direct_access.stderr_lines | default([])) }}"
|
||||||
|
|
||||||
|
- name: Try docker compose from different locations
|
||||||
|
shell: |
|
||||||
|
echo "=== Current directory ==="
|
||||||
|
pwd
|
||||||
|
echo ""
|
||||||
|
echo "=== Try from home directory ==="
|
||||||
|
cd ~ && docker compose -f ~/deployment/stacks/staging/docker-compose.yml ps 2>&1 || echo "Failed from home"
|
||||||
|
echo ""
|
||||||
|
echo "=== Try from staging directory ==="
|
||||||
|
cd ~/deployment/stacks/staging && docker compose ps 2>&1 || echo "Failed from staging directory"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: compose_check
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display compose check results
|
||||||
|
debug:
|
||||||
|
msg: "{{ (compose_check.stdout_lines | default([])) + (compose_check.stderr_lines | default([])) }}"
|
||||||
|
|
||||||
|
- name: Check docker compose configuration
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Docker Compose file exists? ==="
|
||||||
|
test -f docker-compose.yml && echo "? docker-compose.yml exists" || echo "? docker-compose.yml missing"
|
||||||
|
echo ""
|
||||||
|
echo "=== Docker Compose file first 30 lines ==="
|
||||||
|
head -30 docker-compose.yml
|
||||||
|
echo ""
|
||||||
|
echo "=== Check service names ==="
|
||||||
|
docker compose config --services 2>&1 || echo "Could not get service names"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: compose_config
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display compose configuration
|
||||||
|
debug:
|
||||||
|
msg: "{{ (compose_config.stdout_lines | default([])) + (compose_config.stderr_lines | default([])) }}"
|
||||||
|
|
||||||
|
- name: Try getting logs with explicit file path
|
||||||
|
shell: |
|
||||||
|
docker compose -f ~/deployment/stacks/stacks/staging/docker-compose.yml logs --tail=20 staging-app 2>&1 || \
|
||||||
|
docker compose -f ~/deployment/stacks/staging/docker-compose.yml logs --tail=20 staging-app 2>&1 || \
|
||||||
|
echo "All methods failed"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: explicit_logs
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display explicit logs attempt
|
||||||
|
debug:
|
||||||
|
msg: "{{ (explicit_logs.stdout_lines | default([])) + (explicit_logs.stderr_lines | default([])) }}"
|
||||||
44
deployment/ansible/playbooks/view-staging-logs-readable.yml
Normal file
44
deployment/ansible/playbooks/view-staging-logs-readable.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
- name: View Staging Logs in Readable Format
|
||||||
|
hosts: production
|
||||||
|
gather_facts: yes
|
||||||
|
become: no
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Get and format staging-app logs
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Staging App Logs (Last 50 lines, formatted) ==="
|
||||||
|
docker compose logs --tail=200 staging-app 2>&1 | \
|
||||||
|
while IFS= read -r line; do
|
||||||
|
# Try to parse JSON logs and format them nicely
|
||||||
|
if echo "$line" | grep -qE '^{|^\{'; then
|
||||||
|
echo "$line" | python3 -m json.tool 2>/dev/null || echo "$line"
|
||||||
|
else
|
||||||
|
echo "$line"
|
||||||
|
fi
|
||||||
|
done | tail -50
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: formatted_logs
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display formatted logs
|
||||||
|
debug:
|
||||||
|
msg: "{{ formatted_logs.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Show simple tail of logs (for quick view)
|
||||||
|
shell: |
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
echo "=== Quick View: Last 30 lines ==="
|
||||||
|
docker compose logs --tail=30 staging-app 2>&1
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: quick_logs
|
||||||
|
ignore_errors: yes
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display quick logs
|
||||||
|
debug:
|
||||||
|
msg: "{{ quick_logs.stdout_lines }}"
|
||||||
@@ -132,6 +132,10 @@
|
|||||||
- **[workflow-troubleshooting.md](reference/workflow-troubleshooting.md)** - Workflow Troubleshooting
|
- **[workflow-troubleshooting.md](reference/workflow-troubleshooting.md)** - Workflow Troubleshooting
|
||||||
- **[quick-start.md](guides/quick-start.md)** - Troubleshooting Quick Reference
|
- **[quick-start.md](guides/quick-start.md)** - Troubleshooting Quick Reference
|
||||||
|
|
||||||
|
### Staging-Probleme
|
||||||
|
|
||||||
|
- **[staging-502-nginx-phpfpm.md](troubleshooting/staging-502-nginx-phpfpm.md)** - Staging 502 Bad Gateway: Nginx kann nicht zu PHP-FPM verbinden
|
||||||
|
|
||||||
### Test-Dokumentation
|
### Test-Dokumentation
|
||||||
|
|
||||||
- **[test-results.md](tests/test-results.md)** - Test Ergebnisse
|
- **[test-results.md](tests/test-results.md)** - Test Ergebnisse
|
||||||
@@ -174,7 +178,8 @@
|
|||||||
|
|
||||||
1. **[quick-start.md](guides/quick-start.md)** - Quick Troubleshooting
|
1. **[quick-start.md](guides/quick-start.md)** - Quick Troubleshooting
|
||||||
2. **[workflow-troubleshooting.md](reference/workflow-troubleshooting.md)** - Workflow-Probleme
|
2. **[workflow-troubleshooting.md](reference/workflow-troubleshooting.md)** - Workflow-Probleme
|
||||||
3. Stack-spezifische READMEs f?r Details
|
3. **[staging-502-nginx-phpfpm.md](troubleshooting/staging-502-nginx-phpfpm.md)** - Staging 502 Fehler (Nginx/PHP-FPM)
|
||||||
|
4. Stack-spezifische READMEs f?r Details
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
169
deployment/docs/troubleshooting/staging-502-nginx-phpfpm.md
Normal file
169
deployment/docs/troubleshooting/staging-502-nginx-phpfpm.md
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
# Staging 502 Bad Gateway - Nginx PHP-FPM Connection Issue
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Staging-Server zeigt **502 Bad Gateway** Fehler auf `https://staging.michaelschiemer.de/`.
|
||||||
|
|
||||||
|
Nginx-Fehlerlog zeigt:
|
||||||
|
```
|
||||||
|
connect() failed (111: Connection refused) while connecting to upstream,
|
||||||
|
client: 172.21.0.4, server: _, request: "GET / HTTP/1.1",
|
||||||
|
upstream: "fastcgi://127.0.0.1:9000"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ursache
|
||||||
|
|
||||||
|
**Root Cause:** Nginx versucht, sich mit PHP-FPM auf `127.0.0.1:9000` (localhost) zu verbinden, aber PHP-FPM l?uft in einem **separaten Docker-Container** (`staging-app`).
|
||||||
|
|
||||||
|
### Technische Details
|
||||||
|
|
||||||
|
1. **Nginx-Konfiguration:** Es gibt zwei Nginx-Konfigurationsdateien:
|
||||||
|
- `/etc/nginx/conf.d/default.conf` ? Korrekt: verwendet `upstream php-upstream { server staging-app:9000; }`
|
||||||
|
- `/etc/nginx/sites-available/default` ? Falsch: verwendet `upstream php-upstream { server 127.0.0.1:9000; }`
|
||||||
|
|
||||||
|
2. **Nginx Include-Ordnung:** `nginx.conf` inkludiert:
|
||||||
|
```nginx
|
||||||
|
include /etc/nginx/sites-enabled/*; # Wird ZULETZT geladen
|
||||||
|
include /etc/nginx/conf.d/*.conf; # Wird ZUERST geladen
|
||||||
|
```
|
||||||
|
Da `sites-enabled/default` **nach** `conf.d/default.conf` geladen wird, **?berschreibt** sie die korrekte Konfiguration.
|
||||||
|
|
||||||
|
3. **Container-Architektur:**
|
||||||
|
- `staging-nginx` Container: L?uft Nginx
|
||||||
|
- `staging-app` Container: L?uft PHP-FPM auf Port 9000
|
||||||
|
- Beide Container sind im `staging-internal` Docker-Netzwerk
|
||||||
|
|
||||||
|
## L?sung
|
||||||
|
|
||||||
|
### Sofort-Fix (Manuell)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
|
||||||
|
# Fix upstream in sites-available/default
|
||||||
|
docker compose exec -T staging-nginx sed -i '/upstream php-upstream {/,/}/s|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default
|
||||||
|
|
||||||
|
# Reload nginx
|
||||||
|
docker compose restart staging-nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
Oder mit Ansible:
|
||||||
|
```bash
|
||||||
|
ansible-playbook -i deployment/ansible/inventory/production.yml deployment/ansible/playbooks/fix-sites-available-default.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Permanente L?sung
|
||||||
|
|
||||||
|
Das Entrypoint-Script in `deployment/stacks/staging/docker-compose.yml` (Zeilen 181-192) wurde erweitert, um das Problem **automatisch beim Container-Start** zu beheben:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fix nginx upstream configuration - sites-enabled/default overrides conf.d/default.conf
|
||||||
|
if [ -f "/etc/nginx/sites-available/default" ]; then
|
||||||
|
echo "?? [staging-nginx] Fixing PHP-FPM upstream configuration..."
|
||||||
|
# Replace in upstream block
|
||||||
|
sed -i '/upstream php-upstream {/,/}/s|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || true
|
||||||
|
sed -i '/upstream php-upstream {/,/}/s|server localhost:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || true
|
||||||
|
# Replace any direct fastcgi_pass references too
|
||||||
|
sed -i 's|fastcgi_pass 127.0.0.1:9000;|fastcgi_pass php-upstream;|g' /etc/nginx/sites-available/default || true
|
||||||
|
sed -i 's|fastcgi_pass localhost:9000;|fastcgi_pass php-upstream;|g' /etc/nginx/sites-available/default || true
|
||||||
|
echo "? [staging-nginx] PHP-FPM upstream fixed"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Diagnose-Schritte
|
||||||
|
|
||||||
|
Wenn das Problem erneut auftritt:
|
||||||
|
|
||||||
|
### 1. Pr?fe Nginx Error Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/deployment/stacks/staging
|
||||||
|
docker compose logs --tail=50 staging-nginx | grep -i "502\|error\|upstream"
|
||||||
|
```
|
||||||
|
|
||||||
|
Oder direkt im Container:
|
||||||
|
```bash
|
||||||
|
docker compose exec -T staging-nginx tail -100 /var/log/nginx/error.log
|
||||||
|
```
|
||||||
|
|
||||||
|
**Erwartete Fehlermeldung bei diesem Problem:**
|
||||||
|
```
|
||||||
|
connect() failed (111: Connection refused) while connecting to upstream,
|
||||||
|
upstream: "fastcgi://127.0.0.1:9000"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Pr?fe PHP-FPM Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Container-Status
|
||||||
|
docker compose ps staging-app staging-nginx
|
||||||
|
|
||||||
|
# PHP-FPM l?uft?
|
||||||
|
docker compose exec -T staging-app netstat -tlnp | grep 9000
|
||||||
|
# Oder:
|
||||||
|
docker compose exec -T staging-app ss -tlnp | grep 9000
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Pr?fe Upstream-Konfiguration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Welche upstream-Definition wird verwendet?
|
||||||
|
docker compose exec -T staging-nginx grep -A 3 "upstream php-upstream" /etc/nginx/sites-available/default
|
||||||
|
docker compose exec -T staging-nginx grep -A 3 "upstream php-upstream" /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Welche fastcgi_pass Direktiven gibt es?
|
||||||
|
docker compose exec -T staging-nginx grep "fastcgi_pass" /etc/nginx/sites-available/default
|
||||||
|
docker compose exec -T staging-nginx grep "fastcgi_pass" /etc/nginx/conf.d/default.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
**Erwartetes Ergebnis (korrekt):**
|
||||||
|
```
|
||||||
|
upstream php-upstream {
|
||||||
|
server staging-app:9000;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fehlerhaft (zeigt Problem):**
|
||||||
|
```
|
||||||
|
upstream php-upstream {
|
||||||
|
server 127.0.0.1:9000; # ? FALSCH
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Teste Verbindung von Nginx zu PHP-FPM
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Kann nginx sich mit staging-app:9000 verbinden?
|
||||||
|
docker compose exec -T staging-nginx curl -v http://staging-app:9000 2>&1 | head -20
|
||||||
|
|
||||||
|
# Oder teste direkt mit FastCGI (wenn cgi-fcgi installiert ist)
|
||||||
|
docker compose exec -T staging-nginx sh -c "echo -e 'REQUEST_METHOD=GET\nSCRIPT_FILENAME=/var/www/html/public/index.php\n' | cgi-fcgi -bind -connect staging-app:9000"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Vollst?ndige Diagnose mit Ansible
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook -i deployment/ansible/inventory/production.yml \
|
||||||
|
deployment/ansible/playbooks/diagnose-staging-502.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verwandte Dateien
|
||||||
|
|
||||||
|
- **Docker Compose Config:** `deployment/stacks/staging/docker-compose.yml`
|
||||||
|
- **Nginx Config (korrekt):** `deployment/stacks/staging/nginx/conf.d/default.conf`
|
||||||
|
- **Nginx Config (problem):** `/etc/nginx/sites-available/default` (im Container)
|
||||||
|
- **Diagnose-Playbooks:**
|
||||||
|
- `deployment/ansible/playbooks/diagnose-staging-502.yml`
|
||||||
|
- `deployment/ansible/playbooks/fix-sites-available-default.yml`
|
||||||
|
|
||||||
|
## Verhindern in Zukunft
|
||||||
|
|
||||||
|
1. **Entrypoint-Script:** Das Entrypoint-Script behebt das Problem automatisch beim Container-Start
|
||||||
|
2. **Image-Build:** Idealerweise sollte die `sites-available/default` Datei im Docker-Image bereits korrekt konfiguriert sein
|
||||||
|
3. **Alternativ:** Entferne `sites-available/default` komplett und verwende nur `conf.d/default.conf`
|
||||||
|
|
||||||
|
## Siehe auch
|
||||||
|
|
||||||
|
- [Staging Stack README](../../stacks/staging/README.md)
|
||||||
|
- [Nginx Configuration](../../stacks/staging/nginx/conf.d/default.conf)
|
||||||
|
- [Troubleshooting Overview](../README.md)
|
||||||
@@ -117,6 +117,12 @@ services:
|
|||||||
echo ""
|
echo ""
|
||||||
echo "📊 Environment variables:"
|
echo "📊 Environment variables:"
|
||||||
env | grep -E "DB_|APP_" | grep -v "PASSWORD|KEY|SECRET" || true
|
env | grep -E "DB_|APP_" | grep -v "PASSWORD|KEY|SECRET" || true
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🛠️ Adjusting filesystem permissions..."
|
||||||
|
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache 2>/dev/null || true
|
||||||
|
find /var/www/html/storage /var/www/html/bootstrap/cache -type d -exec chmod 775 {} \; 2>/dev/null || true
|
||||||
|
find /var/www/html/storage /var/www/html/bootstrap/cache -type f -exec chmod 664 {} \; 2>/dev/null || true
|
||||||
|
|
||||||
# Start PHP-FPM only (no nginx)
|
# Start PHP-FPM only (no nginx)
|
||||||
echo ""
|
echo ""
|
||||||
@@ -179,14 +185,16 @@ services:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Fix nginx upstream configuration - sites-enabled/default overrides conf.d/default.conf
|
# Fix nginx upstream configuration - sites-enabled/default overrides conf.d/default.conf
|
||||||
|
# This is critical: nginx sites-available/default uses 127.0.0.1:9000 but PHP-FPM runs in staging-app container
|
||||||
if [ -f "/etc/nginx/sites-available/default" ]; then
|
if [ -f "/etc/nginx/sites-available/default" ]; then
|
||||||
echo "🔧 [staging-nginx] Fixing PHP-FPM upstream configuration..."
|
echo "🔧 [staging-nginx] Fixing PHP-FPM upstream configuration..."
|
||||||
sed -i 's|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || true
|
# Replace in upstream block
|
||||||
sed -i 's|server localhost:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || true
|
sed -i '/upstream php-upstream {/,/}/s|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || true
|
||||||
# Also check and fix upstream definition directly
|
sed -i '/upstream php-upstream {/,/}/s|server localhost:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || true
|
||||||
if grep -q "server 127.0.0.1:9000" /etc/nginx/sites-available/default; then
|
# Replace any direct fastcgi_pass references too
|
||||||
sed -i '/upstream php-upstream {/,/}/s/server 127.0.0.1:9000;/server staging-app:9000;/' /etc/nginx/sites-available/default || true
|
sed -i 's|fastcgi_pass 127.0.0.1:9000;|fastcgi_pass php-upstream;|g' /etc/nginx/sites-available/default || true
|
||||||
fi
|
sed -i 's|fastcgi_pass localhost:9000;|fastcgi_pass php-upstream;|g' /etc/nginx/sites-available/default || true
|
||||||
|
echo "✅ [staging-nginx] PHP-FPM upstream fixed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Start nginx only (no PHP-FPM, no Git clone - staging-app container handles that)
|
# Start nginx only (no PHP-FPM, no Git clone - staging-app container handles that)
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ echo ""
|
|||||||
echo "📊 Environment variables:"
|
echo "📊 Environment variables:"
|
||||||
env | grep -E "DB_|APP_" | grep -v "PASSWORD|KEY|SECRET" || true
|
env | grep -E "DB_|APP_" | grep -v "PASSWORD|KEY|SECRET" || true
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🛠️ Adjusting filesystem permissions..."
|
||||||
|
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache 2>/dev/null || true
|
||||||
|
find /var/www/html/storage /var/www/html/bootstrap/cache -type d -exec chmod 775 {} \; 2>/dev/null || true
|
||||||
|
find /var/www/html/storage /var/www/html/bootstrap/cache -type f -exec chmod 664 {} \; 2>/dev/null || true
|
||||||
|
|
||||||
# Start PHP-FPM in background (inherits all environment variables)
|
# Start PHP-FPM in background (inherits all environment variables)
|
||||||
echo ""
|
echo ""
|
||||||
echo "🚀 Starting PHP-FPM..."
|
echo "🚀 Starting PHP-FPM..."
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use App\Framework\Auth\RouteAuthorizationService;
|
|||||||
use App\Framework\Config\TypedConfiguration;
|
use App\Framework\Config\TypedConfiguration;
|
||||||
use App\Framework\DI\Container;
|
use App\Framework\DI\Container;
|
||||||
use App\Framework\Http\HttpMiddleware;
|
use App\Framework\Http\HttpMiddleware;
|
||||||
|
use App\Framework\Http\HttpRequest;
|
||||||
use App\Framework\Http\MiddlewareContext;
|
use App\Framework\Http\MiddlewareContext;
|
||||||
use App\Framework\Http\MiddlewarePriority;
|
use App\Framework\Http\MiddlewarePriority;
|
||||||
use App\Framework\Http\MiddlewarePriorityAttribute;
|
use App\Framework\Http\MiddlewarePriorityAttribute;
|
||||||
@@ -27,6 +28,7 @@ use App\Framework\Router\Result\ViewResult;
|
|||||||
use App\Framework\Router\RouteContext;
|
use App\Framework\Router\RouteContext;
|
||||||
use App\Framework\Router\RouteDispatcher;
|
use App\Framework\Router\RouteDispatcher;
|
||||||
use App\Framework\Router\Router;
|
use App\Framework\Router\Router;
|
||||||
|
use App\Framework\Router\ValueObjects\RouteParameters;
|
||||||
|
|
||||||
#[MiddlewarePriorityAttribute(MiddlewarePriority::ROUTING)]
|
#[MiddlewarePriorityAttribute(MiddlewarePriority::ROUTING)]
|
||||||
final readonly class RoutingMiddleware implements HttpMiddleware
|
final readonly class RoutingMiddleware implements HttpMiddleware
|
||||||
@@ -54,7 +56,7 @@ final readonly class RoutingMiddleware implements HttpMiddleware
|
|||||||
*/
|
*/
|
||||||
public function __invoke(MiddlewareContext $context, Next $next, RequestStateManager $stateManager): MiddlewareContext
|
public function __invoke(MiddlewareContext $context, Next $next, RequestStateManager $stateManager): MiddlewareContext
|
||||||
{
|
{
|
||||||
error_log("DEBUG RoutingMiddleware: __invoke() called - Path: " . $context->request->path);
|
#error_log("DEBUG RoutingMiddleware: __invoke() called - Path: " . $context->request->path);
|
||||||
|
|
||||||
$request = $context->request;
|
$request = $context->request;
|
||||||
|
|
||||||
@@ -98,7 +100,7 @@ final readonly class RoutingMiddleware implements HttpMiddleware
|
|||||||
$route = $routeContext->match->route;
|
$route = $routeContext->match->route;
|
||||||
if ($route instanceof \App\Framework\Core\DynamicRoute && ! empty($route->paramValues)) {
|
if ($route instanceof \App\Framework\Core\DynamicRoute && ! empty($route->paramValues)) {
|
||||||
error_log("DEBUG: Route param values extracted: " . json_encode($route->paramValues));
|
error_log("DEBUG: Route param values extracted: " . json_encode($route->paramValues));
|
||||||
$request = new \App\Framework\Http\HttpRequest(
|
$request = new HttpRequest(
|
||||||
method: $request->method,
|
method: $request->method,
|
||||||
headers: $request->headers,
|
headers: $request->headers,
|
||||||
body: $request->body,
|
body: $request->body,
|
||||||
@@ -109,13 +111,13 @@ final readonly class RoutingMiddleware implements HttpMiddleware
|
|||||||
server: $request->server,
|
server: $request->server,
|
||||||
id: $request->id,
|
id: $request->id,
|
||||||
parsedBody: $request->parsedBody,
|
parsedBody: $request->parsedBody,
|
||||||
routeParameters: \App\Framework\Router\ValueObjects\RouteParameters::fromArray($route->paramValues)
|
routeParameters: RouteParameters::fromArray($route->paramValues)
|
||||||
);
|
);
|
||||||
$context = new MiddlewareContext($request, $context->response);
|
$context = new MiddlewareContext($request, $context->response);
|
||||||
|
|
||||||
// Update request in container so dispatcher gets the updated request
|
// Update request in container so dispatcher gets the updated request
|
||||||
$this->container->instance(Request::class, $request);
|
$this->container->instance(Request::class, $request);
|
||||||
$this->container->instance(\App\Framework\Http\HttpRequest::class, $request);
|
$this->container->instance(HttpRequest::class, $request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform route authorization checks
|
// Perform route authorization checks
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ final readonly class RouteDebugger
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private McpToolContext $context,
|
private McpToolContext $context,
|
||||||
private CompiledRoutes $compiledRoutes,
|
private CompiledRoutes $compiledRoutes,
|
||||||
private Router $router,
|
#private Router $router,
|
||||||
private MiddlewareManager $middlewareManager
|
private MiddlewareManager $middlewareManager
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ use App\Framework\Context\ContextType;
|
|||||||
use App\Framework\Core\PathProvider;
|
use App\Framework\Core\PathProvider;
|
||||||
use App\Framework\Core\RouteCache;
|
use App\Framework\Core\RouteCache;
|
||||||
use App\Framework\Core\RouteCompiler;
|
use App\Framework\Core\RouteCompiler;
|
||||||
|
use App\Framework\DI\Container;
|
||||||
use App\Framework\DI\DefaultContainer;
|
use App\Framework\DI\DefaultContainer;
|
||||||
use App\Framework\DI\Initializer;
|
use App\Framework\DI\Initializer;
|
||||||
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
||||||
|
use App\Framework\Http\Method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verantwortlich für die Einrichtung des Routers
|
* Verantwortlich für die Einrichtung des Routers
|
||||||
@@ -19,11 +21,10 @@ use App\Framework\Discovery\Results\DiscoveryRegistry;
|
|||||||
final readonly class RouterSetup
|
final readonly class RouterSetup
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private DefaultContainer $container,
|
private Container $container,
|
||||||
private RouteCompiler $routeCompiler,
|
private RouteCompiler $routeCompiler,
|
||||||
private DiscoveryRegistry $results,
|
private DiscoveryRegistry $results,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Richtet den Router basierend auf den verarbeiteten Attributen ein
|
* Richtet den Router basierend auf den verarbeiteten Attributen ein
|
||||||
@@ -57,12 +58,12 @@ final readonly class RouterSetup
|
|||||||
error_log("🚦 ROUTER SETUP: HTTP Methods count = " . count($staticRoutes));
|
error_log("🚦 ROUTER SETUP: HTTP Methods count = " . count($staticRoutes));
|
||||||
|
|
||||||
// Check GET method subdomain keys
|
// Check GET method subdomain keys
|
||||||
$getSubdomainKeys = $optimizedRoutes->getSubdomainKeys(\App\Framework\Http\Method::GET);
|
$getSubdomainKeys = $optimizedRoutes->getSubdomainKeys(Method::GET);
|
||||||
error_log("🚦 ROUTER SETUP: GET method has subdomain keys: " . json_encode($getSubdomainKeys));
|
error_log("🚦 ROUTER SETUP: GET method has subdomain keys: " . json_encode($getSubdomainKeys));
|
||||||
|
|
||||||
// Log routes per subdomain for GET
|
// Log routes per subdomain for GET
|
||||||
foreach ($getSubdomainKeys as $subdomainKey) {
|
foreach ($getSubdomainKeys as $subdomainKey) {
|
||||||
$routes = $optimizedRoutes->getStaticRoutesForSubdomain(\App\Framework\Http\Method::GET, $subdomainKey);
|
$routes = $optimizedRoutes->getStaticRoutesForSubdomain(Method::GET, $subdomainKey);
|
||||||
error_log("🚦 ROUTER SETUP: GET subdomain '{$subdomainKey}' has " . count($routes) . " routes");
|
error_log("🚦 ROUTER SETUP: GET subdomain '{$subdomainKey}' has " . count($routes) . " routes");
|
||||||
foreach ($routes as $path => $route) {
|
foreach ($routes as $path => $route) {
|
||||||
error_log("🚦 ROUTER SETUP: - {$path}");
|
error_log("🚦 ROUTER SETUP: - {$path}");
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace App\Framework\Storage;
|
|||||||
|
|
||||||
interface ObjectStorage
|
interface ObjectStorage
|
||||||
{
|
{
|
||||||
public function put(string $bucket, string $key, string|mixed $body, array $opts = []): ObjectInfo;
|
public function put(string $bucket, string $key, string $body, array $opts = []): ObjectInfo;
|
||||||
public function get(string $bucket, string $key): string;
|
public function get(string $bucket, string $key): string;
|
||||||
public function stream(string $bucket, string $key); // resource|StreamInterface
|
public function stream(string $bucket, string $key); // resource|StreamInterface
|
||||||
public function head(string $bucket, string $key): ObjectInfo;
|
public function head(string $bucket, string $key): ObjectInfo;
|
||||||
|
|||||||
155
src/Framework/Storage/STREAMING_IMPLEMENTATION_PLAN.md
Normal file
155
src/Framework/Storage/STREAMING_IMPLEMENTATION_PLAN.md
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
# Streaming-Implementationsliste (Option 2) – Storage Modul
|
||||||
|
|
||||||
|
Ziel: Dedizierte Streaming-Methoden in der Object Storage API implementieren – ohne externe Dependencies. Fokus auf speichereffiziente Downloads/Uploads großer Dateien via Streams (memory-safe).
|
||||||
|
|
||||||
|
## 1) Interface-Erweiterung (ObjectStorage)
|
||||||
|
- Ergänze folgende Methoden im ObjectStorage-Interface:
|
||||||
|
- get(string $bucket, string $key): string
|
||||||
|
- put(string $bucket, string $key, string|mixed $body, array $opts = []): ObjectInfo
|
||||||
|
- getToStream(string $bucket, string $key, mixed $destination): int
|
||||||
|
- Erwartet eine schreibbare PHP-Stream-Resource als $destination
|
||||||
|
- Rückgabewert: Anzahl geschriebener Bytes
|
||||||
|
- putFromStream(string $bucket, string $key, mixed $source, array $opts = []): ObjectInfo
|
||||||
|
- Erwartet eine lesbare PHP-Stream-Resource als $source
|
||||||
|
- openReadStream(string $bucket, string $key)
|
||||||
|
- Gibt eine lesbare PHP-Stream-Resource zurück
|
||||||
|
- head(string $bucket, string $key): ObjectInfo
|
||||||
|
- delete(string $bucket, string $key): void
|
||||||
|
- exists(string $bucket, string $key): bool
|
||||||
|
- url(string $bucket, string $key): ?string
|
||||||
|
- temporaryUrl(string $bucket, string $key, \DateInterval $ttl, array $opts = []): string
|
||||||
|
|
||||||
|
Hinweise:
|
||||||
|
- Signaturen mit mixed für Stream-Parameter (PHP-Resource), genaue Validierung in den Implementierungen.
|
||||||
|
- Bestehende Methoden get/put bleiben kompatibel; Streaming ist ergänzend.
|
||||||
|
|
||||||
|
## 2) Filesystem-Adapter (lokales Backend)
|
||||||
|
Ziel: ObjectStorage-Implementierung auf Basis des bestehenden Filesystem-Backends.
|
||||||
|
|
||||||
|
- Neue Klasse: src/Framework/Storage/FilesystemObjectStorage.php
|
||||||
|
- Verantwortlichkeiten:
|
||||||
|
- Pfadaufbau: basePath/bucket/key
|
||||||
|
- get/put über Filesystem (kleine Dateien)
|
||||||
|
- Streaming:
|
||||||
|
- getToStream: Datei lesen und via stream_copy_to_stream in $destination schreiben
|
||||||
|
- putFromStream: Stream-Inhalt in Datei schreiben (Chunked Copy)
|
||||||
|
- openReadStream: lesbaren Stream auf die Datei öffnen
|
||||||
|
- head/exists/delete/url/temporaryUrl:
|
||||||
|
- head: Dateigröße, mtime, mimetype (falls verfügbar)
|
||||||
|
- url: für lokales Storage in der Regel null (oder optionaler lokaler URL-Generator)
|
||||||
|
- temporaryUrl: nicht unterstützt -> Exception oder leer lassen mit Doku
|
||||||
|
- Fehlerbehandlung:
|
||||||
|
- File not found, Permission, Read/Write-Errors sauber abbilden
|
||||||
|
- Performance:
|
||||||
|
- Buffersize bei stream_copy_to_stream kontrollierbar machen (Optionen)
|
||||||
|
|
||||||
|
## 3) MinIO-Backend (ohne Dependencies)
|
||||||
|
Ziel: S3-kompatibler MinIO-Client mittels nativer PHP-Funktionen (HTTP-Streams und AWS SigV4) + ObjectStorage-Adapter.
|
||||||
|
|
||||||
|
- Dateien:
|
||||||
|
- src/Framework/Storage/Clients/MinioClient.php
|
||||||
|
- Funktionen: putObject, getObject, headObject, deleteObject, createPresignedUrl
|
||||||
|
- Streaming-Funktionen:
|
||||||
|
- getObjectToStream($bucket, $key, $destination): int
|
||||||
|
- putObjectFromStream($bucket, $key, $source, array $opts = []): array
|
||||||
|
- openStream($bucket, $key) -> resource
|
||||||
|
- Interne Helfer:
|
||||||
|
- AWS SigV4 Signierung (kanonische Anfrage, Header, Query, Hashes)
|
||||||
|
- Response-Parsing (Headers, Status, Fehler-XML)
|
||||||
|
- Chunked Transfer wenn keine Content-Length verfügbar
|
||||||
|
- src/Framework/Storage/MinioObjectStorage.php
|
||||||
|
- Implementiert ObjectStorage
|
||||||
|
- get/put: kleinere Dateien
|
||||||
|
- getToStream/putFromStream/openReadStream: nutzen die Streaming-APIs des MinioClient
|
||||||
|
- head/delete/exists/url/temporaryUrl:
|
||||||
|
- temporaryUrl via createPresignedUrl
|
||||||
|
- Sicherheit:
|
||||||
|
- TTL-Limits für temporaryUrl (z. B. max 24h)
|
||||||
|
- Path-Style vs. Virtual Host Style konfigurierbar
|
||||||
|
- Keine externen Pakete
|
||||||
|
|
||||||
|
## 4) Manager/Factory/DI
|
||||||
|
- Option A: StorageManager für ObjectStorage-Driver (local/minio)
|
||||||
|
- src/Framework/Storage/StorageManager.php
|
||||||
|
- driver(string $name): ObjectStorage
|
||||||
|
- bucket(string $name): Bucket (Convenience)
|
||||||
|
- Option B (einfach): Container-Bindings direkt
|
||||||
|
- Default ObjectStorage anhand ENV
|
||||||
|
- Initializer:
|
||||||
|
- src/Framework/Storage/StorageInitializer.php
|
||||||
|
- Konfig aus ENV (DEFAULT_DRIVER, MINIO_ENDPOINT, KEYS, LOCAL_ROOT, PATH_STYLE etc.)
|
||||||
|
- Registriere:
|
||||||
|
- FilesystemObjectStorage (als "local")
|
||||||
|
- MinioClient + MinioObjectStorage (als "minio")
|
||||||
|
- ObjectStorage (Default: ENV)
|
||||||
|
- Bucket-API (optional aber DX-freundlich):
|
||||||
|
- src/Framework/Storage/Bucket.php
|
||||||
|
- wrappt ObjectStorage für festen Bucket-Namen
|
||||||
|
|
||||||
|
## 5) Konfiguration
|
||||||
|
- ENV Variablen vorschlagen (Beispiele):
|
||||||
|
- STORAGE_DRIVER=local|minio
|
||||||
|
- STORAGE_LOCAL_ROOT=/var/www/html/storage/objects
|
||||||
|
- MINIO_ENDPOINT=http://minio:9000
|
||||||
|
- MINIO_ACCESS_KEY=...
|
||||||
|
- MINIO_SECRET_KEY=...
|
||||||
|
- MINIO_REGION=us-east-1
|
||||||
|
- MINIO_USE_PATH_STYLE=true
|
||||||
|
- StorageConfig Klasse (optional) für strukturierte Konfig-Verwaltung
|
||||||
|
|
||||||
|
## 6) Tests (kritisch, da streaming-sensitiv)
|
||||||
|
- Unit-Tests FilesystemObjectStorage:
|
||||||
|
- put/get mit Strings
|
||||||
|
- putFromStream/getToStream mit temp Streams (php://temp)
|
||||||
|
- openReadStream und sequentielles Lesen
|
||||||
|
- head/exists/delete
|
||||||
|
- Unit-Tests MinioClient (Signierung) – isoliert:
|
||||||
|
- Signatur-Konsistenz (Golden Master)
|
||||||
|
- Parsing von Fehlern/Headers
|
||||||
|
- Integration-Tests (optional, per docker-compose mit MinIO):
|
||||||
|
- Upload/Download großer Dateien (z. B. >100MB) per Streams
|
||||||
|
- temporaryUrl Zugriff (GET) mit TTL
|
||||||
|
- Edge Cases:
|
||||||
|
- fehlende Read-/Write-Berechtigungen (Filesystem)
|
||||||
|
- Netzwerkfehler (MinIO)
|
||||||
|
- Nicht existierende Objekte
|
||||||
|
- Streams ohne bekannte Länge (Chunked Transfer)
|
||||||
|
|
||||||
|
## 7) Fehler- und Ausnahmebehandlung
|
||||||
|
- Konsistente Exceptions im Storage-Namespace (z. B. StorageException)
|
||||||
|
- Filesystem-spezifische Fehler sauber mappen
|
||||||
|
- Aussagekräftige Meldungen (inkl. Pfad/Bucket/Key)
|
||||||
|
|
||||||
|
## 8) Performance/Robustheit
|
||||||
|
- Stream-Buffer konfigurierbar (z. B. 8192 Bytes Default)
|
||||||
|
- Keine vollständigen Dateiladungen in Memory bei Streams
|
||||||
|
- Zeitouts/Retry-Strategie (MinIO) minimal vorsehen (optional)
|
||||||
|
- Sauberes Schließen aller Streams (try/finally)
|
||||||
|
|
||||||
|
## 9) Sicherheit
|
||||||
|
- Path-Sanitizing im Filesystem-Adapter (keine Directory-Traversal)
|
||||||
|
- Eindeutige Handhabung von public URL vs. presigned URL
|
||||||
|
- Limitierung der Presign-Dauer und Validierung von Eingaben
|
||||||
|
|
||||||
|
## 10) Dokumentation
|
||||||
|
- README/HowTo:
|
||||||
|
- Beispiel für lokale und MinIO-Nutzung
|
||||||
|
- Beispiele für Streaming (Upload/Download)
|
||||||
|
- Hinweise zu großen Dateien, Memory-Effizienz
|
||||||
|
- PHPDoc ausführlich an allen Public-APIs
|
||||||
|
|
||||||
|
## 11) Milestones (Reihenfolge)
|
||||||
|
1. Interface-Änderungen (ObjectStorage)
|
||||||
|
2. FilesystemObjectStorage (inkl. Streaming)
|
||||||
|
3. MinioClient (Basis + Signierung)
|
||||||
|
4. MinioObjectStorage (inkl. Streaming)
|
||||||
|
5. Initializer/DI und Konfig
|
||||||
|
6. Tests (Unit), danach optional Integration
|
||||||
|
7. Doku + Beispiele
|
||||||
|
|
||||||
|
## 12) Definition of Done
|
||||||
|
- Alle neuen Methoden implementiert und getestet
|
||||||
|
- Große Dateien via Streams funktionieren, ohne OOM
|
||||||
|
- Kein externer Dependency-Einsatz
|
||||||
|
- Doku und Beispiele vorhanden
|
||||||
|
- CI-Tests grün (Unit; Integration optional)
|
||||||
@@ -6,6 +6,7 @@ namespace App\Infrastructure\Database\Migrations;
|
|||||||
|
|
||||||
use App\Framework\Database\Migration\Migration;
|
use App\Framework\Database\Migration\Migration;
|
||||||
use App\Framework\Database\ConnectionInterface;
|
use App\Framework\Database\ConnectionInterface;
|
||||||
|
use App\Framework\Database\Migration\MigrationVersion;
|
||||||
use App\Framework\Database\Schema\Schema;
|
use App\Framework\Database\Schema\Schema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,9 +68,9 @@ final readonly class CreateComponentStateHistoryTable implements Migration
|
|||||||
$schema->execute();
|
$schema->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVersion(): string
|
public function getVersion(): MigrationVersion
|
||||||
{
|
{
|
||||||
return '2024_12_20_120100';
|
return MigrationVersion::fromTimestamp('2024_12_20_120000');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDescription(): string
|
public function getDescription(): string
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace App\Infrastructure\Database\Migrations;
|
|||||||
|
|
||||||
use App\Framework\Database\Migration\Migration;
|
use App\Framework\Database\Migration\Migration;
|
||||||
use App\Framework\Database\ConnectionInterface;
|
use App\Framework\Database\ConnectionInterface;
|
||||||
|
use App\Framework\Database\Migration\MigrationVersion;
|
||||||
use App\Framework\Database\Schema\Schema;
|
use App\Framework\Database\Schema\Schema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,9 +54,9 @@ final readonly class CreateComponentStateTable implements Migration
|
|||||||
$schema->execute();
|
$schema->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVersion(): string
|
public function getVersion(): MigrationVersion
|
||||||
{
|
{
|
||||||
return '2024_12_20_120000';
|
return MigrationVersion::fromString('2024_12_20_120000');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDescription(): string
|
public function getDescription(): string
|
||||||
|
|||||||
Reference in New Issue
Block a user