8

I'm trying to enable directory listing for a folder outside the web root, from a different local ext4 mount that uses Basic Authentication, but I'm getting an empty list and no logged errors. What's strange is that if I put in the known location of a file under this directory in my browser, it downloads the file just fine.

enter image description here

Here's my example.conf file:

<virtualhost *:80>

  ServerAdmin donotreply@blah.com
  ServerName  example.com
  ServerAlias www.example.com


  DirectoryIndex index.php
  DocumentRoot /var/www/example.com
    <Directory />
    Options FollowSymLinks
    AllowOverride All
    </Directory>

  LogLevel warn
  ErrorLog  /var/apachelogs/error.log
  CustomLog /var/apachelogs/access.log combined

  Alias /blah2 "/blah1/blah2"
    <Location /blah2>
              Options +Indexes +MultiViews +FollowSymLinks
              IndexOptions +FancyIndexing
    </Location>


</virtualhost>

And here's my .htaccess

AuthType Basic
AuthName "Authentication Required"
AuthUserFile "/home/myusername/.htpasswd"
Require valid-user

Also, I've commented IndexIgnore out in /etc/apache2/mods-enabled/autoindex.conf

#IndexIgnore .??* *~ *# RCS CVS *,v *,t

I've run chmod -R 755 /blah1/blah2, and chgrp -R www-data /blah1/blah2 and chmod a+x -R /blah1/blah2. The folder owner is a member of www-data. If I run sudo usermod -a -G www-data myusername I can browse and read all files and folders just fine.

Doing some testing, my configuration works fine if I move /blah1/blah2 under my home directory and change the alias. There's something about it being on another mount that is messing up mod_autoindex, even though apache can clearly read the files themselves. Removing authentication doesn't help. With LogLevel warn I get no logged errors. After changing my LogLevel to trace4, here's my error log.

Here's the mount line from /etc/fstab:

UUID=[theuuid] /blah1 ext4 rw,nosuid,nodev,errors=remount-ro    0    0

EDIT Last note: confirming that www-data can read and write to my folder, I made the following php script:

<?php

mkdir ("testdir");
var_dump(scandir('.'));

?>

The result: directory testdir is created with owner www-data:www-data, and the list of directories and files is dumped as a variable.

EDIT2 I've run the following commands to set permissions correctly:

chmod 755 /blah1/blah2
chmod 755 /blah1
find /blah1/blah2 -type d -exec chgrp www-data {} +
find /blah1/blah2 -type d -exec chmod o+rx {} +
find /blah1/blah2 -type d -exec chmod g+rwxs {} +

Still the same result.

10
  • What about using LogLevel debug and then checking log files? – Michal Przybylowicz Aug 31 '19 at 16:00
  • No new info with debug. pastebin.com/xu1bUuvB – user255406 Aug 31 '19 at 18:12
  • Based on your logs. I think your issue is the index cannot access your .htaccess. try to copy the content of .htaccess into <Directory /> – abu-ahmed al-khatiri Sep 2 '19 at 10:16
  • Tried that, same result. – user255406 Sep 2 '19 at 10:18
  • 1
    Have you tried using <Directory /blah1/blah2> instead of <Location /blah2>? – Dan Sep 6 '19 at 14:44
1
+100

There are several things that could be changed in your configuration. In order to help you, I'm providing here the following guide, based on the default Apache2's configuration.

Deal with the file system permissions

In order to access the files, the Apache's user www-data needs to have read permissions to the files and read-execute permissions to the directories, also in this number read-execute permissions to the whole path. If you do not have any special requirements, I would suggest you to use the other users permissions.

Let's assume the directory you want to index via the web server is named bar and it is located in the home directory of the user foo. By default he directories /home and /home/foo must have 755 permissions. The last bit in the octal number 755 means all other users have read-execute permissions (content rad access) to the files inside /home/foo.

So let's create our directory /home/foo/bar and let's assure it (and its path) has r-x permissions for the other users:

mkdir -p /home/foo/bar                            # create the directory
find /home/foo/bar -type d -exec chmod o+rx {} +  # apply o+rx for the dirs recursively
sudo chmod o+rx /home /home/foo                   # this step is optional

Now let's create three test files and assure they have read permissions for the other users:

touch /home/foo/bar/file.{1..3}                  # create three empty test files
find /home/foo/bar -type f -exec chmod o+r {} +  # apply o+r for the files recursively

In order to allow www-data to write content in /home/foo/bar you can change the group ownership of the directory and add rwxs group permissions (more details):

find /home/foo/bar -type d -exec chgrp www-data {} +
find /home/foo/bar -type d -exec chmod g+rwxs {} +

Test by creating another three empty files:

sudo -u www-data touch /home/foo/bar/file.{4..6}


Deal with the Apache's configuration

By default, within the main configuration file /etc/apache2/apache2.conf, for security reasons, the access to the root directory / is restricted. I would suggest you to do not override these rules via the virtual host configuration and remove <Directory /> tags (and the enclosed directives).

In particular, if you are creating an Alias to a directory outside of your DocumentRoot, you may need to explicitly permit access to the target directory (source Apache Module mod_alias).

Let's first create .htpasswd file with enough permissions (add more security by using 2FA - p.6):

htpasswd -c /home/foo/.htpasswd foo               # authentication for the username 'foo'
chmod 400 /home/foo/.htpasswd                     # restricted the permissions
sudo chown www-data:www-data /home/foo/.htpasswd  # change the ownership

