Home Assistant with Secure (SSL/HTTPS) DuckDNS Connection
This post is a continuation of the series:
- Install Home Assistant on RaspberryPi
- Use Samba to configure Home Assistant
- Configure Home Assistant for remote access with DuckDNS
In particularly the last one where we saw how to use DuckDNS to remotely access our Home Assistant from anywhere in the world!
What I’ll cover
The focus in this article will be securing this connection!
As it stands in fact the connection use the HTTP protocol that is not encrypted and therefore is vulnerable to attacks.
I’ll also explore how to automate the renewal of the certificate and other related sub tasks…
Without the need to say anything more right now, let’s jump straight into making our Home Assistant connection safe!
Let’s secure it with SSL and use HTTPS
Now that we can access our Home Assistant from the web we are somehow exposed when we operate on it remotely.
What I mean is that the communication through the web currently happens through an non-encrypted protocol…
We still have a solution though and this is (how the title says) using SSL to encrypt our connection (from Wikipedia):
Cryptographic protocol designed to provide communications security over a computer network.
In conjunction with it you’ll hear the other acronym HTTPS that is instead simply identifying that the protocol used to reach the page/website is secured with an SSL Certificate.
I will look into two ways to achieve this:
- One is the simplest and quickest one that does the minimum to reach the goal and will be very useful to understand the key concepts that comes into play here.
- The second one is built on top of the previous and expands it making it more professional in the way you’ll see.
Splitting this into this two section will help in understanding clearly what’s going on and why we need to do what we’ll do, without putting too much concept all together confusing the whole thing.
The key difference between the two is the creation of the Certificates used to encrypt the connection.
In the first case we’ll just create them ourselves, while in the second we’ll use a Certificate Authority.
Again, the difference is the validity of the certificate and how much we (or anyone for what it matters) can trust it… and therefore how much is the connection trustworthy.
One is the proper fully fledged way that uses certificates requested through a real Certificate Authority. For this the common solution is to use the free https://letsencrypt.org/: “Let’s Encrypt is a free, automated, and open Certificate Authority.”
The other way (a little bit quicker) is to self-sign our certificates and use them.
The drawback of the second solution is only that the authority (us) cannot be verified and therefore the browser will raise a warning of the danger… but we know it’s us ;)
I’ll use the second quick option for now, so that the main concept will be clear (not too much magic) and is both good enough for me and also allows to do the next step if we want to, focusing only on the certification step.
(https://www.home-assistant.io/docs/ecosystem/certificates/tls_self_signed_certificate/)
Create the (Self-Signed) SSL Certificates
So, let’s start with the first version and let’s create our self-signed certificate!
Login as “homeassistant” and go into the usual “~/.homeassistant” folder (check the previous posts if you are not sure what I’m talking about here).
I will create the certificates into a new folder that I’ll call “certs“:
1 2 |
homeassistant@homeassistant:~/.homeassistant $ mkdir certs homeassistant@homeassistant:~/.homeassistant $ cd certs |
To create the certificate we’ll use “openssl“. We’ll specify few parameters with the following meaning:
- “req“: From the manual: “The req command primarily creates and processes certificate requests in PKCS#10 format. It can additionally create self signed certificates for use as root CAs for example.“
- “-days 365“: I will create a certificate that will expire in 365 days. By default this would be 30 days
- “-sha256“: That’s just the secure hash algorithm
- “-newkey“: generate a new private key
- “rsa:4096“: is the type and length of the key
- “-nodes“: it stands for “no des” and it’s used to generate the private key without encrypting it (with a password). Despite the security concerns is commonly used as option, mainly because you would need to type the password to start services and therefore would create problem with auto-restarting services
- “-keyout privkey.pem“: The generated file that will contain the private key will be: “privkey.pem“
- “-x509 -out certificate.pem“: The certificate will be stored in the file: “certificate.pem“
That’s the complete command:
1 |
openssl req -days 365 -sha256 -newkey rsa:4096 -nodes -keyout privkey.pem -x509 -out certificate.pem |
When you execute it, the system will prompt you with some questions about the certificate.
In this case you can answer whatever you want (check the “Country Name”, “Common Name”, etc. in the next block to see what I put there as an example).
That’s the final output you should expect from the execution of the command:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
homeassistant@homeassistant:~/.homeassistant/certs $ openssl req -days 365 -sha256 -newkey rsa:4096 -nodes -keyout privkey.pem -x509 -out certificate.pem Generating a 4096 bit RSA private key .................................................................................................................++ .............................++ writing new private key to 'privkey.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:IT State or Province Name (full name) [Some-State]:Roma Locality Name (eg, city) []:Roma Organization Name (eg, company) [Internet Widgits Pty Ltd]:riccardotramma.com Organizational Unit Name (eg, section) []:homeassistant Common Name (e.g. server FQDN or YOUR name) []:Riccardo Email Address []:no-email |
As I mentioned above the certificate expiration date is 30 days by default but we specified “-days 356” to extend the validity to 1 year… so let’s check it out (for fun and to learn!)
You can check the expiration date with:
1 2 |
homeassistant@homeassistant:~/.homeassistant/certs $ openssl x509 -enddate -noout -in certificate.pem notAfter=Oct 20 20:57:57 2019 GMT |
That is in fact 1 year from now! (the time I’m working on this article).
Anyway, job done!
We have the certificate and the associated private key:
1 2 |
homeassistant@homeassistant:~/.homeassistant/certs $ ls certificate.pem privkey.pem |
we just need to tell our Home Assistant to use them to allow https connections… as simple as that!
Configure https
Open the “configuration.yaml“.
Look for the “http:” placeholder:
1 2 3 |
# Uncomment this if you are using SSL/TLS, running in Docker container, etc. # http: # base_url: example.duckdns.org:8123 |
Let’s change it to:
1 2 3 |
http: ssl_certificate: /home/homeassistant/.homeassistant/certs/certificate.pem ssl_key: /home/homeassistant/.homeassistant/certs/privkey.pem |
Note that the entries needs to point to the key and certificate files we created in the previous step, so change it accordingly if you created them somewhere else or with different names.
As usual, let’s verify our configuration:
1 2 |
(homeassistant) homeassistant@homeassistant:~/.homeassistant/certs $ hass --script check_config Testing configuration at /home/homeassistant/.homeassistant |
Test it out
Restart the service (and check its status if you want):
1 2 3 4 5 6 7 8 |
pi@homeassistant:~ $ sudo systemctl restart home-assistant@homeassistant pi@homeassistant:~ $ sudo systemctl status home-assistant@homeassistant.service ● home-assistant@homeassistant.service - Home Assistant Loaded: loaded (/etc/systemd/system/home-assistant@homeassistant.service; ena Active: active (running) since Sat 2018-10-20 21:24:37 UTC; 16s ago Main PID: 32273 (hass) CGroup: /system.slice/system-home\x2dassistant.slice/home-assistant@homeassis └─32273 /srv/homeassistant/bin/python3 /srv/homeassistant/bin/hass -c |
Everything is fine, so let’s test it out!
If you go to the DuckDNS page that you registered you’ll now use the secure connection (note the “https” protocol), but you’ll immediately see as well the problem I was highlighting at the start (related to the verification of the certificate and the fact that cannot be universally trusted… because we signed it and because we are the only one to say so and as far as everyone else’s concerns, no one can confirm who we are).
Using our self-signed certificates will therefore generate a warning from the browser (as expected).
This is how it looks like in Safari for example:
To confirm which certificate the browser is complaining about, and to see how everything makes sense and goes back together, click on the “Show Details” button:
and then on “view the certificate“:
as you can see, that’s exactly the certificate we signed with all the data we put above… pretty cool uh?
Hopefully this clarifies a lot what’s going on there and the reason of everything we did above.
You can instead click on “visit this website” to go ahead and reach the page we are looking for.
Similarly, as another example, if you use Chrome you’ll see something like this:
Once again, click on “Advanced“:
and then on “Proceed to …” to access your Home Assistant dashboard with a secure connection.
Again, on the address bar Chrome will make sure you remember about the non-trusted certificate…
but hopefully you know you can thrust yourself, right?
So in theory you could just be happy and safely access your Home Assistant in this way.
If you are ready instead to work more on it, because you don’t like the scary warnings, the need to press multiple buttons to access your website or you need to make it the website accessible to other people and you don’t want to scare them out, then keep reading.
Make a Trustworthy Certificate
As mentioned at the start, there are Certification Authorities that allow to create trusted certificates.
Using them will avoid the warnings that we currently receive.
The Certificate Authority I’ll use for this is https://letsencrypt.org/:
Let’s Encrypt is a free, automated, and open Certificate Authority.
The process of creating a certificate and updating it (when it expires) is a little bit involved and while we could do it manually, for this step I’ll use a script that takes care of a lot of details directly for us.
You can find it there: https://dehydrated.io/
Dehydrated is a client for signing certificates with an ACME-server (currently only provided by Let’s Encrypt) implemented as a relatively simple bash-script.
The bash-script it’s referring to is here: https://github.com/lukas2511/dehydrated
Dehydrated
If you want to grab the code from github you could checkout it with git or svn at the url: “https://github.com/lukas2511/dehydrated.git”
Just grab the code
For simplicity (especially if you don’t have git) I can just grab dehydrated downloading the files (we don’t have intention to modify/check-in or update anything and we can grab it again in the future if needed).
Anyway, I will put it inside a subfolder “dehydrated” placed inside the same “certs” folder I created before (too keep all this together):
1 2 3 |
homeassistant@homeassistant:~/.homeassistant/certs $ mkdir dehydrated homeassistant@homeassistant:~/.homeassistant/certs $ cd dehydrated/ homeassistant@homeassistant:~/.homeassistant/certs/dehydrated $ |
Let’s now download it straight from the source:
1 2 3 4 5 6 7 8 9 10 11 |
homeassistant@homeassistant:~/.homeassistant/certs/dehydrated $ wget https://raw.githubusercontent.com/lukas2511/dehydrated/master/dehydrated --2018-10-20 23:18:35-- https://raw.githubusercontent.com/lukas2511/dehydrated/master/dehydrated Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.16.133 Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.16.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 66607 (65K) [text/plain] Saving to: ‘dehydrated’ dehydrated 100%[================================================================================================>] 65.05K --.-KB/s in 0.09s 2018-10-20 23:18:36 (687 KB/s) - ‘dehydrated’ saved [66607/66607]<br> |
With git instead
With git you can simply grab the code (and it will create the dehydrated folder for you).
Go into the “certs” folder and clone the repository with:
1 |
git clone https://github.com/lukas2511/dehydrated.git |
That’s the output:
1 2 3 4 5 6 7 8 |
homeassistant@homeassistant:~/.homeassistant/certs $ git clone https://github.com/lukas2511/dehydrated.git Cloning into 'dehydrated'... remote: Enumerating objects: 8, done. remote: Counting objects: 100% (8/8), done. remote: Compressing objects: 100% (7/7), done. remote: Total 1922 (delta 1), reused 5 (delta 1), pack-reused 1914 Receiving objects: 100% (1922/1922), 637.08 KiB | 757.00 KiB/s, done. Resolving deltas: 100% (1200/1200), done. |
Make it executable
One important step is now to make the script executable.
This can be easily done with the command:
1 |
chmod a+x dehydrated |
Ok, if we follow the documentation it says that before executing it we need to specify the domain we want to secure inside a file named “domains.txt” (you can read this here: “https://github.com/lukas2511/dehydrated/blob/master/docs/domains_txt.md”)
Let’s do this then:
1 |
nano domains.txt |
Inside this file just write the name of your website, that should be something like this, naturally with your specific domain specified:
1 |
<your_domain>.duckdns.org |
Once this is done we need to edit another file “config”
1 |
nano config |
You can read about it here: “https://github.com/lukas2511/dehydrated#config”
Write this inside it:
1 2 3 4 5 |
# Which challenge should be used? Currently http-01 and dns-01 are supported CHALLENGETYPE="dns-01" # Script to execute the DNS challenge and run after cert generation HOOK="${BASEDIR}/hook.sh" |
Under the hood
If you are not interested into the details of what we just wrote, skip this section, otherwise bare with me.
Going back to Let’s Encrypt, let’s read more of its definition:
“To enable HTTPS on your website, you need to get a certificate (a type of file) from a Certificate Authority (CA). Let’s Encrypt is a CA. In order to get a certificate for your website’s domain from Let’s Encrypt, you have to demonstrate control over the domain. With Let’s Encrypt, you do this using software that uses the ACME protocol, which typically runs on your web host.”
Dehydrated is one of this software (well, script in this case) that use the ACME protocol we need. In fact, looking at dehydrated once again:
“Dehydrated is a client for signing certificates with an ACME-server (e.g. Let’s Encrypt) implemented as a relatively simple (zsh-compatible) bash-script. This client supports both ACME v1 and the new ACME v2 including support for wildcard certificates!”
Now, Let’s Encrypt need a demonstration that you control the domains you want to secure. For this we use the “dns-01” verification (you can read about other types of verification on their website). The details are here: https://docs.certifytheweb.com/docs/dns-validation.html
Dehydrated supports “dns-01” (https://github.com/lukas2511/dehydrated/blob/master/docs/dns-verification.md).
As described in that documentation, this type of verification requires you to be able to create a specific TXT DNS record (from wikipedia: “a type of resource record in the Domain Name System (DNS) used to provide the ability to associate arbitrary text with a host or other name, such as human readable information about a server, network, data center, or other accounting information.“) for each hostname included in the certificate.
Dehydrated then specified that we need a hook script that deploys the challenge to our DNS server.
In order to do this, dehydrated will invoke our hook script… more on this in a bit.
As a matter of fact, DuckDNS allows us to generate this TXT record.
Looking at the documentation (https://www.duckdns.org/spec.jsp):
“The TXT update URL can be requested on HTTPS or HTTP.”
and again:
“You can update your domain(s) TXT record with a single HTTPS get to DuckDNS your TXT record will apply to all sub-subdomains under your domain e.g. xxx.yyy.duckdns.org shares the same TXT record as yyy.duckdns.org”
As an example it’s given:
1 |
https://www.duckdns.org/update?domains={YOURVALUE}&token={YOURVALUE}&txt={YOURVALUE}[&verbose=true][&clear=true] |
as you will see, we’ll do this in our dehydrated hook, using something like:
1 |
curl "https://www.duckdns.org/update?domains=$domain&token=$token&txt=$4" |
The “$4” parameter is explained in dehydrated documentation (all the parameters):
- $1 an operation name (clean_challenge, deploy_challenge, deploy_cert, invalid_challenge or request_failure) and some operands for that.
For deploy_challenge
- $2 is the domain name for which the certificate is required,
- $3 is a “challenge token” (which is not needed for dns-01), and
- $4 is a token which needs to be inserted in a TXT record for the domain.
The DuckDNS hook is the one indicated online always in the documentation: https://github.com/lukas2511/dehydrated/wiki/DNS-01-hook-for-DuckDNS
As another example, to clear the token the real important part is only the last parameter to pass to DuckDNS: “clear=true“.
Note that the challenge token is what we’ll receive from Let’s Encrypt.
So, the full logic flow is essentially the following:
- We request Let’s Encrypt (our Certificate Authority) to generate a certificate for our domain
- We receive the certificate and the challenge token to use to prove that we control the domain
- We tell DuckDNS to update the TXT record for our domain to match the token used for the challenge
- We then tell Let’s Encrypt validate the domain (more here: https://letsencrypt.org/how-it-works/)
This should help in clarifying what is this “dns-01”, how we tell DuckDNS to verify it and the meaning of the hook script.
Ok, Where were we…
If you read the section above you should know why we need the hook script. In any case, we need a hook to help with the DNS challenge.
In the same script we’ll also provide a way of restarting the Home Assistant service and this is used when the certificate is created/updated.
Create a “hook.sh” file:
1 |
nano hook.sh |
The content comes from the one provided by Dehydrated as an example: https://github.com/lukas2511/dehydrated/wiki/DNS-01-hook-for-DuckDNS
I modified the “deploy_cert” section in order to restart the service using the “pi” account (because we need the sudo privileges).
Anyway, this is the content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#!/usr/bin/env bash set -e set -u set -o pipefail domain="<your_domain>" token="<your_token>" case "$1" in "deploy_challenge") curl "https://www.duckdns.org/update?domains=$domain&token=$token&txt=$4" echo ;; "clean_challenge") curl "https://www.duckdns.org/update?domains=$domain&token=$token&txt=removed&clear=true" echo ;; "deploy_cert") su pi -c "sudo bash; systemctl restart home-assistant@homeassistant.service" ;; "unchanged_cert") ;; "startup_hook") ;; "exit_hook") ;; *) echo Unknown hook "${1}" exit 0 ;; esac |
NOTE: change:
- <your_domain> with your specific DuckDNS domain, in the same way you did above
- <your_token> with your DuckDNS token
(if you t follow the other posts or you have a different installation, ensure to change the “deploy_cert” section as well to correctly restart the Home Assistant service)
Last thing to do is make it executable:
1 |
chmod 755 hook.sh |
Checkpoint
At the end of all of this verify that this is what you have in your folder:
1 2 3 4 5 6 7 8 |
homeassistant@homeassistant:~/.homeassistant/certs/dehydrated $ ls -la total 704 drwxr-xr-x 2 homeassistant homeassistant 4096 Oct 20 23:14 . drwxr-xr-x 4 homeassistant homeassistant 4096 Oct 20 23:03 .. -rw-r--r-- 1 homeassistant homeassistant 195 Oct 20 23:08 config -rwxr-xr-x 1 homeassistant homeassistant 697126 Oct 20 23:03 dehydrated -rw-r--r-- 1 homeassistant homeassistant 18 Oct 20 23:07 domains.txt -rwxr-xr-x 1 homeassistant homeassistant 661 Oct 20 23:14 hook.sh |
Register with letsencrypt
From the (dehydrated) documentation:
“Before any certificates can be requested, Dehydrated needs to acquire an account with the Certificate Authorities.
Optionally, an email address can be provided. It will be used to e.g. notify about expiring certificates. You will usually need to accept the Terms of Service of the CA.
Dehydrated will notify if no account is configured.
Run with –register –accept-terms to create a new account.”
The license agreement for Let’s Encrypt (at the time of writing) is there: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
If you run dehydrated without the “–accept-terms” you can see the latest terms link.
If you want to register a mail, edit your config file adding (with your email):
1 2 |
# E-mail to use during the registration (default: <unset>) CONTACT_EMAIL=<your_email> |
Time to register!
When you are ready run dehydrated with the registration options:
1 |
./dehydrated --register --accept-terms |
That should produce this output:
1 2 3 4 5 |
homeassistant@homeassistant:~/.homeassistant/certs/dehydrated $ ./dehydrated --register --accept-terms # INFO: Using main config file /home/homeassistant/.homeassistant/certs/dehydrated/config + Generating account key... + Registering account key with ACME server... + Done! |
It created a new folder “accounts” that will contain a folder with the information about the registrations with letsencrypt.
Create the certificate
We can now happily created the wanted certificate!
Just run dehydrated with this option:
1 |
./dehydrated -c |
and this should be the output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
homeassistant@homeassistant:~/.homeassistant/certs/dehydrated $ ./dehydrated -c # INFO: Using main config file /home/homeassistant/.homeassistant/certs/dehydrated/config Unknown hook this_hookscript_is_broken__dehydrated_is_working_fine__please_ignore_unknown_hooks_in_your_script + Creating chain cache directory /home/homeassistant/.homeassistant/certs/dehydrated/chains Processing <your_domain>.duckdns.org + Creating new directory /home/homeassistant/.homeassistant/certs/dehydrated/certs/<your_domain>.duckdns.org ... Unknown hook this_hookscript_is_broken__dehydrated_is_working_fine__please_ignore_unknown_hooks_in_your_script + Signing domains... + Generating private key... + Generating signing request... + Requesting new certificate order from CA... + Received 1 authorizations URLs from the CA + Handling authorization for <your_domain>.duckdns.org + 1 pending challenge(s) + Deploying challenge tokens... OK + Responding to challenge for <your_domain>.duckdns.org authorization... + Challenge is valid! + Cleaning challenge tokens... OK + Requesting certificate... + Checking certificate... + Done! + Creating fullchain.pem... Password: + Done! |
Note that at the end the script is requesting for the sudo password for pi.
This is because the hook is trying to execute “deploy_cert” that tries to restart the service.
If you didn’t change the default hook script in the way I described above, you should receive the request of the sudo password for “homeassistant”. At that point you will probably need to kill the script [CTRL+C].
Everything is still ok, but you will manually need to restart the service.
Final step
… in reality we still need to do one final step, that is update out “configuration.yaml” file of Home Assistant to point to the certificate and key we generated with dehydrated.
Last time we modified it (above) we set the keys that we self-signed.
Open “configuration.yaml” and update the HTTPS certificate section with:
1 2 3 |
http: ssl_certificate: /home/homeassistant/.homeassistant/certs/dehydrated/certs/<your_domain>.duckdns.org/fullchain.pem ssl_key: /home/homeassistant/.homeassistant/certs/dehydrated/certs/<your_domain>.duckdns.org/privkey.pem |
(put your domain of course).
Check your script!
1 2 |
(homeassistant) homeassistant@homeassistant:~/.homeassistant/certs/dehydrated $ hass --script check_config Testing configuration at /home/homeassistant/.homeassistant |
Restart the Service
1 2 3 4 5 6 7 |
pi@homeassistant:~ $ sudo systemctl restart home-assistant@homeassistant pi@homeassistant:~ $ sudo systemctl status home-assistant@homeassistant.service ● home-assistant@homeassistant.service - Home Assistant Loaded: loaded (/etc/systemd/system/home-assistant@homeassistant.service; ena Active: active (running) since Sat 2018-10-20 23:32:08 UTC; 1s ago Main PID: 3370 (hass) CGroup: /system.slice/system-home\x2dassistant.slice/home-assistant@homeassis └─3370 /srv/homeassistant/bin/python3 /srv/homeassistant/bin/hass -c |
Visit the HTTPS website
you can now open the browser and try again to reach your Home Assistant website using HTTPS:
This time the warning should have disappeared and everything should be nice and clean!
If you check the certificate this time is indeed from “Let’s Encrypt Authority” and considered valid (trustworthy):
Autorenew (cronjob)
If you check the expiration date of the certificate generated by Let’s Encrypt you’ll see that is set to 90 days.
This means that before that time we’ll have to run the dehydrated script again to refresh the certificate.
You can clearly do it manually, but is probably a good idea to automate this step.
We can easily do this setting up a cron job to execute every so often.
In this job we’ll execute the certificate creation script and this already takes care of checking the validity and:
- Do nothing: if the certificate is still valid (and more than 30 days from expiration by default)
or:
- Update the certificate otherwise
The only detail is that the service will try to restart when the certificate updates, and this, as it stands, requires to type the password for the user “pi” (check “hook.sh“)
Allow homeassistant to restart the service
in order to fix this properly we can do small modification to our system: Allow “homeassistant” to restart the service, and do not ask him any password for this!
To enable this we need to enable the sudoers file.
Now note: Is BAD to edit directly this file. So DON’T do it!
This is because if you make any error, you will compromise the system and neither the admin (pi) will be able to execute any admin command! You can still recover the situation but it will not necessarily be fun/easy.
Because of this, there is a specific command that will allow to edit the sudoers, but it will validate the changes before saving them.
So, switch to the admin (pi) user and execute the command:
1 |
sudo visudo |
You should see something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# # This file MUST be edited with the 'visudo' command as root. # # Please consider adding local content in /etc/sudoers.d/ instead of # directly modifying this file. # # See the man page for details on how to write a sudoers file. # Defaults env_reset Defaults mail_badpass Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" # Host alias specification # User alias specification # Cmnd alias specification # User privilege specification root ALL=(ALL:ALL) ALL # Allow members of group sudo to execute any command %sudo ALL=(ALL:ALL) ALL # See sudoers(5) for more information on "#include" directives: #includedir /etc/sudoers.d |
edit the file adding this at the end:
1 |
homeassistant ALL= NOPASSWD: /bin/systemctl restart home-assistant@homeassistant.service |
Save the changes and exit as usual [CTRL+X].
If everything is fine you should be back to the prompt.
If something is not correct, then the system will ask you: “What now?”
In this case press “e” and you will go back in edit mode.
Test it out
Switch to the “homeassistant” account:
1 |
sudo -u homeassistant -H -s |
and try to restart the service:
1 |
sudo /bin/systemctl restart home-assistant@homeassistant.service |
If everything has been setup correctly, then you should just get the prompt and no error nor password requests and the service will just restart. You can check the status to verify this (but for this command you’ll need to be admin (pi) again).
Edit the hook.sh
We need now to adjust our “hook.sh” to use exactly this command where it’s trying to restart the service (remember that we are now the “homeassistant” user):
1 2 |
"deploy_cert") sudo /bin/systemctl restart home-assistant@homeassistant.service |
You can test that it works simply running:
1 |
./hook.sh deploy_cert |
Add the cron job!
I will add an automatic job that will run at 8:00 of the 1st day of every month.
The command it will execute will be the “./dehydrated -c” command that will take care of renewing the certificate if the expiration date is less than 30 days ahead.
You can create a cron job with:
1 |
crontab -e |
Quick verification…
Note, to quickly test that the service restart will work you can put this in the crontab:
1 |
* * * * * ~/.homeassistant/certs/dehydrated/hook.sh deploy_cert |
then switch to “pi” and wait for the CRON log that will notify the fact that the command has been executed (and therefore the service restarted):
1 |
tail -f /var/log/syslog | grep CRON |
that after a couple of minutes will be something like:
1 2 3 |
pi@homeassistant:~ $ tail -f /var/log/syslog | grep CRON Nov 3 20:49:01 homeassistant CRON[2767]: (homeassistant) CMD (~/.homeassistant/certs/dehydrated/hook.sh deploy_cert) Nov 3 20:50:01 homeassistant CRON[2843]: (homeassistant) CMD (~/.homeassistant/certs/dehydrated/hook.sh deploy_cert) |
Anyway, as soon as you see the command executed you can kill the tail command and check the status of the service and notice that the start time should be just few seconds before.
NOTE: Remember to remove the automated job now, to avoid to constantly restart the service every minute!
Back to our real cron job
Ok, now that we know that everything work as expected, put this in the cron file instead:
1 |
0 8 1 * * ~/.homeassistant/certs/dehydrated/dehydrated -c |
then save and exit.
Job Done!
From now on, this will take care from now on of renewing the certificates when required… and restart the service when this happens! Fantastic!
Conclusion
If you followed the whole article you should now have everything clear about how connect securely to your Home Assistant and understand everything required for this.
We saw how to generate and have full control of our certificate and and also how to have any future certification done automatically for us from now on.
This effectively concludes the series of articles aimed to install our own Home Assistant using the advanced and secure settings and set it up, ready for us to easily reach it and edit its configuration in a comfortable way and operate on it from everywhere in the world and in a safe/secure way.
From this moment on we can just focus and have fun automating our home! Stay tuned! :)
If you enjoyed this article, found it interesting or just learned something new (or simply liked it) please share it, comment or feel free to if you think I deserved it or you simply want to show your appreciation :). In any case thanks for passing by and until next time!
Ciao, innanzitutto complimenti per il tuo blog. Volevo porti una domanda a proposito dei certificati SSL su Home assistant.
Posso inserire il certificato direttamente nel router (se questi lo prevede), in modo da avere poi tutta la rete ad esso connessa in https?
Io, avendo un router fritz box 7390 che permette l’inserimento del certificato SSL ho pensato di certificare il router in modo che poi vado a girare l’indirizzo del raspberry dove risiede il servizio di Home assistant per raggiungerlo in https. Però non riesco. Cioè raggiungo il fritz in https ma non l’ip del rasp con HA. La mia domanda è: sbaglio la configurazione di Home Assistant oppure ogni macchina ha funzioni di webserver deve avere il suo certificato? Ti ringrazio anticipatamente per il tempo che vorrai dedicarmi.
Ciao Nicolò,
Grazie per il messaggio e per i complimenti.
Non ho mai provato quel tipo di configurazione, ma in teoria dovrebbe essere possibile si.
Se il problema fosse il certificato personale della macchina mi aspetterei più un errore relativo al fatto che il certificato non è trusted…
Se non raggiungi per niente il raspberry ci sono un paio di cose che potresti verificare:
1. Verifica che comunque https è abilitato sul raspberry pi. Puoi provare a connetterti (dall’interno della stessa rete) all’indirizzo interno del raspberry utilizzando https, per confermare che la configurazione sia corretta (naturalmente dovresti ricevere un warning sul fatto che il certificato non è trusted, ma se non altro significa che il raspberry risponde).
2. Verifica che non sia solo un problema relativo al fatto che stai testando la connessione dall’interno della stessa rete. Nel senso che provi ad accedere all’indirizzo (esterno) del tuo router dall’interno (facendo quindi: interno->esterno->interno). A volte alcuni router hanno problemi a farti rientrare nella rete. Fai una prova a connetterti direttamente dall’esterno per vedere se risolve il problema.
Fammi sapere come va e se riesci a risolvere.
YOU ARE THE BEST !!! THANK YOU SO MUCH !!!!