Rails 8 I always get a bad gateway 502 when the machine starts

This is the log from the error

2024-12-09T14:08:01.032 app[080e207b56d668] gru [info] INFO Checking filesystem on /data
2024-12-09T14:08:01.034 app[080e207b56d668] gru [info] /dev/vdc: clean, 15/65280 files, 8911/261120 blocks
2024-12-09T14:08:01.036 app[080e207b56d668] gru [info] INFO Mounting /dev/vdc at /data w/ uid: 1000, gid: 1000 and chmod 0755
2024-12-09T14:08:01.039 app[080e207b56d668] gru [info] INFO Resized /data to 1069547520 bytes
2024-12-09T14:08:01.048 app[080e207b56d668] gru [info] INFO Preparing to run: `/rails/bin/docker-entrypoint ./bin/thrust ./bin/rails server` as 1000
2024-12-09T14:08:01.057 app[080e207b56d668] gru [info] INFO [fly api proxy] listening at /.fly/api
2024-12-09T14:08:01.166 runner[080e207b56d668] gru [info] Machine started in 1.039s
2024-12-09T14:08:01.167 proxy[080e207b56d668] gru [info] machine started in 1.04619947s
2024-12-09T14:08:01.275 health[080e207b56d668] gru [warn] Health check on port 8080 is in a 'warning' state. Your app may not be responding properly.
2024-12-09T14:08:01.362 app[080e207b56d668] gru [info] 2024/12/09 14:08:01 INFO SSH listening listen_address=[fdaa:2:f8b7:a7b:136:4a0b:c00e:2]:22 dns_server=[fdaa::3]:53
2024-12-09T14:08:03.663 proxy[080e207b56d668] gru [error] [PC01] instance refused connection. is your app listening on 0.0.0.0:8080? make sure it is not only listening on 127.0.0.1 (hint: look at your startup logs, servers often print the address they are listening on)
2024-12-09T14:08:04.020 app[080e207b56d668] gru [info] {"time":"2024-12-09T14:08:04.020557015Z","level":"INFO","msg":"Server started","http":":8080"}
2024-12-09T14:08:04.480 proxy[080e207b56d668] gru [info] machine became reachable in 3.312728333s
2024-12-09T14:08:04.482 app[080e207b56d668] gru [info] {"time":"2024-12-09T14:08:04.482316024Z","level":"INFO","msg":"Unable to proxy request","path":"/","error":"dial tcp 127.0.0.1:3000: connect: connection refused"}
2024-12-09T14:08:04.482 app[080e207b56d668] gru [info] {"time":"2024-12-09T14:08:04.482508604Z","level":"INFO","msg":"Request","path":"/","status":502,"dur":1,"method":"GET","req_content_length":0,"req_content_type":"","resp_content_length":0,"resp_content_type":"text/plain; charset=utf-8","remote_addr":"2a02:26f7:e506:4000:5415:b76b:f740:ee45, 2a09:8280:1::54:1384:0","user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1.1 Safari/605.1.15","cache":"miss","query":""}
2024-12-09T14:08:04.799 health[080e207b56d668] gru [error] Health check on port 8080 has failed. Your app is not responding properly.
2024-12-09T14:08:04.806 app[080e207b56d668] gru [info] => Booting Puma
2024-12-09T14:08:04.806 app[080e207b56d668] gru [info] => Rails 8.0.0 application starting in production
2024-12-09T14:08:04.806 app[080e207b56d668] gru [info] => Run `bin/rails server --help` for more startup options
2024-12-09T14:08:06.175 app[080e207b56d668] gru [info] Puma starting in single mode...
2024-12-09T14:08:06.176 app[080e207b56d668] gru [info] * Puma version: 6.5.0 ("Sky's Version")
2024-12-09T14:08:06.176 app[080e207b56d668] gru [info] * Ruby version: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [x86_64-linux]
2024-12-09T14:08:06.176 app[080e207b56d668] gru [info] * Min threads: 3
2024-12-09T14:08:06.176 app[080e207b56d668] gru [info] * Max threads: 3
2024-12-09T14:08:06.176 app[080e207b56d668] gru [info] * Environment: production
2024-12-09T14:08:06.176 app[080e207b56d668] gru [info] * PID: 347
2024-12-09T14:08:06.178 app[080e207b56d668] gru [info] * Listening on http://0.0.0.0:3000
2024-12-09T14:08:06.179 app[080e207b56d668] gru [info] Use Ctrl-C to stop

And this is my fly.toml file, it was generated by flyctl

app = 'david-on-rails'
primary_region = 'gru'
console_command = '/rails/bin/rails console'

[build]

[env]
  DATABASE_URL = 'sqlite3:///data/production.sqlite3'
  HTTP_PORT = '8080'
  PORT = '8080'

[[mounts]]
  source = 'data'
  destination = '/data'

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = 'stop'
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

[checks]
  [checks.status]
    port = 8080
    type = 'http'
    interval = '10s'
    timeout = '3s'
    grace_period = '15s'
    method = 'GET'
    path = '/up'
    protocol = 'http'
    tls_skip_verify = false

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

[[vm]]
  memory = '512mb'
  cpu_kind = 'shared'
  cpus = 1

It seems like the proxy forwards the request before the rails server is ready. After the machine is ready, everything works as expected.

Tru deteling from your dockerfile:

“./bin/thrust”

Longer answer, now that I’m back home: thruster is designed to solve problems that don’t apply here at fly.io:

  • HTTP/2 support
  • Automatic TLS certificate management with Let’s Encrypt
  • Basic HTTP caching of public assets
  • X-Sendfile support and compression, to efficiently serve static files

This wouldn’t be a problem, but it appears that unlike other proxies, thruster will accept requests prior to verifying that the software that it is intended to proxy is ready. Which wouldn’t be a problem if it held on to those requests until rails started, but it doesn’t do that either.

Oh, and I neglected to mention that if you remove thruster, you will need to update your fly.toml to route requests directly to Rails:

internal_port = 3000
1 Like

It is working, after removing thruster and changing the http port. For those using rails 8 who are having the same problem, check my config below

fly.toml

app = 'your-app-name-here'
primary_region = 'gru'
console_command = '/rails/bin/rails console'

[build]

[env]
  DATABASE_URL = 'sqlite3:///data/production.sqlite3'
  HTTP_PORT = '3000'

[[mounts]]
  source = 'data'
  destination = '/data'

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = 'stop'
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

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

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

[[vm]]
  memory = '512mb'
  cpu_kind = 'shared'
  cpus = 1

Dockerfile

ARG RUBY_VERSION=3.3.0
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base

# Rails app lives here
WORKDIR /rails

# Install base packages
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 && \
    rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
ENV RAILS_ENV="production" \
    BUNDLE_DEPLOYMENT="1" \
    BUNDLE_PATH="/usr/local/bundle" \
    BUNDLE_WITHOUT="development"

# Throw-away build stage to reduce size of final image
FROM base AS build

# Install packages needed to build gems
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential git pkg-config && \
    rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle install && \
    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
    bundle exec bootsnap precompile --gemfile

# Copy application code
COPY . .

# Precompile bootsnap code for faster boot times
RUN bundle exec bootsnap precompile app/ lib/

# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile




# Final stage for app image
FROM base

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
COPY --from=build /rails /rails

# Run and own only the runtime files as a non-root user for security
RUN groupadd --system --gid 1000 rails && \
    useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
    chown -R rails:rails db log storage tmp
USER 1000:1000

# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]

EXPOSE 80
EXPOSE 3000

CMD ["./bin/rails", "server"]

Thanks for the help!

2 Likes

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