subdir in nginx for rails api-app - ruby-on-rails

I am trying to configure the nginx to have a separate subdir for rails-5 api backend. (to separate frontend and backend)
Original, I am calling backend api under GET "/bills". Now I'd like to be it: GET '/api/bills'. so all requests under 'api' should be redirected to rails app.
But I can't make it working. The redirection works, but I see on rails side in logs: ActionController::RoutingError (No route matches [GET] "/api/bills"). Of course this route doesn't exists. Rails only knows about the "/bills" route. Could I configure nginx so, that the redirection would be transparent to Rails, and it would see the request like [GET]"/bills" ?
here is my current config:
upstream app {
# Path to Unicorn SOCK file, as defined previously
server unix:/var/sockets/unicorn.myapp.sock fail_timeout=0;
}
server {
#redirect to https
listen 0.0.0.0:80;
listen [::]:80 ipv6only=on default_server;
server_name localhost; ## Replace this with something like gitlab.example.com
server_tokens off; ## Don't show the nginx version number, a security best practice
return 301 https://$server_name$request_uri;
access_log /var/log/nginx/app_access.log;
error_log /var/log/nginx/app_error.log;
}
server {
listen 0.0.0.0:443 ssl;
listen [::]:443 ipv6only=on ssl default_server;
server_name localhost; ## Replace this with something like gitlab.example.com
ssl on;
ssl_certificate /etc/ssl/nginx/host.crt;
ssl_certificate_key /etc/ssl/nginx/host.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
location ^~ /api {
#try_files $uri/index.html $uri $uri/;
try_files $uri/index.html $uri #app;
root /app/backend/public;
}
location #app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
error_page 500 502 503 504 /500.html;
}
location / {
# Application Frontend root, as defined previously
try_files $uri $uri/ =404;
root /app/frontend/;
}
client_max_body_size 4G;
keepalive_timeout 10;
}

Inside your location #app block try adding this:
rewrite ^/api(.*)$ $1 break;
That should just strip off the /api prefix before sending the remainder of the URI upstream.
See this document for details.

Related

Rails Application using Nginx working on HTTP but not HTTPS

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.

Rails 5, Nginx, Puma, Rails admin - ERR_TOO_MANY_REDIRECTS

I would like to know how to enforce SSL in a rails 5 app. The app works fine in development. In production some POST requests over SSL via rails admin do not work.
If SSL is enforced via production.rb, the browser returns:
"ERR_TOO_MANY_REDIRECTS"
And if "force_ssl" is set to false, some "POST" requests via rails admin return:
HTTP Origin header (https://www.example.com) didn't match request.base_url (http://www.example.com)
Thanks in advance.
These are the app settings:
production.rb
# ...
config.force_ssl = true
# ...
nginx.conf
upstream puma {
server unix:///home/bgc/apps/domain/shared/tmp/sockets/domain-puma.sock;
}
server {
listen 80;
listen 443 ssl;
server_name domain.com;
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domain.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
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;
root /home/bgc/apps/domain/current/public;
access_log /home/bgc/apps/domain/current/log/nginx.access.log;
error_log /home/bgc/apps/domain/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-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;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
keepalive_timeout 10;
}
The reason for this is pretty simple. When you are using the Nginx server with ssl, it will already sort out the ssl for you. If you remove config.force_ssl = true from production.rb and it will be sorted.

Rails app and Wordpress blog on the same server - how to configure nginx?

I have a DigitalOcean droplet. There's running a Rails 5 app on nginx and PostgreSQL database. I have installed PHP, MySQL, and Wordpress (WP to the /home/deployer/blog directory).
Here's my /etc/nginx/sites-available/default:
upstream unicorn {
server unix:/home/deployer/apps/myapp/shared/sockets/unicorn.myapp.sock fail_timeout=0;
}
server {
listen 443 ssl;
server_name myapp.com;
ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/ssl/certs/dhparam.pem;
return 301 https://www.myapp.com$request_uri;
}
server {
#listen 80 default deferred;
listen 443 ssl; # managed by Certbot
server_name www.myapp.com;
root /home/deployer/apps/myapp/current/public; # rails app
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location ~ ^/(robots.txt|sitemap.xml.gz)/ {
root /home/deployer/apps/myapp/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 $http_host;
proxy_set_header X-Forwarded-Proto https; # added because of looping
proxy_redirect off;
proxy_pass http://unicorn;
}
# I added this blog for the WP blog
location /blog {
index index.php;
try_files $uri $uri/ /blog /index.php?$args;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/ssl/certs/dhparam.pem;
if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot
}
When I restart nginx after modifying this config file and go to www.myapp.com/blog, I only receive the Rails error page saying The page you were looking for doesn't exist.
I found quite a lot of articles how to modify the nginx config in order to make the WP blog working on a subdomain, but still cannot find the right recipe for me.
Any idea what I am doing wrong and why nginx doesn't load WP and instead of that still only the Rails app?

Get infinite redirect loop with Rails 4, NGinx and puma [duplicate]

This question already has answers here:
https redirect for rails app behind proxy?
(2 answers)
Closed 7 years ago.
I implemented an SSL certificate for my Rails 4 app, with NGinx and puma. I used the following nginx.conf file:
upstream puma {
server unix:///home/deploy/apps/bestpark/shared/tmp/sockets/bestpark-puma.sock;
}
server {
listen 80;
server_name lebonparking.fr;
rewrite ^/(.*) https://lebonparking.fr/$1 permanent;
}
server {
listen 443;
server_name lebonparking.fr;
ssl on;
ssl_certificate /home/deploy/apps/bestpark/current/certificates/lebonparking.fr.crt;
ssl_certificate_key /home/deploy/apps/bestpark/current/certificates/lebonparking.fr.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;
root /home/deploy/apps/bestpark/current/public;
access_log /home/deploy/apps/bestpark/current/log/nginx.access.log;
error_log /home/deploy/apps/bestpark/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 it works fine when accessing https:// URLs. But the links of the app don't use the HTTPS protocol so I added config.force_ssl = true in config/environments/production.rb :
Rails.application.configure do
...
config.force_ssl = true
...
end
But then get:
This webpage has a redirect loop
From my browser! I looked for many sources (including https://www.digitalocean.com/community/tutorials/how-to-create-an-ssl-certificate-on-nginx-for-ubuntu-14-04 and https://gist.github.com/rkjha/d898e225266f6bbe75d8) but don't know exactly which line I missed. Any help?
You'll need to set a header so that rails knows it's getting the traffic through https. Checkout this answer

Nginx HTTPS issue to redirect from www to non-www

I need to configure nginx for one of my rails application to route some pages through SSL but facing problem with configuration.
I've a SSL certificate where common name is example.com and my site is routing to example.com from www.example.com
Here is my nginx.conf:
upstream unicorn {
server unix:/tmp/unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
return 301 $scheme://example.com$request_uri;
ssl on;
ssl_certificate /certificate path;
ssl_certificate_key /key path;
}
server {
listen 80 default deferred;
root /public path;
try_files $uri/index.html $uri #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
client_max_body_size 50M;
}
I've tried different configuration as well but nothing work. Any suggestion would be appreciated. Thanks in advance for that.
Not sure if this help.
I have had a same problem. I struggle with it for a longtime until I redirect from ApplicationController
In the ApplicationController:
before_filter :redirect_subdomain
def redirect_subdomain
if request.host == 'www.example.com.au'
redirect_to 'https://example.com.au' + request.fullpath
end
end
My issue has been resolved by doing modifications below, answering this as it might help someone else:
Removed ssl_certificate and ssl_certificate_key from default_server block.
Removed URL overwriting from SSL server block.
Added ssl_protocols and ssl_ciphers to SSL server block
The configuration look like below after modification:
upstream unicorn {
server unix:/tmp/unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
listen 80 default_server;
root /example.com/current/public;
try_files $uri/index.html $uri #unicorn;
......
}
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl on;
ssl_certificate /example.com.crt;
ssl_certificate_key /example.com.key;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
......
}

Resources