How to configure Let's Encrypt SSL Certificates for Home Assistant completely 100% free (Updated for 2022/2023)

UPDATED 2/22/2023: It looks like Cloudflare may be preventing users from getting Let’s Encrypt certificates using domains that end in cf, .ga, .gq, .ml or .tk. In order to continue with a completely free solution, you may need to implement your own DNS server as described by the EFF (organization that created LE). Due to the complexity required, a new help document will need to be created and will likely be beyond the skills of the novice home user.

I’m brand new to Home Assistant and was going through the documentation and found that they could use some updating. So I figured I’d do the Open Source thing and update it myself.

This topic will cover how to enable Let’s Encrypt for free SSL certificates and enable you to use your own domain that you can get for free (as of this writing). There is this old topic from May 2020 (Updated in 2021). The Let’s Encrypt Addon makes obtaining the certificate much easier.

There is also this blog post that is even older and many of the settings do not apply to the current version of Home Assistant.

Much of the configuration can be done by someone who has very little technical skills.

I should also note that while “hands-on-keyboard” time is likely to be about a two hours MAX, the total amount of time it will take to set everything up is 1-2 days due to how DNS works. If you want a faster turn-around, you can continue to use DuckDNS (or similarly free subdomain providers) but I’ll walk you through how register a free domain.

Services we’ll be utilizing:

Get your domain first

When you get a domain name, the name and configuration must propagate throughout the root DNS servers around the globe. On average, it can take 1-2 days, but I recommend giving it three days for good measure.

Go to freenom and get a domain ending in .tk, .ml, .ga, .cf, .gq. If you want a .com or something more conventional, you’ll need to pay for it. They can run you about $10-15 a year. I personally recommend namecheap.com. I’ve been using them for almost 20 years. I won’t cover instructions on using a different registrar but you should be able to follow along.

Some notes when registering:

  • Most registrars have a “privacy” mechanism whereby if someone tries to do a ‘whois’ lookup on the domain, they won’t get your actual personal information. Typically it’s an email with the registrar that someone can contact. While Freenom includes this service when you check out, I am not holding my breath. You may want to consider registering with non-personal information just to be on the safe side.
  • It should also be noted that due to the fact that these domains are free, it tends to attract spammers, hackers, etc. If you’re on a forum and you are providing links to your legit digital assets, it may get flagged for spam simply because you’re using one of their TLDs. You using them for personal use is completely allowed per Freenom’s terms of use but just be aware of the reputation.

Once you go through the registration process, go to “Services” > “My Domains”. It can take you an hour or two to have the domain come up on the portal. Most times, it’s instantaneous.

Either way, you are ready to go to the next step.

Create a Cloudflare account

The internet needs a way to resolve your cool new domain name to an IP address. Cloudflare is a very reputable company and have been around for ages. I’ve personally been using them for 15+ years and is very easy to use and does not require a credit card.

Create a Cloudflare account.

Once you are logged in, go to “Domain Registration” on the left-hand side. You might see a notice saying you need to verify your email. Make sure you do that before continuing.

Once your email is verified, click on the “Add site” button at the top of the page. Type in your newly created domain in the prompt and click “Add site”. Remember: Your domain may not be available yet. If you get an error, it means that your domain hasn’t propagated yet to Cloudflare yet. Don’t worry; it just takes time.

If Cloudflare is able to add your domain, go ahead and complete your registration by selecting the “Free” service and then click “Continue”.

Either way, you are ready to go to the next step.

Assign Cloudflare as your DNS provider

Once Cloudflare can pick up your domain, you’ll be presented with instructions on the kind of service you want. Scroll down to the “Free” service and then click Continue.

Cloudflare will scan for existing records for your domain. Since none exist, you’ll be presented with the Cloudflare nameservers you must add on Freenom’s site. Make note of BOTH domains or open a new tab and log back into your Freenom account.

