Well, let’s comes to a point which usually scares developers the most is deployment.
But the intresting fact is, it way more simpler than you think.
Here’s my personal VPS deployment checklist - from fresh server to HTTPS-secured subdomains.
1. Prepare Your VPS:
First things first, let’s update your packages and install the essentials:
sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl build-essential
2. Install Node.js & npm
I like to use Node 18.x for most apps:
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
node -v && npm -v
3. Set Up your GitHub Access (for private repos)
Generate an SSH key and add it to your GitHub account:
(In case of public repository, you can skip this step)
ssh-keygen -t ed25519 -C "you@example.com"
cat ~/.ssh/id_ed25519.pub
4. Install PM2 (Optional but Highly Recommended)
Forget nohup - PM2 keeps your apps alive and restarts them if they crash:
sudo npm install -g pm2
pm2 start npm - name client - run start
pm2 start npm - name server - start
pm2 start npx - name admin - serve -s build -l 4000
PM2 gives you:
- Auto-restart
- Logging
- Startup on boot (pm2 startup)
5. Do You Need Nginx? (Yes, You Probably Do)
Why Nginx is awesome for deployments:
- Serve your frontend from a nice domain (
https://myapp.com) - Reverse proxy your backend (hide ugly ports like
:3000) - Easy SSL setup with Let’s Encrypt
sudo apt install nginx -y
sudo ufw allow ‘Nginx Full’
6. Automate with deploy.sh
I keep all my deployment steps in a bash script so I can update everything with a single command.
#!/bin/bash
REPO_URL="git@github.com:yourname/abc.git"
REPO_DIR="/var/www/abc"
echo " Deploying..."
if [ ! -d "$REPO_DIR" ]; then
git clone "$REPO_URL" "$REPO_DIR"
else
cd "$REPO_DIR" && git pull origin main
fi
# Client
cd "$REPO_DIR/client"
npm install && npm run build
pm2 delete client || true
pm2 start "npm" --name "client" -- start
# Server
cd "$REPO_DIR/server"
npm install
pm2 delete server || true
pm2 start "npm" --name "server" -- start
pm2 save
echo "✅ Deployment Completed!"
Make it executable:
chmod +x deploy.sh
7. Point Your Domain to VPS (DNS Setup)
In your domain provider, add A records pointing to your VPS IP:
Type → Host → Value
A → @ → VPS_IP
A → api → VPS_IP
A → admin → VPS_IP
A → business → VPS_IP
8. Configure Nginx
Example config for your main site (abc.com):
server {
listen 80;
server_name abc.com www.abc.com;
location / {
proxy_pass http://localhost:2000;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
}
}
Repeat for each subdomain with the correct port.
9. Enable Sites & Restart Nginx
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
10. Add HTTPS with Let’s Encrypt
Install Certbot:
sudo apt install certbot python3-certbot-nginx -y
Get SSL for each domain:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
sudo certbot --nginx -d api.yourdomain.com
Test auto-renewal:
sudo certbot renew --dry-run
That’s it!
Now your apps are:
- Running on PM2
- Reverse proxied via Nginx
- Secured with SSL
- Deployable with one script
No more “which command was it again? ” moments.
Just ./deploy.sh and done.
Next time, I’ll share how to fully automate this with GitHub Actions so deployments happen every time you push to main.
The post How you can deploy your first web app to a VPS (With PM2, Nginx & SSL) appeared first on Muhammad Tabarak.
