Powerful Code Snippets

Production-ready Ubuntu, Bash, and PowerShell 7 commands for sysadmins and developers

Nginx VPS Configuration & Optimization Commands

December 17, 2025 Updated May 29, 2026
ubuntu nginx web-server vps ssl optimization

Nginx Management Essentials

Essential commands for managing Nginx on Ubuntu VPS. These snippets cover installation, SSL setup, performance tuning, and troubleshooting.

1. Complete Nginx Installation & Setup

Install Nginx and enable it to start on boot:

# Install Nginx
sudo apt update && sudo apt install nginx -y

# Enable and start Nginx
sudo systemctl enable nginx
sudo systemctl start nginx

# Check status
sudo systemctl status nginx

# Test Nginx configuration
sudo nginx -t

2. SSL Certificate with Let's Encrypt

Set up free SSL certificates using Certbot:

# Install Certbot
sudo apt install certbot python3-certbot-nginx -y

# Obtain and install SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# Auto-renewal test
sudo certbot renew --dry-run

# List all certificates
sudo certbot certificates

3. View Real-Time Access Logs

Monitor incoming requests in real-time:

# Tail access log with color coding
sudo tail -f /var/log/nginx/access.log

# Show only 403/404/500 errors
sudo tail -f /var/log/nginx/access.log | grep -E "403|404|500"

# Monitor specific domain
sudo tail -f /var/log/nginx/access.log | grep "yourdomain.com"

# Count requests per IP in last 1000 lines
sudo tail -1000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

Best Practices

  • Always test configuration with nginx -t before reloading
  • Keep SSL certificates updated - check certbot renew regularly
  • Monitor error logs daily for security issues
  • Use nginx -s reload instead of restart for zero-downtime config updates
  • Implement rate limiting on all public endpoints
  • Set up log rotation to prevent disk space issues

Enabling Gzip Compression in Nginx

Gzip compression dramatically reduces the size of text-based responses sent over the wire, improving load times and reducing bandwidth costs. Add the following block inside your http context in /etc/nginx/nginx.conf:

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json
           application/javascript application/xml+rss
           application/atom+xml image/svg+xml;

Run nginx -t && systemctl reload nginx after every config change. Verify compression is active with curl -H "Accept-Encoding: gzip" -I https://yourdomain.com and look for Content-Encoding: gzip in the response headers.

Browser Caching with Cache-Control Headers

Static assets — images, CSS, JavaScript — rarely change between requests. Telling browsers to cache them locally saves round-trips and speeds up repeat visits significantly.

location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

Use a content-hash in filenames (e.g. app.a3f9c1.js) so browsers pick up new versions automatically when you deploy.

Rate Limiting to Prevent Abuse

Rate limiting protects your server from brute-force attacks, scrapers, and runaway clients. Define a shared memory zone and apply it to sensitive endpoints:

http {
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
}

server {
    location /login {
        limit_req zone=login burst=3 nodelay;
    }
}

The burst parameter allows a small spike above the rate before nginx starts returning 429 Too Many Requests. Monitor hits with grep "limiting requests" /var/log/nginx/error.log.

Hardening Security Headers

Security headers are free to add and meaningfully reduce your attack surface. Place these inside your server block or a shared snippet:

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Validate your headers at securityheaders.com — aim for an A or A+ rating.

Tuning Worker Processes and Connections

Nginx performance at the OS level is controlled by a few key directives in /etc/nginx/nginx.conf:

worker_processes auto;          # match CPU core count
worker_rlimit_nofile 65535;

events {
    worker_connections 1024;
    use epoll;
    multi_accept on;
}

http {
    keepalive_timeout 65;
    keepalive_requests 1000;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
}

worker_processes auto automatically sets one worker per CPU core. sendfile enables zero-copy file transfers. tcp_nopush batches response headers with the first data packet, reducing small-packet overhead.

Testing Your Configuration

Always validate before reloading: nginx -t catches syntax errors without touching the live config. Use ab (Apache Bench) or wrk for load testing:

wrk -t4 -c100 -d30s https://yourdomain.com/

Check /var/log/nginx/access.log and error.log regularly. Tools like GoAccess parse nginx logs in real time and produce useful dashboards without sending data to third parties.

Essential Ubuntu System Monitoring & Cleanup Commands

December 17, 2025 Updated May 29, 2026
ubuntu bash system-admin monitoring cleanup performance

Comprehensive System Monitoring

Check system resources, disk usage, and running processes with these essential Ubuntu commands. Perfect for diagnosing performance issues on your VPS or local machine.

1. Real-Time System Resource Monitor

Monitor CPU, memory, and processes in real-time with htop (more user-friendly than top):

sudo apt install htop -y && htop

2. Disk Usage Analysis

Find the largest directories consuming disk space:

# Show top 10 largest directories in /
sudo du -h / 2>/dev/null | sort -rh | head -n 10

