DNS & EMAIL
July 13, 2026

How to Set Up Cloudflare with Your VPS

7 min read
Author
CloudStick Team
Security Specialist
Share this article
How to Set Up Cloudflare with Your VPS
CloudStick
Cloudflare + VPS

Add your site and import DNS records

Putting Cloudflare in front of a VPS takes four moves: add the domain to Cloudflare, import your DNS records, switch nameservers at your registrar, and set the SSL/TLS mode to Full (strict). The whole thing is maybe twenty minutes of work, and the order matters — get the DNS records right before you flip nameservers, or your site and email go dark during the switch. Start at the Cloudflare dashboard: create a free account, click Add a Site, enter your domain, and pick the Free plan. Cloudflare immediately scans public DNS and presents a list of records it found.

Do not trust that scan blindly. It reliably finds your apex A record and www, but it routinely misses subdomains it cannot guess — staging environments, API hosts, DKIM TXT records, and CNAMEs used for service verification. Open your current DNS zone at the old provider side by side and compare line by line. Every A record should point at your VPS IP, every MX at your mail host, and every TXT record (SPF, DKIM, DMARC, site verifications) should be copied exactly. Anything you forget here becomes a mystery outage the moment nameservers switch, because the old zone stops answering entirely.

Change nameservers at your registrar

Cloudflare does nothing until your registrar points the domain at it. At the end of the add-site flow, Cloudflare assigns you two nameservers — something like ada.ns.cloudflare.com and rick.ns.cloudflare.com. Log in to wherever the domain is registered (Namecheap, GoDaddy, Porkbun, Google Domains successor, anywhere), find the nameserver settings, delete the existing entries, and paste in exactly the two Cloudflare gave you. The registrar and the DNS host are separate roles: the domain stays registered where it is; only DNS resolution moves to Cloudflare.

Propagation usually completes within an hour, though registrars quote up to 24. Verify it from your terminal rather than refreshing the dashboard:

$ dig NS example.com +short
ada.ns.cloudflare.com.
rick.ns.cloudflare.com.
$ dig A example.com +short
104.21.63.184 # a Cloudflare edge IP, not your VPS — proxy is live

When dig NS returns the Cloudflare pair, the zone is active and Cloudflare marks the site as such in its dashboard. Notice the second query: once a record is proxied, dig no longer returns your VPS IP at all — it returns a Cloudflare edge address. That is the point of the next section.

The orange cloud: what proxying actually does

Every DNS record in Cloudflare has a toggle: an orange cloud (Proxied) or a grey cloud (DNS only). Orange means visitor traffic flows through Cloudflare's edge network before reaching your VPS — you get caching, DDoS absorption, the WAF, and your origin IP is hidden from the public. Grey means Cloudflare just answers the DNS query with your real IP and steps out of the way. The proxy is where nearly all of Cloudflare's value lives, so your web-facing A, AAAA, and CNAME records (apex, www, app subdomains) should be orange.

Some records must stay grey. MX records cannot be proxied — Cloudflare's proxy speaks HTTP, not SMTP — so the hostname your MX points to needs a grey-cloud A record, or mail delivery breaks. The same applies to anything non-HTTP: SFTP endpoints, game servers, custom TCP services. And remember that SSH never goes through the proxy either way — connect to your VPS by its IP address directly. Be deliberate about grey-cloud records for hosts on the same VPS: each one publishes your origin IP, which weakens the "hidden origin" benefit unless your firewall backstops it (covered below).

Choose the right SSL/TLS mode: Full (strict)

Go to SSL/TLS in the Cloudflare dashboard and set the encryption mode to Full (strict). It is the only mode you should run in production. The modes describe the second leg of the connection — Cloudflare to your VPS. Flexible encrypts browser-to-Cloudflare but talks plain HTTP to your origin. Full uses HTTPS to the origin but accepts any certificate, even expired or self-signed. Full (strict) uses HTTPS and validates the certificate, giving you real end-to-end encryption.

