Fly edge rejects TLS handshake for apex domain (no cert, “protocol_version” alert)

Hi,

My SSL cert was automatically renewed a day or two ago and I started getting reports the site wasn’t working in Safari and Firefox. Below is a summary of the config and everything I tried, but it’s still a problem. Yes, it’s AI-generated, it was really useful for helping me iterate through options and narrow down to a good summary.

Summary

  • App: drop-safe (primary region ord)
  • Domain: dropsafe.app
  • Cloudflare disabled; apex points directly to Fly anycast IPs
  • Recent cert actions: reissued, removed/re‑added — behavior unchanged
  • Symptom: TLS handshake is aborted by the Fly edge before any certificate is presented
    (fatal protocol_version alert). Reproduces on IPv4 and IPv6, across multiple clients/
    browsers.

DNS

  • A: 66.241.125.242
  • AAAA: 2a09:8280:1::83:950c:0

Current TLS config (fly.toml)

  • Termination at edge (internal_port = 8080, force_https = true)
  • TLS:
    [http_service.tls_options]
    min_version = “TLSv1.2”
    max_version = “TLSv1.3”
    alpn = [“http/1.1”]

We also tried the versions = [“TLSv1.2”,“TLSv1.3”] array and ALPN defaults
([“h2”,“http/1.1”]). Redeployed after each change; no difference.

Client versions

  • Machine A:
    • openssl: OpenSSL 3.5.1
    • curl: curl 8.7.1 (SecureTransport, LibreSSL/3.3.6)
  • Machine B:
    • openssl: LibreSSL 3.3.6
    • curl: curl 8.7.1 (SecureTransport, LibreSSL/3.3.6)

Browser behavior

  • Safari: hangs or “can’t establish a secure connection”
  • Firefox: fails
  • nscurl ATS diagnostics: hangs (no output)

Repro (copy/paste)

  • Resolve:
    • dig +short dropsafe.app A
    • dig +short dropsafe.app AAAA
  • Domain (resolver may pick v6):
    • curl -vI https://dropsafe.app
    • Expected: cert + headers
    • Actual: “LibreSSL/3.3.6: … ST_CONNECT: tlsv1 alert protocol version”
  • Force Fly IPv4 + SNI:
    • curl -4Iv https://66.241.125.242/ -H ‘Host: dropsafe.app’
    • openssl s_client -connect 66.241.125.242:443 -servername dropsafe.app
    • Actual: no peer certificate; protocol_version alert; sometimes SSL_ERROR_SYSCALL
  • Force Fly IPv6 + SNI:
    • curl -6Iv ‘https://[2a09:8280:1::83:950c:0]/’ -H ‘Host: dropsafe.app’
    • openssl s_client -connect [2a09:8280:1::83:950c:0]:443 -servername dropsafe.app
    • Actual: same early abort; no cert
  • Force TLS versions (IPv4):
    • openssl s_client -tls1_2 -connect 66.241.125.242:443 -servername dropsafe.app
    • openssl s_client -tls1_3 -connect 66.241.125.242:443 -servername dropsafe.app
    • Actual: both fail with protocol_version alert

Representative snippet (IPv4, s_client):

  • no peer certificate available
  • SSL handshake has read 5 bytes and written 315 bytes
  • error: tlsv1 alert protocol version

What we’ve tried

  • Reissued cert; removed/re‑added cert (no change)
  • TLS options: versions array → min/max; toggled ALPN default vs http/1.1
  • Multiple deploys between changes
  • Disabled Cloudflare completely; apex now goes straight to Fly

Has anyone seen Fly’s edge return a fatal protocol_version alert before cert presentation,
even with min_version TLS 1.2 and max_version TLS 1.3 configured?

Are there recent changes in Fly’s TLS termination that would cause this behavior on
certain edges?

Any advice to force an edge rollout/propagation of tls_options, or additional config we
should try?

Thank you!!

:waving_hand: @r38y

I’m unable to reproduce the browser behaviour on my machine, my suspicion would be an OS/browser that is too far out of date, or possibly a caching issue in those browsers. Let’s Encrypt rotated their intermediates in August, so they will have changed from your prior certificate. This shouldn’t pose an issue, but clearing the browsing data for your site is always a worthwhile step.

Our TLS termination hasn’t changed recently. SSLLabs can give you a good overview of browser/device support: SSL Server Test: dropsafe.app (Powered by Qualys SSL Labs)


Regarding your curl tests:

These commands are expected to fail, so this isn’t highlighting an issue with your setup. In these cases, curl is expecting a certificate for that IP address, and there isn’t any SNI for our end to resolve. The correct tests to force an IP are:

curl -Iv https://dropsafe.app/ --resolve dropsafe.app:443:66.241.125.242
curl -Iv https://dropsafe.app/ --resolve 'dropsafe.app:443:[2a09:8280:1::83:950c:0]'

Both of these are working from my machine.

Both of these checks also pass from my machine.

Hi, thank you for the reply. It looks like removing the cert and re-adding it a third time got it to work again. About six hours ago the latest Firefox and Safari were returning an error.

The second time I removed and re-added the cert, it took over 19 hours to get issued. The third time, it was > 3 but I was away from my computer so I’m not sure exactly when it started working. This is the last time I checked on the cert before walking away:


❯ fly certs show dropsafe.app
The certificate for dropsafe.app has not been issued yet.

Hostname = dropsafe.app
DNS Provider = cloudflare
Certificate Authority = Let’s Encrypt
Issued =
Added to App = 3 hours ago
Source = fly

Your certificate for dropsafe.app is being issued. Status is Awaiting certificates. Make sure to create another certificate for www.dropsafe.app when the current certificate is issued.


I don’t remember it taking more than a few minutes on my other Fly apps, so I figured something wasn’t quite right.

One of my attempts to get the site back up was to enable proxying traffic through Cloudflare and terminating the SSL there, but Cloudflare also reported an error reaching the origin because of an SSL error.

Anyways, it seems fixed now.

Cheers,

Randy

Hi @bglw

Actually, the cert still hasn’t been issued, but yet it’s working for us both now, how’s that possible?

My dashboard right now: CleanShot 2025-09-07 at 18.06.45 · CleanShot Cloud

Via the CLI:

drop_safe main ≡2s
❯ date
Sun Sep  7 18:07:40 MDT 2025

drop_safe main ≡
❯ fly certs show dropsafe.app
The certificate for dropsafe.app has not been issued yet.

Hostname                  = dropsafe.app
DNS Provider              = cloudflare
Certificate Authority     = Let’s Encrypt
Issued                    =
Added to App              = 4 hours ago
Source                    = fly

Your certificate for dropsafe.app is being issued. Status is Awaiting certificates. Make sure to create another certificate for www.dropsafe.app when the current certificate is issued.

Just had a quick look into that. Your hostname has been rate limited by Let’s Encrypt due to it being removed/added repeatedly, so this latest certificate won’t show as configured for about 7 days.

Our edge still has the previously issued certificate available, so your hosting will work fine. Once the Let’s Encrypt rate limit clears a new certificate will be issued and swapped out.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.