External Redis connection fails with I/O error despite correct config and passing health checks

Hey,
I’m running into an issue trying to expose a Redis instance publicly over TCP on Fly.io. Despite following all the expected configuration steps, external connections are still failing with an I/O error or Server closed the connection.


App details

  • App type: Redis
  • Region: cdg
  • Port: 6379
  • Base image: redis:7

Dockerfile:

FROM redis:7
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]

redis.conf:

bind 0.0.0.0
requirepass <REDACTED>
logfile "/data/redis.log"

What’s working

  • Redis starts successfully and is accessible via redis-cli inside the Fly VM
  • bind 0.0.0.0 is active
  • Password auth works internally
  • TCP health check is defined and passing:
[[services]]
  protocol = "tcp"
  internal_port = 6379

  [[services.tcp_checks]]
    interval = 15000
    timeout = 2000

  [[services.ports]]
    handlers = []
    port = 6379
  • fly status confirms:
    • Machines started
    • 1 total, 1 passing health check
  • DNS resolves correctly to public IP
  • Redis works locally inside the VM and logs show “Ready to accept connections”

What’s not working

  • External connections (e.g. via redis-cli) always return:
I/O error
Error: Server closed the connection
  • Redis logs show no errors or incoming connection attempts
  • No indication the edge is passing traffic through, even though the port is exposed and the health check is passing

What I’ve tried

  • Re-deploying with --strategy immediate and cache busting
  • Confirmed config file is loaded
  • Tested multiple formats for tcp_checks
  • Tried alternate ports
  • Verified all behavior from inside the Fly VM
  • Confirmed INFO clients shows no hits from outside

My question

  • Is there any reason Fly’s edge proxy might still be blocking TCP connections, even after a health check passes?
  • Are there additional config steps or workarounds for exposing raw TCP services like Redis?

Any help would be much appreciated!
Thanks in advance!

Depending on what kind of network you’re using, you might have to listen on IPv6 instead of IPv4. Try swapping from 0.0.0.0 to [::0] and see if you have more luck.

Yep, raw TCP services are incompatible with the low-budget shared IPv4 addresses, :raggedy_rabbit:

https://fly.io/docs/networking/services/#shared-ipv4

I don’t know the Redis protocol that well myself, but if you could use TLS/SSL (with SNI) then that would be the best fix:

[[services.ports]]
  handlers = ["tls"]  # ←
  port = 6379

You were right it was the shared ipv4 that was the issue. Using a dedicated ($2/month) ipv4 address solved it :slight_smile: thanks a lot! haven’t tried the TLS/SSL solution, because i have pulled enough hair out of my head already ^^

1 Like

In my experience simply using ipv6 to connect to redis works fine. you should already have a dedicated ipv6 on your machine

1 Like

Well, you’re right too :slight_smile: i just moved to ipv6 and was able to release my dedicated ipv4 address. thanks for the help!

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