Kamal: Are you trying to open an SSL connection to a non-SSL Puma?

Using Kamal 2.2.2 and Rails 7.2.1. After running kamal deploy I am getting

INFO [53229d8c] Running **docker exec kamal-proxy kamal-proxy deploy find-a-coach-web --target="861f2b0e8501:3000" --host="www.findacoach.eu" --tls --deploy-timeout="30s" --drain-timeout="30s" --buffer-requests --buffer-responses --log-request-header="Cache-Control" --log-request-header="Last-Modified" --log-request-header="User-Agent"** on 168.119.124.201

ERROR Failed to boot web on 168.119.124.201

INFO First web container is unhealthy on 168.119.124.201, not booting any other roles

HTTP parse error, malformed request: #<Puma::HttpParserError: Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?>

And relevant config files

Dockerfile

EXPOSE 80 443 3000

deploy.yml

proxy:
  ssl: true
  host: www.findacoach.eu
  # kamal-proxy connects to your container over port 80, use `app_port` to specify a different port.
  app_port: 3000

and production.rb

# Assume all access to the app is happening through a SSL-terminating reverse proxy.
  # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies.
  # config.assume_ssl = true

  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  config.force_ssl = true

  # Skip http-to-https redirect for the default health check endpoint.
  # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }

Hi Stanislav,

I had the same issue and adding both assume_ssl and force_ssl to production fixed it for me.

config.assume_ssl = true
config.force_ssl = true

There’s an issue for this:

Also make sure to expose an /up endpoint e.g. routes: get ‘/up’, to: ‘health#up’

class HealthController < ApplicationController
  skip_before_action :authenticate_user!, only: [:up]

  def up
    render json: { status: 'UP' }, status: :ok
  end
end

Right, if you use force_ssl and you have SSL termination on a load balancer / kamal-proxy / thruster, anything sitting in front of PUMA, then you need to use assume_ssl too which is a very simple middleware that forces the right headers like X-Forwarded-Proto https

And Rails 7.2.1 will have

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

Available for the health check side.

SOLVED. Thank you Lucas.