feat(deploy): serve backend from api subdomain

This commit is contained in:
2026-04-29 20:16:18 +03:30
parent 64be80da12
commit a91606cc32
4 changed files with 73 additions and 19 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -1 +1 @@
VITE_API_BASE_URL=https://qlockify.ir/api
VITE_API_BASE_URL=https://api.qlockify.ir

View File

@@ -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;
}
}