Credits: Digital Ocean for the WebDAV tutorial. hexeract for his post about multiple WebDAV users. Raymond Camden for the responsive directory index.
For a project I’ve been working on, I needed some place for users to upload and access files. I started off using Google Drive, Sharepoint etc, but I also wanted to have the option of hosting the files myself.
So, I looked at all sorts of options (Pydio, Seafile, Owncloud, FTP, WebDAV). I decided to have a stab at WebDAV, mainly due to it being included with Apache through mod_dav. Initially, I was using file based storage, but the Apache docs advise to use a dbm database instead due to being far faster. However, the same docs weren’t very helpful when it came to using dbm for group management / authorisation.
The following is what I did to get everything working. If you want to do something similar yourself, hopefully it will help. I’m using Debian 11, Apache 2.4.51.
First, create a directory for the credentials to live
# mkdir -p /usr/local/apache2/var
cd
into the new directory and then create the dbm file that Apache will use for auth. I’ll add myself and also what groups I belong to. After running command below, you’ll be prompted for a password. I use pwgen for generating passwords.
# htdbm -ct users.dbm me@mydomain.com "project1,project2"
The -c
is needed to create the database. -t
is used to add a comment which Apache uses for the group credentials (it would have been nice if the Apache docs stated that!). The most important things to remember are: no spaces in group names, and separate each group with commas. Just stick with alphanumeric characters or an underscore, and you should be golden.
Next, we’ll add a second user who we only want to access project1
# htdbm -t users.dbm someone@somewhere.com "project1,"
The next user can only access project2
# htdbm -t users.dbm user@somewhere.com "project2,"
If you need to delete a user you can do that like so:
# htdbm -x users.dbm simon
I think you can see why setting up access control in this way is such a good idea. You’ve only got one file to manage. Adding, modifying or deleting users is just one line using htdbm. And the lookups are super fast. I’ve been using dbm for session management for years. You might want to install db-util as well for managing the database.
List database members:
htdbm -l users.dbm
Apache setup
You’ll need to enable the required modules.
# a2enmod dav
# a2enmod dav_fs
# a2enmod authn_dbm
# a2enmod authz_dbm
The following is what I’m using for my apache.conf
DavLockDB /usr/local/apache2/var/DavLock
<IfModule mod_ssl.c>
<VirtualHost *:443>
DocumentRoot "/var/www/files.yoursite.com"
ServerName files.yoursite.com
SSLCertificateFile /etc/letsencrypt/live/files.yoursite.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/files.yoursite.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# Directory Listing Display Options
IndexOptions +FancyIndexing
IndexOptions +VersionSort
IndexOptions +HTMLTable
IndexOptions +FoldersFirst
IndexOptions +IconsAreLinks
IndexOptions +IgnoreCase
IndexOptions +XHTML
IndexOptions +NameWidth=*
IndexOptions +SuppressDescription
IndexOptions +SuppressHTMLPreamble
IndexOptions +Charset=UTF-8
# Make it responsive
IndexHeadInsert "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
# project1
Alias /project1 /var/www/webdav/project1
<Directory /var/www/webdav/project1>
DAV On
SSLRequireSSL
AuthType Basic
AuthName "webdav"
AuthBasicProvider dbm
AuthDBMUserFile "/usr/local/apache2/var/users.dbm"
AuthDBMGroupFile "/usr/local/apache2/var/users.dbm"
Require dbm-group project1
</Directory>
# project2
Alias /project2 /var/www/webdav/project2
<Directory /var/www/webdav/project2>
DAV On
SSLRequireSSL
AuthType Basic
AuthName "webdav"
AuthBasicProvider dbm
AuthDBMUserFile "/usr/local/apache2/var/users.dbm"
AuthDBMGroupFile "/usr/local/apache2/var/users.dbm"
Require dbm-group project2
</Directory>
</VirtualHost>
</IfModule>
As always check your config is correct
# apachectl -t
Syntax OK
Restart Apache
# systemctl restart apache2
Each time you have a new project, you can just copy the Alias and directory block, at the bottom like so.
DavLockDB /usr/local/apache2/var/DavLock
<IfModule mod_ssl.c>
<VirtualHost *:443>
DocumentRoot "/var/www/files.yoursite.com"
ServerName files.yoursite.com
SSLCertificateFile /etc/letsencrypt/live/files.yoursite.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/files.yoursite.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# Directory Listing Display Options
IndexOptions +FancyIndexing
IndexOptions +VersionSort
IndexOptions +HTMLTable
IndexOptions +FoldersFirst
IndexOptions +IconsAreLinks
IndexOptions +IgnoreCase
IndexOptions +XHTML
IndexOptions +NameWidth=*
IndexOptions +SuppressDescription
IndexOptions +SuppressHTMLPreamble
IndexOptions +Charset=UTF-8
# Make it responsive
IndexHeadInsert "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
# project1
Alias /project1 /var/www/webdav/project1
<Directory /var/www/webdav/project1>
DAV On
SSLRequireSSL
AuthType Basic
AuthName "webdav"
AuthBasicProvider dbm
AuthDBMUserFile "/usr/local/apache2/var/users.dbm"
AuthDBMGroupFile "/usr/local/apache2/var/users.dbm"
Require dbm-group project1
</Directory>
# project2
Alias /project2 /var/www/webdav/project2
<Directory /var/www/webdav/project2>
DAV On
SSLRequireSSL
AuthType Basic
AuthName "webdav"
AuthBasicProvider dbm
AuthDBMUserFile "/usr/local/apache2/var/users.dbm"
AuthDBMGroupFile "/usr/local/apache2/var/users.dbm"
Require dbm-group project2
</Directory>
# project3
Alias /project3 /var/www/webdav/project3
<Directory /var/www/webdav/project3>
DAV On
SSLRequireSSL
AuthType Basic
AuthName "webdav"
AuthBasicProvider dbm
AuthDBMUserFile "/usr/local/apache2/var/users.dbm"
AuthDBMGroupFile "/usr/local/apache2/var/users.dbm"
Require dbm-group project3
</Directory>
</VirtualHost>
</IfModule>
Hopefully, this will save someone a few hours of digging around Apache mailing lists. Or looking through the source code for comments.
In a future post, I’ll tackle another item on my todo list – making the directory listing look a bit better. It’s not unbearable, but it’s a bit disappointing that in 2021, the default page is not even responsive. Hence the IndexHeaderInsert override in the apache conf.
October 2023 Update
I forgot to mention I’m now using mod_macro which simplifies setting up new shares:
<Macro WebDAVShare $alias>
Alias /$alias /var/www/myserver.tld/$alias
<Directory /var/www/myserver.tld/$alias>
DAV On
SSLRequireSSL
AuthType Basic
AuthName "webdav"
AuthBasicProvider dbm
AuthDBMUserFile "/usr/local/apache2/var/users.dbm"
AuthDBMGroupFile "/usr/local/apache2/var/users.dbm"
Require dbm-group admin $alias
</Directory>
<Directory /var/www/myserver.tld/$alias/cgi-bin/*>
Options ExecCGI
SetHandler cgi-script
DirectoryIndex
</Directory>
</Macro>
Use WebDAVShare simon
Use WebDAVShare bob
Use WebDAVShare alice
Use WebDAVShare some_other_site
I’ve also started using an admin
group. This group can access any webdav share (as shown in the conf). I add myself to that group, so if there’s a problem with a share, I can access it and troubleshoot any problems.
$ htdbm -t users.dbm simon@mydomain.com "admin"