Chapter 5 — VPS & Dedicated Servers

A VPS (Virtual Private Server) is the workhorse of professional web hosting. You get a virtual machine with root access, a public IP, and full control — without managing physical hardware.

Provider Comparison

ProviderCheapest VPSData CentersStrengthsBest For
DigitalOcean$4/mo (512MB)14 regionsSimple UI, great docs, managed DBsStartups, learning
Hetzner€3.79/mo (2GB)EU + USBest price/performance ratioPrice-conscious, EU hosting
Linode (Akamai)$5/mo (1GB)11 regionsReliable, good supportGeneral purpose
Vultr$2.50/mo (512MB)32 locationsMost locations, bare metal optionEdge deployments
OVH€3.50/mo (2GB)EU focusedCheap dedicated servers tooEU, budget dedicated

Initial Server Setup (The First 10 Minutes)

Every new VPS should go through this hardening process before deploying anything:

# 1. Connect as root (first time only)
ssh root@YOUR_SERVER_IP

# 2. Update the system
apt update && apt upgrade -y

# 3. Create a non-root user
adduser deploy
usermod -aG sudo deploy

# 4. Set up SSH key authentication for the new user
mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys

# 5. Harden SSH - edit /etc/ssh/sshd_config
sudo sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config
sudo systemctl restart sshd

# 6. Set up firewall
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp    # SSH (custom port)
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS
sudo ufw enable

# 7. Install fail2ban (brute-force protection)
sudo apt install -y fail2ban
sudo systemctl enable fail2ban

# 8. Set up automatic security updates
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
Test SSH access with the new user BEFORE closing your root session. Open a new terminal, SSH as the deploy user on the new port. If it works, you're safe to close root. If not, you still have root access to fix it.

Deploying an Application

# On your server (as deploy user):

# Install your runtime (example: Node.js via nvm)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm install --lts

# Clone your application
cd /opt
sudo mkdir myapp && sudo chown deploy:deploy myapp
git clone git@github.com:you/myapp.git /opt/myapp
cd /opt/myapp
npm install --production

# Set up environment variables
sudo cp .env.example /etc/myapp.env
sudo chmod 600 /etc/myapp.env
# Edit with your production values

# Create systemd service (as shown in Chapter 4)
# Set up Nginx reverse proxy (as shown in Chapter 4)
# Obtain SSL certificate with Certbot

Deployment Strategies for VPS

Option A: Git Pull (Simple)

# On server:
cd /opt/myapp
git pull origin main
npm install --production
sudo systemctl restart myapp

Option B: rsync (No Git on Server)

# From your local machine:
rsync -avz --delete \
  --exclude='node_modules' \
  --exclude='.env' \
  ./dist/ deploy@server:/opt/myapp/
ssh deploy@server 'cd /opt/myapp && npm install --production && sudo systemctl restart myapp'

Option C: Docker (Recommended for Production)

# Build locally or in CI, push to registry
docker build -t myregistry/myapp:v1.2.3 .
docker push myregistry/myapp:v1.2.3

# On server:
docker pull myregistry/myapp:v1.2.3
docker stop myapp && docker rm myapp
docker run -d --name myapp -p 3000:3000 --env-file /etc/myapp.env myregistry/myapp:v1.2.3
Docker is the professional standard. It ensures your app runs identically everywhere — your laptop, CI, staging, production. Chapter 8 covers this in depth.

Process Managers

ToolLanguageFeaturesWhen to Use
systemdAnyBuilt into Linux, restart policies, loggingAlways (it's already there)
PM2Node.jsCluster mode, zero-downtime reload, monitoringNode.js apps without Docker
SupervisorAnySimple config, process groupsLegacy systems, multiple processes