I'd like to use nginx in order to map all my rails apps on port 80.
Currently, I have 3 rails apps running on port 3000 3001 and 3002 and I'd like to use nginx on port 80 to map them so :
http://127.0.0.1/app1 => 127.0.0.1:3000
http://127.0.0.1/app2 => 127.0.0.1:3001
http://127.0.0.1/app3 => 127.0.0.1:3002
Here's what I did :
server {
listen 80;
location /app1/ {
proxy_pass http://127.0.0.1:3000/;
}
location /app2/ {
proxy_pass http://127.0.0.1:3001/;
}
location /app3/ {
proxy_pass http://127.0.0.1:3002/;
}
}
However, when I try to access http://127.0.0.1/app1, I only get the HTML content, no assets/js/css as the browser tries to get them from http://127.0.0.1/assets instead of http://127.0.0.1/app1/assets.
Is there a way to fix this?
Add ActionController::Base.relative_url_root = "/app1" to the end of your config/environment.rb of app1 (similarly for other two apps). This will make Rails add proper prefix to URLs.
If you don't want to mess with Rails config, you probably could force Nginx to go through all of your assets folder until it finds the one it needs, if I'm not mistaken it could be archived like this:
location /assets/ {
try_files /app1/$uri /app2/$uri /app3/$uri;
}
Please note that you must have different filenames for assets of different apps. That is already so if you are using asset pipeline everywhere, as it hashes file names.
UPD.
You can also try 'Referer'-based routing:
location /assets/ {
if ($http_referer ~* /app1) {
rewrite ^(.*)$ app1/$1 break;
}
if ($http_referer ~* /app2) {
rewrite ^(.*)$ app2/$1 break;
}
if ($http_referer ~* /app3) {
rewrite ^(.*)$ app3/$1 break;
}
}
This is a good default configuration for what you want to achieve:
server {
listen 80;
location /app1/ {
root /srv/rails/app1/public;
try_files $uri $uri/index.html $uri.html #app1_forward;
}
location #app1_forward {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app1_backend;
}
location /app2/ {
root /srv/rails/app2/public;
try_files $uri $uri/index.html $uri.html #app2_forward;
}
location #app2_forward {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app2_backend;
}
location /app3/ {
root /srv/rails/app3/public;
try_files $uri $uri/index.html $uri.html #app3_forward;
}
location #app3_forward {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app3_backend;
}
}
upstream app1_backend {
server 127.0.0.1:3000 fail_timeout=0;
}
upstream app2_backend {
server 127.0.0.1:3001 fail_timeout=0;
}
upstream app3_backend {
server 127.0.0.1:3002 fail_timeout=0;
}
Also check this article, where I link to this example nginx config, for Rails.
Related
I made an nginx.conf file, my issue is that the all the proxy_pass redirects end up being 502 Bad Gateway messages.
Here is the nginx.conf:
http {
server {
listen 80;
server_tokens off;
location / {
client_max_body_size 0;
gzip off;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
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 $scheme;
proxy_pass http://172.21.144.10;
}
}
server {
listen 443;
server_tokens off;
location / {
client_max_body_size 0;
gzip off;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
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 $scheme;
proxy_pass http://172.21.144.10:443;
}
}
}
The url http://172.21.144.10 points to a gitlab-ce install in another docker container, it is accessible via the browser.
I've tried both proxy_pass with and without a trailing slash, so that's not the issue.
I need to redirect or proxy_pass the following:
Every request starting with /api/v1/ to: #server
everything else / to #client
I have #server running on port 8080 and #client on port 8081
#client and #server are running as docker containers.
Note. Everything should be using https.
The following config is what I have but its not working idkw
server {
server_name example.com;
listen 80;
listen [::]:80 ipv6only=on;
return 301 https://example.com$request_uri;
}
server {
server_name example.com;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
...
proxy_set_header Host $host;
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 $scheme;
location /api/v1/ {
try_files $uri #server;
}
location / {
try_files $uri #client;
}
location #client {
proxy_pass http://client:8081;
}
location #server {
proxy_pass http://server:8080/api/v1/;
}
}
If you must use named locations then you can use error_page approach below.
By returning unused HTTP status codes and error_page for those codes set to named locations, we can forward requests to those named locations:
server {
server_name example.com;
listen 80;
listen [::]:80 ipv6only=on;
return 301 https://example.com$request_uri;
}
server {
server_name example.com;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
...
proxy_set_header Host $host;
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 $scheme;
error_page 350 = #client;
error_page 351 = #server;
location /api/v1/ {
return 351;
}
location / {
return 350;
}
location #client {
proxy_pass http://client:8081;
}
location #server {
proxy_pass http://server:8080/api/v1/;
}
}
nginx.conf (exposed on port 8900 in docker-compose)
upstream app_api {
server api:8888;
}
upstream app_dashboard {
server dashboard:8080;
}
server {
listen 80;
server_name api_server;
index index.html;
# Needed for Django API testing
location /static {
alias /var/www/static;
try_files $uri /$uri /index.html;
}
#Django API
location /api/ {
proxy_pass http://app_api/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
# Dashboard static served from nginx
location / {
root /var/www/dist/;
try_files $uri /$uri /index.html;
}
# Dashboard served from webpack-dev-server in container
location /serve {
proxy_pass http://app_dashboard;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
# still testing - this will fix the HMR for webpack
location /serve/sockjs-node {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://app_dashboard;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
vue.config.js
module.exports = {
baseUrl: process.env.NODE_ENV === 'docker' ? '/serve' : '/'
}
In a browser go to:
localhost:8900/serve
Pages get served fine, however,webpack-dev-server HMR is not working since the calls to sockjs are now /serve instead of /serve/sockjs-node :
POST http://localhost:8900/serve/908/3so2cyjm/xhr_streaming?t=1548885104223 404 (Not Found)
I am assuming this can be fixed with setting devServer.proxy instead of baseUrl, however I could not find the correct configuration.
What I need is:
/ -> should go to http://localhost:8900/serve
/api -> should go to http://localhost:8900/api
/sockjs-node -> should go to http://localhost:8900/serve/sockjs-node
We can change the default socket path using sockPath option:
module.exports = {
//...
devServer: {
sockPath: 'path/to/socket',
}
};
Here will be:
sockPath: '/serve/sockjs-node',
Managed to fix that issue with something like:
devServer: {
proxy: {
"/serve": {
target: "http://localhost:8900",
pathRewrite: { "^/serve": "/sockjs-node" },
},
}
}
I have a docker-compose file that creates 3 apache containers, and an NGINX container. The apache containers are all different applications that will have their own docker containers.
I want to use NGINX to reverse proxy from a directory off the root nginx container URL to the main parent of the 3 apache instances.
In the configuration below location / works. /parts and /wiki do not.
I have confirmed that all 3 apache containers do work by swapping out the proxy_pass on the / location, so I know the issue is with the nginx config. However I am a newb to nginx, and am not sure how to figure this out.
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream docker-apache-php {
server ths_apache_php:80;
}
upstream docker-apache-php-two {
server ths_apache_php_two:80;
}
upstream docker-apache-php-three {
server ths_apache_php_three:80;
}
server {
listen 8080;
location / {
proxy_pass http://docker-apache-php;
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;
proxy_set_header X-Forwarded-Host $server_name;
}
location /parts {
proxy_pass http://docker-apache-php-two;
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;
proxy_set_header X-Forwarded-Host $server_name;
}
location /wiki {
proxy_pass http://docker-apache-php-three;
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;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
I solved the problem, apparently the URLs on the proxy_pass needed to end with a /. This is now working as I need it too.
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream docker-apache-php {
server ths_apache_php:80;
}
upstream docker-apache-php-two {
server ths_apache_php_two:80;
}
upstream docker-apache-php-three {
server ths_apache_php_three:80;
}
server {
listen 8080;
location / {
proxy_pass http://docker-apache-php/;
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;
proxy_set_header X-Forwarded-Host $server_name;
}
location /parts {
proxy_pass http://docker-apache-php-two/;
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;
proxy_set_header X-Forwarded-Host $server_name;
}
location /wiki {
proxy_pass http://docker-apache-php-three/;
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;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
Requirement:
Redirect http://ruby.server.com to https://ruby.server.com/app1/ and don't append anything if the incoming URL has context (ex: http://ruby.server.com/app2/) in it
Setup
We have the following setup
Amazon Load Balancer
| http - |
| --> 80(ruby.server.com)
| https - |
nginx is running on ruby.server.com at port 80. There is no 443 in nginx.
server {
listen 80;
server_name ruby.server.com;
root /home/ubuntu/ruby/server/public/;
location / {
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
client_max_body_size 100M;
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;
proxy_pass http://127.0.0.1:4009/;
root /home/ubuntu/ruby/server/public/;
}
if ($http_x_forwarded_proto != 'https') line is used for redirecting http://ruby.server.com to https://ruby.server.com
More context
We have 2 rails apps running inside the rails server, /public/app1, /public/app2. By default we want to redirect ruby.server.com to go to app1.
We can solve the above problem within the rails itself that involves an additional redirection. We are trying to see if we can get that context append within the nginx layer.
Solution based #timothy's note.
server {
listen 80;
server_name ruby.server.com;
root /home/ubuntu/staging/server/public/;
location / {
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host/app1/? permanent;
}
client_max_body_size 100M;
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;
proxy_pass http://127.0.0.1:4009/;
root /home/ubuntu/staging/server/public/;
#auth_basic "Restricted";
#auth_basic_user_file /etc/nginx/.htpasswd;
}
location ^~ /[^\/]+/ {
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
client_max_body_size 100M;
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;
proxy_pass http://127.0.0.1:4009/;
}
}
server {
listen 80;
server_name ruby.server.com;
root /home/ubuntu/ruby/server/public/;
location / {
# Default location for:
# http://ruby.server.com
# https://ruby.server.com
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
client_max_body_size 100M;
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;
proxy_pass http://127.0.0.1:4009/;
}
location ^~ /[^\/]+/ {
# Location for:
# http://ruby.server.com/anything/
# https://ruby.server.com/anything/
# Do whatever you need here. :)
client_max_body_size 100M;
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;
proxy_pass http://127.0.0.1:4009/;
}
}