Unable to serve multiple rails applications with Nginx + Unicorn - ruby-on-rails

I know this is a very common issue, but I've been struggling days with a strange one this time:
I want to serve two Rails 4 apps on the same VPS (ubuntu 14.04). I followed this guide for one app with success. My app1 is working fine. But not app2.
The error is this one (/var/log/nginx/error.log):
directory index of "/srv/app1/public/app2/" is forbidden
General nginx.conf
# Run nginx as www-data.
user www-data;
# One worker process per CPU core is a good guideline.
worker_processes 1;
# The pidfile location.
pid /var/run/nginx.pid;
# For a single core server, 1024 is a good starting point. Use `ulimit -n` to
# determine if your server can handle more.
events {
worker_connections 1024;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay off;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
gzip_http_version 1.1;
gzip_proxied any;
gzip_min_length 500;
gzip_types text/plain text/xml text/css
text/comma-separated-values text/javascript
application/x-javascript application/atom+xml;
##
# Unicorn Rails
##
# The socket here must match the socket path that you set up in unicorn.rb.
upstream unicorn_app2 {
server unix:/srv/app2/tmp/unicorn.app2.sock fail_timeout=0;
}
upstream unicorn_app1 {
server unix:/srv/app1/tmp/unicorn.app1.sock fail_timeout=0;
}
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
sites-available/app1
server {
listen 80;
server_name _
public.ip.of.vps; # Replace this with your site's domain.
keepalive_timeout 300;
client_max_body_size 4G;
root /srv/app1/public; # Set this to the public folder location of your Rails application.
location /app1 {
try_files $uri #unicorn_app1;
}
location #unicorn_app1 {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded_Proto $scheme;
proxy_redirect off;
# This passes requests to unicorn, as defined in /etc/nginx/nginx.conf
proxy_pass http://unicorn_app1;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
auth_basic "Restricted"; #For Basic Auth
auth_basic_user_file /etc/nginx/.htpasswd; #For Basic Auth
}
location ~ ^/assets/ {
#gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
}
# You can override error pages by redirecting the requests to a file in your
# application's public folder, if you so desire:
error_page 500 502 503 504 /500.html;
location = /500.html {
root /srv/app1/public;
}
}
sites-available/app2
server {
listen 80;
server_name __
public.ip.of.vps; # Replace this with your site's domain.
keepalive_timeout 300;
client_max_body_size 4G;
root /srv/app2/public; # Set this to the public folder location of your Rails application.
location /app2 {
try_files $uri #unicorn_app2;
}
location #unicorn_app2 {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded_Proto $scheme;
proxy_redirect off;
# This passes requests to unicorn, as defined in /etc/nginx/nginx.conf
proxy_pass http://unicorn_app2;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
auth_basic "Restricted"; #For Basic Auth
auth_basic_user_file /etc/nginx/.htpasswd; #For Basic Auth
}
location ~ ^/assets/ {
#gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
}
# You can override error pages by redirecting the requests to a file in your
# application's public folder, if you so desire:
error_page 500 502 503 504 /500.html;
location = /500.html {
root /srv/app2/public;
}
}
Why is that nginx is looking for app2 in the public folder of app1?

The problem is that your 2 nginx server blocks are listening to the same domain name.
Move the location blocks /app2 and unicorn_app2 into site-available/app1
And delete site-available/app2
This answer shows an example.

Related

Nginx won't run after symlink creation

