This is the type of question you should search before posting, as it has nothing to do with Docker. But yes, the database is definitely part of the backup.
I agree with the idea, but haven’t researched if it’s possible or even less - exactly how to do it.
unfortunately, it doesn’t seem to work here, I don’t really get why it complains about zha_gateway. And on the other hand, I migrated the database from sqlite to pgsql, which I’m already backing up. Perhaps I should do just a rclone/rsync task for the data directory.
homeassistant | 2024-01-19 00:55:00.144 ERROR (MainThread) [homeassistant.components.automation.backup_create_backup] While executing automation automation.backup_create_backup
homeassistant | Traceback (most recent call last):
homeassistant | File "/usr/src/homeassistant/homeassistant/components/automation/__init__.py", line 669, in async_trigger
homeassistant | await self.action_script.async_run(
homeassistant | File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1587, in async_run
homeassistant | return await asyncio.shield(run.async_run())
homeassistant | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
homeassistant | File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 426, in async_run
homeassistant | await self._async_step(log_exceptions=False)
homeassistant | File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 479, in _async_step
homeassistant | self._handle_exception(
homeassistant | File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 502, in _handle_exception
homeassistant | raise exception
homeassistant | File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 476, in _async_step
homeassistant | await getattr(self, handler)()
homeassistant | File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 713, in _async_call_service_step
homeassistant | response_data = await self._async_run_long_action(
homeassistant | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
homeassistant | File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 675, in _async_run_long_action
homeassistant | return long_task.result()
homeassistant | ^^^^^^^^^^^^^^^^^^
homeassistant | File "/usr/src/homeassistant/homeassistant/core.py", line 2149, in async_call
homeassistant | response_data = await coro
homeassistant | ^^^^^^^^^^
homeassistant | File "/usr/src/homeassistant/homeassistant/core.py", line 2186, in _execute_service
homeassistant | return await target(service_call)
homeassistant | ^^^^^^^^^^^^^^^^^^^^^^^^^^
homeassistant | File "/usr/src/homeassistant/homeassistant/components/backup/__init__.py", line 29, in async_handle_create_service
homeassistant | await backup_manager.generate_backup()
homeassistant | File "/usr/src/homeassistant/homeassistant/components/backup/manager.py", line 176, in generate_backup
homeassistant | raise result
homeassistant | File "/usr/src/homeassistant/homeassistant/components/zha/backup.py", line 15, in async_pre_backup
homeassistant | zha_gateway = get_zha_gateway(hass)
homeassistant | ^^^^^^^^^^^^^^^^^^^^^
homeassistant | File "/usr/src/homeassistant/homeassistant/components/zha/core/helpers.py", line 459, in get_zha_gateway
homeassistant | raise ValueError("No gateway object exists")
homeassistant | ValueError: No gateway object exists
One more strategy:
I am using git as backup. It is a bit fiddly with the permissions, but I have a script which can be run as root.I have it run by a cron job a few times a day:
#!/bin/bash
cd <path to installation>
chmod -R a+r .
sudo -i -u <username> bash << EOF
cd <path to installation>
git add .
git commit -m "[BACKUP `date +'%Y-%m-%d %T'`]"
git push
EOF
Git makes it really easy to track changes or to revert only some part of the configuration. There are also great free online services to host your repository
I am also using MariaDB and I have another machine replicate it continuously. Then on that other machine I make a backup every night with something like:
mysqldump -u <username> -p ha | lbzip2 -9czq > backup.bz2
Hi… Is there a way to add an action that wait for the backup to wait and then call the script directly from HA? I know how to call the script, but not sure on how to start it after the backup end… Maybe a waiting template?
You already use an action to create the backup. You could change the trigger (or add a new one) to be a webhook, which you can easily call from your local script with curl.
Here is what I have implemented using some information provided here:
- Trigger the backups with a cronjob executing one script:
0 4 1/10 * * cd /usr/local/home_assistant && /bin/bash /usr/local/home_assistant/generate_backup.sh >> /var/log/home_assistant_backup.log 2>&1
- I use an external postgres database to generate the backups which I have to backup separately.
- The HA config is backed up with an automation which is triggered by a webhook which is called by the script.
- In order to know that the backup is done I use the logs of HA.
- Finally I use rclone to send the backups to a local nexcloud server.
Example of the automation:
- alias: "Backup: Create backup hook"
description: ""
trigger:
- platform: webhook
allowed_methods:
- POST
local_only: true
webhook_id: backup-create-backup-<put here some random characters as pseudopassword>
condition: []
action:
- action: system_log.write
metadata: {}
data:
level: warning
message: Creating backup...
- data: {}
action: backup.create
- action: system_log.write
metadata: {}
data:
level: warning
message: >
Backup created for date: {{ as_timestamp(now()) |
timestamp_custom('%Y-%m-%d') }}
mode: single
The script that creates the backups:
#!/bin/bash
##########
# CONFIG
# This has to be configured in an automation
BACKUP_HOOK=http://localhost:<port>/api/webhook/backup-create-backup-<my_hook_secret>
# Configure the backups folder inside your config
HA_BACKUP_FOLDER=./config/backups
# Configuration of rclone
RCLONE_CONFIG_FOLDER=./rclone_config
# Confgure where to store locally the database backups
DATABASE_BACKUP_FOLDER=./backup_database
# Configure the maximum time the script waits for the backup to complete
WAITING_TIME=120
# rclone path where the backups will be sent
REMOTE_BACKUP_FOLDER=nextcloud:/00_backups/05_home_assistant
##########
# START HA BACKUP
DATE_STRING=$(date +%Y-%m-%d)
echo "Deleting old backups..."
if [ -z ${HA_BACKUP_FOLDER+x} ]; then echo "HA_BACKUP_FOLDER is not set" && exit 1; fi
rm ${HA_BACKUP_FOLDER}/*.tar
echo "Sending generate backup to backup hook..."
# Data is not relevant, just a post request
curl -vvv -d '{"data":"create_backup"}' -H "Content-Type: application/json" -X POST ${BACKUP_HOOK}
echo "Waiting for the backup to be generated..."
attempt=1
until /usr/local/bin/docker-compose logs --tail 20 | grep -q "Backup created for date: ${DATE_STRING}"; do
if [ "$attempt" -ge "$WAITING_TIME" ]; then
echo "Timeout reached after $WAITING_TIME attempts."
exit 1
fi
attempt=$((attempt + 1))
sleep 1
done
echo "Renaming generated backup..."
mv "$(ls -t ${HA_BACKUP_FOLDER}/*.tar | head -n 1)" "${HA_BACKUP_FOLDER}/ha-backup-${DATE_STRING}.tar"
echo "Sending backup to backup server..."
/usr/bin/docker run --rm \
--volume ${RCLONE_CONFIG_FOLDER}:/config/rclone \
--volume ${HA_BACKUP_FOLDER}:/data \
rclone/rclone \
copy /data ${REMOTE_BACKUP_FOLDER} \
--no-check-certificate
echo "Config backup done for ${DATE_STRING}"
##########
# START HA DATABASE BACKUP
echo Starting database backup...
mkdir -p ${DATABASE_BACKUP_FOLDER}
echo "Deleting old database backups..."
if [ -z ${HA_BACKUP_FOLDER+x} ]; then echo "HA_BACKUP_FOLDER is not set" && exit 1; fi
rm ${DATABASE_BACKUP_FOLDER}/*.sql.gz
echo "Generating database backup..."
/usr/bin/docker exec homeassistant_db /bin/bash \
-c "/usr/bin/pg_dump -U postgres homeassistant_db" |
gzip -9 >${DATABASE_BACKUP_FOLDER}/homeassistant_db-${DATE_STRING}.sql.gz
echo "Sending backup to backup server..."
/usr/bin/docker run --rm \
--volume ${RCLONE_CONFIG_FOLDER}:/config/rclone \
--volume ${DATABASE_BACKUP_FOLDER}:/data \
rclone/rclone \
copy /data ${REMOTE_BACKUP_FOLDER} \
--no-check-certificate
echo "Database backup done for ${DATE_STRING}"