# VPS Deployment This project is much easier to manage if we stop treating your desktop folder as the "deployment artifact" and instead treat the app like a normal repository with a normal deploy target. ## Recommended Setup Use three directories on the VPS: ```txt /srv/content-editor-v2/ repo.git/ # bare git repo, receives pushes app/ # checked out working tree, built + run from here shared/ content/ # persistent content, survives redeploys ``` Why this shape works: - `repo.git` is the deployment remote. - `app/` is the live checkout your process manager runs. - `shared/content/` keeps your authored data outside the release tree. That means redeploying code does not overwrite your content. ## Best Fit For This Project This app is not just a static front-end build. It also has: - `server.js` for the API - `content/` for writable data - `docs/` for wiki assets - `dist/` for the built front-end Because of that, the cleanest production model is: 1. Run `server.js` on the VPS from a stable app directory. 2. Let `server.js` serve `dist/` and `/wiki`. 3. Put Nginx or your hosting panel in front of it as a reverse proxy. That is better than manually uploading a folder to a public web root. ## One-Time VPS Setup Run these on the VPS. ### 1. Create directories ```bash sudo mkdir -p /srv/content-editor-v2/repo.git sudo mkdir -p /srv/content-editor-v2/app sudo mkdir -p /srv/content-editor-v2/shared/content ``` ### 2. Initialize the bare repo ```bash cd /srv/content-editor-v2/repo.git git init --bare ``` ### 3. Create the live checkout ```bash git --work-tree=/srv/content-editor-v2/app --git-dir=/srv/content-editor-v2/repo.git checkout -f ``` If this is the first time and there is no pushed branch yet, that checkout will not fully populate until the first push. ### 4. Keep content outside the app tree This project already supports `CONTENT_ROOT`. Production should use: ```bash export CONTENT_ROOT=/srv/content-editor-v2/shared/content ``` If you already have good content locally, copy it once: ```bash cp -R /srv/content-editor-v2/app/content/. /srv/content-editor-v2/shared/content/ ``` ### 5. Install Node dependencies in the live app dir ```bash cd /srv/content-editor-v2/app npm install ``` ### 6. Add a process manager PM2 is the easiest option: ```bash npm install -g pm2 ``` Then start the app: ```bash cd /srv/content-editor-v2/app CONTENT_ROOT=/srv/content-editor-v2/shared/content PORT=5180 pm2 start server.js --name content-editor-v2 pm2 save ``` ## Automatic Deploy On Push The cleanest version is a `post-receive` hook in the bare repo. Create: ```txt /srv/content-editor-v2/repo.git/hooks/post-receive ``` Use this: ```bash #!/usr/bin/env bash set -euo pipefail APP_DIR="/srv/content-editor-v2/app" GIT_DIR="/srv/content-editor-v2/repo.git" CONTENT_ROOT="/srv/content-editor-v2/shared/content" PORT="5180" echo "[deploy] checking out latest code" git --work-tree="$APP_DIR" --git-dir="$GIT_DIR" checkout -f cd "$APP_DIR" echo "[deploy] installing dependencies" npm install echo "[deploy] validating content" npm run validate:content echo "[deploy] building" npm run build echo "[deploy] reloading app" CONTENT_ROOT="$CONTENT_ROOT" PORT="$PORT" pm2 restart content-editor-v2 || \ CONTENT_ROOT="$CONTENT_ROOT" PORT="$PORT" pm2 start server.js --name content-editor-v2 ``` Make it executable: ```bash chmod +x /srv/content-editor-v2/repo.git/hooks/post-receive ``` ## Local Machine Setup On your home computer, initialize git in this project if you have not already: ```powershell git init git add . git commit -m "Initial project import" ``` Add the VPS as a remote: ```powershell git remote add vps ssh://YOUR_USER@YOUR_HOST:/srv/content-editor-v2/repo.git ``` Then deploy with: ```powershell git push vps master ``` Or `main`, if that is your branch name. ## Windows-Friendly Deploy Helper This repo includes a PowerShell helper: ```powershell .\scripts\deploy-vps.ps1 -Remote vps -Branch master ``` What it does: 1. Runs `npm run validate:content` 2. Runs `npm run build` 3. Pushes your branch to the chosen remote That means your local build fails before a bad deploy reaches the server. ## Reverse Proxy If your VPS uses Nginx, proxy your public domain to the Node app: ```nginx server { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:5180; proxy_http_version 1.1; 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; } } ``` ## If You Really Need A Separate Hosted Directory If your panel requires a specific public directory, there are two workable options: ### Option A: still run Node, proxy to it Best option. Keep the app in `/srv/content-editor-v2/app` and point the panel or reverse proxy at the Node port. ### Option B: copy only `dist/` into a public web root This works only if you separate the API and front-end hosting model. For this project today, that is not the clean default because `server.js` also serves static files and wiki docs. ## Recommended Workflow Day to day: 1. Work locally in a normal git repo. 2. Commit changes. 3. Run `.\scripts\deploy-vps.ps1`. 4. Let the VPS hook pull, build, validate, and restart. That replaces: - random desktop folder - manual upload - dragging files through a VPS file manager - wondering what version is actually live ## What I Recommend You Do Next 1. Initialize this folder as a git repo. 2. Set up the bare repo + app + shared content structure on the VPS. 3. Put the `post-receive` hook in place. 4. Start the app under PM2. 5. Switch deployment to `git push vps `. Once you want, we can also add: - a production `.env` loader - branch-based staging vs production deploys - backup/restore scripts for `content/` - a one-command VPS bootstrap script