
This guide explains how to deploy a Node.js (Express) backend with MySQL and PM2 on a VPS, along with setting up a React frontend using Nginx as a reverse proxy.
ssh root@203.0.113.10
Connect securely to your VPS via SSH using your server's IP address.
apt update && apt upgrade -y
apt install nodejs npm -y
npm install pm2 -g
node -v
npm -v
pm2 -v
Update system packages, install Node.js and npm, then install PM2 globally to manage Node processes.
Before you begin editing configuration files on your VPS, it’s helpful to know some basic keyboard shortcuts for nano (the default text editor in most Linux servers).
These commands make it easy to save, cancel, or navigate when editing files like .env or Nginx configs.
# Save changes in Nano
Ctrl + O → Write (save) changes to file
Enter → Confirm file name
Ctrl + X → Exit the editor
# Cancel editing without saving
Ctrl + X → Exit
N → Discard changes
# Other helpful shortcuts
Ctrl + K → Cut the current line
Ctrl + U → Paste (after cutting)
Ctrl + W → Search for text in file
Ctrl + C → Show current cursor position
These shortcuts are essential when editing configuration files such as
/etc/nginx/sites-available/example.com or environment files like .env directly on your server terminal.
cd /root
git clone https://github.com/example/demo-express-app.git
cd demo-express-app
Clone your backend project from GitHub or manually upload your code into the VPS.
npm install
Install all required npm packages defined in package.json.
Create a .env file in your project root to store app and database configuration.
APP_NAME=DemoApp
APP_PORT=5000
APP_URL=http://localhost
DB_ENGINE=mysql
DB_NAME=demo_db
DB_HOST=localhost
DB_USER=demo_user
DB_PASS=supersecret
DB_PORT=3306
JWT_SECRET_KEY=change_this_secret
JWT_ALGORITHM=HS256
BASE_URL=http://localhost:5000
These variables define your app name, ports, and MySQL credentials.
apt install mysql-server -y
systemctl start mysql
systemctl enable mysql
mysql_secure_installation
Install and secure MySQL, then start and enable it to run automatically on reboot.
mysql -u root -p
CREATE DATABASE demo_db;
CREATE USER 'demo_user'@'localhost' IDENTIFIED BY 'supersecret';
GRANT ALL PRIVILEGES ON demo_db.* TO 'demo_user'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;
Create a new database and user with full privileges for your application.
mysql -u demo_user -p
SHOW DATABASES;
Verify your new MySQL user can access the database successfully.
npm run start
# expect logs:
# Connected to mysql database
# Server running on http://localhost:5000
Run the app locally to confirm it connects properly before using PM2.
pm2 start dist/index.js --name demo-backend
pm2 save
pm2 startup
PM2 ensures your backend runs continuously even after terminal closure or system reboot.
pm2 list
pm2 logs demo-backend
pm2 restart demo-backend
pm2 stop demo-backend
pm2 delete demo-backend
Use these PM2 commands to view logs, restart, stop, or remove your app process.
apt install nginx -y
nano /etc/nginx/sites-available/example.com
Install Nginx and create a configuration file to route traffic to your Node.js app.
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
Link the config file, test syntax, and reload Nginx to apply changes.
apt install certbot python3-certbot-nginx -y
certbot --nginx -d example.com -d www.example.com
Install Certbot to automatically configure free SSL certificates via Let's Encrypt.
cd /root/demo-express-app
git pull
npm install
pm2 restart demo-backend
Pull the latest code, update dependencies, and restart your app using PM2.
.env credentials and MySQL grants.systemctl start mysql.pm2 logs demo-backend.ssh root@203.0.113.10
Connect again to your VPS to deploy the frontend application.
apt update && apt upgrade -y
apt install nodejs npm -y
npm install -g serve pm2
Install Node.js, npm, and serve for hosting static files.
cd /root
git clone https://github.com/example/demo-frontend.git
cd demo-frontend
Fetch your React project from GitHub or upload it manually.
npm install
Install frontend dependencies required for the React build.
npm run build
Generate production-ready static files in the dist/ folder.
serve -s dist -l 3000
Preview your app locally on port 3000 before deploying it permanently.
pm2 start "serve -s dist -l 3000" --name demo-frontend
pm2 save
pm2 startup
Use PM2 to keep the frontend running continuously in the background.
pm2 list
pm2 logs demo-frontend
pm2 restart demo-frontend
pm2 stop demo-frontend
Check logs and restart or stop the frontend when needed.
http://203.0.113.10:3000
Open the IP address in your browser to confirm the site is running.
/root
├── demo-express-app/
│ ├── dist/
│ ├── package.json
│ └── ...
└── demo-frontend/
├── dist/
├── package.json
└── ...
pm2 stop demo-frontend
npm run build
pm2 restart demo-frontend
Stop the old process, rebuild the latest code, and restart the frontend.
“Great things are built step by step — keep learning, keep building.”


