summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md90
-rw-r--r--systemd/prismv2-backend.service10
-rw-r--r--systemd/prismv2-frontend.service12
3 files changed, 84 insertions, 28 deletions
diff --git a/README.md b/README.md
index 41ee1b4..fb492f8 100644
--- a/README.md
+++ b/README.md
@@ -96,6 +96,19 @@ NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8001 npm run dev -- --hostname 127.0.0
The UI stores the selected ticker in the URL, for example `/?ticker=AAPL`.
+Production frontend runtime:
+
+```bash
+npm run build
+npm run start -- --hostname 127.0.0.1 --port 3001
+```
+
+Important API-base rule:
+
+- In production, browser requests should use same-origin `/api/*` through nginx.
+- Do not hardcode a localhost fallback API base in frontend browser code.
+- `frontend/lib/api.ts` should default to an empty base when `NEXT_PUBLIC_API_BASE_URL` is unset.
+
## Quick Start
`scripts/stack.sh` manages both services as a local development stack:
@@ -114,35 +127,69 @@ Notes:
- logs are written to `.run/logs/`
- override hosts/ports via env vars: `BACKEND_HOST`, `BACKEND_PORT`, `FRONTEND_HOST`, `FRONTEND_PORT`
-## Running as a systemd Service
+## Running in Production (systemd + nginx)
-Unit files live in `systemd/`. Install them for the current user:
+The production model is:
+
+- backend on `127.0.0.1:8001` via `uvicorn`
+- frontend on `127.0.0.1:3001` via `next start` (not `next dev`)
+- nginx TLS reverse proxy:
+ - `/api/*` -> backend
+ - `/` -> frontend
+
+Unit templates live in `systemd/` and nginx server block template lives in `nginx/`.
+
+Install system services:
```bash
-# Copy units
-cp systemd/prismv2-backend.service ~/.config/systemd/user/
-cp systemd/prismv2-frontend.service ~/.config/systemd/user/
-cp systemd/prismv2.target ~/.config/systemd/user/
+sudo cp systemd/prismv2-backend.service /etc/systemd/system/
+sudo cp systemd/prismv2-frontend.service /etc/systemd/system/
+sudo systemctl daemon-reload
+sudo systemctl enable --now prismv2-backend.service prismv2-frontend.service
+```
-systemctl --user daemon-reload
+Install nginx site:
-# Start both services via the target
-systemctl --user enable --now prismv2.target
+```bash
+sudo cp nginx/prism.tylerhoang.xyz.conf /etc/nginx/sites-available/prism.tylerhoang.xyz
+sudo ln -sf /etc/nginx/sites-available/prism.tylerhoang.xyz /etc/nginx/sites-enabled/prism.tylerhoang.xyz
+sudo nginx -t
+sudo systemctl reload nginx
+```
-# Control individual services
-systemctl --user status prismv2-backend.service
-systemctl --user restart prismv2-frontend.service
-systemctl --user stop prismv2.target
+Create writable npm cache for service user:
-# View logs
-journalctl --user -u prismv2-backend.service -f
-journalctl --user -u prismv2-frontend.service -f
+```bash
+sudo mkdir -p /var/www/prism-v2/frontend/.npm
+sudo chown -R www-data:www-data /var/www/prism-v2/frontend
```
-To start automatically on login, enable lingering once:
+Service controls:
```bash
-loginctl enable-linger $USER
+sudo systemctl status prismv2-backend.service --no-pager
+sudo systemctl status prismv2-frontend.service --no-pager
+sudo systemctl restart prismv2-backend.service prismv2-frontend.service
+sudo journalctl -u prismv2-backend.service -f
+sudo journalctl -u prismv2-frontend.service -f
+```
+
+Production deploy refresh:
+
+```bash
+cd /var/www/prism-v2
+git pull origin master
+
+cd backend
+python3 -m venv .venv
+.venv/bin/pip install -r requirements.txt
+
+cd ../frontend
+npm ci
+npm run build
+
+sudo systemctl restart prismv2-backend.service prismv2-frontend.service
+sudo systemctl reload nginx
```
## Verification
@@ -162,6 +209,13 @@ npm run lint
npm run build
```
+Production smoke checks:
+
+```bash
+curl -i http://127.0.0.1:8001/health
+curl -i "https://prism.tylerhoang.xyz/api/search?q=AAPL"
+```
+
## Current Local URLs
If port `8000` is already occupied on your machine, use:
diff --git a/systemd/prismv2-backend.service b/systemd/prismv2-backend.service
index fd69a4d..49035ff 100644
--- a/systemd/prismv2-backend.service
+++ b/systemd/prismv2-backend.service
@@ -1,15 +1,15 @@
[Unit]
-Description=Prism v2 Backend (FastAPI/uvicorn)
+Description=Prism v2 Backend (FastAPI)
After=network.target
[Service]
Type=simple
-User=tyler
-WorkingDirectory=/home/tyler/Work/prism-v2/backend
+User=www-data
+WorkingDirectory=/var/www/prism-v2/backend
Environment=PYTHONUNBUFFERED=1
-ExecStart=/home/tyler/Work/prism-v2/backend/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8001
+ExecStart=/var/www/prism-v2/backend/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8001
Restart=on-failure
RestartSec=5
[Install]
-WantedBy=multi-user.target prismv2.target
+WantedBy=multi-user.target
diff --git a/systemd/prismv2-frontend.service b/systemd/prismv2-frontend.service
index f50dd1e..5dec3fb 100644
--- a/systemd/prismv2-frontend.service
+++ b/systemd/prismv2-frontend.service
@@ -5,12 +5,14 @@ Wants=prismv2-backend.service
[Service]
Type=simple
-User=tyler
-WorkingDirectory=/home/tyler/Work/prism-v2/frontend
-Environment=NODE_ENV=development
-ExecStart=/usr/bin/npm run dev -- --hostname 127.0.0.1 --port 3001
+User=www-data
+WorkingDirectory=/var/www/prism-v2/frontend
+Environment=NODE_ENV=production
+Environment=HOME=/var/www/prism-v2/frontend
+Environment=NPM_CONFIG_CACHE=/var/www/prism-v2/frontend/.npm
+ExecStart=/usr/bin/npm run start -- --hostname 127.0.0.1 --port 3001
Restart=on-failure
RestartSec=5
[Install]
-WantedBy=multi-user.target prismv2.target
+WantedBy=multi-user.target