Cloudflare in Front of Neo: Flexible SSL and edge_https

Cloudflare's Flexible SSL mode talks HTTP to your origin — edge_https tells your app it was actually HTTPS, without a redirect loop.

5 min read

The problem Flexible SSL creates

With Cloudflare's "Flexible" SSL mode, the browser talks HTTPS to Cloudflare, but Cloudflare talks plain HTTP to your origin server. If your app checks $_SERVER['HTTPS'] or a framework's equivalent and forces a redirect to HTTPS when it's missing, you get a redirect loop: the app redirects to HTTPS, Cloudflare's request was HTTP, the app redirects again.

The fix

edge_https: true

This tells Neo the origin is genuinely HTTP, but sits behind an HTTPS edge. Neo configures Caddy to set X-Forwarded-Proto: https on the request to your app, so frameworks that trust that header (Laravel with TRUSTED_PROXIES=*, most others by default) see the request as HTTPS-secure without Neo's own Caddy needing to terminate TLS itself.

Why not just use Cloudflare's Full or Full (strict) mode instead

Full/Full (strict) mode has Cloudflare talk HTTPS to your origin too, which is generally the better setup — Neo's own Caddy already provisions a real Let's Encrypt certificate automatically, so Full (strict) works with zero extra config beyond pointing DNS at the server. edge_https exists specifically for the case where you can't change the Cloudflare mode (a legacy setup, an organizational policy) and need the origin to work correctly anyway.

Combining with basic auth

edge_https: true
basic_auth:
  user: admin
  password: "${NEO_BASIC_AUTH_PASSWORD}"

Both apply at the Caddy layer independently — edge_https affects the forwarded headers, basic_auth gates access. Order of declaration in .neo.yml doesn't matter; both are always applied together on every route rebuild.

Try it yourself — Neo is free, with every feature unlocked.

Get started free