1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-04-02 08:12:47 +01:00
Commit Graph

79 Commits

Author SHA1 Message Date
Stefan Agner
e630ec1ac4 Include Docker registry configurations in backups (#6674)
* Include Docker registry configurations in backups

Docker registry credentials were removed from backup metadata in a prior
change to avoid exposing secrets in unencrypted data. Now that the encrypted
supervisor.tar inner archive exists, add docker.json alongside mounts.json
to securely backup and restore registry configurations.

On restore, registries from the backup are merged with any existing ones.
Old backups without docker.json are handled gracefully.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Increase test coverage by testing more error paths

* Address review feedback for Docker registry backup

Remove unnecessary dict() copy when serializing registries for backup
since the property already returns a dict.

Change DockerConfig.registries to use direct key access instead of
.get() with a default. The schema guarantees the key exists, and
.get() with a default would return a detached temporary dict that
silently discards updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:34:27 +02:00
Paul Tarjan
2b9c8282a4 Include network storage mount configurations in backups (#6411)
* Include network storage mount configurations in backups

When creating backups, now stores mount configurations (CIFS/NFS shares)
including server, share, credentials, and other settings. When restoring
from a backup, mount configurations are automatically restored.

This fixes the issue where network storage definitions for backups
were lost after restoring from a backup, requiring users to manually
reconfigure their network storage mounts.

Changes:
- Add ATTR_MOUNTS schema to backup validation
- Add store_mounts() method to save mount configs during backup
- Add restore_mounts() method to restore mount configs during restore
- Add MOUNTS stage to backup/restore job stages
- Update BackupManager to call mount backup/restore methods
- Add tests for mount backup/restore functionality

Fixes home-assistant/core#148663

* Address reviewer feedback for mount backup/restore

Changes based on PR review:
- Store mount configs in encrypted mounts.tar instead of unencrypted
  backup metadata (security fix for passwords)
- Separate mount restore into config save + async activation tasks
  (mounts activate in background, failures don't block restore)
- Add replace_default_backup_mount parameter to control whether to
  overwrite existing default mount setting
- Remove unnecessary broad exception handler for default mount setter
- Simplify schema: ATTR_MOUNTS is now just a boolean flag since
  actual data is in the encrypted tar file
- Update tests to reflect new async API and return types

* Fix code review issues in mount backup/restore

- Add bind mount handling for MEDIA and SHARE usage types in
  _activate_restored_mount() to mirror MountManager.create_mount()
- Fix double save_data() call by using needs_save flag
- Import MountUsage const for usage type checks

* Add pylint disable comments for protected member access

* Tighten broad exception handlers in mount backup restore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address second round of reviewer feedback

- Catch OSError separately and check errno.EBADMSG for drive health
- Validate mounts JSON against SCHEMA_MOUNTS_CONFIG before importing
- Use mount_data[ATTR_NAME] instead of .get("name", "unknown")
- Overwrite existing mounts on restore instead of skipping
- Move restore_mount/activate logic to MountManager (no more
  protected-access in Backup)
- Drop unused replace_default_backup_mount parameter
- Fix test_backup_progress: add mounts stage to expected events
- Fix test_store_mounts: avoid create_mount which requires dbus

* Rename mounts.tar to supervisor.tar for generic supervisor config

Rename the inner tar from mounts.tar to supervisor.tar so it can hold
multiple config files (mounts.json now, docker credentials later).
Rename store_mounts/restore_mounts to store_supervisor_config/
restore_supervisor_config and update stage names accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix pylint protected-access and test timeouts in backup tests

- Add pylint disable comment for _mounts protected access in test_backup.py
- Mock restore_supervisor_config in test_full_backup_to_mount and
  test_partial_backup_to_mount to avoid D-Bus mount activation during
  restore that causes timeouts in the test environment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address agners review feedback

- Change create_inner_tar() to create_tar() per #6575
- Remove "r" argument from SecureTarFile (now read-only by default)
- Change warning to info for missing mounts tar (old backups won't have it)
- Narrow exception handler to (MountError, vol.Invalid, KeyError, OSError)

* Update supervisor/backups/backup.py

* Address agners feedback: remove metadata flag, add mount feature check

- Remove ATTR_SUPERVISOR boolean flag from backup metadata; instead
  check for physical presence of supervisor.tar (like folder backups)
- Remove has_supervisor_config property
- Always attempt supervisor config restore (tar existence check handles it)
- Add HostFeature.MOUNT check in _activate_restored_mount before
  attempting to activate mounts on systems without mount support

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2026-03-26 17:08:16 -04:00
Stefan Agner
31c2fcf377 Treat empty string password as None in backup restore (#6618)
* Treat empty string password as None in backup restore

Work around a securetar 2026.2.0 bug where an empty string password
sets encrypted=True but fails to derive a key, leading to an
AttributeError on restore. This also restores consistency with backup
creation which uses a truthiness check to skip encryption for empty
passwords.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Explicitly mention that "" is treated as no password

* Add tests for empty string password handling in backups

Verify that empty string password is treated as no password on both
backup creation (not marked as protected) and restore (normalized to
None in set_password).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Improve comment

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 09:53:43 +01:00
Stefan Agner
3de2deaf02 Bump securetar to 2026.2.0 (#6575)
* Bump securetar from 2025.12.0 to 2026.2.0

Adapt to the new securetar API:
- Use SecureTarArchive for outer backup tar (replaces SecureTarFile
  with gzip=False for the outer container)
- create_inner_tar() renamed to create_tar(), password now inherited
  from the archive rather than passed per inner tar
- SecureTarFile no longer accepts a mode parameter (read-only by
  default, InnerSecureTarFile for writing)
- Pass create_version=2 to keep protected backups at version 2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Reformat imports

* Rename _create_cleanup to _create_finalize and update docstring

* Use constant for SecureTar create version

* Add test for SecureTarReadError in validate_backup

securetar >= 2026.2.0 raises SecureTarReadError instead of
tarfile.ReadError for invalid passwords. Catching this exception
and raising BackupInvalidError is required so Core shows the
encryption key dialog to the user.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Handle InvalidPasswordError for v3 backups

* Address typos

* Add securetar v3 encrypted password test fixture

Add a test fixture for a securetar v3 encrypted backup with password.
This will be used in the test suite to verify that the backup
extraction process correctly handles encrypted backups.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:08:14 +01:00
Stefan Agner
6070d54860 Harden backup tar extraction with Python tar_filter (#6559)
* Harden backup tar extraction with Python data filter

Replace filter="fully_trusted" with a custom backup_data_filter that
wraps tarfile.data_filter. This adds protection against symlink attacks
(absolute targets, destination escapes), device node injection, and
path traversal, while resetting uid/gid and sanitizing permissions.

Unlike using data_filter directly, the custom filter skips problematic
entries with a warning instead of aborting the entire extraction. This
ensures existing backups containing absolute symlinks (e.g. in shared
folders) still restore successfully with the dangerous entries omitted.

Also removes the now-redundant secure_path member filtering, as
data_filter is a strict superset of its protections. Fixes a standalone
bug in _folder_restore which had no member filtering at all.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Simplify security tests to test backup_data_filter directly

Test the public backup_data_filter function with plain tarfile
extraction instead of going through Backup internals. Removes
protected-access pylint warnings and unnecessary coresys setup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Switch to tar filter instead of custom data filter wrapper

Replace backup_data_filter (which wrapped data_filter and skipped
problematic entries) with the built-in tar filter. The tar filter
rejects path traversal and absolute names while preserving uid/gid
and file permissions, which is important for add-ons running as
non-root users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Use BackupInvalidError instead of BackupError for tarfile.TarError

Make sure FilterErrors lead to BackupInvalidError instead of BackupError,
as they are not related to the backup process itself but rather to the
integrity of the backup data.

* Improve test coverage and use pytest.raises

* Only make FilterError a BackupInvalidError

* Add test case for FilterError during Home Assistant Core restore

* Add test cases for Add-ons

* Fix pylint warnings

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
2026-02-23 10:09:19 +01:00
Mike Degatano
a122b5f1e9 Migrate info, events and container logs to aiodocker (#6514)
* Migrate info and events to aiodocker

* Migrate container logs to aiodocker

* Fix dns plugin loop test

* Fix mocking for docker info

* Fixes from feedback

* Harden monitor error handling

* Deleted failing tests because they were not useful
2026-02-03 18:36:41 +01:00
Mike Degatano
909a2dda2f Migrate (almost) all docker container interactions to aiodocker (#6489)
* Migrate all docker container interactions to aiodocker

* Remove containers_legacy since its no longer used

* Add back remove color logic

* Revert accidental invert of conditional in setup_network

* Fix typos found by copilot

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Revert "Apply suggestions from code review"

This reverts commit 0a475433ea.

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-27 12:42:17 +01:00
Mike Degatano
64f94a159c Add progress syncing from child jobs (#6207)
* Add progress syncing from child jobs

* Fix pylint issue

* Set initial progress from parent and end at 100
2025-09-30 14:52:16 -04:00
Mike Degatano
207b665e1d Send progress updates during image pull for install/update (#6102)
* Send progress updates during image pull for install/update

* Add extra to tests about job APIs

* Sent out of date progress to sentry and combine done event

* Pulling container image layer
2025-08-22 10:41:10 +02:00
Mike Degatano
033896480d Fix backup equal and add hash to objects with eq (#6059)
* Fix backup equal and add hash to objects with eq

* Add test for failed consolidate
2025-08-04 14:19:33 +02:00
Mike Degatano
ae036ceffe Don't backup uninstalled addons (#5988)
* Don't backup uninstalled addons

* Remove hash in backup
2025-07-04 07:05:53 +02:00
Stefan Agner
d0d11db7b1 Harmonize folder and add-on backup error handling (#5885)
* Harmonize folder and add-on backup error handling

Align add-on and folder backup error handling in that in both cases
errors are recorded on the respective backup Jobs, but not raised to
the caller. This allows the backup to complete successfully even if
some add-ons or folders fail to back up.

Along with this, also record errors in the per-add-on and per-folder
backup jobs, as well as the add-on and folder root job.

And finally, align the exception handling to only catch expected
exceptions for add-ons too.

* Fix pytest
2025-05-15 10:14:35 +02:00
Stefan Agner
c855eaab52 Delete Backup files on error (#5880) 2025-05-13 20:51:16 +02:00
Stefan Agner
b9bbb99f37 Fix pytests to make them run in isolation (#5878) 2025-05-12 12:37:09 +02:00
Stefan Agner
c1b45406d6 Improve backup upload location determination (#5848)
* Improve backup upload location determination

For local backup upload locations, check if the location is on the same
file system an thuse allows to move the backup file after upload. This
allows custom backup mounts. Currently there is no documented,
persistent way to create such mounts in with Home Assistant OS
installations, but since we might add local mounts in the future this
seems a worthwhile addition.

Fixes: #5837

* Fix pytests
2025-04-29 16:14:20 +02:00
Mike Degatano
01a682cfaa Fix mypy issues in backups and dbus (#5792)
* Fix mypy issues in backups module

* Fix mypy issues in dbus module

* Fix mypy issues in api after rebase

* TypedDict to dataclass and other small fixes

* Finish fixing mypy errors in dbus

* local_where must exist

* Fix references to name in tests
2025-03-31 17:03:54 -04:00
Mike Degatano
9222a3c9c0 Report stage with error in jobs (#5784)
* Report stage with error in jobs

* Copy doesn't lose track of the successful copies

* Add stage to errors in api output test

* revert unneessary change to import

* Add tests for a bit more coverage of copy_additional_locations
2025-03-27 10:07:06 -04:00
Mike Degatano
5facf4e790 Fix logging error for invalid password for backup (#5747)
* Fix logging error for invalid password for backup

* Improved test
2025-03-12 15:21:10 -04:00
Mike Degatano
e1c9c8b786 Finish out effort of adding and enabling blockbuster in tests (#5735)
* Finish out effort of adding and enabling blockbuster

* Skip getting addon file size until securetar fixed

* Fix test for devcontainer and blocking I/O

* Fix docker fixture and load_config to post_init
2025-03-07 13:29:24 +01:00
Mike Degatano
324b059970 Move write of core state to executor (#5720) 2025-03-04 17:49:53 +01:00
Mike Degatano
31193abb7b FileConfiguration uses executor for I/O (#5652)
* FileConfiguration uses executor for I/O

* Fix credentials tests

* Remove migrate_system_env as its very deprecated
2025-02-26 19:11:11 +01:00
Stefan Agner
ce8b107f1e Handle OS errors on backup create (#5662)
* Handle permission error on backup create

Make sure we handle (write) permission errors when creating a backup.

* Introduce BackupFileExistError and BackupPermissionError exceptions

* Make error messages a bit more uniform

* Drop use of exclusive mode

SecureTar does not handle exclusive mode nicely. Drop use of it for now.
2025-02-24 21:34:23 +01:00
Stefan Agner
34939cfe52 Remove I/O in event loop for backup load, import and remove (#5647)
* Avoid IO in event loop when removing backup

* Refactor backup size calculation

Currently size is lazy loaded when required via properties. This
however is blocking the async event loop.

Backup sizes don't change. Instead of lazy loading the size of a backup
simply determine it on loading/after creation.

* Fix tests for backup size change

* Avoid IO in event loop when loading backups

* Avoid IO in event loop when importing a backup
2025-02-19 16:00:17 +01:00
Stefan Agner
4c108eea64 Always validate Backup before restoring (#5632)
* Validate Backup always before restoring

Since #5519 we check the encryption password early in restore case.
This has the side effect that we check the file existance early too.
However, in the non-encryption case, the file is not checked early.

This PR changes the behavior to always validate the backup file before
restoring, ensuring both encryption and non-encryption cases are
handled consistently.

In particular, the last case of test_restore_immediate_errors actually
validates that behavior. That test should actually have failed so far.
But it seems that because we validate the backup shortly after freeze
anyways, the exception still got raised early enough.

A simply `await asyncio.sleep(10)` right after the freeze makes the
test case fail. With this change, the test works consistently.

* Address pylint

* Fix backup_manager tests

* Drop warning message
2025-02-14 18:19:35 +01:00
Stefan Agner
d254937590 Drop Docker config from Supervisor backup (#5605)
* Drop Docker config from Supervisor backup

The Docker config is part of the main backup metadata. Because we
consolidate encrypted and unencrypted backups today, this leads to
potential bugs when restoring a backup.

* Drop obsolete encrypt/decrypt functions

* Drop unused Backup Job stage
2025-02-06 11:15:56 +01:00
Stefan Agner
58df65541c Handle non-existing file in Backup password check too (#5599)
* Handle non-existing file in Backup password check too

Make sure we handle a non-existing backup file also when validating
the password.

* Update supervisor/backups/manager.py

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>

* Add test case and fix password check when multiple locations

* Mock default backup unprotected by default

Instead of setting the protected property which we might not use
everywhere, simply mock the default backup to be unprotected.

* Fix mock of protected backup

* Introduce test for validate_password

Testing showed that validate_password doesn't return anything. Extend
tests to cover this case and fix the actual code.

---------

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2025-02-04 11:23:05 +01:00
Mike Degatano
7f39538231 Update cache if a backup file is missing (#5596)
* Update cache if a backup file is missing

* Remove references to single file reload
2025-02-03 13:46:57 +01:00
Stefan Agner
9491b1ff89 Avoid reordering add-on repositories on Backup load (#5595)
* Avoid reordering add-on repositories on Backup load

The `ensure_builtin_repositories` function uses a set to deduplicate
items, which sometimes led to a change of order in elements. This is
problematic when deduplicating Backups.

Simply avoid mangling the list of add-on repositories on load. Instead
rely on `update_repositories` which uses the same function to ensure
built-in repositories when loading the store configuration and restoring
a backup file.

* Update tests

* ruff format

* ruff check

* ruff check fixes

* ruff format

* Update tests/store/test_validate.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Simplify test

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-01-31 12:10:47 -05:00
Stefan Agner
30cbb039d0 Handle non-existing backup file (#5590)
* Make the API return 404 for non-existing backup files

* Introduce BackupFileNotFoundError exception

* Return 404 on full restore as well

* Fix remaining API tests

* Improve error handling in delete

* Fix pytest

* Fix tests and change error handling to agreed logic

---------

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2025-01-31 14:27:24 +01:00
Stefan Agner
690f1c07a7 Use version which is treated CalVer by AwesomeVersion (#5572)
* Use version which is treated CalVer by AwesomeVersion

The current dev version `99.9.9dev` is treated as unkown version type
by AwesomeVersion. This prevents the version from comparing with
actual Supervisor versions, e.g. from an exsiting backup file.

Make the development version a valid CalVer version so development
versions can handle non-development backups.

* Bump to year 9999
2025-01-24 09:59:50 +01:00
Mike Degatano
61a2101d8a Backup protected status can vary per location (#5569)
* Backup protected status can vary per location

* Fix test_backup_remove_error test

* Update supervisor/backups/backup.py

* Add Docker registry configuration to backup metadata

* Make use of backup location fixture

* Address pylint

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2025-01-23 15:05:35 -05:00
Stefan Agner
088832c253 Extend backup API with file name field (#5567)
* Extend backup API with file name field

Allow to specify a backup file name when creating a backup. This allows
for user friendly backup file names. If none is specified, the current
behavior remains (backup file name is the backup slug).

* Check passed file name using regex

* Use custom filename on download only if backup file name is backup slug

* ruff format

* Remove path from location for download file name
2025-01-23 15:24:47 +01:00
dependabot[bot]
463f196472 Bump securetar from 2024.11.0 to 2025.1.3 (#5553)
* Bump securetar from 2024.11.0 to 2025.1.3

Bumps [securetar](https://github.com/pvizeli/securetar) from 2024.11.0 to 2025.1.3.
- [Release notes](https://github.com/pvizeli/securetar/releases)
- [Commits](https://github.com/pvizeli/securetar/compare/2024.11.0...2025.1.3)

---
updated-dependencies:
- dependency-name: securetar
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Use file_filter and add test for addon backup_exclude

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2025-01-17 11:18:55 +01:00
Mike Degatano
0073227785 Add env on core restart due to restore (#5548)
* Add env on core restart due to restore

* Move is_restore to backup manager
2025-01-16 18:15:06 +01:00
Mike Degatano
600bf91c4f Sort jobs by creation in API (#5545)
* Sort jobs by creation in API

* Fix tests missing new field

* Fix sorting logic around child jobs
2025-01-16 09:51:44 +01:00
Stefan Agner
c2f6e319f2 Check password early on backup restore (#5519)
Introduce a validate password method which only peaks into the archive
to validate the password before starting the actual restore process.
This makes sure that a wrong password returns an error even when
restoring the backup in background.
2024-12-31 13:58:12 +01:00
Mike Degatano
de68868788 Restore backup from specific location (#5491) 2024-12-17 11:09:32 +01:00
Mike Degatano
02ceb713ea Add location to backup download and remove APIs (#5482) 2024-12-12 19:44:40 +01:00
Mike Degatano
6e32144e9a Fix and extend cloud backup support (#5464)
* Fix and extend cloud backup support

* Clean up task for cloud backup and remove by location

* Args to kwargs on backup methods

* Fix backup remove error test and typing clean up
2024-12-05 00:07:04 -05:00
Mike Degatano
11ca772ada Disable backup complete ws message (#5452) 2024-11-26 09:08:12 +01:00
Mike Degatano
42e704d563 Fix flaky backup test (#5453) 2024-11-26 00:47:00 +01:00
Mike Degatano
5519f6a53b Add support for cloud backups in Core (#5438)
* Add support for cloud backups in Core

* Test cases and small fixes identified

* Add test for partial reload no file failure
2024-11-21 18:14:20 -05:00
Mike Degatano
591b9a4d87 Stop backup if pre backup failed in Core (#5203)
* Stop backup if pre backup failed in Core

* Fix API tests

* Partial backup in ci since there's no Home assistant

* Add ssl folder to partial backup

* Allow backups when Home Assistant is not running

* Undo change to skip db test
2024-07-25 17:08:43 +02:00
Mike Degatano
c4452a85b4 Fix addon in wrong state after restore (#5111)
* Fix addon in wrong state after restore

* Do not stop docker monitor for a shutdown
2024-06-04 16:17:43 +02:00
J. Nick Koston
1f19f84edd Create backups files without having to copy inner tarballs (#4884)
* Create backups files without having to copy inner tarballs

needs https://github.com/pvizeli/securetar/pull/33

* fix writing json

* fix writing json

* fixes

* fixes

* ensure cleaned up

* need ./

* fix type

* Bump securetar to 2024.2.0

changelog: https://github.com/pvizeli/securetar/compare/2023.12.0...2024.2.0

* backup file is now created sooner

* reorder so comment still makes sense
2024-02-14 09:24:43 +01:00
Mike Degatano
b5bf270d22 Mount status checks look at connection (#4882)
* Mount status checks look at connection

* Fix tests and refactor to fixture

* Fix test
2024-02-12 17:32:54 +01:00
Mike Degatano
4c573991d2 Improve error handling when mounts fail (#4872) 2024-02-05 16:24:53 -05:00
Mike Degatano
7fd6dce55f Migrate to Ruff for lint and format (#4852)
* Migrate to Ruff for lint and format

* Fix pylint issues

* DBus property sets into normal awaitable methods

* Fix tests relying on separate tasks in connect

* Fixes from feedback
2024-02-05 11:37:39 -05:00
Mike Degatano
480b383782 Add background option to backup APIs (#4802)
* Add background option to backup APIs

* Fix decorator tests

* Working error handling, initial test cases

* Change to schedule_job and always return job id

* Add tests

* Reorder call at/later args

* Validation errors return immediately in background

* None is invalid option for background

* Must pop the background option from body
2024-01-22 12:09:15 -05:00
Mike Degatano
6c66a7ba17 Improve error handling in backup restore (#4791) 2023-12-29 11:45:50 +01:00