Introduction
This guide explains a safe production strategy for Docusaurus when your VPS has limited resources.
If your VPS often shows high CPU and RAM usage, the root cause is usually running npm run build directly on the server. Docusaurus build uses Node.js tooling (bundling, minification, optimization) that can be heavy for small VPS plans.
The solution is simple: build outside the VPS, deploy only static output, and let the VPS serve files.
Pain points (what usually goes wrong)
When build runs on VPS, common issues are:
- CPU spikes to near 100% during asset bundling.
- Memory pressure from Node.js process during production build.
- Swap usage increases, making server very slow.
- OOM kills or failed deploys on small VPS.
- Unstable uptime because deploy workload competes with live traffic.
In short: your VPS is doing two jobs at once (build machine + web server), and small servers are not designed for that.
Offered solution
Use a static deployment workflow:
- Build on local machine or CI runner (GitHub Actions).
- Copy generated
build/files to VPS. - Serve those files through Nginx/Apache.
With this approach, VPS handles only lightweight static file serving.
Step-by-step implementation
Step 1 - Build outside VPS
Run build on your laptop or CI:
npm ci
npm run build
Expected result:
- A
build/directory is created. - Heavy CPU/RAM usage happens on your machine/CI, not on VPS.
Good practice:
- Use
npm ci(faster and deterministic for deployment). - Keep Node.js version consistent between local and CI.
Step 2 - Prepare VPS static directory
Choose a web root folder, for example:
/var/www/docusaurus
Create it once (on VPS):
sudo mkdir -p /var/www/docusaurus
sudo chown -R $USER:$USER /var/www/docusaurus
Expected result:
- VPS has a dedicated folder for published static files.
Step 3 - Upload built files
From your local machine, sync build/ to VPS:
rsync -avz --delete ./build/ user@your-vps-ip:/var/www/docusaurus/
What flags mean:
-a: preserve file structure and metadata.-v: verbose output.-z: compress during transfer.--delete: remove old files on VPS that are not in latest build.
Expected result:
- VPS content matches exactly your latest successful build.
Step 4 - Configure Nginx to serve static files
Example Nginx server block:
server {
listen 80;
server_name your-domain.com;
root /var/www/docusaurus;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800";
try_files $uri =404;
}
}
Then validate and reload:
sudo nginx -t
sudo systemctl reload nginx
Expected result:
- Website is served as static files.
- Very low memory and CPU usage in steady state.
Step 5 - Verify resource improvement
After switching workflow, check VPS metrics:
top
free -h
You should see:
- No long-running Node build process on VPS.
- Lower CPU spikes.
- More stable memory usage.
Optional: automate with GitHub Actions
You can automate build + deploy so every push to main publishes automatically:
- GitHub Actions runs
npm ci && npm run build. - Action uploads/syncs
build/to VPS via SSH. - Nginx instantly serves the new files.
This gives reproducible deployments and removes manual steps.
Troubleshooting quick notes
- If deploy is slow, use
rsyncwith SSH key auth. - If old files remain, ensure
--deleteis present. - If page refresh returns 404, confirm
try_files ... /index.htmlis configured. - If you still run
npm run buildon VPS via cron/PM2, disable that job.
Final recommendation
For small VPS, treat Docusaurus as a static site:
code change -> build local/CI -> rsync build/ -> Nginx serves
This is the safest way to reduce CPU/RAM usage and keep production stable.