After logging back into your Freenom account, select the “Manage Domain” button that is next to your domain. Select “Management Tools” > “Nameservers”. Select “Use custom nameservers” and enter the server names that are shown for your DNS records on Cloudflare’s website. Once done, click “Change Nameservers” at the bottom.

Name Server changes can happen pretty quickly but can take up to 24 hours. You can continue with the process in the mean time, up until you get to the point of actually getting your certificates.

Register your subdomains

It is highly recommended that you use a subdomain to access your Home Assistant so that there is a bit of buffer between your domain and your home. While it takes some additional set up that I won’t go into detail in this document, you can actually have your home network setup like this:

  • domain: example.tk
  • Home Assistant URL when outside your personal network: homenetwork.example.tk
  • Home Assistant URL when accessed inside your personal network: homeassistant.homenetwork.example.tk

To get the above to work, you’ll need to create a new “A” record for “homenetwork”. To do so, click on “DNS” on the left side. When your DNS records show up, click “Add record” toward the middle of the page.

Fill out the form with the following information:

  • You’ll be creating an “A” Type record. The creation of other record types are not covered in this document. They are not needed for Home Assistant.
  • Name is the subdomain. In the example provided, you can use “homenetwork” or “home” or whatever suites your fancy.
  • IPv4 Address is YOUR home IP address. If you need to look that up, you can use https://whatismyipaddress.com/
  • Proxy status: turn OFF so it says “DNS only”
  • TTL leave unchanged to Auto

You can create a comment about this record if you prefer. Once you are satisfied, click “Save”.

Check your IP address

Subdomains can take a few minutes to an hour or two to resolve. Cloudflare is faster than most other DNS providers and will often update within 5-10 minutes. Most of your waiting is going to be on Freenom propegating Cloudflare’s nameservers throughout the internet. You can check on it’s status by using Google’s dig tool or, if you’re comfortable with the command line, dig on Mac and Linux, and nslookup on Windows.

If you are using Google’s dig tool, type in the subdomain along with the domain in the “Name” field. With my example, I’d type in “homenetwork.example.tk”.

If you get “Record not found!” then you still need to wait. Give it a few hours and then check again. Remember it can take up to a day to complete.

While you are waiting, you can continue onto the next step.

Create a Cloudflare API token

An API token is needed to allow Let’s Encrypt verify that you own the registered domain. This token should be treated like a password: do not give it out or publish it anywhere. No one will ever call you or email you and ask you for this token.

Click on the “person” icon on the upper right hand corner on Cloudflare. Click on “My Profile”.

Once there, click on “API Tokens” on the left menu. Then click on “Create Token”.

According to the Let’s Encrypt documentation, the API token requires edit access to your domain. Select the “Edit zone DNS” template.

Under “Zone Resources” select your specific domain. It should read “Include” “Specific zone” and then your domain.

Leave all of the other values in their default state.

Click “Continue to summary”. Review your options and then click “Create Token”.

Copy the token to notepad or somewhere else safe on your local computer. You will need it again later. You will NOT be able to retrieve it again, forcing you to “roll” your credentials.

Once you have your token safely stored, you can move onto the next step.

Check your external connection

If you have not yet completed the instructions listed in Remote Access, you should do that first.

Once your domain is working and the dig tool returns a record for your subdomain, then it’s time to finally test your connection. Using your mobile phone, disconnect from your home wifi and then update the companion app’s URL to the subdomain that you created.

If everything worked, congrats! You can move onto setting up Let’s Encrypt.

If you cannot connect, double-check that your IP address has not changed. These days, it’s rare for your IP address to change. However, your IP address is not guaranteed by most home ISPs. There are a number of tools that provide a mechanism to update your IP address on Cloudflare automatically.

If you’ve checked your IP address, then your router is most-likely blocking your access. Review the instructions listed in in Remote Access to ensure that you have a Port Forwarding rule set up.

Let’s Encrypt Certificate vs. Cloudflare Certificates (Skip this if you aren’t into the nerdy stuff)

Cloudflare offers something akin to Let’s Encrypt by allowing SSL traffic to be encrypted between the host (in this case Home Assistant) and the rest of the world. If you wish to do this, please read their documentation. There are some pros/cons with this but I have decided to leave this out. While easier to set up, I personally think it’s not as safe as it can create a man-in-the-middle that you do not control between Home Assistant and your devices.

Doing this also will require you to log into Home Assistant through the Internet, creating some additional latency, albeit minute.

Install the Let’s Encrypt Addon

Log into your Home Assistant web portal and then go to “Settings” > “Add-ons”. Click on the “Add-on Store” on the bottom right corner and search for “Let’s Encrypt”.

Click “Install” but do NOT select “Start on Boot”. We’ll enable this at the very end.

Configure Let’s Encrypt

Once installed, click on the “Configuration” tab.

Click on the “Kabob” menu on the right side and click “Edit in YAML”. (The UI does not present you with the ability to type in a domain name.)

Copy and paste the text below, replacing what is listed:

domains:
  - homenetwork.example.tk
  - "*.homenetwork.example.tk"
email: [email protected]
keyfile: privkey.pem
certfile: fullchain.pem
challenge: dns
dns:
  provider: dns-cloudflare
  cloudflare_api_token: replace-me-with-your-api-token

Under the “domains” property, you’ll notice that I provided both the subdomain and what’s called a wildcard domain. This is necessary if you want Home Assistant to not give you an error while you are inside your home network.

A real email address is not required. Providing one will send you reminders when your certificate is about to expire.

Be sure to replace the “cloudflare_api_toke” with the token you generated a few steps ago.

Once complete, hit save.

Start the Let’s Encrypt Addon

Return to the “Info” tab for the Let’s Encrypt addon. Click “Start” and hold your breath!

If everything worked, you should see a green circle on the upper-right corner of the addon. Go to “Log” to confirm everything ran correctly. Once done, set the “Start on Boot” option.

If you got an error, double-check that your API tokens are correct, rolling them if necessary. You do not need to update your HTTP port as you are verifying using Cloudflare.

Finally, install your certificates

Once everything is completed, you’ll need to update your configuration.yaml. The easiest way to edit this file is by installing the Studio Code Server

Ensure you have the following lines under http:

http:
  ssl_certificate: /ssl/fullchain.pem
  ssl_key: /ssl/privkey.pem

Once updated, you’ll need to restart Home Assistant. And once it’s updated, you’ll need to start using your full domain URL to access Home Assistant. So on your local network, that would be homeassistant.homenetwork.example.tk or homenetwork.example.tk (depending on your local network settings). You will continue to get the same “Untrusted” message if you try to access Home Assistant using https://homeassistant:8123 or anything without your registered domain. This is a limitation/feature of Let’s Encrypt.

Final notes

I will make every attempt to keep this documentation updated for at least the next year but feel free to DM me if something is no longer working or if something is out of date.

One thing I haven’t tested yet is whether Let’s Encrypt will actually rotate my certificate. It should in a few weeks. As of this writing, I have 59 days left. I was able to create a card for Lovelace using a command line sensor that read from a JSON file produced by cfssl. but that’s getting into advanced territory. If this would be of interest, please let me know.

Hopefully this will be useful to all of you looking to accomplish the same thing and are new to Home Assistant. If I missed something, feel free to let me know in the comments.

24 Likes

I’ve followed your instructions. After configuring and starting Let’s Encrypt, the log shows that it successfully generated the certificate and the key, but then after that the log says “cp: can’t create ‘/ssl//ssl/privkey.pem’: No such file or directory”

So it’s trying to copy the file to a bad directory, but I can’t find anywhere that this directory is defined as the destination for LE to copy the file to. Any ideas?

A couple more site to check one’s external IP Address

and

