Creating a full WebDAV support server with Nginx on CentOS 7

Up to some iPad Pro apps requirement, I need a WebDAV solution sync my notes and document. I can set up a WebDAV server with Apache easily so far, but I loathe the large Apache binary as much as ever. By the way, I am a big Nginx fan. To accomplish this, I decided to run WebDAV via the Nginx.

Unfortunately, Nginx doesn’t support the PROPFIN and OPTIONS methods. I need to do something to make everything well. So I found an Nginx module allow us to run WebDAV with those two methods. Let’s go start.

1. Prepare

Install the libraries we need via the yum package manager.

First, install the EPEL Repository.

# Install the EPEL repository.
yum install epel-release -y
yum update -y

You need the development repository to compile the WebDAV dynamic module for Nginx.

yum groupinstall "Development Tools" -y
yum install yum-utils pcre-devel zlib-devel libxslt-devel libxml2-devel -y

2. Installing Nginx

Install the official stable/mainline version Nginx via the yum package manager. You can find the repository file from Nginx.org.

Create a yum repository file named /etc/yum.repos.d/nginx.repo with the following content.

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

At this point, you should be able to install the pre-built Nginx package with dynamic module support.

yum install nginx -y
systemctl enable nginx
systemctl start nginx

3. Compile Module

Download the Nginx and the module source code, and you need to determine which Nginx version is running on your server.

Determine running Nginx version:

nginx -v

nginx version: nginx/1.16.1

Download the source code corresponding to the installed version:

wget http://nginx.org/download/nginx-1.16.1.tar.gz

Clone the module repository:

git clone https://github.com/arut/nginx-dav-ext-module

Change to the Nginx source code directory, compile the module, and copy it to the standard directory for the Nginx modules.

cd nginx-1.16.1
./configure --with-compat --with-http_dav_module --add-dynamic-module=../nginx-dav-ext-module/
make modules
cp objs/ngx_http_dav_ext_module.so /etc/nginx/modules/

4. Configure

At the final stage, you need to load this module and set up an appropriate configuration file.

Create a root directory for WebDAV:

mkdir -p /var/www/webdav/temp

I generate the SSL certificate from Let’s Encrypt, and I would like to recommend ACME.SH. That was a fantastic script, apply Let’s Encrypt certificate with bash shell only.

curl https://get.acme.sh | sh
acme.sh --issue --ecc --keylength ec-384 -d webdav.example.com -w /usr/share/nginx/html
acme.sh --installcert --ecc -d webdav.example.com --fullchain-file /etc/nginx/ssl/webdav.example.com.crt --key-file /etc/nginx/ssl/webdav.example.com.key --reloadcmd "systemctl reload nginx"

Here was the example configuration file contact for Nginx.1 You can generate your HTTP Basic authentification file with htpasswd.2

server {
    listen 80;
    listen [::]:80;
    server_name webdav.example.com;

    location /.well-known/acme-challenge/ {
        root /usr/share/nginx/html/;
        try_files $uri =404;
    }

    location / {
        # 301 Only work for GET/HEAD/OPTIONS, So we use 307 to temporary for POST go through.
        if ($request_method = POST) {
            return 307 https://$host$request_uri;
        }
        return 301 https://$host$request_uri;
        }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name webdav.example.com;
    root /var/www/webdav/;
    index index.html index.htm;
    access_log /var/log/nginx/webdav/access.log combined gzip;
    error_log /var/log/nginx/webdav/error.log warn;
    ssl_certificate /etc/nginx/ssl/webdav.example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/webdav.example.com.key;
    ssl_dhparam /etc/nginx/ssl/dhparams.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    add_header Strict-Transport-Security "max-age=31536000";
    add_header X-Content-Type-Options nosniff;

    location / {
        auth_basic "Restricted site.";
        auth_basic_user_file /etc/nginx/auth/webdav-users.passwd;
        client_body_temp_path /var/www/webdav/temp;
        dav_methods PUT DELETE MKCOL COPY MOVE;
        dav_ext_methods PROPFIND OPTIONS;
        create_full_put_path on;
        dav_access user:rw group:rw all:rw;
        autoindex on;
    }
}

Reload the Nginx configuration.

# Use built-in validator to check the configuration file beforun reload.
nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

systemctl reload nginx

Then, enjoy your WebDAV server!

  1. Using 307 for HTTP POST request: https://opensource.ncsa.illinois.edu/confluence/display/ERGO/Creating+a+WebDAV+repository+server+with+NGINX 

  2. CentOS 7 need install the httpd-tools package to use htpasswd.