Let's Encrypt

最後更新: 2019-11-07



Let's Encrypt is a Python-based utility

Let’s Encrypt CA issues short lived certificates (90 days).

Make sure you renew the certificates at least once in 3 months.

Homepage: https://letsencrypt.org/

Source: https://github.com/letsencrypt/letsencrypt


Automatic Certificate Management Environment (ACME)

The protocol, based on passing JSON-formatted messages over HTTPS ( RFC 8555 )

automatically obtain a browser-trusted certificate, without any human intervention

This is accomplished by running a certificate management agent on the web server.

Let’s Encrypt identifies the server administrator by public key.

The first time the agent software interacts with Let’s Encrypt,

it generates a new key pair and proves to the Let’s Encrypt CA that the server controls one or more domains.

# Challenges & validation:

A) Agent 建立用來與 Let’s Encrypt CA 溝通的 key pair

1. The agent asks the Let’s Encrypt CA what it needs to do in order to prove that it controls

2. The Let’s Encrypt CA also provides a nonce that the agent must sign with its private key pair

    (to prove that it controls the key pair)

3. Agent creates a file on a specified path on the site.

4. Agent notifies the CA that it’s ready to complete validation

    (Let’s Encrypt call the URL)

5. If the signature over the nonce is valid, and the challenges check out,

    then the agent identified by the public key is authorized to do certificate management for example.com.

B) requesting, renewing, and revoking certificates

Agent send certificate management messages and sign them with the authorized key pair

(asks the Let’s Encrypt CA to issue a certificate for example.com with a specified public key.)

The agent signs the whole CSR with the authorized key for example.com


What IP addresses does Let's Encrypt use to validate my web server?

We don't publish a list of IP addresses we use to validate,

because they may change at any time. In the future we may validate from multiple IP addresses at once.




cd /usr/src

git clone https://github.com/letsencrypt/letsencrypt


定期 update 它

cd letsencrypt

git pull

ln -s /usr/src/letsencrypt/letsencrypt-auto /usr/sbin/

# 建立 virtualenv (行 cli 一次, 它就會自動建立)


# check version

certbot-auto --version

certbot 0.17.0

# help

certbot-auto --help


Key 的位置


All generated keys and issued certificates can be found in /etc/letsencrypt/live/$domain/


ll /etc/letsencrypt/live/datahunter.org/

lrwxrwxrwx 1 root root   38 May 14 22:01 cert.pem -> ../../archive/datahunter.org/cert5.pem
lrwxrwxrwx 1 root root   39 May 14 22:01 chain.pem -> ../../archive/datahunter.org/chain5.pem
lrwxrwxrwx 1 root root   43 May 14 22:01 fullchain.pem -> ../../archive/datahunter.org/fullchain5.pem
lrwxrwxrwx 1 root root   41 May 14 22:01 privkey.pem -> ../../archive/datahunter.org/privkey5.pem

* /etc/letsencrypt/live symlinks to the latest versions

* /etc/letsencrypt/archive and /etc/letsencrypt/keys contain all previous keys and certificates,





letsencrypt [SUBCOMMAND] [options] [-d domain] [-d domain] ...


  •  run (default)              # Obtain & install
  •  certonly                     # Obtain cert, but do not install it
  •  install
  •  revoke
  •  rollback
  •  config_changes

# Sign a single domain

letsencrypt-auto certonly --test-cert  --standalone  -d datahunter.org -d www.datahunter.org

* --standalone      # runs its own simple webserver to prove you control a domain)

* --certonly          #  不用 automatic installation

* --test-cert          # This will get certificates from staging server. (They won’t be valid in browsers)

# multiple domains

letsencrypt -d www.example.org -d example.org

# Renewing

letsencrypt renew --cert-path example-cert.pem


service nginx stop       # 必須要放返 port 80 出黍先 renew 到

letsencrypt-auto renew --standalone --cert-path /etc/letsencrypt/live/datahunter.org/cert.pem

Auto renew script



service nginx stop

if ! $letsencrypt renew -nvv --standalone --cert-path $CERT > $LOGFILE 2>&1 ; then
    echo "Automated renewal failed:"
    echo "Please check log: $LOGFILE"
    exit 1

service nginx start

crontab -e

1 1 1 */2 *       /root/scripts/letsencrypt/cron_renew.sh > /dev/null

# For testing

--force-renewal            # that will force a renewal even if your cert isn’t close to expiry.

--dry-run                     # will fetch a certificate from staging server.


它會根據 /etc/letsencrypt/renewal/datahunter.org.conf 去 renew

# renew_before_expiry = 30 days
cert = /etc/letsencrypt/live/datahunter.org/cert.pem
privkey = /etc/letsencrypt/live/datahunter.org/privkey.pem
chain = /etc/letsencrypt/live/datahunter.org/chain.pem
fullchain = /etc/letsencrypt/live/datahunter.org/fullchain.pem
version = 0.8.1

# Options and defaults used in the renewal process
installer = None
authenticator = standalone
account = ?????????????????????????????????????

# Revoking a Certificate

# menu of all your managed certificates

letsencrypt revoke

# You may also revoke a particular certificate

$ letsencrypt revoke --cert-path example-cert.pem

# revoke all certificates with a particular key.

$ letsencrypt revoke --key-path example-key.pem





letsencrypt-auto --config cli.ini

# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Uncomment and update to register with the specified e-mail address
# email = foo@example.com

