Jul 042017
 

This blog post describes my Let’s Encrypt solution which uses acme.sh and dns-01 challenges to obtain SSL certificates. If you are using HTTP challenges, this post might still be useful, but your configuration will differ slightly.

Let’s Encrypt is a certificate authority which has become wildly popular since it was launched in April 2016 (just a short 14 months ago). Why so popular? It provides a secure way to offer free SSL certificates. The goal: make it easy to automate the provisioning of SSL certificates for websites.

What is ACME? Automated Certificate Management Environment is a “communications protocol for automating interactions between certificate authorities and their users’ web servers, allowing the automated deployment of public key infrastructure at very low cost”.

I have been working on this project ever since I read Peter Wemm’s blog post about how the FreeBSD project uses Let’s Encrypt. I liked the centralized approach to renewing all of your certs from one jail, then distributing them out to where they are used.

Why do I like that?

  1. It reduces your exposure. Should there be an exploit in the Let’s Encrypt protocols, only one jail will be affected.
  2. Instead of configuring Let’s Encrypt in N locations, I am configuring it in one place.
  3. Not all of my SSL certificates will be associated with websites, so validation via HTTP was going to be a challenge. This meant dns-01* was the preferred authentication method for me. I was not about to allow DNS updates from every SSL certificate location. That would be asking for trouble.

*I found many references to dns-01 and the best definition I found is in the IETF draft ACME document.

There are many Let’s Encrypt clients. I selected acme.sh because Peter did, and because it’s a shell script. I like that.

Installing acme.sh on FreeBSD

On FreeBSD, acme.sh is available as the security/acme.sh port. By default, this port creates the the acme user with a home directory of /var/db/acme. Let’s Encrypt provisioning can, and should, be done as non-root. If you can do something as non-root, you should do it as non-root.

I do not like the standard acme.sh installation process. It installs the script into a local directory. I prefer to leave the acme.sh where it is installed by the port (specifically, /usr/local/sbin/acme.sh) and run it from there. It is because of that different approach that we need to manually create some configuration files.

What happens if you try running the acme.sh install process?

NOTE: Do not follow the steps in this section. They are for educational purposes only.

Please skip to the next section, nothing to see here.

The following is provided mostly for my own reference while I manually configure acme.sh in the next step. You can skip reading this section without missing anything.

[dan@certs:~/tmp] $ /usr/local/sbin/acme.sh --install 
[Thu Jun 29 12:23:01 UTC 2017] Installing to /usr/home/dan/.acme.sh
cp: acme.sh: No such file or directory
[Thu Jun 29 12:23:01 UTC 2017] Install failed, can not copy acme.sh

Oh. You really do need to be in that directory, just like the instructions say.

Let’s try that again.

[dan@certs:~/tmp] $ cd /usr/local/sbin
[dan@certs:/usr/local/sbin] $ ./acme.sh --install 
[Thu Jun 29 12:23:22 UTC 2017] Installing to /usr/home/dan/.acme.sh
[Thu Jun 29 12:23:22 UTC 2017] Installed to /usr/home/dan/.acme.sh/acme.sh
[Thu Jun 29 12:23:22 UTC 2017] Installing alias to '/usr/home/dan/.profile'
[Thu Jun 29 12:23:22 UTC 2017] OK, Close and reopen your terminal to start using acme.sh
[Thu Jun 29 12:23:22 UTC 2017] Installing alias to '/usr/home/dan/.cshrc'
[Thu Jun 29 12:23:22 UTC 2017] Installing cron job
crontab: no crontab for dan
crontab: no crontab for dan
[Thu Jun 29 12:23:23 UTC 2017] Good, bash is found, so change the shebang to use bash as preferred.
./acme.sh: cannot create /usr/home/dan/.acme.sh/acme.sh: Permission denied
./acme.sh: cannot create /usr/home/dan/.acme.sh/acme.sh: Permission denied
[Thu Jun 29 12:23:23 UTC 2017] OK
[dan@certs:/usr/local/sbin] $ 

What did it do?

It created these files:

