How To Put Cloudflare CDN and Proxy in Front of Your Website
Tricknowtech Team 18 min read
Goal
By the end of this tutorial, your domain's DNS will be authoritative at Cloudflare with its web records proxied, HTTPS will be enforced end to end using a validated origin certificate, a caching level and browser cache TTL will be configured, and you'll know how to purge the cache and optionally restrict your origin to Cloudflare's IP ranges.
Prerequisites
A registered domain name (this tutorial uses example.com) that you can manage at your domain registrar, including changing its nameservers.
A web server (Nginx or Apache) already running on a Linux host, such as Ubuntu 22.04 LTS, and serving your site over HTTP.
SSH access to that server with a non-root user that has sudo privileges.
A free or paid Cloudflare account.
Basic familiarity with DNS record types (A, AAAA, CNAME, MX, TXT) and editing your web server's configuration files.
Let an AI agent do this for you
Copy a ready-made prompt for an AI coding assistant with terminal access to your server (Claude Code, Cursor, or similar) — it can carry out the steps below for you. Review what it plans to run before it executes anything.
Putting a domain behind Cloudflare moves the first hit of every request onto Cloudflare's network instead of your origin server. Static assets get served from a nearby edge cache, TLS termination and basic DDoS filtering happen before traffic ever reaches your box, and your origin's real IP address stops being directly exposed to the public internet. None of this requires touching your application code — it is entirely a DNS and dashboard-level change plus a small amount of web server configuration for the TLS certificate.
This tutorial walks through adding a domain to Cloudflare, switching its nameservers, turning on the proxy (the "orange cloud") for the records that serve your website, choosing a TLS/SSL mode and installing a matching certificate on your origin, enforcing HTTPS, setting a caching level and browser cache TTL, and purging the cache after you deploy changes. It uses example.com throughout and applies equally to a site served by Nginx or Apache.
Step 1 — Add Your Site to Cloudflare
Sign in to the Cloudflare dashboard and click Add a Site (sometimes labeled Add a Domain). Enter your root domain, for example example.com, without a leading www or protocol. Choose a plan — the Free plan includes the proxy, Universal SSL, and basic caching controls used in this tutorial, so it's sufficient to follow along.
Cloudflare will scan your domain's existing DNS records at your current provider and import what it finds. This scan is a convenience, not a guarantee — treat the next step as mandatory rather than optional.
Step 2 — Review the Imported DNS Records
On the DNS management screen, compare every imported record against what you know should exist: the A or AAAA record pointing at your origin server, a CNAME for www if you use one, and — importantly — your MX records for mail and any TXT records used for SPF/DKIM/domain verification. Cloudflare's scan can occasionally miss a record, especially unusual TXT entries.
“If you have access to your current DNS provider, export or screenshot its full record list before you change nameservers. If Cloudflare's import misses an MX or TXT record and you don't catch it before cutting over, email delivery or a third-party verification (SSL certificate validation, a SaaS integration, etc.) can silently break.”
Add any missing records now, and correct any that are wrong. Each record has a proxy status shown as a cloud icon: a gray, unfilled cloud means DNS-only (Cloudflare answers the DNS query but traffic goes straight to the origin), and an orange, filled cloud means Proxied (traffic is routed through Cloudflare). Leave everything gray for now — you'll turn on the proxy deliberately in Step 4, after the nameserver cutover is confirmed.
Tricknowtech DNS Management
Cloudflare-backed DNS with instant propagation, all record types, free with hosting.
Step 3 — Update Your Nameservers at Your Registrar
Cloudflare assigns your zone two nameservers, shown on the DNS overview page in your dashboard, following the pattern something.ns.cloudflare.com. Log in to whichever registrar manages example.com, find the nameserver settings for the domain, and replace the existing nameservers with the two Cloudflare gave you. Save the change.
“Do not add Cloudflare's nameservers alongside your existing ones — replace them entirely. A domain should point at exactly one authoritative DNS provider's nameservers at a time.”
Nameserver changes propagate through the DNS system as other resolvers' cached records for your domain expire; this is often done within a couple of hours but can officially take up to 24-48 hours. Cloudflare emails you and flips the zone's dashboard status to Active once it detects the new nameservers are live and authoritative.
Step 4 — Enable the Proxy on Your Web-Facing Records
Once the zone shows Active, return to the DNS management screen. For the A (or AAAA) record on your root domain and on www, click the gray cloud icon to switch it to Proxied — it turns orange. This is the change that actually routes HTTP(S) traffic for that hostname through Cloudflare's network rather than resolving directly to your origin's IP.
“Only proxy records that serve web traffic on standard HTTP/HTTPS ports. The proxy does not forward arbitrary TCP — an SSH-only subdomain, an MX record, or a record pointing at a service listening on a non-web port must stay DNS-only (gray cloud), or connections to it will fail.”
With the proxy enabled, a DNS lookup for example.com no longer returns your origin server's IP address — it returns one of Cloudflare's anycast IPs. Your origin's real address is no longer visible from a plain DNS query, which is part of why proxying is also a basic hardening step, covered further in the optional last step below.
Step 5 — Choose an SSL/TLS Encryption Mode and Certificate
In the dashboard, open the SSL/TLS section for your zone. Cloudflare offers four encryption modes for the connection between Cloudflare and your origin server:
Off — no HTTPS at all; visitor traffic to your site is sent in plaintext. Do not use this.
Flexible — encrypts the connection between the visitor and Cloudflare, but Cloudflare talks to your origin over plain HTTP. This can cause redirect loops if your origin also tries to force HTTPS, and it leaves the Cloudflare-to-origin hop unencrypted.
Full — encrypts both hops (visitor-to-Cloudflare and Cloudflare-to-origin) but accepts a self-signed or otherwise unvalidated certificate on the origin.
Full (strict) — encrypts both hops and requires the origin to present a certificate that Cloudflare can validate, either one from a public certificate authority or Cloudflare's own Origin CA.
Full (strict) is the recommended setting for a production site: it removes the unencrypted hop that Flexible leaves open and it verifies the origin's identity rather than trusting any certificate. If your origin already has a valid certificate (for example from Let's Encrypt), select Full (strict) now and skip to Step 6.
If your origin doesn't yet have a certificate that a public CA would trust, Cloudflare can issue one for it. Under SSL/TLS → Origin Server, click Create Certificate, accept the defaults (RSA key, the hostnames covering example.com and *.example.com, and a long validity period), and generate it. Cloudflare shows you the certificate and private key exactly once — copy both immediately.
On your origin server, save the two values to files and lock down the private key's permissions:
bash
sudo mkdir -p /etc/ssl/cloudflare
sudo nano /etc/ssl/cloudflare/cert.pem # paste the origin certificate, save and exit
sudo nano /etc/ssl/cloudflare/key.pem # paste the private key, save and exit
sudo chmod 600 /etc/ssl/cloudflare/key.pem
For Nginx, point the ssl_certificate directives at those files inside the server block listening on 443:
nginx
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/cloudflare/cert.pem;
ssl_certificate_key /etc/ssl/cloudflare/key.pem;
# ... the rest of your existing server block
}
bash
sudo nginx -t && sudo systemctl reload nginx
For Apache, the equivalent directives go inside the VirtualHost for port 443:
apache
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/cloudflare/cert.pem
SSLCertificateKeyFile /etc/ssl/cloudflare/key.pem
# ... the rest of your existing virtual host
</VirtualHost>
Once the certificate is installed and the web server has reloaded without errors, go back to SSL/TLS in the Cloudflare dashboard and set the mode to Full (strict).
Step 6 — Enforce HTTPS for Visitors
With an encryption mode selected, go to SSL/TLS → Edge Certificates and enable Always Use HTTPS. This makes Cloudflare's edge respond to any plain-HTTP request for your domain with a redirect to the HTTPS version, so visitors and any stray http:// links always end up on an encrypted connection.
“The same Edge Certificates screen has an HSTS toggle. HSTS tells browsers to refuse plain HTTP for your domain for a period of time you set, even on the visitor's very next visit, and it is difficult to safely undo once enabled with a long max-age. Confirm HTTPS is working correctly on every subdomain you serve before turning it on.”
Step 7 — Set the Caching Level and Browser Cache TTL
Open the Caching section (Caching → Configuration) for your zone. The Caching Level setting controls how Cloudflare treats URLs that differ only by query string; the default, Standard, caches based on the full URL including its query string and is the right choice for most sites. Leave it on Standard unless you have a specific reason to ignore query strings.
Browser Cache TTL controls how long Cloudflare tells visitors' browsers to keep a cached copy of a static asset locally before rechecking it, via the Cache-Control header Cloudflare adds to responses. Respect Existing Headers defers to whatever Cache-Control your origin already sends; picking a fixed value such as 4 hours overrides it. If your origin doesn't set explicit cache headers today, starting with a moderate fixed value (a few hours) is a reasonable default for typical static assets like images, CSS, and JavaScript.
By default, Cloudflare's cache only stores static file types (images, CSS, JavaScript, fonts, and similar) — HTML responses from your origin are not cached unless you add a Cache Rule or a legacy Page Rule with a Cache Everything setting. That's outside the scope of this tutorial, but worth knowing before you assume a change to your HTML is being served from cache when it isn't.
Step 8 — Purge the Cache After You Deploy Changes
Whenever you push an update to a cached asset — a new CSS file, an updated image, a redeployed build — visitors may keep seeing the old cached copy until it naturally expires. Purge it manually from Caching → Configuration → Purge Cache. Purge Everything clears the entire zone's cache; Custom Purge lets you clear specific URLs or file paths instead, which is gentler on your origin if only a few assets changed.
The same action is available through the API, which is useful for wiring a purge into a deploy script. You'll need your Zone ID (shown on the dashboard's Overview page) and an API token with cache-purge permission (created under My Profile → API Tokens):
Confirm DNS is actually resolving through Cloudflare rather than straight to your origin:
bash
dig +short example.com
The address returned should be one of Cloudflare's IPs, not your origin server's own address — if it still shows your origin's IP, the record likely isn't proxied (gray cloud) or the nameserver change hasn't finished propagating. Next, confirm the proxy and HTTPS redirect are working end to end:
bash
curl -I https://example.com
A response routed through Cloudflare includes a cf-ray header and typically a server: cloudflare header. Finally, load the site in a browser, check that the padlock shows a valid certificate, and click through a few pages to confirm there's no mixed-content warning or redirect loop, which would point back to an SSL/TLS mode mismatch from Step 5.
Step 10 — Restrict the Origin to Cloudflare's IP Ranges (Optional)
Enabling the proxy hides your origin's IP from casual DNS lookups, but it doesn't stop someone who already knows the address (from a leaked log, an old DNS record, or a scan of common hosting ranges) from connecting to it directly and bypassing Cloudflare entirely. Locking your firewall down to accept web traffic only from Cloudflare's published IP ranges closes that gap.
Cloudflare publishes its current IPv4 and IPv6 ranges at cloudflare.com/ips-v4 and cloudflare.com/ips-v6 — fetch them and allow traffic from each range before switching your firewall's default policy to deny:
bash
curl -s https://www.cloudflare.com/ips-v4 -o /tmp/cf-ips-v4.txt
while read -r ip; do
sudo ufw allow proto tcp from "$ip" to any port 443
done < /tmp/cf-ips-v4.txt
# only after confirming the allow rules above are in place and working:
sudo ufw default deny incoming
“These ranges change occasionally. If you rely on this hardening step, re-fetch the list periodically (a scheduled script is common) rather than treating it as a one-time setup task. Also keep whatever rule allows your own SSH access in place before flipping the default policy to deny, or you'll lock yourself out.”
Conclusion
The domain now resolves through Cloudflare's nameservers, its web-facing DNS records are proxied through Cloudflare's network, and the origin enforces HTTPS using either its own certificate or a Cloudflare Origin Certificate under Full (strict) mode. Plain-HTTP requests get redirected at the edge, static assets are cached according to the configured caching level and browser TTL, and there's a known procedure — dashboard or API — for purging that cache after a deploy. Optionally, the origin firewall now only accepts web traffic from Cloudflare's own IP ranges, closing off direct access to the underlying server.