According to the above, the relevant part of you virtual host configuration file should be something like this:

<VirtualHost *:80>

    # Other configuration directives

    Alias "/bar" "/home/foo/bar"

    <Directory "/home/foo/bar">
            #Require all granted
            Options +Indexes +MultiViews +FollowSymLinks
            IndexOptions +FancyIndexing

            # Allow using of a .htaccess files
            AllowOverride All

            # This section could be moved in .htaccess file
            <IfModule mod_authz_core.c>

                <IfModule mod_authn_file.c>
                    AuthType Basic
                    AuthName "Type some hints here..."
                    AuthUserFile /home/foo/.htpasswd
                </IfModule>

                Require valid-user

            </IfModule>

    </Directory>


</VirtualHost>

Enable the relevant modules and restart Apache2 to apply the new configuration:

sudo a2enmod authz_core authz_user authn_file
sudo systemctl restart apache2.service


Sample result

enter image description here


Update:

I'm assuming the problem belongs to file system's permissions issue. Probably the most easiest way, to solve it, is to mount the target directory inside the DocumentRoot directory by using bindfs as it is described in this answer.


Working solution:

Here's the final solution: abandon the idea of getting Alias to work correctly for my externally mounted folder and instead take @pa4080's workaround advice and usebindfs to mount the folder to /blah2 in the webroot. I was unsuccessful in getting /etc/fsab to correctly initialize my bind, so I decided to write an init script for the task.

First, install bindfs:

apt-get update
apt-get install bindfs
mkdir /var/www/example.com/blah2

Next I created a script file /var/www/scripts/blahbind.sh to be run on startup:

#!/bin/bash
bindfs -o force-user=www-data,perms=a=rX /blah1/blah2 /var/www/example.com/blah2

Then give it correct permissions:

chmod 750 /var/www/scripts/blahbind.sh
chmod +x /var/www/scripts/blahbind.sh

Next I created a service script:

vi /etc/systemd/system/blahbind.service 

With the contents:

[Unit]
Requires=mydrive.mount
After=mydrive.mount
Description=bind /blah1/blah2 to example.com/blah2 folder

[Service]
ExecStart=/var/www/scripts/blahbind.sh
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Note, mydrive.mount should be replaced with the drive of the /blah1/blah2 folder. Get a list of mounts with systemctl list-units --type=mount.

Confirm that the service script works by running

sudo service blahbind start

Then enable the service to persist on reboot with:

sudo systemctl enable blahbind.service

And then, my simplified Location block, sans Alias in example.com.conf

   <Location /blah2>
            Options +Indexes +MultiViews +FollowSymLinks
            IndexOptions +FancyIndexing
   </Location>
5
  • 1
    Thanks for the comprehensive explanation. If I follow your tutorial for a directory in my home folder it works perfectly, but if that folder is on another mounted drive I get the same result. I added the code I ran to EDIT2. – user255406 Sep 5 '19 at 21:31
  • Hello, @user255406, IMO this is permissions issue. I've added a reference to a possible workaround to my answer. – pa4080 Sep 6 '19 at 12:56
  • 1
    Using the bindfs workaround, I was able to get everything working correctly. To me, this says it's not really a permissions issue at all. – user255406 Sep 6 '19 at 14:04
  • 1
    Ultimately, the workaround is a working solution for me. Would you like to expand your Update section to explain the method here? (I used bindfs and added mounting it as a systemd service to bring it up on reboot) – user255406 Sep 6 '19 at 16:55
  • Hi, @user255406, I would like to expand the update section, I will have an access to a computer tomorrow morning. You are welcome, if you want to add some update to the answer, Stack Exchange is a team game at all :) – pa4080 Sep 6 '19 at 17:20
0

Apache will need execute rights for all directories, your case /blah1 and /blah2. If it encounters a directory it doesn't have group execute rights for a directory it will not do the listing.

You probably need to modify /blah1 to either have public execute rights or chown www-data to be it's group with group execution right, eg. g+x

2
  • I added the code I added onto EDIT2. apache can execute, but still no dice. – user255406 Sep 5 '19 at 21:32
  • Execute rights for the directory, which is listing rights essentially. – Kristopher Ives Sep 5 '19 at 21:58
0

Based on example.conf, you have /var/www/example.com as Document Root and /blah1/blah2 as Directory ext4 mounted.

Let's assumed the Document Root Symlinked to your Directory mounted. now we need confirm the location of our Document Root. we will copy the files using rsync. it will dump the contents into the mount point instead of transferring it into a containing html location.

$sudo rsync -av /var/www/example.com/html /blah1/blah2

Now we are ready to update the configuration

<VirtualHost *:80>

...
...
DocumentRoot /var/www/example.com
<Directory />
    Options FollowSymLinks
    AllowOverride All
</Directory>
...
...
Alias /blah2 "/blah1/blah2"
<Directory "/blah1/blah2">
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    IndexOptions FancyIndexing
    Require valid-user
    ...
    ...
    #to ensure the DocumentRoot is updated in rewrites or aliases to reflect the changes at the new location.
    RewriteEngineon
    RewriteCond %{HTTP_HOST} =www.example.com
    RewriteRule ^index\.html$ filename.html
    ...
</Directory>

<VirtualHost>

Don't forget to enable mod_rewrite see this docs.

Finally we check the syntax and Restart your Apache.

$sudo apachectl configtest
$sudo systemctl reload apache

Hope this helpfully.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.