Rails Application using Nginx working on HTTP but not HTTPS - ruby-on-rails

I have been trying to get my application working in production. I was able to access the site before changing config.force_ssl = true in my config\environments\production.rb.
I have seen many others with this problem need to add proxy_set_header X-Fowarded-Proto https;
I have tried adding this in my /etc/nginx/sites-available/default but haven't seen a difference.
My full default is below:
upstream puma {
server unix:///home/deploy/apps/appname/shared/tmp/sockets/appname-puma.sock;
}
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
root /var/www/html;
index index.html index.htm index.nginx-debian.html
server_name appname.com www.appname.com
try_files $uri/index.html $uri #puma;
location #puma {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
}
After making changes I reloaded nginx using sudo service nginx reload followed by sudo service nginx stop and sudo service nginx start
Am I missing something?
EDIT:
I updated my default and removed the config.force_ssl = true:
upstream puma {
server unix:///home/kiui/apps/appnamw/shared/tmp/sockets/appname-puma.sock;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
keepalive_timeout 70;
server_name appname.com www.appname.com;
ssl on;
ssl_certificate /root/appname.com.chain.cer;
ssl_certificate_key /root/appname.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
root /home/deploy/apps/appname/current/public;
access_log /home/deploy/apps/appname/current/log/nginx.access.log;
error_log /home/deploy/apps/appname/current/log/nginx.error.log info;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #puma;
location #puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
}
I can now access the site with http but not https.

Could you try the following:
upstream puma {
  server unix:///home/deploy/apps/appname/shared/tmp/sockets/appname-puma.sock;
}
server {
 listen 80;
 server_name appname.com www.appname.com;
 return 301 https://$host$request_uri;
}
server {
  # SSL configuration
  ssl on;
 listen 443 ssl;
 ssl_certificate path-to-your-crt-file;
 ssl_certificate_key path-to-your-key-file;
 server_name appname.com www.appname.com;
...
}

My problem was where I was adding the code above. I was adding it in default rather than nginx.conf. Moving the code above solved the problem.

Related

Nginx SSL working but sending request as http

I followed Deploying a Rails App on Ubuntu 14.04 with Capistrano, Nginx, and Puma to deploy a Rails app to Digital Ocean.
It suggested to keep nginx.conf (/etc/nginx/sites-enabled/medical-app) as
upstream puma {
server unix:///home/myappuser/apps/medical-app/shared/tmp/sockets/medical-app-puma.sock;
}
server {
listen 80 default_server deferred;
# server_name example.com;
root /home/myappuser/apps/medical-app/current/public;
access_log /home/myappuser/apps/medical-app/current/log/nginx.access.log;
error_log /home/myappuser/apps/medical-app/current/log/nginx.error.log info;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #puma;
location #puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
keepalive_timeout 10;
}
and than I added domain and than installed SSL using let's encrypt
which changed the nginx.conf (/etc/nginx/sites-enabled/medical-app) as following
upstream puma {
server unix:///home/myappuser/apps/medical-app/shared/tmp/sockets/medical-app-puma.sock;
}
server {
listen 80 default_server deferred;
# server_name example.com;
root /home/myappuser/apps/medical-app/current/public;
access_log /home/myappuser/apps/medical-app/current/log/nginx.access.log;
error_log /home/myappuser/apps/medical-app/current/log/nginx.error.log info;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #puma;
location #puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
keepalive_timeout 10;
}
server {
# server_name example.com;
root /home/myappuser/apps/medical-app/current/public;
access_log /home/myappuser/apps/medical-app/current/log/nginx.access.log;
error_log /home/myappuser/apps/medical-app/current/log/nginx.error.log info;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #puma;
location #puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
keepalive_timeout 10;
server_name www.medtib.com medtib.com; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.medtib.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.medtib.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = medtib.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = www.medtib.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
server_name www.medtib.com medtib.com;
return 404; # managed by Certbot
}
Now https is working fine but if I enable force SSL through Rails config
config.force_ssl = true
Than it gives error page not working with message redirected too many times
and if I try to login with Facebook which requires https than it gives following error
I don't have idea about nginx etc.
You should forward X-Forwarded-Proto header to your application to inform your application which protocol used. (https, http)
Put the following:
proxy_set_header X-Forwarded-Proto $scheme;
Before:
proxy_pass http://puma;
It should do the trick.

NGINX showing blank page on http to https redirect

