TCP/UDP port 53 blocked? Trying to setup a DNS server

Hi! I’m still fairly new to Fly, but I’m loving spinning up some small projects with it. It’s fast, simple, practical and the cherry on top is having the ability of creating a global presence faster than I can blink.

My latest small experiment is trying to ditch a bunch of dnscrypt-proxy local instances that I have, across multiple places doing DoH upstream and using a handful of blocklists. It’s a pain to maintain it, every time a config changes, I end up having to touch multiple machines. (I won’t even touch the subject of sending queries to third parties from my home IP). I’ve found a very interesting Go project named Blocky, and it seems that it can do almost everything dnscrypt-proxy does, in a simpler way and specially provide me plain DNS and DoH support, with all this plus some Fly magic, I can even serve DNS on multiple continents while maintaining one single file.

Sorry for the rambling, now for the actual problem, the Dockerfile works, I’ve tested locally and on a VPS, but when flyctl finishes the launch and I can see the logs via the dashboard, I can’t query 53 TCP/UDP. If I had to guess it’s either being blocked (port 53 is tricky I know) or I’m doing something stupid with fly.toml.


app = "some actual app name"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []


  allowed_public_ports = [53]
  auto_rollback = true

  internal_port = 53
  protocol = "udp"

    port = 53

Either way I would love any input and/or ideas on how to solve this! Thanks a lot in advance!

You can empty allowed_public_ports to [].

Make sure blocky is listening for UDP and TCP on port 53 (UDP must listen on a special Fly address fly-global-services and is IPv4 only (ref); no such special addresses or limitations for TCP, however). After adding a TCP section (which is missing), consider adding tcp health checks to fly.toml, so deployments fail / VM restarts whenever nothing happens to be listening on TCP/53.

Not sure if it matters but while services.internal_port is a Number, services.ports.port appears to be a String (ref). At least, that’s how a Golang project I deploy to Fly declares it (code).

Note: For UDP, both services.internal_port and services.ports.port must be one and the same. For TCP, they could be different

Thank you very much sir! That was spot on!

Now I just need to figure out the best way to keep certificates renewed via secrets or just use Fly as the TLS termination! But that’s another thing to tackle!

No problem.

With DoH, you’d need to handle both h2c and http1x: Here’s how we solved it in Go (relevant fly.toml bits).