Ruby on Rails Thin and force_ssl, empty response over HTTP - ruby-on-rails

I've set up several Ruby on Rails servers lately on CentOS 7.x using Thin as the web server and an SSL Certificate from Comodo.
I have enabled the force_ssl option in my config/environments/production.rb file, and I'm running my server with the command:
RAILS_ENV=production thin start -a <IP> -p 3000 --ssl --ssl-key-file <KEY FILE PATH> --ssl-cert-file <CERT FILE PATH>
I'm using devise, so in config/initializers/devise.rb I set
config.rememberable_options = { secure: true }
I also set some config in config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, key: '_secure_<domain>_session', httponly: true, secure: true
When I first access my server over HTTP from an internet browser I get an empty response message (tested with multiple browsers and multiple computers). When I access it over https directly it resolves fine (and SSL is working perfectly), and when I next try to access over http it redirects just fine. I'm not certain what I can do to fix this bar using nginx or Apache.
Here are the other questions I've read:
Rails with thin and ssl: http request not auto-redirected to https
Ruby on rails: force_ssl not redirecting from http to https when using thin start --ssl

Thin can only listen on one port and can only serve either SSL or non-SSL requests per instance. When thin is started with --ssl it attempts to process inbound connections as TLS connections, and will drop those which it can't negotiate (ie, plain HTTP requests).
You need to use nginx (or some other reverse proxy) to listen on multiple ports and terminate SSL, and then forward to Thin. Otherwise, you'll need to run multiple Thin instances, one serving SSL and the other not.

Related

Rails with thin and ssl: http request not auto-redirected to https

Recently I wanted to secure my rails 4.2.1 app with https the easiest way. I found this question as well as this answer about WEBrick+SSL, both referencing to this post which is unfortunately not reachable any more. Then I found this answer recommending to use thin instead (naming other advantages of using thin). Then I followed this step-by-step guide, finally running thin start --ssl --ssl-key-file .ssl/key.pem --ssl-cert-file .ssl/cert.pem -e production with self-signed certificate. My config/environments/production.rb contains config.force_ssl = true.
Now I would like to access the web normally by typing example.com expecting to be automatically redirected to https://example.com but this does not happen. Typing looong https://example.com works fine. Here is a 2-year-old question with similar issue but any answer doesn't work either and something could have also changed since then.
How can I make it work? Or is there any different recent but simple enough way to start using ssl with rails? Thanks!
In your config/environment/production.rb file make sure you have the following:
config.force_ssl = true
Also make sure to update your cookie settings in config/initializers/session_store.rb:
Rails.application.config.session_store :cookie_store, key: '_secure_domain_session', httponly: true, secure: true
You also need to specify secure: true in the config/initializers/devise.rb file if you are using Devise
Also make sure to clear the cache on your browser
If you have a load balancer in front of your website that is terminating the TLS/SSL and then connecting via HTTPS to the backend, this would mean the connection from the load balancer to your server is HTTPS, even though the client connection to the load balancer is not. Your load balancer should send the X-Forwarded-Proto header which Rails should take into account.
If you are running Rails under Passenger inside Nginx (or Apache), you may need to configure that to forward the header and/or port.
passenger_set_header X-Forwarded-Proto $http_x_forwarded_proto;
passenger_set_header X-Forwarded-Port $server_port;
Note, however, that Rails looks first at the HTTPS environment variable before it looks at the header, and that might be set to "on" because connection to your web server is HTTPS.
In that case you can redirect all traffic from HTTP to HTTPS inside Nginx:
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$uri permanent;
}

Why my app asks to choose to authenticate myself for my Rails app with HTTPS?

