0

I use Nginx to reverse proxy a backend API. However, I would like Nginx to serve one static file named "readme.html" when a request is made to "/".

I did extensive research. The most promising solution seemed to be that one: https://stackoverflow.com/a/15467555/2237433.

Trying to apply that solution to my case, here is my code. Here is my Dockerfile:

# syntax=docker/dockerfile:1
FROM nginx:1.22.0-alpine
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./readme.html /www/
EXPOSE 80

With my Nginx container running, I can connect to a shell into it and run cat /www/readme.html to confirm that the file is indeed present.

Now here is my nginx.conf:

# a lot of stuff
http {
    # a lot of stuff
    proxy_cache_path  /data/nginx/cache keys_zone=my-zone:10m;
    server {

        listen 80;
        add_header X-Cache-Status $upstream_cache_status always;

        location / {
            root /www/;
            try_files readme.html @backend;
        }

        location @backend {
            proxy_pass http://api:8080;
            proxy_cache my-zone;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
            proxy_cache_lock on;
        }

    }
}

With this config, all my paths work as expected, except that when I run a request on "/", I get a 404 error. The 404 actually comes from the backend. Here is the log from the backend after the request:

[20/Jun/2022 01:51:06] "GET / HTTP/1.0" 404 -

So the "/" request was actually passed to the backend.

I tried a high number of tweaks from that configuration, but to no avail. Thank you for your help!

Ian
  • 3
  • 2

2 Answers2

0

I found a working solution. It turns out the location / block had to be like so:

location / {
    root /www;
    try_files $uri/readme.html @backend;
}

I can't say I really understand why though, so if anyone can explain the reason behind this, I would be grateful.

Ian
  • 3
  • 2
  • For instance, what is the reason why a simple `{try_files /www/readme.html @backend}` (without any `root` directive) not work here? It passes a `/` request to the backend (as in my question statement). I suppose it means that Nginx could not find the file at `/www/readme.html`. But why? The file is there and the permissions are correct. – Ian Jun 20 '22 at 13:57
0

You can explicitly rewrite "root" request URI:

location = / {
    root /www;
    rewrite ^ /readme.html break;
}
location / {
    proxy_pass http://api:8080;
    ...
}

Or you can use readme.html as your index file:

location / {
    root /www;
    index readme.html;
    try_files $uri $uri/ @backend;
}
Ivan Shatsky
  • 2,726
  • 2
  • 7
  • 19
  • That worked, thank you! – Ian Jun 20 '22 at 13:48
  • First option should be somewhat better since it will eliminate an extra `stat` system call that would be made due to the `try_files` directive. Another difference is that it is only `/` request that will be served with the `readme.html` file contents in the first case, request `/readme.html` will be passed to the backend; in the second case both `/` and `/readme.html` will be served with the `readme.html` file contents. – Ivan Shatsky Jun 20 '22 at 13:51