Skip to content
Muhammet Şafak
tr
Asked by: Gazi Answered:

Should I put my API server behind a Cloudflare Tunnel and close port 443 to the internet?


Question

I serve my API on AWS EC2 using Laravel Octane's FrankenPHP driver. Here's an idea I had: what if I create a Cloudflare Tunnel that points to the app server, and the app runs on localhost:8080? Then port 443 on the API server would never be exposed to the internet, and SSL management wouldn't live on the API server at all. How sound is this, and what are the downsides? My current setup: I use DeployerPHP for deployment. Traffic flows Cloudflare → Caddy → App. I issue the certificate with Cloudflare Origin and load it through Caddy's config on the app server; on the Cloudflare side, SSL is in "Full (strict)" mode. Laravel Octane runs together with Caddy as a supervisor process bound to 0.0.0.0:443 (FrankenPHP driver, max-requests=500, admin-port=2019).

Answer

Short answer: yes, this is a solid pattern. Cloudflare’s Zero Trust side already recommends exactly this — publishing a private origin through a tunnel without ever exposing it to the internet. In your scenario the app runs on 127.0.0.1:8080, cloudflared carries the request there, port 443 never reaches the public internet, and SSL management is fully handed off to Cloudflare. Still, it’s not a “set it and forget it” thing — there are a few things you need to know and accept.

What you have to accept:

  1. Cloudflare becomes the only way in. Once the tunnel is up, Cloudflare is the single entry point to the origin; during a CF outage you have no fallback to fall back on. You’re taking on that dependency knowingly.
  2. Manage the process properly. Run the tunnel client (cloudflared) under systemd with autorestart enabled. You can run two replicas with the same tunnel token to improve availability — but that’s a scaling concern now, not something you need at the start.
  3. Never bind the app to 0.0.0.0. In the tunnel model the app should only be reachable from loopback (127.0.0.1:8080); no port should stay open to the outside. That’s exactly why the --host=0.0.0.0 --port=443 in your current supervisor config has to change.
  4. Cloudflare’s timeouts and limits apply through the tunnel too. The edge request timeout and size limits also apply to requests coming through the tunnel; don’t keep long-running work synchronous — push it onto a queue.
  5. Always configure trusted proxies. If you don’t set Laravel’s TrustProxies, every request will look like it’s coming from loopback; you’ll lose the real client IP, and your rate limiting and logs will break.

Bottom line: if you’re willing to take on the single-path dependency and entrust availability to Cloudflare’s HA, the tunnel is the cleanest solution. But personally I’d stay on your current Cloudflare → Caddy → App setup, lock the origin down to Cloudflare’s IP ranges with a Security Group rule, and add authenticated origin pulls on top — that effectively closes 443 to the outside while keeping you out of a single-path dependency, so it’s more flexible.

Related Reading

Tags: #infrastructure#cloudflare#laravel
Share:

Comments

Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.

More Questions

All questions
Bora

Canary or Blue-Green deployment for a fintech API?

Make Canary your default for routine releases (smallest blast radius), and keep Blue-Green for big cutovers where you want an instant flip/rollback. The real pivot is the database: both demand backward-compatible (expand/contract) schema changes.

#ci-cd#deploy#resilience

Search the site

Start typing to search posts, projects and pages.

Esc to close Powered by Pagefind