Difference between revisions of "Let’s Encrypt"
(Fix warning template) |
(Use let’s encrypt template) |
||
Line 232: | Line 232: | ||
And finally just get you certificate | And finally just get you certificate | ||
− | |||
− | |||
− | |||
− | + | {{Let’s Encrypt/New Cert Command|domain = imap.example.org|command = service dovecot reload | |
− | + | [ ok ] Reloading IMAP/POP3 mail server: dovecot}}Note that the command will create only one certificate per execution. If you added multiple of them, you need to run the command multiple times.[[Category:Debian Release]] | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | service dovecot reload | ||
− | [ ok ] Reloading IMAP/POP3 mail server: dovecot | ||
− | |||
− | Note that the command will create only one certificate per execution. If you added multiple of them, you need to run the command multiple times. | ||
− | |||
− | [[Category:Debian Release]] | ||
[[Category:Linux Server]] | [[Category:Linux Server]] | ||
[[Category:Web Server]] | [[Category:Web Server]] |
Revision as of 21:46, 21 March 2016
Warning: | These instructions were only tested on Debian. It will probably work for other Linux distributions, but you might need to adapt the provided instructions. |
This guide will show you how to get free certificates using Let’s Encrypt.
While Let’s Encrypt provide scripts that are able to edit your webserver configuration files, I don’t trust anyone enough to do that. Let’s Encrypt scripts will only be used to create and renew certificates.
Warning: Let’s Encrypt is still a very young project. While certificate creation is working pretty well, scripts are still changing rapidly. Stay tuned and be prepared to update your configuration.
Prerequisite
This guide assume that you have an Nginx server running and listening on port 80.
The certificates can be then used for other purposes, like email server. Nginx is only used for the renewal process.
Installation
If you are using Debian Jessie, you will need to configure jessie-backports source for the following command to work.
# apt install letsencrypt/jessie-backports
Configuration
Register Account
Although not mandatory, it is recommended to provide an email when registering your account. Make sure you enter it right as Let’s Encrypt will not validate it.
# letsencrypt certonly --standalone -n --agree-tos --email youremail@example.org
Missing command line flag or config entry for this setting:
Please enter in your domain name(s) (comma and/or space separated)
(You can set this with the --domains flag)
IMPORTANT NOTES:
- If you lose your account credentials, you can recover through
e-mails sent to logs-letsencrypt-anjie@meurisse.org.
- Your account credentials have been saved in your Let's Encrypt
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Let's
Encrypt so making regular backups of this folder is ideal.
The error about missing parameter is normal. You should be looking at the IMPORTANT NOTES section in the output.
Nginx
- First create folder
/var/www/acme-challenge
# mkdir -p /var/www/acme-challenge/.well-known/acme-challenge
# chmod -R 750 /var/www/acme-challenge
# chown -R root:www-data /var/www/acme-challenge
- Create file
/etc/nginx/snippets/acme-challenge.conf
location ^~ /.well-known/acme-challenge/ {
root /var/www/acme-challenge;
auth_basic off;
allow all;
}
Renewal Script
Let’s Encrypt delivers certificates that are valid for 90 days. It make automatic renewal an important part of the setup. They also have a limit of 5 certificates per week per domain.
In order to avoid blocking your domain (in case you need to create a new certificate), the following script will renew at most one certificate per run and will run every two days.
Certificates are renewed 30d before expiry. Additionally, if a certificate is close to expiry (20 days) a warning will be displayed with details.
- Save the following file as
/usr/local/sbin/renew_certificates
and make it executable
#! /usr/bin/env python
from datetime import timedelta, date
import time
import os.path
import subprocess
import OpenSSL
import pyrfc3339
# Configure your certificates here
# Each item in the list represent one certificate
# If domains list contains multiple domains, the first one is used as filename for the certificate
config = []
RENEW_CMD = '/usr/bin/letsencrypt'
RENEW_ARGS = ['certonly', '--non-interactive', '-a', 'webroot', '--webroot-path', '/var/www/acme-challenge/', '--keep-until-expiring', '--expand']
LIVE_FOLDER = '/etc/letsencrypt/live/'
CERT_FILE = '/cert.pem'
RENEW_DATE = timedelta(days=30)
ALERT_DATE = timedelta(days=20)
def get_date(cert_path):
if os.path.isfile(cert_path):
with open(cert_path) as f:
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
timestamp = OpenSSL.crypto.X509.get_notAfter(x509)
reformatted_timestamp = [timestamp[0:4], "-", timestamp[4:6], "-",
timestamp[6:8], "T", timestamp[8:10], ":",
timestamp[10:12], ":", timestamp[12:]]
return pyrfc3339.parse("".join(reformatted_timestamp)).date()
else:
return date.min
def get_next_renew():
mindate = date.max
cert = None
for conf in config:
main_name = conf.get('domains')[0]
filename = LIVE_FOLDER + main_name + CERT_FILE
expiration = get_date(filename)
if expiration < mindate:
mindate = expiration
cert = {
'file': filename,
'domains': conf.get('domains'),
'reload': conf.get('reload'),
'expiration': expiration
}
return cert
def should_renew(cert):
now = date.today()
return cert.get('expiration') - now < RENEW_DATE
def should_alert(cert):
now = date.today()
return cert.get('expiration') - now < ALERT_DATE
def renew(cert):
cmd = renew_cmd(cert)
subprocess.call(cmd)
def renew_cmd(cert):
return [RENEW_CMD] + RENEW_ARGS + [arg for domain in cert.get('domains') for arg in ['-d', domain]]
def after_cert(cert):
if 'reload' in cert:
print 'Restarting services:'
for cmd in cert.get('reload'):
print ' '.join(cmd)
subprocess.call(cmd)
if __name__ == "__main__":
next = get_next_renew()
if should_renew(next):
print 'Renewing certificate for ' + ', '.join(next.get('domains')) + ' that will expire on ' + next.get('expiration').isoformat() + '\n\n'
renew(next)
# Waiting OCSP responses
# https://community.letsencrypt.org/t/ocsp-server-sometimes-has-malformed-response-of-5-bytes-or-unauthorized/10568/10
time.sleep(5)
was_renewed = get_date(next.get('file')) != next.get('expiration')
if was_renewed:
after_cert(next)
next = get_next_renew()
if should_alert(next):
print """
=============================================================
WARNING
=============================================================
Your certificate for %s will expire on %s
Certificate should have been renewed already. Maybe there is a issue with renewal process.
Renew command
%s
""" % (', '.join(next.get('domains')), next.get('expiration').isoformat(), ' '.join(renew_cmd(next)))
- You can then run it automatically during the night. Add this to the file
/etc/crontab
12 4 */2 * * root /usr/local/sbin/renew_certificates
Create Certificate
Web Server
Let’s encrypt require a website to work on port 80 before delivering a certificate for your domain.
If you are creating a certificate for a website, you simply need to first create the configuration for Nginx.
If your certificate is not intended for the web (SMTP, IMAP, Jabber…), you can create a dedicated config in Nginx
# touch /etc/nginx/sites-available/noweb
# ln -s /etc/nginx/sites-available/noweb /etc/nginx/sites-enabled
Edit the file as bellow. There should be one server_name
per domain in your certificates. Note that this configuration need to stay in place after you got the certificate as certificates are renewed automatically every 60 day.
server {
include snippets/listen-http.conf;
server_name smtp.example.org;
server_name imap.example.org;
include snippets/acme-challenge.conf;
deny all;
}
Make sure you reload Nginx config
# service nginx reload
Certificate
Now, you just need to add your certificate to the config
list in /usr/local/sbin/renew_certificates
. Each certificate is represented y a dict with two keys:
domains
- The list of domains to be included in the certificate. The order is important as the first is domain is used for certificate file name.
reload
- List of commands to be executed after certificate creation. Each command is represented by a list: first item is the command, next ones are arguments.
Here are some examples:
config = [{
'domains': ['www.example.org', 'example.org'],
'reload': [['/usr/sbin/service', 'nginx', 'reload']]
}, {
'domains': ['imap.example.org'],
'reload': [['/usr/sbin/service', 'dovecot', 'reload']]
}, {
'domains': ['smtp.example.org'],
'reload': [['/usr/local/bin/myCustomCommand'], ['/usr/sbin/service', 'dovecot', 'reload']]
}]
And finally just get you certificate
$ sudo /usr/local/sbin/certmanage
Renewing certificate for imap.example.org that will expire on 0001-01-01
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for imap.example.org
Using the webroot path /var/www/acme-challenge for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/1764_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/1764_csr-certbot.pem
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/imap.example.org/fullchain.pem. Your cert
will expire on 2025-03-04. To obtain a new or tweaked version of
this certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Restarting services:
service dovecot reload
[ ok ] Reloading IMAP/POP3 mail server: dovecot
Note that the command will create only one certificate per execution. If you added multiple of them, you need to run the command multiple times.