# TA-ATS — Linux (production deployment)

Reference host: `ats.indovisionconsultancy.in` on a cPanel/WHM server.
Project root: `/home/indovisionconsul/public_html/ats.indovisionconsultancy.in`
MCP (sibling):  `/home/indovisionconsul/public_html/auth_mcp`

> **Architecture on this server:** Django runs on **port 8000**, managed by the systemd
> unit **`ats.service`**, and **nginx proxies `/api` → 8000**. The frontend runs on
> **:3000**; the MCP on **:9000**. The FastAPI gateway is optional here (not in the
> request path) — it's only needed if you want the activity WebSocket.

Run everything as the **owning user** where possible (`indovisionconsul`) so file
ownership stays correct; use `root` only for `systemctl`.

---

## 0. Prerequisites
- Python 3.12, Node 20/22, PostgreSQL, nginx (or LiteSpeed) fronting the domain with TLS.
- DBs `ats_main` (app) and `ats_mcp_db` (MCP) created.

---

## 1. First-time install (venvs + deps)
```bash
PROJ=/home/indovisionconsul/public_html/ats.indovisionconsultancy.in
MCP=/home/indovisionconsul/public_html/auth_mcp

# MCP
cd $MCP        && python3.12 -m venv venv && ./venv/bin/pip install -r requirements.txt
# Backend
cd $PROJ/backend && python3.12 -m venv venv && ./venv/bin/pip install -r requirements/base.txt
./venv/bin/pip install gunicorn        # production WSGI server
# Gateway (only if you use it)
cd $PROJ/gateway && python3.12 -m venv venv && ./venv/bin/pip install -r requirements.txt
# Frontend
cd $PROJ/frontend && npm install
```

---

## 2. Environment files
`backend/.env`:
```
SECRET_KEY=<strong-random>
DEBUG=False
ALLOWED_HOSTS=ats.indovisionconsultancy.in,127.0.0.1,localhost
CORS_ALLOWED_ORIGINS=https://ats.indovisionconsultancy.in
DB_NAME=ats_main
DB_USER=postgres
DB_PASSWORD=<pg-password>
DB_HOST=localhost
DB_PORT=5432
# ONE dot-one. A 127.0.0.0 typo => "MFA service unavailable".
MCP_URL=http://127.0.0.1:9000/mcp
```

`frontend/.env.production` — **required before building** (baked in at build time):
```
NEXT_PUBLIC_API_URL=https://ats.indovisionconsultancy.in/api/v1
```

---

## 3. Migrate + seed (against the PROD database)
The seed scripts default to dev settings internally, so **export prod first**:
```bash
cd $PROJ/backend
export DJANGO_SETTINGS_MODULE=config.settings.prod
PY=./venv/bin/python
$PY manage.py migrate
$PY seed_demo_users.py
$PY update_permissions.py
$PY add_master_data_menus.py
$PY add_master_skills_menu.py
$PY add_reports_menu.py
$PY seed_india_data.py
$PY seed_world_data.py
$PY seed_master_defaults.py        # if it errors on a duplicate stage, see TROUBLESHOOTING #6

# MCP auth store
cd $MCP && ./venv/bin/python -c "import db; db.ensure_schema()"
```

---

## 4. Build the frontend (production)
```bash
cd $PROJ/frontend
npm install            # ALWAYS after a git pull (new deps, e.g. xlsx)
rm -rf .next
npm run build          # must end without "Module not found"
```

---

## 5. Start / restart services
Django is managed by **systemd**; MCP + frontend by the launcher (or manually).
```bash
# Backend (systemd) on :8000
sudo systemctl restart ats.service

# MCP on :9000
cd $MCP && setsid nohup ./venv/bin/python server.py > $PROJ/logs/mcp.log 2>&1 &

# Frontend on :3000 (production server, NOT dev)
cd $PROJ/frontend
pkill -f next-server; fuser -k 3000/tcp 2>/dev/null; sleep 2
setsid nohup npm start > $PROJ/logs/frontend.log 2>&1 &
```

### One-shot deploy
Everything above is bundled in **`deploy_server.sh`** at the repo root:
```bash
cd $PROJ
bash deploy_server.sh
```
It migrates + seeds, installs deps, applies the WebSocket fix, rebuilds, restarts all
services, and prints a health check (ports + a real login → expect `200`).

---

## 6. nginx (reverse proxy + TLS + WebSocket)
Serve the UI and API over one HTTPS origin. Minimal `server` block:
```nginx
server {
    listen 443 ssl;
    server_name ats.indovisionconsultancy.in;
    # ssl_certificate / ssl_certificate_key managed by cPanel/AutoSSL

    # REST API -> Django (systemd ats.service)
    location /api/ {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Activity WebSocket -> gateway (only if the gateway is running on :8000/ws)
    # Requires the Upgrade headers or the socket will not connect.
    location /api/ws/ {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host       $host;
        proxy_read_timeout 3600s;
    }

    # Everything else -> Next.js frontend
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```
> Note: the frontend uses **`wss://<host>/api/ws/activity`** on HTTPS (see
> TROUBLESHOOTING #8). Without the `/api/ws/` upgrade block the page still loads — you
> just won't get the live-activity feed.

---

## 7. Health checks
```bash
for p in 9000 8000 3000; do ss -ltn | grep -q ":$p " && echo "OK $p" || echo "DOWN $p"; done

# real login test (expect HTTP 200 + tokens)
curl -s -X POST https://ats.indovisionconsultancy.in/api/v1/auth/login/ \
  -H "Content-Type: application/json" \
  -d '{"email":"ats@admin.com","password":"ats@2468"}' -w "\nHTTP %{http_code}\n"
```
Backend logs: `sudo journalctl -u ats.service -n 50 --no-pager`
Frontend/MCP logs: `tail -n 50 $PROJ/logs/frontend.log $PROJ/logs/mcp.log`

---

## 8. Updating (git pull) — avoid the traps we hit
```bash
cd $PROJ
sudo -u indovisionconsul git config --global --add safe.directory $PROJ   # once
sudo -u indovisionconsul git stash        # if base.py / run_linux.sh were edited locally
sudo -u indovisionconsul git pull
# reconcile .env-type local edits, then:
bash deploy_server.sh
```
Golden rules: **`npm install` after every pull**, **rebuild the frontend**, and
**`systemctl restart ats.service`** so the backend reloads code + `.env`.