log file



nginx ssl configure


server {
        listen                     443 ssl http2;
        ssi                        on;
        ssl_certificate            /etc/letsencrypt/live/datahunter.org/fullchain.pem;
        ssl_certificate_key        /etc/letsencrypt/live/datahunter.org/privkey.pem;
        ssl_protocols              TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers  on;
        ssl_session_cache          shared:SSL:10m;
        ssl_session_timeout        15m;




新版由 letsencrypt command 改成了 certbot command


./certbot-auto --help all

Plugins Type (一共有兩類)

certonly - obtain a cert

install - install a cert (modify your webserver’s configuration)

Usage: renew


attempts to renew any previously-obtained certificates that expire in less than 30 days.

它會 read /etc/letsencrypt/renewal/*.conf 內的設定再去 renew domain

--cert-path CERT_PATH                     # Path to where cert is saved (with auth --csr), installed from, or revoked.
(default: None)

--standalone                                    # To obtain a cert using a “standalone” webserver

--preferred-challenges http/tls-sni     # Port 80 / 443

--force-renewal                        # msg: "The following certs are not due for renewal yet:"

                                              # If a certificate already exists for the requested domains,

                                              # renew it now, regardless of whether it is near expiry.


certbot-auto renew


The renew command includes hooks for running commands or scripts before or after a certificate is renewed.

certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start"


only be called if a certificate is actually to be obtained/renewed.


to restart any servers that were stopped by --pre-hook.

  * the certonly command attempts to renew that specific(-d) certificate.

  * certbot renew exit status will only be 1 if a renewal attempt failed.


# view a list of the certificates Certbot knows

certbot-auto certificates

Found the following certs:
  Certificate Name: datahunter.org
    Domains: datahunter.org mail.datahunter.org
    Expiry Date: 2017-07-02 04:21:00+00:00 (VALID: 87 days)
    Certificate Path: /etc/letsencrypt/live/datahunter.org/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/datahunter.org/privkey.pem


T1: “Error: couldn’t get currently installed version for letsencrypt”

S1: mv /root/.local/share /root/.local/share.bak





$certbot renew --pre-hook "service nginx stop" \
               --post-hook "service nginx start" \
               --standalone --preferred-challenges http \
               --cert-path $CERT > $LOGFILE 2>&1

# letsencrypt

1 1 1 * *       /root/scripts/letsencrypt/cron_renew.sh

Plugin: webroot

Obtains a cert by writing to the webroot directory of an already running webserver.

The webroot plugin works by creating a temporary file for each of your requested domains in ${webroot-path}/.well-known/{acme-challenge}


certbot certonly --webroot -w /var/www/example/ -d www.example.com -d example.com -w /var/www/other -d other.example.net -d another.other.example.net

Usage: create cert (certonly)



$certbot certonly --pre-hook "service nginx stop" \
                --post-hook "service nginx start" \
                --standalone --preferred-challenges http \
                -d datahunter.org \
                -d www.datahunter.org


重新建立 Cert

Step1: backup 以下 Folder 內的 Folder

  • archive  
  • live  
  • renewal

certbot-auto certificates

沒有 output 再重新申請




# certonly: make the changes to your Apache configuration by hand

# --apache: Apache plugin

# (get a certificate for you and edit your Apache configuration automatically to serve it)

certbot-auto certonly --apache -d datahunter.org

會 renew 以下 file


設定 renew cron jobs

# 測試 renew

certbot-auto renew --dry-run

# cron jobs

# Monthly
1 1 1 * * certbot-auto renew &> /dev/null


Letsencrypt validate server IP


letsencrypt don't publish a list of IP addresses we use to validate, because they may change at any time.




Wildcard SSL Certificate



1. 執行 CLi

certbot-auto certonly --manual \
--preferred-challenges=dns \
-d "datahunter.org" -d "*.datahunter.org"

2. 填資料


3. 建立 txt record

最後會 Certbot 會顯示一個 TXT Record


Please deploy a DNS TXT record under the name
_acme-challenge.datahunter.org with the following value:


Before continuing, verify the record is deployed.

dig -t txt _acme-challenge.datahunter.org




Tools: win-acme (https://pkisharp.github.io/win-acme/)


  • A very simple text interface to create
  • DNS, HTTP and TLS validation
  • Completely unattended operation from the command line


if you want to download or develop extra plugins,

you should get the pluggable version instead of the trimmed one.


The validation request is always made to port 80, that cannot be changed.

The ACME server does follow 301/302 redirects.

The client has to make sure that when the ACME server makes a request to


the content of the HTTP response will be y with some specific headers set as well.



Alias /.well-known/ "C:/vhosts/ssl/.well-known/"

<Directory "C:/vhosts/ssl/">
    Options -FollowSymlinks -Includes -ExecCGI
    Order allow,deny
    Allow from all
    DirectoryIndex index.php index.html index.htm



Enter the path we created in step 4. In my case: C:\xampp\htdocs


actual root and not the path to "/.well-known/acme-challenge".

Win-acme is assuming you haven't got this far and will attempt to create these folders if they don't exist.


Command line arguments


     Renew any certificates that are due.


     Force renewal on all scheduled certificates when used together with --renew.


     List all created renewals in unattended mode.




obtain a certificate running certbot on a machine other than your target webserver

./certbot-auto certonly --manual --preferred-challenges http -d datahunter.org