I have installed nginx (version 1.6.3) on my amazon ec2 server with unicorn, Rails 4.2.0 and Ruby 2.1.3. Amazon load balancing is enabled on my system. The domain looks like abc.example.com. If no redirection code is written on nginx conf file, then both https://abc.example.com and http://abc.example.com seem working. But when I try to redirect all http requests to https, then sometimes it works for few seconds and then appear blank page, and sometimes it appears blank page from the beginning. Sometimes it shows 503 error too. The redirection code is:
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
My nginx conf file looks like this:
user www-data;
worker_processes 4;
pid /run/nginx.pid;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 80;
listen 443 ssl;
client_max_body_size 4G;
server_name abc.example.com;
root '/var/www/html/example/public';
try_files $uri/index.html $uri.html $uri #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded_Proto $scheme;
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
proxy_redirect off;
proxy_pass http://unicorn;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/html/example/public;
}
}
}
So, how to resolve this issue?
Please move the redirection to its own block;
Can you please use this as your redirection:
server {
server_name domain.com.au;
server_tokens off;
return 301 https://$host$request_uri;
}
I prefer not to use IF Condition in Nginx unless I have to. See if this works if not we can work on it.
Also please remove listen 80; if everything suppose to go to ssl then you can forget port 80.
listen 443 default deferred;
try it and let me know if you need more help.
Can you please adjust this setting to fit yours then restart the Nginx:
upstream unicorn {
server unix:/tmp/unicorn.production_domain.sock fail_timeout=0;
}
server {
server_name domain.com;
server_tokens off;
return 301 https://$host$request_uri;
}
server {
listen 443 default deferred;
ssl on;
ssl_certificate /etc/ssl/SSL.crt;
ssl_certificate_key /etc/ssl/domain.com.key;
server_name domain.com.au;
root /var/www/public_html/production.domain.com;
access_log /var/www/public_html/production.domain.com/log/nginx.access.log;
error_log /var/www/public_html/production.domain.com/log/nginx.error.log ;
try_files $uri/index.html $uri #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
error_page 500 502 503 504 /public/500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
What do you have in your unicorn.rb?

SSL on Nginx causes redirect loop

I'm trying to setup SSL on a Digital Ocean VPS using Nginx. My server conf is like so:
upstream unicorn {
server unix:/home/ubuntu/apps/example/shared/sock/unicorn.example.sock fail_timeout=0;
}
server {
listen 80;
server_name www.example.com example.com;
rewrite ^/(.*) https://example.com/$1 permanent;
}
server {
listen 443;
include example_ssl;
server_name www.example.com;
rewrite ^/(.*) https://example.com/$1 permanent;
}
server {
listen 443;
include example_ssl;
server_name example.com;
root /home/ubuntu/apps/example/current/public;
try_files $uri/index.html $uri #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_pass http://unicorn;
}
location ~ ^/(assets)/ {
gzip_static on;
expires max;
add_header Cache-Control public;
#add_header Last-Modified "";
#add_header ETag "";
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 60;
}
The ssl info is in example_ssl:
ssl on;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_session_timeout 10m;
ssl_ciphers "AES256+EECDH:AES256+EDH";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
This is causing an endless redirect loop. Http requests are redirected to HTTPS as expected but all tries to https://example.com are being redirected back to HTTP.
I can't seem to figure out why the HTTPS requests are being redirected. I checked my SSL cert by going to www.digicert.com and everything came back saying it was successfully installed.
When I try from my terminal:
openssl s_client -connect example.com:443
I get the following error:
verify error:num=20:unable to get local issuer certificate
The cert I got from my client did not contain the intermediate certs, but from what I understand this should still work when trying to access the site from the browser.
If I change the server block to only listen for 80 and not use SSL the site is able to load successfully, but I need to use SSL only.
Also, this is hosting a Rails app with Unicorn web server. My unicorn.log is empty other than starting the webserver so am I correct that this is not touching my Rails configuration at all, just an issue with nginx/ssl cert configuration?
Thanks!
Try this:
upstream unicorn {
server unix:/home/ubuntu/apps/example/shared/sock/unicorn.example.sock fail_timeout=0;
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
include example_ssl;
server_name example.com;
root /home/ubuntu/apps/example/current/public;
try_files $uri/index.html $uri #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_pass http://unicorn;
}
location ~ ^/(assets)/ {
gzip_static on;
expires max;
add_header Cache-Control public;
#add_header Last-Modified "";
#add_header ETag "";
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 60;
}
You will need to remove "ssl on;" from your ssl include file, that is for older versions of nginx. You might have to modify this if you are using multiple ssl on a single IP.

nginx - configuration issue - production mode - code 403

I want to configure NGINX with Rails 4 and run my application in production mode. The problem is I get 403 code - command: rails s -e production and in browser typing localhost. Naturally I established 755 privileges for the whole files in my application folder. There is my nginx.conf below:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
# include /etc/nginx/conf.d/*.conf;
# include /etc/nginx/sites-enabled/*;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
client_max_body_size 50M;
# fastcgi_buffers 8 16k;
# fastcgi_buffer_size 32k;
# fastcgi_connect_timeout 300;
# fastcgi_send_timeout 300;
# fastcgi_read_timeout 300;
upstream proxy-user {
server 127.0.0.1:2000;
}
upstream thin_cluster {
server unix:/tmp/thin.0.sock;
# server unix:/tmp/thin.1.sock;
# server unix:/tmp/thin.2.sock;
}
server {
listen 80;
server_name localhost;
# access_log /var/log/nginx-access.log;
root /home/user/Apps/myapp/public;
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mp3|flv|mpeg|avi)$ {
try_files $uri #app;
}
location /home/user/Apps/myapp/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://proxy-user;
if (!-f $request_filename) {
proxy_pass http://proxy-user;
break;
}
}
}
server {
listen 443;
server_name _;
ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers HIGH:!ADH:!MD5;
access_log /var/log/nginx-access-ssl.log;
root /home/user/Apps/myapp/public;
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mp3|flv|mpeg|avi)$ {
try_files $uri #app;
}
location /home/user/Apps/myapp/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-FORWARDED_PROTO https;
proxy_set_header SSL_CLIENT_S_DN $ssl_client_s_dn;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://proxy-user;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
You kinda have few issues in your config, I'll write what I would have done and you tell me what ever questions you have, I'll assume that the server is on port 2000 because that's the upstream you used.
I'll also ignore the http block and only use the server and upstream blocks.
upstream rails {
server 127.0.0.1:2000;
}
server {
server_name domain.com; # or whichever
listen 80;
# ssl settings start
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# ssl settings end
root /home/user/Apps/myapp/public;
error_page 500 502 503 504 /50x.html;
access_log /var/log/nginx/domain-access.log;
error_log /var/log/nginx/domain-error.log;
location #pass_to_rails {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-FORWARDED_PROTO $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://rails;
}
location / {
try_files $uri $uri/ #pass_to_rails;
}
}
You should place this inside sites-available and symlink to sites-enabled if you are on a debian/ubuntu distro, or use /etc/nginx/conf.d if you are on another distro, to keep things tidy and maintainable.
also make sure to uncomment one of those lines depending on what you want to use
# include /etc/nginx/conf.d/*.conf;
# include /etc/nginx/sites-enabled/*;

