This post assumes you have installed Home Assistant following the diyAutomate installation posts (on Raspbian). Docker and other installation methods can be found on the Home Assistant or Let’s Encrypt web sites.
This post also assumes you have a Dynamic DNS service configured. Many routers have DDNS built in, or you can see the diyAutomate article Using Dynamic DNS in your home Automation Architecture using Duck DNS.
Ensure Port 80 is forwarding to Home Assistant:
For this installation to work you will need to enable port forwarding of external port 80 to your servers internal port 80
Because every router is different I am not going to walk you through opening the port. There is an excellent resource on the net (portforward.com) that has instructions for many routers. Please see https://portforward.com/router.htm
Once port forwarding is complete your Home Assistant server is published to the internet. However it is NOT SECURED. You will need to do the following things to secure it:
As part of the installation I am going to assume that Home Assistant will be served from port 443 (externally) permanently after this process. We will leave port 80 forwarding to port 80 for certbot to use when your certificates need to be renewed. Certbot will only open this port on your server during the renewal process, port 80 will not be available at any other time.
- Ensure you have a complex password
- Setup Port Forwarding
- Install SSL certificates
- Configure Home Assistant to use SSL
- Set IP Banning of anyone who tries to log in multiple times with a bad password
- Create a CRON job (scheduled task) to renew certificates
The most common password attack is called a dictionary attack. this is where an attack has a very large file of possible passwords (10’s of thousands of password guesses), and uses a script to try each password, one after the other until a successful logon is obtained. A complex password is one of the easiest ways to make this difficult I recommend at least 10 characters, including upper case, lower case, and numeric values, special characters such as # add to the security as well.
Install SSL certificates
What is SSL:
Without going into the technical way in which it works (public and private certificates), SSL can be thought of as a way to encrypt communications between two points. In this case a web browser and Home Assistant.
Why use SSL:
You should use SSL because without it all your communication is sent in plain text. Meaning that if someone wanted to, they could listen in on your communications between your browser, (on your computer, cell phone, or any other way you connect) and Home Assistant. Most importantly this includes your user name and password
Why Get certs from Let’s Enctypt:
Let’s encrypt is a free SSL certificate issuing authority maintained by the Electronic Frontier Foundation. It is free, secure, and can be setup to auto-renew (a cert lasts 90 days by default).
There are many agents that can help us get and install certs from Let’s Encrypt. We will use the one Let’s Encrypt recommends (certbot). It is fast, easy, and free.
there are a few ways to install certbot. The EFF website would have you install the backports repository. I think this way is much easier.
How do I install and use a Certificate?
from your home drive (
cd ~) make a directory called certbot:
Change to that directory:
Download the certbot installation files:
change the permissions on the installation file (to allow execution):
chmod a+x certbot-auto
Execute certbot to get your certificates (do not run this as sudu)
./certbot-auto certonly --standalone --preferred-challenges http-01 --email YuurEmail@address.com -d YourDomain.duckdns.org
The instalation will take serveral minutes. You will be asked several questions. You can safely say yes to all of them (there is one asking to give your email address to EFF. That is up to you).
Change to the letsenctypt directory
Change permissions of the live and archive directories, this will make it so users other than root can access the certificates (such as the home assistant users)
sudo chmod 755 /etc/letsencrypt/live/
sudo chmod 755 /etc/letsencrypt/archive
You are now done with the SSL certificate installation and configuration.
Configure Home Assistant to use the new certificates:
Open configuration.yaml and configure the http: component as follows:
http: api_password: !secret http_password ssl_certificate: /etc/letsencrypt/live/YourDomainName/fullchain.pem ssl_key: /etc/letsencrypt/live/YourDomainName/privkey.pem
Set IP Banning
It is also a good idea to limit the amount of failed logon attempts. There are advanced ways to do this, but Home Assistant has an antiquate one built in. Add the following line to the http component (change 5 to any number you are comfy with:
Final http: component:
http: api_password: !secret http_password ssl_certificate: /etc/letsencrypt/live/[Yours].duckdns.org/fullchain.pem ssl_key: /etc/letsencrypt/live/[Yours].duckdns.org/privkey.pem ip_ban_enabled: True login_attempts_threshold: 5
For more info on all http component options please see the Home Assistant help page
Set Up A CRON job to Automatically Renew Certificates.
We have configured to port forwarding rules on our routers. Port 443 forwards to our Home Assistant instance (port 8123 by default) and Port 80 forwards to the same IP for use by Certbot.
There is a level of build in security because Certbot only opens port 80 when it is needed. When Certbot is not obtaining or renewing certificates it is not listening on any ports.
You can check the ports your server has open by issuing the following command:
For an explanation of netstat and it’s switches see: http://www.computerhope.com/unix/unetstat.htm
Because we are using two different ports, we will not have to take Home Assistant offline to renew the certificates. We will use crontab to schedule the renewals.
To edit your CRON table type the following command (do not use sudo):
pick the editor you would like to use (I recommend nano)
at the end of the file add the following line
0 13 * * * /home/haadmin/certbot/certbot-auto renew --quiet
Save and exit the file
This will schedule a renewal attemp at 13:00 hours every day (you can change this to any time or interval you would like). For more info See: https://debian-administration.org/article/56/Command_scheduling_with_cron
if you would like to ensure your cron job is running (and I recommend you do) follow these stesp:
Make sure you are logged off when the cron job is supposed to run (it will work with you logged in, but being logged off ensure all permissions are set correctly (all permissions are set correctly as part of the default installation)
Change to the log directly root:
grant access to the letsencrypt directory:
chmod 775 /var/log/letsenctypr
The most recent logfile is letsencrypt.log. to see the contents of this log:
14 thoughts on “Securing Home Assistant with Lets Encrypt SSL, Complex Passwords, and IP Banning”
Thanks for all your help and great how to’s. are you using a virtual eniv for ha? I’m using hasbian and I’m booming out on the certbot.
Thanks again for all the hard work! these have helped me a ton.
I am not using a virtual environment. I have other videos that show my full setup. It is raspbian (via pi bakery) and and a straight HA install.
I figured it out, it was way to simple…
sudo pip3 install packaging
sudo pip3 install appdirs
and that handled it
just a quick question on port forwarding…..are you assuming that external ip xxx.xxx.xxx.xxx:443 gets forwarded to HA internal ip xxx.xxx.xxx.xxx:8123. I also did not understand where to forward external ip: xxx.xxx.xxx.xxx:80 to which internal ip:80?
Though all routers are different, it would have been nice you could have demo’ed it on one router so we could adapt it to suit routers we have.
Point taken. External port 80 forwards to your H.A. server port 80 and 443 forwards to 8123.
I didn’t like having port 443 open since its so common, i just used port 8123 to 8123, works well
the reason i did not change ports on the router is that way i can access the same url inside and out (and ports work on the iOS app)
yes…that works. everyone likes specific things…that is why we like to do it ourselfs….:)
Thanks for the great videos Paul they’re super useful!
I’m running into an issue on the final step, when I try to enable the SSL in the config file then navigate to my https://mydomain.duckdns.org I get “This site can’t be reached”. I have both port 80 forwarding to 80 and 443 to 8123 for the IP of HA. I also can no longer access HA using my local network until I uncomment out the cert and key in the config. At which point I can reach HA using http://mydomain.duckdns.org:8123 from outside my network.
Do you have any suggestions on what the issue could be?
did you use nslookup to make sure your dns record is pointing to the right address?
Nslookup using – mydomain.duckdns.org returned my external IP correctly do you have any other suggestions on how I can troubleshoot this?
Sorry about the delayed response I wasn’t notified. I just ran nslookup using mydomain.duckdns.org and it returned my external IP which I just double checked so that part looks ok.
Great work, I just have a question, with the cron job, will you need to renew the certificate every 90 days?
No, that is what the cron job does for you.