Env
Rails 4.0.4
Using SSL certificates for HTTPS connections
In my config/environments/production.rb
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true
This is how I start my server:
thin start -e production -d -p 3001 -P ./tmp/pids/thin_https.pid --ssl --ssl-key-file /etc/ssl/current/www_domain_io.key --ssl-cert-file /etc/ssl/current/WWW.DOMAIN.IO.crt
Then I am getting this screen when accessing my production website:
I click OK, and I land on my page https://www.domain.io page successfully. The entity is verified and the https: show in green. So I am good ... but why do I get that "Select a certificate to authenticate to www.domain.io:443` ? I figured that once my entity was verified I should land automatically on my page ? Any ideas?
UPDATE
The documention shows --ssl-disable-verify option that is actually not available on thin 1.6.2 codename Doc Brown
SSL options:
--ssl Enables SSL
--ssl-key-file PATH Path to private key
--ssl-cert-file PATH Path to certificate
--ssl-disable-verify Disables (optional) client cert requests <=== this is NOT available
I have posted an issue on github
Thin lighthouse ticket about --ssl-disable-verify
Existing ticket on GitHub
I just don't understand how to get the version of thin where this option is available.
A similar post on SO suggests your .crt file includes the root CA certificate for your certificate chain. Remove it, and you should be good to go.
Intermediate certifcates should still remain in the .crt file, presumably.
You're starting your thin server on port 3001, but you're connecting to the regular https URL, which by default connects to port 443. So I assume you have a web server instance (Apache/nginx) proxying requests for thin.
If that's the case, you should disable SSL for thin, as this will be handled by the proxy server in front of your thin instance.
If you don't have a reverse proxy, and want to use just thin, you should specify the port where thin is listening in the URL (https://example.com:3001).

Development Rails server that's compatible with both HTTP and HTTPS

My application isn't quite ready to go full SSL so in the meantime, I am allowing SSL but not requiring it. I do require SSL for certain controllers and force redirects to HTTPS for actions in such controllers.
I can start a thin server using SSL via thin start --ssl. This works great for SSL testing. However, I cannot have HTTP and HTTPS running simultaneously on the same port. Obviously, this makes testing redirects from HTTP to HTTPS quite frustrating. I can run an Apache or nginx server on top but I don't really want to go through the trouble of doing that in my development environment.
To start two servers, one for SSL and without, I use foreman like so:
web: rails server
ssl: thin start --ssl -p 3001
This starts the HTTP server on port 3000 and HTTPS server on 3001. Now my question is. How do I create a "smart redirect" policy only on my development environment only such that redirects from HTTP to HTTPS intelligently changes the port from 3000 to 3001? Thanks!

Using Thin Web Server with HTTP and HTTPS

I'm using the Thin web server to serve my Rails app.
Starting the server with thin start serves http requests.
Starting the server with thin start --ssl serves https requests.
Is there a way to have thin serve both http and https requests concurrently?
The reason I ask is because when I use redirect_to some_path in my controllers, they redirect to http. Since thin is serving https requests, nothing is rendered.
Note: I'm using Rack::SSL in Rails 3.0.7.
(Comment converted to answer as requested.)
Simplest option is probably to run two separate instances of thin: one accepting SSL requests and one accepting plaintext requests. Any reason you don't want to do this? (Alternatively, if thin is running behind another web server, like Apache or Nginx, you only need one instance of thin: the frontend server can report whether the request came in over SSL.)
You can't accept both HTTP and HTTPS connections on the same port. (This is why, by default convention, HTTP runs on port 80 whereas HTTPS runs on port 443.)
you can use foreman (https://github.com/ddollar/foreman);
You create a Procfile with 2 process then start both with forman start command.
put this on a file called Procfile:
web: thin start
ssl: thin start --ssl
Then use foreman start and he start the 2 process.
This is how i am using... hope this helps you!

Rack ssl not working with Thin

I installed rack ssl for Rails 3.07 per these instructions: http://www.simonecarletti.com/blog/2011/05/configuring-rails-3-https-ssl/
It is not working. The first https request (for the login page) is made and the page is served securely, but when you login it redirects to a non-secure http URL.
I am running Thin server. Does it work for Thin? What about Webrick?
Any ideas? Thanks.
For Thin, you can pass your SSL information in using the following options:
$ thin --help
SSL options:
--ssl Enables SSL
--ssl-key-file PATH Path to private key
--ssl-cert-file PATH Path to certificate
--ssl-verify Enables SSL certificate verification
If you would like to configure Webrick to use SSL, this article from this question seems to work.

Resources