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!