I have this nginx config to serve a rails app:
location ^~ /api/ {
alias /srv/www/rails/public/;
try_files $uri #unicorn;
}
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://127.0.0.1:2007;
}
I want to remove /api/ from the start of path before passing it to rails app, but since it's a named location I can't add "/" at the end of proxy_pass directive, how can I remove /api/ before passing request to rails?
Use:
location #unicorn {
rewrite ^/api(.*)$ $1 break;
...
}
See this document for details.
Related
I am using proxy_pass in Nginx to redirect /phpmyadmin[/] to a container where PHPMyAdmin is running (the project is available here on Github). The problem is that when I use https://localhost/phpmyadmin/, I get the HTML and content of PHPMyAdmin in the correct way, but, when I drop "/" at the end of the URL, it returns me the HTML with the wrong resource URLs (such as https://localhost/favicon.ico instead of https://localhost/phpmyadmin/favicon.ico). My Nginx config file looks like this:
upstream backend {
server app1:9000;
server app2:9000;
server app3:9000;
server app4:9000;
}
upstream docker_phpmyadmin {
server phpmyadmin:443;
}
server {
server_name localhost;
listen 443 ssl http2;
root /var/www;
location ~ /phpmyadmin {
# (START) some queries don't work when modsecurity is on
modsecurity off;
# (END) some queries don't work when modsecurity is on
# (START) large databases might demand long time and large memory
client_max_body_size 100m;
client_body_buffer_size 10M;
proxy_read_timeout 6000;
proxy_send_timeout 6000;
# (END) large databases might demand long time and large memory
rewrite /phpmyadmin/?(.*)$ /$1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass https://docker_phpmyadmin;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
}
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
location / {
index index.php;
try_files $uri $uri/ /index.php;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
error_page 404 error.html;
location = /error.html {
root /var/www;
}
location ~* \.(ico|css|js|gif|jpe?g|png)$ {
expires 10d;
}
location ~* \.php$ {
try_files $uri =404;
fastcgi_pass backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
The same issue arises when I try to use MailCow in my project using:
location ~ /mailcow {
rewrite /mailcow/?(.*)$ /$1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass https://docker_nginx_mailcow;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto https;
# proxy_redirect off;
}
I am setting up a Rails app with nginx in front.
What I want is first to check if the URL makes sense for Rails then serve content of the public folder.
I can't achieve this:
upstream extranet {
server localhost:3000;
}
server {
location / {
try_files #extranet $uri;
root /var/www/extranet/public;
}
location #extranet {
proxy_pass http://extranet;
proxy_read_timeout 90;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Host $host;
client_max_body_size 100m;
}
}
I get: *1 rewrite or internal redirection cycle while internally redirecting to "/" error.
It seems like try_files $uri #extranet; works but in my case it feels safer to check the Rails app first because the public folder might change.
try_files checks for the presence of a file on the local file system and cannot respond to the response code from a proxy.
Presumably, the proxy response with a 404 response if the remote page does not exist, which can be intercepted by an error_page statement.
For example:
location / {
proxy_pass http://extranet;
proxy_set_header ...
proxy_set_header ...
proxy_set_header ...
proxy_intercept_errors on;
error_page 404 = #fallback;
}
location #fallback {
root /var/www/extranet/public;
try_files $uri =404;
}
See this document for more.
I wanna to deploy my Ruby on Rails application in my local computer by Nginx and RoR web servers (like Unicorn, Thin or WEBrick).
As shown below, I wanna access to my web-app by post subdomain:
upstream sub {
server unix:/tmp/unicorn.subdomain.sock fail_timeout=0;
# server 127.0.0.1:3000;
}
server {
listen 80;
server_name post.subdomain.me;
access_log /var/www/subdomain/log/access.log;
error_log /var/www/subdomain/log/error.log;
root /var/www/subdomain;
index index.html;
location / {
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;
try_files /system/maintenance.html $uri $uri/index.html $uri.html #ruby;
}
location #ruby {
proxy_pass http://sub;
}
}
Everything is working fine and when I type post.subdomain.me I can see my RoR app.
Problem: When I use post.subdomain.me url I can't access to my subdomain (request.subdomain returns empty and request.host returns subdomain instaed of subdomain.me). But when I use post.subdomain.me:3000 every things work perfect (I lost half of my hairs to realize that). Why and How can I resolve it?
When you access app with port - you are accessing the rails server directly, not proxied by nginx, this is fine for debug, but usually is not well for production.
Probably host header is not passed over by client, $host defaults to nginx host
Try
location #ruby {
proxy_set_header Host $host;
proxy_pass http://sub;
}
And a 'hardcode'-way: proxy_set_header Host post.subdomain.me;
The proxy_set_header and proxy_redirect directives configure the proxy_pass directive and need to be within the same location block or inherited from the enclosing server block. You need to format your configuration file like this:
location / {
try_files /system/maintenance.html $uri $uri/index.html $uri.html #ruby;
}
location #ruby {
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://sub;
}
EDIT: Assuming that nginx is not passing the information to RoR correctly, as #Vasfed suggested, try other values for proxy_set_header Host. There are three other candidates, all with slightly different meanings.
proxy_set_header Host post.subdomain.me;
proxy_set_header Host $server_name;
proxy_set_header Host $host;
If I have:
try_files $uri/index.html $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://app
}
When I create a file at foo/bar/baz.txt it works but if 'bar' is a symlink, it stops working. Anyone know how to solve this as I need to use symlinks.
I was being daft, there was not executable rights for all on one of the parent directories.
What the quickest and cleanest solution if you want to proxy URL request to two different backends via proxypass based on location.
location /app1/ {
alias /var/www/ruby/public;
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;
try_files $uri $uri/ #ruby;
}
location #ruby {
proxy_pass http://127.0.0.1:3000;
}
location /app2/ {
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;
try_files $uri $uri/ #other;
}
location #other {
proxy_pass http://127.0.0.1:8080;
}
With this config nginx pass "/app1" or "/app2" to proxy and backend doesn't recognize the url/command ..
as for instance would like to pass to http://127.0.0.1:3000 only /messages when accessing http://<nginx>/app1/messages - but in configuration above also pass /app1/ as http://127.0.0.1:3000/app1/messages. Same goes for /app2
Try putting "/" at the end of upstream name
e.g
proxy_pass http://127.0.0.1:8080/;
Please see this post:
How to preserve request url with nginx proxy_pass