Why is SSL redirect not working with force_ssl and Nginx?

I have a Rails 3.2.13 app that I am trying to configure SSL for with Nginx and Unicorn. I want to be able to tell some controllers and some controller actions to 'force_ssl' and to properly redirect. I have been able to get this working so that I can manually hit the app with 'https://foo.com' and things work. When I put 'force_ssl' into a controller action, let's say users#index:
class UsersController < ApplicationController
force_ssl
def index
# do some stuff
end
end
I would expect that if I navigate to 'http://foo.com/users' that it would redirect to 'https://foo.com/users'.
It does not.
Instead, it redirects to: 'https://unicorn_foo/users'. What am I missing?
nginx.conf:
upstream unicorn_foo {
server unix:/tmp/unicorn.foo.sock fail_timeout=0;
}
server {
listen 80 default;
server_name foo.com;
root /home/webuser/apps/foo/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #unicorn_foo;
location #unicorn_foo {
proxy_set_header X-Forwarded-Proto http;
proxy_pass http://unicorn_foo;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 5G;
keepalive_timeout 10;
send_timeout 240;
sendfile_max_chunk 5m;
}
server {
listen 443;
server_name foo.com;
root /home/webuser/apps/foo/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #unicorn_foo;
location #unicorn_foo {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn_foo;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 5G;
keepalive_timeout 10;
ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:-ADH:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP;
ssl_session_cache shared:SSL:10m;
send_timeout 240;
sendfile_max_chunk 5m;
}
First guess... the port 80 server block does not pass the host through, maybe that's it?
proxy_set_header Host $http_host;
The SSL block does, but if you start at the non-SSL side and Rails picks it up, it might not have the full header there?

Resources