How to pass a Rails route through an ember-CLI app - ruby-on-rails

I have a Rails app that has some controllers and views, but it also acts as the API back-end for an Ember-CLI app I have created. My problem is that I need to access a route that is defined in the Rails routes.rb but I believe the Ember-CLI app is preventing this route from being loaded in a web browser.
The Rails route looks like the following:
refile_app /attachments #<Refile::App app_file="/Users/myUserName/.rvm/gems/ruby-2.1.5/bundler/gems/refile-373d42114839/lib/refile/app.rb">
Another Rails route that isn't loading in the web browser is:
signup GET /signup(.:format) users#new
I need to be able to download an attachment, but I am unable to do so on the production box.
In my local dev environment I'm starting Rails with the following command:
rails s --binding 127.0.0.1
and I'm starting the ember-CLI app with the following command:
ember server --proxy http://127.0.0.1:300
In production, my nginx.conf looks like the following:
upstream puma_Kegcop {
server unix:///home/user/apps/Kegcop/shared/tmp/sockets/Kegcop-puma.sock;
}
server {
listen 80;
server_name kegcop.chrisrjones.com;
root /opt/ember/kegcop-web-frontend/dist;
access_log /home/user/apps/Kegcop/current/log/nginx.access.log;
error_log /home/user/apps/Kegcop/current/log/nginx.error.log;
# Proxy to our API
location /api {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_pass http://puma_Kegcop;
}
# UI, Ember app, Static Build
location / {
try_files $uri $uri/ /index.html?/$request_uri;
}
}

Related

Add URL Prefix to requests using nginx or rails

I'm trying to understand the best way to redirect all traffic for https://app.company.com/ to https://app.company.com/app
app.company.com is a rails 4.2 server which uses nginx to serve static assets and unicorn to handle the rails requests.
Should this redirect happen in nginx or rails?
Back story:
A few years ago I supported some rails apps that were installed on the intranet using URL Prefixing, like:
https://company.com/app1/
https://company.com/app2/
https://company.com/app3/
company.com ran an nginx server which routed traffic to each app server based on the url prefix.
Each app server runs nginx to serve static assets and unicorn as the rails server.
Recently a decision was made to hand management of the company.com server over to the parent company. As a result, a decision was made to route to each rails server by DNS using subdomains in place of nginx rules.
For now apps will be accessed using:
https://app1.company.com/app1/
https://app2.company.com/app2/
https://app3.company.com/app3/
Individual app servers are largely unchanged. They still run nginx and unicorn.
My main issue is understanding the best way to push traffic for the root to the url prefix
https://app1.company.com/ --> https://app1.company.com/app1/
The root route without the url prefix never reached the rails servers before.
UPDATE
Here is my nginx config file with original enhancement proposed by Vashed's answer.
I'm now curious if there is a refinement to this which would allow my config file to be independent of the server name like it was before.
upstream unicorn {
server unix:/tmp/unicorn.app1.sock fail_timeout=0;
}
server {
listen 80 deferred;
# ADDED THIS LOCATION BLOCK PER VASFED'S ANSWER
location = / {
rewrite ^ https://app1.company.com/app1;
}
location /app1/assets {
alias /var/www/application/current/public/app1/assets;
}
# Serve file uploads from nginx
location /app1/system {
alias /var/www/application/current/public/app1/system;
}
try_files $uri $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 1G;
keepalive_timeout 10;
}
You can issue a redirect using nginx:
server{
server_name app1.company.com;
listen 443 ssl;
# other setup
location = / {
rewrite ^ https://app1.company.com/app1/;
}
location / {
# as before
}
}

Rails app served via Passenger standalone behind an nginx proxy

I have two apps: /foo and /bar. In each of those folders I'm starting up passenger. For foo:
passenger start -d -e production -p 4000
And for bar:
passenger start -d -e production -p 4001
I then have nginx configured like so:
server {
listen 80 default_server;
server_name www.server.com;
root /var/www/html;
location /foo/ {
proxy_pass http://0.0.0.0:4000/;
proxy_set_header Host $host;
}
location /bar/ {
proxy_pass http://0.0.0.0:4001/;
proxy_set_header Host $host;
}
}
The apps are getting served up, but none of the links work. A link to the users#index action comes back as '/users' not '/foo/users'.
I've set config.relative_url_root in both apps, that helps with the assets but not the links.
I've tried with both the _url and _path methods, neither work.
This answer is close, but passenger_base_uri isn't a valid directive for stock nginx.
So then I followed the advanced configuration instructions for Passenger's nginx configuration and added passenger_base_uri = '/foo'; to my custom conf file and loaded it like so:
passenger start -d -e production -p 4000 --nginx-config-template nginx.conf.erb
Still no love, and I'm out of ideas. Has anyone done this before? It seems like a common way to deploy multiple apps in production.
More Thoughts (2015-06-05)
Adding passenger_base_uri = '/foo' to my nginx.conf.erb file hosts the application in TWO locations (which is odd to me, but whatever):
localhost:4000/
localhost:4000/foo/
The first doesn't have the correct resource links (i.e. it's just '/users') but has access to its assets.
The second has the correct resource links (e.g. '/foo/users') but doesn't have its assets (this is because it's looking for /foo/assets/* inside of its public folder, not just /assets/*). I believe that this is the way to go though, as I can change my proxy like this to get at the application:
location /foo/ {
proxy_pass http://0.0.0.0:4000/foo/;
proxy_set_header Host $host;
}
Does anyone else have any thoughts though? If I do this, it'll mean I'll have to rake my assets into public/foo for it to work. Not the end of the world, but it still seems weird.
For anyone else looking to do the same thing, here's what it was in the end:
Follow the Advanced Configuration to get a project specific nginx.conf.erb file.
Add a passenger_base_uri directive to that file for your app (e.g. passenger_base_uri = '/foo';)
In your config/environments/production.rb file move the location of the assets: config.assets.prefix = '/foo/assets'.
Start passenger passenger start -d -e production -p SOME_PORT --nginx-config-template nginx.conf.erb
In your nginx proxy configuration add a location directive for your app:
location /foo/ {
proxy_pass http://0.0.0.0:SOME_PORT/foo/;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host; # more robust than http_host
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # this ensures your app's env is correct
proxy_set_header X-Forwarded-Host $host;
# proxy_set_header X-Forwarded-Proto https; # add this if you always want the redirects to go to HTTPS
}
After that, (re)start your nginx proxy and you should be good at http://your_proxy/foo/.

Deploy rails app at sub uri of a domain

We have set up a production server for our rails app with Nginx and puma. We want to deploy our rails app at sub uri and on main domain we want to put wordpress for home page, pricing page etc.
How we configure our rails that it able to run on sub uri which have Devise gem as authentication. Will we need to change our routes for sub uri?
What will be the configuration for nginx and puma?
Thanks in advance!
First put your desired sub uri path in application.rb i.e. main
...
config.relative_url_root = "/main"
...
In config.ru, add these lines.
require ::File.expand_path('../config/environment', __FILE__)
map SampleApplication::Application.config.relative_url_root || "/" do
run Rails.application
end
In production.rb, add below line.
# Enable serving of images, stylesheets, and JavaScripts from an asset server
config.action_controller.asset_host = "YOUR_DOMAIN_NAME/main"
# ActionMailer Config
config.action_mailer.default_url_options = {
:host => "YOUR_DOMAIN_NAME",
:only_path => false,
:script_name => "/main"
}
In nginx configuration file, add these lines
location /main {
alias /var/deploy/sample_application/current/public;
try_files $uri #main;
}
location #main {
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://puma_sample_application;
}
No, you should not configure rails app at all.
In fact you can just change your nginx config.
It should proxy root domain requests to your wordpress app, and subdomain requests to your rails app.
Check out this question, to get config of nginx How configure nginx for rails app as subdomain?

Set public directory outside rails app

Is it possible to make public directory outside of main Rails App directory?
Schema
/apps/app1
/apps/app2
/apps/this_dir_wants_to_be_public
I need use it with several Rails and Non-Rails Applications to manage Uploads
Two ways I can think of:
First: if you are using nginx, you can configure it to first check your custom dir, and serve files from there if found, otherwise ask rails app for responce. Nginx config would look like this
upstream backend {
server localhost:3000;
}
server {
listen 80;
server_name whatever.com;
root /your_static_path;
try_files $uri $uri/index.html #backend;
location #backend {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://backend;
}
}
It is using nginx as a reverse proxy. You run thin server on 3000 port (or any other server you like), and nginx turns to it only if it could not find requested file in root directory.
Second: Just create symlinks
ln -s /apps/this_dir_wants_to_be_public /apps/rails_app/public
so /apps/this_dir_wants_to_be_public would be actual directory, and /apps/rails_app/public link to it. Seems absolutelly transparent for rails app and simple
Multiple public folders, single rails installation
use public.path
Symlinks may be the best approach in your case I think

nginx 403 forbidden error in Rails 4 (with no index.html file)

I'm following along with a Railscast http://railscasts.com/episodes/293-nginx-unicorn?view=asciicast about setting up Nginx and Unicorn on Vagrant, with one important difference. Ryan's making his application with Rails 3 (that has the default /public/index.html that Rails 4 only generates dynamically). After getting Nginx installed and running, we were able to see the default page on port 8080. We then created a basic config file for Nginx to put in the config directory of the rails application
/config/nginx.conf
server {
listen 80 default;
# server_name example.com;
root /vagrant/public;
}
and then removed the default page in sites enabled and symlinked to the configuration file
vagrant#lucid32:/etc/nginx/sites-enabled$ sudo rm default
vagrant#lucid32:/etc/nginx/sites-enabled$ sudo ln -s /vagrant/config/nginx.conf todo
After this, Ryan restarted nginx and was able to see the Rails index page at localhost:8080. However, when I visit localhost:8080, I'm getting a 403 Forbidden error.
403 Forbidden
nginx/1.1.19
Update
since Rails 4 doesn't have the public/index.html file anymore, I think the 403 error might be caused by that, as I learned from this blog post
http://www.nginxtips.com/403-forbidden-nginx/. It says to set autoindex to on (the default is off) in the config, but I'm not sure how to set it to get the Rails homepage to show.
When I did this
server {
listen 80 default;
root /vagrant/public;
location / {
autoindex on;
}
}
it got rid of the 403 permissions error (yay!), however, it's not showing the default Rails home page. Rather it's showing the directory structure so I'm wondering what the proper way to set it is.
If I try to set it to location/public, I get the 403 error again. Any ideas?
location /public {
autoindex on;
}
Update
Since I'm using Vagrant (virtual box), the app is in /vagrant, however setting the location to location/vagrant also results in a 403 error
location /vagrant {
autoindex on;
}
You'll need to pass the request from Nginx to Unicorn. You can do this like so:
server {
listen *:80;
root /vagrant/public;
location / {
# Serve static files if they exist, if not pass the request to rails
try_files $uri $uri/index.html $uri.html #rails;
}
location #rails {
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
}
You may have to change the proxy_pass url. By default, unicorn will listen on 127.0.0.1:8080 but, if you have changed that, then you will need to specify that port.

Resources