WebDAV

Background

The best approach to maintaining content on a small-scale webserver is to use WebDAV. This lets you remain with to HTTP protocols and conventions on for the whole stack. No messing about with firewalls, ftp or windows sharing.

On the content creator’s side, it’s built into the Operating System so they can use the File Manager they use everyday to manage their web content just like a local file. This simplifies support greatly.

Server Testing

Apache is the only major web server that fully supports the native file managers on major OSs (as of 2022). Nginx almost get’s there in our testing, but write-level access doesn’t quite work with Mac OS Finder. IIS is similarly lacking.

Deployment

Installation

We’re installing from repo and enabling the DAV modules using the debian tools rather than creating the symlinks ourselves.

sudo apt-get update
sudo apt-get install apache2
sudo a2enmod dav dav_fs dav_lock

Configuration

The best method is to use a site-based approach where we put our content and config in their own locations. We’re using the debian conventions for file locations here.

# Create the content folder
sudo mkdir /var/www/www.your.org
sudo chown www-data:www-data /var/www/www.your.org

# Check ownership on the WebDAV file lock database folder
# and chown -R www-data:root as needed.
ls -la /var/lock/apache2

# Create the config file
sudo vi /etc/apache2/sites-enabled/www.your.org

Here’s our example site.

DavLockDB /var/lock/apache2/DavLock

<VirtualHost *:80>
        ServerAdmin [email protected]
        DocumentRoot /var/www/www.your.org
        ServerName www.example.org
        ErrorLog ${APACHE_LOG_DIR}/wwwerror.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <Directory /var/www/test.your.local/>
                DAV On
                AuthType Digest
                AuthName "webdav"
                AuthUserFile /etc/apache2/users.password

                <LimitExcept GET POST OPTIONS HEAD>
                        Require user test
                </LimitExcept>
        </Directory>
</VirtualHost>

Useful notes:

If you leave out the DocumentRoot, apache will use a default value and present the default web site even when you have no sites enabled, driving you nuts until you finally find a hint about the default value being compiled differently for different distributions.

For authentication you should at least use HTTP Digest Authentication. Though it’s generally recognized that SSL should be deployed everywhere.

Limiting Access to WebDAV

The Require Directive

These two methods appear functionally equivalent. The first is the example from the Require Directive

<RequireAny>
     Require method GET POST OPTIONS
     Require valid-user
</RequireAny>

The second is the example from the WEBDAV module. NOTE - if you leave the ‘all granted’ you seem to mask

Require all granted
<LimitExcept GET POST OPTIONS>
	Require valid-user
</LimitExcept>

Apache’s LimitExcept directive is part of the core module, and the webdav example uses it, so we’re going with it here.

This article suggest the three methods below. HEAD is a common one, so it makes sense.

<Directory />
    <LimitExcept GET POST HEAD>
        deny from all
    </LimitExcept>
</Directory>

Or possibly

<LimitExcept GET POST OPTIONS PROPFIND>

The AuthBasicProvider is, in this case, optional, since file is the default value for this directive.

User Database LDAP/AD

Now that you’re requiring auth, you have to compare it against a user database. LDAP is a possibility.

First, enable the LDAP module:

a2enmod authnz_ldap 

Then config with an ldap source.

DavLockDB /usr/local/apache2/var/DavLock

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/test.your.local
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <Directory /var/www/test.your.local/>
                DAV On
                AuthName "YOUR"
                AuthType Basic
                AuthBasicProvider ldap
                AuthLDAPBindDN [email protected]
                	# Creds are "svcapache/XXXXXX"
                AuthLDAPBindPassword XXXXX
                AuthLDAPURL "ldap://ldap.your.local:389/OU=People,DC=your,DC=local?uid?sub?(objectClass=*)"
                
                Require all granted
                <LimitExcept GET POST OPTIONS>
						Require valid-user
                </LimitExcept>
        </Directory>

</VirtualHost>

Last modified April 14, 2026: Old site imports (677647f)