Skip to content

Instantly share code, notes, and snippets.

@chaffeqa
Forked from etozzato/puma.rb
Last active June 20, 2025 10:17
Show Gist options
  • Save chaffeqa/d6c6ac491d3e1824a2980607d796e4a8 to your computer and use it in GitHub Desktop.
Save chaffeqa/d6c6ac491d3e1824a2980607d796e4a8 to your computer and use it in GitHub Desktop.
A section of config/puma.rb that will automatically generate a self-signed X509 certificate and provide https in development
if Rails.env.development?
def os
@os ||= (
host_os = RbConfig::CONFIG['host_os']
case host_os
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
:windows
when /darwin|mac os/
:macos
when /linux/
:linux
else
:unknown
end
)
end
def install_cert_macos(cert_path)
puts "Installing certificate to macOS system keychain..."
system("sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain #{cert_path}")
end
def install_cert_linux(cert_path)
cert_dest = "/usr/local/share/ca-certificates/finalforms-dev.crt"
puts "Installing certificate to Linux system certificates..."
# Copy cert to the system certificate directory
system("sudo cp #{cert_path} #{cert_dest}")
system("sudo update-ca-certificates")
end
def install_cert_windows(cert_path)
puts "Installing certificate to Windows certificate store..."
# Use PowerShell to import the certificate
ps_script = "Import-Certificate -FilePath '#{cert_path.gsub('/', '\\')}' -CertStoreLocation Cert:\\LocalMachine\\Root"
system("powershell -Command \"Start-Process powershell -Verb RunAs -ArgumentList '-Command #{ps_script}'\"")
end
FileUtils.mkdir_p(Rails.root.join('config', 'certs'))
key_path = Rails.root.join('config', 'certs', 'development.key')
crt_path = Rails.root.join('config', 'certs', 'development.crt')
unless File.exist?(key_path) && File.exist?(crt_path)
def cert_domain
'localhost' # Setting[:cookie_domain] || 'localhost'
end
def generate_cert(key, subject)
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = 0x0
cert.subject = cert.issuer = subject
cert.public_key = key.public_key
cert.not_before = Time.now
# never have to renew it
cert.not_after = Time.now + 100.years
extend_and_sign(cert, key)
end
def extend_and_sign(cert, key)
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = ef.issuer_certificate = cert
cert.add_extension(ef.create_extension('keyUsage', 'digitalSignature', true))
cert.add_extension(ef.create_extension('extendedKeyUsage', 'serverAuth', true))
cert.add_extension(ef.create_extension('subjectAltName', "DNS.1:#{cert_domain},DNS.2:*.#{cert_domain}", true))
cert.sign(key, OpenSSL::Digest.new('SHA256'))
end
begin
subject = OpenSSL::X509::Name.parse("/L=Los Angeles/C=US/O=AINZ/OU=TOP/ST=CA/CN=#{cert_domain}")
key = OpenSSL::PKey::RSA.new(2048)
FileUtils.rm key_path, force: true
file = File.new(key_path, 'wb')
file.write(key)
file.close
cert = generate_cert(key, subject)
FileUtils.rm crt_path, force: true
file = File.new(crt_path, 'wb')
file.write(cert)
file.close
rescue StandardError => e
Rails.logger.warn "An error occurred creating the SSL certificate in development: #{e.message}.. Skipping SSL!"
FileUtils.rm key_path, force: true
FileUtils.rm crt_path, force: true
end
end
if File.exist?(key_path) && File.exist?(crt_path)
puts "SSL certificate created successfully at #{crt_path} with key at #{key_path}."
case os
when :macos
install_cert_macos(crt_path)
when :linux
install_cert_linux(crt_path)
when :windows
install_cert_windows(crt_path)
else
puts "Unsupported operating system. Please install the certificate manually:"
puts "Certificate location: #{cert_path}"
end
ssl_bind '0.0.0.0', ENV.fetch("PORT", '3001'), {
key: key_path,
cert: crt_path,
}
end
end
@etozzato
Copy link

Brilliant!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment