Backing up Home Assistant to TrueNAS Scale
Last Updated:UPDATE: Since the release of Home Assistant 2023.6 you are able to add network storage directly to Home Assistant and the process for backing up to TrueNAS is ridiculously easy.
Directly below is the new way to do this, but I'm keeping the old way on here for reference in case I ever need to look back at it.
In Home Assistant, go to Settings > System > Storage and click the Add Network Storage button
Enter a name for the entity/folder. I'm calling mine trnas_ha
Select the Backup radio button
Enter the IP address of your TrueNAS device
Select Network File Share (NFS) radio button
Enter the path to your backup dataset. /mnt/<Pool>/<dataset>/home-assistant. (See the Home Assistant section below for more details on this)
Click the Connect button
Go to Settings > System > Backups
Click the three dots in the top right corner and select "Change default backup location"
There should be a dropdown and the NAS should be selected
Click the Create Backup button in the bottom corner
Give this backup a name. I'm just doing `trnas_test_backup.
I'm selecting to do a partial backup and just backing up Node-RED. I'm doing this because I just want to make sure it's connected and works.
Click the Create button
It should only take a second because it's a partial backup. I've got my dataset mounted to my computer and when I refresh I can see the backup I just created.
All is good. Now you can just set up a script/automation/whatever to do this at whatever interval you want and it'll always just go to the TrueNAS box.
These are the original instructions that are outdated
What I'm doing:
- Create a dataset in TrueNAS to store Home Assistant backups
- Share that dataset via NFS in TrueNAS
- Mount the share from TrueNAS to the
/backupfolder on the Home Assistant machine - Set up an automation in Home Assistant to do regularly scheduled backups
- Backups should be saved to the shared folder, which is a dataset on TrueNAS
If you've looked up how to mount an NFS share in Home Assistant for backing up to a NAS you've probably figured out that it's not as simple as you would think. Yes, you can mount the drive, but it won't stay mounted after reboots and the automatic backup folder can't easily be changed. So that means we have to find a work-around. I think what I've got here is a pretty good solution and seems to be working quite well.
TrueNAS
Create a new dataset to hold all the backups. I'll just call mine home-assistant
I just set the permissions to allow Other to read/write, but depending on your situation you might want to create a new user and give the permissions to them. Just make sure to set it to whatever user is active in the container Home Assistant is going to run the script in. I would suggest keeping it as the default root with all the permissions checked until it's working and then go back and make changes because it can get confusing when trying to debug if it doesn't work.
Create a new NFS share for the home-assistant dataset that was just created.
In the Hosts section, allow the IP address of your Home Assistant device
Save
Home Assistant
Create full backup
This is just a good idea before messing with stuff like this. In Home Assistant go to Settings > System > Backups and click the "+ Create Backup" button at the bottom right of the screen
Give the backup a name and make sure the "Full Backup" radio button is selected Click the Create button
Once it's done, click on the backup you just created, click the three dots at the bottom of the modal that appears and select Download. Save it somewhere just in case you need it.
Delete all the backups in this folder. This isn't necessary, but since this is going to be automated, I just want to start fresh.
This is where things start to get tricky.
The problem(s): Home Assistant runs several containers and each of them have different privileges and also different directories mapped. When you run a shell_command action, it runs inside a Home Assistant container that does not have access to the /backups folder that the other ones do. This means we have to SSH in to a container that does have access to the backups, mount the NAS drive and copy them over. Let's begin...
- Download and install the SSH and Web Terminal add-on.
- Download and install the File Editor add-on.
On the main screen for the SSH add-on, flip the switch to add it to the sidebar (optional) and turn off Protection Mode then restart the add-on.
On the Configuration tab of the SSH plugin, take note of the username/password. We'll need these in a minute. I don't remember what the defaults are, but change them if you want. For the following steps, I'm using the username hassio.
Open up the Web Terminal and get in to the Docker container that Home Assistant uses for running shell scripts by typing: docker exec -it homeassistant bash
After running that you should be in a bash shell, not as pretty as the zsh one, but oh well...
Do an ls -l /. You shouldn't see the /backup folder in there. This is why we can't just do a simple mount/copy. The container that runs all the shell_commands can't see our backups for whatever reason.
Generate SSH keys for this container to use with the container the SSH add-on is using
ssh-keygen -t rsa -C "keys-for-backup"
The -C "keys-for-backup" flag is just a comment, this can be whatever you want
Press Enter and just skip though all the questions
Once that's done, make sure it generated the keys with: cat ~/.ssh/id_rsa.pub
You should see a string like ssh-rsa AAAAIg2Wh47gx0VEoA...RQmDax93 keys-for-backup
Copy this whole thing somewhere
Sometimes copying from this web terminal doesn't work out so you can do:
mkdir /config/temp
cp ~/.ssh/id_rsa.pub /config/temp/id_rsa.pubAnd then open the file up in the File Editor plugin and copy it from there when you need it. 🤷♀️
(still in the bash shell here)
SSH in to the SSH/Web Terminal container <add-on-username>@a0d7b954-ssh. Since my username for the addon is hassio, I'm entering hassio@a0d7b954-ssh.
Type yes to add this host to the known_hosts file and enter your password (the one from the SSH add-on configuration page)
You should now be in a zsh shell and connected to the container that runs the SSH add-on
Do another ls -l / and you should see the /backup folder
Exit this container with exit and we'll be back in the bash shell (the homeassistant Docker container)
Open the configuration tab for the SSH/Web Terminal add-on.
In the field that says authorized_keys: [] put the ssh-rsa AA... string from earlier. This will let us log in to this container without having to enter a password. We need to do this because when we run the shell_script action we won't be able to interact with the shell, it'll all just have to work in one go.
Save and restart the add-on
Open the File Editor add-on
It should automatically open up the configuration.yml file, but if not, open it.
In that file add:
shell_command:
nas_backup: "ssh <add-on-username>@a0d7b954-ssh 'sleep 10 && sudo mkdir ~/backup_to_nas && sudo mount -t nfs4 <your-truenas-ip>:/mnt/<pool>/<dataset> ~/backup_to_nas && sudo cp /backup/$(ls -t /backup | head -n1) ~/backup_to_nas && sleep 5 && sudo umount ~/backup_to_nas && sudo rm -rf ~/backup_to_nas'"
Change the <add-on-username>, <your-truenas-ip>, <pool> and <dataset> sections
This is where the magic happens. I'll try to break this down:
ssh hassio@a0d7b954-ssh
- log in to the SSH/Web Terminal container because that container has access to the backups we need
The commands wrapped in single-quotes after that are commands that will get run as soon as the SSH connection is made. So they'll run on the SSH/Web Terminal container
sleep 3
- Basically just wait for three seconds for good measure. No harm in that.
mkdir ~/temp_nas
- Create a temporary folder to mount our TrueNAS dataset while we transfer the backup
sudo mount -t nfs4 192.168.X.X:/mnt/<Pool>/<dataset> ~/temp_nas
- This will mount our TrueNAS dataset to the
~/temp_nasdirectory we just created. The-t nsf4tells it to use NFS4, I'm not 100% sure if this is always required, but I couldn't get it to mount without it. Make sure to change the IP address and path to match your TrueNAS IP and the path to your dataset
cp /backup/$(ls -t /backup | head -n1)
cp- Copy (cp <file-to-copy> <where-to-copy>)- In the
<file-to-copy>spot, we don't know what the name of the file will be because it's random with every backup, but we do know it's in the/backupfolder. So we do ls -t- List the files by time|Pass the result to the next commandhead -n1Only get the first result, which would be the most recent one if they're sorted by time.- When we put that together it's the same as
cp /backup/<most-recent-file> ~/temp_nas
- In the
sleep 5
- Just wait a few more seconds. The
&&should mean that the next command only runs after the one before it is done, but I like to play it safe
sudo umount ~/temp_nas
- Unmount the shared folder so it doesn't get in our way next time. And because it doesn't need to be there if we're not using it anymore
rm -rf ~/temp_nas
- remove the temp folder we created
exit
- Exit the container.
Save the configuration.yml file
Restart Home Assistant. Don't just reload the yaml, make sure to do an actual restart.
Automating the backup
In Home Assistant go to Settings > Automations & Scenes > Scripts
Click 'Add Script'
Give the script a name. Mine is just Backup to TrueNAS
Click the 'Add Action' button and select Home Assistant Supervisor: Create a full backup
Add another action and select Shell Command: nas_backup
Save
Go back and go to the Automations tab
Create a new automation
Set the Trigger to "Time" and set a time you want the backup to happen. I'm choosing 04:00:00 so it runs at 4am every day.
Add an action and choose script.backup_to_nas
Save
Now every day at 4:00am there should be a new backup in my TrueNAS dataset.
Apparently this is not persisting through Home Assistant updates. I'm pretty sure I had this working at some point, but anyway...
After an update:
- Open the web terminal
docker exec -it homeassistant bashssh-keygen -t rsa -C "keys-for-backup"mkdir -p /config/temp && cp ~/.ssh/id_rsa.pub /config/temp/id_rsa.pubssh hassio@a0d7b954-ssh- Type
yes - Open File Editor, copy the new key to the SSH plugin config and save/restart the plugin
Having to do this is obviously not ideal, but I'll figure out how I had it working and either update this or make a follow up on it.