From d9cf68ba7c9aa8ecabefc75feb79c91b71c21a60 Mon Sep 17 00:00:00 2001 From: javad Date: Fri, 11 Sep 2026 13:32:31 +0330 Subject: [PATCH] static and media url fix 3 --- docker-compose.yml | 20 ++++++++++++++++++++ docs/DEPLOYMENT_COOLIFY.md | 4 ++-- tests/test_deployment.py | 14 +++++++++----- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index afeb158..913e554 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -86,6 +86,25 @@ services: restart: unless-stopped networks: - coolify + labels: + # Coolify generates the Host/PathPrefix/TLS rules from the three nginx + # Domains entries. Pin those generated routers to this container and give + # them precedence over web's catch-all PathPrefix(`/`) router. + - "traefik.enable=true" + - "traefik.docker.network=${COOLIFY_RESOURCE_UUID:?}" + - "traefik.http.services.customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}.loadbalancer.server.port=80" + - "traefik.http.routers.http-0-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" + - "traefik.http.routers.http-0-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" + - "traefik.http.routers.http-1-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" + - "traefik.http.routers.http-1-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" + - "traefik.http.routers.http-2-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" + - "traefik.http.routers.http-2-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" + - "traefik.http.routers.https-0-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" + - "traefik.http.routers.https-0-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" + - "traefik.http.routers.https-1-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" + - "traefik.http.routers.https-1-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" + - "traefik.http.routers.https-2-${COOLIFY_RESOURCE_UUID:?}-nginx.priority=10000" + - "traefik.http.routers.https-2-${COOLIFY_RESOURCE_UUID:?}-nginx.service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" expose: - "80" depends_on: @@ -102,6 +121,7 @@ services: interval: 15s timeout: 7s retries: 5 + start_period: 10s volumes: static_data: diff --git a/docs/DEPLOYMENT_COOLIFY.md b/docs/DEPLOYMENT_COOLIFY.md index d8d0a7d..b8ed98d 100644 --- a/docs/DEPLOYMENT_COOLIFY.md +++ b/docs/DEPLOYMENT_COOLIFY.md @@ -30,11 +30,11 @@ customer_ticket_seed - `Domains for web`: `https://connect.loolegostar.com:8000` - `Domains for notification-worker`: خالی -- `Domains for nginx`: `cc` +- `Domains for nginx`: `https://connect.loolegostar.com/static,https://connect.loolegostar.com/media/branding,https://connect.loolegostar.com/protected-media` در `Configuration > Advanced` گزینه `Strip Prefixes` را **خاموش** کنید. در غیر این صورت Coolify پیشوند `/static` یا `/media/branding` را قبل از تحویل درخواست حذف می‌کند، در حالی که `docker/nginx.conf` عمداً همان مسیرهای کامل را match می‌کند. بعد از Save، گزینه `Reload Compose File` و سپس Redeploy را اجرا کنید. -Traefik خود Coolify TLS، reverse proxy و اولویت routeهای path-based را مدیریت می‌کند؛ Nginx جلوی Django قرار نمی‌گیرد و فقط فایل‌های static و media را سرو می‌کند. +Traefik خود Coolify ruleهای Host/PathPrefix، TLS و reverse proxy را تولید می‌کند. به‌دلیل باگ رقابت route مسیرمحور با route عمومی در برخی نسخه‌های Coolify، Compose روی routerهای تولیدشده‌ی nginx صراحتاً `priority=10000`، یک service روی پورت 80 و شبکه‌ی resource-specific را تنظیم می‌کند. ترتیب سه Domain بالا را تغییر ندهید، چون شماره routerهای `0` تا `2` از همین ترتیب ساخته می‌شود. Nginx جلوی Django قرار نمی‌گیرد و فقط فایل‌های static و media را سرو می‌کند. فایل‌های آپلودی تیکت عمومی نیستند: Django ابتدا مجوز را بررسی می‌کند و سپس کاربر را با یک URL امضاشده پنج‌دقیقه‌ای به `/protected-media/` روی Nginx می‌فرستد. branding عمومی زیر `/media/branding/` مستقیماً از Nginx سرو می‌شود. diff --git a/tests/test_deployment.py b/tests/test_deployment.py index 0ca7a48..2001c70 100644 --- a/tests/test_deployment.py +++ b/tests/test_deployment.py @@ -45,11 +45,15 @@ def test_nginx_serves_assets_without_proxying_django(): assert "media_data:/app/media:ro" in compose assert "notification-worker:" in compose assert " db:" not in compose - # Normal Git-based Coolify applications generate proxy routes from the - # service Domains fields. Hand-maintained Traefik routers belong to Raw - # Compose deployments and must not compete with Coolify's generated routes. - assert "traefik.http.routers" not in compose - assert "traefik.docker.network" not in compose + # Coolify owns Host/PathPrefix/TLS generation. The Compose file only pins + # the generated nginx routers to a high-priority port-80 service so web's + # catch-all route cannot capture static/media traffic. + assert ".rule=Host(" not in compose + assert "customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}" in compose + assert "traefik.docker.network=${COOLIFY_RESOURCE_UUID:?}" in compose + assert compose.count(".priority=10000") == 6 + assert compose.count(".service=customer-ticket-assets-${COOLIFY_RESOURCE_UUID:?}") == 6 + assert ".loadbalancer.server.port=80" in compose assert "Set MEDIA_SIGNING_SECRET in Coolify" not in compose