Lets Encrypt SSL Certificates

Setup

mkdir /etc/letsencrypt
cd /etc/letsencrypt/
wget https://raw.githubusercontent.com/lukas2511/letsencrypt.sh/master/letsencrypt.sh
chmod +x letsencrypt.sh
mkdir certs
mkdir /var/www/letsencrypt/
chown -R www-data:www-data /var/www/letsencrypt/
config.sh
#!/bin/bash
 
########################################################
# This is the config file for letsencrypt.sh           #
#                                                      #
# This file is looked for in the following locations:  #
# $SCRIPTDIR/config.sh (next to this script)           #
# ${HOME}/.letsencrypt.sh/config.sh (in user home)     #
# /usr/local/etc/letsencrypt.sh/config.sh              #
# /etc/letsencrypt.sh/config.sh                        #
# ${PWD}/config.sh (in current working-directory)      #
#                                                      #
# Default values of this config are in comments        #
########################################################
 
# Path to certificate authority (default: https://acme-v01.api.letsencrypt.org/directory)
#CA="https://acme-v01.api.letsencrypt.org/directory"
 
# Path to license agreement (default: https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf)
#LICENSE="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
 
# Output directory for challenge-tokens to be served by webserver or deployed in HOOK (default: $SCRIPTDIR/.acme-challenges)
WELLKNOWN="/var/www/letsencrypt"
 
# Default keysize for private keys (default: 4096)
KEYSIZE="4096"
 
# Base directory for account key, generated certificates and list of domains (default: $SCRIPTDIR -- uses config directory if undefined)
#BASEDIR=$SCRIPTDIR
 
# Path to openssl config file (default: <unset> - tries to figure out system default)
#OPENSSL_CNF=
 
# Name of root certificate (default: lets-encrypt-x1-cross-signed.pem)
#ROOTCERT="lets-encrypt-x1-cross-signed.pem"
 
# Program or function called in certain situations
#
# After generating the challenge-response, or after failed challenge (in this case altname is empty)
# Given arguments: clean_challenge|deploy_challenge altname token-filename token-content
#
# After successfully signing certificate
# Given arguments: deploy_cert domain path/to/privkey.pem path/to/cert.pem path/to/fullchain.pem
#
# BASEDIR and WELLKNOWN variables are exported and can be used in an external program
# default: <unset>
HOOK=/etc/letsencrypt/hooks.sh
 
# Minimum days before expiration to automatically renew certificate (default: 14)
#RENEW_DAYS="14"
 
# Regenerate private keys instead of just signing new certificates on renewal (default: no)
#PRIVATE_KEY_RENEW="no"
 
# E-mail to use during the registration (default: <unset>)
CONTACT_EMAIL=myemail@domain.com
/etc/letsencrypt/hooks.sh
#!/usr/bin/env bash
 
function deploy_challenge {
    local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"
 
    # This hook is called once for every domain that needs to be
    # validated, including any alternative names you may have listed.
    #
    # Parameters:
    # - DOMAIN
    #   The domain name (CN or subject alternative name) being
    #   validated.
    # - TOKEN_FILENAME
    #   The name of the file containing the token to be served for HTTP
    #   validation. Should be served by your web server as
    #   /.well-known/acme-challenge/${TOKEN_FILENAME}.
    # - TOKEN_VALUE
    #   The token value that needs to be served for validation. For DNS
    #   validation, this is what you want to put in the _acme-challenge
    #   TXT record. For HTTP validation it is the value that is expected
    #   be found in the $TOKEN_FILENAME file.
}
 
function clean_challenge {
    local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"
 
    # This hook is called after attempting to validate each domain,
    # whether or not validation was successful. Here you can delete
    # files or DNS records that are no longer needed.
    #
    # The parameters are the same as for deploy_challenge.
}
 
function deploy_cert {
    local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}"
 
    service apache2 reload
    service nginx reload
 
    # This hook is called once for each certificate that has been
    # produced. Here you might, for instance, copy your new certificates
    # to service-specific locations and reload the service.
    #
    # Parameters:
    # - DOMAIN
    #   The primary domain name, i.e. the certificate common
    #   name (CN).
    # - KEYFILE
    #   The path of the file containing the private key.
    # - CERTFILE
    #   The path of the file containing the signed certificate.
    # - FULLCHAINFILE
    #   The path of the file containing the full certificate chain.
    # - CHAINFILE
    #   The path of the file containing the intermediate certificate(s).
}
 
function unchanged_cert {
    local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}"
 
    # This hook is called once for each certificate that is still
    # valid and therefore wasn't reissued.
    #
    # Parameters:
    # - DOMAIN
    #   The primary domain name, i.e. the certificate common
    #   name (CN).
    # - KEYFILE
    #   The path of the file containing the private key.
    # - CERTFILE
    #   The path of the file containing the signed certificate.
    # - FULLCHAINFILE
    #   The path of the file containing the full certificate chain.
    # - CHAINFILE
    #   The path of the file containing the intermediate certificate(s).
}
 
HANDLER=$1; shift; $HANDLER $@
chmod +x /etc/letsencrypt/hooks.sh
domains.txt
domain.com www.domain.com

If nginx

/etc/nginx/letsencrypt.conf
location /.well-known/acme-challenge {
    alias /var/www/letsencrypt;
}

If apache

/etc/apache2/apache2.conf
Alias /.well-known/acme-challenge /var/www/letsencrypt
 
<Directory /var/www/letsencrypt>
        Options None
        AllowOverride None
 
        # Apache 2.x
        <IfModule !mod_authz_core.c>
                Order allow,deny
                Allow from all
        </IfModule>
 
        # Apache 2.4
        <IfModule mod_authz_core.c>
                Require all granted
        </IfModule>
</Directory>
include /etc/nginx/letsencrypt.conf;
/etc/nginx/sites-enabled/domain.com_ssl.conf
    ssl_certificate      /etc/letsencrypt/certs/domain.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/certs/domain.com/privkey.pem;

Test

/etc/letsencrypt/letsencrypt.sh --config /etc/letsencrypt/config.sh -c

Cron

cron
0 0 * * * /etc/letsencrypt/letsencrypt.sh --config /etc/letsencrypt/config.sh -c