$ find .acme.sh
.acme.sh
.acme.sh/acme.sh.env
.acme.sh/acme.sh.csh
.acme.sh/account.conf
.acme.sh/acme.sh

What is in those files?

[dan@certs:~/.acme.sh] $ cat acme.sh.env 
export LE_WORKING_DIR="/usr/home/dan/.acme.sh"
alias acme.sh="/usr/home/dan/.acme.sh/acme.sh"
[dan@certs:~/.acme.sh] $
[dan@certs:~/.acme.sh] $ cat acme.sh.csh 
setenv LE_WORKING_DIR "/usr/home/dan/.acme.sh"
alias acme.sh "/usr/home/dan/.acme.sh/acme.sh"
[dan@certs:~/.acme.sh] $ cat account.conf 


#LOG_FILE="/usr/home/dan/.acme.sh/acme.sh.log"
#LOG_LEVEL=1

#AUTO_UPGRADE="1"

#NO_TIMESTAMP=1

It added these lines to these files:

$ grep acme ~/.profile ~/.cshrc 
/usr/home/dan/.profile:. "/usr/home/dan/.acme.sh/acme.sh.env"
/usr/home/dan/.cshrc:source "/usr/home/dan/.acme.sh/acme.sh.csh"

It created this crontab:

$ crontab -l
22 0 * * * "/usr/home/dan/.acme.sh"/acme.sh --cron --home "/usr/home/dan/.acme.sh" > /dev/null

NOTE: the cronjob was eventually changed to:

7 22 * * * /usr/local/sbin/acme.sh --cron --home /var/db/acme/.acme.sh

re: Author’s advice.

What is this LE it refers to? Let’s Encrypt.

Plus, I don’t want that alias to be invoked. I want to use the acme.sh instance installed by the port, not a local copy.

The configuration files

I hope you ignored the previous section, thank you.

The current FreeBSD port automatically creates a user, acme, with a home directory of /var/db/acme. The following actions are performed as that user.

In this section, I will manually create the configuration files for acme.sh. I think this work will form the basis for a port update so that the port automagically creates these files for you, if they do not already exist. Before writing this blog post, I had a working acme.sh solution which I saved away, and now, as I type this, I am creating a new acme.sh installation from scratch.

Cleaning the account and starting fresh

NOTE: this section describes a destructive action. Be careful.

Here is what I did to start with a fresh Let’s Encrypt key. This may not apply to your configuration, but it works for how I have things set up.

