0

I have a running website where I have a specific directory where I store random stuff (it sounds very informal and it indeed is).

So, I wanted to have some sort of index there that lists the contents of that directory (and subdirectories). autoindex would work perfectly.

Then, I don't really want others to browse that index. auth_basic would work perfectly.

But, I'd like to be able to link to specific files or directories inside that directory (that is a directory that does contain an index file and not an autoindex) without having them password protected.

So, the final idea would be to have a location with autoindices that are password protected with basic auth but leaving the rest of the files and directories untouched.

I came up with a hacky solution that works: since an HTTP status 403 is issued when an index that does not exist is accessed, I redirect that to a custom location block that enables autoindex with auth_basic.

See here an example:

server {
    root ...;
    index index.php index.html index.htm;
    server_name ...;
    access_log ...;
    error_log ...;

    # general site
    location / {
        try_files $uri $uri/ @rewrite;
        location ~ \.php(/|$) {
            include fastcgi.conf;
            fastcgi_split_path_info ^(.+\.php)(/.*)$;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
            fastcgi_param DOCUMENT_ROOT $realpath_root;
            try_files $uri $uri/;
            fastcgi_pass unix:/run/php/php-fpm-....sock;
        }
    }

    # rewrite for the general site
    /location @rewrite {
        rewrite ...;
    }

    # that specific directory
    location /directory {
        try_files $uri $uri/ =404;
        error_page 403 = @autoindex; # hack 1

        location ~ \.php(/|$) {
            # include snippets/fastcgi-php.conf;
            include fastcgi.conf;
            fastcgi_split_path_info ^(.+\.php)(/.*)$;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
            fastcgi_param DOCUMENT_ROOT $realpath_root;
            try_files $uri $uri/;
            fastcgi_pass unix:/run/php/php-fpm-....sock;
        }
    }
    
    # password-protected autoindices
    location @autoindex {
        autoindex on;
        autoindex_exact_size off;
        auth_basic "directory";
        auth_basic_user_file /.../.htpasswd;
    }
}

So... is there a better idea? Is this hack a bad idea?

Thank you!

1 Answers1

0

So, the final idea would be to have a location with autoindices that are password protected with basic auth but leaving the rest of the files and directories untouched.

Try using regex location to specify any locations you need to protect with basic_auth.

Prefix-based location will always checked first, but used last, after all regex-based location checked. If no regex-based location matches current request, longest-matching prefix-based location will be used.

Here, you can do something like

index index.html;

location ~ /directory(/$|$) { # http://example.com/directory, http://example.com/directory/
    autoindex on;
    autoindex_exact_size off;
    auth_basic "directory";
    auth_basic_user_file /.../.htpasswd;
}

location /directory { # http://example.com/directory/favicon.ico
    try_files $uri $uri/ =404;

    location ~ \.php(/|$) {
        # include snippets/fastcgi-php.conf;
        include fastcgi.conf;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        try_files $uri $uri/;
        fastcgi_pass unix:/run/php/php-fpm-....sock;
    }
}

Using http://example.com as your base URL:

  • any requests to http://example.com/directory and http://example.com/directory/ will be autoindex-ed and having auth_basic enabled, according to location ~ /directory(/$|$) directive.
  • any other requests to http://example.com/directory/* will be served according to location /directory directive.
mforsetti
  • 2,488
  • 2
  • 14
  • 20
  • Aha, but what about requests to `http;//example.com/directory/inner/`? I'd like to have those _autoindex_ed. And then, what would happen if `http://example.com/directory/other/` does have an `index.html` file? I'd like that to be served. Thanks! – nerestaren May 14 '21 at 18:40
  • would specifying the directories manually suffice, e.g. `location ~ /(directory|directory/inner)(/$|$) {`? and any directories with `index.html`, as long as `index` directive is set with `index.html` and regex-based location doesn't include the directory, its `index.html` will be served. – mforsetti May 14 '21 at 18:45