Nginx runs fine with an empty sites-enabled directory, but then I create the symlink with
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/,
and restarting nginx fails. I type nginx -T, and the culprit is
2020/06/29 20:24:19 [emerg] 4087#4087: duplicate upstream "appname" in /etc/nginx/sites-available/default:1
, which is clearly caused my symolink, so I'm not sure what I did wrong.
The original problem I'm trying to fix is getting my EC2 instance to serve my API instead of the default "Welcome to nginx!" page.
Deleting the symlink lets nginx run normally. Here is a shortened version of my output of nginx -T when it works:
# configuration file /etc/nginx/nginx.conf:
user root;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 20000;
# multi_accept on;
}
http {
disable_symlinks off;
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;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
include /etc/nginx/sites-available/*;
...
}
# configuration file /etc/nginx/sites-available/default:
upstream appname {
# Path to Puma SOCK file, as defined previously
server unix:/home/ubuntu/appname/shared/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80 ipv6only=on default_server;
# server_name domain.tld www.domain.tld;
server_name ec2...compute.amazonaws.com www.ec2...compute.amazonaws.com
root /home/ubuntu/appname/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_pass http://ec2...us-east-2.compute.amazonaws.com;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
access_log /home/ubuntu/appname/log/nginx.access.log;
error_log /home/ubuntu/appname/log/nginx.error.log;
}
location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
I'm pretty new to this so I assume it's something basic, but I've been on this for hours and I'm not sure what to do. Also, if it helps, I'm using puma for my application server.

Nginx not rendering puma application

I'm trying to serve my rails application using Puma and Nginx. When ever I got to the page it renders the default nginx page. I've tried with two different configurations. This first fails with "upstream" directive is not allowed here. The second warns Starting nginx: nginx: [warn] conflicting server name "localhost" on 0.0.0.0:80, ignored
(1) overwrite nginx.conf
nginx.conf
upstream puma {
server unix:///home/deploy/apps/exelon-api/shared/tmp/sockets/rails-api-puma.sock;
}
server {
listen 80 default_server deferred;
# server_name example.com;
root /home/deploy/apps/rails-api/current/public;
access_log /home/deploy/apps/rails-api/current/log/nginx.access.log;
error_log /home/deploy/apps/rails-api/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;
}
(2) using sites enabled
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_requests 100;
keepalive_timeout 65;
gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_proxied any;
gzip_vary off;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/rss+xml application/atom+xml text/javascript application/javascript application/json text/mathml;
gzip_min_length 1000;
gzip_disable "MSIE [1-6]\.";
variables_hash_max_size 1024;
variables_hash_bucket_size 64;
server_names_hash_bucket_size 64;
types_hash_max_size 2048;
types_hash_bucket_size 64;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
sites-enable/rails-api_production
upstream puma_rails-api_production {
server unix:/home/deploy/apps/rails-api/shared/tmp/sockets/rails-api-puma.sock fail_timeout=0;
}
server {
listen 80;
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 504 /500.html;
error_page 503 #503;
server_name localhost rails-api.local;
root /home/deploy/apps/rails-api/current/public;
try_files $uri/index.html $uri #puma_rails-api_production;
location #puma_rails-api_production {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma_rails-api_production;
# limit_req zone=one;
access_log /home/deploy/apps/rails-api/shared/log/nginx.access.log;
error_log /home/deploy/apps/rails-api/shared/log/nginx.error.log;
}
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location = /50x.html {
root html;
}
location = /404.html {
root html;
}
location #503 {
error_page 405 = /system/maintenance.html;
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html break;
}
rewrite ^(.*)$ /503.html break;
}
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
return 405;
}
if (-f $document_root/system/maintenance.html) {
return 503;
}
location ~ \.(php|html)$ {
return 405;
}
}
Second error practically says that you have two server sections defined with listen 80 (which practically means 0.0.0.0:80 where 0.0.0.0 is equal to "any address") and localhost in server_name.
So, action you have to take depends on what you want to achieve:
Have some other app as default
If you want to have your app to be accessible alongside some other apps you have (or want to have in future) on server by some hostname, let's say example.com, you have to simply remove localhost from server_name in the entry you added.
In this case, you will have to access your app by one of the names you have specified for it in server_name ( example.com), neither localhost nor server IP.
Note that if you still have to make sure domain you've specified resolves to the server address.
If it is on your own local machine and you want to be able to access your app for development purposes (testing how it works with nginx, for example) you can
add row 127.0.0.1 name.here (for example, 127.0.0.1 example.com).
If it is on some server you own and you want others to be able to access app by the same domain, you have to buy/register it (if it has not been registered by someone else yet, it happens) and create the A DNS record pointing to your app server IP.
Make your app default
If you want this app to be default on the server, you can:
Find other server sections defined with listen 80 default; (so, if they don't have default or listen any other port like 8080 or 443 you can safely leave them) and remove the default from there - there can be only one default server section per port and IP combination.
Change listen 80; in your server section to listen 80 default;. This will tell nginx that you want this server section to handle all requests not catched by other section.
This will allow you to access app by IP and point any domain to it without specifying it in server_name section. You still need to register or buy domain to be able to point it to app.

Ruby process running at max CPU usage and not serving any page - Ubuntu Nginx Unicorn Rails Configuration

I am following this guide to setup Rails service using Nginx and Unicorn http://ariejan.net/2011/09/14/lighting-fast-zero-downtime-deployments-with-git-capistrano-nginx-and-unicorn/
When I started Nginx without Unicorn I get 502 Bad Gateway error
and as soon as I start the Unicorn server using the following command unicorn_rails -c config/unicorn.rb -D the request times out and I get 504 Gateway Time-out error. The CPU usage for ruby process is 100% and seems like something is stuck in a loop but I do not understand what is happening
nginx/1.2.6 (Ubuntu)
This is my /etc/nginx/nginx.conf
user ubuntu staff;
# Change this depending on your hardware
worker_processes 4;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay off;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
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_vary on;
gzip_proxied any;
gzip_min_length 500;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml applicat
ion/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
and this is my /etc/nginx/sites-available/default
upstream home {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
# for UNIX domain socket setups:
server unix:/tmp/home.socket fail_timeout=0;
}
server {
# if you're running multiple servers, instead of "default" you should
# put your main domain name here
listen 80;
# you could put a list of other domain names this application answers
server_name patellabs.com;
root /home/ubuntu/apps/home/current/public;
access_log /var/log/nginx/home_access.log;
rewrite_log on;
location / {
#all requests are sent to the UNIX socket
proxy_pass http://home;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
# if the request is for a static resource, nginx should serve it directly
# and add a far future expires header to it, making the browser
# cache the resource and navigate faster over the website
# this probably needs some work with Rails 3.1's asset pipe_line
location ~ ^/(images|javascripts|stylesheets|system)/ {
root /home/ubuntu/apps/home/current/public;
expires max;
break;
}
}

RoR - nginx issue when trying to deploy with unicorn

I'm beginner in Ruby on Rails and have some difficulties to deploy my rails application (with nginx + unicorn). I don't know what's going on, but here is the kind of errors I get in log files when I launch nginx :
2013/04/14 00:31:42 [error] 14469#0: *1 connect() to unix:/home/user/www/sahitoo/shared/sockets/unicorn.sock
**failed (111: Connection refused)** while connecting to upstream, client: XX.XXX.XX.XX, server: myapp.com,
request: "GET / HTTP/1.1", upstream: "http://unix:/home/user/www/sahitoo/shared/sockets/unicorn.sock:/",
host: "www.XXXXX.com"
If you could help to find out the problem, or at least give me some advices to track it, that would be very nice !!
Thanks a lot.
I also post nginx.conf file :
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
events {
worker_connections 768;
multi_accept on;
}
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_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
upstream sahitoo {
server unix:/home/kar/www/sahitoo/shared/sockets/unicorn.sock;
}
}
With
/etc/nginx/sites-enabled/sahitoo file :
server {
listen 80;
server_name myapp.com;
access_log /var/log/nginx/sahitoo.access.log;
error_log /var/log/nginx/sahitoo.error.log;
root /www/sahitoo/public;
# direct to maintenance if this file exists
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html last;
break;
}
location / {
proxy_redirect http://sahitoo/ /;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# If the file exists as a static file serve it directly
if (-f $request_filename) {
break;
}
if (!-f $request_filename) {
proxy_pass http://sahitoo;
break;
}
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/kar/www/sahitoo/public;
}
}
This would happen if you are running ruby on a different user, possibly root and it doesn't have any privilege on current user, are you sure you are getting results from
'ruby -v' or 'rails -v'
.
I would suggest to take a look at this working example nginx.conf :
upstream unicorn-your_app {
server unix:/tmp/unicorn.your_app.sock fail_timeout=0;
}
server {
listen 80;
server_name myapp.com;
root /www/sahitoo/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #unicorn-yourapp;
location #unicorn-yourapp {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn-your_app;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
As you can see there are some differents:
upstram block;
root points to your_dir/current/public;
try_files routine;
location #unicorn-yourapp;
If you would like to get a deeper understanding at the topic, there is very nice Railscast.

How can I get nginx to serve static files from two locations when also serving a unicorn rails server?

Ok, so I have pretty much the standard nginx config for serving a unicorn rails server (listens to a socket file and also serves static files from the rails_app/public directory).
However, I want to do the following:
serve static files from
rails_app/public (as currently is
done)
serve static files with url /reports/ from a different root (like /mnt/files/)
I tried adding the following to my nginx config:
location /reports/ {
root /mnt/matthew/web;
}
but it didn't work.
Any ideas how I can get this to happen?
(below is my entire nginx.conf file:
worker_processes 1;
pid /tmp/nginx.pid;
error_log /tmp/nginx.error.log;
events {
worker_connections 1024; # increase if you have lots of clients
accept_mutex off; # "on" if nginx worker_processes > 1
# use epoll; # enable for Linux 2.6+
# use kqueue; # enable for FreeBSD, OSX
}
http {
# nginx will find this file in the config directory set at nginx build time
include mime.types;
# fallback in case we can't determine a type
default_type application/octet-stream;
# click tracking!
access_log /tmp/nginx.access.log combined;
sendfile on;
tcp_nopush on; # off may be better for *some* Comet/long-poll stuff
tcp_nodelay off; # on may be better for some Comet/long-poll stuff
gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/html text/xml text/css
text/comma-separated-values
text/javascript application/x-javascript
application/atom+xml;
# this can be any application server, not just Unicorn/Rainbows!
upstream app_server {
server unix:/home/matthew/server/tmp/unicorn.sock fail_timeout=0;
}
server {
# enable one of the following if you're on Linux or FreeBSD
listen 80 default deferred; # for Linux
# listen 80 default accept_filter=httpready; # for FreeBSD
client_max_body_size 4G;
server_name _;
keepalive_timeout 5;
location /reports/ {
root /mnt/matthew/web;
}
# path for static files
root /home/matthew/server/public;
try_files $uri/index.html $uri.txt $uri.html $uri #app;
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_server;
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root public;
}
}
}
location #app is looking for the files in /home/matthew/server/public, as that's the parent root specified. If your try files statement is matching files in location /reports/ that has a different root, those files won't be found. You need to set things up like this:
location /reports/ {
root /mnt/matthew/web;
try_files $uri/index.html $uri.txt $uri.html $uri #foo;
}
root /home/matthew/server/public;
try_files $uri/index.html $uri.txt $uri.html $uri #app;
location #foo {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
root /mnt/matthew/web
}
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_server;
}

Resources