https://ifconfig.io/

:slight_smile:

/ssl//ssl/privkey.pem is a bad directory name. It sounds like something might not be configured correctly. Try uninstalling/reinstalling the Let’s Encrypt plugin.

Or post your config and I can try to help.

Hi,

Thanks for the guide. It collects the same steps I followed but then there’s two problems with it:

  • freenom domains seems to be blocked by cloudflare. I get these error when trying it:

Requesting a certificate for *.myfreenomdomain.ml
Encountered CloudFlareAPIError adding TXT record: 1038 You cannot use this API for domains with a .cf, .ga, .gq, .ml, or .tk TLD (top-level domain). To configure the DNS settings for this domain, use the Cloudflare Dashboard.

  • Are wildcards domains supported (liek your example snippet for the addon)? If so, how do you setup the wildcard CNAME at cloudflare?

Thanks!

Good day @diamant-x ! I apologize for the delay in responding.

After a quick search, it looks like Cloudflare made a change back in May of 2020 that prevents users from using those TLD domains. I wonder if the reason I was able to is because I have a long-standing account with them.

I’ll update my post accordingly. – DONE

Please read my update at the very top of the post. If you’re tech savvy, you can stand up your own DNS server. But it might be outside of what a novice home user can accomplish.

You might want to add : if your ISP does not give you a fixed IP-address, you can use the Cloudflare integration to update your IP when it changes.

1 Like

Hi,

What is wrong with my syntax?
It won’t let me save.

BTW, I saw this in the documentation. Do I have to provide both?
What is the difference? Where do I find each one of them?

cloudflare_api_key: ’ ’
cloudflare_api_token: ’ ’

Thanks.

@siqueira

Try putting your domain name between quotes. At a minimum, I think the wildcard domain needs to be quoted such as

- "*.domain.app"

when im trying start letsencrypt nothing happens…
log:

s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
cont-init: info: running /etc/cont-init.d/file-structure.sh
cont-init: info: /etc/cont-init.d/file-structure.sh exited 0
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
services-up: info: copying legacy longrun lets-encrypt (no readiness notification)
s6-rc: info: service legacy-services successfully started
[21:13:24] INFO: Selected DNS Provider: dns-cloudflare
[21:13:24] INFO: Use propagation seconds: 60
[21:13:24] INFO: Use CloudFlare token
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Certificate not yet due for renewal
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate not yet due for renewal; no action taken.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
s6-rc: info: service legacy-services: stopping
s6-rc: info: service legacy-services successfully stopped
s6-rc: info: service legacy-cont-init: stopping
s6-rc: info: service legacy-cont-init successfully stopped
s6-rc: info: service fix-attrs: stopping
s6-rc: info: service fix-attrs successfully stopped
s6-rc: info: service s6rc-oneshot-runner: stopping
s6-rc: info: service s6rc-oneshot-runner successfully stopped

ohhh… now i restarted hostmachine and all working

1 Like

Just wanted to say thank you! Instructions worked perfectly. Long time cloudflare customer, so this was perfect!

3 Likes

Thank you so much @HoneypotLeopard. I’ve been struggling to get my Google Domains certificate updated, but your guide was perfect.

Hey i followed the guide like this:

  • bought namecheap domain
  • added cloudflare
  • created home.mydomain.xyz → My IP
  • started letsencrypt

i can now access my ui with home.mydomain.xyz:8123 with an ssl connection. I kinda missed how you configured the homeassitant.home.mydomain.xyz subdomain and how you do not have to use the 8123 port anymore. Did i miss this or is it a router setting (german fritzbox)

ok i followed along this: Installing TLS/SSL using Let’s Encrypt - Community Guides - Home Assistant Community (home-assistant.io)

and did a port forwarding 8123 → 443. so i can access by using home.mydomain.xyz[:443] remotely.
how does homeasstant.home.mydomain work?

