I'm setting up a Rails application with Puma, I can't seem to make it serve over HTTPS. I've tried maybe fifteen different guides and stack over flow answers, but neither of them have worked for me. Now, I can't serve regular HTTP either, even when reverting the configuration.
What I've tried:
config/puma.rb
port ENV.fetch("PORT") { 3000 }
my_key = "#{File.join(Rails.root, 'public', '.well-known', 'privkey.pem')}"
my_crt = "#{File.join(Rails.root, 'public', '.well-known', 'cert.pem')}"
ssl_bind(
'mydomain.com',
3000,
key: my_key,
cert: my_crt,
verify_mode: 'peer'
)
mydomain.com
is of course replaced by the proper domain name.
config/application.rb
config.force_ssl = true
I've put my certificate and private key in public/.well-known
. The files were generated using Certbot.
Folder contents:
cert.pem
chain.pem
fullchain.pem
privkey.pem
The files were generated using Certbot.
The resulting error message is as follows:
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?>
What am I doing wrong?
-
Also, when resetting my configuration and testing out the site, I get the same error message. What can be done about that?
SOLUTION: Check out the comments in the reply by Jan Vítek to see how this was solved.
I see a few problems here:
/public
path. It is not much private there.whatever.domain
. It can bring many problems. If there is a NAT the app has no interface to bind to. If there is the server's FQDN in /etc/hosts
it would bind to the localhost interface a you wouldn't be able to access it from the internet. If it actually bound to the interface with IP resolved from that domain, you might have problems accessing the app locally. Just change it to 0.0.0.0
for now and when you have it working you can experiment with this attribute.peer
would verify client certificates. I'm not sure if it is your intention but it would require :ca
option to be passed to ssl_bind()
with a path to your CA certificateAnyway I created a new Rails 7 application, placed my crt and key to config/ssl/
and modified only the config/puma.rb
#config/puma.rb
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
port ENV.fetch("PORT") { 3000 }
ssl_bind '0.0.0.0', 3001, {
key: 'config/ssl/dev.mydomain.com.key',
cert: 'config/ssl/fullchain.cer',
verify_mode: 'none'
}
environment ENV.fetch("RAILS_ENV") { "development" }
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
plugin :tmp_restart
Then simple rails s
and I am able to connect to https://dev.mydomain.com:3001
. Make sure to explicitly call https://
.