docs: add reverse proxy setup instructions for HTTPS deployment
- Add Step 11 with Caddy and nginx configuration examples - Update Step 2.2 to explain VITE_API_URL setup for proxy vs direct access - Add common fix for API requests returning HTML instead of JSON - Document the critical requirement to route /api/* before static files This documents the fixes for HTTPS proxy deployment where API requests were being served as HTML instead of being forwarded to the backend.
This commit is contained in:
parent
fe9dbc77e5
commit
e0712ea520
@ -46,6 +46,16 @@ Notes:
|
||||
- If you manage Postgres on a separate host, you only need `postgresql-client` on this server.
|
||||
- If you install Postgres locally, install `postgresql` (server) too, not just the client.
|
||||
|
||||
### Firewall Rules (One-time setup)
|
||||
|
||||
Configure firewall to allow access to the application ports:
|
||||
|
||||
```bash
|
||||
sudo ufw allow 3000/tcp # Admin frontend
|
||||
sudo ufw allow 3001/tcp # Viewer frontend
|
||||
sudo ufw allow 8000/tcp # Backend API
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fast path (recommended): run the deploy script
|
||||
@ -60,10 +70,13 @@ chmod +x scripts/deploy_from_scratch.sh
|
||||
|
||||
The script will:
|
||||
- Install system packages (including Redis)
|
||||
- Configure firewall rules (optional, with prompt)
|
||||
- Copy `*_example` env files to real `.env` files (if missing)
|
||||
- Install Python + Node dependencies
|
||||
- Generate Prisma clients for the viewer
|
||||
- Create auth DB tables and admin user (idempotent)
|
||||
- Build frontend applications for production
|
||||
- Configure PM2 (copy ecosystem.config.js from example if needed)
|
||||
- Start services with PM2
|
||||
|
||||
If you prefer manual steps, continue below.
|
||||
@ -131,10 +144,19 @@ cp .env_example .env
|
||||
|
||||
2. Edit `.env`:
|
||||
|
||||
**For direct access (no reverse proxy):**
|
||||
```bash
|
||||
VITE_API_URL=http://YOUR_SERVER_IP_OR_DOMAIN:8000
|
||||
```
|
||||
|
||||
**For reverse proxy setup (HTTPS via Caddy/nginx):**
|
||||
```bash
|
||||
# Leave empty to use relative paths - API calls will go through the same proxy
|
||||
VITE_API_URL=
|
||||
```
|
||||
|
||||
**Important:** When using a reverse proxy (Caddy/nginx) with HTTPS, set `VITE_API_URL` to empty. This allows the frontend to use relative API paths that work correctly with the proxy, avoiding mixed content errors.
|
||||
|
||||
### 2.3 Viewer env: `/opt/punimtag/viewer-frontend/.env`
|
||||
|
||||
1. Copy and rename:
|
||||
@ -211,10 +233,44 @@ npx tsx scripts/fix-admin-user.ts
|
||||
|
||||
---
|
||||
|
||||
## Step 6 — Start the services (PM2)
|
||||
## Step 6 — Build frontends
|
||||
|
||||
This repo includes a PM2 config at `ecosystem.config.js`.
|
||||
Verify the paths/ports match your server, then:
|
||||
Build the frontend applications for production:
|
||||
|
||||
```bash
|
||||
# Admin frontend
|
||||
cd /opt/punimtag/admin-frontend
|
||||
npm run build
|
||||
|
||||
# Viewer frontend
|
||||
cd /opt/punimtag/viewer-frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
Note: The admin frontend build creates a `dist/` directory that will be served by PM2.
|
||||
The viewer frontend build creates an optimized Next.js production build.
|
||||
|
||||
---
|
||||
|
||||
## Step 7 — Configure PM2
|
||||
|
||||
This repo includes a PM2 config template. If `ecosystem.config.js` doesn't exist, copy it from the example:
|
||||
|
||||
```bash
|
||||
cd /opt/punimtag
|
||||
cp ecosystem.config.js.example ecosystem.config.js
|
||||
```
|
||||
|
||||
Edit `ecosystem.config.js` and update:
|
||||
- All `cwd` paths to your deployment directory (e.g., `/opt/punimtag`)
|
||||
- All `error_file` and `out_file` paths to your user's home directory
|
||||
- `PYTHONPATH` and `PATH` environment variables to match your deployment paths
|
||||
|
||||
---
|
||||
|
||||
## Step 8 — Start the services (PM2)
|
||||
|
||||
Start all services using PM2:
|
||||
|
||||
```bash
|
||||
cd /opt/punimtag
|
||||
@ -230,7 +286,7 @@ pm2 startup
|
||||
|
||||
---
|
||||
|
||||
## Step 7 — First-run DB initialization (automatic)
|
||||
## Step 9 — First-run DB initialization (automatic)
|
||||
|
||||
On first startup, the backend will connect to Postgres and create missing tables automatically.
|
||||
|
||||
@ -248,7 +304,7 @@ curl -sS http://127.0.0.1:3001/api/health
|
||||
|
||||
---
|
||||
|
||||
## Step 8 — Open the apps
|
||||
## Step 10 — Open the apps
|
||||
|
||||
- **Admin**: `http://YOUR_SERVER:3000`
|
||||
- **Viewer**: `http://YOUR_SERVER:3001`
|
||||
@ -256,8 +312,112 @@ curl -sS http://127.0.0.1:3001/api/health
|
||||
|
||||
---
|
||||
|
||||
## Step 11 — Reverse Proxy Setup (HTTPS via Caddy/nginx)
|
||||
|
||||
If you're using a reverse proxy (Caddy, nginx, etc.) to serve the application over HTTPS, you need to configure it to route `/api/*` requests to the backend **before** serving static files.
|
||||
|
||||
### Issue: API requests returning HTML instead of JSON
|
||||
|
||||
**Symptom:** Login works but navigation tabs don't show, or API calls return HTML (the frontend's `index.html`) instead of JSON data.
|
||||
|
||||
**Cause:** The reverse proxy is serving static files for all requests, including `/api/*` requests, instead of forwarding them to the backend.
|
||||
|
||||
### Solution: Configure proxy to route `/api/*` first
|
||||
|
||||
The proxy must forward `/api/*` requests to the backend (port 8000) **before** trying to serve static files.
|
||||
|
||||
#### Caddy Configuration
|
||||
|
||||
Update your Caddyfile on the proxy server:
|
||||
|
||||
```caddyfile
|
||||
your-admin-domain.com {
|
||||
import security-headers
|
||||
|
||||
# CRITICAL: Route API requests to backend FIRST (before static files)
|
||||
handle /api/* {
|
||||
reverse_proxy http://YOUR_BACKEND_IP:8000 {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# Proxy everything else to the frontend
|
||||
reverse_proxy http://YOUR_BACKEND_IP:3000
|
||||
}
|
||||
```
|
||||
|
||||
**Important:** The `handle /api/*` block **must come before** the general `reverse_proxy` directive.
|
||||
|
||||
After updating:
|
||||
```bash
|
||||
# Test configuration
|
||||
caddy validate --config /path/to/Caddyfile
|
||||
|
||||
# Reload Caddy
|
||||
sudo systemctl reload caddy
|
||||
```
|
||||
|
||||
#### Nginx Configuration
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-admin-domain.com;
|
||||
|
||||
root /opt/punimtag/admin-frontend/dist;
|
||||
index index.html;
|
||||
|
||||
# CRITICAL: API proxy must come FIRST, before static file location
|
||||
location /api {
|
||||
proxy_pass http://YOUR_BACKEND_IP:8000;
|
||||
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;
|
||||
}
|
||||
|
||||
# Serve static files for everything else
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After updating:
|
||||
```bash
|
||||
# Test configuration
|
||||
sudo nginx -t
|
||||
|
||||
# Reload nginx
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Environment Variable Setup
|
||||
|
||||
When using a reverse proxy, ensure `admin-frontend/.env` has:
|
||||
|
||||
```bash
|
||||
VITE_API_URL=
|
||||
```
|
||||
|
||||
This allows the frontend to use relative API paths (`/api/v1/...`) that work correctly with the proxy.
|
||||
|
||||
---
|
||||
|
||||
## Common fixes
|
||||
|
||||
### API requests return HTML instead of JSON (reverse proxy issue)
|
||||
|
||||
**Symptom:** Browser console shows API responses are HTML (the frontend's `index.html`) instead of JSON. Login may work but navigation tabs don't appear.
|
||||
|
||||
**Solution:**
|
||||
1. Ensure your reverse proxy (Caddy/nginx) routes `/api/*` requests to the backend **before** serving static files (see Step 11 above).
|
||||
2. Verify `admin-frontend/.env` has `VITE_API_URL=` (empty) when using a proxy.
|
||||
3. Rebuild the frontend after changing `.env`: `cd admin-frontend && npm run build && pm2 restart punimtag-admin`
|
||||
|
||||
### Viewer `/api/health` says permission denied
|
||||
|
||||
Run the provided grant script on the DB server (as a privileged Postgres user):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user