<title>WebDAV with nginx · Sysadmining. All day. Every day.</title>
<metaname="description"content="This website has been hosted on an Online.net dedicated server since its creation. I&rsquo;ve been one of their customers for the past 3 years now, and I still "/>
<p>This website has been hosted on an <ahref="https://www.online.net">Online.net</a> dedicated server since its creation. I’ve been one of their customers for the past 3 years now, and I still don’t have anything bad to say about them.</p>
<p>They recently upgraded their personnal range, and I took the opportunity to upgrade from a single server running all of my services to 2 servers running LXC containers that are hosting my services.</p>
<p>It took me 2 days to migrate everything, but it was worth it. If I decide to switch servers again, I’ll have to migrate the containers instead of the services themselves. Considering they are stored on a separate BTRFS volume, it shouldn’t take me more than a few hours at most.</p>
<p>During the migration, I realized that I needed to make files that were hosted on one server accessible to the other. I could have gone with CIFS or NFS, but I wanted to have encryption built-in instead of having to rely on a VPN for that. Since I figured it was a good opportunity to learn something new, I ended up going with WebDAV.</p>
<p>In this tutorial, I’ll explain how I’ve configured a read-only WebDAV share using <ahref="https://www.nginx.com/">nginx</a> and <ahref="https://letsencrypt.org/">Let’sEncrypt</a> SSL certificates between two Debian Jessie containers.</p>
<p>We now need to configure nginx by adding the following in the <code>/etc/nginx/sites-available/default</code> file, anywhere in the <code>server{}</code> block that is configured to listen on port 80.</p>
<pre><code>location /.well-known/acme-challenge {
root /var/www/letsencrypt;
}
</code></pre>
<p>Let’s make sure that we haven’t done anything wrong :</p>
<pre><codeclass="language-bash">nginx -t
</code></pre>
<p>The command should give you the following output :</p>
<pre><code>nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
</code></pre>
<p>If that’s the case, you can safely reload the nginx daemon :</p>
<p><em>Please do modify www.example.com by your server’s FQDN, and please note that the letsencrypt servers need to be able to resolve that name to your server’s IP.</em></p>
<p>If everything goes well, your certificates will be generated and stored in the /etc/letsencrypt folder.</p>
<p><em>This configuration will work if you’re using a single certificate on your server. If not, you’ll have to remove the <code>ssl_certificate</code>, <code>ssl_certificate_key</code> and <code>ssl_trusted_certificate</code> directives from this file and move them to the correct <code>server{}</code> block.</em></p>
<p>We now need to generate a <code>dhparam.pem</code> file :</p>
<p>We now have to create a <code>/etc/nginx/sites-available/example</code> file that will contain our actual webdav configuration. This example makes a <code>data</code> folder stored in <code>/var/www/</code> accessible.</p>
<pre><code>server {
listen 80;
listen [::]:80;
server_name www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
root /var/www;
location / {
index index.html;
}
location /.well-known/acme-challenge {
root /var/www/letsencrypt;
}
location /data {
client_body_temp_path /tmp;
dav_methods PUT DELETE MKCOL COPY MOVE;
dav_ext_methods PROPFIND OPTIONS;
create_full_put_path on;
dav_access user:r group:r;
auth_basic "Restricted access";
auth_basic_user_file auth/webdav;
limit_except GET {
allow <YOUR IP HERE>;
deny all;
}
}
}
</code></pre>
<p>The last thing we have to do is to create a symlink so that nginx will load our configuration :</p>
<p>This goes beyond the scope of the article, but since letsencrypt certficates are only valid for 3 months, you’ll need to renew them regularily. You can do so manually or you can setup a cron that does it for you.</p>
echo "Something went wrong while renewing the certificates on $(hostname -f)
Manual action needed." | mail -s "Letsencrypt error on $(hostname -f)" $MAILDEST
fi
</code></pre>
<p>You can add multiple domains in the script. As long as you add all 3 lines for each domain, it will not automatically reload nginx if one or more certificate could not be renewed and will send an e-mail to the address configured in the <code>MAILDEST</code> variable.</p>
<p>You can configure this script in the root user crontab using the <code>crontab -e</code> command :</p>
<pre><code>## LETSENCRYPT CERTIFICATE AUTORENEWAL
30 03 01 */2 * /root/bin/tlsrenew
</code></pre>
<p>This will run the script every two months, on the first day of the month, at 3:30 AM.</p>
<h3id="mounting-the-share-manually">Mounting the share manually</h3>
<p>If like me, you want to mount your webdav share in a LXC container, you’ll first need to make sure that the following line is present in its configuration file :</p>
<pre><code>lxc.cgroup.devices.allow = c 10:229 rwm
</code></pre>
<p>You’ll also need to create the <code>/dev/fuse</code> node in the container :</p>
<pre><code>mknod /dev/fuse c 10 229
</code></pre>
<p>In any case, we have to edit the <code>/etc/davfs2/secrets</code> file to add the mount point, username and password that will be used to mount the share :</p>
<p>You might need to edit the parameters depending on which users you want to make the share available to.</p>
<h3id="mouting-the-share-on-boot">Mouting the share on boot</h3>
<p>A davfs volume can be mounted via the <code>/etc/fstab</code> file, but I decided to use monit instead so that the volume would be mounted again automatically should my WebDAV server reboot.</p>
<p>In order to do so, I first created a <code>davfs.txt</code> file in the <code>/var/www/data</code> folder on my WebDAV server :</p>
<pre><code>touch /var/www/data/davfs.txt
</code></pre>
<p>I then created the following <code>/root/bin/mount_davfs</code> script :</p>
<pre><code>#!/bin/bash
mknod /dev/fuse c 10 229
mount -t davfs https://www.example.com/data /data -o ro,dir_mode=750,file_mode=640,uid=root,gid=root
</code></pre>
<p>The last thing I did was create a <code>/etc/monit/conf.d/davfs</code> file with the following content :</p>
<pre><code>check file davfs with path /data/davfs.txt
alert monit@example.com
if does not exist then exec "/root/bin/mount_davfs"
</code></pre>
<p>That way, if monit notices that the <code>/data/davfs.txt</code> file becomes inaccessible for some reason, it will try remouting the share.</p>
<h2id="conclusion">Conclusion</h2>
<p>That’s all ! Hopefully this has been useful to someone. Please do comment below if you have any question or if this has been helpful !</p>
<sectionclass="poweredby">Proudly generated by <aclass="icon-hugo"href="http://gohugo.io">HUGO</a>, with <aclass="icon-theme"href="https://github.com/vjeantet/hugo-theme-casper">Casper</a> theme</section>