From 8344032fb67162b5259309143d5ebac2918607c3 Mon Sep 17 00:00:00 2001 From: Michael Schiemer Date: Sun, 2 Nov 2025 15:58:30 +0100 Subject: [PATCH] feat: add Redis connection diagnostics, VPN routing fixes, and Traefik middleware updates --- .../playbooks/check-redis-connection.yml | 193 +++++++++++++ .../check-staging-redis-connection.yml | 255 ++++++++++++++++++ .../check-staging-redis-env-file.yml | 135 ++++++++++ .../playbooks/diagnose-vpn-routing.yml | 172 ++++++++++++ .../playbooks/fix-grafana-vpn-access.yml | 67 +++++ .../test-redis-connection-direct.yml | 121 +++++++++ .../stacks/traefik/dynamic/middlewares.yml | 16 +- docs/deployment/GRAFANA-VPN-ACCESS.md | 108 ++++++++ docs/deployment/VPN-ROUTING-CLIENT-CHECK.md | 195 ++++++++++++++ docs/deployment/VPN-ROUTING-FIX.md | 120 +++++++++ src/Framework/Core/AppBootstrapper.php | 3 + src/Framework/Redis/RedisConnectionPool.php | 1 - 12 files changed, 1380 insertions(+), 6 deletions(-) create mode 100644 deployment/ansible/playbooks/check-redis-connection.yml create mode 100644 deployment/ansible/playbooks/check-staging-redis-connection.yml create mode 100644 deployment/ansible/playbooks/check-staging-redis-env-file.yml create mode 100644 deployment/ansible/playbooks/diagnose-vpn-routing.yml create mode 100644 deployment/ansible/playbooks/fix-grafana-vpn-access.yml create mode 100644 deployment/ansible/playbooks/test-redis-connection-direct.yml create mode 100644 docs/deployment/GRAFANA-VPN-ACCESS.md create mode 100644 docs/deployment/VPN-ROUTING-CLIENT-CHECK.md create mode 100644 docs/deployment/VPN-ROUTING-FIX.md diff --git a/deployment/ansible/playbooks/check-redis-connection.yml b/deployment/ansible/playbooks/check-redis-connection.yml new file mode 100644 index 00000000..10f96900 --- /dev/null +++ b/deployment/ansible/playbooks/check-redis-connection.yml @@ -0,0 +1,193 @@ +--- +- name: Check Redis Connection and Environment Variables in PHP Container + hosts: production + gather_facts: yes + become: no + + tasks: + - name: Check if application stack is running + shell: | + cd ~/deployment/stacks/application + docker compose ps + args: + executable: /bin/bash + register: stack_status + ignore_errors: yes + failed_when: false + + - name: Display stack status + debug: + msg: "{{ stack_status.stdout_lines }}" + + - name: Check PHP container exists + shell: | + docker ps --filter "name=app" + args: + executable: /bin/bash + register: php_container + ignore_errors: yes + failed_when: false + + - name: Display PHP container status + debug: + msg: "{{ php_container.stdout_lines }}" + + - name: Check Environment Variables in PHP Container + shell: | + echo "=== Redis Environment Variables in PHP Container ===" + docker exec app env | grep -E "(REDIS_|CACHE_|SESSION_|QUEUE_)" || echo "Container not accessible or no Redis vars found" + echo "" + echo "=== All Environment Variables in PHP Container ===" + docker exec app env | sort | head -50 || echo "Container not accessible" + args: + executable: /bin/bash + register: env_vars + ignore_errors: yes + failed_when: false + + - name: Display environment variables + debug: + msg: "{{ env_vars.stdout_lines }}" + + - name: Test Redis Connection from PHP Container + shell: | + echo "=== Testing Redis Connection from PHP Container ===" + echo "Test 1: Check if Redis is reachable" + docker exec app php -r " + \$redis_host = getenv('REDIS_HOST') ?: 'redis'; + \$redis_port = (int)(getenv('REDIS_PORT') ?: 6379); + \$redis_password = getenv('REDIS_PASSWORD'); + + echo \"REDIS_HOST: \" . \$redis_host . \"\\n\"; + echo \"REDIS_PORT: \" . \$redis_port . \"\\n\"; + echo \"REDIS_PASSWORD: \" . (\$redis_password ? 'SET (length: ' . strlen(\$redis_password) . ')' : 'NOT SET') . \"\\n\"; + + // Test TCP connection + \$socket = @fsockopen(\$redis_host, \$redis_port, \$errno, \$errstr, 2); + if (\$socket) { + echo \"TCP Connection: OK\\n\"; + fclose(\$socket); + } else { + echo \"TCP Connection: FAILED (errno: \$errno, errstr: \$errstr)\\n\"; + } + + // Test with Predis if available + if (class_exists('Predis\\Client')) { + try { + \$client = new Predis\\Client([ + 'scheme' => 'tcp', + 'host' => \$redis_host, + 'port' => \$redis_port, + 'password' => \$redis_password ?: null, + ]); + \$client->connect(); + echo \"Predis Connection: OK\\n\"; + echo \"Redis PING: \" . \$client->ping() . \"\\n\"; + \$client->disconnect(); + } catch (Exception \$e) { + echo \"Predis Connection: FAILED - \" . \$e->getMessage() . \"\\n\"; + } + } else { + echo \"Predis not available\\n\"; + } + " || echo "Could not execute PHP test" + args: + executable: /bin/bash + register: redis_test + ignore_errors: yes + failed_when: false + + - name: Display Redis connection test results + debug: + msg: "{{ redis_test.stdout_lines }}" + + - name: Check Redis Container Configuration + shell: | + echo "=== Redis Container Status ===" + docker ps --filter "name=redis" + echo "" + echo "=== Redis Container Environment ===" + docker exec redis env | grep -E "(REDIS_|REQUIREPASS)" || echo "No Redis env vars found" + echo "" + echo "=== Test Redis Password ===" + REDIS_PASSWORD=$(cd ~/deployment/stacks/application && grep REDIS_PASSWORD .env | cut -d '=' -f2 | tr -d ' ' || echo "") + if [ -n "$REDIS_PASSWORD" ]; then + PASSWORD_LEN=$(echo -n "$REDIS_PASSWORD" | wc -c) + echo "REDIS_PASSWORD from .env file: SET (length: $PASSWORD_LEN)" + docker exec redis redis-cli -a "$REDIS_PASSWORD" PING || echo "Redis password test failed" + else + echo "REDIS_PASSWORD from .env file: NOT SET" + docker exec redis redis-cli PING || echo "Redis connection test failed (no password)" + fi + args: + executable: /bin/bash + register: redis_config + ignore_errors: yes + failed_when: false + + - name: Display Redis container configuration + debug: + msg: "{{ redis_config.stdout_lines }}" + + - name: Check Docker Network Connectivity + shell: | + echo "=== Docker Network: app-internal ===" + docker network inspect app-internal 2>&1 | grep -E "(Name|Subnet|Containers)" | head -20 || echo "Network not found" + echo "" + echo "=== Testing Network Connectivity ===" + echo "From PHP container to Redis:" + docker exec app ping -c 2 redis 2>&1 || echo "Ping test failed" + echo "" + echo "From PHP container to Redis (port 6379):" + docker exec app nc -zv redis 6379 2>&1 || echo "Port test failed" + args: + executable: /bin/bash + register: network_test + ignore_errors: yes + failed_when: false + + - name: Display network connectivity test + debug: + msg: "{{ network_test.stdout_lines }}" + + - name: Check Application Logs for Redis Errors + shell: | + cd ~/deployment/stacks/application + echo "=== Application Logs (Last 50 lines, Redis-related) ===" + docker compose logs app --tail=50 2>&1 | grep -i redis || echo "No Redis-related logs found" + args: + executable: /bin/bash + register: app_logs + ignore_errors: yes + failed_when: false + + - name: Display application logs + debug: + msg: "{{ app_logs.stdout_lines }}" + + - name: Check .env file configuration + shell: | + cd ~/deployment/stacks/application + echo "=== .env file Redis Configuration ===" + if [ -f .env ]; then + grep -E "(REDIS_|CACHE_|SESSION_|QUEUE_)" .env | grep -v "^#" || echo "No Redis config found in .env" + else + echo ".env file not found" + fi + echo "" + echo "=== Checking for application.env file ===" + if [ -f application.env ]; then + echo "application.env exists" + grep -E "(REDIS_|CACHE_|SESSION_|QUEUE_)" application.env | grep -v "^#" || echo "No Redis config found in application.env" + else + echo "application.env file not found" + fi + args: + executable: /bin/bash + register: env_file_config + ignore_errors: yes + failed_when: false + + - name: Display .env file configuration + debug: + msg: "{{ env_file_config.stdout_lines }}" diff --git a/deployment/ansible/playbooks/check-staging-redis-connection.yml b/deployment/ansible/playbooks/check-staging-redis-connection.yml new file mode 100644 index 00000000..d80b8f32 --- /dev/null +++ b/deployment/ansible/playbooks/check-staging-redis-connection.yml @@ -0,0 +1,255 @@ +--- +- name: Check Redis Connection and Environment Variables in Staging PHP Container + hosts: production + gather_facts: yes + become: no + + tasks: + - name: Check if staging stack is running + shell: | + cd ~/deployment/stacks/staging + docker compose ps + args: + executable: /bin/bash + register: stack_status + ignore_errors: yes + failed_when: false + + - name: Display stack status + debug: + msg: "{{ stack_status.stdout_lines }}" + + - name: Check PHP container exists + shell: | + docker ps --filter "name=staging-app" + args: + executable: /bin/bash + register: php_container + ignore_errors: yes + failed_when: false + + - name: Display PHP container status + debug: + msg: "{{ php_container.stdout_lines }}" + + - name: Check Environment Variables in Staging PHP Container + shell: | + echo "=== Redis Environment Variables in Staging PHP Container ===" + docker exec staging-app env | grep -E "(REDIS_|CACHE_|SESSION_|QUEUE_)" || echo "Container not accessible or no Redis vars found" + echo "" + echo "=== All Environment Variables in Staging PHP Container ===" + docker exec staging-app env | sort | head -50 || echo "Container not accessible" + args: + executable: /bin/bash + register: env_vars + ignore_errors: yes + failed_when: false + + - name: Display environment variables + debug: + msg: "{{ env_vars.stdout_lines }}" + + - name: Test Redis Connection from Staging PHP Container + shell: | + echo "=== Testing Redis Connection from Staging PHP Container ===" + echo "Test 1: Check if Redis is reachable" + docker exec staging-app php -r " + \$redis_host = getenv('REDIS_HOST') ?: 'staging-redis'; + \$redis_port = (int)(getenv('REDIS_PORT') ?: 6379); + \$redis_password = getenv('REDIS_PASSWORD'); + + echo \\\"REDIS_HOST: \\\" . \$redis_host . \\\"\\\\n\\\"; + echo \\\"REDIS_PORT: \\\" . \$redis_port . \\\"\\\\n\\\"; + echo \\\"REDIS_PASSWORD: \\\" . (\$redis_password ? 'SET (length: ' . strlen(\$redis_password) . ')' : 'NOT SET') . \\\"\\\\n\\\"; + + // Test TCP connection + \$socket = @fsockopen(\$redis_host, \$redis_port, \$errno, \$errstr, 2); + if (\$socket) { + echo \\\"TCP Connection: OK\\\\n\\\"; + fclose(\$socket); + } else { + echo \\\"TCP Connection: FAILED (errno: \$errno, errstr: \$errstr)\\\\n\\\"; + } + " || echo "Could not execute PHP test" + args: + executable: /bin/bash + register: redis_test + ignore_errors: yes + failed_when: false + + - name: Display Redis connection test results + debug: + msg: "{{ redis_test.stdout_lines }}" + + - name: Test Redis connection with actual php-redis extension + shell: | + docker exec staging-app php -r " + // Get environment variables + \$redis_host = getenv('REDIS_HOST') ?: 'staging-redis'; + \$redis_port = (int)(getenv('REDIS_PORT') ?: 6379); + \$redis_password = getenv('REDIS_PASSWORD'); + + echo '=== Staging Redis Connection Test ===' . PHP_EOL; + echo 'REDIS_HOST: ' . \$redis_host . PHP_EOL; + echo 'REDIS_PORT: ' . \$redis_port . PHP_EOL; + echo 'REDIS_PASSWORD: ' . (\$redis_password ? 'SET (length: ' . strlen(\$redis_password) . ')' : 'NOT SET') . PHP_EOL; + echo PHP_EOL; + + if (!extension_loaded('redis')) { + echo 'ERROR: php-redis extension is not loaded!' . PHP_EOL; + exit(1); + } + + if (!class_exists('Redis')) { + echo 'ERROR: Redis class is not available!' . PHP_EOL; + exit(1); + } + + try { + \$redis = new Redis(); + echo 'Created Redis instance' . PHP_EOL; + + // Connect + \$success = \$redis->connect(\$redis_host, \$redis_port, 2.0); + if (!\$success) { + echo 'ERROR: Failed to connect to Redis server' . PHP_EOL; + echo 'Host: ' . \$redis_host . ', Port: ' . \$redis_port . PHP_EOL; + exit(1); + } + echo 'Connected to Redis server' . PHP_EOL; + + // Authenticate if password is provided + if (\$redis_password) { + \$auth_result = \$redis->auth(\$redis_password); + if (!\$auth_result) { + echo 'ERROR: Redis authentication failed' . PHP_EOL; + echo 'Password used: ' . substr(\$redis_password, 0, 5) . '...' . PHP_EOL; + exit(1); + } + echo 'Authenticated with Redis' . PHP_EOL; + } + + // Test PING + \$ping_result = \$redis->ping(); + echo 'Redis PING: ' . \$ping_result . PHP_EOL; + + // Test SET/GET + \$test_key = 'test_connection_' . time(); + \$test_value = 'test_value'; + \$set_result = \$redis->set(\$test_key, \$test_value); + echo 'SET test: ' . (\$set_result ? 'OK' : 'FAILED') . PHP_EOL; + + \$get_result = \$redis->get(\$test_key); + echo 'GET test: ' . (\$get_result === \$test_value ? 'OK' : 'FAILED') . PHP_EOL; + + // Cleanup + \$redis->del(\$test_key); + \$redis->close(); + + echo PHP_EOL . '? All tests passed!' . PHP_EOL; + } catch (Exception \$e) { + echo 'ERROR: ' . \$e->getMessage() . PHP_EOL; + echo 'Exception type: ' . get_class(\$e) . PHP_EOL; + exit(1); + } + " + args: + executable: /bin/bash + register: redis_direct_test + ignore_errors: yes + failed_when: false + + - name: Display Redis direct connection test results + debug: + msg: "{{ redis_direct_test.stdout_lines }}" + + - name: Check Staging Redis Container Configuration + shell: | + echo "=== Staging Redis Container Status ===" + docker ps --filter "name=staging-redis" + echo "" + echo "=== Staging Redis Container Environment ===" + docker exec staging-redis env | grep -E "(REDIS_|REQUIREPASS)" || echo "No Redis env vars found" + echo "" + echo "=== Test Redis Password ===" + REDIS_PASSWORD=$(cd ~/deployment/stacks/staging && grep REDIS_PASSWORD .env | cut -d '=' -f2 | tr -d ' ' || echo "") + if [ -n "$REDIS_PASSWORD" ]; then + PASSWORD_LEN=$(echo -n "$REDIS_PASSWORD" | wc -c) + echo "REDIS_PASSWORD from .env file: SET (length: $PASSWORD_LEN)" + docker exec staging-redis redis-cli -a "$REDIS_PASSWORD" PING || echo "Redis password test failed" + else + echo "REDIS_PASSWORD from .env file: NOT SET" + docker exec staging-redis redis-cli PING || echo "Redis connection test failed (no password)" + fi + args: + executable: /bin/bash + register: redis_config + ignore_errors: yes + failed_when: false + + - name: Display Redis container configuration + debug: + msg: "{{ redis_config.stdout_lines }}" + + - name: Check Docker Network Connectivity for Staging + shell: | + echo "=== Docker Network: staging-internal ===" + docker network inspect staging-internal 2>&1 | grep -E "(Name|Subnet|Containers)" | head -20 || echo "Network not found" + echo "" + echo "=== Testing Network Connectivity ===" + echo "From Staging PHP container to Redis:" + docker exec staging-app php -r "echo gethostbyname('staging-redis') . PHP_EOL;" 2>&1 || echo "DNS test failed" + echo "" + echo "Testing connection from staging-app to staging-redis:" + docker exec staging-app php -r "\$socket = @fsockopen('staging-redis', 6379, \$errno, \$errstr, 2); if (\$socket) { echo 'Port 6379: OK' . PHP_EOL; fclose(\$socket); } else { echo 'Port 6379: FAILED (errno: ' . \$errno . ', errstr: ' . \$errstr . ')' . PHP_EOL; }" + args: + executable: /bin/bash + register: network_test + ignore_errors: yes + failed_when: false + + - name: Display network connectivity test + debug: + msg: "{{ network_test.stdout_lines }}" + + - name: Check Staging Application Logs for Redis Errors + shell: | + cd ~/deployment/stacks/staging + echo "=== Staging Application Logs (Last 50 lines, Redis-related) ===" + docker compose logs staging-app --tail=50 2>&1 | grep -i -E "(redis|connection|error)" | tail -20 || echo "No Redis-related logs found" + args: + executable: /bin/bash + register: app_logs + ignore_errors: yes + failed_when: false + + - name: Display application logs + debug: + msg: "{{ app_logs.stdout_lines }}" + + - name: Check Staging .env file configuration + shell: | + cd ~/deployment/stacks/staging + echo "=== .env file Redis Configuration ===" + if [ -f .env ]; then + grep -E "(REDIS_|CACHE_|SESSION_|QUEUE_)" .env | grep -v "^#" || echo "No Redis config found in .env" + else + echo ".env file not found" + fi + echo "" + echo "=== Checking for application.env file ===" + if [ -f application.env ]; then + echo "application.env exists" + grep -E "(REDIS_|CACHE_|SESSION_|QUEUE_)" application.env | grep -v "^#" || echo "No Redis config found in application.env" + else + echo "application.env file not found" + fi + args: + executable: /bin/bash + register: env_file_config + ignore_errors: yes + failed_when: false + + - name: Display .env file configuration + debug: + msg: "{{ env_file_config.stdout_lines }}" diff --git a/deployment/ansible/playbooks/check-staging-redis-env-file.yml b/deployment/ansible/playbooks/check-staging-redis-env-file.yml new file mode 100644 index 00000000..0323d3a0 --- /dev/null +++ b/deployment/ansible/playbooks/check-staging-redis-env-file.yml @@ -0,0 +1,135 @@ +--- +- name: Check Staging Redis Environment File and Container Password + hosts: production + gather_facts: yes + become: no + + tasks: + - name: Check .env file exists and contains REDIS_PASSWORD + shell: | + cd ~/deployment/stacks/staging + echo "=== Checking .env file ===" + if [ -f .env ]; then + echo ".env file exists" + echo "" + echo "=== REDIS_PASSWORD from .env ===" + REDIS_PASSWORD_FROM_ENV=$(grep "^REDIS_PASSWORD=" .env | cut -d '=' -f2- | tr -d ' ' || echo "") + if [ -n "$REDIS_PASSWORD_FROM_ENV" ]; then + PASSWORD_LEN=$(echo -n "$REDIS_PASSWORD_FROM_ENV" | wc -c) + echo "REDIS_PASSWORD found in .env (length: $PASSWORD_LEN)" + echo "First 10 chars: ${REDIS_PASSWORD_FROM_ENV:0:10}..." + echo "Last 10 chars: ...${REDIS_PASSWORD_FROM_ENV: -10}" + else + echo "REDIS_PASSWORD NOT FOUND in .env file!" + fi + else + echo ".env file NOT FOUND!" + fi + args: + executable: /bin/bash + register: env_file_check + ignore_errors: yes + failed_when: false + + - name: Display .env file check + debug: + msg: "{{ env_file_check.stdout_lines }}" + + - name: Check how Redis container was started + shell: | + echo "=== Checking Redis container command ===" + docker inspect staging-redis --format '{{ '{{' }}.Config.Cmd{{ '}}' }}' || echo "Could not inspect container" + echo "" + echo "=== Checking if Redis actually requires password ===" + # Try without password first + docker exec staging-redis redis-cli PING 2>&1 || echo "Connection failed (expected if password required)" + echo "" + # Try with password from .env + cd ~/deployment/stacks/staging + REDIS_PASSWORD=$(grep "^REDIS_PASSWORD=" .env | cut -d '=' -f2- | tr -d ' ' || echo "") + if [ -n "$REDIS_PASSWORD" ]; then + echo "Testing with password from .env:" + docker exec staging-redis redis-cli -a "$REDIS_PASSWORD" PING 2>&1 || echo "Password test failed" + else + echo "Cannot test with password - REDIS_PASSWORD not found in .env" + fi + args: + executable: /bin/bash + register: redis_startup_check + ignore_errors: yes + failed_when: false + + - name: Display Redis startup check + debug: + msg: "{{ redis_startup_check.stdout_lines }}" + + - name: Test actual connection from PHP container + shell: | + cd ~/deployment/stacks/staging + REDIS_PASSWORD_ENV=$(grep "^REDIS_PASSWORD=" .env | cut -d '=' -f2- | tr -d ' ' || echo "") + + docker exec staging-app php -r " + \$redis_host = 'staging-redis'; + \$redis_port = 6379; + \$redis_password = getenv('REDIS_PASSWORD'); + \$redis_password_env_file = '$REDIS_PASSWORD_ENV'; + + echo '=== Password Comparison ===' . PHP_EOL; + echo 'REDIS_PASSWORD from environment: ' . (\$redis_password ? 'SET (length: ' . strlen(\$redis_password) . ')' : 'NOT SET') . PHP_EOL; + echo 'REDIS_PASSWORD from .env file: ' . (\$redis_password_env_file ? 'SET (length: ' . strlen(\$redis_password_env_file) . ')' : 'NOT SET') . PHP_EOL; + + if (\$redis_password && \$redis_password_env_file) { + if (\$redis_password === \$redis_password_env_file) { + echo 'Passwords MATCH!' . PHP_EOL; + } else { + echo 'Passwords DO NOT MATCH!' . PHP_EOL; + echo 'Env password first 10: ' . substr(\$redis_password, 0, 10) . PHP_EOL; + echo '.env password first 10: ' . substr(\$redis_password_env_file, 0, 10) . PHP_EOL; + } + } + + echo PHP_EOL . '=== Connection Test ===' . PHP_EOL; + + if (!extension_loaded('redis')) { + echo 'ERROR: php-redis extension not loaded!' . PHP_EOL; + exit(1); + } + + try { + \$redis = new Redis(); + \$success = \$redis->connect(\$redis_host, \$redis_port, 2.0); + if (!\$success) { + echo 'ERROR: Failed to connect to Redis' . PHP_EOL; + exit(1); + } + echo 'Connected to Redis' . PHP_EOL; + + if (\$redis_password) { + \$auth_result = \$redis->auth(\$redis_password); + if (\$auth_result) { + echo 'Authentication: SUCCESS' . PHP_EOL; + \$ping = \$redis->ping(); + echo 'PING: ' . \$ping . PHP_EOL; + } else { + echo 'Authentication: FAILED' . PHP_EOL; + echo 'Tried password: ' . substr(\$redis_password, 0, 10) . '...' . PHP_EOL; + } + } else { + echo 'WARNING: No password set in environment!' . PHP_EOL; + } + + \$redis->close(); + } catch (Exception \$e) { + echo 'ERROR: ' . \$e->getMessage() . PHP_EOL; + exit(1); + } + " + args: + executable: /bin/bash + register: password_comparison + ignore_errors: yes + failed_when: false + + - name: Display password comparison + debug: + msg: "{{ password_comparison.stdout_lines }}" diff --git a/deployment/ansible/playbooks/diagnose-vpn-routing.yml b/deployment/ansible/playbooks/diagnose-vpn-routing.yml new file mode 100644 index 00000000..98985a56 --- /dev/null +++ b/deployment/ansible/playbooks/diagnose-vpn-routing.yml @@ -0,0 +1,172 @@ +--- +- name: Diagnose VPN Routing Problem f?r Grafana + hosts: production + gather_facts: yes + become: yes + become_user: root + + tasks: + - name: Check WireGuard interface status + shell: | + echo "=== WireGuard Interface Status ===" + ip addr show wg0 2>&1 || echo "WireGuard interface not found" + echo "" + echo "=== WireGuard Peers ===" + wg show 2>&1 || echo "WireGuard not running" + register: wg_status + ignore_errors: yes + failed_when: false + + - name: Display WireGuard status + debug: + msg: "{{ wg_status.stdout_lines }}" + + - name: Check routing table for VPN network + shell: | + echo "=== Routing Table for 10.8.0.0/24 ===" + ip route show | grep 10.8.0 || echo "No routes found for 10.8.0.0/24" + echo "" + echo "=== Default Route ===" + ip route show default || echo "No default route" + register: routing_info + ignore_errors: yes + failed_when: false + + - name: Display routing information + debug: + msg: "{{ routing_info.stdout_lines }}" + + - name: Check Traefik access logs for recent Grafana requests + shell: | + cd ~/deployment/stacks/traefik + echo "=== Recent Grafana Access (Last 10 requests) ===" + tail -50 logs/access.log | grep grafana | tail -10 | jq -r '[.ClientAddr, .ClientHost, .RequestHost, .DownstreamStatus] | @tsv' 2>&1 || tail -50 logs/access.log | grep grafana | tail -10 + args: + executable: /bin/bash + register: traefik_access + ignore_errors: yes + failed_when: false + + - name: Display Traefik access logs + debug: + msg: "{{ traefik_access.stdout_lines }}" + + - name: Test DNS resolution from server + shell: | + echo "=== DNS Resolution Tests ===" + echo "1. Grafana via VPN DNS (10.8.0.1):" + dig +short grafana.michaelschiemer.de @10.8.0.1 2>&1 || echo "Failed" + echo "" + echo "2. Grafana via public DNS (8.8.8.8):" + dig +short grafana.michaelschiemer.de @8.8.8.8 2>&1 || echo "Failed" + echo "" + echo "3. Grafana via system DNS:" + dig +short grafana.michaelschiemer.de 2>&1 || echo "Failed" + args: + executable: /bin/bash + register: dns_tests + ignore_errors: yes + failed_when: false + + - name: Display DNS test results + debug: + msg: "{{ dns_tests.stdout_lines }}" + + - name: Check firewall rules for WireGuard + shell: | + echo "=== Firewall Rules for WireGuard (port 51820) ===" + sudo ufw status | grep 51820 || sudo iptables -L -n | grep 51820 || echo "No firewall rules found" + echo "" + echo "=== Allowed IPs in WireGuard Config ===" + grep -E "AllowedIPs" /etc/wireguard/wg0.conf 2>&1 || echo "WireGuard config not found" + args: + executable: /bin/bash + register: firewall_info + ignore_errors: yes + failed_when: false + + - name: Display firewall information + debug: + msg: "{{ firewall_info.stdout_lines }}" + + - name: Check Traefik forwardedHeaders configuration + shell: | + cd ~/deployment/stacks/traefik + echo "=== Traefik forwardedHeaders Config ===" + grep -A 10 "forwardedHeaders:" traefik.yml || echo "Not found" + args: + executable: /bin/bash + register: forwarded_headers + ignore_errors: yes + failed_when: false + + - name: Display forwardedHeaders configuration + debug: + msg: "{{ forwarded_headers.stdout_lines }}" + + - name: Check Grafana middleware configuration + shell: | + cd ~/deployment/stacks/traefik/dynamic + echo "=== Grafana VPN Only Middleware ===" + grep -A 6 "grafana-vpn-only:" middlewares.yml || echo "Not found" + args: + executable: /bin/bash + register: grafana_middleware + ignore_errors: yes + failed_when: false + + - name: Display Grafana middleware configuration + debug: + msg: "{{ grafana_middleware.stdout_lines }}" + + - name: Check CoreDNS configuration + shell: | + cd ~/deployment/stacks/dns + echo "=== CoreDNS Corefile ===" + cat Corefile 2>&1 || echo "Not found" + args: + executable: /bin/bash + register: coredns_config + ignore_errors: yes + failed_when: false + + - name: Display CoreDNS configuration + debug: + msg: "{{ coredns_config.stdout_lines }}" + + - name: Test connection to Grafana from server via VPN IP + shell: | + echo "=== Test Connection to Grafana via VPN IP (10.8.0.1) ===" + curl -k -H "User-Agent: Mozilla/5.0" -s -o /dev/null -w "HTTP %{http_code}\n" https://10.8.0.1:443 -H "Host: grafana.michaelschiemer.de" 2>&1 || echo "Connection failed" + echo "" + echo "=== Test Connection via Domain ===" + curl -k -H "User-Agent: Mozilla/5.0" -s -o /dev/null -w "HTTP %{http_code}\n" https://grafana.michaelschiemer.de/ 2>&1 || echo "Connection failed" + args: + executable: /bin/bash + register: connection_tests + ignore_errors: yes + failed_when: false + + - name: Display connection test results + debug: + msg: "{{ connection_tests.stdout_lines }}" + + - name: Monitor Traefik access logs in real-time (for next request) + shell: | + echo "=== Instructions ===" + echo "1. Connect to VPN with your WireGuard client" + echo "2. Ensure DNS is set to 10.8.0.1 in WireGuard config" + echo "3. Access https://grafana.michaelschiemer.de in your browser" + echo "4. Check the ClientAddr in the access logs below" + echo "" + echo "=== Last Grafana Access Attempt ===" + tail -1 ~/deployment/stacks/traefik/logs/access.log 2>&1 | jq -r '[.ClientAddr, .ClientHost, .DownstreamStatus] | @tsv' || tail -1 ~/deployment/stacks/traefik/logs/access.log + args: + executable: /bin/bash + register: monitoring_info + ignore_errors: yes + failed_when: false + + - name: Display monitoring instructions + debug: + msg: "{{ monitoring_info.stdout_lines }}" diff --git a/deployment/ansible/playbooks/fix-grafana-vpn-access.yml b/deployment/ansible/playbooks/fix-grafana-vpn-access.yml new file mode 100644 index 00000000..6aeddf8a --- /dev/null +++ b/deployment/ansible/playbooks/fix-grafana-vpn-access.yml @@ -0,0 +1,67 @@ +--- +- name: Fix Grafana VPN Access - Update Middleware to ipAllowList + hosts: production + gather_facts: no + become: no + + tasks: + - name: Backup current middlewares.yml + shell: | + cd ~/deployment/stacks/traefik/dynamic + cp middlewares.yml middlewares.yml.backup.$(date +%Y%m%d_%H%M%S) + args: + executable: /bin/bash + + - name: Update middlewares.yml - Change ipWhiteList to ipAllowList + shell: | + cd ~/deployment/stacks/traefik/dynamic + sed -i 's/ipWhiteList:/ipAllowList:/g' middlewares.yml + sed -i 's/ipWhitelist/ipAllowList/g' middlewares.yml + # Validate YAML syntax + python3 -c "import yaml; yaml.safe_load(open('middlewares.yml')); print('YAML valid')" + args: + executable: /bin/bash + + - name: Display updated grafana-vpn-only middleware + shell: | + cd ~/deployment/stacks/traefik/dynamic + grep -A 6 'grafana-vpn-only:' middlewares.yml + args: + executable: /bin/bash + register: grafana_middleware + + - name: Show updated middleware + debug: + msg: "{{ grafana_middleware.stdout_lines }}" + + - name: Restart Traefik to apply changes + command: docker compose restart traefik + args: + chdir: ~/deployment/stacks/traefik + register: traefik_restart + + - name: Wait for Traefik to restart + pause: + seconds: 5 + + - name: Check Traefik logs for deprecation warnings + shell: | + cd ~/deployment/stacks/traefik + docker compose logs traefik --tail=20 2>&1 | grep -i 'allowlist\|whitelist\|deprecated' || echo "No warnings found" + args: + executable: /bin/bash + register: traefik_warnings + + - name: Display Traefik warnings + debug: + msg: "{{ traefik_warnings.stdout_lines }}" + + - name: Verify Traefik status + command: docker compose ps traefik + args: + chdir: ~/deployment/stacks/traefik + register: traefik_status + + - name: Display Traefik status + debug: + msg: "{{ traefik_status.stdout_lines }}" diff --git a/deployment/ansible/playbooks/test-redis-connection-direct.yml b/deployment/ansible/playbooks/test-redis-connection-direct.yml new file mode 100644 index 00000000..530152d7 --- /dev/null +++ b/deployment/ansible/playbooks/test-redis-connection-direct.yml @@ -0,0 +1,121 @@ +--- +- name: Test Redis Connection Directly with php-redis Extension + hosts: production + gather_facts: yes + become: no + + tasks: + - name: Check if php-redis extension is loaded + shell: | + docker exec app php -r " + if (extension_loaded('redis')) { + echo 'php-redis extension: LOADED' . PHP_EOL; + echo 'Redis class available: ' . (class_exists('Redis') ? 'YES' : 'NO') . PHP_EOL; + } else { + echo 'php-redis extension: NOT LOADED' . PHP_EOL; + } + " + args: + executable: /bin/bash + register: extension_check + ignore_errors: yes + failed_when: false + + - name: Display extension check + debug: + msg: "{{ extension_check.stdout_lines }}" + + - name: Test Redis connection with actual php-redis + shell: | + docker exec app php -r " + // Get environment variables + \$redis_host = getenv('REDIS_HOST') ?: 'redis'; + \$redis_port = (int)(getenv('REDIS_PORT') ?: 6379); + \$redis_password = getenv('REDIS_PASSWORD'); + + echo '=== Redis Connection Test ===' . PHP_EOL; + echo 'REDIS_HOST: ' . \$redis_host . PHP_EOL; + echo 'REDIS_PORT: ' . \$redis_port . PHP_EOL; + echo 'REDIS_PASSWORD: ' . (\$redis_password ? 'SET (length: ' . strlen(\$redis_password) . ')' : 'NOT SET') . PHP_EOL; + echo PHP_EOL; + + if (!extension_loaded('redis')) { + echo 'ERROR: php-redis extension is not loaded!' . PHP_EOL; + exit(1); + } + + if (!class_exists('Redis')) { + echo 'ERROR: Redis class is not available!' . PHP_EOL; + exit(1); + } + + try { + \$redis = new Redis(); + echo 'Created Redis instance' . PHP_EOL; + + // Connect + \$success = \$redis->connect(\$redis_host, \$redis_port, 2.0); + if (!\$success) { + echo 'ERROR: Failed to connect to Redis server' . PHP_EOL; + exit(1); + } + echo 'Connected to Redis server' . PHP_EOL; + + // Authenticate if password is provided + if (\$redis_password) { + \$auth_result = \$redis->auth(\$redis_password); + if (!\$auth_result) { + echo 'ERROR: Redis authentication failed' . PHP_EOL; + echo 'Password used: ' . substr(\$redis_password, 0, 5) . '...' . PHP_EOL; + exit(1); + } + echo 'Authenticated with Redis' . PHP_EOL; + } + + // Test PING + \$ping_result = \$redis->ping(); + echo 'Redis PING: ' . \$ping_result . PHP_EOL; + + // Test SET/GET + \$test_key = 'test_connection_' . time(); + \$test_value = 'test_value'; + \$set_result = \$redis->set(\$test_key, \$test_value); + echo 'SET test: ' . (\$set_result ? 'OK' : 'FAILED') . PHP_EOL; + + \$get_result = \$redis->get(\$test_key); + echo 'GET test: ' . (\$get_result === \$test_value ? 'OK' : 'FAILED') . PHP_EOL; + + // Cleanup + \$redis->del(\$test_key); + \$redis->close(); + + echo PHP_EOL . '? All tests passed!' . PHP_EOL; + } catch (Exception \$e) { + echo 'ERROR: ' . \$e->getMessage() . PHP_EOL; + echo 'Exception type: ' . get_class(\$e) . PHP_EOL; + exit(1); + } + " + args: + executable: /bin/bash + register: redis_test + ignore_errors: yes + failed_when: false + + - name: Display Redis connection test results + debug: + msg: "{{ redis_test.stdout_lines }}" + + - name: Check for Redis errors in application logs + shell: | + cd ~/deployment/stacks/application + docker compose logs app --tail=100 2>&1 | grep -i -E "(redis|connection|error)" | tail -20 || echo "No Redis errors found in logs" + args: + executable: /bin/bash + register: error_logs + ignore_errors: yes + failed_when: false + + - name: Display error logs + debug: + msg: "{{ error_logs.stdout_lines }}" diff --git a/deployment/stacks/traefik/dynamic/middlewares.yml b/deployment/stacks/traefik/dynamic/middlewares.yml index f511942b..4bcc09a4 100644 --- a/deployment/stacks/traefik/dynamic/middlewares.yml +++ b/deployment/stacks/traefik/dynamic/middlewares.yml @@ -52,17 +52,23 @@ http: # - "127.0.0.1/32" # - "10.0.0.0/8" - # VPN-only IP whitelist for Grafana and other monitoring services + # VPN-only IP allowlist for Grafana and other monitoring services # Restrict access strictly to the WireGuard network + # Note: ipAllowList checks the real client IP from the connection + # When connected via VPN, client IP should be from 10.8.0.0/24 + # If client IP shows public IP (e.g., 89.246.96.244), check: + # 1. VPN connection is active and traffic is routed through VPN + # 2. DNS uses 10.8.0.1 (VPN DNS server) to resolve grafana.michaelschiemer.de + # 3. Browser/system routing sends traffic through VPN interface grafana-vpn-only: - ipWhiteList: + ipAllowList: sourceRange: - - "10.8.0.0/24" # WireGuard VPN network + - "10.8.0.0/24" # WireGuard VPN network (10.8.0.1 = server, 10.8.0.x = clients) - # VPN-only IP whitelist for general use (Traefik Dashboard, etc.) + # VPN-only IP allowlist for general use (Traefik Dashboard, etc.) # Restrict access strictly to the WireGuard network vpn-only: - ipWhiteList: + ipAllowList: sourceRange: - "10.8.0.0/24" # WireGuard VPN network diff --git a/docs/deployment/GRAFANA-VPN-ACCESS.md b/docs/deployment/GRAFANA-VPN-ACCESS.md new file mode 100644 index 00000000..a7248373 --- /dev/null +++ b/docs/deployment/GRAFANA-VPN-ACCESS.md @@ -0,0 +1,108 @@ +# Grafana VPN Access - Troubleshooting Guide + +## Problem + +Grafana ist nur ?ber VPN (WireGuard) erreichbar, aber auch mit VPN-Verbindung bekommt man einen 403-Fehler. + +## Ursache + +Traefik sieht die ?ffentliche Client-IP (z.B. `89.246.96.244`) statt der VPN-IP (z.B. `10.8.0.7`). Das bedeutet, dass der Traffic **nicht ?ber das VPN** geroutet wird. + +## L?sung + +### 1. VPN-Verbindung pr?fen + +```bash +# Pr?fe ob WireGuard Interface aktiv ist +sudo wg show + +# Pr?fe ob VPN-IP zugewiesen ist +ip addr show wg0 # oder das WireGuard Interface-Name +``` + +### 2. DNS-Konfiguration pr?fen + +Stelle sicher, dass dein System den VPN-DNS-Server (`10.8.0.1`) verwendet: + +**Windows:** +- Pr?fe in WireGuard-Client: `DNS = 10.8.0.1` sollte gesetzt sein +- Oder manuell in Windows: Netzwerk-Einstellungen ? DNS-Server auf `10.8.0.1` setzen + +**Linux/Mac:** +```bash +# Pr?fe aktive DNS-Server +cat /etc/resolv.conf +# oder +resolvectl status + +# Sollte 10.8.0.1 enthalten (oder automatisch ?ber VPN gesetzt) +``` + +### 3. DNS-Aufl?sung testen + +```bash +# Teste DNS-Aufl?sung ?ber VPN-DNS +dig +short grafana.michaelschiemer.de @10.8.0.1 +# Sollte zur?ckgeben: 10.8.0.1 + +# Teste normale DNS-Aufl?sung +dig +short grafana.michaelschiemer.de +# Falls das eine andere IP zur?ckgibt, wird der Traffic ?ber ?ffentliche Route gehen +``` + +### 4. Routing pr?fen + +Stelle sicher, dass der Traffic f?r `10.8.0.0/24` ?ber das VPN-Interface geroutet wird: + +**Windows:** +- Pr?fe in WireGuard-Client: `AllowedIPs = 10.8.0.0/24` sollte gesetzt sein + +**Linux/Mac:** +```bash +# Pr?fe Routing-Tabelle +ip route | grep 10.8.0 +# oder +route -n | grep 10.8.0 + +# Sollte zeigen: 10.8.0.0/24 via +``` + +### 5. Browser-Zugriff testen + +**Option A: Direkt ?ber VPN-IP** +- ?ffne im Browser: `https://10.8.0.1` (falls Traefik darauf l?uft) +- Oder: `https://grafana.michaelschiemer.de` nachdem DNS auf `10.8.0.1` aufgel?st wurde + +**Option B: Hosts-Datei verwenden (tempor?r)** +```bash +# Linux/Mac +echo "10.8.0.1 grafana.michaelschiemer.de" | sudo tee -a /etc/hosts + +# Windows (als Administrator) +# C:\Windows\System32\drivers\etc\hosts +# 10.8.0.1 grafana.michaelschiemer.de +``` + +### 6. Client-IP in Traefik-Logs pr?fen + +```bash +# Pr?fe welche Client-IP Traefik sieht +ssh deploy@94.16.110.151 +cd ~/deployment/stacks/traefik +tail -20 logs/access.log | grep grafana | jq '.ClientAddr' + +# Sollte zeigen: 10.8.0.x (VPN-IP), nicht die ?ffentliche IP +``` + +## Aktuelle Konfiguration + +- **Grafana Middleware:** `grafana-vpn-only@file` +- **IP Allowlist:** `10.8.0.0/24` (WireGuard VPN network) +- **Traefik Middleware:** `ipAllowList` (Traefik v3.0, nicht mehr deprecated `ipWhiteList`) + +## Weitere Hilfe + +Falls das Problem weiterhin besteht: +1. Pr?fe Traefik-Logs auf detaillierte Fehlermeldungen +2. Pr?fe ob WireGuard korrekt konfiguriert ist +3. Pr?fe ob der Traffic tats?chlich ?ber das VPN-Interface geht (z.B. mit `tcpdump`) diff --git a/docs/deployment/VPN-ROUTING-CLIENT-CHECK.md b/docs/deployment/VPN-ROUTING-CLIENT-CHECK.md new file mode 100644 index 00000000..49a67ef1 --- /dev/null +++ b/docs/deployment/VPN-ROUTING-CLIENT-CHECK.md @@ -0,0 +1,195 @@ +# VPN Routing - Client-Side Checks + +## Problem +Grafana gibt 403-Fehler, obwohl VPN verbunden ist. Traefik sieht die ?ffentliche Client-IP statt der VPN-IP. + +## Client-Side Diagnose + +### 1. VPN-Verbindung pr?fen + +**Windows:** +```powershell +# Pr?fe WireGuard Interface +wireguard.exe /show wg0 + +# Oder in PowerShell (als Administrator) +Get-NetAdapter | Where-Object {$_.InterfaceDescription -like "*WireGuard*"} +``` + +**Linux:** +```bash +# Pr?fe WireGuard Interface +sudo wg show + +# Pr?fe Interface-Status +ip addr show wg0 +# Sollte zeigen: inet 10.8.0.7/24 +``` + +**Mac:** +```bash +# Pr?fe WireGuard Interface +sudo wg show + +# Pr?fe Interface-Status +ifconfig utun* | grep -A 5 "inet 10.8.0" +# Sollte zeigen: inet 10.8.0.7 +``` + +### 2. DNS-Konfiguration pr?fen + +**Windows:** +- ?ffne WireGuard-Client +- Pr?fe ob `DNS = 10.8.0.1` in der Config gesetzt ist +- Oder in PowerShell: +```powershell +Get-DnsClientServerAddress | Select-Object InterfaceAlias, ServerAddresses +``` + +**Linux:** +```bash +# Pr?fe aktive DNS-Server +cat /etc/resolv.conf +# Oder +resolvectl status +# Sollte 10.8.0.1 enthalten +``` + +**Mac:** +```bash +# Pr?fe DNS-Server +scutil --dns | grep nameserver +# Oder +networksetup -getdnsservers Wi-Fi +``` + +### 3. DNS-Aufl?sung testen + +```bash +# Teste DNS-Aufl?sung ?ber VPN-DNS +dig +short grafana.michaelschiemer.de @10.8.0.1 +# Sollte zur?ckgeben: 10.8.0.1 + +# Teste normale DNS-Aufl?sung +dig +short grafana.michaelschiemer.de +# Falls das eine andere IP zur?ckgibt (z.B. 94.16.110.151), wird der Traffic ?ber ?ffentliche Route gehen +``` + +**Windows:** +```powershell +# Teste DNS-Aufl?sung +Resolve-DnsName grafana.michaelschiemer.de -Server 10.8.0.1 +nslookup grafana.michaelschiemer.de 10.8.0.1 +``` + +### 4. Routing pr?fen + +**Linux:** +```bash +# Pr?fe Routing-Tabelle +ip route show | grep 10.8.0 +# Sollte zeigen: 10.8.0.0/24 dev wg0 + +# Pr?fe Default Route +ip route show default +``` + +**Windows:** +```powershell +# Pr?fe Routing-Tabelle +route print | findstr "10.8.0" +``` + +**Mac:** +```bash +# Pr?fe Routing-Tabelle +netstat -rn | grep 10.8.0 +``` + +### 5. AllowedIPs in WireGuard Config pr?fen + +**Deine WireGuard-Config sollte enthalten:** +``` +[Peer] +AllowedIPs = 10.8.0.0/24 +``` + +**Wichtig:** Wenn `AllowedIPs = 0.0.0.0/0` ist, wird ALLER Traffic ?ber VPN geroutet. Das ist OK, aber k?nnte Probleme verursachen. + +Wenn `AllowedIPs = 10.8.0.0/24` ist, wird nur Traffic f?r das VPN-Netzwerk ?ber VPN geroutet. Der Rest geht ?ber das normale Internet. + +### 6. Browser-Zugriff testen + +**Option A: Direkt ?ber VPN-IP** +``` +https://10.8.0.1 +``` +(Wenn das funktioniert, ist Traefik erreichbar, aber die Host-Header-Konfiguration k?nnte ein Problem sein) + +**Option B: Via Domain mit Hosts-Datei** + +**Linux/Mac:** +```bash +# F?ge VPN-IP zur Hosts-Datei hinzu +echo "10.8.0.1 grafana.michaelschiemer.de" | sudo tee -a /etc/hosts + +# Teste dann +curl -k -H "Host: grafana.michaelschiemer.de" https://10.8.0.1 +``` + +**Windows:** +``` +# C:\Windows\System32\drivers\etc\hosts (als Administrator bearbeiten) +10.8.0.1 grafana.michaelschiemer.de +``` + +**Option C: Via VPN-DNS** +- Stelle sicher, dass dein System 10.8.0.1 als DNS-Server verwendet +- Dann sollte `grafana.michaelschiemer.de` automatisch auf 10.8.0.1 aufgel?st werden + +### 7. Traceroute testen + +```bash +# Pr?fe welchen Weg der Traffic nimmt +traceroute 10.8.0.1 +# Sollte direkt ?ber wg0 Interface gehen, nicht ?ber Gateway + +# Teste Domain +traceroute grafana.michaelschiemer.de +# Wenn das ?ber ?ffentliche IPs geht, l?uft der Traffic nicht ?ber VPN +``` + +**Windows:** +```powershell +tracert 10.8.0.1 +tracert grafana.michaelschiemer.de +``` + +## H?ufige Probleme + +### Problem 1: DNS verwendet ?ffentliche Server +**L?sung:** Stelle sicher, dass WireGuard `DNS = 10.8.0.1` setzt, oder setze es manuell im System. + +### Problem 2: AllowedIPs nicht korrekt +**L?sung:** `AllowedIPs = 10.8.0.0/24` sollte gesetzt sein f?r VPN-Zugriff. + +### Problem 3: Routing geht ?ber ?ffentliche IP +**L?sung:** Pr?fe ob grafana.michaelschiemer.de ?ber ?ffentliche DNS aufgel?st wird. Falls ja, setze DNS auf 10.8.0.1 oder verwende Hosts-Datei. + +### Problem 4: Browser cached alte IP +**L?sung:** Browser-Cache leeren oder Inkognito-Modus verwenden. + +## Server-Side Diagnose + +F?hre das Diagnose-Playbook auf dem Server aus: +```bash +cd deployment/ansible +ansible-playbook -i inventory/production.yml playbooks/diagnose-vpn-routing.yml +``` + +Das Playbook zeigt: +- WireGuard-Status +- Routing-Konfiguration +- Traefik Access-Logs (welche Client-IPs Traefik sieht) +- DNS-Aufl?sungstests +- Firewall-Regeln diff --git a/docs/deployment/VPN-ROUTING-FIX.md b/docs/deployment/VPN-ROUTING-FIX.md new file mode 100644 index 00000000..35a4ad26 --- /dev/null +++ b/docs/deployment/VPN-ROUTING-FIX.md @@ -0,0 +1,120 @@ +# VPN Routing Fix f?r Grafana - Schritt-f?r-Schritt + +## Problem +Grafana gibt 403-Fehler, obwohl VPN verbunden ist. Traefik sieht ?ffentliche Client-IP (`89.246.96.244`) statt VPN-IP (`10.8.0.7`). + +## L?sung: DNS auf VPN-DNS setzen + +### Schritt 1: Pr?fe aktuelle DNS-Konfiguration + +**Windows:** +```powershell +# In PowerShell (als Administrator) +Get-DnsClientServerAddress | Select-Object InterfaceAlias, ServerAddresses +``` + +**Linux:** +```bash +cat /etc/resolv.conf +# oder +resolvectl status +``` + +**Mac:** +```bash +scutil --dns | grep nameserver +``` + +### Schritt 2: DNS-Test + +```bash +# Teste DNS-Aufl?sung +dig +short grafana.michaelschiemer.de +# Oder +nslookup grafana.michaelschiemer.de + +# Falls das 94.16.110.151 zur?ckgibt (?ffentliche IP) ? Problem! +# Sollte 10.8.0.1 zur?ckgeben (VPN-IP) ? OK! +``` + +### Schritt 3: WireGuard Config pr?fen + +?ffne deine WireGuard-Config und pr?fe: + +``` +[Interface] +DNS = 10.8.0.1 + +[Peer] +AllowedIPs = 10.8.0.0/24 +``` + +**Wichtig:** `DNS = 10.8.0.1` MUSS gesetzt sein! + +### Schritt 4: WireGuard-Verbindung neu starten + +1. Trenne die VPN-Verbindung +2. Starte sie neu +3. Pr?fe ob DNS jetzt 10.8.0.1 ist + +### Schritt 5: DNS erneut testen + +```bash +dig +short grafana.michaelschiemer.de @10.8.0.1 +# Sollte zur?ckgeben: 10.8.0.1 +``` + +### Schritt 6: Browser testen + +1. **Browser-Cache leeren** (oder Inkognito-Modus verwenden) +2. ?ffne: `https://grafana.michaelschiemer.de` +3. Sollte jetzt funktionieren! + +## Alternative: Hosts-Datei verwenden (tempor?r) + +Falls DNS nicht automatisch funktioniert: + +**Linux/Mac:** +```bash +sudo sh -c 'echo "10.8.0.1 grafana.michaelschiemer.de" >> /etc/hosts' +``` + +**Windows:** +``` +# Als Administrator: C:\Windows\System32\drivers\etc\hosts +10.8.0.1 grafana.michaelschiemer.de +``` + +## Pr?fen ob es funktioniert + +Nach dem Fix solltest du: +1. VPN verbunden haben +2. DNS zeigt 10.8.0.1 f?r grafana.michaelschiemer.de +3. Browser zeigt Grafana-Login statt 403-Fehler + +## Server-Side Pr?fung + +Auf dem Server kannst du pr?fen, welche Client-IP Traefik jetzt sieht: + +```bash +ssh deploy@94.16.110.151 +cd ~/deployment/stacks/traefik +tail -5 logs/access.log | grep grafana +``` + +**Vor dem Fix:** `ClientAddr: 89.246.96.244` (?ffentliche IP) +**Nach dem Fix:** `ClientAddr: 10.8.0.7` (VPN-IP) + +## Warum funktioniert das? + +- Wenn DNS auf `10.8.0.1` zeigt, wird `grafana.michaelschiemer.de` auf `10.8.0.1` aufgel?st +- Der Browser sendet die Anfrage an `10.8.0.1` (VPN-Server) +- Der Traffic geht ?ber das VPN-Interface +- Traefik sieht die VPN-Client-IP (`10.8.0.7`) +- IP-Allowlist erlaubt Zugriff ? + +- Wenn DNS auf ?ffentliche DNS zeigt, wird `grafana.michaelschiemer.de` auf `94.16.110.151` aufgel?st +- Der Browser sendet die Anfrage direkt an die ?ffentliche IP +- Der Traffic geht NICHT ?ber VPN +- Traefik sieht die ?ffentliche Client-IP (`89.246.96.244`) +- IP-Allowlist blockiert Zugriff ? (403) diff --git a/src/Framework/Core/AppBootstrapper.php b/src/Framework/Core/AppBootstrapper.php index 85e745ca..ba2e8c35 100644 --- a/src/Framework/Core/AppBootstrapper.php +++ b/src/Framework/Core/AppBootstrapper.php @@ -52,6 +52,9 @@ final readonly class AppBootstrapper // Initialize environment with encryption support $env = $this->initializeEnvironment(); + error_log("------ ENVIRONMENT VARIABLES ------"); + error_log(print_r($env->all(), true)); + // Make Environment available throughout the application $this->container->instance(Environment::class, $env); diff --git a/src/Framework/Redis/RedisConnectionPool.php b/src/Framework/Redis/RedisConnectionPool.php index 887db76c..77f81139 100644 --- a/src/Framework/Redis/RedisConnectionPool.php +++ b/src/Framework/Redis/RedisConnectionPool.php @@ -23,7 +23,6 @@ final class RedisConnectionPool */ public function registerConnection(string $name, RedisConfig $config): void { - var_dump("
", $config);
         $this->configs[$name] = $config;
     }