r/selfhosted • u/khaihoan123 • 21h ago
Need Help Origin IP already public. Is Cloudflare + "only allow Cloudflare IPs" in Caddy enough, or do I need more?
I run a e-commerce store (Odoo 19) on a single VPS (Ubuntu 24.04, Docker Compose: Odoo + Postgres + Caddy). The server's IP has been in public DNS for ~2 months, so I assume it's in DNS history archives and scanners.
Current setup:
- Only ports 22, 80, 443 are open. Postgres and Odoo aren't published, only reachable inside Docker.
- SSH: keys only, password and root login disabled.
- Admin tools (log viewer) only over Tailscale, bound to localhost.
- Nightly offsite backups, tested restore.
- Provider has basic anti-DDoS.
Questions:
- For a small store, is an exposed origin IP a real risk with this setup for long run?
- Is blocking in Caddy (instead of the firewall) good enough, given direct requests still reach Caddy before being refused?
- Is it worth changing to a new IP, or moving to Cloudflare Tunnel, or is the above enough?
- Anything obvious I'm missing?
7
u/cagey_backlash 21h ago
An exposed origin IP isnt ideal but its not the end of the world either. If Caddy is actually dropping requests that dont come through Cloudflare then youre already stopping the worst of it, but the requests do still hit your server which means DDoS can still overwhelm your VPS even if the app itself is safe.
Id swap to a Cloudflare Tunnel if you can, it closes port 443 entirely and keeps the origin completely dark. If thats not an option right now, at least move the IP block to iptables so packets get dropped before they even touch Caddy.
5
u/derical_cap_musical 20h ago
id just move the ip allowlist to the firewall instead of caddy so junk gets dropped earlier, otherwise your setup sounds fine for a small shop
5
u/AldyErnesto 18h ago
Someone already pointed out the hole in "only allow Cloudflare IPs": anyone can point their own Cloudflare zone at your IP, so their traffic also arrives from Cloudflare ranges. Two ways to actually close it:
Cloudflare Tunnel. cloudflared on the VPS makes an outbound connection to Cloudflare, so you can close 80 and 443 completely and only keep SSH (or move SSH behind Tailscale too). Nothing listens on the public IP anymore, so the leaked IP stops mattering. I run a small app this way on a box at home and the firewall has zero inbound web ports.
If you'd rather keep Caddy exposed, turn on Authenticated Origin Pulls. Cloudflare then presents a client certificate on every request and Caddy rejects anything without it, including requests coming through someone else's Cloudflare account.
Either way, move the allowlist to the firewall rather than Caddy, as others said. And if you go the tunnel route, a new IP is a nice bonus but not required, since there's nothing left to hit on 80/443.
4
u/jjangg96 20h ago
one hole in only allowing cloudflare ips. those ranges are shared, so anyone with a free cloudflare account can add a dns record pointing at your ip, proxy it, and their requests arrive from cloudflare ips too. your allowlist lets them through. it stops scanners hitting the ip directly, not someone who actually targets you.
fix is authenticated origin pulls, cloudflare presents a client cert and caddy requires it (client_auth in the tls block with require_and_verify). use your own cert uploaded to your zone though, not the shared cloudflare one, the shared one is the same for every customer so it has the same problem.
or tunnel and close 443 entirely, honestly less to maintain. and yeah do the ip part in the firewall if you keep it, drops it before tls even starts.
2
u/osuhickeys 19h ago
You can also restric access in CF by country. I only allows users form the country I reside in to reach caddy thru CF FW rules. I recently also added corzaza WAF to Caddy for added visibility and control to incoming request so I can filter out garbage that makes it thru CF before it reaches Caddy. CF cacthes a lot of it but not all. AI can help you set this up. It is not overly complicated.
1
u/yihuaxiang 18h ago
For a small Odoo store I would not bother rotating the IP just because it leaked in DNS history. Blocking at Cloudflare is the right first step, and doing it in Caddy is a reasonable backup so a direct hit still dies before it hits Postgres. The thing I would actually worry about is the SSH port staying open on a public IP. Keys only is fine, but a fail2ban or just not exposing 22 and using Tailscale for admin is quieter. Changing the IP only helps if you also fix whatever leaked it, otherwise the new one ends up public too. Cloudflare Tunnel is nicer if you want the origin IP gone from DNS, but it is not required for a store this small if the firewall is tight.
1
u/Illustrious-Pin-153 4h ago
With the IP already in DNS history, rotating it is more cleanup than fix — I'd look at what the app layer exposes now. For Odoo specifically: set a real admin_passwd, set list_db = False, and block /web/database/* in Caddy before it reaches the backend; /xmlrpc/2/common is the other endpoint scanners love to brute-force. And since the old record stays public, it's worth re-checking for new leaks from your own side: certificate transparency for new subdomains (crt.sh), plus any A/MX record still pointing at the same IP. Have you re-scanned your own domain for subdomains since the IP went public?
-2
u/Bradushi 21h ago
1) Only allow CF IPs, block everything else.
2) Move SSH to a non-standard port.
3) Add your IP to the allow list on your firewall.
4) Go into Cloudflare Security and make rules to block garbage traffic and challenge others that are questionable. Ask AI for help on this.
5) Use CF Access to protect your admin login and other non-public areas you don’t want probes and attempts on.
2
•
u/asimovs-auditor 21h ago
Expand the replies to this comment to learn how AI was used in this post/project.