555 lines
32 KiB
HTML
555 lines
32 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
|
|
|
<title>WebDAV with nginx</title>
|
|
|
|
<link href="https://captainark.net/rss.xml" type="application/atom+xml" rel="alternate" title="Sysadmining. All day. Every day. Full Atom Feed" />
|
|
<!-- Bootstrap Core CSS -->
|
|
<link href="https://captainark.net/theme/css/bootstrap.min.css" rel="stylesheet">
|
|
|
|
<!-- Custom CSS -->
|
|
<link href="https://captainark.net/theme/css/clean-blog.min.css" rel="stylesheet">
|
|
|
|
<!-- Code highlight color scheme -->
|
|
<link href="https://captainark.net/theme/css/code_blocks/github.css" rel="stylesheet">
|
|
|
|
|
|
<!-- Custom Fonts -->
|
|
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
|
|
<link href='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
|
|
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
|
|
|
|
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
|
<!--[if lt IE 9]>
|
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
|
<![endif]-->
|
|
|
|
|
|
|
|
<meta name="description" content="This website has been hosted on an Online.net dedicated server since its creation. I've been one of their customers for the past 3 years ...">
|
|
|
|
<meta name="author" content="Antoine Joubert">
|
|
|
|
|
|
<meta property="og:locale" content="">
|
|
<meta property="og:site_name" content="Sysadmining. All day. Every day.">
|
|
|
|
<meta property="og:type" content="article">
|
|
<meta property="article:author" content="https://captainark.net/author/antoine-joubert.html">
|
|
<meta property="og:url" content="https://captainark.net/webdav-with-nginx.html">
|
|
<meta property="og:title" content="WebDAV with nginx">
|
|
<meta property="article:published_time" content="2016-03-26 00:00:00+01:00">
|
|
<meta property="og:description" content="This website has been hosted on an Online.net dedicated server since its creation. I've been one of their customers for the past 3 years ...">
|
|
|
|
<meta property="og:image" content="https://captainark.net//bg.png">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:site" content="@captainark">
|
|
<meta name="twitter:title" content="WebDAV with nginx">
|
|
|
|
<meta name="twitter:image" content="https://captainark.net//bg.png">
|
|
|
|
<meta name="twitter:description" content="This website has been hosted on an Online.net dedicated server since its creation. I've been one of their customers for the past 3 years ...">
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<!-- Navigation -->
|
|
<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
|
|
<div class="container-fluid">
|
|
<!-- Brand and toggle get grouped for better mobile display -->
|
|
<div class="navbar-header page-scroll">
|
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
|
<span class="sr-only">Toggle navigation</span>
|
|
<span class="icon-bar"></span>
|
|
<span class="icon-bar"></span>
|
|
<span class="icon-bar"></span>
|
|
</button>
|
|
<a class="navbar-brand" href="https://captainark.net/">Sysadmining. All day. Every day.</a>
|
|
</div>
|
|
|
|
<!-- Collect the nav links, forms, and other content for toggling -->
|
|
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
|
<ul class="nav navbar-nav navbar-right">
|
|
<li><a href="/">Homepage</a></li>
|
|
<li><a href="/rss.xml">RSS</a></li>
|
|
<li><a href="/categories.html">Categories</a></li>
|
|
|
|
<li><a href="https://captainark.net/pages/about.html">About</a></li>
|
|
<li><a href="https://captainark.net/pages/resume.html">Resume</a></li>
|
|
</ul>
|
|
</div>
|
|
<!-- /.navbar-collapse -->
|
|
</div>
|
|
<!-- /.container -->
|
|
</nav>
|
|
|
|
<!-- Page Header -->
|
|
<header class="intro-header" style="background-image: url('/bg.png')">
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
|
|
<div class="post-heading">
|
|
<h1>WebDAV with nginx</h1>
|
|
<span class="meta">Posted by
|
|
<a href="https://captainark.net/author/antoine-joubert.html">Antoine Joubert</a>
|
|
on Sat 26 March 2016
|
|
</span>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
|
|
<!-- Post Content -->
|
|
<article>
|
|
<p>This website has been hosted on an <a href="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 <a href="https://www.nginx.com/">nginx</a> and <a href="https://letsencrypt.org/">Let'sEncrypt</a> SSL certificates between two Debian Jessie containers.</p>
|
|
<h2>Server configuration</h2>
|
|
<h3>Installing the required packages</h3>
|
|
<p>First thing first, we need to install the packages we'll need for this configuration :</p>
|
|
<div class="highlight"><pre><span></span>apt update
|
|
|
|
apt -t jessie-backports install nginx letsencrypt
|
|
apt install apache2-utils
|
|
</pre></div>
|
|
|
|
|
|
<h3>Getting our first certificate from letsencrypt</h3>
|
|
<h4>letsencrypt configuration</h4>
|
|
<p>Let's create a configuration file for letsencrypt :</p>
|
|
<div class="highlight"><pre><span></span>mkdir /etc/letsencrypt
|
|
|
|
<span class="nb">echo</span> <span class="s1">'rsa-key-size = 3072</span>
|
|
<span class="s1">renew-by-default</span>
|
|
<span class="s1">text = True</span>
|
|
<span class="s1">agree-tos = True</span>
|
|
<span class="s1">renew-by-default = True</span>
|
|
<span class="s1">authenticator = webroot</span>
|
|
<span class="s1">email = admin@example.com</span>
|
|
<span class="s1">webroot-path = /var/www/letsencrypt/'</span> > /etc/letsencrypt/cli.ini
|
|
</pre></div>
|
|
|
|
|
|
<p><em>Please do modify admin@example.com by your actual e-mail address.</em></p>
|
|
<p>We also need to create the directory structure where letsencrypt ACME challenge temporary files will be stored :</p>
|
|
<div class="highlight"><pre><span></span>mkdir -p /var/www/letsencrypt/.well-known
|
|
</pre></div>
|
|
|
|
|
|
<h4>nginx configuration</h4>
|
|
<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>
|
|
<div class="highlight"><pre><span></span>location /.well-known/acme-challenge {
|
|
root /var/www/letsencrypt;
|
|
}
|
|
</pre></div>
|
|
|
|
|
|
<p>Let's make sure that we haven't done anything wrong :</p>
|
|
<div class="highlight"><pre><span></span>nginx -t
|
|
</pre></div>
|
|
|
|
|
|
<p>The command should give you the following output :</p>
|
|
<div class="highlight"><pre><span></span><span class="n">nginx</span><span class="o">:</span> <span class="n">the</span> <span class="n">configuration</span> <span class="n">file</span> <span class="sr">/etc/nginx/</span><span class="n">nginx</span><span class="o">.</span><span class="na">conf</span> <span class="n">syntax</span> <span class="k">is</span> <span class="n">ok</span>
|
|
<span class="n">nginx</span><span class="o">:</span> <span class="n">configuration</span> <span class="n">file</span> <span class="sr">/etc/nginx/</span><span class="n">nginx</span><span class="o">.</span><span class="na">conf</span> <span class="n">test</span> <span class="k">is</span> <span class="n">successful</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>If that's the case, you can safely reload the nginx daemon :</p>
|
|
<div class="highlight"><pre><span></span>nginx -s reload
|
|
</pre></div>
|
|
|
|
|
|
<h4>Certificate request</h4>
|
|
<p>Now that letsencrypt and nginx are properly configured, we can request our certificate from letsencrypt :</p>
|
|
<div class="highlight"><pre><span></span>letsencrypt --config /etc/letsencrypt/cli.ini certonly -w /var/www/letsencrypt -d www.example.com
|
|
</pre></div>
|
|
|
|
|
|
<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>
|
|
<h3>WebDAV configuration</h3>
|
|
<p>Now that we've obtained our certificate from letsencrypt, we can begin configuring nginx.</p>
|
|
<p>First, we need to comment two SSL directives from the default nginx configuration :</p>
|
|
<div class="highlight"><pre><span></span>sed -i '/ssl_/ s/^/#/' /etc/nginx/nginx.conf
|
|
</pre></div>
|
|
|
|
|
|
<p>Let's now create a <code>/etc/nginx/conf.d/ssl.conf</code> with the following content :</p>
|
|
<div class="highlight"><pre><span></span><span class="nt">ssl_session_timeout</span> <span class="nt">1d</span><span class="o">;</span>
|
|
<span class="nt">ssl_session_cache</span> <span class="nt">shared</span><span class="nd">:SSL:50m</span><span class="o">;</span>
|
|
<span class="nt">ssl_session_tickets</span> <span class="nt">off</span><span class="o">;</span>
|
|
|
|
<span class="nt">ssl_certificate</span> <span class="o">/</span><span class="nt">etc</span><span class="o">/</span><span class="nt">letsencrypt</span><span class="o">/</span><span class="nt">live</span><span class="o">/</span><span class="nt">www</span><span class="nc">.example.com</span><span class="o">/</span><span class="nt">fullchain</span><span class="nc">.pem</span><span class="o">;</span>
|
|
<span class="nt">ssl_certificate_key</span> <span class="o">/</span><span class="nt">etc</span><span class="o">/</span><span class="nt">letsencrypt</span><span class="o">/</span><span class="nt">live</span><span class="o">/</span><span class="nt">www</span><span class="nc">.example.com</span><span class="o">/</span><span class="nt">privkey</span><span class="nc">.pem</span><span class="o">;</span>
|
|
<span class="nt">ssl_trusted_certificate</span> <span class="o">/</span><span class="nt">etc</span><span class="o">/</span><span class="nt">letsencrypt</span><span class="o">/</span><span class="nt">live</span><span class="o">/</span><span class="nt">www</span><span class="nc">.example.com</span><span class="o">/</span><span class="nt">fullchain</span><span class="nc">.pem</span><span class="o">;</span>
|
|
|
|
<span class="nt">ssl_dhparam</span> <span class="o">/</span><span class="nt">etc</span><span class="o">/</span><span class="nt">nginx</span><span class="o">/</span><span class="nt">ssl</span><span class="o">/</span><span class="nt">dhparam</span><span class="nc">.pem</span><span class="o">;</span>
|
|
|
|
<span class="nt">ssl_protocols</span> <span class="nt">TLSv1</span> <span class="nt">TLSv1</span><span class="nc">.1</span> <span class="nt">TLSv1</span><span class="nc">.2</span><span class="o">;</span>
|
|
<span class="nt">ssl_ciphers</span> <span class="s1">'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'</span><span class="o">;</span>
|
|
<span class="nt">ssl_prefer_server_ciphers</span> <span class="nt">on</span><span class="o">;</span>
|
|
|
|
<span class="nt">add_header</span> <span class="nt">Strict-Transport-Security</span> <span class="nt">max-age</span><span class="o">=</span><span class="nt">15768000</span><span class="o">;</span>
|
|
<span class="nt">add_header</span> <span class="nt">X-Frame-Options</span> <span class="nt">DENY</span><span class="o">;</span>
|
|
<span class="nt">add_header</span> <span class="nt">X-Content-Type-Options</span> <span class="nt">nosniff</span><span class="o">;</span>
|
|
|
|
<span class="nt">ssl_stapling</span> <span class="nt">on</span><span class="o">;</span>
|
|
<span class="nt">ssl_stapling_verify</span> <span class="nt">on</span><span class="o">;</span>
|
|
<span class="nt">resolver</span> <span class="nt">127</span><span class="nc">.0.0.1</span> <span class="nt">valid</span><span class="o">=</span><span class="nt">300s</span><span class="o">;</span>
|
|
<span class="nt">resolver_timeout</span> <span class="nt">5s</span><span class="o">;</span>
|
|
</pre></div>
|
|
|
|
|
|
<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>
|
|
<div class="highlight"><pre><span></span>mkdir /etc/nginx/ssl <span class="o">&&</span> chmod <span class="m">700</span> /etc/nginx/ssl
|
|
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 3072
|
|
chmod <span class="m">600</span> /etc/nginx/ssl/dhparam.pem
|
|
</pre></div>
|
|
|
|
|
|
<p>Let's now generate a HTTP basic authentication file. This example creates a user named example :</p>
|
|
<div class="highlight"><pre><span></span>mkdir /etc/nginx/auth
|
|
|
|
htpasswd -c /etc/nginx/auth/webdav example
|
|
New password:
|
|
Re-type new password:
|
|
Adding password for user user
|
|
</pre></div>
|
|
|
|
|
|
<p>This file has to be readable by the user running your webserver. For security reasons, we'll make it readable only by him :</p>
|
|
<div class="highlight"><pre><span></span>chown -R www-data:nogroup /etc/nginx/auth
|
|
chmod 700 /etc/nginx/auth
|
|
chmod 400 /etc/nginx/auth/webdav
|
|
</pre></div>
|
|
|
|
|
|
<p>Let's now modify our <code>/etc/nginx/sites-available/default</code> file with the following content :</p>
|
|
<div class="highlight"><pre><span></span>server {
|
|
listen 80 default_server;
|
|
listen [::]:80 default_server ipv6only=on;
|
|
server_name "";
|
|
|
|
return 444;
|
|
}
|
|
|
|
server {
|
|
listen 443 default_server ssl http2;
|
|
listen [::]:443 default_server ipv6only=on ssl http2;
|
|
server_name "";
|
|
|
|
return 444;
|
|
}
|
|
</pre></div>
|
|
|
|
|
|
<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>
|
|
<div class="highlight"><pre><span></span><span class="nt">server</span> <span class="p">{</span>
|
|
<span class="n">listen</span> <span class="m">80</span><span class="p">;</span>
|
|
<span class="n">listen</span> <span class="cp">[</span><span class="p">::</span><span class="cp">]</span><span class="o">:</span><span class="m">80</span><span class="p">;</span>
|
|
<span class="n">server_name</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">;</span>
|
|
<span class="n">return</span> <span class="m">301</span> <span class="n">https</span><span class="o">://</span><span class="err">$</span><span class="n">server_name</span><span class="err">$</span><span class="n">request_uri</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="nt">server</span> <span class="p">{</span>
|
|
<span class="n">listen</span> <span class="m">443</span> <span class="n">ssl</span> <span class="n">http2</span><span class="p">;</span>
|
|
<span class="n">listen</span> <span class="cp">[</span><span class="p">::</span><span class="cp">]</span><span class="o">:</span><span class="m">443</span> <span class="n">ssl</span> <span class="n">http2</span><span class="p">;</span>
|
|
<span class="n">server_name</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">;</span>
|
|
|
|
<span class="n">root</span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">www</span><span class="p">;</span>
|
|
|
|
<span class="n">location</span> <span class="o">/</span> <span class="err">{</span>
|
|
<span class="n">index</span> <span class="n">index</span><span class="o">.</span><span class="n">html</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="nt">location</span> <span class="o">/</span><span class="nc">.well-known</span><span class="o">/</span><span class="nt">acme-challenge</span> <span class="p">{</span>
|
|
<span class="n">root</span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">www</span><span class="o">/</span><span class="n">letsencrypt</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="nt">location</span> <span class="o">/</span><span class="nt">data</span> <span class="p">{</span>
|
|
<span class="n">client_body_temp_path</span> <span class="o">/</span><span class="n">tmp</span><span class="p">;</span>
|
|
<span class="n">dav_methods</span> <span class="n">PUT</span> <span class="n">DELETE</span> <span class="n">MKCOL</span> <span class="n">COPY</span> <span class="n">MOVE</span><span class="p">;</span>
|
|
<span class="n">dav_ext_methods</span> <span class="n">PROPFIND</span> <span class="n">OPTIONS</span><span class="p">;</span>
|
|
<span class="n">create_full_put_path</span> <span class="n">on</span><span class="p">;</span>
|
|
<span class="n">dav_access</span> <span class="n">user</span><span class="o">:</span><span class="n">r</span> <span class="n">group</span><span class="o">:</span><span class="n">r</span><span class="p">;</span>
|
|
|
|
<span class="n">auth_basic</span> <span class="s2">"Restricted access"</span><span class="p">;</span>
|
|
<span class="n">auth_basic_user_file</span> <span class="n">auth</span><span class="o">/</span><span class="n">webdav</span><span class="p">;</span>
|
|
|
|
<span class="n">limit_except</span> <span class="n">GET</span> <span class="err">{</span>
|
|
<span class="n">allow</span> <span class="o"><</span><span class="n">YOUR</span> <span class="n">IP</span> <span class="n">HERE</span><span class="o">></span><span class="p">;</span>
|
|
<span class="n">deny</span> <span class="n">all</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="err">}</span>
|
|
|
|
<span class="err">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>The last thing we have to do is to create a symlink so that nginx will load our configuration :</p>
|
|
<div class="highlight"><pre><span></span>ln -s /etc/nginx/sites-available/example /etc/nginx/sites-enabled/example
|
|
</pre></div>
|
|
|
|
|
|
<p>Like before, let's make sure our configuration is correct and then reload the daemon :</p>
|
|
<div class="highlight"><pre><span></span>nginx -t
|
|
nginx -s reload
|
|
</pre></div>
|
|
|
|
|
|
<p>That's it for the WebDAV configuration server-side !</p>
|
|
<h3>nginx monitoring</h3>
|
|
<p>If you're using monit, you can easily monitor the nginx daemon by copying the following in <code>/etc/monit/conf.d/nginx</code> :</p>
|
|
<div class="highlight"><pre><span></span>check process nginx
|
|
with pidfile "/run/nginx.pid"
|
|
start program = "/bin/systemctl start nginx"
|
|
stop program = "/bin/systemctl stop nginx"
|
|
alert monit@example.com
|
|
</pre></div>
|
|
|
|
|
|
<h3>Certificates auto-renewal</h3>
|
|
<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>
|
|
<p>I personnaly use the following script :</p>
|
|
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
15
|
|
16
|
|
17</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
|
|
|
|
<span class="nv">PRG</span><span class="o">=</span><span class="s2">"/usr/bin/letsencrypt"</span>
|
|
<span class="nv">CONFIG</span><span class="o">=</span><span class="s2">"/etc/letsencrypt/cli.ini"</span>
|
|
<span class="nv">MAILDEST</span><span class="o">=</span><span class="s2">"admin@example.com"</span>
|
|
<span class="nv">GLOBAL</span><span class="o">=</span>0
|
|
|
|
<span class="c1"># www.example.com</span>
|
|
<span class="nv">$PRG</span> --config <span class="nv">$CONFIG</span> certonly -w /var/www/letsencrypt -d www.example.com
|
|
<span class="o">[[</span> <span class="nv">$?</span> !<span class="o">=</span> <span class="m">0</span> <span class="o">]]</span> <span class="o">&&</span> <span class="nv">GLOBAL</span><span class="o">=</span><span class="k">$((</span> <span class="nv">$GLOBAL</span> <span class="o">+</span> <span class="m">1</span> <span class="k">))</span>
|
|
|
|
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$GLOBAL</span> <span class="o">==</span> <span class="m">0</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
|
|
/usr/sbin/nginx -s reload
|
|
<span class="k">else</span>
|
|
<span class="nb">echo</span> <span class="s2">"Something went wrong while renewing the certificates on </span><span class="k">$(</span>hostname -f<span class="k">)</span><span class="s2"></span>
|
|
<span class="s2"> Manual action needed."</span> <span class="p">|</span> mail -s <span class="s2">"Letsencrypt error on </span><span class="k">$(</span>hostname -f<span class="k">)</span><span class="s2">"</span> <span class="nv">$MAILDEST</span>
|
|
<span class="k">fi</span>
|
|
</pre></div>
|
|
</td></tr></table>
|
|
|
|
<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>
|
|
<div class="highlight"><pre><span></span>## LETSENCRYPT CERTIFICATE AUTORENEWAL
|
|
30 03 01 */2 * /root/bin/tlsrenew
|
|
</pre></div>
|
|
|
|
|
|
<p>This will run the script every two months, on the first day of the month, at 3:30 AM.</p>
|
|
<h2>Client configuration</h2>
|
|
<h3>Installing the required packages</h3>
|
|
<p>A single package is required to mount a webdav volume on Debian :</p>
|
|
<div class="highlight"><pre><span></span>apt update && apt install davfs2
|
|
</pre></div>
|
|
|
|
|
|
<h3>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>
|
|
<div class="highlight"><pre><span></span>lxc.cgroup.devices.allow = c 10:229 rwm
|
|
</pre></div>
|
|
|
|
|
|
<p>You'll also need to create the <code>/dev/fuse</code> node in the container :</p>
|
|
<div class="highlight"><pre><span></span>mknod /dev/fuse c 10 229
|
|
</pre></div>
|
|
|
|
|
|
<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>
|
|
<div class="highlight"><pre><span></span>echo '/data webdav notanactualpassword' >> /etc/davfs2/secrets
|
|
</pre></div>
|
|
|
|
|
|
<p>Once that's done, we can mount our share with the following command :</p>
|
|
<div class="highlight"><pre><span></span>mount -t davfs https://www.example.com/data /data -o ro,dir_mode=750,file_mode=640,uid=root,gid=root
|
|
</pre></div>
|
|
|
|
|
|
<p>You might need to edit the parameters depending on which users you want to make the share available to.</p>
|
|
<h3>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>
|
|
<div class="highlight"><pre><span></span>touch /var/www/data/davfs.txt
|
|
</pre></div>
|
|
|
|
|
|
<p>I then created the following <code>/root/bin/mount_davfs</code> script :</p>
|
|
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
|
2
|
|
3
|
|
4</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
|
|
|
|
mknod /dev/fuse c <span class="m">10</span> 229
|
|
mount -t davfs https://www.example.com/data /data -o ro,dir_mode<span class="o">=</span>750,file_mode<span class="o">=</span>640,uid<span class="o">=</span>root,gid<span class="o">=</span>root
|
|
</pre></div>
|
|
</td></tr></table>
|
|
|
|
<p>The last thing I did was create a <code>/etc/monit/conf.d/davfs</code> file with the following content :</p>
|
|
<div class="highlight"><pre><span></span>check file davfs with path /data/davfs.txt
|
|
alert monit@example.com
|
|
if does not exist then exec "/root/bin/mount_davfs"
|
|
</pre></div>
|
|
|
|
|
|
<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>
|
|
<h2>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>
|
|
</article>
|
|
|
|
|
|
<hr>
|
|
<div class="sharing">
|
|
</div>
|
|
<hr>
|
|
|
|
<div class="comments">
|
|
<h2>Comments !</h2>
|
|
<div id="disqus_thread"></div>
|
|
<script type="text/javascript">
|
|
var disqus_shortname = 'captainark';
|
|
var disqus_identifier = 'webdav-with-nginx.html';
|
|
var disqus_url = 'https://captainark.net/webdav-with-nginx.html';
|
|
(function() {
|
|
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
|
|
dsq.src = '//captainark.disqus.com/embed.js';
|
|
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
|
})();
|
|
</script>
|
|
<noscript>Please enable JavaScript to view the comments.</noscript>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<!-- Footer -->
|
|
<footer>
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
|
|
<ul class="list-inline text-center">
|
|
<li>
|
|
<a href="mailto:contact@captainark.net">
|
|
<span class="fa-stack fa-lg">
|
|
<i class="fa fa-circle fa-stack-2x"></i>
|
|
<i class="fa fa-envelope fa-stack-1x fa-inverse"></i>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://twitter.com/captainark">
|
|
<span class="fa-stack fa-lg">
|
|
<i class="fa fa-circle fa-stack-2x"></i>
|
|
<i class="fa fa-twitter fa-stack-1x fa-inverse"></i>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://github.com/captainark">
|
|
<span class="fa-stack fa-lg">
|
|
<i class="fa fa-circle fa-stack-2x"></i>
|
|
<i class="fa fa-github fa-stack-1x fa-inverse"></i>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="http://www.last.fm/user/captainark">
|
|
<span class="fa-stack fa-lg">
|
|
<i class="fa fa-circle fa-stack-2x"></i>
|
|
<i class="fa fa-lastfm fa-stack-1x fa-inverse"></i>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://steamcommunity.com/id/captainark">
|
|
<span class="fa-stack fa-lg">
|
|
<i class="fa fa-circle fa-stack-2x"></i>
|
|
<i class="fa fa-steam fa-stack-1x fa-inverse"></i>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="http://www.twitch.tv/captainark">
|
|
<span class="fa-stack fa-lg">
|
|
<i class="fa fa-circle fa-stack-2x"></i>
|
|
<i class="fa fa-twitch fa-stack-1x fa-inverse"></i>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<p class="copyright text-muted">
|
|
Blog powered by <a href="http://getpelican.com">Pelican</a>,
|
|
which takes great advantage of <a href="http://python.org">Python</a>.
|
|
</p> </div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<!-- jQuery -->
|
|
<script src="https://captainark.net/theme/js/jquery.js"></script>
|
|
|
|
<!-- Bootstrap Core JavaScript -->
|
|
<script src="https://captainark.net/theme/js/bootstrap.min.js"></script>
|
|
|
|
<!-- Custom Theme JavaScript -->
|
|
<script src="https://captainark.net/theme/js/clean-blog.min.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
var _gaq = _gaq || [];
|
|
_gaq.push(['_setAccount', 'UA-53658366-1']);
|
|
_gaq.push(['_trackPageview']);
|
|
(function() {
|
|
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
|
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
|
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
|
})();
|
|
</script>
|
|
<script type="text/javascript">
|
|
var disqus_shortname = 'captainark';
|
|
(function () {
|
|
var s = document.createElement('script'); s.async = true;
|
|
s.type = 'text/javascript';
|
|
s.src = '//' + disqus_shortname + '.disqus.com/count.js';
|
|
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
|
|
}());
|
|
</script>
|
|
</body>
|
|
|
|
</html> |