Connect VPS to Cloudflare: CDN + DDoS Protection
Using Cloudflare as a reverse proxy in front of your VPS is one of the most cost-effective ways to get enterprise-grade CDN, DDoS Protection, Web Application Firewall (WAF), and free SSL Certificates — without paying a dime. This article will walk you through setup from start to finish, step by step.
How Cloudflare Works with Your VPS
When you enable Cloudflare proxy (orange cloud icon), your domain's DNS points to Cloudflare's IP addresses instead of your VPS's real IP. All traffic flows through Cloudflare first, then gets forwarded to your VPS. The benefits are:
- Your VPS's real IP is hidden — attackers cannot find the target
- Cloudflare absorbs DDoS attacks at Tbps scale before they reach your VPS
- Static assets (images, CSS, JS) are cached at edge locations, reducing bandwidth on your VPS
- SSL/TLS is managed at Cloudflare — you don't need to install Let's Encrypt on the VPS
Step 1 — Sign Up and Add Your Domain to Cloudflare
- Go to dash.cloudflare.com and sign up for a free account
- Click "Add a Site" and enter your domain name (e.g.,
example.com) - Select the Free plan and click Continue
- Cloudflare automatically scans your existing DNS records. Verify that the A record points to your VPS's IP address
- Copy the two Nameservers that Cloudflare assigns (e.g.,
ada.ns.cloudflare.comandbob.ns.cloudflare.com) - Log into your domain Registrar and update the Nameservers to Cloudflare's
Step 2 — Configure DNS Records and Enable Proxy
After your Nameservers are transferred, go to the DNS tab in your Dashboard and review your records:
- A record named
@→ your VPS IP → enable Proxy (orange cloud) - A record named
www→ your VPS IP → enable Proxy (orange cloud) - Other records that should not be proxied (e.g., mail servers) → leave as DNS Only (gray cloud)
Step 3 — Configure SSL/TLS Mode
Go to SSL/TLS → Overview and choose a mode that fits your setup:
Flexible SSL
Cloudflare connects to your browser via HTTPS but connects to your VPS via plain HTTP. Use this if your VPS doesn't have an SSL certificate yet. Good for initial testing.
Full SSL (Recommended)
Cloudflare connects to your VPS via HTTPS, but does not validate whether your certificate is valid. Your VPS must have an SSL certificate (self-signed is OK).
Full (Strict) — Most Secure
Like Full SSL, but Cloudflare verifies that your certificate is valid (Let's Encrypt or Cloudflare Origin Certificate). Strictest security option.
Step 4 — Install Cloudflare Origin Certificate on Your VPS
An Origin Certificate is issued by Cloudflare specifically for your VPS, valid for up to 15 years, and works only when traffic flows through Cloudflare.
- In your Cloudflare Dashboard, go to SSL/TLS → Origin Server
- Click "Create Certificate"
- Select the hostnames you want (e.g.,
example.comand*.example.com) - Choose certificate validity (recommended: 15 years to avoid renewal)
- Copy the Origin Certificate and Private Key and save them on your VPS
SSH into your VPS and create certificate files:
ssh root@YOUR_VPS_IP
# Create a directory for the certificate
mkdir -p /etc/ssl/cloudflare
# Save the Origin Certificate
nano /etc/ssl/cloudflare/cert.pem
# Paste the certificate from Cloudflare and press Ctrl+X, Y, Enter
# Save the Private Key
nano /etc/ssl/cloudflare/key.pem
# Paste the private key and press Ctrl+X, Y, Enter
# Restrict file permissions
chmod 600 /etc/ssl/cloudflare/key.pem
chmod 644 /etc/ssl/cloudflare/cert.pem
Configure Nginx to Use the Origin Certificate
nano /etc/nginx/sites-available/example.com
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/cloudflare/cert.pem;
ssl_certificate_key /etc/ssl/cloudflare/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# Test the config
nginx -t
# Reload Nginx
systemctl reload nginx
Configure Apache to Use the Origin Certificate
nano /etc/apache2/sites-available/example.com-ssl.conf
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/ssl/cloudflare/cert.pem
SSLCertificateKeyFile /etc/ssl/cloudflare/key.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
</VirtualHost>
a2enmod ssl
a2ensite example.com-ssl
systemctl reload apache2
Step 5 — Configure Your Firewall to Accept Traffic Only from Cloudflare
To prevent attackers from accessing your VPS's real IP directly, block ports 80/443 to everyone except Cloudflare:
# Download Cloudflare IP ranges
curl -s https://www.cloudflare.com/ips-v4 -o /tmp/cf_ipv4.txt
curl -s https://www.cloudflare.com/ips-v6 -o /tmp/cf_ipv6.txt
# Remove old iptables rules for ports 80/443
iptables -D INPUT -p tcp --dport 80 -j ACCEPT 2>/dev/null
iptables -D INPUT -p tcp --dport 443 -j ACCEPT 2>/dev/null
# Allow only Cloudflare IPv4
while read ip; do
iptables -I INPUT -p tcp --dport 80 -s "$ip" -j ACCEPT
iptables -I INPUT -p tcp --dport 443 -s "$ip" -j ACCEPT
done < /tmp/cf_ipv4.txt
# Block all other IPs
iptables -A INPUT -p tcp --dport 80 -j DROP
iptables -A INPUT -p tcp --dport 443 -j DROP
# Save rules (Debian/Ubuntu)
apt-get install -y iptables-persistent
netfilter-persistent save
Step 6 — Configure WAF and Security Rules
Go to Security → WAF in your Cloudflare Dashboard:
Enable Managed Rules (Free Plan)
- Enable Cloudflare Managed Ruleset — protects against SQLi, XSS, RCE, and common attack patterns
- Enable Cloudflare OWASP Core Ruleset — protects against OWASP Top 10 vulnerabilities
Configure Security Level
Go to Security → Settings and adjust your Security Level:
- Low — challenge only IPs with a history of attacks. Best for user experience.
- Medium — recommended for most websites
- High — challenge more suspicious traffic. Use during active attacks.
- Under Attack! — use during DDoS attacks. All visitors see a challenge page.
Step 7 — Configure Caching for Static Assets
Go to Caching → Configuration:
- Set Caching Level to "Standard"
- Set Browser Cache TTL to 4 hours or more for assets that don't change often
Create a Page Rule to cache all static files:
- Go to Rules → Page Rules and click "Create Page Rule"
- URL pattern:
example.com/static/* - Setting: Cache Level → Cache Everything
- Edge Cache TTL: 1 month
Step 8 — Configure Always Use HTTPS and HSTS
In your Cloudflare Dashboard, go to SSL/TLS → Edge Certificates:
- Enable Always Use HTTPS — automatically redirect all HTTP requests to HTTPS
- Enable Automatic HTTPS Rewrites — fix Mixed Content issues automatically
- Enable HTTP Strict Transport Security (HSTS) — tell browsers this domain uses HTTPS only (set max-age to at least 6 months)
Verify Your Configuration is Working Correctly
After setup is complete, test with these commands:
# Check that the response header contains "cf-ray" from Cloudflare
curl -sI https://example.com | grep -E "cf-ray|server|x-cache"
# Check the SSL certificate issuer
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -issuer -dates
# Check that HTTP redirects to HTTPS
curl -sI http://example.com | grep location
You should see the cf-ray: header in the response and the certificate issuer should be Cloudflare Inc ECC CA-3 or CloudFlare Origin CA.
Common Issues & Troubleshooting
Error 521 — Web server is down
Cloudflare cannot connect to your VPS. Check:
- Nginx/Apache is running:
systemctl status nginx - Your firewall is not blocking Cloudflare IPs
- Your VPS is listening on port 443:
ss -tlnp | grep 443
Error 525 — SSL Handshake Failed
Your VPS certificate has an issue. Check:
- Your cert.pem and key.pem files match
- SSL Mode in Cloudflare is set to Full or Full (Strict), not Flexible
- Your Nginx/Apache config has no syntax errors:
nginx -t
Redirect Loop (ERR_TOO_MANY_REDIRECTS)
This occurs when SSL Mode is Flexible but your VPS also redirects HTTP to HTTPS. Fix by changing SSL Mode to Full or disabling the HTTP→HTTPS redirect on your VPS.
Complete Setup Summary
Setting up Cloudflare in front of your VPS involves these key steps:
- Sign up for Cloudflare and add your domain, then change your Registrar's Nameservers
- Configure DNS A records and enable Proxy (orange cloud) for your main domain
- Choose Full (Strict) SSL Mode for maximum security
- Create an Origin Certificate from Cloudflare and install it on Nginx/Apache
- Configure your firewall to accept ports 80/443 traffic only from Cloudflare IP ranges
- Enable WAF Managed Rules to protect against OWASP Top 10 attacks
- Set up caching for static assets to reduce load on your VPS
- Enable Always Use HTTPS and HSTS
Verify Cloudflare is Working Correctly
# Check that the response header contains cf-ray from Cloudflare
curl -sI https://example.com | grep -i "cf-ray\|server\|x-cache"
# Check the SSL certificate issuer (should be Cloudflare)
echo | openssl s_client -connect example.com:443 2>/dev/null \
| openssl x509 -noout -issuer -dates
# Check that HTTP redirects to HTTPS correctly
curl -sI http://example.com | grep -i location
# Check the IP that DNS resolves to (should be Cloudflare, not your VPS)
dig +short A example.com
cf-ray: xxxxxxxx-BKK and the issuer is E6 or Cloudflare Inc ECC CA-3, traffic is flowing through Cloudflare correctly.Additional Common Troubleshooting Issues
Error 522 — Connection timed out
Unlike 521, this means Cloudflare can establish a TCP connection but doesn't receive a response in time — usually caused by a firewall blocking Cloudflare IPs.
# Check if Cloudflare IPs are blocked
iptables -L INPUT -n | grep -E "80|443"
# Check that Nginx is listening on port
ss -tlnp | grep -E "80|443"
# Download the latest Cloudflare IP ranges
curl -s https://www.cloudflare.com/ips-v4 | head
Cache Not Updating — Users See Old Content
Cloudflare caches static files at edge servers. You need to purge the cache when content changes.
# Purge all cache via Dashboard:
# Caching → Configuration → Purge Everything
# Or purge specific URLs via API
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" \
-H "Authorization: Bearer API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"files":["https://example.com/style.css"]}'
WebSocket Not Working Through Cloudflare
Cloudflare supports WebSocket, but you must enable it first.
# Enable in Dashboard:
# Network → WebSockets → On
# Verify your Nginx config supports WebSocket upgrade
location /ws/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Visitor Real IP is Incorrect in Logs (Showing Only Cloudflare IP)
Configure Nginx to use the CF-Connecting-IP header instead.
# Add to nginx.conf http section
set_real_ip_from 103.21.244.0/22; # Cloudflare IP ranges
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 173.245.48.0/20;
real_ip_header CF-Connecting-IP;
sudo nginx -t && sudo systemctl reload nginx
Frequently Asked Questions
Is Cloudflare Free Plan Enough for a Typical Website?
Yes. Free Plan provides unlimited DDoS protection, global CDN, basic WAF, free SSL, and basic analytics. Perfect for most websites. Features requiring paid upgrade include Advanced WAF Rules, Image Optimization, Real-time Analytics, and Priority Support.
Can Cloudflare See Our HTTPS Traffic?
Yes. Cloudflare acts as a man-in-the-middle that decrypts SSL at the edge, re-encrypts it, then forwards to your VPS (SSL Termination at Edge). Your request/response data flows through Cloudflare's hands, even with Full (Strict) mode. For true end-to-end encryption that Cloudflare cannot see, use Cloudflare Tunnel or don't use Cloudflare proxy.
Can We Use Cloudflare's Origin Certificate on Other Websites?
No. Cloudflare Origin Certificates only work when traffic flows through Cloudflare. If you access your VPS directly (bypassing Cloudflare), browsers will show a warning because this certificate is not trusted by standard browser CA stores.