1

Usually userdir's in webservers prefix a ~ to the username, e.g. https://example.com/~me/ to access /home/me/public_html/.

Now, for $reasons, I need to setup an nginx server that serves directories in /home/${user}/public_html/ without this ~ prefix: https://example.com/me/. At the same time, the webserver should also serve content from the webroot (/var/www/html/).

I don't really care for the case where content is available in both locations (e.g. https://example.com/foo/index.html could be served by both /var/www/html/foo/index.html and /home/foo/public_html/index.html).

Answers here on Server Fault have lead me to this config:

location ~ (?<user>[^/]+)(?<path>.*)?$ {
  alias /home/$1/public_html$2;
  index index.html index.htm;
  autoindex on;
}

This works OK, but unfortunately, it also shadows the webroot (so I can no longer access /var/www/html/index.html via https://example.com/index.html).

So my 2nd try is this:

location ~ (?<user>[^/]+)(?<path>.*)?$ {
  root /home/$user/public_html;
  try_files $path $path/ @fallback;
  index index.html index.htm;
  autoindex on;
}

location @fallback { root /var/www/html/; index index.html index.htm; }

This allows me to access both /home/me/public_html/index.html via https://example.com/me/index.html and /var/www/html/index.html via https://example.com/index.html

It also allows me to /home/me/public_html/bla/index.html via https://example.com/me/bla/

Unfortunately, things break with https://example.com/me/bla (note the missing trailing slash): nginx will issue a permanent redirect (301) to https://example.com/bla/ (stripping away my username! where it really should only do a redirect to https://example.com/me/bla/). This gives plenty of 404 errors (when /var/www/html/bla/ does not exist), or the wrong content (when it does exist).

I'm sure people will forget to add their trailing slashes, and then end up in the wrong (or non-existant) directories.

My gut feeling is, that this wrong redirection comes from my use of root in the location block. There's no such problem with alias, but how can I use try_files with a fallback location in that case?

So: how can I teach nginx to serve userdirs without a ~, while still serving content from my webroot and allowing the user to forget to type the trailing / when they want to access directories on the webserver?

umläute
  • 541

1 Answers1

0

last night i had a stroke of sudden intelligence, and I came up with an improvied regular expression that allows me to combine the try_files with the alias directive, eliminating the need for the root directive.

So here's the final configuration, which appears to do everything i want:

    root /var/www/html;
    location ~ (?<user>[^/]+)(?<path>.*/)?(?<file>.*)?$ {
        alias /home/$user/public_html/$path;
        try_files $file $file/ @fallback;
    index index.html index.htm;
    autoindex on;
}

location @fallback {
    index index.html index.htm;
}
location / {
    index index.html index.htm;
}

i don't really like that i have to duplicate the location @fallback to the location / block, but i guess i can live with it for now.

as mentioned in my question, this will have /home/foo/public_html/ override /var/www/html/foo/. i wonder whether i can revert this (so that /var/www/html/foo/ overrides /home/foo/public_html/) - but again, that's not high priority.

umläute
  • 541