Let’s make things easier with ACME.SH
Certbot is the default client to issue a certificate from Let’s Encrypt.
Why not use Certbot?
Certbot requires bind port 80 or 443 but many ISP doesn’t let incoming requests from port 80 or 443.
Certbot also required port forward so you must open the port 80 or 443 to renew certs.
The solution to this is to use a lightweight client - ACME.SH with ACME DNS-01 challenge
- It does not requires any port forwarding.
- An ACME protocol client written purely in Shell (Unix shell) language.
- Full ACME protocol implementation.
- Bash, dash and sh compatible.
- Simplest shell script for Let’s Encrypt free certificate client.
- Purely written in Shell with no dependencies on python or the official Let’s Encrypt client.
- Just one script to issue, renew and install your certificates automatically.
- DOES NOT require root/sudoer access.
How It Works
There is some way to get a valid Certificate, one of then is DNS
When the identifier being validated is a domain name, the client can
prove control of that domain by provisioning a resource record under
it. The DNS challenge requires the client to provision a TXT record
containing a designated value under a specific validation domain
name.
type (required, string): The string "dns-01"
token (required, string): A random value that uniquely identifies
the challenge. This value MUST have at least 128 bits of entropy,
in order to prevent an attacker from guessing it. It MUST NOT
contain any characters outside the URL-safe Base64 alphabet and
MUST NOT contain any padding characters ("=").
{
"type": "dns-01",
"token": "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
}
A client responds to this challenge by constructing a key
authorization from the "token" value provided in the challenge and
the client's account key. The client then computes the SHA-256
digest of the key authorization.
The record provisioned to the DNS is the base64url encoding of this
digest. The client constructs the validation domain name by
prepending the label "_acme-challenge" to the domain name being
validated, then provisions a TXT record with the digest value under
that name. For example, if the domain name being validated is
"example.com", then the client would provision the following DNS
record:
_acme-challenge.example.com. 300 IN TXT "gfj9Xq...Rg85nM"
So ACME.SH use DNS API from providers to generate and send automatically a TXT Record to prove that domain belongs to you.
Step 1: SET UP A DUCKDNS ACCOUNT
Open your browser and go to https://duckdns.org.
Sign in and create an account using one of the id validation options in the top right corner.
In the domains section pick a name for your subdomain, this can be anything you like, and click add domain.
The URL you will be using later to access your Home Assistant instance from outside will be the subdomain you picked, followed by duckdns.org . For our example we will say our URL is examplehome.duckdns.org
STEP 2: Configure AutoUpdate of DNS Domain
addons/duckdns/README.md at master · home-assistant/addons · GitHub
or
Duck DNS - install
Step 3: Instal ACME.SH as homeassistant user
$ sudo su - home assistant
$ curl https://get.acme.sh | sh
Output:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 705 100 705 0 0 499 0 0:00:01 0:00:01 --:--:-- 499
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 150k 100 150k 0 0 277k 0 --:--:-- --:--:-- --:--:-- 277k
[Fri 1 Sep 13:57:31 -03 2017] Installing from online archive.
[Fri 1 Sep 13:57:31 -03 2017] Downloading https://github.com/Neilpang/acme.sh/archive/master.tar.gz
[Fri 1 Sep 13:57:33 -03 2017] Extracting master.tar.gz
[Fri 1 Sep 13:57:33 -03 2017] Installing to /home/homeassistant/.acme.sh
[Fri 1 Sep 13:57:33 -03 2017] Installed to /home/homeassistant/.acme.sh/acme.sh
[Fri 1 Sep 13:57:33 -03 2017] No profile is found, you will need to go into /home/homeassistant/.acme.sh to use acme.sh
[Fri 1 Sep 13:57:33 -03 2017] Installing cron job
no crontab for homeassistant
no crontab for homeassistant
[Fri 1 Sep 13:57:34 -03 2017] Good, bash is found, so change the shebang to use bash as preferred.
[Fri 1 Sep 13:57:35 -03 2017] OK
[Fri 1 Sep 13:57:35 -03 2017] Install success!
## Check crontab job for auto renew.
$ crontab -l
33 0 * * * "/home/homeassistant/.acme.sh"/acme.sh --cron --home "/home/homeassistant/.acme.sh" > /dev/null
STEP 4: Just issue a cert using DNS API
Note: Automatic DNS API integration have a huge List of Provider supported - check here GitHub - acmesh-official/acme.sh: A pure Unix shell script implementing ACME client protocol
On this case I’m using DuckDNS API
run as “homeassistant” user
Command to generate certs using DuckDNS
$ sudo su - homeassistant
$ export DuckDNS_Token="<your token id >"
$ cd ~/.acme.sh/
$ ./acme.sh --insecure --issue --dns dns_duckdns -d <your_sub_domain>.duckdns.org
Example Output:
[Fri 1 Sep 14:00:23 -03 2017] Registering account
[Fri 1 Sep 14:00:29 -03 2017] Registered
[Fri 1 Sep 14:00:30 -03 2017] Update account tos info success.
[Fri 1 Sep 14:00:30 -03 2017] ACCOUNT_THUMBPRINT='[redacted]'
[Fri 1 Sep 14:00:30 -03 2017] Creating domain key
[Fri 1 Sep 14:00:35 -03 2017] The domain key is here: /home/homeassistant/.acme.sh/example.duckdns.org/example.duckdns.org.key
[Fri 1 Sep 14:00:35 -03 2017] Single domain='example.duckdns.org'
[Fri 1 Sep 14:00:35 -03 2017] Getting domain auth token for each domain
[Fri 1 Sep 14:00:35 -03 2017] Getting webroot for domain='example.duckdns.org'
[Fri 1 Sep 14:00:35 -03 2017] Getting new-authz for domain='example.duckdns.org'
[Fri 1 Sep 14:00:36 -03 2017] The new-authz request is ok.
[Fri 1 Sep 14:00:37 -03 2017] Found domain api file: /home/homeassistant/.acme.sh/dnsapi/dns_duckdns.sh
[Fri 1 Sep 14:00:37 -03 2017] Trying to add TXT record
[Fri 1 Sep 14:00:38 -03 2017] TXT record has been successfully added to your DuckDNS domain.
[Fri 1 Sep 14:00:38 -03 2017] Note that all subdomains under this domain uses the same TXT record.
[Fri 1 Sep 14:00:38 -03 2017] Sleep 120 seconds for the txt records to take effect
[Fri 1 Sep 14:02:41 -03 2017] Verifying:example.duckdns.org
[Fri 1 Sep 14:02:47 -03 2017] Success
[Fri 1 Sep 14:02:47 -03 2017] Trying to remove TXT record
[Fri 1 Sep 14:02:48 -03 2017] TXT record has been successfully removed from your DuckDNS domain.
[Fri 1 Sep 14:02:48 -03 2017] Verify finished, start to sign.
[Fri 1 Sep 14:02:50 -03 2017] Cert success.
-----BEGIN CERTIFICATE-----
[redacted]
-----END CERTIFICATE-----
[Fri 1 Sep 14:02:50 -03 2017] Your cert is in /home/homeassistant/.acme.sh/example.duckdns.org/example.duckdns.org.cer
[Fri 1 Sep 14:02:50 -03 2017] Your cert key is in /home/homeassistant/.acme.sh/example.duckdns.org/example.duckdns.org.key
[Fri 1 Sep 14:02:51 -03 2017] The intermediate CA cert is in /home/homeassistant/.acme.sh/example.duckdns.org/ca.cer
[Fri 1 Sep 14:02:51 -03 2017] And the full chain certs is there: /home/homeassistant/.acme.sh/example.duckdns.org/fullchain.cer
Step 5: ConfigureHA to use Certs
The final step is to point Home Assistant at the generated certificates.
http:
api_password: YOUR_SECRET_PASSWORD
ssl_certificate: /home/homeassistant/.acme.sh/example.duckdns.org/fullchain.cer
ssl_key: /home/homeassistant/.acme.sh/example.duckdns.org/example.duckdns.org.key
Hope it helps.