# Or use ncdu for interactive browsing
sudo apt install ncdu -y
sudo ncdu /

3. Memory Usage Breakdown

View detailed memory usage including cache and buffers:

# Detailed memory info
free -h

# Show top memory-consuming processes
ps aux --sort=-%mem | head -n 10

System Cleanup Commands

4. Complete Package Cleanup

Remove unnecessary packages, clean apt cache, and reclaim disk space:

# Full cleanup chain
sudo apt autoremove -y && \
sudo apt autoclean -y && \
sudo apt clean -y && \
sudo journalctl --vacuum-time=3d && \
sudo rm -rf /tmp/* 2>/dev/null

echo "Cleanup complete!"

5. Find and Remove Old Kernels

Safely remove old kernel versions (keep current + 1 previous):

# List installed kernels
dpkg --list | grep linux-image

# Remove old kernels (interactive)
sudo apt autoremove --purge

6. Clear System Logs

Reduce systemd journal size and clear old logs:

# Limit journal to 100MB
sudo journalctl --vacuum-size=100M

# Keep only last 2 days of logs
sudo journalctl --vacuum-time=2d

# Check current journal size
journalctl --disk-usage

Performance Monitoring

7. Check Network Connections

View active network connections and listening ports:

# Show all listening ports
sudo netstat -tulpn | grep LISTEN

# Or use ss (faster, modern alternative)
sudo ss -tulpn | grep LISTEN

# Monitor real-time network usage
sudo apt install nethogs -y && sudo nethogs

8. Service Status Check

Check status of critical services:

# Check multiple services at once
for service in nginx postgresql ssh ufw; do
    systemctl is-active $service && \
    echo "✓ $service is running" || \
    echo "✗ $service is NOT running"
done

Pro Tips

  • Run cleanup commands monthly or when disk space is low
  • Always use sudo for system-level operations
  • Create aliases in ~/.bashrc for frequently used commands
  • Monitor systemd journal size - it can grow to several GB on busy servers

Analyzing Systemd Service Startup Times

systemd-analyze reveals exactly how long boot took and which services are responsible for the slowdown:

# Total boot time breakdown
systemd-analyze

# Per-service time sorted by slowest
systemd-analyze blame | head -20

# Visual SVG timeline (opens in browser)
systemd-analyze plot > /tmp/boot.svg

Services taking more than 3–5 seconds are candidates for disabling (if you don't need them) or masking. Disable with systemctl disable --now servicename. Common culprits on VPS servers: ModemManager, avahi-daemon, and multipathd.

Swap Management and Tuning

On systems with adequate RAM, swap should rarely be used. A high vm.swappiness value causes the kernel to swap aggressively, degrading performance:

# Check current swap usage
free -h && swapon --show

# Check swappiness (default is 60, server-optimal is 10)
cat /proc/sys/vm/swappiness

# Set it permanently
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

If your server has 2 GB+ RAM and swap is consistently in use, the real fix is identifying the memory-hungry process with ps aux --sort=-%mem | head -10, not expanding swap.

Log Rotation and Journal Size Control

Systemd journals can grow unchecked on busy servers. Cap them to prevent disk fill:

# Check current journal size
journalctl --disk-usage

# Vacuum entries older than 30 days OR down to 500 MB
sudo journalctl --vacuum-time=30d
sudo journalctl --vacuum-size=500M

# Make the cap permanent
sudo nano /etc/systemd/journald.conf
# Set: SystemMaxUse=500M and MaxRetentionSec=1month
sudo systemctl restart systemd-journald

For traditional syslog (/var/log/), logrotate handles rotation. Check /etc/logrotate.d/ for per-service configs and logrotate -d /etc/logrotate.conf to do a dry run.

Fail2Ban: Automatic Brute-Force Protection

Fail2ban monitors logs and temporarily bans IPs that show malicious behavior — essential for any server with SSH exposed to the internet:

# Install and enable
sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban

# Check banned IPs
sudo fail2ban-client status sshd

# Unban a specific IP (if you lock yourself out)
sudo fail2ban-client set sshd unbanip 1.2.3.4

Create /etc/fail2ban/jail.local to override defaults without touching jail.conf (which gets overwritten on updates). Recommended SSH settings: maxretry = 3, bantime = 1h, findtime = 10m.

Docker and Container Cleanup

If you run Docker, images, containers, and volumes accumulate silently. A full prune recovers significant disk space:

# What's taking space?
docker system df

# Remove stopped containers, dangling images, unused networks
docker system prune -f

# Also remove unused volumes (careful — this deletes data)
docker system prune --volumes -f

# Remove all unused images (not just dangling)
docker image prune -a -f

Schedule a weekly prune with cron: 0 3 * * 0 /usr/bin/docker system prune -f >> /var/log/docker-prune.log 2>&1