Step-by-Step Guide: Connect a Domain with Cloudflare and Enable HTTPS on NGINX

Prerequisites #

Before you begin, ensure you have:

  • A domain name
    Registered and managed through Cloudflare.
  • A publicly accessible IP address
    Both IPv4 and IPv6 are recommended.
  • A deployed website
    Your site's files should be located under /var/www/<name>/public_html (adjust as needed).
  • Basic familiarity with the command line
    Ability to navigate, edit files using vim, and manage system services.

Connect Domain #

Step 1: Create DNS Records #

Ensure all records are proxied (orange cloud icon) to route traffic through Cloudflare.

In the Cloudflare dashboard, add the following DNS records under the DNS tab:

Type Name Content Proxy Status TTL
A @ <public_IPv4> Proxied Auto
A www <public_IPv4> Proxied Auto
AAAA @ <public_IPv6> Proxied Auto
AAAA www <public_IPv6> Proxied Auto

Step 2: Configure Nginx #

Open NGINX site configuration:

bash
sudo vim /etc/nginx/sites-available/<name>

Locate the server block and set the server_name directive:

/etc/nginx/sites-available/<name>
server {
  ...
  server_name example.com;
  ...
}

Test configuration for syntax errors:

bash
sudo nginx -t

If successful, reload NGINX to apply:

bash
sudo systemctl reload nginx

Step 3: Verify DNS Propagation #

You should see your site served via HTTP.

Open website in a browser:
http://example.com

Enable HTTPS #

Step 1: Set Up Cloudflare #

  1. Go to SSL/TLSOverview Configure:
    • Set SSL mode to Full (strict) and save.
  2. Navigate to SSL/TLSEdge Certificates:
    • Always Use HTTPS: enable.
    • HTTP Strict Transport Security (HSTS): enable.
      • Max Age Header: 12 months
      • Apply policy to subdomains: enable
      • Preload: enable
      • No-Sniff Header: enable
      • Save changes.
    • Minimum TLS Version: set to TLS 1.3
  3. Redirect www to root domain:
    • Go to RulesOverview
    • Create a redirect rule using the "Redirect from www to root" template.
    • Deploy rule.

Step 2: Create SSL Certificates #

  1. Go to SSL/TLSOrigin ServerCreate Certificate.
  2. Settings:
    • Private Key Type: ECC
    • Hostnames:
      • *.example.com
      • example.com
    • Certificate Validity: 15 years
  3. Create

Step 3: Configure Nginx for SSL #

Create SSL directory:

bash
sudo mkdir -p /etc/ssl/cloudflare

Create and edit the certificate files:

Paste the contents of the Cloudflare-provided certificate and private key into the respective files.

bash
sudo vim /etc/ssl/cloudflare/cert.pem
bash
sudo vim /etc/ssl/cloudflare/key.pem

Secure files:

