docs: add deploy.sh and rewrite DEPLOYMENT.md for local-build workflow
- Add deploy.sh: builds frontend locally, rsyncs build/ to server, restarts services via passwordless sudo - DEPLOYMENT.md: remove pnpm build from server setup (frontend is never built on the LXC — esbuild hangs on low-resource containers), add rsync to apt packages, document deploy.sh setup (SSH config, sudoers), replace manual update steps with ./deploy.sh invocation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
99584521a1
commit
3428885aaa
2 changed files with 121 additions and 47 deletions
|
|
@ -14,6 +14,10 @@ Reverse proxy (existing) innercontext LXC (new, Debian 13)
|
|||
FastAPI + MCP SvelteKit Node
|
||||
```
|
||||
|
||||
> **Frontend is never built on the server.** The `vite build` + `adapter-node`
|
||||
> esbuild step is CPU/RAM-intensive and will hang on a small LXC. Build locally,
|
||||
> deploy the `build/` artifact via `deploy.sh`.
|
||||
|
||||
## 1. Prerequisites
|
||||
|
||||
- Proxmox VE host with an existing PostgreSQL LXC and a reverse proxy
|
||||
|
|
@ -53,7 +57,7 @@ pct enter 200 # or SSH into the container
|
|||
|
||||
```bash
|
||||
apt update && apt upgrade -y
|
||||
apt install -y git nginx curl ca-certificates gnupg lsb-release libpq5
|
||||
apt install -y git nginx curl ca-certificates gnupg lsb-release libpq5 rsync
|
||||
```
|
||||
|
||||
### Python 3.12+ + uv
|
||||
|
|
@ -65,7 +69,10 @@ curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh
|
|||
|
||||
Installing to `/usr/local/bin` makes `uv` available system-wide (required for `sudo -u innercontext uv sync`).
|
||||
|
||||
### Node.js 24 LTS + pnpm
|
||||
### Node.js 24 LTS
|
||||
|
||||
The server only needs Node.js to **run** the pre-built frontend bundle.
|
||||
`pnpm` is **not** needed on the server — the frontend is always built locally.
|
||||
|
||||
```bash
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash
|
||||
|
|
@ -75,23 +82,12 @@ nvm install 24
|
|||
|
||||
Copy `node` to `/usr/local/bin` so it is accessible system-wide
|
||||
(required for `sudo -u innercontext` and for systemd).
|
||||
Symlinking into `/root/.nvm/` won't work — other users can't traverse `/root/`.
|
||||
Use `--remove-destination` to replace any existing symlink with a real file:
|
||||
|
||||
```bash
|
||||
cp --remove-destination "$(nvm which current)" /usr/local/bin/node
|
||||
```
|
||||
|
||||
Install pnpm as a standalone binary from GitHub releases — self-contained,
|
||||
no wrapper scripts, works system-wide. Do **not** use `corepack enable pnpm`
|
||||
(the shim requires its nvm directory structure and breaks when copied/linked):
|
||||
|
||||
```bash
|
||||
curl -fsSL "https://github.com/pnpm/pnpm/releases/latest/download/pnpm-linux-x64" \
|
||||
-o /usr/local/bin/pnpm
|
||||
chmod 755 /usr/local/bin/pnpm
|
||||
```
|
||||
|
||||
### Application user
|
||||
|
||||
```bash
|
||||
|
|
@ -194,11 +190,10 @@ systemctl status innercontext
|
|||
|
||||
---
|
||||
|
||||
## 7. Frontend build and setup
|
||||
## 7. Frontend setup
|
||||
|
||||
```bash
|
||||
cd /opt/innercontext/frontend
|
||||
```
|
||||
The frontend is **built locally and uploaded** via `deploy.sh` — never built on the server.
|
||||
This section only covers the one-time server-side configuration.
|
||||
|
||||
### Create `.env.production`
|
||||
|
||||
|
|
@ -211,25 +206,24 @@ chmod 600 /opt/innercontext/frontend/.env.production
|
|||
chown innercontext:innercontext /opt/innercontext/frontend/.env.production
|
||||
```
|
||||
|
||||
### Install dependencies and build
|
||||
### Grant `innercontext` passwordless sudo for service restarts
|
||||
|
||||
```bash
|
||||
sudo -u innercontext bash -c '
|
||||
cd /opt/innercontext/frontend
|
||||
pnpm install
|
||||
PUBLIC_API_BASE=http://innercontext.lan/api pnpm build
|
||||
'
|
||||
cat > /etc/sudoers.d/innercontext-deploy << 'EOF'
|
||||
innercontext ALL=(root) NOPASSWD: \
|
||||
/usr/bin/systemctl restart innercontext, \
|
||||
/usr/bin/systemctl restart innercontext-node
|
||||
EOF
|
||||
chmod 440 /etc/sudoers.d/innercontext-deploy
|
||||
```
|
||||
|
||||
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
|
||||
systemctl enable innercontext-node
|
||||
# Do NOT start yet — build/ is empty until the first deploy.sh run
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -276,7 +270,40 @@ Reload your reverse proxy after applying the change.
|
|||
|
||||
---
|
||||
|
||||
## 10. Verification
|
||||
## 10. First deploy from local machine
|
||||
|
||||
All subsequent deploys (including the first one) use `deploy.sh` from your local machine.
|
||||
|
||||
### SSH config
|
||||
|
||||
Add to `~/.ssh/config` on your local machine:
|
||||
|
||||
```
|
||||
Host innercontext
|
||||
HostName <innercontext-lxc-ip>
|
||||
User innercontext
|
||||
```
|
||||
|
||||
Make sure your SSH public key is in `/home/innercontext/.ssh/authorized_keys` on the server.
|
||||
|
||||
### Run the first deploy
|
||||
|
||||
```bash
|
||||
# From the repo root on your local machine:
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Build the frontend locally (`pnpm run build`)
|
||||
2. Upload `frontend/build/` to the server via rsync
|
||||
3. Restart `innercontext-node`
|
||||
4. Upload `backend/` source to the server
|
||||
5. Run `uv sync --frozen` on the server
|
||||
6. Restart `innercontext` (runs alembic migrations on start)
|
||||
|
||||
---
|
||||
|
||||
## 11. Verification
|
||||
|
||||
```bash
|
||||
# From any machine on the LAN:
|
||||
|
|
@ -290,30 +317,18 @@ The web UI should be accessible at `http://innercontext.lan`.
|
|||
|
||||
---
|
||||
|
||||
## 11. Updating the application
|
||||
## 12. Updating the application
|
||||
|
||||
```bash
|
||||
cd /opt/innercontext
|
||||
git pull
|
||||
|
||||
# Sync backend dependencies if pyproject.toml changed:
|
||||
cd backend && sudo -u innercontext uv sync && cd ..
|
||||
|
||||
# Apply any new DB migrations (runs automatically via ExecStartPre, but safe to run manually first):
|
||||
sudo -u innercontext bash -c 'cd /opt/innercontext/backend && uv run alembic upgrade head'
|
||||
|
||||
# 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
|
||||
# From the repo root on your local machine:
|
||||
./deploy.sh # full deploy (frontend + backend)
|
||||
./deploy.sh frontend # frontend only
|
||||
./deploy.sh backend # backend only
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. Troubleshooting
|
||||
## 13. Troubleshooting
|
||||
|
||||
### 502 Bad Gateway on `/api/*`
|
||||
|
||||
|
|
@ -328,7 +343,7 @@ journalctl -u innercontext -n 50
|
|||
```bash
|
||||
systemctl status innercontext-node
|
||||
journalctl -u innercontext-node -n 50
|
||||
# Verify /opt/innercontext/frontend/build/index.js exists (pnpm build ran successfully)
|
||||
# Verify /opt/innercontext/frontend/build/index.js exists (deploy.sh ran successfully)
|
||||
```
|
||||
|
||||
### MCP endpoint not responding
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue