How to Host a Website Using Cloudflare and Nginx on Ubuntu 24
Establishing a contemporary web hosting environment using Cloudflare and Nginx on Ubuntu 24 provides outstanding performance, security, and reliability at a fraction of the cost typically associated with enterprise services. This setup uses Cloudflare’s global Content Delivery Network (CDN) and DDoS protection, with Nginx serving as a high-efficiency reverse proxy and web server. This guide will demonstrate how to configure the two systems to work in harmony, set up SSL termination, implement effective caching strategies, and resolve frequent deployment challenges that might even confuse seasoned developers.
The Synergy Between Cloudflare and Nginx
The architecture of this integration is both simple and effective. Cloudflare acts as a reverse proxy in front of your server, managing DNS, SSL termination, caching, and filtering out malicious traffic. When valid requests pass through Cloudflare’s infrastructure, they reach your Ubuntu server where Nginx handles them and delivers your content.
Cloudflare connects to your origin server (your Ubuntu machine) over either HTTP or HTTPS. There are various configurations for the connection between Cloudflare and your server:
- Flexible SSL – SSL is used between the user and Cloudflare, while Cloudflare connects to your server via HTTP
- Full SSL – End-to-end HTTPS with Cloudflare not checking your origin certificate
- Full SSL (Strict) – Full HTTPS with validation of the certificate
Nginx is responsible for serving the actual web content, can operate numerous virtual hosts, and manages connections to your application backend if you are utilising frameworks such as Node.js, Python, or PHP.
Prerequisites and Initial server Setup
Before getting started, ensure you have a fresh Ubuntu 24.04 server with root permissions, alongside a domain pointed to Cloudflare’s nameservers. Basic firewall rules should also be in place.
sudo apt update && sudo apt upgrade -y
sudo apt install nginx ufw curl wget -y
Set up basic firewall
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw --force enable
Verify that Nginx is operational:
sudo systemctl status nginx
sudo systemctl enable nginx
Step-by-Step Nginx Configuration
Begin by crafting a suitable server block configuration. Remove the default config in Nginx and substitute it with your own:
sudo rm /etc/nginx/sites-enabled/default
sudo nano /etc/nginx/sites-available/your-domain.com
Here’s a robust starter configuration designed to work seamlessly with Cloudflare:
server { listen 80; listen [::]:80; server_name your-domain.com www.your-domain.com;
root /var/www/your-domain.com; index index.html index.htm index.nginx-debian.html; # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "sniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; # Configuration for Cloudflare real IP set_real_ip_from 173.245.48.0/20; set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 108.162.192.0/18; set_real_ip_from 190.93.240.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; set_real_ip_from 162.158.0.0/15; set_real_ip_from 104.16.0.0/13; set_real_ip_from 104.24.0.0/14; set_real_ip_from 172.64.0.0/13; set_real_ip_from 131.0.72.0/22; real_ip_header CF-Connecting-IP; location / { try_files $uri $uri/ =404; } # Enhance the delivery of static content location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 1y; add_header Cache-Control "public, immutable"; } # Security - conceal nginx version info server_tokens off;
}
Set up your web directory and activate the site:
sudo mkdir -p /var/www/your-domain.com sudo chown -R www-data:www-data /var/www/your-domain.com sudo chmod -R 755 /var/www/your-domain.com
Create a simple index file for testing
echo "" | sudo tee /var/www/your-domain.com/index.html
Enable the site
sudo ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
Configuring and Integrating Cloudflare
Access your Cloudflare dashboard and add your domain. Essential settings to adjust include:
- DNS Settings – Create an A record pointing to your server’s IP with the orange cloud icon enabled (indicating it’s proxied)
- SSL/TLS Mode – Initially set to “Flexible”, then switch to “Full” once SSL is configured on your server
- Always Use HTTPS – Enable this feature to automatically reroute HTTP requests to HTTPS
- Auto Minify – Activate for CSS, JavaScript, and HTML
Your DNS records should appear as follows:
Type | Name | Content | Proxy Status |
---|---|---|---|
A | @ | your.server.ip.address | Proxied |
CNAME | www | your-domain.com | Proxied |
Once the DNS propagates (typically within 5-10 minutes), your website should be reachable through Cloudflare’s network. You can confirm this by assessing the CF-RAY header through your browser’s developer tools.
SSL Configuration Options and Recommended Practices
For production-level use, ensure you implement proper SSL certificates. Cloudflare offers various options to choose from:
Option 1: Cloudflare Origin Certificates (Recommended)
In the Cloudflare dashboard, generate an origin certificate from SSL/TLS → Origin server. This certificate is trusted by Cloudflare for the connection between their Servers and yours.
# Save the certificate and key files
sudo nano /etc/ssl/certs/cloudflare-origin.pem
sudo nano /etc/ssl/private/cloudflare-origin.key
sudo chmod 600 /etc/ssl/private/cloudflare-origin.key
Update your Nginx configuration to support HTTPS:
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name your-domain.com www.your-domain.com;
ssl_certificate /etc/ssl/certs/cloudflare-origin.pem; ssl_certificate_key /etc/ssl/private/cloudflare-origin.key; # Strong SSL configuration ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; # Your existing configuration continues here...
}
Redirect HTTP requests to HTTPS
server {
listen 80;
listen [::]:80;
server_name your-domain.com www.your-domain.com;
return 301 https://$server_name$request_uri;
}
Option 2: Let’s Encrypt with Certbot
If you prefer to utilise Let’s Encrypt certificates:
sudo apt install certbot python3-certbot-nginx -y sudo certbot --nginx -d your-domain.com -d www.your-domain.com
Set up automatic renewal for the certificate:
sudo crontab -e # Add the following line: 0 12 * * * /usr/bin/certbot renew --quiet
Optimising Performance and Caching Techniques
The combination of Cloudflare and Nginx offers multiple layers of caching. Here’s how to maximise both:
Nginx Caching Configuration
# Add to /etc/nginx/nginx.conf within the http block proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
Within your server block
location / { proxy_cache my_cache; proxy_cache_revalidate on; proxy_cache_min_uses 3; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_background_update on; proxy_cache_lock on;
try_files $uri $uri/ =404;
}
Cloudflare Cache Settings
Establish page rules in Cloudflare to ensure optimal caching:
URL Pattern | Setting | Value |
---|---|---|
*.your-domain.com/*.css | Cache Level | Cache Everything |
*.your-domain.com/*.js | Cache Level | Cache Everything |
*.your-domain.com/api/* | Cache Level | Bypass |
Security Enhancements and Typical Mistakes
Consider implementing a few vital security measures that are commonly overlooked:
Limit Access to Real IP
Since traffic routes through Cloudflare, you can prevent direct server access:
# Add the following to your Nginx server block
# Permit Cloudflare IPs only
allow 173.245.48.0/20;
allow 103.21.244.0/22;
allow 103.22.200.0/22;
allow 103.31.4.0/22;
allow 141.101.64.0/18;
allow 108.162.192.0/18;
allow 190.93.240.0/20;
allow 188.114.96.0/20;
allow 197.234.240.0/22;
allow 198.41.128.0/17;
allow 162.158.0.0/15;
allow 104.16.0.0/13;
allow 104.24.0.0/14;
allow 172.64.0.0/13;
allow 131.0.72.0/22;
deny all;
Common Issues and Resolutions
Issue: Nginx logs display Cloudflare IPs instead of visitor IPs.
Solution: Ensure that the real_ip_from directives are accurately configured (as indicated in the configuration above).
Issue: SSL certificate errors.
Solution: Verify that your SSL/TLS mode in Cloudflare aligns with your server settings. Use “Flexible” if no SSL is configured on your server, “Full” if any SSL certificate is present, or “Full (Strict)” if a valid, trusted certificate exists.
Issue: Excessive redirects.
Solution: This often occurs if Cloudflare is set to “Always Use HTTPS” while your server is also enforcing HTTPS. Either disable the redirect in Nginx or switch off “Always Use HTTPS” in Cloudflare.
Real-World Applications and Performance Analysis
This configuration is particularly beneficial for:
- Popular blogs or content-driven websites – Cloudflare’s CDN significantly reduces server strain
- API backends – Cache sensitive or bypass caching for specific endpoints
- Online shops – DDoS protection and swift global content delivery elevate the user experience
- SaaS platforms – Geographic load balancing and redundancy options
Performance Comparison
Configuration | Time to First Byte (TTFB; avg) | Page Load Duration | DDoS Protection | Global CDN Access |
---|---|---|---|---|
Nginx only | 200ms | 2.3s | ||
Nginx + Cloudflare | 50ms | 1.1s | Yes | Yes |
Advanced Settings and Monitoring
For production scenarios, consider these supplementary settings:
Rate Limiting
# Add to nginx.conf in the http block
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
In server block
location /login {
limit_req zone=login burst=5 delay;
Your normal configuration follows
}
Monitoring and Logging
Set up comprehensive logging to measure performance:
# Custom log format in nginx.conf
log_format cloudflare '$http_cf_connecting_ip - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
In server block
access_log /var/log/nginx/your-domain.access.log cloudflare;
This setup presents you with a secure, scalable hosting solution capable of managing significant traffic while ensuring security and efficiency. The collaboration between Cloudflare’s edge network and Nginx’s adept request processing builds a strong foundation for contemporary web applications.
For more comprehensive information, refer to the official Nginx documentation and Cloudflare’s developer documentation.
This article draws upon information and materials from a variety of online sources. We recognise and appreciate the contributions of all original authors, publishers, and websites. While we have made every effort to credit source material appropriately, any accidental oversights do not constitute a copyright violation. All trademarks, logos, and images mentioned are the property of their respective owners. Should you believe that any content used in this article infringes upon your copyright, we urge you to contact us promptly for a review and quick resolution.
This article is intended purely for information and educational purposes and does not infringe on copyright owners’ rights. If any copyrighted material has been used without the necessary acknowledgment or in violation of copyright laws, it is unintentional, and we will promptly amend it upon notification.
Please note that any reproduction, redistribution, or publishing of part or all of the contents in any format is forbidden without explicit consent from the author and website owner. For permissions or further inquiries, please reach out to us.