how to deploy angular plus rails on nginx? - ruby-on-rails

I am trying to configure my NGINX, I ham hosting both the Angular and the Rails server on the same instance and would like to know how to get them to work together on the same server. I have alreadt
My NGINX conf file:
#rails config
server {
listen 3000;
server_name www.mysite.com;
root /var/www/mysite/public;
try_files $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://mysite_prod;
proxy_intercept_errors on;
}
error_page 500 502 504 /500.html;
error_page 503 /503.html;
error_page 404 /404.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
#angular config
server {
listen 80;
listen [::]:80;
server_name www.mysite.com;
root /var/www/my_app/dist;
server_tokens off;
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html =404;
}
}
In my rails application, I have addded the IP to the Origins file
config/application.rb
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins 'localhost:3000', 'www.mysite.com', 'localhost:4200',
resource '*',
headers: :any,
expose: ['access-token', 'expiry', 'token-type', 'uid', 'client'],
methods: [:get, :post, :options, :put]
end
end
I get a cors error and the front end is unable to talk to the back end.
Error - 'has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value '
How do I get this to work?

I think you should not have two servers running. Only the Rails app should run and Angular app should just be the index.html file that the rails app serves.
Build the Angular app for distribution and replace the Rails' index file with the Angular app build artifacts. One you get this working look for options that enables you to perform this manual steps automatically.

Could not find too much in terms of documentation online for this combination on angular-rails-nginx. Figured it out based on similar apps people had built for react-rails-nginx. Finally this is what worked for me. Did not have any CORS issues etc.
nginx.conf
server {
listen 80;
listen [::]:80;
server_name mysite.com;
root /var/www/my_angular_app/dist;
server_tokens off;
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html =404;
}
location /api {
root /var/www/my_app/public;
proxy_pass http://my_app_prod;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}
Of course, this also means that all the api calls to the rails back-end should go through the route '/api/xxx' so nginx knows it has to route it to the rails app without having to host it on a different port.

Related

Nginx reverse proxy instead of directory listing

I'm trying to have nginx serve static content while reverse proxying everything else to a rails server.
All that works, except for the home page.
If I go to example.com I get a 403 error and the error log shows
2019/06/14 04:32:59 [error] 9746#9746: *1 directory index of "/var/www/html/" is forbidden
I want the request to be sent to the rails server as example.com/ instead of trying (and failing) to get a directory listing. The rails server should display a homepage instead. (side note: if I turn autoindex on I will get a directory listing)
Configuration is here:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
server_name example.com;
index index.html;
location / {
autoindex off;
root /var/www/html;
try_files $uri $uri/ #rails;
expires max;
access_log off;
}
location #rails {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:3000;
}
}
If you want to disable the index behaviour for all URIs, drop the $uri/ term from the try_files statement. For example:
location / {
try_files $uri #rails;
...
}
See this document for details.
Alternatively, add a new location block to specifically handle the URI /, for example:
location = / {
try_files nonexistant #rails;
}
See this document for details.
A fix for the homepage would be to add an exact location for the homepage, like so:
location = / {
try_files #rails =404;
}

How to deploy React front end + Rails api backend with nginx, capistrano and passenger

I am deploying an app with a React front end created using create-react-app and a Rails API as the backend. I do not know much about configuring web servers and proxies so I am not sure exactly how to get it to work in production. I am deploying the app to Ubuntu on an Amazon EC2 instance. Nginx is the web server. I need to configure it so that Nginx serves the static files from the client/build directory and then any requests made to /api go to the Rails app running on port 3001. Right now Nginx is serving the index.html and the Javascript is running properly but requests to /api are not going to the right place. Any thoughts on how to configure Nginx to do this? Here is my /etc/nginx/sites-enabled/default file:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mydomain.com;
passenger_enabled on;
rails_env staging;
root /home/ubuntu/app-name/current/client/build;
index index.html;
location /api {
proxy_pass http://127.0.0.1:3001;
}
}
What am I missing? How do I get the Rails app to run on port 3001 and have all requests to /api go there? Do I need a separate server block in this config?
I don't know if you already solved your issue and if this solution will apply to you but I think it might be useful for other people searching on this issue.
I am using Puma as the application server to run my rails 5 api.
This is the configuration file for my dev environment:
upstream app {
# Path to Puma SOCK file, here is where you make the connection to your application server
server unix:/path/to/your/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name mydomain.com;
# this is where my react-app is located
root /var/www/development/ram/public/;
index index.html index.htm;
# Serve the static content (React app)
location / {
try_files $uri /index.html =404;
}
location /api {
# Insert your public app path
root /your/rails-app/path/public;
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
So comparing, I think your problem might be solved by adding a root directive pointing to your rails api public directory
I hope this can give you some hints on how to configure yours
Here is my working nginx config
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 default_server;
root /home/deploy/www/sublime/current/public;
index index.html;
server_name domain.com;
access_log /home/deploy/www/sublime/logs/access.log;
error_log /home/deploy/www/sublime/logs/errors.log;
server_name localhost;
passenger_enabled on;
passenger_app_env production;
location ~* ^.+\.(jpeg|gif|png|jpg) {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
}
location /api {
# Insert your public app path
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri /index.html;
}
}
You can use this repos to see rails configuration
https://github.com/Eth3rnit3/rails-react

Rails 4.2 Deploy NGINX, Puma, Capistrano, RBenv with SSL - 403 errors

I am getting 403 Forbidden. I have checked my nginx/error.log and get directory index of /home/deploy/apps/myapp/current/public/ is forbidden
I have SSL and did a check on https://www.digicert.com/help/ and see my certificates are set up OK.
I am wondering if it could be be perhaps because I don't have any index.html file in my public folder. I am running on Rails 4.2. My public folder has assets, 404.html, 422.html, 500.html, favicon.ico and robots.txt.
My question is, should I be doing something to set up an index.html in my public folder that lets me use my /app/views/static_pages/home.html.erb (set up as root static_pages#home in my routes file)?
I would guess Nginx isn't liking that there is not an index.html to find.
I also went into my static pages controller and added:
def home
render :file => 'public/index.html'
end
This is my nginx config file without SSL
upstream puma {
server unix:///home/laurie/apps/creativehub/shared/tmp/sockets/creativehub-puma.sock;
}
server {
listen 80 default_server deferred;
server_name creativecalgary.ca www.creativecalgary.ca;
root /home/laurie/apps/creativehub/current/public;
access_log /home/laurie/apps/creativehub/current/log/nginx.access.log;
error_log /home/laurie/apps/creativehub/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;
}
This is my first Rails deploy. I am deploying on a digital ocean droplet using SSH on Cloud9 (with capistrano, puma, and nginx).

Sidekiq UI is not loading assets - 404 not found

I am having rails 4.1 application running with sidekiq on production. I have deployed it using nginx + unicorn. Also I have mounted sidekiq UI as follows,
mount Sidekiq::Web => '/sidekiq'
but since last few days when ever I try to access sidekiq UI, all assets of sidekiq returning 404, not found. But it was working previously fine. But not able to find what leads 404.
Here is my settings
nginx+unicorn settings for my app
upstream sample_app {
server unix:/tmp/sample_app.sock fail_timeout=0;
}
server {
listen 80;
server_name www.sample_app.com;
root /home/deploy/applications/sample_app/current/public;
# set expire to all assets
location ~* \.(?:ico|css|js|gif|jpe?g|png|svg)$ {
expires max;
}
try_files $uri/index.html $uri #sample_app;
location #sample_app {
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://sample_app;
}
error_page 500 502 503 504 /500.html;
error_page 404 413 /404.html;
client_max_body_size 50M;
keepalive_timeout 10;
}
After debugging, I able to solve it by adding following line
# set expire to all assets
location ~* \.(?:ico|css|js|gif|jpe?g|png|svg)$ {
expires max;
try_files $uri #sample_app;
}

Error Messages Showing in Production - Ruby on Rails 3.1, Nginx, Unicorn

I have a Rails 3.1 app running in production using Nginx and Unicorn. And for some reason, my custom 404 and 500 html error pages are not showing. Instead I'm getting the actual error message ("Routing Error", for example).
In my production.rb file, I have config.consider_all_requests_local = false
And on the same server with a nearly identical configuration, I have a 'staging' site that works just fine. The only difference, as far as I can tell, is that the production one has SSL while the staging does not.
Here is the Nginx config for the production app:
upstream unicorn_myapp_prod {
server unix:/tmp/unicorn.myapp_prod.sock fail_timeout=0;
}
server {
listen 80;
server_name myapp.com;
root /home/deployer/apps/myapp_prod/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control 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_redirect off;
proxy_pass http://unicorn_myapp_prod;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
server {
listen 443 default;
ssl on;
ssl_certificate /home/deployer/apps/myapp_prod/shared/ssl_certs/myapp_prod.crt;
ssl_certificate_key /home/deployer/apps/myapp_prod/shared/ssl_certs/myapp_prod.key;
server_name myapp.com;
root /home/deployer/apps/myapp_prod/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn_myapp_prod;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
Any ideas? Thanks!
The https listener's location #unicorn block is missing the X-Forwarded-For directive.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
It's in your http listener, but not the https listener.
Assuming that Rails' force_ssl is successfully redirecting all of the http requests and your only errors are happening on https requests, it seems that would explain it.
Also, to be very clear, there is a well known problem in Rack/Rails3 with respect to routing errors, which you specifically mention.
https://rails.lighthouseapp.com/projects/8994/tickets/4444-can-no-longer-rescue_from-actioncontrollerroutingerror
If you're using haproxy along with nginx and unicorn (e.g. you're on Engineyard), this fix won't be enough. You'll need to override Rails with something like this:
class ActionDispatch::Request
def local?
Rails.env != 'production'
end
end
Good luck!
not sure if this is applicable but we also have a link in our nginx config after the error_page line which handles the location of the /500.html pages
location = /500.html { root /path/to/rails/app/public; }
obviously substitute the path to rails app portion with your path.

Resources