mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-18 11:59:26 +00:00
feat: implement deployment isolation verification and enhance API URL patching
This commit is contained in:
parent
e10e8ee5ba
commit
482dd930ce
4 changed files with 143 additions and 10 deletions
|
|
@ -47,14 +47,20 @@ See `COOLIFY_ENV_VARS.md` for complete list. Key variables for isolation:
|
|||
- ✅ **Port mismatch fixed**: Changed from 3000 to 80
|
||||
- ✅ **Container accessibility**: Traefik can now route to port 80
|
||||
- ✅ **Frontend running**: Next.js server operational on port 8000
|
||||
- ❌ **Backend failing**: PM2 bash execution error fixed
|
||||
- ⚠️ **502 errors**: Should resolve once backend starts correctly
|
||||
- ✅ **Backend running**: FastAPI server operational on port 9000
|
||||
- ❌ **Cross-deployment contamination**: LIVE calling DEV APIs and vice versa
|
||||
- ⚠️ **Root cause**: Frontend build-time API URLs not properly isolated
|
||||
|
||||
### Identified Issues & Fixes:
|
||||
|
||||
**Problem**: Backend API service failing with bash execution error
|
||||
**Root Cause**: Incorrect PM2 command syntax for starting uvicorn
|
||||
**Solution**: Updated start script to use direct Python execution instead of bash interpreter
|
||||
**Problem**: Cross-deployment data contamination (LIVE sees DEV data)
|
||||
**Root Cause**: Next.js build embeds API URLs at build-time, both deployments may share same URLs
|
||||
**Solution**: Added runtime API URL patching in Docker container startup
|
||||
|
||||
**Current Fix Applied**:
|
||||
1. ✅ Enhanced patched-start.sh to replace API URLs at runtime
|
||||
2. ✅ Added debug endpoint `/api/v1/debug/deployment` for verification
|
||||
3. ✅ Added deployment verification script `verify-isolation.sh`
|
||||
|
||||
### Next Debugging Steps:
|
||||
|
||||
|
|
@ -102,14 +108,25 @@ The 502 errors should resolve once:
|
|||
|
||||
### Post-Deploy Verification:
|
||||
|
||||
After redeploying, run the debug script again and verify:
|
||||
After redeploying, verify isolation works:
|
||||
```bash
|
||||
docker exec -it <container_name> /app/debug-services.sh
|
||||
# Run the automated verification script
|
||||
./verify-isolation.sh
|
||||
|
||||
# Or manually test the debug endpoints
|
||||
curl https://adr-lms.whitex.cloud/api/v1/debug/deployment
|
||||
curl https://edu.adradviser.ro/api/v1/debug/deployment
|
||||
|
||||
# Check for cross-deployment API calls in browser Network tab
|
||||
# Should see only same-domain API calls:
|
||||
# - DEV: Only calls to adr-lms.whitex.cloud
|
||||
# - LIVE: Only calls to edu.adradviser.ro
|
||||
```
|
||||
|
||||
Expected output should show:
|
||||
- ✅ PM2 status: Both services "online"
|
||||
- ✅ Port 9000: Backend responding with status 200
|
||||
- ✅ No bash execution errors in logs
|
||||
- ✅ Different database hosts for DEV vs LIVE
|
||||
- ✅ Different cookie domains: adr-lms.whitex.cloud vs edu.adradviser.ro
|
||||
- ✅ No cross-domain API calls in browser Network tab
|
||||
- ✅ Separate content/courses on each deployment
|
||||
|
||||
The port configuration fix was the critical missing piece for Traefik routing.
|
||||
|
|
|
|||
|
|
@ -69,6 +69,12 @@ find /app/web/.next -type f -name "*.js" -exec sed -i "s/domain:[^,}]*,/domain:
|
|||
find /app/web/.next -type f -name "*.js" -exec sed -i "s/domain: *process.env.LEARNHOUSE_COOKIE_DOMAIN/domain: undefined/g" {} \\;\n\
|
||||
find /app/web/.next -type f -name "*.js" -exec sed -i "s/\.domain\s*=\s*[^;]*;/\.domain = undefined;/g" {} \\;\n\
|
||||
echo "Patch complete."\n\
|
||||
echo "Patching API URLs for deployment isolation..."\n\
|
||||
if [ ! -z "$NEXT_PUBLIC_LEARNHOUSE_API_URL" ]; then\n\
|
||||
find /app/web/.next -type f -name "*.js" -exec sed -i "s|https://[^/\"]*\\(/api/v1/\\)|${NEXT_PUBLIC_LEARNHOUSE_API_URL}|g" {} \\;\n\
|
||||
find /app/web/.next -type f -name "*.js" -exec sed -i "s|https://[^/\"]*\\(/api/auth\\)|${NEXT_PUBLIC_LEARNHOUSE_BACKEND_URL}api/auth|g" {} \\;\n\
|
||||
echo "API URLs patched to: $NEXT_PUBLIC_LEARNHOUSE_API_URL"\n\
|
||||
fi\n\
|
||||
sh /app/start.sh' > /app/patched-start.sh && chmod +x /app/patched-start.sh
|
||||
|
||||
# Use the patched start script
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import uvicorn
|
||||
import os
|
||||
# import logfire
|
||||
from fastapi import FastAPI, Request
|
||||
from config.config import LearnHouseConfig, get_learnhouse_config
|
||||
|
|
@ -20,6 +21,15 @@ from fastapi.middleware.gzip import GZipMiddleware
|
|||
# Get LearnHouse Config
|
||||
learnhouse_config: LearnHouseConfig = get_learnhouse_config()
|
||||
|
||||
# Debug logging for deployment isolation
|
||||
print(f"🔍 DEPLOYMENT DEBUG INFO:")
|
||||
print(f" DEPLOYMENT_NAME: {os.environ.get('DEPLOYMENT_NAME', 'NOT_SET')}")
|
||||
print(f" DATABASE: {learnhouse_config.database_config.sql_connection_string[:50]}...")
|
||||
print(f" REDIS: {learnhouse_config.redis_config.redis_connection_string[:50]}...")
|
||||
print(f" COOKIE_DOMAIN: {learnhouse_config.hosting_config.cookie_config.domain}")
|
||||
print(f" API_DOMAIN: {learnhouse_config.hosting_config.domain}")
|
||||
print(f"🔍 END DEBUG INFO")
|
||||
|
||||
# Global Config
|
||||
app = FastAPI(
|
||||
title=learnhouse_config.site_name,
|
||||
|
|
@ -83,3 +93,15 @@ if __name__ == "__main__":
|
|||
@app.get("/")
|
||||
async def root():
|
||||
return {"Message": "Welcome to LearnHouse ✨"}
|
||||
|
||||
# Debug endpoint for deployment verification
|
||||
@app.get("/debug/deployment")
|
||||
async def debug_deployment():
|
||||
import os
|
||||
return {
|
||||
"deployment_name": os.environ.get('DEPLOYMENT_NAME', 'NOT_SET'),
|
||||
"cookie_domain": learnhouse_config.hosting_config.cookie_config.domain,
|
||||
"api_domain": learnhouse_config.hosting_config.domain,
|
||||
"database_host": learnhouse_config.database_config.sql_connection_string.split('@')[1].split('/')[0] if '@' in learnhouse_config.database_config.sql_connection_string else "unknown",
|
||||
"redis_host": learnhouse_config.redis_config.redis_connection_string.split('@')[1].split(':')[0] if '@' in learnhouse_config.redis_config.redis_connection_string else "unknown"
|
||||
}
|
||||
|
|
|
|||
88
verify-isolation.sh
Executable file
88
verify-isolation.sh
Executable file
|
|
@ -0,0 +1,88 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "🔍 LearnHouse Deployment Isolation Verification"
|
||||
echo "==============================================="
|
||||
|
||||
# Check DEV deployment
|
||||
echo ""
|
||||
echo "📋 DEV Deployment (adr-lms.whitex.cloud):"
|
||||
echo "----------------------------------------"
|
||||
echo "Testing API connection..."
|
||||
DEV_RESPONSE=$(curl -s https://adr-lms.whitex.cloud/api/v1/debug/deployment 2>/dev/null)
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ DEV API accessible"
|
||||
echo " Response: $DEV_RESPONSE"
|
||||
else
|
||||
echo "❌ DEV API not accessible"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Testing frontend..."
|
||||
DEV_FRONTEND=$(curl -s -o /dev/null -w "%{http_code}" https://adr-lms.whitex.cloud/ 2>/dev/null)
|
||||
if [ "$DEV_FRONTEND" = "200" ]; then
|
||||
echo "✅ DEV Frontend accessible (HTTP $DEV_FRONTEND)"
|
||||
else
|
||||
echo "❌ DEV Frontend issue (HTTP $DEV_FRONTEND)"
|
||||
fi
|
||||
|
||||
# Check LIVE deployment
|
||||
echo ""
|
||||
echo "📋 LIVE Deployment (edu.adradviser.ro):"
|
||||
echo "---------------------------------------"
|
||||
echo "Testing API connection..."
|
||||
LIVE_RESPONSE=$(curl -s https://edu.adradviser.ro/api/v1/debug/deployment 2>/dev/null)
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ LIVE API accessible"
|
||||
echo " Response: $LIVE_RESPONSE"
|
||||
else
|
||||
echo "❌ LIVE API not accessible"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Testing frontend..."
|
||||
LIVE_FRONTEND=$(curl -s -o /dev/null -w "%{http_code}" https://edu.adradviser.ro/ 2>/dev/null)
|
||||
if [ "$LIVE_FRONTEND" = "200" ]; then
|
||||
echo "✅ LIVE Frontend accessible (HTTP $LIVE_FRONTEND)"
|
||||
else
|
||||
echo "❌ LIVE Frontend issue (HTTP $LIVE_FRONTEND)"
|
||||
fi
|
||||
|
||||
# Analysis
|
||||
echo ""
|
||||
echo "🔍 Cross-Deployment Isolation Analysis:"
|
||||
echo "========================================"
|
||||
|
||||
# Extract database hosts if responses are valid JSON
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
DEV_DB=$(echo "$DEV_RESPONSE" | jq -r '.database_host // "unknown"' 2>/dev/null)
|
||||
LIVE_DB=$(echo "$LIVE_RESPONSE" | jq -r '.database_host // "unknown"' 2>/dev/null)
|
||||
|
||||
if [ "$DEV_DB" != "unknown" ] && [ "$LIVE_DB" != "unknown" ]; then
|
||||
if [ "$DEV_DB" = "$LIVE_DB" ]; then
|
||||
echo "⚠️ WARNING: Both deployments using same database host: $DEV_DB"
|
||||
else
|
||||
echo "✅ Database isolation: DEV($DEV_DB) ≠ LIVE($LIVE_DB)"
|
||||
fi
|
||||
fi
|
||||
|
||||
DEV_COOKIE=$(echo "$DEV_RESPONSE" | jq -r '.cookie_domain // "unknown"' 2>/dev/null)
|
||||
LIVE_COOKIE=$(echo "$LIVE_RESPONSE" | jq -r '.cookie_domain // "unknown"' 2>/dev/null)
|
||||
|
||||
if [ "$DEV_COOKIE" != "unknown" ] && [ "$LIVE_COOKIE" != "unknown" ]; then
|
||||
if [ "$DEV_COOKIE" = "$LIVE_COOKIE" ]; then
|
||||
echo "⚠️ WARNING: Both deployments using same cookie domain: $DEV_COOKIE"
|
||||
else
|
||||
echo "✅ Cookie isolation: DEV($DEV_COOKIE) ≠ LIVE($LIVE_COOKIE)"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ Install 'jq' for detailed analysis"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🚀 Next Steps:"
|
||||
echo "=============="
|
||||
echo "1. If APIs are accessible, check browser Network tab for cross-deployment calls"
|
||||
echo "2. Clear browser cache/cookies for both domains"
|
||||
echo "3. Test in incognito mode to verify isolation"
|
||||
echo "4. Check container logs: docker logs <container_name>"
|
||||
Loading…
Add table
Add a link
Reference in a new issue