Search code examples
ruby-on-railsrubyruby-on-rails-3sslwebrick

Run rails on secure (https) and redirect non secure(http) request to secure through webricks


I am using the below environments:

Server: Webrick
Rails: 3.2.6
Ruby: 1.9.3p555

I have added the below code in /script/rails :

require 'rails/commands/server'
require 'rack'
require 'webrick'
require 'webrick/https'

if ENV['SSL'] == "true"
  module Rails
      class Server < ::Rack::Server
          def default_options
              super.merge({
                  :Port => 3000,
                  :environment => (ENV['RAILS_ENV'] || "production").dup,
                  :daemonize => false,
                  :debugger => false,
                  :pid => File.expand_path("tmp/pids/server.pid"),
                  :config => File.expand_path("config.ru"),
                  :SSLEnable => true,
                  :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
                  :SSLPrivateKey => OpenSSL::PKey::RSA.new(
                                   File.open("certs/project.key").read),
                  :SSLCertificate => OpenSSL::X509::Certificate.new(
                                   File.open("certs/project.crt").read),
                  :SSLCertName => [["CN", WEBrick::Utils::getservername]],
              })
          end
      end
  end
end

APP_PATH = File.expand_path('../../config/application',  __FILE__)
require File.expand_path('../../config/boot',  __FILE__)
require 'rails/commands'

I have added the below line in /config/environments/production.rb:

config.force_ssl = true

Now I have tried the below attempts:

  1. Start rails on 3000

    SSL=true rails s -e production -p 3000

It runs rails on https://project.com but 404 error on http://project.com

  1. Start rails on 443 and mentioned the same port in script:

    rvmsudo rails s -p 443

  2. Start rails on 80 and 443 both using two different pid:

    rvmsudo rails s -p 80 -P PID1 rvmsudo rails s -p 443 -P PID2

4.Finally I have tried to forward request to 3000 from 443 and 80:

sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
sudo iptables -t nat -I PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 3000

Also I have tried to run same thing with thin gem as well but results are same.


Solution

  • At the risk of getting flamed and downvoted...

    Having a hammer and only seeing everything as a nail isn't a valid plan. Sometimes when faced with a screw you have to find a screwdriver.

    Webrick is the worst available option for a rails web server and should only be used if absolutely necessary. Its too simple to put thin or puma in your Gemfile and move along in a happier, thread-safier world.

    In that regard here is your nine step plan to sanity.

    Step 1: Stop.

    Step 2: Think a bit.

    Step 3: Realize best practices are there for a reason, e.g. perfect forward secrecy, load balancing to proxied rails apps, static asset serving.

    Step 4: Decide to stop reinventing the wheel and take the time to learn your craft.

    Step 5: Install nginx via your distribution's repos

    Step 6: Change default nginx host to serve your domain via SSL.

    Step 7: Add puma to your Gemfile, and bundle update

    Step 8: Setup puma init.d or upstart file so it persists across reboots

    Step 9: Profit