From a91606cc32adeb0a19bf73fbe68d703f70864d94 Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Wed, 29 Apr 2026 20:16:18 +0330 Subject: [PATCH] feat(deploy): serve backend from api subdomain --- README.md | 15 ++++++---- backend/.env.sample | 6 ++-- frontend/.env.sample | 2 +- nginx/nginx.conf | 69 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 0e7a0c3..e517fed 100644 --- a/README.md +++ b/README.md @@ -45,18 +45,20 @@ The backend container runs database migrations and `collectstatic` on startup, t The Nginx config is prepared for: - `qlockify.ir` - `www.qlockify.ir` +- `api.qlockify.ir` Requests to `www.qlockify.ir` are redirected to `qlockify.ir`. +Backend traffic is served from `api.qlockify.ir`. Before bringing the stack up in production: -1. Point the DNS `A` or `AAAA` records for `qlockify.ir` and `www.qlockify.ir` to your server. +1. Point the DNS `A` or `AAAA` records for `qlockify.ir`, `www.qlockify.ir`, and `api.qlockify.ir` to your server. 2. Set the backend env values in `./backend/qlockify-backend-deployment/.env`: - - `DJANGO_ALLOWED_HOSTS=qlockify.ir,www.qlockify.ir` + - `DJANGO_ALLOWED_HOSTS=api.qlockify.ir,qlockify.ir,www.qlockify.ir` - `CORS_ALLOWED_ORIGINS=https://qlockify.ir,https://www.qlockify.ir` - - `CSRF_TRUSTED_ORIGINS=https://qlockify.ir,https://www.qlockify.ir` - - `BASE_URL=https://qlockify.ir` + - `CSRF_TRUSTED_ORIGINS=https://api.qlockify.ir,https://qlockify.ir,https://www.qlockify.ir` + - `BASE_URL=https://api.qlockify.ir` 3. Set the frontend env value in `./frontend/qlockify-frontend-deployment/.env`: - - `VITE_API_BASE_URL=https://qlockify.ir/api` + - `VITE_API_BASE_URL=https://api.qlockify.ir/api` ## SSL certificates @@ -73,6 +75,9 @@ With the current Nginx config: - `http://qlockify.ir` redirects to `https://qlockify.ir` - `http://www.qlockify.ir` redirects to `https://qlockify.ir` - `https://www.qlockify.ir` redirects to `https://qlockify.ir` +- `http://api.qlockify.ir` redirects to `https://api.qlockify.ir` +- the main site is served from `https://qlockify.ir` +- the backend API, admin, docs, media, and static files are served from `https://api.qlockify.ir` Make sure port `443` is open on the server firewall before starting the stack. diff --git a/backend/.env.sample b/backend/.env.sample index d9c6726..600349a 100644 --- a/backend/.env.sample +++ b/backend/.env.sample @@ -5,7 +5,7 @@ DEBUG=True # Django Core DJANGO_SETTINGS_MODULE=config.settings DJANGO_SECRET_KEY= -DJANGO_ALLOWED_HOSTS=qlockify.ir,www.qlockify.ir +DJANGO_ALLOWED_HOSTS=api.qlockify.ir,qlockify.ir,www.qlockify.ir # Database POSTGRES_DB=app_db @@ -16,7 +16,7 @@ POSTGRES_PORT=5432 # CORS / CSRF CORS_ALLOWED_ORIGINS=https://qlockify.ir,https://www.qlockify.ir -CSRF_TRUSTED_ORIGINS=https://qlockify.ir,https://www.qlockify.ir +CSRF_TRUSTED_ORIGINS=https://api.qlockify.ir,https://qlockify.ir,https://www.qlockify.ir # JWT ACCESS_TOKEN_LIFETIME=5 @@ -41,4 +41,4 @@ LANGUAGE_CODE=en-us TIME_ZONE=Asia/Tehran SMS_APIKEY= -BASE_URL=https://qlockify.ir +BASE_URL=https://api.qlockify.ir diff --git a/frontend/.env.sample b/frontend/.env.sample index 3b14e2d..5989de1 100644 --- a/frontend/.env.sample +++ b/frontend/.env.sample @@ -1 +1 @@ -VITE_API_BASE_URL=https://qlockify.ir/api +VITE_API_BASE_URL=https://api.qlockify.ir diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 0a922b1..ef27af7 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -5,6 +5,13 @@ server { return 301 https://qlockify.ir$request_uri; } +server { + listen 80; + server_name api.qlockify.ir; + + return 301 https://api.qlockify.ir$request_uri; +} + server { listen 443 ssl; http2 on; @@ -35,7 +42,58 @@ server { client_max_body_size 100M; sendfile on; - # Static and Media files + location /api/ { + return 301 https://api.qlockify.ir$request_uri; + } + + location /admin/ { + return 301 https://api.qlockify.ir$request_uri; + } + + location /docs { + return 301 https://api.qlockify.ir$request_uri; + } + + location /redoc { + return 301 https://api.qlockify.ir$request_uri; + } + + location /openapi.json { + return 301 https://api.qlockify.ir$request_uri; + } + + location /static/ { + return 301 https://api.qlockify.ir$request_uri; + } + + location /media/ { + return 301 https://api.qlockify.ir$request_uri; + } + + location / { + proxy_pass http://frontend:80; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} + +server { + listen 443 ssl; + http2 on; + server_name api.qlockify.ir; + + ssl_certificate /etc/nginx/certs/fullchain.pem; + ssl_certificate_key /etc/nginx/certs/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:10m; + + client_max_body_size 100M; + sendfile on; + location /static/ { alias /usr/share/nginx/html/static/; expires 30d; @@ -48,7 +106,6 @@ server { access_log off; } - # Protect API Documentation with Basic Auth location ~ ^/(docs|redoc|openapi.json|api/docs|api/redoc|api/openapi.json|api/v1/docs) { auth_basic "Restricted API Documentation"; auth_basic_user_file /etc/nginx/.htpasswd; @@ -90,12 +147,4 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } - - location / { - proxy_pass http://frontend:80; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } }