BLOG POSTS
    MangoHost Blog / How to Host a Website Using Cloudflare and Nginx on Ubuntu 24
How to Host a Website Using Cloudflare and Nginx on Ubuntu 24

How to Host a Website Using Cloudflare and Nginx on Ubuntu 24

Setting up a modern web hosting stack with Cloudflare and Nginx on Ubuntu 24 gives you enterprise-grade performance, security, and reliability without the enterprise price tag. This combination leverages Cloudflare’s global CDN and DDoS protection while using Nginx as a high-performance reverse proxy and web server. You’ll learn how to configure both services to work together seamlessly, implement SSL termination, set up proper caching strategies, and troubleshoot common deployment issues that can trip up even experienced developers.

How Cloudflare and Nginx Work Together

The architecture here is straightforward but powerful. Cloudflare sits in front of your server as a reverse proxy, handling DNS resolution, SSL termination, caching, and filtering malicious traffic. When legitimate requests make it through Cloudflare’s network, they hit your Ubuntu server where Nginx processes them and serves your content.

Cloudflare communicates with your origin server (your Ubuntu box) using either HTTP or HTTPS. The connection between Cloudflare and your server can be configured in several ways:

  • Flexible SSL – HTTPS between visitor and Cloudflare, HTTP between Cloudflare and your server
  • Full SSL – HTTPS end-to-end, but Cloudflare doesn’t validate your origin certificate
  • Full SSL (Strict) – HTTPS end-to-end with certificate validation

Nginx handles the actual web serving, can run multiple virtual hosts, and manages your application backend connections if you’re running something like Node.js, Python, or PHP applications.

Prerequisites and Initial Server Setup

Before diving in, make sure you have a fresh Ubuntu 24.04 server with root access and a domain name pointed to Cloudflare’s nameservers. You’ll also need basic firewall rules configured.

sudo apt update && sudo apt upgrade -y
sudo apt install nginx ufw curl wget -y

# Configure basic firewall
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw --force enable

Check that Nginx is running:

sudo systemctl status nginx
sudo systemctl enable nginx

Step-by-Step Nginx Configuration

Start by creating a proper server block configuration. Remove the default Nginx config and create your own:

sudo rm /etc/nginx/sites-enabled/default
sudo nano /etc/nginx/sites-available/your-domain.com

Here’s a solid starter configuration that plays well 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 "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    
    # Real IP configuration for Cloudflare
    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;
    }
    
    # Optimize static content delivery
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # Security - hide nginx version
    server_tokens off;
}

Create your web directory and enable 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 "<h1>Hello from Nginx + Cloudflare!</h1>" | 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

Cloudflare Configuration and Integration

Log into your Cloudflare dashboard and add your domain. The key settings you need to configure:

  • DNS Settings – Create an A record pointing to your server’s IP with the orange cloud enabled (proxied)
  • SSL/TLS Mode – Set to “Flexible” initially, then “Full” once you have SSL configured on your server
  • Always Use HTTPS – Enable this to redirect HTTP to HTTPS automatically
  • Auto Minify – Enable for CSS, JavaScript, and HTML

For the DNS record, it should look like this:

Type Name Content Proxy Status
A @ your.server.ip.address Proxied
CNAME www your-domain.com Proxied

Once DNS propagates (usually 5-10 minutes), your site should be accessible through Cloudflare’s network. You can verify this by checking the CF-RAY header in your browser’s developer tools.

SSL Configuration Options and Best Practices

For production use, you want proper SSL certificates. You have several options with Cloudflare:

Option 1: Cloudflare Origin Certificates (Recommended)

Generate an origin certificate in Cloudflare’s dashboard under SSL/TLS β†’ Origin Server. This gives you a certificate that Cloudflare trusts 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 use 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 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 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:

sudo crontab -e
# Add this line:
0 12 * * * /usr/bin/certbot renew --quiet

Performance Optimization and Caching Strategies

The combination of Cloudflare and Nginx gives you multiple caching layers. Here’s how to optimize both:

Nginx Caching Configuration

# Add to /etc/nginx/nginx.conf in 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;

# In 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 Rules

Set up page rules in Cloudflare for 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 Hardening and Common Pitfalls

A few security configurations that often get overlooked:

Restrict Access to Real IP

Since traffic comes through Cloudflare, you can block direct access to your server:

# Add to your Nginx server block
# Allow 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 Pitfalls and Troubleshooting

Problem: Nginx logs show Cloudflare IPs instead of visitor IPs

Solution: Make sure you have the real_ip_from directives configured correctly (shown in the configuration above).

Problem: SSL certificate errors

Solution: Check that your SSL/TLS mode in Cloudflare matches your server configuration. Use “Flexible” if you don’t have SSL on your server, “Full” if you have any SSL certificate, or “Full (Strict)” only if you have a valid, trusted certificate.

Problem: Too many redirects error

Solution: This usually happens when Cloudflare is set to “Always Use HTTPS” but your server is also redirecting to HTTPS. Either disable the redirect in Nginx or turn off “Always Use HTTPS” in Cloudflare.

Real-World Use Cases and Performance Comparison

This setup works particularly well for:

  • High-traffic blogs or content sites – Cloudflare’s CDN reduces server load significantly
  • API backends – You can selectively cache or bypass caching for different endpoints
  • E-commerce sites – DDoS protection and fast global delivery improve user experience
  • SaaS applications – Geographic load balancing and failover capabilities

Performance Comparison

Configuration TTFB (avg) Page Load Time DDoS Protection Global CDN
Nginx only 200ms 2.3s No No
Nginx + Cloudflare 50ms 1.1s Yes Yes

Advanced Configuration and Monitoring

For production environments, consider these additional configurations:

Rate Limiting

# Add to nginx.conf 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 nodelay;
    # Your normal configuration
}

Monitoring and Logging

Configure detailed logging to track 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 gives you a robust, scalable hosting solution that can handle significant traffic while maintaining security and performance. The combination of Cloudflare’s edge network and Nginx’s efficient request handling creates a powerful foundation for modern web applications.

For more detailed information, check the official Nginx documentation and Cloudflare’s developer documentation.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked