(outdated) Tutorial for using free SSL/TLS certificates provided by "letsencrypt"

[Update 2018-08-13: This guide is now rather outdated. See the many excellent comments below for more details. Some basic Letsencrypt instructions have also been integrated in the official Seafile manual, both for nginx and for apache.]

Hi, I wrote a tutorial on how to use free TLS certificates with seafile:


The certificates are free, signed, valid and accepted by all current browsers. They’re provided by the Let’s Encrypt initiative.

My guide is based on the current “certbot” client provided by the EFF.

For convenience’s sake and to prevent dead links I reproduce a (slightly edited) copy of it below. Unfortunately I can’t guarantee to keep it up to date at all times. A previous article quickly became outdated due to the fast development of the whole letsencrypt/certbot approach. Feel free to contact me if you notice a problem with this guide.

1. Introduction

This guide is based on the assumption that Seafile is already up and running (with possibly a self-signed certificate): MySQL, nginx + SSL, Seafile. (In fact my original setup was on a raspberry pi, that’s why some data folders are located in /mnt/usbdrive.)

In this post I’ll show you how I’ve recently configured my Seafile installation to always have a perfectly valid and signed SSL/TLS-certificate that is accepted by all web browsers. And it’s free.

To achieve this I’m using a certificate from the “Let’s Encrypt” CA. The kind people from the Internet Security Research Group, the public benefit corporation behind Let’s Encrypt, have developed a custom protocol, ACME, in order to automate the usually cumbersome domain ownership verification procedures. Even though the provided certificates are very short-lived (3 months validity), the resulting setup is actually much less maintenance-intensive than my previous (free) StartCom StartSSL certificates: I don’t have to keep track of expiry dates, manually create certificates and signing requests, and so on. The whole premise of the Let’s Encrypt approach is to force the admin’s hands in
automating certificate handling, all while providing the necessary tools.

2. Installation

Since the Let’s Encrypt project is still in its infancy, I didn’t really consider any of the alternative ACME clients, I stayed with the official one, “certbot”. It has a multitude of plugins to facilitate its integration in an existing server setup. To be honest, though, I’m no fan of having an automated tool mess with my nginx configuration files. That’s why I elected to use the socalled webroot plugin.

Basically, I indicate to certbot where my webroot directory is located. The client in turn communicates with the Let’s Encrypt-ACME-server and puts some cryptographic tokens in a hidden subdirectory of the webroot. These are checked by the (remote) ACME-server in order to ascertain that the client (or rather the admin) truly has domain ownership (or at least administrative rights). Finally the (locally created!) certificates are signed by the CA and stored in /etc/letsencrypt/live. Do note that the ACME-server always checks the cryptographic token through http. (security reasons)
It does however follow redirects from http to https. (This just in case that you set up your server to listen on port 443 exclusively.)

To actually install certbot I refer you to the official documentation. Indeed, it very much depends on your linux distribution whether or not certbot is provided through your default package manager. Depending on the path you chose, you may end up with one of the following commands to interact with the ACME-servers: letsencrypt, letsencrypt-auto, certbot or certbot-auto. In this tutorial I’ll use the certbot command, but they’re all compatible in regard to the arguments they take. (letsencrypt is the old name of the client; certbot the new one.)

3. Preparing the webroot folder

The “webroot” method of the letsencrypt client presents a minor inconvenience when used in conjunction with Seafile: it requires an active webroot… However, in our case, the nginx web server is used as a simple FastCGI-Proxy for Seafile, i.e. it simply forwards incoming requests to one of seafile’s daemons.Hence the need for a slight modification to nginx’s config. But first we’ll create a “fake” webroot for nginx/seafile:
sudo mkdir /mnt/usbdrive/certbot-webroot
(/mnt/usbdrive corresponds to the drive on which I’ve installed Seafile. You could put the webroot anywhere you like.)
Then we add the additional location directive inside of the main server block:
# in /etc/nginx/sites-enabled/seafile:

location '/.well-known/acme-challenge' {
    default_type "text/plain";
    root /mnt/usbdrive/certbot-webroot;

Using this directive all requests to the acme-challenge folder will be redirected to the certbot-webroot folder.
Next step: reload nginx (sudo service nginx reload). Note that at no time we’ll have to truly shut down nginx.

4. Calling certbot

The first call to certbot instructs it to use the webroot plugin and create a certificate for the indicated domain.

sudo certbot certonly --webroot -w /mnt/usbdrive/certbot-webroot -d seafile.example.org

Certbot interactively asks for an e-mail address (for urgent notices and certificate revocation) and that’s about it! If everything works fine (check the program’s output!), the newly created (and signed!) certificates should be stored in /etc/letsencrypt/live/seafile.example.org. The last step of the initial setup consists in updating nginx’s config file to point to the new location of the certificate and key. (I suppose that you’re already hosting Seafile through SSL/TLS, even if it’s “only” with a self-signed certificate. If you’re using the Let’s Encrypt certificates for an initial setup, you should probably consult either the official manual for the specifics of configuring Seafile for SSL/TLS.)
ssl_certificate /etc/letsencrypt/live/seafile.example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/seafile.example.org/privkey.pem;

Now, reload nginx a second time and everything should work just fine. (If not, try reloading seafile too.)

5. Automating certificate renewal

The last piece of the puzzle, the crucial one, is to actually automate the renewal process. This has become very easy with certbot’s recent enhancements regarding exit codes and addition of a --quiet switch. Current versions are ready to be called directly through cron without having to use a wrapper script.

It’s sufficient to add a daily (or twice daily) call to either the system crontab or root’s own crontab. Type crontab -e as root in order to edit root’s crontab. Add the following line:

47 */12 * * * sleep 16; /path/to/certbot renew --quiet --post-hook "/usr/sbin/service nginx reload"

Please change the minutes number (47) and seconds number (16) to random integers between 0 and 59, in order to spread the load on the ACME-servers!

That should be all! Certbot only actually contacts the server if one of the configured certificates approaches its expiration date (leaving you a month to fix any upcoming issues). It only exits with code 1 if it encounters a serious problem. In this case cron will collect the error output and send an e-mail to the administrator. Obviously you should make sure that your crontab contains a working mailto directive! (e.g. MAILTO="admin@example.org")

Note (2016-08-10, certbot v0.8.1): Currently the command given to --post-hook is always executed even when no renewal attempt was made. This is a bug; it will be fixed in the next release. In the meantime you may reduce certbot’s frequency in crontab or use a simple wrapper script that checks the modification time of the certificate. (See the original blog post for a sample script.)

Further debugging output can be found in /var/log/letsencrypt.

I hope this write-up doesn’t contain too many errors. If you find any, please notify my in the comments.


This is great Hambier! I really appreciate your contribution on this.

Thank you very much!

I would love to add a link of your tutorial to my one because you provide a great alternative for an own certificate chain. I just would feel better if a copy of your tutorial would be available in your starting post to avoid dead links. Maybe you could add a copy commenting it as “current snapshot” (so that you don’t need to maintain 2 versions)?

You’re probably right… It’s done now! :wink:

1 Like

Have been looking for this for a while. Thanks very much!

Do you know how that would be done with Apache?

Hi, unfortunately I don’t have any experience concerning Apache, but I found this thread which could lead you in the right direction: https://community.letsencrypt.org/t/apache-multidomain-webroot/10663
It seems to me that you’ll just have to adapt the paths to your specific server setup.

If this works out could you please give a heads-up in this thread? Other Apache users may appreciate this, too.

Ill give it a shot…

Thanks @hambier for this great tutorial! Nice to have an A+ now on SSL Server Test (Powered by Qualys SSL Labs)! :slight_smile:

Just some questions to understand better what I did:

1.) cerbot-webroot/ just contains .well-known in my case and there is no data inside. I didn’t recognize any data saved here during the certbot command. So the cryptographic tokens are just temporary saved in there?

[quote=“hambier, post:1, topic:215, full:true”]
47 */12 * * * sleep 16; /path/to/certbot renew --quiet --post-hook "/usr/sbin/service nginx reload"[/quote]

2.) So if whereis certbot gives me certbot: /usr/bin/certbot /usr/share/man/man1/certbot.1.gz /usr/bin/certbot should be fine?

3.) Which means I just add a line MAILTO="admin@example.org" above the certbot line like this?

47 */12 * * * sleep 16; /usr/bin/certbot renew --quiet --post-hook "/usr/sbin/service nginx reload"

Congratulations on the A+!

I suppose that the webroot folder only holds temporary content for the duration of the client-server communication. I don’t know much about the technical details.

Yes, exactly.

You should also make sure that you’ve actually configured a working mailserver on your sever. You could try the following command which should send an email to the specified address:
echo "Hi, there" | mail -s "Test mail" me@somedomain.com

If you don’t like the idea of setting up a full-fledged mail server, you may just as well use a simple smtp relay server. (After a bit of trial & error I settled for msmtp in conjuction with heirloom-mailx to provide a “mail” binary.)

1 Like

Thanks, I’m already using Nullmailer for this which is very easy to set up.

Jfyi: Let’s Encrypt is asking for donations: https://www.generosity.com/community-fundraising/make-a-more-secure-web-with-let-s-encrypt

Edit: the page wants address data. Direct donation is only possible with PayPal. I have requested a way without PayPal or personal data for a third party. Will add information here if I get an answer from LE support.

Hi and thanks a lot for your tutorial.

I am getting an error message and don’t know why.

The message is:

>  - The following errors were reported by the server:

>    Domain: seafile.example.com
>    Type:   unauthorized
>    Detail: Invalid response from
>    http://seafile.example.com/.well-known/acme-challenge/c3t-DyxxxxxxxxxxIF4XYkxxxxxxxxxxxxgJyHI:
>    "<html>
>    <head><title>403 Forbidden</title></head>
>    <body bgcolor="white">
>    <center><h1>403 Forbidden</h1></center>
>    <hr><center>"

>    To fix these errors, please make sure that your domain name was
>    entered correctly and the DNS A record(s) for that domain
>    contain(s) the right IP address.

The IP Address is properly forwarded and theseafile server works on https://seafile.example.com

What am I doing wrong?

A bit of help would be very much appreciated,

Greetings, Chris


First of all, I’m sorry for the late reply. Hopefully my answer is still of value to you.

Here are some settings/issues you could check:

Is your server accessible through plain HTTP? (Without SSL-encryption) This is needed by letsencrypt. It’s not necessary to have all of seafile.example.com exposed through plain http, but your webserver must be listening on port 80.

This leads to question 2:

Is your nginx(?) server setup correct? You could try manually creating a testfile in /.well-known and check if it is accessible through your regular web browser. I’d guess it isn’t! It could be valuable to have a look at your nginx config file. Could you maybe post the relevant excerpts? In particular: where did you put the directive location '/.well-known/acme-challenge'?

I am looking for an letsencrypt solution for my setup with apache & seafile
Do you have any usefulle tips for me ?

Kind Regards

Sorry I never got around to doing it, I still use my traditional SSL.

I did get everything to work execpt:

47 */12 * * * sleep 16; /path/to/certbot renew --quiet --post-hook "/usr/sbin/service nginx reload"

how do I know the /path/to/certbot ? I have never typed a path to certbot?

whereis certbot

Thanks, how often do crontab -e look after renews?

Changes with crontab -e have immediate effect. So every 12 hours in minute 47 the command is being executed.

1 Like