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 usingvim
, 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:
sudo vim /etc/nginx/sites-available/<name>
Locate the server
block and set the server_name
directive:
server {
...
server_name example.com;
...
}
Test configuration for syntax errors:
sudo nginx -t
If successful, reload NGINX to apply:
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 #
- Go to SSL/TLS → Overview → Configure:
- Set SSL mode to Full (strict) and save.
- Navigate to SSL/TLS → Edge 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
- Redirect
www
to root domain:- Go to Rules → Overview
- Create a redirect rule using the "Redirect from www to root" template.
- Deploy rule.
Step 2: Create SSL Certificates #
- Go to SSL/TLS → Origin Server → Create Certificate.
- Settings:
- Private Key Type: ECC
- Hostnames:
*.example.com
example.com
- Certificate Validity: 15 years
- Create
Step 3: Configure Nginx for SSL #
Create SSL directory:
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.
sudo vim /etc/ssl/cloudflare/cert.pem
sudo vim /etc/ssl/cloudflare/key.pem
Secure files:
sudo chmod 600 /etc/ssl/cloudflare/*
Verify permissions:
ll /etc/ssl/cloudflare/
Backup current NGINX config:
sudo cp /etc/nginx/sites-available/<name> /etc/nginx/sites-available/<name>.bak
Edit NGINX config:
sudo vim /etc/nginx/sites-available/<name>
Modify:
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:
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:
sudo nginx -t
If successful, reload NGINX to apply:
sudo systemctl reload nginx
Step 4: Verify Configuration #
Check response headers:
curl -I https://example.com
curl -I https://www.example.com
Expected results:
https://example.com
→HTTP/2 200
https://www.example.com
→HTTP/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:
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.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444; # Close connection immediately
}
Test configuration for syntax errors:
sudo nginx -t
If successful, reload NGINX to apply changes:
sudo systemctl reload nginx
Check response headers:
curl -I <public_ipv4>
Expected result: curl: (52) Empty reply from server
3. Block Direct Access with Firewall Rules
- Configure your firewall (e.g.,
ufw
) to allow incoming HTTPS traffic only from Cloudflare IP ranges: https://www.cloudflare.com/ips/
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:
- Visit: https://en.internet.nl
- Select "Test your website".
- Enter your domain (e.g.
example.com
). - Run the test.
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
- 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.
- Modify resource URLs by appending version query strings or unique identifiers (e.g.,
- 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.
- 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.
- 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