fly.toml health checks and Rails config.hosts

Note: I’ve changed my URL to foo.fly.dev and IP/port to x.x.x.x:x below.

Problem (via fly logs):

2024-06-27T00:54:43Z health[2865945fe95498] syd [error]Health check on port 3000 
has failed. Your app is not responding properly.
2024-06-27T00:54:53Z app[2865945fe95498] syd [info]E, [2024-06-27T00:54:53.520223 #323] ERROR -- : [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: x.x.x.x:x

Solution (in config/application.rb):

    config.hosts << "foo.fly.dev"
    config.hosts << "x.x.x.x:x"

When I first tried to fly deploy it hung on the health check because the Rails config did not allow the IP/port that was used when trying to hit the health endpoint, defined in config/routes.rb as:

  get "up" => "rails/health#show", :as => :rails_health_check

So firstly I commented-out the entire checks section of the fly.toml config:

[checks]
[checks.status]
port = 3000
type = 'http'
interval = '10s'
timeout = '2s'
grace_period = '5s'
method = 'GET'
path = '/up'
protocol = 'http'
tls_skip_verify = false

[checks.status.headers]
X-Forwarded-Proto = 'https'

By prepending each line with a #

Then I was able to deploy without issue. After uncommenting that section though I still found I had a problem and when I checked fly logs I could see the problem above.

My question is will my IP address for my app change? If so then I’ll have to keep updating my config to allow each new IP/port. I could also use a regex rule if there’s a set range that Fly.io uses? Is there another way around this or a better solution?

First, just a guess. Are you trying to run your Rails app in development mode? That’s not recommended.

Your IPv6 address may change over time if your app is moved to another host. That is something that is done from time to time. But you really shouldn’t have an issue with blocked hosts.

If you are willing to experiment, create a second application. You can delete it when done:

rails new demo --minimal
cd demo
echo 'Rails.application.routes.draw { root "rails/welcome#index" }' >> config/routes.rb
fly launch

Press enter when you see:

? Do you want to tweak these settings before proceeding? (y/N)

Unless you are running Ruby 3.3.3, things should just work. If you are running 3.3.3, add the following:

bin/rails generate dockerfile --force
fly deploy

If you check your logs, you may see a line like the following before puma starts, but it is benign:

2024-06-27T01:26:22Z health[90801679a10038] iad [warn]Health check on port 3000 is in a 'warning' state. Your app may not be responding properly.

Once puma starts, you should see:

2024-06-27T01:26:29Z health[90801679a10038] iad [info]Health check on port 3000 is now passing.

If you reproduce these steps, the question to be resolved is what is the difference in the configuration of these two applications?

Thanks @rubys I just found the solution.

Just as I was spinning up a minimal Rails app as per your suggestion, I googled to find the page about the config.hosts and why it’s a good idea:

I noticed it had a config.host_authorization part and so checked my code for this and found this in config/environments/production.rb:

  # Skip DNS rebinding protection for the default health check endpoint.
  # config.host_authorization = { exclude: ->(request) { request.path == "/up" } }

After uncommenting the second line above and also removing the now unnecessary Fly host IP/port from my config.hosts in config/application.rb, I did another fly deploy and things worked fine!

Hopefully this will help others out there trying to deploy Rails apps! It’s probably a noob mistake on my part being relatively new to the framework, but it’s also nice to know these security measures are baked into the configuration.

1 Like

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