| name | vps-linux |
| description | VPS Linux — Docker, reverse proxy, SSL, security hardening. |
VPS Linux Setup — Docker-Based
1. Initial Server Access & Hardening
ssh root@<SERVER_IP>
adduser deploy
usermod -aG sudo deploy
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
nano /etc/ssh/sshd_config
systemctl restart sshd
ufw allow OpenSSH
ufw allow 80
ufw allow 443
ufw enable
2. System Update & Essential Packages
apt update && apt upgrade -y
apt install -y \
curl \
wget \
git \
htop \
fail2ban \
unattended-upgrades
3. Docker Installation
curl -fsSL https://get.docker.com | sh
usermod -aG docker deploy
apt install -y docker-compose-plugin
docker --version
docker compose version
4. Reverse Proxy — Nginx + SSL (Certbot)
Install Nginx
apt install -y nginx certbot python3-certbot-nginx
Nginx Site Config
# /etc/nginx/sites-available/myapp
server {
listen 80;
server_name myapp.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name myapp.example.com;
ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 60s;
}
}
ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
certbot --nginx -d myapp.example.com
certbot renew --dry-run
5. Application Directory Structure
mkdir -p /opt/myapp
chown deploy:deploy /opt/myapp
6. Deployment Script
#!/bin/bash
set -e
IMAGE_TAG=${1:-latest}
cd /opt/myapp
echo "Pulling image..."
docker compose pull app
echo "Deploying..."
IMAGE_TAG=$IMAGE_TAG docker compose up -d --remove-orphans
echo "Cleaning up old images..."
docker image prune -f
echo "Deployed successfully."
7. Fail2Ban Configuration
cat > /etc/fail2ban/jail.local << EOF
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[sshd]
enabled = true
[nginx-http-auth]
enabled = true
EOF
systemctl restart fail2ban
8. Maintenance Checklist
Common Issues
| Problem | Fix |
|---|
| 502 Bad Gateway | App container not running — docker compose ps |
| SSL cert expired | certbot renew |
| Port already in use | lsof -i :PORT to find the process |
| Out of disk space | docker system prune -a, check logs |