Applying Basic Auth to only one directory of several served by nginx Docker container

I have an nginx docker container that serves the following directory structure:

/privatebin/
/misc/dir1
/misc/dir2
/misc/file.jpg
/misc/rss/

I only want basic authentication for the /misc/rss/ directory. The following docker run command (using labels) allows everything to be served correctly, but does not apply basic auth to the /misc/rss directory.

docker run \
--name nginx_run \
--mount type=volume,source=privatebin-static,target=/var/www/privatebin,readonly \
--mount type=bind,source=/srv/http,target=/var/www/misc,readonly \
--read-only \
-v /etc/localtime:/etc/localtime:ro \
-l traefik.enable=true \
-l "traefik.http.routers.nginx-run.rule=Host(`domain.com`) && PathPrefix(`/privatebin`) || PathPrefix(`/misc`)" \
-l traefik.http.routers.nginx-run.entrypoints=websecure \
-l traefik.http.routers.nginx-run.priority=1 \
-l traefik.http.routers.nginx-run.tls.certResolver=le \
-l traefik.http.services.nginx-run.loadbalancer.server.port=8080 \
-l "traefik.http.routers.rss.rule=Host(`domain.com`) && Path(`/misc/rss`)"  \
-l traefik.http.routers.rss.entrypoints=websecure \
-l traefik.http.routers.rss.priority=2 \
-l traefik.http.routers.rss.tls.certResolver=le \
-l traefik.http.routers.rss.middlewares=auth_rss \
-l traefik.http.routers.rss.service=nginx-run \
-l traefik.http.middlewares.auth_rss.basicAuth.users=username:$$apr1$$xxxxxx$$xxxxxx \
nginx

I thought that adding a second router (rss) with a higher priority that uses basic auth and matches the /misc/rss path would do the trick, but...it doesn't.

Can anyone point me in the right direction?

Thanks!

Hello,

It's a problem with your routing rule, you missed some parenthesis:

traefik.http.routers.nginx-run.rule=Host(`domain.com`) && (PathPrefix(`/privatebin`) || PathPrefix(`/misc`))

Adding the parenthesis didn't change the functioning of that rule. That also doesn't address why basic auth isn't working on /misc/rss (which is covered by a different rule). As I stated in the original post, the content is all served and both routers and rules show up correctly on the dashboard.

After some more poking around, I discovered that in the PathPrefix(/misc) rule I would have needed to add a negation for /misc/rss because /misc always matches even though there is a different rule with a higher priority to first match /misc/rss. And apparently using a regex negative look ahead or look behind would have been necessary...neither of which are supported by Golang's regex engine.

So, I ended up moving the /misc/rss directory to /rss. That works perfectly using a second router with basic auth attaching to the nginx-run service!

Final docker run command:

docker run \
--name nginx_run \
--mount type=volume,source=privatebin-static,target=/var/www/privatebin,readonly \
--mount type=bind,source=/srv/http,target=/var/www/misc,readonly \
--mount type=bind,source=/srv/rss,target=/var/www/rss,readonly \
--read-only \
-v /etc/localtime:/etc/localtime:ro \
-l traefik.enable=true \
-l "traefik.http.routers.nginx-run.rule=Host(`domain.com`) && (PathPrefix(`/privatebin`) || PathPrefix(`/misc`))" \
-l traefik.http.routers.nginx-run.entrypoints=websecure \
-l traefik.http.routers.nginx-run.tls.certResolver=le \
-l traefik.http.services.nginx-run.loadbalancer.server.port=8080 \
-l "traefik.http.routers.rss.rule=Host(`domain.com`) && PathPrefix(`/rss`)"  \
-l traefik.http.routers.rss.entrypoints=websecure \
-l traefik.http.routers.rss.tls.certResolver=le \
-l traefik.http.routers.rss.middlewares=auth_rss \
-l traefik.http.routers.rss.service=nginx-run \
-l traefik.http.middlewares.auth_rss.basicAuth.users=username:$$apr1$$xxx$$xxx \
nginx