├── LICENSE ├── README.md ├── letsencrypt-autorun ├── letsencrypt-generate ├── letsencrypt-hash ├── letsencrypt-install ├── letsencrypt-renew ├── letsencrypt-request └── letsencrypt-tlsa /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jon Musselwhite 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lets-encrypt-tlsa 2 | 3 | Read the [article](https://flippingbinary.com/2018/02/26/lets-encrypt-with-tlsa-dane/) about this script on the [Flipping Binary website](https://flippingbinary.com). 4 | 5 | ## Contributors wanted 6 | 7 | I've noticed an uptick in interest recently, but my time is devoted to other projects at the moment. If you make improvements that you want to share, please submit a pull request. I will probably approve it as long as it doesn't break anything and provides some sort of improvement. 8 | 9 | ## Installation 10 | 11 | Modify these steps and the scripts as necessary for your distribution. The steps have been tested only on Ubuntu 16.04 servers. 12 | 13 | 1. Change ownership and permissions of the script files 14 | 15 | ``` 16 | $ sudo chown root:root letsencrypt-* 17 | $ sudo chmod +x letsencrypt-* 18 | ``` 19 | 20 | 2. Change the settings in `letsencrypt-tlsa` file, especially the `EMAIL` setting! 21 | ``` 22 | $ sudo nano letsencrypt-tlsa 23 | ``` 24 | 3. Move the `letsencrypt-tlsa` file to `/etc/default` so it is accessible by the other scripts and easy to edit. 25 | ``` 26 | $ sudo mv letsencrypt-tlsa /etc/default 27 | ``` 28 | 4. Move `letsencrypt-autorun` to `/etc/cron.weekly` 29 | ``` 30 | $ sudo mv letsencrypt-autorun /etc/cron.weekly 31 | ``` 32 | 5. Move the rest to `/usr/local/sbin` 33 | ``` 34 | $ sudo mv letsencrypt-* /usr/local/bin 35 | ``` 36 | ## Usage 37 | 38 | 1. Generate a key pair and Certificate Signing Request (CSR). This script does not limit the number of domain names, but attempting to generate one certificate for dozens of domains at a time might fail. The first listed domain is primary and needs to be listed first for each command in this set of tools. Using `example.com` and `www.example.com` as an example: 39 | ``` 40 | $ sudo letsencrypt-generate example.com www.example.com 41 | ``` 42 | 2. Request a signature from Let's Encrypt. Using `example.com` and `www.example.com` as an example both of these commands do the same thing (note the primary domain is listed first and is the only one that matters): 43 | ``` 44 | $ sudo letsencrypt-request example.com 45 | $ sudo letsencrypt-request example.com www.example.com 46 | ``` 47 | 3. Check the hash of the signed certificate. You can list secondary domains along with the primary domain, but the hash will be the same for each. The important part includes and follows the `3 1 1` which makes up your TLSA record. Using `example.com` and `www.example.com` as an example: 48 | ``` 49 | $ sudo letsencrypt-hash example.com www.example.com 50 | ``` 51 | 4. Publish the TLSA records with your DNS provider. 52 | 53 | 5. Install the new certificates. This command will create a symlink in a consistent location (defaulting to `/etc/ssl/letsencrypt/live/`) to the latest signed certificate for the primary domain. Using `example.com` and `www.example.com` as an example, both of these commands do the same thing (note the primary domain is listed first and is the only one that matters): 54 | ``` 55 | $ sudo letsencrypt-install example.com 56 | $ sudo letsencrypt-install example.com www.example.com 57 | ``` 58 | -------------------------------------------------------------------------------- /letsencrypt-autorun: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## 3 | ## letsencrypt-autorun 4 | ## 5 | ## This script calls letsencrypt-renew and belongs in /etc/cron.monthly 6 | ## 7 | ## Source: https://flippingbinary.com 8 | ## 9 | ## Copyright 2017 Jonathan Musselwhite 10 | ## 11 | ## Permission is hereby granted, free of charge, to any person obtaining a copy 12 | ## of this software and associated documentation files (the "Software"), to 13 | ## deal in the Software without restriction, including without limitation the 14 | ## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | ## sell copies of the Software, and to permit persons to whom the Software is 16 | ## furnished to do so, subject to the following conditions: 17 | ## 18 | ## The above copyright notice and this permission notice shall be included in 19 | ## all copies or substantial portions of the Software. 20 | ## 21 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | ## THE SOFTWARE. 28 | ## 29 | ### 30 | 31 | ###### CHECK SETTINGS ###### 32 | SBIN_DIR=/usr/local/sbin 33 | ###### CHECK SETTINGS ###### 34 | 35 | ${SBIN_DIR}/letsencrypt-renew || true 36 | -------------------------------------------------------------------------------- /letsencrypt-generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## 3 | ## letsencrypt-generate 4 | ## 5 | ## This script generates a new keypair and certificate signing request 6 | ## for Let's Encrypt. 7 | ## 8 | ## Source: https://flippingbinary.com 9 | ## 10 | ## Copyright 2017 Jonathan Musselwhite 11 | ## 12 | ## Permission is hereby granted, free of charge, to any person obtaining a copy 13 | ## of this software and associated documentation files (the "Software"), to 14 | ## deal in the Software without restriction, including without limitation the 15 | ## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | ## sell copies of the Software, and to permit persons to whom the Software is 17 | ## furnished to do so, subject to the following conditions: 18 | ## 19 | ## The above copyright notice and this permission notice shall be included in 20 | ## all copies or substantial portions of the Software. 21 | ## 22 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | ## THE SOFTWARE. 29 | ## 30 | ### 31 | 32 | ###### CHECK SETTINGS ###### 33 | MAIN_DIR=/etc/ssl/letsencrypt 34 | ###### CHECK SETTINGS ###### 35 | [ -f /etc/default/letsencrypt-tlsa ] && . /etc/default/letsencrypt-tlsa 36 | 37 | if [ "$#" -lt 1 ] 38 | then 39 | echo "Usage: $0 domain [space-separated list of alternate domains]" >&2 40 | exit 1 41 | fi 42 | 43 | DATE=$(date +%Y%m%d%H%M%S) 44 | DOMAINS="DNS:$1" 45 | COMMON_NAME="$1" 46 | CSR_DIR=${MAIN_DIR}/csr/${COMMON_NAME} 47 | PRIVKEY_DIR=${MAIN_DIR}/keys/${COMMON_NAME} 48 | CSR_PATH="${CSR_DIR}/csr-${DATE}.der" 49 | PRIVKEY_PATH="${PRIVKEY_DIR}/privkey-${DATE}.pem" 50 | 51 | # Build the list of alternate domain names 52 | shift 53 | for x in "$@" 54 | do 55 | DOMAINS="$DOMAINS,DNS:$x" 56 | done 57 | 58 | # Create a few directories to prevent simple errors 59 | mkdir -p ${CSR_DIR} 60 | mkdir -p ${PRIVKEY_DIR} 61 | chmod 700 ${PRIVKEY_DIR} 62 | 63 | # Generate the actual keypair using OpenSSL 64 | openssl req \ 65 | -config <(printf "[req]\ndistinguished_name=req_dn\n[req_dn]\ncommonName=${COMMON_NAME}\n[san]\nsubjectAltName=${DOMAINS}") \ 66 | -new \ 67 | -nodes \ 68 | -subj '/' \ 69 | -reqexts san \ 70 | -out "${CSR_PATH}" \ 71 | -keyout "${PRIVKEY_PATH}" \ 72 | -newkey rsa:4096 \ 73 | -outform DER 74 | -------------------------------------------------------------------------------- /letsencrypt-hash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## 3 | ## letsencrypt-hash 4 | ## 5 | ## This script hashes a TLS certificate and produces a valid TLSA record. 6 | ## 7 | ## Source: https://flippingbinary.com 8 | ## 9 | ## Copyright 2017 Jonathan Musselwhite 10 | ## 11 | ## Permission is hereby granted, free of charge, to any person obtaining a copy 12 | ## of this software and associated documentation files (the "Software"), to 13 | ## deal in the Software without restriction, including without limitation the 14 | ## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | ## sell copies of the Software, and to permit persons to whom the Software is 16 | ## furnished to do so, subject to the following conditions: 17 | ## 18 | ## The above copyright notice and this permission notice shall be included in 19 | ## all copies or substantial portions of the Software. 20 | ## 21 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | ## THE SOFTWARE. 28 | ## 29 | ### 30 | 31 | ###### CHECK SETTINGS ###### 32 | MAIN_DIR=/etc/ssl/letsencrypt 33 | ###### CHECK SETTINGS ###### 34 | [ -f /etc/default/letsencrypt-tlsa ] && . /etc/default/letsencrypt-tlsa 35 | 36 | if [ "$#" -lt 1 ] 37 | then 38 | echo "Usage: $0 domain" >&2 39 | echo " domain MUST be the first listed domain" >&2 40 | echo " additional arguments (such as alternate domains) are ignored" >&2 41 | exit 1 42 | fi 43 | 44 | COMMON_NAME="$1" 45 | ARCHIVE_DIR=${MAIN_DIR}/archive/${COMMON_NAME} 46 | 47 | # Find the latest certificate. This will fail if le-request has not yet run. 48 | unset -v latest 49 | for file in "${ARCHIVE_DIR}"/cert-*.pem; do 50 | [[ $file -nt $latest ]] && latest=$file 51 | done 52 | 53 | if [ ! -f "${latest}" ] 54 | then 55 | echo "Error: Couldn't find a certificate to hash!" >&2 56 | echo " Cannot generate TLSA record!" >&2 57 | exit 1 58 | fi 59 | 60 | # Hash the certificate 61 | HASH=$(openssl x509 -in ${latest} -noout -pubkey | 62 | openssl pkey -pubin -outform DER | 63 | openssl dgst -sha256 -binary | 64 | hexdump -ve '/1 "%02x"') 65 | 66 | # Print out an example TLSA record for each listed domain 67 | for x in "$@" 68 | do 69 | echo " _443._tcp.${x}. IN TLSA 3 1 1 ${HASH}" 70 | done 71 | -------------------------------------------------------------------------------- /letsencrypt-install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## 3 | ## letsencrypt-install 4 | ## 5 | ## This script installs the latest certificate into the live directory. 6 | ## 7 | ## Source: https://flippingbinary.com 8 | ## 9 | ## Copyright 2017 Jonathan Musselwhite 10 | ## 11 | ## Permission is hereby granted, free of charge, to any person obtaining a copy 12 | ## of this software and associated documentation files (the "Software"), to 13 | ## deal in the Software without restriction, including without limitation the 14 | ## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | ## sell copies of the Software, and to permit persons to whom the Software is 16 | ## furnished to do so, subject to the following conditions: 17 | ## 18 | ## The above copyright notice and this permission notice shall be included in 19 | ## all copies or substantial portions of the Software. 20 | ## 21 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | ## THE SOFTWARE. 28 | ## 29 | ### 30 | 31 | ###### CHECK SETTINGS ###### 32 | MAIN_DIR=/etc/ssl/letsencrypt 33 | ###### CHECK SETTINGS ###### 34 | [ -f /etc/default/letsencrypt-tlsa ] && . /etc/default/letsencrypt-tlsa 35 | 36 | if [ "$#" -lt 1 ] 37 | then 38 | echo "Usage: $0 domain" >&2 39 | echo " domain MUST be the first listed domain" >&2 40 | echo " additional arguments (such as alternate domains) are ignored" >&2 41 | exit 1 42 | fi 43 | 44 | COMMON_NAME="$1" 45 | ARCHIVE_DIR=${MAIN_DIR}/archive/${COMMON_NAME} 46 | LIVE_DIR=${MAIN_DIR}/live/${COMMON_NAME} 47 | PRIVKEY_DIR=${MAIN_DIR}/keys/${COMMON_NAME} 48 | 49 | # Make sure the directory exists to prevent simple problems 50 | mkdir -p ${LIVE_DIR} 51 | 52 | # Install cert file 53 | 54 | unset -v latest 55 | for file in "${ARCHIVE_DIR}"/cert-*.pem; do 56 | [[ $file -nt $latest ]] && latest=$file 57 | done 58 | 59 | if [ ! -f "${latest}" ] 60 | then 61 | echo "Error: cert file does not exist!" 62 | exit 1 63 | fi 64 | 65 | ln -sf ${latest} ${LIVE_DIR}/cert.pem 66 | 67 | # Install fullchain file 68 | 69 | unset -v latest 70 | for file in "${ARCHIVE_DIR}"/fullchain-*.pem; do 71 | [[ $file -nt $latest ]] && latest=$file 72 | done 73 | 74 | if [ ! -f "${latest}" ] 75 | then 76 | echo "Error: fullchain file does not exist!" 77 | exit 1 78 | fi 79 | 80 | ln -sf ${latest} ${LIVE_DIR}/fullchain.pem 81 | 82 | # Install chain file 83 | 84 | unset -v latest 85 | for file in "${ARCHIVE_DIR}"/chain-*.pem; do 86 | [[ $file -nt $latest ]] && latest=$file 87 | done 88 | 89 | if [ ! -f "${latest}" ] 90 | then 91 | echo "Error: chain file does not exist!" 92 | exit 1 93 | fi 94 | 95 | ln -sf ${latest} ${LIVE_DIR}/chain.pem 96 | 97 | # Install private key 98 | 99 | unset -v latest 100 | for file in "${PRIVKEY_DIR}"/privkey-*.pem; do 101 | [[ $file -nt $latest ]] && latest=$file 102 | done 103 | 104 | if [ ! -f "${latest}" ] 105 | then 106 | echo "Error: privkey does not exist!" 107 | exit 1 108 | fi 109 | 110 | ln -sf ${latest} ${LIVE_DIR}/privkey.pem 111 | 112 | # Reload the services which use certificates 113 | 114 | if [ "$RELOAD_APACHE" = true ] ; then 115 | /usr/sbin/service apache2 reload 116 | fi 117 | 118 | if [ "$RELOAD_NGINX" = true ] ; then 119 | /usr/sbin/service nginx reload 120 | fi 121 | 122 | if [ "$RELOAD_DOVECOT" = true ] ; then 123 | /usr/sbin/service/dovecot reload 124 | fi 125 | -------------------------------------------------------------------------------- /letsencrypt-renew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## 3 | ## letsencrypt-renew 4 | ## 5 | ## This script requests new certificates for each domain present in the live 6 | ## directory. 7 | ## 8 | ## Source: https://flippingbinary.com 9 | ## 10 | ## Copyright 2017 Jonathan Musselwhite 11 | ## 12 | ## Permission is hereby granted, free of charge, to any person obtaining a copy 13 | ## of this software and associated documentation files (the "Software"), to 14 | ## deal in the Software without restriction, including without limitation the 15 | ## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | ## sell copies of the Software, and to permit persons to whom the Software is 17 | ## furnished to do so, subject to the following conditions: 18 | ## 19 | ## The above copyright notice and this permission notice shall be included in 20 | ## all copies or substantial portions of the Software. 21 | ## 22 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | ## THE SOFTWARE. 29 | ## 30 | ### 31 | 32 | ###### CHECK SETTINGS ###### 33 | MAIN_DIR=/etc/ssl/letsencrypt 34 | ###### CHECK SETTINGS ###### 35 | [ -f /etc/default/letsencrypt-tlsa ] && . /etc/default/letsencrypt-tlsa 36 | 37 | # Attempt to renew every certificate in live directory which expires in less 38 | # than three weeks. 39 | for file in "${MAIN_DIR}/live"/*; do 40 | if ! openssl x509 -checkend 2592000 -noout -in ${file}/cert.pem 41 | then 42 | /usr/local/sbin/letsencrypt-request $(basename $file) 43 | /usr/local/sbin/letsencrypt-install $(basename $file) 44 | fi 45 | if ! openssl x509 -checkend 2592000 -noout -in ${file}/cert.pem 46 | then 47 | echo "Certificate renewal failed! Check status of $(basename $file)!" 48 | fi 49 | done 50 | -------------------------------------------------------------------------------- /letsencrypt-request: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## 3 | ## letsencrypt-request 4 | ## 5 | ## This script requests a signature from Let's Encrypt CA with a reusable 6 | ## keypair, overriding the default behavior of certbot. 7 | ## 8 | ## Source: https://flippingbinary.com 9 | ## 10 | ## Copyright 2017 Jonathan Musselwhite 11 | ## 12 | ## Permission is hereby granted, free of charge, to any person obtaining a copy 13 | ## of this software and associated documentation files (the "Software"), to 14 | ## deal in the Software without restriction, including without limitation the 15 | ## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | ## sell copies of the Software, and to permit persons to whom the Software is 17 | ## furnished to do so, subject to the following conditions: 18 | ## 19 | ## The above copyright notice and this permission notice shall be included in 20 | ## all copies or substantial portions of the Software. 21 | ## 22 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | ## THE SOFTWARE. 29 | ## 30 | ### 31 | 32 | ###### CHECK SETTINGS ###### 33 | EMAIL=UnconfiguredScript@example.com 34 | MAIN_DIR=/etc/ssl/letsencrypt 35 | LOG_DIR=/var/log/letsencrypt 36 | ###### CHECK SETTINGS ###### 37 | [ -f /etc/default/letsencrypt-tlsa ] && . /etc/default/letsencrypt-tlsa 38 | 39 | if [ "$#" -lt 1 ] 40 | then 41 | echo "Usage: $0 domain" >&2 42 | echo " domain MUST be the first listed domain" >&2 43 | echo " additional arguments (such as alternate domains) are ignored" >&2 44 | exit 1 45 | fi 46 | 47 | # Set some environment variables to clean things up a little down below 48 | DATE=$(date +%Y%m%d%H%M%S) 49 | COMMON_NAME="$1" 50 | LOG_PATH=${LOG_DIR}/${COMMON_NAME}.log 51 | ARCHIVE_DIR=${MAIN_DIR}/archive/${COMMON_NAME} 52 | CSR_DIR=${MAIN_DIR}/csr/${COMMON_NAME} 53 | CERT_PATH="${ARCHIVE_DIR}/cert-${DATE}.pem" 54 | FULLCHAIN_PATH="${ARCHIVE_DIR}/fullchain-${DATE}.pem" 55 | CHAIN_PATH="${ARCHIVE_DIR}/chain-${DATE}.pem" 56 | 57 | # Locate the latest certificate signing request 58 | unset -v latest 59 | for file in "${CSR_DIR}"/csr-*.der; do 60 | [[ $file -nt $latest ]] && latest=$file 61 | done 62 | 63 | if [ ! -f "${latest}" ] 64 | then 65 | echo "Error: Couldn't find a certificate signing request!" >&2 66 | echo " Cannot request certificate!" >&2 67 | exit 1 68 | fi 69 | 70 | # Make sure the directory exists to prevent simple problems 71 | mkdir -p ${ARCHIVE_DIR} 72 | mkdir -p ${LOG_DIR} 73 | 74 | # Finally request the actual signed certificate 75 | certbot certonly \ 76 | -n \ 77 | --agree-tos \ 78 | -m ${EMAIL} \ 79 | --webroot \ 80 | --csr ${latest} \ 81 | --preferred-challenges http-01 \ 82 | -w /var/www/${COMMON_NAME} \ 83 | --fullchain-path ${FULLCHAIN_PATH} \ 84 | --chain-path ${CHAIN_PATH} \ 85 | --cert-path ${CERT_PATH} >> ${LOG_PATH} 2>&1 86 | 87 | if [ ! -f ${FULLCHAIN_PATH} ]; then 88 | echo "Error: Failed to create fullchain file!" >&2 89 | fi 90 | 91 | if [ ! -f ${CHAIN_PATH} ]; then 92 | echo "Error: Failed to create chain file!" >&2 93 | fi 94 | 95 | if [ ! -f ${CERT_PATH} ]; then 96 | echo "Error: Failed to create cert file!" >&2 97 | fi 98 | 99 | if [ ! -f ${FULLCHAIN_PATH} -o ! -f ${CHAIN_PATH} -o ! -f ${CERT_PATH} ]; then 100 | echo "Error: Failed to generate required files!" 101 | if [ -f ${LOG_PATH} ]; then 102 | tail ${LOG_PATH} # just show the last few lines 103 | fi 104 | exit 1; 105 | fi 106 | -------------------------------------------------------------------------------- /letsencrypt-tlsa: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ## 3 | ## letsencrypt-tlsa 4 | ## 5 | ## This script sets environment variables for the other scripts in the series. 6 | ## It should be placed inside the /etc/default folder in order to be used. 7 | ## 8 | ## Source: https://flippingbinary.com 9 | ## 10 | ## Copyright 2017 Jonathan Musselwhite 11 | ## 12 | ## Permission is hereby granted, free of charge, to any person obtaining a copy 13 | ## of this software and associated documentation files (the "Software"), to 14 | ## deal in the Software without restriction, including without limitation the 15 | ## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | ## sell copies of the Software, and to permit persons to whom the Software is 17 | ## furnished to do so, subject to the following conditions: 18 | ## 19 | ## The above copyright notice and this permission notice shall be included in 20 | ## all copies or substantial portions of the Software. 21 | ## 22 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | ## THE SOFTWARE. 29 | ## 30 | ### 31 | 32 | ###### CHECK SETTINGS ###### 33 | EMAIL=UnconfiguredScript@example.com 34 | MAIN_DIR=/etc/ssl/letsencrypt 35 | LOG_DIR=/var/log/letsencrypt 36 | RELOAD_APACHE=true 37 | RELOAD_NGINX=false 38 | RELOAD_DOVECOT=true 39 | ###### CHECK SETTINGS ###### 40 | --------------------------------------------------------------------------------