I have an application running as a docker container mapped to port 8080; On this same server I also have nginx also configured to serve a Laravel application which has some URLs that have api
at context root https://example.com/api/news
for example. The docker application URLs starts with either web/
or api/
so to avoid URL proxy confusions I'm trying to serve all docker container application /comments
context path, thereby Laravel requests continue from host/api
and docker app URL host/comments/api
etc. I have following locations in the configuration (in the order described here)
upstream remark42 {
server 127.0.0.1:8080 weight=100 max_fails=5 fail_timeout=5;
}
server {
listen 80;
server_name www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
access_log /var/www/example.com/storage/logs/access.log;
error_log /var/www/example.com/storage/logs/error.log;
ssl_certificate /etc/nginx/ssl/example_com_chain.crt;
ssl_certificate_key /etc/nginx/ssl/example_com.key;
root /var/www/example.com/public/;
index index.php index.html index.htm;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param APP_ENV production;
include fastcgi_params;
}
location /comments {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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 https;
rewrite ^/comments(.*) /$1 break;
proxy_pass http://remark42/;
}
location ~* \.(?:css|js)$ {
access_log on;
etag on;
if_modified_since exact;
add_header Pragma "public";
add_header Cache-Control "max-age=31557600, public, must-revalidate, proxy-revalidate";
}
And then at the end of file
location / {
try_files $uri $uri/ /index.php?$args;
}
I get a 404 error on accessing https://www.example.com/comments/web/embed.js
or https://www.example.com/comments/api/v1/user?blah
with the JS file giving following error in logs
2020/05/18 18:05:54 [error] 3047#3047: *5035 open() "/var/www/example.com/public/comments/web/last-comments.js" failed (2: No such file or directory), client: 49.207.48.221, server: , request: "GET /comments/web/last-comments.js HTTP/2.0", host: "www.example.com", referrer: "https://www.example.com/blogs/yet-another-svn-change-log-tool"
So the proxy pass doesn't work and it tries to fetch js files from disk.
As documented in the
ngx_http_rewrite_module
documentation, after a rewrite, thelocation
is searched again - so after the rewrite thelocation ~* \.(?:css|js)$
is entered instead of executing theproxy_pass
.If what you want to do is to represent resources from
http://127.0.0.1:8080/
underhttp://www.example.com/comments/
, thenproxy_pass
will do this automatically. From the NGINX Reverse Proxy documentation:"URI" here means the part after the upstream name, which you specified as
/
.So your location should be simply written as such:
Note the ending
/
on thelocation
path to make the mapping canonical - sohttps://www.example.com/comments/web/embed.js
is proxied tohttp://remark42/web/embed.js
(/comments/
is mapped to/
).Otherwise, you'd get something like this:
https://www.example.com/comments/web/embed.js
->http://remark42//web/embed.js
- note the double slash. This is often not a problem as the upstream server should handle this and canonicalize the double slash, but it is not correct.I believe there are two solutions to your problem.
or
To understand, read nginx proxy module
The first solution, is based upon
Ie. /comments is replaced by /
The second solution is based on
You were passing an URI, the last "/" in "http://remark42/".