Properly route to server-containing gems proxied as directories in nginx - ruby-on-rails

I have several applications running on different ports of a development server and use nginx as a reverse proxy.
Some of these apps are Rails applications and some are gems that come packaged with a preconfigured server (e.g. mailcatcher, gollum, sinatra). I can't find a configuration to set the proper paths for static assets.
Consider a request made to http://oh.no/gem which serves content from http://oh.no:666
Since the gem points to files at the root of the site (e.g. '/images/wth.jpg') they never load. With Rails apps, I generally change the root directive in nginx and appropriately configure the apps files, but that method lacks elegance and is a PITA when toying with gems.
With Rails applications, I'm familiar with adding directives to allow Passenger to handle a sub-URI elegantly, but I don't know a noninstrusive solution for apps loaded by other servers. What additions/deletions would I need to make to the following to serve the assets?
location /gem {
proxy_pass http://localhost:666/;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Related

.Net core POST API in NGINX reverse proxy throws error 404

This is my first time posting a question. Kindly let me know if I am missing something that needs to be shared.
I am trying to POST some data into database through my C# APP and API (separately build), but it throws error 404 only for the POST API. All other pages work fine and so does the GET request. The app and API have been deployed on a LINUX machine through NGINX reverse proxy server. Both of them work on HTTP protocol. The feature works for localhost, but not for IP dependent URL.
Here is the content of service file for the app, I do not know what is missing in it. Please take care of the "/" as well where ever it is needed. While performing RnD, I found that the POST request in NGINX gets redirected to GET, I don't know if this will be helpful or not, but felt like sharing.
server {
listen myIP:6002;
server_name attendancepp;
root /home/user/net-core/Publish/AttendanceModule/AttendanceApp;
location /AttendanceApp/{
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://myIP:6002/;
proxy_set_header Accept-Encoding "";
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
The app works on the URL http://myIP:6002/attendance/allPages . All the pages are accessible without any issue. Just the POST part is not working.
Thank you, in advance.
working fine after commenting
try_files $uri $uri/ =404
cd /etc/nginx/sites-available/
sudo nano default << nginx
edit file then CTR+X and 'y' for yes
sudo systemctl restart nginx

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

Is it possible to run a Rails app and React app on the same domain?

I have a scenario where I want to build a site which would serve as a CMS and social network. All along I would be using Rails only as my API provider. I was originally going to do the client side entirely in React with Redux but as the build grew I found myself writing tons of boilerplate for the most simple tasks (CMS wise).
Instead of going through with the build I thought it would be best to build out the CMS using Rails being that you get your CRUD based tools right of the box. At this point I would have the API and CMS in the same Rails app.
The social network aspect of writing posts, creating collections, etc. would still be done using React. I was wondering if it were at all possible to accomplish a scenario where I could separately make a Rails app and SPA under the same domain. Any resources would be greatly appreciated.
NOTE: I'm aware there's a React gem for rails but would rather use it as a standalone to take advantage of using Redux and other Node packages.
Consider using a reverse proxy like Nginx. Nginx allows you to map different paths to different hosts or same host (with different ports)
location /cms/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://192.168.1.2:3000;
}
location /social/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://192.168.1.2:3100;
}
You can find more information in the following URL
https://www.nginx.com/resources/admin-guide/reverse-proxy/

Can one application with one server serve websockets and http traffic?

Is this somehow possible? Is it possible to do something like this in Ruby on top of Rack? I've seen there's websockets-rack but as far as I understand, that is only a rack module to serve ONLY websocket traffic not http also.
So basically, as the question states, is it possible to serve both protocols with just one server on the same port, instead of firing of something like Faye, websockets-rack or em-websockets?
Websockets are just an in-protocol upgrade of HTTP(s), so they are not normal TCP sockets but reuse the existing HTTP(S) connection (and thus use the same port). So, in theory it should work and from what I know it works with the Perl Mojolicious framework. But I don't know if it works work ruby/rack.
The short answer is - (AFAIK) no.
Currently, a ruby HTTP server (like rails or sinatra) and a websocket server are mutually exclusive.
After saying that, you could use a third party to emulate that. Specifically Ngnix. With Nginx you can listen to a single port, but, accroding to a path, decide whether you want to dispatch the request to the HTTP server or the Websocket server.
For example, you can run the HTTP server on port 3000, and the Websocket server on port 3020, and then configure the nginx.conf like this:
upstream http_app {
server 127.0.0.1:3000;
}
upstream websocket_app {
server 127.0.0.1:3020;
}
server {
listen 80;
server_name .example.com;
access_log /var/www/myapp.example.com/log/access.log;
error_log /var/www/myapp.example.com/log/error.log;
root /var/www/myapp.example.com;
index index.html;
location /web {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://http_app;
}
location /socket {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://websocket_app;
}
}
Now any request to http://www.example.com/web/... will reach the HTTP server, and any request to http://www.example.com/socket will reach the Websocket server.

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