[acme@certs ~]$ rm -rf .acme.sh/ca .acme.sh/http.header certs/* .rnd

This is the list of files I start with:

$ find .
.
./.acme.sh
./.acme.sh/dnsapi
./Kcerts.int.unixathome.org.+165+59977.key
./Kcerts.int.unixathome.org.+165+59977.private
./certs

account.conf

My ~/.acme.sh/account.conf looks like this:

$ cat account.conf
USER_PATH='/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin'

NSUPDATE_SERVER="dns-hidden-master.int.unixathome.org"
NSUPDATE_KEY="/var/db/acme/Kcerts.int.unixathome.org.+165+59977.key"
DEFAULT_DNS_SLEEP="10"
CERT_HOME="/var/db/acme/certs"
LOG_FILE='/var/db/acme/acme.sh.log'

Lines 4 and 5 define environment variables used by the dns_nsupdate.sh script which is included with the FreeBSD port of acme.sh (see /usr/local/share/examples/acme.sh/dnsapi). The Kcerts file is explained in my recent post on creating a key for nsupdate.

Line 6 indicates how long (in seconds) to wait for DNS propagation. My value is low, for testing, but I would use something like 60 in production. Longer waits are just fine. There is no rush in production.

Line 7 specifies the key length for the certificates. I want 4KB certificates.

Line 8 indicates that new certificates will be placed in the specified directory. Keys will also be placed in this directory, therefore, it must not be world readable.

Line 9 specifies the log file to use.

Running acme.sh for the first time

acme.sh tries to do as much for you as it can. Read below for more information.

You should note that I have specified –staging. There are limits on how many live certificates you can create. When testing, always use –staging. Such certificates will not be useful in public.

[acme@certs ~]$ acme.sh --staging --issue --dns dns_nsupdate -d lists.unixathome.org
[Fri Jun 30 20:50:27 UTC 2017] Using stage api:https://acme-staging.api.letsencrypt.org
[Fri Jun 30 20:50:28 UTC 2017] Registering account
[Fri Jun 30 20:50:29 UTC 2017] Registered
[Fri Jun 30 20:50:29 UTC 2017] Update success.
[Fri Jun 30 20:50:29 UTC 2017] ACCOUNT_THUMBPRINT='BYEw6p8pAnuj6LEO-bM-rf_NxosNa0HVmLDE5NsGVog'
[Fri Jun 30 20:50:29 UTC 2017] Creating domain key
[Fri Jun 30 20:50:29 UTC 2017] Single domain='lists.unixathome.org'
[Fri Jun 30 20:50:29 UTC 2017] Getting domain auth token for each domain
[Fri Jun 30 20:50:29 UTC 2017] Getting webroot for domain='lists.unixathome.org'
[Fri Jun 30 20:50:29 UTC 2017] Getting new-authz for domain='lists.unixathome.org'
[Fri Jun 30 20:50:30 UTC 2017] The new-authz request is ok.
[Fri Jun 30 20:50:30 UTC 2017] Found domain api file: /var/db/acme/.acme.sh/dnsapi/dns_nsupdate.sh
[Fri Jun 30 20:50:30 UTC 2017] adding _acme-challenge.lists.unixathome.org. 60 in txt "DlyqdRNT7WKpetBJx4DsVsA-U_zblScu-O95EaBD4VU"
[Fri Jun 30 20:50:30 UTC 2017] Sleep 10 seconds for the txt records to take effect
[Fri Jun 30 20:50:41 UTC 2017] Verifying:lists.unixathome.org
[Fri Jun 30 20:50:44 UTC 2017] Success
[Fri Jun 30 20:50:44 UTC 2017] removing _acme-challenge.lists.unixathome.org. txt
[Fri Jun 30 20:50:44 UTC 2017] Verify finished, start to sign.
[Fri Jun 30 20:50:45 UTC 2017] Cert success.
-----BEGIN CERTIFICATE-----
MIIE7DCCA9SgAwIBAgITAPr8V+8RKtnmcj7aForvT4rYVzANBgkqhkiG9w0BAQsF
ADAiMSAwHgYDVQQDDBdGYWtlIExFIEludGVybWVkaWF0ZSBYMTAeFw0xNzA2MzAx
OTUxMDBaFw0xNzA5MjgxOTUxMDBaMB8xHTAbBgNVBAMTFGxpc3RzLnVuaXhhdGhv
bWUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA85soDhohxOuG
amZyAOtmTyc90Y44VkEifrsAoYNOIKewTybmZ5UrVXqPd6txGFdhzJNpvuJKJ0RV
zo7ZPvCpIegIx8M3hrFluacuzWpEByqAQaY+9a063oar6reVWsPf/LPJqij78SAh
7V+QHy1kM5eeUS/B1OLqj0aoyWLdNA5GyGWmWOv7WYh/kmu9VcQCQAI7L8qWYj7r
M0pXDMTMP+td9ZeMAJZGHPolqypJFLEn4rU0UDjTZd3nY+z7HQIKe2ldEwel++kn
rqr+xcAZJL42WH+BDof0U18VafuN6lLeYZCyVjhX2a2ySboxxvKsfEOW+vadfzJJ
EaBLfrE+VQIDAQABo4ICHDCCAhgwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG
CCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQgv0cy
YBgtejOPH9JvBABUt4QrLTAfBgNVHSMEGDAWgBTAzANGuVggzFxycPPhLssgpvVo
OjB3BggrBgEFBQcBAQRrMGkwMgYIKwYBBQUHMAGGJmh0dHA6Ly9vY3NwLnN0Zy1p
bnQteDEubGV0c2VuY3J5cHQub3JnMDMGCCsGAQUFBzAChidodHRwOi8vY2VydC5z
dGctaW50LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYDVR0RBBgwFoIUbGlzdHMudW5p
eGF0aG9tZS5vcmcwgf4GA1UdIASB9jCB8zAIBgZngQwBAgEwgeYGCysGAQQBgt8T
AQEBMIHWMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCB
qwYIKwYBBQUHAgIwgZ4MgZtUaGlzIENlcnRpZmljYXRlIG1heSBvbmx5IGJlIHJl
bGllZCB1cG9uIGJ5IFJlbHlpbmcgUGFydGllcyBhbmQgb25seSBpbiBhY2NvcmRh
bmNlIHdpdGggdGhlIENlcnRpZmljYXRlIFBvbGljeSBmb3VuZCBhdCBodHRwczov
L2xldHNlbmNyeXB0Lm9yZy9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEA
zRQHa16e/jbtkewtro1I2aJBhX6FVQbA7aWPMpT+NZVqOTQNMp2kYfdxcvhQDavA
uBqPfjZHRY4pydPN53vXnRHA8FCKfTXGeS68ZxzEu4CQ1YBLBqCPMDzawmVYkBjD
+E+AuFpFr3YRMppsGt5GUUsoKkUaUZQEMhyXdL+r1hzKQptinvHr7w1YRAdeg6ac
aMBAPk2hdUNS57iz9nxsvdhLP6qCKakREKvoP/xP2N/fgZbbpaFDDJGnlcfeGYKx
B5LWTFYUBJqPsVYG6rD8j3f7LWzVPkq2d4yj1pR+vaqb+C/POZq0Kvrg74Fo8Hdq
U/tzny/gcGi2wcjuLfB7Wg==
-----END CERTIFICATE-----
[Fri Jun 30 20:50:45 UTC 2017] Your cert is in  /var/db/acme/certs/lists.unixathome.org/lists.unixathome.org.cer 
[Fri Jun 30 20:50:45 UTC 2017] Your cert key is in  /var/db/acme/certs/lists.unixathome.org/lists.unixathome.org.key 
[Fri Jun 30 20:50:45 UTC 2017] The intermediate CA cert is in  /var/db/acme/certs/lists.unixathome.org/ca.cer 
[Fri Jun 30 20:50:45 UTC 2017] And the full chain certs is there:  /var/db/acme/certs/lists.unixathome.org/fullchain.cer 
[acme@certs ~]$ 

On line 3, you can see the registration process starting. This results in two files, a certificate and a key:

.acme.sh/ca/acme-staging.api.letsencrypt.org/account.key
.acme.sh/ca/acme-staging.api.letsencrypt.org/account.json

On line 13, the authorization process begins.

As you can see, they are prefixed with acme-staging because we are running in –staging.

Viewing the newly obtained certificate, we see:

[acme@certs ~]$ openssl x509 -text -noout -in ./certs/lists.unixathome.org/lists.unixathome.org.cer
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            fa:fc:57:ef:11:2a:d9:e6:72:3e:da:16:8a:ef:4f:8a:d8:57
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Fake LE Intermediate X1
        Validity
            Not Before: Jun 30 19:51:00 2017 GMT
            Not After : Sep 28 19:51:00 2017 GMT
        Subject: CN=lists.unixathome.org
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:f3:9b:28:0e:1a:21:c4:eb:86:6a:66:72:00:eb:
                    66:4f:27:3d:d1:8e:38:56:41:22:7e:bb:00:a1:83:
                    4e:20:a7:b0:4f:26:e6:67:95:2b:55:7a:8f:77:ab:
                    71:18:57:61:cc:93:69:be:e2:4a:27:44:55:ce:8e:
                    d9:3e:f0:a9:21:e8:08:c7:c3:37:86:b1:65:b9:a7:
                    2e:cd:6a:44:07:2a:80:41:a6:3e:f5:ad:3a:de:86:
                    ab:ea:b7:95:5a:c3:df:fc:b3:c9:aa:28:fb:f1:20:
                    21:ed:5f:90:1f:2d:64:33:97:9e:51:2f:c1:d4:e2:
                    ea:8f:46:a8:c9:62:dd:34:0e:46:c8:65:a6:58:eb:
                    fb:59:88:7f:92:6b:bd:55:c4:02:40:02:3b:2f:ca:
                    96:62:3e:eb:33:4a:57:0c:c4:cc:3f:eb:5d:f5:97:
                    8c:00:96:46:1c:fa:25:ab:2a:49:14:b1:27:e2:b5:
                    34:50:38:d3:65:dd:e7:63:ec:fb:1d:02:0a:7b:69:
                    5d:13:07:a5:fb:e9:27:ae:aa:fe:c5:c0:19:24:be:
                    36:58:7f:81:0e:87:f4:53:5f:15:69:fb:8d:ea:52:
                    de:61:90:b2:56:38:57:d9:ad:b2:49:ba:31:c6:f2:
                    ac:7c:43:96:fa:f6:9d:7f:32:49:11:a0:4b:7e:b1:
                    3e:55
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier: 
                20:BF:47:32:60:18:2D:7A:33:8F:1F:D2:6F:04:00:54:B7:84:2B:2D
            X509v3 Authority Key Identifier: 
                keyid:C0:CC:03:46:B9:58:20:CC:5C:72:70:F3:E1:2E:CB:20:A6:F5:68:3A

            Authority Information Access: 
                OCSP - URI:http://ocsp.stg-int-x1.letsencrypt.org
                CA Issuers - URI:http://cert.stg-int-x1.letsencrypt.org/

            X509v3 Subject Alternative Name: 
                DNS:lists.unixathome.org
            X509v3 Certificate Policies: 
                Policy: 2.23.140.1.2.1
                Policy: 1.3.6.1.4.1.44947.1.1.1
                  CPS: http://cps.letsencrypt.org
                  User Notice:
                    Explicit Text: This Certificate may only be relied upon by Relying Parties and only in accordance with the Certificate Policy found at https://letsencrypt.org/repository/

    Signature Algorithm: sha256WithRSAEncryption
         cd:14:07:6b:5e:9e:fe:36:ed:91:ec:2d:ae:8d:48:d9:a2:41:
         85:7e:85:55:06:c0:ed:a5:8f:32:94:fe:35:95:6a:39:34:0d:
         32:9d:a4:61:f7:71:72:f8:50:0d:ab:c0:b8:1a:8f:7e:36:47:
         45:8e:29:c9:d3:cd:e7:7b:d7:9d:11:c0:f0:50:8a:7d:35:c6:
         79:2e:bc:67:1c:c4:bb:80:90:d5:80:4b:06:a0:8f:30:3c:da:
         c2:65:58:90:18:c3:f8:4f:80:b8:5a:45:af:76:11:32:9a:6c:
         1a:de:46:51:4b:28:2a:45:1a:51:94:04:32:1c:97:74:bf:ab:
         d6:1c:ca:42:9b:62:9e:f1:eb:ef:0d:58:44:07:5e:83:a6:9c:
         68:c0:40:3e:4d:a1:75:43:52:e7:b8:b3:f6:7c:6c:bd:d8:4b:
         3f:aa:82:29:a9:11:10:ab:e8:3f:fc:4f:d8:df:df:81:96:db:
         a5:a1:43:0c:91:a7:95:c7:de:19:82:b1:07:92:d6:4c:56:14:
         04:9a:8f:b1:56:06:ea:b0:fc:8f:77:fb:2d:6c:d5:3e:4a:b6:
         77:8c:a3:d6:94:7e:bd:aa:9b:f8:2f:cf:39:9a:b4:2a:fa:e0:
         ef:81:68:f0:77:6a:53:fb:73:9f:2f:e0:70:68:b6:c1:c8:ee:
         2d:f0:7b:5a
[acme@certs ~]$ 

Line 8 is important. It indicates we obtained this cert via –staging.

As this point, there are the files I have:

$ find .
.
./.acme.sh
./.acme.sh/ca
./.acme.sh/ca/acme-staging.api.letsencrypt.org
./.acme.sh/ca/acme-staging.api.letsencrypt.org/account.key
./.acme.sh/ca/acme-staging.api.letsencrypt.org/account.json
./.acme.sh/ca/acme-staging.api.letsencrypt.org/ca.conf
./.acme.sh/account.conf
./.acme.sh/account.conf.sample
./.acme.sh/dnsapi
./.acme.sh/http.header
./Kcerts.int.unixathome.org.+165+59977.private
./Kcerts.int.unixathome.org.+165+59977.key
./certs
./certs/lists.unixathome.org
./certs/lists.unixathome.org/lists.unixathome.org.key
./certs/lists.unixathome.org/fullchain.cer
./certs/lists.unixathome.org/lists.unixathome.org.csr.conf
./certs/lists.unixathome.org/lists.unixathome.org.cer
./certs/lists.unixathome.org/lists.unixathome.org.conf
./certs/lists.unixathome.org/lists.unixathome.org.csr
./certs/lists.unixathome.org/ca.cer

Getting a second cert

In the previous section, I obtained a cert for lists.unixathome.org. Now let’s get one for www.unixathome.org.

$ acme.sh --staging --issue --dns dns_nsupdate -d www.unixathome.org
[Fri Jun 30 21:10:29 UTC 2017] Using stage api:https://acme-staging.api.letsencrypt.org
[Fri Jun 30 21:10:29 UTC 2017] Single domain='www.unixathome.org'
[Fri Jun 30 21:10:29 UTC 2017] Getting domain auth token for each domain
[Fri Jun 30 21:10:29 UTC 2017] Getting webroot for domain='www.unixathome.org'
[Fri Jun 30 21:10:29 UTC 2017] Getting new-authz for domain='www.unixathome.org'
[Fri Jun 30 21:10:32 UTC 2017] The new-authz request is ok.
[Fri Jun 30 21:10:32 UTC 2017] Found domain api file: /var/db/acme/.acme.sh/dnsapi/dns_nsupdate.sh
[Fri Jun 30 21:10:32 UTC 2017] adding _acme-challenge.www.unixathome.org. 60 in txt "eMwKmRpe6zkx_b1u1WZyCP01ZdqBkF9j4wlpBudkKb8"
[Fri Jun 30 21:10:32 UTC 2017] Sleep 10 seconds for the txt records to take effect
[Fri Jun 30 21:10:44 UTC 2017] Verifying:www.unixathome.org
[Fri Jun 30 21:10:46 UTC 2017] Success
[Fri Jun 30 21:10:46 UTC 2017] removing _acme-challenge.www.unixathome.org. txt
[Fri Jun 30 21:10:46 UTC 2017] Verify finished, start to sign.
[Fri Jun 30 21:10:47 UTC 2017] Cert success.
-----BEGIN CERTIFICATE-----
MIIE6DCCA9CgAwIBAgITAPqSDeV9j0oajwBNjbstp4DQmzANBgkqhkiG9w0BAQsF
ADAiMSAwHgYDVQQDDBdGYWtlIExFIEludGVybWVkaWF0ZSBYMTAeFw0xNzA2MzAy
MDExMDBaFw0xNzA5MjgyMDExMDBaMB0xGzAZBgNVBAMTEnd3dy51bml4YXRob21l
Lm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOaDCsU5c433w+f
JQvPZXkzVMS1GHRrYXfe1cx8ThYTICPqECIlg02e5YbFmZQDbgt8REdt5nMqR6t3
JlaAi6tthX/qjgLfRE6NQzUQS2R73Etwy+AlWXOe4RdkWd3iSA/LixqJZT9gM4O8
yB+ZyhZ9Pw7tDlINketLkWB3zPkj4NVmHaJ4eWTHqR0pT9TFS/AQVG+qtpmLvwaO
KYCvrkX/cItdXXHyQJuJ1+JMJMsmW5S7Ky0l1VGbf20PdsO4re++mAWDRvpO3RcS
L/bJJuKXair444DhUpHX76+Y3Zz827ib6IWc8zp+FPbcuBCMV+7oGuMRYgkCzX/u
hjjaB1kCAwEAAaOCAhowggIWMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggr
BgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUxebNiKsz
S79Zdy9eYzDFKUz6ZucwHwYDVR0jBBgwFoAUwMwDRrlYIMxccnDz4S7LIKb1aDow
dwYIKwYBBQUHAQEEazBpMDIGCCsGAQUFBzABhiZodHRwOi8vb2NzcC5zdGctaW50
LXgxLmxldHNlbmNyeXB0Lm9yZzAzBggrBgEFBQcwAoYnaHR0cDovL2NlcnQuc3Rn
LWludC14MS5sZXRzZW5jcnlwdC5vcmcvMB0GA1UdEQQWMBSCEnd3dy51bml4YXRo
b21lLm9yZzCB/gYDVR0gBIH2MIHzMAgGBmeBDAECATCB5gYLKwYBBAGC3xMBAQEw
gdYwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIGrBggr
BgEFBQcCAjCBngyBm1RoaXMgQ2VydGlmaWNhdGUgbWF5IG9ubHkgYmUgcmVsaWVk
IHVwb24gYnkgUmVseWluZyBQYXJ0aWVzIGFuZCBvbmx5IGluIGFjY29yZGFuY2Ug
d2l0aCB0aGUgQ2VydGlmaWNhdGUgUG9saWN5IGZvdW5kIGF0IGh0dHBzOi8vbGV0
c2VuY3J5cHQub3JnL3JlcG9zaXRvcnkvMA0GCSqGSIb3DQEBCwUAA4IBAQAwqYno
tqFqdFxAxR1DvACweV8Ao9iTyn0cAX2heuS0D+wjNPZRXpAPSeZKlfuYrlzBbOdg
8/pA1+4PO9VpIIT0V7fTBW40QljXZap+WciPEpkmSuvm2xNRA5nXtn9FntY+X6A+
E5XeaiQ7/e+qczmAFSKzLj3vXEk2ThTbFbC5jQEaX7Uwg2aYbZH+PJIof0lovICB
TeVpBMPwQCjJ60/aiMh8T0ZSNdF87wGJyLFtBLWCRbYMfRoySwr1aXtNxINoaOl4
KmKCk7CKDGjdRqd8qpWto3ymHdV1asIC3X1W+8kYLfMoHZsXH6t+0yOwUnUvRzDq
Pc7nb5W8NfThdMnR
-----END CERTIFICATE-----
[Fri Jun 30 21:10:47 UTC 2017] Your cert is in  /var/db/acme/certs/www.unixathome.org/www.unixathome.org.cer 
[Fri Jun 30 21:10:47 UTC 2017] Your cert key is in  /var/db/acme/certs/www.unixathome.org/www.unixathome.org.key 
[Fri Jun 30 21:10:47 UTC 2017] The intermediate CA cert is in  /var/db/acme/certs/www.unixathome.org/ca.cer 
[Fri Jun 30 21:10:47 UTC 2017] And the full chain certs is there:  /var/db/acme/certs/www.unixathome.org/fullchain.cer 
[acme@certs ~]$ 

What new files do I have now?

/certs/www.unixathome.org
./certs/www.unixathome.org/ca.cer
./certs/www.unixathome.org/fullchain.cer
./certs/www.unixathome.org/www.unixathome.org.cer
./certs/www.unixathome.org/www.unixathome.org.conf
./certs/www.unixathome.org/www.unixathome.org.csr
./certs/www.unixathome.org/www.unixathome.org.csr.conf
./certs/www.unixathome.org/www.unixathome.org.key

I think you can see where this is going.

Getting a real certificate

Everything up to now has been in –staging. Now we go live:

[acme@certs ~]$ acme.sh --issue --dns dns_nsupdate -d certs.unixathome.org
[Tue Jul  4 20:38:07 UTC 2017] Creating domain key
[Tue Jul  4 20:38:07 UTC 2017] Single domain='certs.unixathome.org'
[Tue Jul  4 20:38:07 UTC 2017] Getting domain auth token for each domain
[Tue Jul  4 20:38:07 UTC 2017] Getting webroot for domain='certs.unixathome.org'
[Tue Jul  4 20:38:07 UTC 2017] Getting new-authz for domain='certs.unixathome.org'
[Tue Jul  4 20:38:10 UTC 2017] The new-authz request is ok.
[Tue Jul  4 20:38:10 UTC 2017] certs.unixathome.org is already verified, skip dns-01.
[Tue Jul  4 20:38:10 UTC 2017] Verify finished, start to sign.
[Tue Jul  4 20:38:11 UTC 2017] Cert success.
-----BEGIN CERTIFICATE-----
MIIFCzCCA/OgAwIBAgISAzFhPgUiIxRB9Df/0W27wy1VMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzA3MDQxOTM4MDBaFw0x
NzEwMDIxOTM4MDBaMB8xHTAbBgNVBAMTFGNlcnRzLnVuaXhhdGhvbWUub3JnMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqyxK6kW7TGbIjffYZI2omOOT
MPogmLnQYHn+efsp4RqzRK2QTh0pMW/7BnwPKXNExfWv3ymp4G7lvrUDUQNNKjyi
fG6UL/W+EHVAW72Vx3iTdd1OLBvjTkPpP25wNLXEroJnsLLkJZODi57d8MTB71Vq
YVB6eYEv+1wrZ/o7mrcLEq+Tl5SLpmWEcoLF/DZOEEZ8Uksbh1fgsAJPRju0PgfX
nA96YBqQOViOQOuTznLO/gVBOhXbVlw7Dv/KBlUpvCNYKiNAhHKmCHx4oAzBbCdy
tJFBqPZGmxaiTxwouLfkbl9s/wuMf0oFAwZoZ3lKmQ993olREqZvwKEUB6RAGQID
AQABo4ICFDCCAhAwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB
BggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRnTjSuCVhE3wUvsbp3
/7IvpJQfiDAfBgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEF
BQcBAQRjMGEwLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5j
cnlwdC5vcmcwLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5j
cnlwdC5vcmcvMB8GA1UdEQQYMBaCFGNlcnRzLnVuaXhhdGhvbWUub3JnMIH+BgNV
HSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAmBggrBgEFBQcC
ARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwgasGCCsGAQUFBwICMIGeDIGb
VGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBvbiBieSBSZWx5
aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0
aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcv
cmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBAFDMUvXunbV1CgPxyy2Aw8TM
zvmCjQiWMalvLMVqL3DXjLyt8U0ckHeFR+crqH1aiZXbDtbTWQQpDFDbJubzk/0p
vmkqU5YeSd2M5eIYPNDnO4SqvCv1i94a7Flhr3bFpwLgHFBAfmIHL7TCl+tI9eIJ
pGQgSW2zJ7yqhj1Kmi1yLlf2hpGJEEi0eIj0rFgGXOx2k2Tj0QUlNI5ZCtw88wO6
9GCH77KfqsLKHznGOl9yZCWFg7pKYCFOiWUXb5GgON9rWrj/Rzm4AaD9k0TdQMEd
t4jMsLw8R7Lh8sHX4t5FsL9l73I6lVAHEkSdtjI1Ew6GM+uLCUytYDMhWwDLmQo=
-----END CERTIFICATE-----
[Tue Jul  4 20:38:11 UTC 2017] Your cert is in  /var/db/acme/certs/certs.unixathome.org/certs.unixathome.org.cer 
[Tue Jul  4 20:38:11 UTC 2017] Your cert key is in  /var/db/acme/certs/certs.unixathome.org/certs.unixathome.org.key 
[Tue Jul  4 20:38:11 UTC 2017] The intermediate CA cert is in  /var/db/acme/certs/certs.unixathome.org/ca.cer 
[Tue Jul  4 20:38:11 UTC 2017] And the full chain certs is there:  /var/db/acme/certs/certs.unixathome.org/fullchain.cer 
[acme@certs ~]$ 

BANG! There I have a legit cert, which you can see now at https://certs.unixathome.org/

You will note that line 8 shows that I am already verified to produce certificates for this host. Thus dns-01 validation was skipped. This is because the above was not the first time I created a certificate for that host, but I had purposely deleted the local cert, so a new key was generated and a new certificate issues. This was done for testing purposes.

But wait, there’s more!

This blog post is just about creating certs. I have more to write about how I distribute those certificates to where they are used. That will be coming soon.

Website Pin Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google StumbleUpon Premium Responsive