diff --git a/custom_components/auto_backup/__init__.py b/custom_components/auto_backup/__init__.py index ab8628f..0e15488 100644 --- a/custom_components/auto_backup/__init__.py +++ b/custom_components/auto_backup/__init__.py @@ -37,6 +37,7 @@ DEFAULT_BACKUP_TIMEOUT, DATA_AUTO_BACKUP, DOMAIN, + ATTR_ENCRYPTED, ) from .handlers import SupervisorHandler, BackupHandler from .helpers import is_backup @@ -53,7 +54,8 @@ vol.Optional(ATTR_PASSWORD): vol.Any(None, cv.string), vol.Optional(ATTR_KEEP_DAYS): vol.Any(None, vol.Coerce(float)), vol.Optional(ATTR_DOWNLOAD_PATH): vol.All(cv.ensure_list, [cv.isdir]), - vol.Optional(ATTR_COMPRESSED): cv.boolean, + vol.Optional(ATTR_ENCRYPTED, default=False): cv.boolean, + vol.Optional(ATTR_COMPRESSED, default=True): cv.boolean, vol.Optional(ATTR_LOCATION): vol.All( cv.string, lambda v: None if v == "/backup" else v ), diff --git a/custom_components/auto_backup/const.py b/custom_components/auto_backup/const.py index 9a3eb29..2f373b2 100644 --- a/custom_components/auto_backup/const.py +++ b/custom_components/auto_backup/const.py @@ -35,6 +35,7 @@ ATTR_EXCLUDE_FOLDERS = "exclude_folders" ATTR_DOWNLOAD_PATH = "download_path" ATTR_COMPRESSED = "compressed" +ATTR_ENCRYPTED = "encrypted" ATTR_LOCATION = "location" ATTR_LAST_FAILURE = "last_failure" diff --git a/custom_components/auto_backup/manager.py b/custom_components/auto_backup/manager.py index a104df7..1691eb2 100644 --- a/custom_components/auto_backup/manager.py +++ b/custom_components/auto_backup/manager.py @@ -4,6 +4,7 @@ from os.path import join, isfile from typing import List, Dict, Tuple, Optional +from homeassistant.components.backup.manager import DATA_MANAGER from homeassistant.components.hassio import ( ATTR_FOLDERS, ATTR_ADDONS, @@ -34,6 +35,7 @@ ATTR_EXCLUDE, ATTR_KEEP_DAYS, ATTR_DOWNLOAD_PATH, + ATTR_ENCRYPTED, ) from .handlers import HassioAPIError, HandlerBase @@ -44,6 +46,7 @@ class AutoBackup: def __init__(self, hass: HomeAssistant, options: Dict, handler: HandlerBase): self._hass = hass self._handler = handler + self._manager = hass.data[DATA_MANAGER] self._auto_purge = options[CONF_AUTO_PURGE] self._backup_timeout = options[CONF_BACKUP_TIMEOUT] * 60 self._state = 0 @@ -217,6 +220,17 @@ async def _async_create_backup(self, data: Dict, partial: bool = False): keep_days = data.pop(ATTR_KEEP_DAYS, None) download_paths: Optional[List[str]] = data.pop(ATTR_DOWNLOAD_PATH, None) + # support default encryption key + if ( + not data.get(ATTR_PASSWORD, "") + and data.get(ATTR_ENCRYPTED) + and self._manager + ): + data[ATTR_PASSWORD] = self._manager.config.data.create_backup.password + del data[ATTR_ENCRYPTED] + elif ATTR_ENCRYPTED in data: + del data[ATTR_ENCRYPTED] + ### LOG DEBUG INFO ### # ensure password is scrubbed from logs password = data.get(ATTR_PASSWORD) diff --git a/custom_components/auto_backup/services.yaml b/custom_components/auto_backup/services.yaml index 7d8bfe3..f8841c6 100644 --- a/custom_components/auto_backup/services.yaml +++ b/custom_components/auto_backup/services.yaml @@ -60,9 +60,17 @@ backup: value: media - label: Local Add-ons value: addons + encrypted: &encrypted + name: Encrypted + description: | + Encrypt backups with the default encryption key found in backup settings, + if encrypted is false and password is not set backups will be unencrypted. + default: false + selector: + boolean: password: &password name: Password - description: Optional password to secure backup. + description: Optional custom password to encrypt the backup with. example: "1234" selector: text: @@ -113,6 +121,7 @@ backup_full: default: { "addons": ["MariaDB"], "folders": ["Local add-ons", "share"] } selector: object: + encrypted: *encrypted password: *password keep_days: *keep_days location: *location @@ -150,6 +159,7 @@ backup_partial: value: media - label: Local Add-ons value: addons + encrypted: *encrypted password: *password keep_days: *keep_days location: *location diff --git a/docs/index.md b/docs/index.md index 421875b..6ae5da6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,7 @@ Auto Backup is an Improved Backup Service for Home Assistant that can Automatica - [x] Provides a [sensor](sensors.md) to monitor the status of your backups. - [x] Creates [events](events.md) for when backups are started/created/failed/deleted. - [x] Supports [generational backup](advanced-examples.md#generational-backups) schemes. -- [x] Supports unencrypted and encrypted backups, including the default encryption added in 2025.1 see [#181](https://github.com/jcwillox/hass-auto-backup/issues/181). +- [x] Supports unencrypted and [encrypted](services.md#encryption) backups, including the default encryption added in 2025.1. ## Blueprints diff --git a/docs/services.md b/docs/services.md index 0fb0d3d..0ac173d 100644 --- a/docs/services.md +++ b/docs/services.md @@ -8,18 +8,19 @@ Create a full or partial backup. This is the primary method and includes the functionality of the `backup_full` and `backup_partial` services. -| Parameter | Description | Type | Example | -| -------------------------------------------- | ---------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------- | -| `name` | Optional name, defaults to the current date and time. | `string` | `#!jinja Automatic Backup {{ now().strftime('%Y-%m-%d') }}` | -| [`include_addons`](#addon-and-folder-names) | List of addons to include in the backup (name or slug). Wildcards supported for slugs. | `list` | `#!json ["Almond", "glances", "core_mariadb", "core_*"]` | -| [`include_folders`](#addon-and-folder-names) | List of folders to include in the backup. | `list` | `#!json ["Local add-ons", "homeassistant", "share"]` | -| [`exclude_addons`](#addon-and-folder-names) | List of addons to exclude from the backup (name or slug). Wildcards supported for slugs. | `list` | `#!json ["Almond", "glances", "core_mariadb", "core_*"]` | -| [`exclude_folders`](#addon-and-folder-names) | List of folders to exclude from the backup. | `list` | `#!json ["Local add-ons", "homeassistant", "share"]` | -| `password` | Optional password to secure backup. | `string` | `#!json 1234` | -| [`keep_days`](#keep-days) | The number of days to keep the backup. | `float` | `#!json 2` | -| [`location`](#custom-locations) | Name of a backup network storage to put backup (or /backup) | `string` | `#!json my_backup_mount` | -| [`download_path`](#download-path) | Locations to download the backup to after creation. | `list` | `#!json ["/usb_drive"]` | -| `compressed` | Use compressed archives (default: true) | `bool` | `#!json true` | +| Parameter | Description | Type | Example | +| -------------------------------------------- | ----------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------- | +| `name` | Optional name, defaults to the current date and time. | `string` | `#!jinja Automatic Backup {{ now().strftime('%Y-%m-%d') }}` | +| [`include_addons`](#addon-and-folder-names) | List of addons to include in the backup (name or slug). Wildcards supported for slugs. | `list` | `#!json ["Almond", "glances", "core_mariadb", "core_*"]` | +| [`include_folders`](#addon-and-folder-names) | List of folders to include in the backup. | `list` | `#!json ["Local add-ons", "homeassistant", "share"]` | +| [`exclude_addons`](#addon-and-folder-names) | List of addons to exclude from the backup (name or slug). Wildcards supported for slugs. | `list` | `#!json ["Almond", "glances", "core_mariadb", "core_*"]` | +| [`exclude_folders`](#addon-and-folder-names) | List of folders to exclude from the backup. | `list` | `#!json ["Local add-ons", "homeassistant", "share"]` | +| `encrypted` | Encrypt backups with the default encryption key found in backup settings (default: false) | `bool` | `#!json true` | +| `password` | Optional custom password to encrypt the backup with. | `string` | `#!json 1234` | +| [`keep_days`](#keep-days) | The number of days to keep the backup. | `float` | `#!json 2` | +| [`location`](#custom-locations) | Name of a backup network storage to put backup (or /backup) | `string` | `#!json my_backup_mount` | +| [`download_path`](#download-path) | Locations to download the backup to after creation. | `list` | `#!json ["/usb_drive"]` | +| `compressed` | Use compressed archives (default: true) | `bool` | `#!json true` | ??? example "Create a full backup" @@ -73,16 +74,22 @@ This is the primary method and includes the functionality of the `backup_full` a **Folder names** are also case-insensitive and use the names seen when creating a partial backup through the Supervisor backups page. Currently, accepted values are (ignoring case): -- `ssl` -- `share` -- `media` -- `addons` or `local add-ons` or `addons/local` -- `config` or `home assistant configuration` or `homeassistant` +- `ssl` +- `share` +- `media` +- `addons` or `local add-ons` or `addons/local` +- `config` or `home assistant configuration` or `homeassistant` ### Keep Days The `keep_days` parameter allows you to specify how long the backup should be kept for before being deleted. Default is forever. You can specify a float value for keep days, e.g. to keep a backup for 12 hours use `0.5`. +### Encryption + +By default, all backups created by Auto Backup are **unencrypted**, if you want to create **encrypted** backups you can set the `encrypted` parameter to `true`. If you want to use a custom password for encryption you can set the `password` parameter to the desired password. If you do not specify a password, the default encryption key added in Home Assistant [2025.1](https://www.home-assistant.io/blog/2025/01/03/release-20251/#encrypted-backups-by-default-) will be used. It can be found in **Settings** → **System** → **Backups** → **Backup Settings** → **Configure Backup Settings** → **Encryption key**. + +Do note that you have to go through Home Assistant's "Set up backups" flow to view the key, you likely do not want to use their automatic backups if you are using this integration so when it asks you to "Set up automatic backups" select "Custom", then disable "Enable automatic backups" and click "Next", if you have already set up automatic backups you can disable them on the backup settings page. + ### Custom Locations Home Assistant [2023.6](https://www.home-assistant.io/blog/2023/06/07/release-20236/#connect-and-use-your-existing-network-storage) included support for adding custom backup locations, and even changing the default backup location. Auto Backup supports specifying an alternative location using the `location` option. Additional backup locations can be added by navigating to **Settings** → **System** → **Storage**, and clicking the **Add network storage** button. @@ -109,15 +116,16 @@ The `download_path` parameter allows you to specify a location or of list of loc Create a full backup with optional exclusions. -| Parameter | Description | Type | Example | -| --------------------------------- | ----------------------------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -| `name` | Optional name, defaults to the current date and time. | `string` | `#!jinja Automatic Backup {{ now().strftime('%Y-%m-%d') }}` | -| `exclude` | Addons/Folders to exclude from the backup. | [`Exclude Object`](#exclude-object) | [`#!json {"addons": ["MariaDB"], "folders": ["Local add-ons", "share"]}`](examples.md#excluding-addonsfolders-from-a-backup) | -| `password` | Optional password to secure backup. | `string` | `#!json 1234` | -| [`keep_days`](#keep-days) | The number of days to keep the backup. | `float` | `#!json 2` | -| [`location`](#custom-locations) | Name of a backup network storage to put backup (or /backup) | `string` | `#!json my_backup_mount` | -| [`download_path`](#download-path) | Locations to download the backup to after creation. | `list` | `#!json ["/usb_drive"]` | -| `compressed` | Use compressed archives (default: true) | `bool` | `#!json true` | +| Parameter | Description | Type | Example | +| --------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `name` | Optional name, defaults to the current date and time. | `string` | `#!jinja Automatic Backup {{ now().strftime('%Y-%m-%d') }}` | +| `exclude` | Addons/Folders to exclude from the backup. | [`Exclude Object`](#exclude-object) | [`#!json {"addons": ["MariaDB"], "folders": ["Local add-ons", "share"]}`](examples.md#excluding-addonsfolders-from-a-backup) | +| `encrypted` | Encrypt backups with the default encryption key found in backup settings (default: false) | `bool` | `#!json true` | +| `password` | Optional custom password to encrypt the backup with. | `string` | `#!json 1234` | +| [`keep_days`](#keep-days) | The number of days to keep the backup. | `float` | `#!json 2` | +| [`location`](#custom-locations) | Name of a backup network storage to put backup (or /backup) | `string` | `#!json my_backup_mount` | +| [`download_path`](#download-path) | Locations to download the backup to after creation. | `list` | `#!json ["/usb_drive"]` | +| `compressed` | Use compressed archives (default: true) | `bool` | `#!json true` | #### Exclude Object @@ -130,16 +138,17 @@ Create a full backup with optional exclusions. Create a partial backup. -| Parameter | Description | Type | Example | -| ------------------------------------ | ----------------------------------------------------------- | -------- | ----------------------------------------------------------- | -| `name` | Optional name, defaults to the current date and time. | `string` | `#!jinja Automatic Backup {{ now().strftime('%Y-%m-%d') }}` | -| [`addons`](#addon-and-folder-names) | List of addons to backup (name or slug). | `list` | `#!json ["Almond", "glances", "core_mariadb"]` | -| [`folders`](#addon-and-folder-names) | List of folders to backup. | `list` | `#!json ["Local add-ons", "homeassistant", "share"]` | -| `password` | Optional password to secure backup. | `string` | `#!json 1234` | -| [`keep_days`](#keep-days) | The number of days to keep the backup. | `float` | `#!json 2` | -| [`location`](#custom-locations) | Name of a backup network storage to put backup (or /backup) | `string` | `#!json my_backup_mount` | -| [`download_path`](#download-path) | Locations to download the backup to after creation. | `list` | `#!json ["/usb_drive"]` | -| `compressed` | Use compressed archives (default: true) | `bool` | `#!json true` | +| Parameter | Description | Type | Example | +| ------------------------------------ | ----------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------- | +| `name` | Optional name, defaults to the current date and time. | `string` | `#!jinja Automatic Backup {{ now().strftime('%Y-%m-%d') }}` | +| [`addons`](#addon-and-folder-names) | List of addons to backup (name or slug). | `list` | `#!json ["Almond", "glances", "core_mariadb"]` | +| [`folders`](#addon-and-folder-names) | List of folders to backup. | `list` | `#!json ["Local add-ons", "homeassistant", "share"]` | +| `encrypted` | Encrypt backups with the default encryption key found in backup settings (default: false) | `bool` | `#!json true` | +| `password` | Optional custom password to encrypt the backup with. | `string` | `#!json 1234` | +| [`keep_days`](#keep-days) | The number of days to keep the backup. | `float` | `#!json 2` | +| [`location`](#custom-locations) | Name of a backup network storage to put backup (or /backup) | `string` | `#!json my_backup_mount` | +| [`download_path`](#download-path) | Locations to download the backup to after creation. | `list` | `#!json ["/usb_drive"]` | +| `compressed` | Use compressed archives (default: true) | `bool` | `#!json true` | ## `auto_backup.purge`