chore(readme): add README.md
This commit is contained in:
244
README.md
244
README.md
@@ -1,90 +1,250 @@
|
|||||||
# Qlockify Deployment
|
# Qlockify Deployment
|
||||||
|
|
||||||
This repository is the deployment layer only.
|
Main deployment and operations repository for Qlockify.
|
||||||
|
|
||||||
|
This repo is the entrypoint for running the full product stack in production.
|
||||||
|
|
||||||
|
## Related Repositories
|
||||||
|
|
||||||
|
- Deployment repository declared by `origin`: `https://git.amiirkhl.ir/Qlockify/qlockify-core-deployment.git`
|
||||||
|
- Backend repository declared by its `origin`: `https://git.amiirkhl.ir/Qlockify/qlockify-backend-deployment.git`
|
||||||
|
- Frontend repository declared by its `origin`: `https://git.amiirkhl.ir/Qlockify/qlockify-frontend-deployment.git`
|
||||||
|
|
||||||
|
Use this repo for:
|
||||||
|
|
||||||
|
- Docker Compose orchestration
|
||||||
|
- Nginx
|
||||||
|
- SSL certificate mounting
|
||||||
|
- domain routing
|
||||||
|
- environment layout
|
||||||
|
- production service startup
|
||||||
|
|
||||||
|
Use the backend and frontend repos for application-level implementation details.
|
||||||
|
|
||||||
|
## What This Repo Contains
|
||||||
|
|
||||||
|
- `docker-compose.yml`
|
||||||
|
- Nginx config
|
||||||
|
- Postgres support files
|
||||||
|
- Dockerfiles for production images
|
||||||
|
- deployment environment samples
|
||||||
|
- container networking and volume wiring
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
Main deployed services:
|
||||||
|
|
||||||
|
- `nginx`
|
||||||
|
- `frontend`
|
||||||
|
- `backend`
|
||||||
|
- `celery`
|
||||||
|
- `celery-beat`
|
||||||
|
- `redis`
|
||||||
|
- `db`
|
||||||
|
|
||||||
|
Traffic pattern:
|
||||||
|
|
||||||
|
- `qlockify.ir` serves the frontend
|
||||||
|
- `api.qlockify.ir` serves the backend API, admin, docs, static, and media
|
||||||
|
- Nginx terminates TLS and proxies requests to the frontend and backend containers
|
||||||
|
|
||||||
|
## Expected Repository Layout
|
||||||
|
|
||||||
|
Docker builds read from nested application directories inside this repository:
|
||||||
|
|
||||||
Docker builds now read from nested application source directories inside this repository:
|
|
||||||
- `./backend/qlockify-backend-deployment`
|
- `./backend/qlockify-backend-deployment`
|
||||||
- `./frontend/qlockify-frontend-deployment`
|
- `./frontend/qlockify-frontend-deployment`
|
||||||
|
|
||||||
Those directories are expected to contain the backend and frontend application source before you build for deployment.
|
Expected layout:
|
||||||
|
|
||||||
## Local structure
|
|
||||||
|
|
||||||
The expected deployment layout is:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
qlockify-deployment/
|
qlockify-deployment/
|
||||||
backend/
|
backend/
|
||||||
|
Dockerfile
|
||||||
|
.env.sample
|
||||||
qlockify-backend-deployment/
|
qlockify-backend-deployment/
|
||||||
frontend/
|
frontend/
|
||||||
|
Dockerfile
|
||||||
|
.env.sample
|
||||||
qlockify-frontend-deployment/
|
qlockify-frontend-deployment/
|
||||||
nginx/
|
nginx/
|
||||||
postgres/
|
postgres/
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployment flow
|
## Deployment Flow
|
||||||
|
|
||||||
|
### 1. Place application source
|
||||||
|
|
||||||
|
Put the app repos into:
|
||||||
|
|
||||||
1. Put your application source into:
|
|
||||||
- `./backend/qlockify-backend-deployment`
|
- `./backend/qlockify-backend-deployment`
|
||||||
- `./frontend/qlockify-frontend-deployment`
|
- `./frontend/qlockify-frontend-deployment`
|
||||||
2. Configure deployment env files:
|
|
||||||
|
### 2. Configure env files
|
||||||
|
|
||||||
|
Create and fill:
|
||||||
|
|
||||||
- `./.env`
|
- `./.env`
|
||||||
- `./backend/qlockify-backend-deployment/.env`
|
- `./backend/qlockify-backend-deployment/.env`
|
||||||
- `./frontend/qlockify-frontend-deployment/.env`
|
- `./frontend/qlockify-frontend-deployment/.env`
|
||||||
3. From `qlockify-deployment`, build and start the stack:
|
|
||||||
|
### 3. Build and run
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
docker compose up --build
|
docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
The backend container runs database migrations and `collectstatic` on startup, then serves Django with Gunicorn using `config.wsgi:application`.
|
The backend container runs:
|
||||||
|
|
||||||
## Domain setup
|
- database migrations
|
||||||
|
- `collectstatic`
|
||||||
|
- Gunicorn startup
|
||||||
|
|
||||||
|
## Domain and Routing
|
||||||
|
|
||||||
|
Configured domains:
|
||||||
|
|
||||||
The Nginx config is prepared for:
|
|
||||||
- `qlockify.ir`
|
- `qlockify.ir`
|
||||||
- `www.qlockify.ir`
|
- `www.qlockify.ir`
|
||||||
- `api.qlockify.ir`
|
- `api.qlockify.ir`
|
||||||
|
|
||||||
Requests to `www.qlockify.ir` are redirected to `qlockify.ir`.
|
Behavior:
|
||||||
Backend traffic is served from `api.qlockify.ir`.
|
|
||||||
|
|
||||||
Before bringing the stack up in production:
|
- `www.qlockify.ir` redirects to `qlockify.ir`
|
||||||
1. Point the DNS `A` or `AAAA` records for `qlockify.ir`, `www.qlockify.ir`, and `api.qlockify.ir` to your server.
|
- `http` redirects to `https`
|
||||||
2. Set the backend env values in `./backend/qlockify-backend-deployment/.env`:
|
- frontend is served from `qlockify.ir`
|
||||||
- `DJANGO_ALLOWED_HOSTS=api.qlockify.ir,qlockify.ir,www.qlockify.ir`
|
- backend traffic is served from `api.qlockify.ir`
|
||||||
- `CORS_ALLOWED_ORIGINS=https://qlockify.ir,https://www.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://api.qlockify.ir/api`
|
|
||||||
|
|
||||||
## SSL certificates
|
Before production startup:
|
||||||
|
|
||||||
HTTPS is configured through Nginx if you place these files in:
|
1. Point DNS records for `qlockify.ir`, `www.qlockify.ir`, and `api.qlockify.ir` to the server.
|
||||||
|
2. Make sure `80` and `443` are open on the server firewall.
|
||||||
|
3. Make sure the TLS certificate covers all required names.
|
||||||
|
|
||||||
|
## SSL Certificates
|
||||||
|
|
||||||
|
Place certificate files here:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
./nginx/certs/fullchain.pem
|
./nginx/certs/fullchain.pem
|
||||||
./nginx/certs/privkey.pem
|
./nginx/certs/privkey.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
The repo keeps `./nginx/certs/.gitkeep` only. Actual certificate files are ignored by git.
|
The repository intentionally keeps only:
|
||||||
|
|
||||||
With the current Nginx config:
|
- `./nginx/certs/.gitkeep`
|
||||||
- `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.
|
Real certificate files are ignored by git.
|
||||||
|
|
||||||
## SSE Notifications
|
## Required Backend Environment
|
||||||
|
|
||||||
Notifications now use Server-Sent Events at `/api/notifications/stream/`.
|
Set these in:
|
||||||
|
|
||||||
- Nginx disables buffering and cacheing for the SSE endpoint.
|
```text
|
||||||
- The current Gunicorn setup can serve SSE for MVP traffic, but each live stream consumes a worker while connected.
|
./backend/qlockify-backend-deployment/.env
|
||||||
- If notification concurrency grows, move the SSE endpoint to an async worker class or a dedicated ASGI process.
|
```
|
||||||
|
|
||||||
|
Core production values:
|
||||||
|
|
||||||
|
- `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://api.qlockify.ir,https://qlockify.ir,https://www.qlockify.ir`
|
||||||
|
- `BASE_URL=https://api.qlockify.ir`
|
||||||
|
- `POSTGRES_HOST=db`
|
||||||
|
- `REDIS_HOST=redis`
|
||||||
|
- `REDIS_URL=redis://redis:6379/0`
|
||||||
|
- `CELERY_BROKER_URL=redis://redis:6379/0`
|
||||||
|
- `CELERY_RESULT_BACKEND=redis://redis:6379/1`
|
||||||
|
|
||||||
|
Google OAuth values:
|
||||||
|
|
||||||
|
- `GOOGLE_OAUTH_CLIENT_ID=...`
|
||||||
|
- `GOOGLE_OAUTH_CLIENT_SECRET=...`
|
||||||
|
- `GOOGLE_OAUTH_REDIRECT_URI=https://api.qlockify.ir/api/users/oauth/google/callback/`
|
||||||
|
- `GOOGLE_OAUTH_FRONTEND_CALLBACK_URL=https://qlockify.ir/auth/google/callback`
|
||||||
|
|
||||||
|
## Required Frontend Environment
|
||||||
|
|
||||||
|
Set this in:
|
||||||
|
|
||||||
|
```text
|
||||||
|
./frontend/qlockify-frontend-deployment/.env
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
VITE_API_BASE_URL=https://api.qlockify.ir/api
|
||||||
|
```
|
||||||
|
|
||||||
|
## Background Workers
|
||||||
|
|
||||||
|
This stack includes:
|
||||||
|
|
||||||
|
- `celery` for async jobs
|
||||||
|
- `celery-beat` for scheduled jobs
|
||||||
|
|
||||||
|
If background scheduling stops working, inspect:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
docker compose logs -f celery
|
||||||
|
docker compose logs -f celery-beat
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notifications and SSE
|
||||||
|
|
||||||
|
Notifications use Server-Sent Events at `/api/notifications/stream/`.
|
||||||
|
|
||||||
|
Current behavior:
|
||||||
|
|
||||||
|
- Nginx disables buffering for the SSE endpoint
|
||||||
|
- Gunicorn is tuned to tolerate connected streams for current traffic
|
||||||
|
- if concurrency grows materially, move SSE to async workers or a dedicated ASGI service
|
||||||
|
|
||||||
|
## Useful Operations
|
||||||
|
|
||||||
|
Build/rebuild:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart a subset:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
docker compose up -d --build nginx backend frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
Inspect running services:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
docker compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
Follow logs:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
docker compose logs -f nginx
|
||||||
|
docker compose logs -f backend
|
||||||
|
docker compose logs -f celery
|
||||||
|
docker compose logs -f celery-beat
|
||||||
|
```
|
||||||
|
|
||||||
|
Stop everything:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scope Boundary
|
||||||
|
|
||||||
|
This repo should document:
|
||||||
|
|
||||||
|
- infrastructure
|
||||||
|
- runtime topology
|
||||||
|
- domains
|
||||||
|
- Nginx
|
||||||
|
- Docker Compose
|
||||||
|
- SSL
|
||||||
|
- operational startup and troubleshooting
|
||||||
|
|
||||||
|
It should not duplicate the application-specific implementation details already documented in the backend and frontend repositories.
|
||||||
|
|||||||
Reference in New Issue
Block a user