feat: add deployment guide, nginx/systemd configs, switch to adapter-node
- Add docs/DEPLOYMENT.md: step-by-step Proxmox LXC guide (Debian 13, PostgreSQL, nginx reverse proxy, systemd services) - Add nginx/innercontext.conf: proxy /api/ → uvicorn, /mcp/ → uvicorn with SSE streaming support, / → SvelteKit Node server - Add systemd/innercontext.service and innercontext-node.service - Switch frontend from adapter-auto to adapter-node (required for +page.server.ts form actions); install adapter-node 5.5.4 - Update README.md: add frontend, MCP sections; fix /skin-snapshots → /skincare; update repo layout - Replace frontend/README.md generic Svelte template with project docs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
142fbe8530
commit
95fbdeb212
9 changed files with 649 additions and 47 deletions
311
docs/DEPLOYMENT.md
Normal file
311
docs/DEPLOYMENT.md
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
# Deployment guide — Proxmox LXC (home network)
|
||||
|
||||
Target architecture:
|
||||
|
||||
```
|
||||
Reverse proxy (existing) innercontext LXC (new, Debian 13)
|
||||
┌──────────────────────┐ ┌────────────────────────────────────┐
|
||||
│ reverse proxy │────────────▶│ nginx :80 │
|
||||
│ innercontext.lan → * │ │ /api/* → uvicorn :8000/* │
|
||||
└──────────────────────┘ │ /mcp/* → uvicorn :8000/mcp/* │
|
||||
│ /* → SvelteKit Node :3000 │
|
||||
└────────────────────────────────────┘
|
||||
│ │
|
||||
FastAPI + MCP SvelteKit Node
|
||||
```
|
||||
|
||||
## 1. Prerequisites
|
||||
|
||||
- Proxmox VE host with an existing PostgreSQL LXC and a reverse proxy
|
||||
- LAN hostname `innercontext.lan` resolvable on the network (via router DNS or `/etc/hosts`)
|
||||
- The PostgreSQL LXC must accept connections from the innercontext LXC IP
|
||||
|
||||
---
|
||||
|
||||
## 2. Create the LXC container
|
||||
|
||||
In the Proxmox UI (or via CLI):
|
||||
|
||||
```bash
|
||||
# CLI example — adjust storage, bridge, IP to your environment
|
||||
pct create 200 local:vztmpl/debian-13-standard_13.0-1_amd64.tar.zst \
|
||||
--hostname innercontext \
|
||||
--cores 2 \
|
||||
--memory 1024 \
|
||||
--swap 512 \
|
||||
--rootfs local-lvm:8 \
|
||||
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
|
||||
--unprivileged 1 \
|
||||
--start 1
|
||||
```
|
||||
|
||||
Note the container's IP address after it starts (`pct exec 200 -- ip -4 a`).
|
||||
|
||||
---
|
||||
|
||||
## 3. Container setup
|
||||
|
||||
```bash
|
||||
pct enter 200 # or SSH into the container
|
||||
```
|
||||
|
||||
### System packages
|
||||
|
||||
```bash
|
||||
apt update && apt upgrade -y
|
||||
apt install -y git nginx curl ca-certificates gnupg lsb-release
|
||||
```
|
||||
|
||||
### Python 3.12+ + uv
|
||||
|
||||
```bash
|
||||
apt install -y python3 python3-venv
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
source $HOME/.local/bin/env # or re-login
|
||||
```
|
||||
|
||||
### Node.js 22 + pnpm
|
||||
|
||||
```bash
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
apt install -y nodejs
|
||||
npm install -g pnpm
|
||||
```
|
||||
|
||||
### Application user
|
||||
|
||||
```bash
|
||||
useradd --system --create-home --shell /bin/bash innercontext
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Create the database on the PostgreSQL LXC
|
||||
|
||||
Run on the **PostgreSQL LXC**:
|
||||
|
||||
```bash
|
||||
psql -U postgres <<'SQL'
|
||||
CREATE USER innercontext WITH PASSWORD 'change-me';
|
||||
CREATE DATABASE innercontext OWNER innercontext;
|
||||
SQL
|
||||
```
|
||||
|
||||
Edit `/etc/postgresql/18/main/pg_hba.conf` and add (replace `<lxc-ip>` with the innercontext container IP):
|
||||
|
||||
```
|
||||
host innercontext innercontext <lxc-ip>/32 scram-sha-256
|
||||
```
|
||||
|
||||
Then reload:
|
||||
|
||||
```bash
|
||||
systemctl reload postgresql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Clone the repository
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/innercontext
|
||||
git clone https://github.com/your-user/innercontext.git /opt/innercontext
|
||||
chown -R innercontext:innercontext /opt/innercontext
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Backend setup
|
||||
|
||||
```bash
|
||||
cd /opt/innercontext/backend
|
||||
```
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
sudo -u innercontext uv sync
|
||||
```
|
||||
|
||||
### Create `.env`
|
||||
|
||||
```bash
|
||||
cat > /opt/innercontext/backend/.env <<'EOF'
|
||||
DATABASE_URL=postgresql+psycopg://innercontext:change-me@<pg-lxc-ip>/innercontext
|
||||
EOF
|
||||
chmod 600 /opt/innercontext/backend/.env
|
||||
chown innercontext:innercontext /opt/innercontext/backend/.env
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
```bash
|
||||
sudo -u innercontext bash -c '
|
||||
cd /opt/innercontext/backend
|
||||
source .env
|
||||
uv run uvicorn main:app --host 127.0.0.1 --port 8000
|
||||
'
|
||||
# Ctrl-C after confirming it starts
|
||||
```
|
||||
|
||||
### Install systemd service
|
||||
|
||||
```bash
|
||||
cp /opt/innercontext/systemd/innercontext.service /etc/systemd/system/
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now innercontext
|
||||
systemctl status innercontext
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Frontend build and setup
|
||||
|
||||
```bash
|
||||
cd /opt/innercontext/frontend
|
||||
```
|
||||
|
||||
### Create `.env.production`
|
||||
|
||||
```bash
|
||||
cat > /opt/innercontext/frontend/.env.production <<'EOF'
|
||||
PUBLIC_API_BASE=http://innercontext.lan/api
|
||||
EOF
|
||||
chmod 600 /opt/innercontext/frontend/.env.production
|
||||
chown innercontext:innercontext /opt/innercontext/frontend/.env.production
|
||||
```
|
||||
|
||||
### Install dependencies and build
|
||||
|
||||
```bash
|
||||
sudo -u innercontext bash -c '
|
||||
cd /opt/innercontext/frontend
|
||||
pnpm install
|
||||
PUBLIC_API_BASE=http://innercontext.lan/api pnpm build
|
||||
'
|
||||
```
|
||||
|
||||
The production build lands in `/opt/innercontext/frontend/build/`.
|
||||
|
||||
### Install systemd service
|
||||
|
||||
```bash
|
||||
cp /opt/innercontext/systemd/innercontext-node.service /etc/systemd/system/
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now innercontext-node
|
||||
systemctl status innercontext-node
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. nginx setup
|
||||
|
||||
```bash
|
||||
cp /opt/innercontext/nginx/innercontext.conf /etc/nginx/sites-available/innercontext
|
||||
ln -s /etc/nginx/sites-available/innercontext /etc/nginx/sites-enabled/
|
||||
rm -f /etc/nginx/sites-enabled/default
|
||||
nginx -t
|
||||
systemctl reload nginx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Reverse proxy configuration
|
||||
|
||||
Point your existing reverse proxy at the innercontext LXC's nginx (`<innercontext-lxc-ip>:80`).
|
||||
|
||||
Example — Caddy:
|
||||
|
||||
```
|
||||
innercontext.lan {
|
||||
reverse_proxy <innercontext-lxc-ip>:80
|
||||
}
|
||||
```
|
||||
|
||||
Example — nginx upstream:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name innercontext.lan;
|
||||
location / {
|
||||
proxy_pass http://<innercontext-lxc-ip>:80;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Reload your reverse proxy after applying the change.
|
||||
|
||||
---
|
||||
|
||||
## 10. Verification
|
||||
|
||||
```bash
|
||||
# From any machine on the LAN:
|
||||
curl http://innercontext.lan/api/health-check # {"status":"ok"}
|
||||
curl http://innercontext.lan/api/products # []
|
||||
curl http://innercontext.lan/ # SvelteKit HTML shell
|
||||
curl -N http://innercontext.lan/mcp/mcp # MCP StreamableHTTP endpoint
|
||||
```
|
||||
|
||||
The web UI should be accessible at `http://innercontext.lan`.
|
||||
|
||||
---
|
||||
|
||||
## 11. Updating the application
|
||||
|
||||
```bash
|
||||
cd /opt/innercontext
|
||||
git pull
|
||||
|
||||
# If backend dependencies changed:
|
||||
cd backend && sudo -u innercontext uv sync && cd ..
|
||||
|
||||
# Rebuild frontend:
|
||||
cd frontend && sudo -u innercontext bash -c '
|
||||
pnpm install
|
||||
PUBLIC_API_BASE=http://innercontext.lan/api pnpm build
|
||||
'
|
||||
|
||||
systemctl restart innercontext innercontext-node
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. Troubleshooting
|
||||
|
||||
### 502 Bad Gateway on `/api/*`
|
||||
|
||||
```bash
|
||||
systemctl status innercontext
|
||||
journalctl -u innercontext -n 50
|
||||
# Check .env DATABASE_URL is correct and PG LXC accepts connections
|
||||
```
|
||||
|
||||
### 502 Bad Gateway on `/`
|
||||
|
||||
```bash
|
||||
systemctl status innercontext-node
|
||||
journalctl -u innercontext-node -n 50
|
||||
# Verify /opt/innercontext/frontend/build/index.js exists (pnpm build ran successfully)
|
||||
```
|
||||
|
||||
### MCP endpoint not responding
|
||||
|
||||
```bash
|
||||
# MCP uses SSE — disable buffering is already in nginx config
|
||||
# Verify the backend started successfully:
|
||||
curl http://127.0.0.1:8000/health-check
|
||||
# Check FastAPI logs:
|
||||
journalctl -u innercontext -n 50
|
||||
```
|
||||
|
||||
### Database connection refused
|
||||
|
||||
```bash
|
||||
# From innercontext LXC:
|
||||
psql postgresql+psycopg://innercontext:change-me@<pg-lxc-ip>/innercontext -c "SELECT 1"
|
||||
# If it fails, check pg_hba.conf on the PG LXC and verify the IP matches
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue