Deploy rails app at sub uri of a domain - ruby-on-rails

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?

Related

Proxied Rails app relative_url_root not prefixing url helpers

So I have Nginx proxying a rails app with the following config
location ^~ /admin {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://admin/;
}
which has the affect of re-writing all requests to http://localhost/admin/XXX/YYY/ZZZ => http://admin/XXX/YYY/ZZZ
so next I ran into the issue of assets urls not pointing at the proxied app, so config.relative_url_root = '/admin' did the trick
Next problem is every link generated by link_to returns a link based at / not /admin which I would believe config.relative_url_root would change... Now I am sort of correct, If i go to rails console then include Rails.application.routes.url_helpers then call say root_path or management_path, I receive /admin and /admin/management. Perfect!
Now this is where I get rather confused. All the routes generated in my views disregard the prefix set by config.relative_url_root...
Why is this configuration option working in the console environment but not in the view environment?
config.relative_url_root is located in my application.rb
Rails 5.1.5
This resolution is not quite what I was hoping for but in the meantime it works.
/config.ru
map ENV['RAILS_RELATIVE_URL_ROOT'] || "/" do
run Rails.application
end
/nginx.conf
location ^~ /admin {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://HC_admin/admin;
}
All that changed is that the app itself now thinks it is running at /admin or whatever you set RAILS_RELATIVE_URL_ROOT to. This in my mind defeats the purpose of parts of your app being separated as you still need to configure where its mounted.
Found some instructions in a gist, here

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

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;
}
}

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/.

nginx does not forward to my rails app

I am rather new to using nginx. I want to use it to serve static content in order to reduce the load on the rails server. It seems to be a rather simple task but I just can't find a solution that works for me.
I want nginx to serve static files which exist in the public directory inside my rails application directory. To be more precise: I got an index.html inside the directory I want to get served when entering http:/[domainname]. Instead I just get the default nginx index.html. I already checked that thin is running and when I query 127.0.0.1:3000 I get the page I want.
So here's the file called [domainname] in the sites-available directory.
upstream rails {
server 127.0.0.1:3000; #This is where thin is waiting for connections
}
# HTTP server
server {
listen 80;
server_name [domainname];
set $app /home/projektor/website/app.[domainname];
root $app/public;
# Set a limit to POST data
client_max_body_size 8M;
# Errors generated by Rails
error_page 400 /400.html;
error_page 422 /422.html;
error_page 500 504 /500.html;
# Errors generated *outside* Rails
error_page 502 #502;
error_page 503 #503;
# If the public/system/maintenance.html file exists,
# return a 503 error, that ...
if (-f $document_root/system/maintenance.html) {
return 503;
}
# ... will serve the very same file. This construct
# is needed in order to stop the request before
# handing it to Rails.
location #503 {
rewrite ^ /system/maintenance.html break;
}
# When a 502 error occurs - that is, Rails is not
# running, serve the 502.html file
location #502 {
rewrite ^ /502.html break;
}
# Add client-side caching headers to static files
#
location ~ ^/(stylesheets|javascripts|images|system/avatars) {
expires 720h;
}
# Hand over the request to Rails, setting headers
# that will be interpreted by request.remote_ip,
# request.ssl? and request.host
#
location / {
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 http;
proxy_set_header Host $http_host;
proxy_redirect off;
# If the file exists as a static file serve it directly
if (-f $request_filename) {
break;
}
# Oh yeah, hand over the request to Rails! Yay! :-D
proxy_pass http://rails;
}
}
The file is based on this one.
Thanks for your help.
Edit:
I already exchanged 127.0.0.1:3000 for 0.0.0.0:3000 in the upstream part. I also checked the the ownership of the files in sites-available and sites-enabled and they should both be ok.
I hardcoded return 503; into the location instruction and it seems that it never matches. It seems that it always matches the precreated default configuration.
Take a look at the Mongrel example from the try_files documentation. Something like this should work:
location / {
try_files /system/maintenance.html $uri $uri/index.html $uri.html #thin;
}
location #thin {
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 http;
proxy_set_header Host $http_host;
proxy_redirect off;
# Oh yeah, hand over the request to Rails! Yay! :-D
proxy_pass http://rails;
}
When I set up a recent version of NGINX, the solution to getting it to point properly to my rails app had everything to do with fully, and properly configuring it. There were a few extra steps I didn't find in the documentation. It was acting just as yours is. I don't have a clean install to go off of, but bear with me here.
I set a directory called sites-enabled in the default install location. This is a debian install from apt repository, so the install loccations are /etc/nginx and /var/nginx.
mkdir /etc/nginx/sites-enabled /etc/nginx/sites-available
Place conf file for site in sites-available/
Add this line to the bottom of /etc/nginx/nginx.conf
include /etc/nginx/sites-enabled/*;
Look for and remove any reference that may include the DEFAULT configuration, which is telling nginx to actually load this file. Which is what gives you the nginx default index.html (/etc/nginx/conf.d/default.conf)
grep -r "default.conf" /etc/nginx
Symlink (man ln) your file in sites-available to sites-enabled.
ln -s /etc/nginx/sites-available/myfilename /etc/nginx/sites-enabled/myfilename
Test your configuration.
/etc/init.d/nginx configtest
Once your configuration is set up properly, restart nginx
/etc/init.d/nginx restart
I can't remember if I removed this reference or including the line in step 2 was enough. If you update or comment on this answer and give me the results, I can try to dig up the other steps I took.
I don't think the problem here is your actual configuration.

Rails/Unicorn deploy: what creating the Unix socket?

I am deploying a Rails 2.3 // Spree app with Capistrano/Unicorn/Foreman/Upstart.
The part that I cannot figure out is how to have the /myapp/shared/sockets/unicorn.sock be automatically created by the foreman/upstart process management (at least that I think the unix socket should come from them).
What's responsible for creating the unix socket?
Let's say your configuration is nginx + unicorn . As you probably know , in the config dir you should create a file named unicorn.rb . In this file there is a description how to handle non-static requests , something like this :
upstream unicapd {
server unix:/tmp/capd.sock fail_timeout=0;
}
I've named the upstream differently than stated in tutorials , this gives me ability to host a number different applications on the same host .
Then , in your vhosts dir on the Nginx configuration you put something like this (let's say your host file is 'vhosts/myconf.conf':
location #unicorn1 {
proxy_pass http://unicapd;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
Here you see the instruction to nginx to serve non-static requests from the place , named "http://unicapd" , which is related to your unicorn.rb config file . This configuration is triggered by a file , which is in your init.d (in case you're running Debian) directory .
Summary : When you say bundle exec unicorn --restart , the script in your init.d triggers the code , forming a "special" file /tmp/capd.sock , which serves the dynamic content from you Rails app.
Path to unix-socket configured in unicorn's config:
...
listen "/home/user/app/shared/sockets/unicorn.sock", :backlog => 64
...
Then in nginx.conf:
location / {
try_files $uri #unicorn;
proxy_cache cache;
proxy_cache_valid 10m;
}
location #unicorn {
proxy_set_header Client-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://unix:/home/user/apps/shared/sockets/unicorn.sock;
}
When application will be started, unicorn create socket-file in setted path (user must have write access to this path)

Resources