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