5.9 KiB
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:
/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.gitis 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.jsfor the APIcontent/for writable datadocs/for wiki assetsdist/for the built front-end
Because of that, the cleanest production model is:
- Run
server.json the VPS from a stable app directory. - Let
server.jsservedist/and/wiki. - 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
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
cd /srv/content-editor-v2/repo.git
git init --bare
3. Create the live checkout
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:
export CONTENT_ROOT=/srv/content-editor-v2/shared/content
If you already have good content locally, copy it once:
cp -R /srv/content-editor-v2/app/content/. /srv/content-editor-v2/shared/content/
5. Install Node dependencies in the live app dir
cd /srv/content-editor-v2/app
npm install
6. Add a process manager
PM2 is the easiest option:
npm install -g pm2
Then start the app:
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:
/srv/content-editor-v2/repo.git/hooks/post-receive
Use this:
#!/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:
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:
git init
git add .
git commit -m "Initial project import"
Add the VPS as a remote:
git remote add vps ssh://YOUR_USER@YOUR_HOST:/srv/content-editor-v2/repo.git
Then deploy with:
git push vps master
Or main, if that is your branch name.
Windows-Friendly Deploy Helper
This repo includes a PowerShell helper:
.\scripts\deploy-vps.ps1 -Remote vps -Branch master
What it does:
- Runs
npm run validate:content - Runs
npm run build - 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:
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:
- Work locally in a normal git repo.
- Commit changes.
- Run
.\scripts\deploy-vps.ps1. - 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
- Initialize this folder as a git repo.
- Set up the bare repo + app + shared content structure on the VPS.
- Put the
post-receivehook in place. - Start the app under PM2.
- Switch deployment to
git push vps <branch>.
Once you want, we can also add:
- a production
.envloader - branch-based staging vs production deploys
- backup/restore scripts for
content/ - a one-command VPS bootstrap script