DOCS-1: Init document work

This commit is contained in:
Blake Ridgway
2026-07-28 07:20:32 -05:00
parent 8f02a3fc8e
commit 0cbcc962f7
66 changed files with 12224 additions and 71 deletions

230
content/vps/nodejs-pm2.md Normal file
View File

@@ -0,0 +1,230 @@
---
title: "Deploy a Node.js App with PM2 and Nginx"
description: "Run a Node.js application behind Nginx reverse proxy with PM2 process management."
section: vps
order: 4
---
# Deploy a Node.js App with PM2 and Nginx
This guide covers running a Node.js application on your Arcline VPS with PM2 for process management and Nginx as a reverse proxy.
---
## Prerequisites
- A VPS with Nginx installed
- A Node.js application (Express, Koa, Fastify, or similar)
- SSH access to your VPS
---
## Step 1 — Install Node.js
Install Node.js from the official NodeSource repository (recommended over the system package manager):
```bash
# Node.js 22.x (LTS)
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install nodejs -y
```
Verify:
```bash
node --version
npm --version
```
---
## Step 2 — Install PM2
PM2 is a process manager that keeps your Node.js app running, handles logging, and provides monitoring.
```bash
sudo npm install -g pm2
```
---
## Step 3 — Upload your application
Create a directory for your app:
```bash
sudo mkdir -p /var/www/example.com
sudo chown -R $USER:$USER /var/www/example.com
```
Upload your application files via SFTP, rsync, or git:
```bash
cd /var/www/example.com
git clone https://git.arcline.it/yourname/your-app.git .
npm install --production
```
---
## Step 4 — Start the app with PM2
```bash
pm2 start app.js --name example-app
```
Or if your app uses `npm start`:
```bash
pm2 start npm --name example-app -- start
```
Save the PM2 process list so it restarts on reboot:
```bash
pm2 save
pm2 startup
```
The `pm2 startup` command will output a command for you to run with sudo. Follow its instructions.
---
## Step 5 — Configure Nginx as a reverse proxy
Your Node.js app runs on a port like `3000` or `8080`. Nginx will sit in front of it, handling SSL and serving static assets directly.
Create an Nginx config:
```bash
sudo nano /etc/nginx/sites-available/example.com
```
```nginx
server {
listen 80;
server_name example.com www.example.com;
# If your app serves static files from a public directory
location /static/ {
alias /var/www/example.com/public/;
expires 1y;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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;
proxy_cache_bypass $http_upgrade;
}
}
```
Enable the site:
```bash
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
Set up SSL:
```bash
sudo certbot --nginx -d example.com -d www.example.com
```
---
## Step 6 — Environment variables
Create an environment file:
```bash
nano /var/www/example.com/.env
```
```
PORT=3000
NODE_ENV=production
DATABASE_URL=postgres://...
```
Update your PM2 process to load it:
```bash
pm2 delete example-app
pm2 start app.js --name example-app --env-file /var/www/example.com/.env
pm2 save
```
Or use a PM2 ecosystem file (`ecosystem.config.js`):
```javascript
module.exports = {
apps: [{
name: 'example-app',
script: 'app.js',
env_file: '/var/www/example.com/.env',
instances: 2,
exec_mode: 'cluster',
max_memory_restart: '500M',
}]
};
```
Then:
```bash
pm2 start ecosystem.config.js
```
---
## PM2 useful commands
| Command | Description |
|---------|-------------|
| `pm2 list` | List all processes |
| `pm2 logs` | Show live logs |
| `pm2 logs --lines 100` | Show last 100 lines |
| `pm2 monit` | Real-time CPU/memory monitor |
| `pm2 restart example-app` | Restart an app |
| `pm2 reload example-app` | Zero-downtime reload |
| `pm2 stop example-app` | Stop an app |
| `pm2 delete example-app` | Remove from PM2 |
| `pm2 save` | Save process list |
| `pm2 startup` | Generate startup script |
---
## WebSocket support
If your app uses WebSockets, ensure the upgrade headers are passed through. The config above already includes them. For socket.io, add these to your Nginx config:
```nginx
location /socket.io/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
}
```
---
## What's next
- [Deploy a Go binary](/vps/go-systemd/) as a systemd service
- [Set up automated backups](/vps/automated-backups/) with restic
- [Install fail2ban](/vps/fail2ban/) for SSH protection