Deploying Phoenix with the Bandit adapter on Fly.io

Wanted to put this out into the world in case someone runs into a similar scenario down-the-way.

I recently deployed a bit of Phoenix 1.7.0 boilerplate, and decided to replace the default HTTP server (Cowboy) with Bandit, just to see how that was.

… and it was pretty great! Everything seemed to work fine; except, when I went and checked the logs, I saw errors, at fifteen second intervals (there’s your clue!) in this form:

2022-12-12T13:15:00.000 app[abcdefgh] iad [info] 13:15:00.000 [error] GenServer #PID<0.1000.0> terminating
2022-12-12T13:15:00.000 app[abcdefgh] iad [info] ** (stop) "Could not determine a protocol"
2022-12-12T13:15:00.000 app[abcdefgh] iad [info] Last message: {:continue, :handle_connection}
2022-12-12T13:15:15.000 app[abcdefgh] iad [info] 13:15:15.000 [error] GenServer #PID<0.1001.0> terminating
2022-12-12T13:15:15.000 app[abcdefgh] iad [info] ** (stop) "Could not determine a protocol"
2022-12-12T13:15:15.000 app[abcdefgh] iad [info] Last message: {:continue, :handle_connection}

It took me a bit to make heads-or-tails, but it turns out, this is the response that Bandit is giving to the TCP checks (15s interval!) that are generated as part of the default fly.toml, similar to what was relayed in this GitHub issue.

I replaced the [[services.tcp_checks]] block in the fly.toml with:

[[services.http_checks]]
  grace_period = "1s"
  interval = "15s"
  method = "get"
  path = "/"
  protocol = "http"
  restart_limit = 0
  timeout = "2s"

… which got rid of that error. However, I started getting this in the log instead:

13:30:00.000 [info] Plug.SSL is redirecting GET / to https://127.0.0.1 with status 301
13:30:15.000 [info] Plug.SSL is redirecting GET / to https://127.0.0.1 with status 301

If you’ve spent time messing about with Plug.SSL before, I think you can quickly figure out what I forgot here: I need to send appropriate headers for Plug.RewriteOn. I appended this after the timeout = "2s" line:

  [services.http_checks.headers]
    X-Forwarded-Proto = "https"

… and I think everything’s clean now!

1 Like

Glad to hear things went smoothly!

Unlike Cowboy, Bandit explicitly logs all errors, including cases where clients connect but never actually make an HTTP request (that’s the case you’re seeing here). I suspect that I’ll likely be making an exception to the ‘log all errors’ rule for this, as it comes up pretty frequently.

2 Likes