Securing Home Assistant with Lets Encrypt SSL, Complex Passwords, and IP Banning

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.

  1. Ensure you have a complex password
  2. Setup Port Forwarding
  3. Install SSL certificates
  4. Configure Home Assistant to use SSL
  5. Set IP Banning of anyone who tries to log in multiple times with a bad password
  6. Create a CRON job (scheduled task) to renew certificates

On Passwords

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:
mkdir certbot

Change to that directory:
cd certbot

Download the certbot installation files:
wget https://dl.eff.org/certbot-auto

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
cd /etc/letsencrypt

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:
ip_ban_enabled: True
login_attempts_threshold: 5

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:
netstat -pln
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):
crontab -e

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:
cd /var/log/letsencrypt

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:
tail letsencrypt.log

14 thoughts on “Securing Home Assistant with Lets Encrypt SSL, Complex Passwords, and IP Banning

  1. 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.

    Like

      1. I figured it out, it was way to simple…
        sudo pip3 install packaging
        sudo pip3 install appdirs

        and that handled it

        Like

  2. 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.

    Like

      1. I didn’t like having port 443 open since its so common, i just used port 8123 to 8123, works well

        Like

  3. 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)

    Like

  4. 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?

    Like

  5. 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.

    Like

  6. Great work, I just have a question, with the cron job, will you need to renew the certificate every 90 days?

    Like

Leave a comment