Recipe: behind Cloudflare
Vaultbase behind Cloudflare's proxy or a Cloudflare Tunnel, with real client IPs, realtime and no cached files.
Two ways to put Cloudflare in front of a Vaultbase server. Both keep the caller’s real address for rate limits, sign-in lockouts and the audit log, and both carry realtime.
- The proxy (an orange-cloud DNS record) in front of the plain VPS recipe. Ports 80 and 443 stay open, to Cloudflare only.
- A tunnel:
cloudflaredon the server connects out to Cloudflare, and no port is open at all. There’s less to set up, and it’s the better choice for a server behind NAT or at home.
Use Vaultbase 0.32.3 or later. Earlier versions sent files without
Cache-Control, so Cloudflare could cache a file served to one caller and
hand it to others. Their fix is under Caching.
A: The proxy
Section titled “A: The proxy”Follow the plain VPS recipe through step 3
(Vaultbase on 127.0.0.1:8091, VAULTBASE_TRUSTED_PROXIES=127.0.0.1/32,::1/128),
then install Caddy as in step 4, without its Caddyfile: you’ll write a
different one below.
1. DNS and TLS
Section titled “1. DNS and TLS”-
In Cloudflare, add an
Arecordapi→ the server’s IP, Proxied. -
SSL/TLS → Origin Server → Create certificate for
api.example.com. Save the certificate as/etc/caddy/origin.pemand the key as/etc/caddy/origin.key, readable by Caddy:Terminal window sudo chown root:caddy /etc/caddy/origin.*sudo chmod 640 /etc/caddy/origin.*The origin certificate is trusted by Cloudflare only, which is all that reaches the server. Caddy doesn’t need to get one from Let’s Encrypt, which can fail behind the proxy.
-
Once Caddy serves that certificate (step 2 below), go to SSL/TLS → Overview and set the mode to Full (strict): choose Custom if the zone is on Automatic. Setting it before the certificate is in place gives
526errors meanwhile. Flexible would reach the server over plain HTTP. Cloudflare would still tell Vaultbase the visitor used HTTPS, but the hop from Cloudflare to the server would be unencrypted.
2. Caddy: trust Cloudflare for the client address
Section titled “2. Caddy: trust Cloudflare for the client address”Requests now reach Caddy from Cloudflare’s addresses, with the visitor’s
address in CF-Connecting-IP. Tell Caddy to believe that header only from
Cloudflare. Replace /etc/caddy/Caddyfile with:
{ servers { # Cloudflare's ranges: https://www.cloudflare.com/ips/ (check them now # and then; they change rarely). trusted_proxies static 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 104.24.0.0/14 172.64.0.0/13 131.0.72.0/22 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 2a06:98c0::/29 2c0f:f248::/32 client_ip_headers CF-Connecting-IP }}
api.example.com { tls /etc/caddy/origin.pem /etc/caddy/origin.key reverse_proxy 127.0.0.1:8091 { # The visitor's address as Caddy worked it out, set (not appended). header_up X-Forwarded-For {client_ip} }}sudo systemctl reload caddyA request that doesn’t come from Cloudflare can’t set the address this way: Caddy then uses the connection’s own address.
3. Firewall: Cloudflare only
Section titled “3. Firewall: Cloudflare only”Close 80 and 443 to everyone but Cloudflare, so nobody can reach the server around it. Add Cloudflare’s rules first, then remove the open one (if fetching the list fails, nothing is closed):
v4=$(curl -fsS https://www.cloudflare.com/ips-v4) && v6=$(curl -fsS https://www.cloudflare.com/ips-v6) && \for ip in $v4 $v6; do sudo ufw allow from "$ip" to any port 80,443 proto tcpdone && sudo ufw delete allow 80,443/tcpsudo ufw statusThen go on with step 5 of the VPS recipe.
B: A tunnel
Section titled “B: A tunnel”On the server, follow steps 1 to 3 of the
plain VPS recipe, leaving out the
ufw allow 80,443/tcp line in step 1: nothing comes in but SSH. Skip Caddy.
- In the Cloudflare dashboard, open Networking → Tunnels → Create a tunnel, name it, and select Create Tunnel.
- Choose the server’s operating system and run the install command it
shows on the server. It installs
cloudflaredas a service with the tunnel’s token. Select Continue once the tunnel is connected. - On the tunnel’s Routes tab, Add route → Published application:
subdomain
api, your domain, and Service URLhttp://127.0.0.1:8091.
cloudflared connects to Vaultbase from the same machine. Cloudflare adds
the visitor’s address at the end of X-Forwarded-For, and Vaultbase reads
that header from the right, from a trusted proxy only. So the
VAULTBASE_TRUSTED_PROXIES=127.0.0.1/32,::1/128 from step 3 is all it needs.
X-Forwarded-Proto arrives as https, so sign-in cookies get the Secure
flag.
Then go on with step 5 of the VPS recipe.
Settings that matter for an API
Section titled “Settings that matter for an API”Caching
Section titled “Caching”Cloudflare doesn’t cache JSON, but it caches images, PDFs and other static
file types by default, keyed on the URL. Vaultbase sends every file with
Cache-Control: private (a token’s file with no-store), which Cloudflare
honors, so a file allowed for one caller is never handed to another.
On a version before 0.32.3, add a rule under Caching → Cache Rules:
when the URI path starts with /api/, Bypass cache.
Don’t turn on Cache Everything for the API’s hostname.
Realtime
Section titled “Realtime”WebSockets (/realtime) and the SSE fallback (/api/v1/realtime) work
through Cloudflare on every plan; check that Network → WebSockets is on.
Cloudflare closes a request whose response hasn’t started after 125 seconds
(error 524). Realtime isn’t affected, since SSE sends a keepalive every 30
seconds.
Uploads
Section titled “Uploads”Cloudflare refuses a request body over 100 MB on the Free and Pro plans
(200 MB on Business), with 413. For larger files, store them in
S3-compatible storage and upload there directly, or keep a hostname that
isn’t proxied for uploads.
Bot protection
Section titled “Bot protection”Bot Fight Mode and challenge rules can answer an API call with an HTML
challenge page, which apps and other servers can’t solve. If calls fail with
403 and HTML, add a WAF custom rule that skips them for the API’s hostname.
Browser origins
Section titled “Browser origins”In the admin, Settings → CORS lists the origins of your web apps; it’s the same with or without Cloudflare.
Check it
Section titled “Check it”curl -sI https://api.example.com/_/health # 200, with cf-ray in the headersThen sign in to the admin and open Logs: requests should show your own
address, not one of Cloudflare’s or 127.0.0.1.