Deploy Node.js App: PM2 and Nginx Guide
Complete guide to deploying Node.js applications on a VPS. Node.js installation with nvm, PM2 process manager, Nginx reverse proxy, SSL certificate, and environment variables management.
What is CDN, Cloudflare free CDN setup, Nginx cache header configuration, gzip/brotli compression, image optimization, and cache-control headers guide.
Your website's speed is critical for user experience and SEO rankings. CDN (Content Delivery Network) and static file optimization can dramatically reduce page load times. This guide covers what CDN is, Cloudflare setup, Nginx cache configuration, and compression techniques.
A CDN (Content Delivery Network) is a network infrastructure that distributes static content (images, CSS, JavaScript, videos) to servers worldwide and serves users from the nearest server.
Benefits of CDN:
Cloudflare offers CDN, DDoS protection, and SSL certificate on its free plan.
Cloudflare automatically scans your existing DNS records. Verify the records:
A @ 203.0.113.50 Proxied (orange cloud)
A www 203.0.113.50 Proxied (orange cloud)
CNAME api api.example.com DNS only (grey cloud)
The "Proxied" (orange cloud) option routes traffic through Cloudflare, providing CDN + DDoS protection. "DNS only" (grey cloud) only performs DNS resolution.
Change the nameservers at your domain registrar to the values provided by Cloudflare:
ns1.cloudflare.com
ns2.cloudflare.com
SSL/TLS: Select Full (strict) mode
Caching:
Speed:
Page Rules (3 rules on free plan):
example.com/static/*
Cache Level: Cache Everything
Edge Cache TTL: 1 month
Setting correct cache headers for static files in Nginx optimizes browser and CDN caching.
server {
listen 80;
server_name example.com;
root /var/www/mysite;
# HTML files - no caching (always fresh)
location ~* \.html$ {
add_header Cache-Control "no-cache, must-revalidate";
add_header Pragma "no-cache";
}
# CSS and JavaScript - long cache for versioned files
location ~* \.(css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Images
location ~* \.(jpg|jpeg|png|gif|ico|webp|avif|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
}
# Font files
location ~* \.(woff|woff2|ttf|eot|otf)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Access-Control-Allow-Origin "*";
}
# API endpoints - no caching
location /api/ {
add_header Cache-Control "no-store, no-cache";
proxy_pass http://localhost:3000;
}
}
Gzip compresses text-based files (HTML, CSS, JS), reducing transfer size by 60-80%.
http {
# Gzip settings
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
image/svg+xml
font/truetype
font/opentype;
}
Brotli offers 15-25% better compression than gzip and is supported by modern browsers.
# Install Brotli module
sudo apt install libnginx-mod-brotli -y
http {
# Brotli settings
brotli on;
brotli_comp_level 6;
brotli_static on;
brotli_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml
image/svg+xml;
}
sudo nginx -t
sudo systemctl reload nginx
# Test compression
curl -H "Accept-Encoding: br" -I https://example.com
# Should show: Content-Encoding: br
WebP format offers 25-35% smaller file sizes compared to JPEG and PNG.
# Install cwebp tool
sudo apt install webp -y
# Convert single file
cwebp -q 80 image.jpg -o image.webp
# Batch conversion
for f in /var/www/mysite/images/*.jpg; do
cwebp -q 80 "$f" -o "${f%.jpg}.webp"
done
# Serve WebP to browsers that support it
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
server {
location ~* \.(jpg|jpeg|png)$ {
add_header Vary Accept;
try_files $uri$webp_suffix $uri =404;
}
}
| Content Type | Cache-Control | Description |
|---|---|---|
| HTML | no-cache | Always fresh |
| CSS/JS (hashed) | public, immutable, max-age=31536000 | 1 year |
| Images | public, max-age=31536000 | 1 year |
| API responses | no-store | Never cache |
| User data | private, no-cache | Browser only |
# Enable ETag (for change detection)
etag on;
# Last-Modified header
add_header Last-Modified $date_gmt;
Use Chrome DevTools > Network tab to test cache headers. Check Cache-Control, ETag, and Age values in Response Headers.
CDN integration and static file optimization significantly improve your website's performance. Using Cloudflare free CDN for global distribution, Nginx cache headers for browser caching, gzip/brotli for compression, and WebP for image optimization together can dramatically reduce page load times.
Select 'Full (strict)' mode in Cloudflare SSL/TLS settings. Make sure your server has a valid SSL certificate (Let's Encrypt). 'Flexible' mode is insecure; the connection between the server and Cloudflare is not encrypted. You can also use a Cloudflare Origin Certificate.
In Cloudflare Dashboard > Caching > Purge Cache, you can clear all cache or specific URLs. For Nginx FastCGI cache, use 'sudo rm -rf /var/cache/nginx/fastcgi/*'. To clear browser cache, do Ctrl+Shift+R (hard refresh).
Check with 'curl -H "Accept-Encoding: gzip" -I https://example.com'. The response should show 'Content-Encoding: gzip'. Alternatively, check the Content-Encoding value in Chrome DevTools > Network > Response Headers. GTmetrix or PageSpeed Insights tools also show compression status.
Cloudflare sends the real IP in the CF-Connecting-IP header. In Nginx, define Cloudflare IP ranges with the 'set_real_ip_from' directive and add 'real_ip_header CF-Connecting-IP;'. This lets you see the real user IP in log files and your application.
Complete guide to deploying Node.js applications on a VPS. Node.js installation with nvm, PM2 process manager, Nginx reverse proxy, SSL certificate, and environment variables management.
Complete guide to deploying PHP applications on a VPS. LAMP vs LEMP comparison, Apache/Nginx + PHP-FPM + MySQL setup, virtual host configuration, and PHP version management.
Guide to installing and optimizing WordPress on a VPS. LEMP stack setup, wp-config.php settings, file permissions, SSL, OPcache performance optimization, and security hardening.