bash
sudo chmod 600 /etc/ssl/cloudflare/*

Verify permissions:

bash
ll /etc/ssl/cloudflare/

Backup current NGINX config:

bash
sudo cp /etc/nginx/sites-available/<name> /etc/nginx/sites-available/<name>.bak

Edit NGINX config:

bash
sudo vim /etc/nginx/sites-available/<name>

Modify:

/etc/nginx/sites-available/<name>
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name example.com;

  root /var/www/<name>/public_html;
  index index.php;

  ssl_certificate /etc/ssl/cloudflare/cert.pem;
  ssl_certificate_key /etc/ssl/cloudflare/key.pem;

  ...
}

Complete example for a Kirby CMS website:

/etc/nginx/sites-available/<name>
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name example.com;

  root /var/www/<name>/public_html;
  index index.php;

  ssl_certificate /etc/ssl/cloudflare/cert.pem;
  ssl_certificate_key /etc/ssl/cloudflare/key.pem;

  rewrite ^/(content|site|kirby)/(.*)$ /error last;
  rewrite ^/\.(?!well-known/) /error last;
  rewrite ^/(?!app\.webmanifest)[^/]+$ /index.php last;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
  }
}

Test configuration for syntax errors:

bash
sudo nginx -t

If successful, reload NGINX to apply:

bash
sudo systemctl reload nginx

Step 4: Verify Configuration #

Check response headers:

bash
curl -I https://example.com
bash
curl -I https://www.example.com

Expected results:

  • https://example.comHTTP/2 200
  • https://www.example.comHTTP/2 301 (redirect to root)

Open website in a browser:
https://example.com/

Protect Origin IP #

The Origin IP is the actual IP address of your web server where NGINX is running. This is the direct address users or attackers could use to bypass Cloudflare and reach your server.

Why Protect the Origin IP? #

  • Prevent DDoS attacks: Cloudflare’s network filters and mitigates attacks, but if attackers find your origin IP, they can attack your server directly, bypassing Cloudflare’s protection.
  • Hide server location: Exposing your origin IP reveals your server’s real location and infrastructure.
  • Ensure Cloudflare’s full protection: Cloudflare works as a reverse proxy; to benefit fully, all traffic should flow through Cloudflare, never directly to your server.

How to Protect the Origin IP #

1. Use Cloudflare Proxy (Orange Cloud)

  • In the Cloudflare DNS settings, make sure your domain’s DNS records (A or AAAA) are set to Proxied (orange cloud icon).
  • This masks your origin IP behind Cloudflare’s network.

2. Block Direct Access to Origin IP on NGINX

Open NGINX default site configuration:

bash
sudo vim /etc/nginx/sites-available/default

Modify:

Create minimal default server to block direct IP access.

Response code 444 is an NGINX code that closes the connection silently without a response, ideal for blocking direct IP requests and preventing misuse.

/etc/nginx/sites-available/default
server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name _;

  return 444; # Close connection immediately
}

Test configuration for syntax errors:

bash
sudo nginx -t

If successful, reload NGINX to apply changes:

bash
sudo systemctl reload nginx

Check response headers:

bash
curl -I <public_ipv4>

Expected result: curl: (52) Empty reply from server

3. Block Direct Access with Firewall Rules

4. Avoid Exposing Origin IP Publicly

  • Do not publish your server IP in DNS records or anywhere on your website.
  • Check for subdomains or old DNS entries pointing directly to your origin IP.

Validate Website Security #

Use the following tool to verify that your domain is properly secured and configured:

If everything is correctly configured, the tool should report a 100% score, confirming that:

  • HTTPS is correctly enforced.
  • HSTS is active.
  • TLS settings are secure.
  • Redirection is correctly set up.
  • No insecure headers or protocols are in use.

This step ensures your domain meets modern security and privacy standards.

Troubleshooting #

Website Not Displayed Correctly

Symptoms
Website appears broken, missing styles, scripts, or displays outdated content.

Possible Cause
Cloudflare is serving outdated or corrupted cached content

Solutions

  1. Use Cache-Busting Techniques
    • Modify resource URLs by appending version query strings or unique identifiers (e.g., /style.css?v=timestamp).
    • Forces browsers and Cloudflare to fetch the latest content without needing to purge cache.
    • Prevents frequent full cache clears and minimises downtime or performance impact.
  2. Purge Cloudflare Cache Manually
    • Log in to the Cloudflare dashboard.
    • Go to Caching > Configuration.
    • Prefer Purge Individual Files to target specific problematic assets.
    • Use Purge Everything only if the issue is widespread or cannot be resolved by selective purging.
    • Purging everything can temporarily impact site performance.
  3. Adjust Cache Settings
    • Review and configure cache TTL (Time To Live) values for better control over cache freshness.
    • Reduce TTL during active development or frequent updates to serve new content faster.
    • Balances performance with timely content updates.
  4. Enable Development Mode (Temporary)
    • Activates bypass of Cloudflare cache, serving content directly from the origin server
    • Ideal for short-term use during development or troubleshooting
    • Automatically disables after 3 hours to avoid prolonged cache bypass