Flexible is also the classic cause of the ERR_TOO_MANY_REDIRECTS loop. Your visitor loads https://example.com, Cloudflare fetches it from your VPS over plain HTTP, and your Nginx or WordPress config — correctly — redirects HTTP to HTTPS. Cloudflare relays that redirect to a browser that is already on HTTPS, the browser re-requests the same URL, Cloudflare fetches over HTTP again, and the loop spins until the browser gives up. People "fix" this by removing the HTTPS redirect on the origin, which leaves every request between Cloudflare and their server unencrypted. The real fix is a valid certificate on the origin and Full (strict).

A valid origin certificate costs nothing: Let's Encrypt issues them free, and Full (strict) accepts them happily. Issue the certificate for your domain on the VPS, confirm HTTPS works directly against the origin, then flip the mode.

TIP

If your VPS runs on CloudStick, this pairing is two clicks: the free Let's Encrypt SSL with auto-renewal gives your origin the valid certificate Full (strict) requires, so the certificate never silently expires and drops your site to a 526 error. CloudStick's Cloudflare integration also manages your DNS records straight from the dashboard via the Cloudflare API — new sites and subdomains get their records created without switching tabs.

Restore real visitor IPs in Nginx logs

The day after you enable the proxy, your Nginx access logs will show every visitor arriving from a handful of Cloudflare IPs — because at the TCP level, Cloudflare is now the client. That wrecks analytics, rate limiting, and especially fail2ban, which will happily ban a Cloudflare edge node and take out half your traffic. Cloudflare sends the visitor's true address in the CF-Connecting-IP header on every request, and Nginx's real_ip module (compiled into standard builds) can substitute it back, but only for connections coming from IP ranges you explicitly trust:

# /etc/nginx/conf.d/cloudflare-real-ip.conf
real_ip_header CF-Connecting-IP;
# Cloudflare IPv4 ranges — full list: cloudflare.com/ips
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
# ...remaining IPv4 and IPv6 ranges from cloudflare.com/ips
$ sudo nginx -t && sudo systemctl reload nginx

The set_real_ip_from lines are the security half of the config: without them, anyone who connects to your origin directly could forge a CF-Connecting-IP header and spoof their address in your logs. Listing Cloudflare's published ranges means Nginx only believes the header when the connection genuinely comes from Cloudflare. Add both the IPv4 and IPv6 lists from cloudflare.com/ips — they change rarely, but it is worth a calendar reminder to re-check them a couple of times a year.

Firewall rules and your next steps

The proxy only protects traffic that goes through it. Your VPS still has a public IP, and an attacker who discovers it — from an old DNS record, an email header, or a certificate transparency log — can hit ports 80 and 443 directly, bypassing Cloudflare's WAF and DDoS protection entirely. The fix is to restrict inbound 80/443 at the server firewall to Cloudflare's published ranges (the same lists from cloudflare.com/ips-v4 and ips-v6) and drop everything else. In CSF that means adding the ranges to the allow list and removing the blanket-open web ports; with ufw, a small loop over the two lists does it. Leave your SSH port out of these rules — SSH never transits Cloudflare, so scope it to your own IP or keep it key-only and rate-limited instead.

That completes a correct setup, and it is worth restating as a checklist you can run in ten minutes: DNS records imported and compared line by line against the old zone; dig NS returning the Cloudflare pair; orange clouds on web records, grey on mail; a Let's Encrypt certificate on the origin with SSL/TLS mode at Full (strict) — never Flexible; CF-Connecting-IP restored in Nginx via real_ip; and web ports firewalled to Cloudflare's ranges. Do them in that order and you get the whole Cloudflare bundle — hidden origin, absorbed attack traffic, edge caching — without the redirect loops, banned edge nodes, and silent bypasses that make people swear off the orange cloud.

Leave a comment
Full Name
Email Address
Message
Contents