Thank you so much for this step-by-step guide!
I too have gone through the whole guide and everything mostly works but like jakethedog above I would like to see how I can create a subdomain for my home network too!

Setting up a sub-zone is kind of outside the scope of this document and is a bit more complex. It requires you to manage your internal network using a DNS resolver (dnsmasq in my case). Most home routers are not set up for this and the configuration can be wildly different.

Generally speaking, you need to find a setting that sets your local DNS domain. Your router might call this your local domain and some routers will default this to the router’s name.localdomain or something similar.

From there, you assign hostnames to your DHCP clients, either through your router’s DHCP settings or directly on each of your devices.

Now to your second point: I do not recommend using native port 443 or HomeAssistant port 8123 for your external access. Since 443 is the default port number for SSL connections, your IP address is going to get pounded by automated bots that are searching for vulnerable web servers. And using 8123 puts you in the same area where bots will be looking for Home Assistant servers that they can penetrate.

I’d recommend using a random port number, somewhere in the upper range and then use your router’s port forwarding feature to send traffic from that port number to your Home Assistant’s IP on it’s standard port 8123.

CC: @SHS

“# Create a Cloudflare account”
I’ve had trouble because my email address ends with “.net.”
After filling out the required information to create an account on Cloudflare, I get an error message that says, “Email is REQUIRED!” In other words, it acts as if I’d left the field blank. Just a note for anyone else who has that problem, and maybe doesn’t understand what the problem is…
I’ll just have to use a gmail account for that…
( Honestly, I haven’t run into that problem in more than 30 years! When the Internet first went “mainstream” there were a few services that had that limitation–because whomever wrote the script for a form (to provide input validation) didn’t imagine that anyone’s email address could possibly end in anything other than “.com” but that hasn’t happened to me since the early days!)
And, BTW, thanks for taking the time & trouble of writing this tutorial!

1 Like

and did a port forwarding 8123 → 443. so i can access by using home.mydomain.xyz[:443] remotely.
how does homeasstant.home.mydomain work?

Just a heads up for security, I would NEVER expose HA externally. If you are using Cloudflare, use an app tunnel (free for like 10 services on each domain). That way your network is not exposed, but you can still access your system. Services like Shodan (and thousands like Shodan), scan the entire internet and every single IP and look for all ports open, and you invited hackers and really anyone into your main network with no security. Port Forwarding is a HORRIBLE idea and leaves you extremely vulnerable. If you must expose the actual site external, setup a DMZ subnet and properly firewall off and segment your hosts on another subnet/vlan. This is a HIGHLY advanced configuration though and your home router will not be able to do this…

Using the Naba.casa URL service is best. Its cheap and worth it and you are not exposing your network, and still makes it where you can access it. OR if you use Cloudflare, they have a feature called App Tunnels, and that allows you to have public facing apps (like HA/UptimeKuma/personal websites/etc…) hosted from your own servers in your home and not expose through your firewall. It uses an agent that communicates with itself over its own 443 tunnel and caches your site/app if you want, and other features, all for free! I do this with a handful of external facing apps I have and I do not have any open ports external on my network. And then you get DDoS and other basics protection with Cloudflare.

I am a Lead Sr. Cyber Security Architect for a fortune 500 financial firm, and see a ton of things daily on attackers using new ways no one ever thought of to get in. You may say “its just my home network, who will care” Well, Sites like Shodan index your IP and open ports and what is running in those open ports and bored hackers can have scripts that just go out and saw give me all home assistant available external and start attacking peoples homes, literally.

1 Like

That wall of test is cool and all, but this is probably easier to follow:

Or if you prefer nabu casa, this one is for you:

As a side note, you are using technical terms incorrectly - many of them.

The A record you are registering in dns is not a subdomain, it’s a dns host name, also known as an FQDN, or fully qualified domain name.

Lastly,i don’t see that you addressed how your solution deals with users hairpinning their firewalls - which is bad for myriad reasons.