Monitor and control Backrest, the web UI and orchestrator for restic backups, from Home Assistant.
The integration talks to Backrest's own API (Connect RPC, the same API the Backrest web UI uses), discovers all backup plans and repositories automatically, keeps up with plans you add or delete later and lets you start or cancel backups from Home Assistant.
This is a community project and not affiliated with the Backrest project.
- Setup from the UI (config flow) with connection test, HTTP or HTTPS, optional certificate verification and optional username/password
- Several Backrest instances side by side
- Automatic discovery of backup plans and repositories, including plans created, re-created or deleted while Home Assistant is running (no restart)
- One device per Backrest server, per backup plan and per repository with stable unique IDs
- Sensors for status, last success, last attempt, next scheduled run, duration, size, data added, progress, 30-day success/failure counts, last error and more
- Live activity: what Backrest is doing right now (backup, check, prune, restore, ...) per server and per repository, plus when the last check and prune ran
- Binary sensors for reachability, running backups, failed backups, overdue plans and an overall "problem" flag
- Buttons and actions to start or cancel a backup, optional repository check/prune buttons
- Real-time updates through Backrest's operation event stream (with regular polling as the source of truth), configurable polling interval (default 60 s)
- Re-authentication and reconfiguration flows, diagnostics with redacted data
- English and German translations
| Component | Supported |
|---|---|
| Home Assistant | 2025.6.0 or newer (CI tests 2025.6 and 2026.10) |
| Backrest | 1.6.0 or newer recommended, tested with 1.6.2 and 1.14.1 |
Backrest versions before 1.6.0 lack the summary dashboard API. The integration detects this and keeps working, but the 30-day counters and data-volume sensors are not created. Versions before 1.6.0 have not been tested.
- Open HACS in Home Assistant.
- Open the menu (⋮) in the top right and choose Custom repositories.
- Add
https://github.com/daschmidt1994/homeassistant-backrestwith type Integration. - Search for Backrest in HACS and download it.
- Restart Home Assistant.
Copy custom_components/backrest into the custom_components folder of your Home
Assistant configuration and restart Home Assistant.
Go to Settings → Devices & services → Add integration → Backrest.
| Field | Description |
|---|---|
| Host | Hostname or IP address of the Backrest server |
| Port | Port of the Backrest web UI, 9898 by default |
| Use HTTPS | Enable when Backrest is served via HTTPS (for example behind a reverse proxy) |
| Verify SSL certificate | Disable only for self-signed certificates |
| Username / Password | Only needed when authentication is enabled in Backrest |
By default Backrest only listens on 127.0.0.1. To reach it from Home Assistant, start
Backrest with --bind-address :9898 (or BACKREST_PORT=0.0.0.0:9898), or put it behind
a reverse proxy. Reverse proxies must forward the /v1.Backrest/ and
/v1.Authentication/ paths and allow long-running and streaming requests (see
Known limitations). Serving Backrest under a sub-path is not
supported.
Options (Settings → Devices & services → Backrest → Configure):
| Option | Default | Description |
|---|---|---|
| Update interval | 60 s | Polling interval, 15–3600 seconds |
| Real-time updates | on | Subscribe to Backrest's event stream to refresh as soon as a backup starts or ends |
Changed credentials can be entered via the re-authentication prompt that appears automatically; a changed address via Reconfigure.
Entity IDs below are what Home Assistant generates for a Backrest instance named
homeserver, a plan with the ID nas and a repository offsite, with Home Assistant
set to English. Home Assistant derives entity IDs from the entity names in its configured
language, so in German they read e.g. sensor.backrest_nas_letztes_backup. Entity IDs are
created once; renaming entities in a later version does not change existing IDs. If two devices would
produce the same entity ID (for example a plan named like the instance), Home Assistant
appends _2.
| Entity | Example entity ID | Notes |
|---|---|---|
| Reachable | binary_sensor.backrest_homeserver_reachable |
off when the last request failed; never unavailable |
| Problem | binary_sensor.backrest_homeserver_problem |
on if unreachable, a plan's last backup failed, a plan is overdue or a repository's last check failed; attributes failed_plans, overdue_plans, failed_checks |
| Backup running | binary_sensor.backrest_homeserver_backup_running |
Any plan |
| Activity | sensor.backrest_homeserver_activity |
What Backrest is doing right now: idle, backup, check, prune, forget, restore, stats, index, hook, command; attribute operations lists all running tasks |
| Backup plans | sensor.backrest_homeserver_backup_plans |
Attribute plans |
| Repositories | sensor.backrest_homeserver_repositories |
|
| Running backups | sensor.backrest_homeserver_running_backups |
|
| Plans with successful last backup | sensor.backrest_homeserver_plans_with_successful_last_backup |
Success or warning |
| Plans with failed last backup | sensor.backrest_homeserver_plans_with_failed_last_backup |
|
| Plans without successful backup | sensor.backrest_homeserver_plans_without_successful_backup |
See How values are determined |
| Last successful backup | sensor.backrest_homeserver_last_successful_backup |
Across all plans, attribute plan |
| Entity | Example entity ID | Notes |
|---|---|---|
| Start backup | button.backrest_nas_start_backup |
|
| Cancel backup | button.backrest_nas_cancel_backup |
|
| Backup running | binary_sensor.backrest_nas_backup_running |
|
| Last backup failed | binary_sensor.backrest_nas_last_backup_failed |
Attribute error_message |
| Backup overdue | binary_sensor.backrest_nas_backup_overdue |
Attribute last_success |
| Last backup status | sensor.backrest_nas_last_backup_status |
success, warning, error, in_progress, system_cancelled, user_cancelled |
| Last successful backup | sensor.backrest_nas_last_successful_backup |
Timestamp, attribute snapshot_id |
| Last backup attempt | sensor.backrest_nas_last_backup_attempt |
Start time of the latest run; diagnostic |
| Next backup | sensor.backrest_nas_next_backup |
Next scheduled run, unknown if the schedule is disabled |
| Last backup duration | sensor.backrest_nas_last_backup_duration |
Shown in minutes |
| Backup progress | sensor.backrest_nas_backup_progress |
Percent while running, 0 when idle |
| Running backups | sensor.backrest_nas_running_backups |
Diagnostic, attribute queued |
| Successful backups (30 days) | sensor.backrest_nas_successful_backups_30_days |
Includes warnings (attribute with_warnings); Backrest ≥ 1.6 |
| Failed backups (30 days) | sensor.backrest_nas_failed_backups_30_days |
Backrest ≥ 1.6 |
| Last backup size | sensor.backrest_nas_last_backup_size |
Bytes processed by the last successful backup |
| Last backup data added | sensor.backrest_nas_last_backup_data_added |
New data stored by the last successful backup |
| Last backup files | sensor.backrest_nas_last_backup_files |
Disabled by default |
| Last status change | sensor.backrest_nas_last_status_change |
Diagnostic |
| Last error message | sensor.backrest_nas_last_error_message |
Diagnostic, attribute occurred_at |
| Entity | Example entity ID | Notes |
|---|---|---|
| Backup plans | sensor.backrest_repository_offsite_backup_plans |
|
| Current task | sensor.backrest_repository_offsite_current_task |
Task running on the repository, same values as Activity |
| Last check | sensor.backrest_repository_offsite_last_check |
When the last check finished; attributes status, error_message |
| Last prune | sensor.backrest_repository_offsite_last_prune |
When the last prune finished; attributes status, error_message |
| Successful backups (30 days) | sensor.backrest_repository_offsite_successful_backups_30_days |
Backrest ≥ 1.6 |
| Failed backups (30 days) | sensor.backrest_repository_offsite_failed_backups_30_days |
Backrest ≥ 1.6 |
| Data added (30 days) | sensor.backrest_repository_offsite_data_added_30_days |
Backrest ≥ 1.6 |
| Protected data | sensor.backrest_repository_offsite_protected_data |
Size of the latest good backup; Backrest ≥ 1.14 |
| Check repository | button.backrest_repository_offsite_check_repository |
Disabled by default |
| Prune repository | button.backrest_repository_offsite_prune_repository |
Disabled by default |
When the configured Backrest is a multihost server (Backrest ≥ 1.10, Settings →
Multihost), every connected client instance gets its own device. Its plans appear as
plan devices named Backrest <instance> <plan>, for example Backrest netbird-vps system,
with the same entities as local plans except:
- no Start backup / Cancel backup buttons: Backrest offers no API to run a backup on a peer, start it on the client instead
- no 30-day statistics: the server's summary dashboard only covers its own plans
The client must grant the server the Read operations permission (for backup results)
and Read config or Read/write config (for schedules; without it the next backup and
overdue detection are unknown). Remote plans count towards the server sensors such as
Problem and Backup plans; their IDs there are <instance>/<plan>.
| Entity | Example entity ID | Notes |
|---|---|---|
| Connected | binary_sensor.backrest_netbird_vps_connected |
Multihost connection to the server |
| Last contact | sensor.backrest_netbird_vps_last_contact |
Last heartbeat; Backrest sends one every 10 minutes by default |
| Connection | sensor.backrest_netbird_vps_connection |
Diagnostic: connected, disconnected, retry_wait, error_auth, ... |
| Action | Fields | Description |
|---|---|---|
backrest.start_backup |
config_entry_id, plan_id |
Start a backup of a plan |
backrest.cancel_backup |
config_entry_id, plan_id |
Request cancellation of the running backup of a plan |
action: backrest.start_backup
data:
config_entry_id: 01JABCDEF0123456789ABCDEFG # pick the instance in the UI editor
plan_id: nas- Plans and repositories come from
GetConfigon every refresh. New plans get their entities on the next refresh; deleted plans and repositories are removed together with their device. Plan IDs cannot be renamed in Backrest, so unique IDs stay stable. A plan that is deleted and re-created with the same ID gets the same entity IDs again. - Backup runs come from
GetOperations(the 50 most recent operations of each plan). New runs update the existing entities; they never create new ones. Dry runs are ignored. - 30-day counters, next run fallback and data volumes come from
GetSummaryDashboard(Backrest ≥ 1.6). - Last successful backup uses the recent operations and falls back to the 30-day summary. If neither contains a success, the value is unknown and the plan counts as "without successful backup". A plan whose last success is older than 30 days and more than ~50 operations back is therefore reported as without success.
- Overdue uses the same rule as the Backrest dashboard: the schedule's nominal period (cron, every N hours or every N days) × 1.25 has passed since the last good backup (success or warning). Plans with a disabled schedule are never overdue; plans that never had a good backup are not overdue (like in Backrest), but show up in "Last backup failed" or "Plans without successful backup".
- Last status change is the time the result of the plan's finished backups last
changed (for example from
successtoerror). It is unknown if the current status goes back further than the fetched history. - A started backup is never reported as successful. Pressing Start backup only
means that Backrest accepted the request; the status sensors switch to
in_progressand later to the real result reported by Backrest.
These examples live in examples/automations.yaml and are
run against the integration in the test suite (tests/test_automation_examples.py).
Replace homeserver and nas with your instance name and plan ID, and notify.notify
with your notification action.
- id: backrest_backup_failed
alias: "Backrest: backup failed"
triggers:
- trigger: state
entity_id: binary_sensor.backrest_nas_last_backup_failed
from: "off"
to: "on"
actions:
- action: notify.notify
data:
title: "Backup failed"
message: >-
Backup plan "nas" failed:
{{ trigger.to_state.attributes.error_message or 'no error message' }}Based on the plan's schedule:
- id: backrest_backup_overdue
alias: "Backrest: backup overdue"
triggers:
- trigger: state
entity_id: binary_sensor.backrest_nas_backup_overdue
from: "off"
to: "on"
actions:
- action: notify.notify
data:
title: "Backup overdue"
message: >-
No successful backup of "nas" since
{{ as_timestamp(trigger.to_state.attributes.last_success, none)
| timestamp_custom('%Y-%m-%d %H:%M', default='never') }}.With your own threshold:
- id: backrest_backup_older_than_48h
alias: "Backrest: no backup for 48 hours"
triggers:
- trigger: template
value_template: >-
{% set last = states('sensor.backrest_nas_last_successful_backup') | as_datetime(none) %}
{{ last is not none and now() - last > timedelta(hours=48) }}
actions:
- action: notify.notify
data:
title: "Backup older than 48 hours"
message: The last successful backup of "nas" is older than 48 hours.- id: backrest_start_backup_nightly
alias: "Backrest: start NAS backup at night"
triggers:
- trigger: time
at: "22:00:00"
conditions:
- condition: state
entity_id: binary_sensor.backrest_nas_backup_running
state: "off"
actions:
- action: button.press
target:
entity_id: button.backrest_nas_start_backup- id: backrest_offline
alias: "Backrest: server offline"
triggers:
- trigger: state
entity_id: binary_sensor.backrest_homeserver_reachable
to: "off"
for: "00:05:00"
actions:
- action: notify.notify
data:
title: "Backrest offline"
message: The Backrest server "homeserver" is not reachable.No screenshots yet. Contributions are welcome.
| Problem | Solution |
|---|---|
| Failed to connect | Check host, port and HTTP/HTTPS. Backrest listens on 127.0.0.1 only by default, see Configuration. |
| The server did not respond like Backrest | Host/port point to another service, or a reverse proxy rewrites the API paths. |
| This Backrest instance requires a username and password | Authentication is enabled in Backrest; enter a Backrest user. |
| SSL certificate could not be verified | Self-signed certificate: disable Verify SSL certificate. |
| Entities are unavailable | Backrest is unreachable; binary_sensor.backrest_<instance>_reachable is off. The integration retries on every polling interval. |
| A new plan does not show up | It appears on the next refresh (polling interval). Check that it exists in Backrest's config. |
| Start backup says a backup is already running | Backrest has a running or queued backup for the plan, or a previous start request is still waiting for Backrest. |
Debug logging
logger:
logs:
custom_components.backrest: debugDiagnostics: Settings → Devices & services → Backrest → ⋮ → Download diagnostics. The file contains the integration version, reachability, the last successful refresh, the detected API features, the last error and the derived state of every plan. Host, username, password and the instance key are redacted; repository URIs, passwords, paths and hook settings are never stored by the integration in the first place.
- No version sensor. Backrest does not expose its version through the API (it is only compiled into the web UI bundle), so the integration does not report it.
- Start backup waits for completion server-side. Backrest's
Backupcall only returns once the backup has finished. The integration sends the request in the background and treats it as accepted when Backrest has not rejected it within 10 seconds. If Home Assistant restarts or the connection drops, the backup keeps running in Backrest; only the waiting request is dropped. Reverse proxies with short read timeouts may close that request; this does not stop the backup either. - Cancel is best effort. Backrest does not guarantee that a cancellation succeeds.
- Dry runs and restore operations are not offered.
- Event stream behind proxies: proxies that buffer responses delay or break the event stream. Updates then arrive with the polling interval; disable Real-time updates if your proxy logs errors.
- Multihost: plans of client instances are read-only (see Remote instance), and repositories of client instances are not shown.
- Authentication uses Backrest's username/password login (JWT). Backrest offers no API keys.
- Backrest returns repository passwords in
GetConfigto every authenticated client. The integration discards them immediately, but the Backrest user you configure can read them.
All calls are Connect RPC requests (POST /<service>/<method>, JSON body) as defined in
proto/v1/service.proto:
| Call | Used for |
|---|---|
v1.Authentication/Login |
Exchange username/password for a JWT (only if Backrest answers 401) |
v1.Backrest/GetConfig |
Plans, repositories, instance name |
v1.Backrest/GetOperations |
Recent operations per plan |
v1.Backrest/GetSummaryDashboard |
30-day statistics (Backrest ≥ 1.6) |
v1.Backrest/GetOperationEvents |
Server stream that triggers immediate refreshes |
v1sync.BackrestSyncStateService/GetPeerSyncStatesStream |
Remote instances and their plans (multihost server); the remote configs it returns contain repository passwords and are reduced to plan schedules right away |
v1.Backrest/Backup |
Start backup button / action |
v1.Backrest/Cancel |
Cancel backup button / action |
v1.Backrest/DoRepoTask |
Check / prune repository buttons |
python3.14 -m venv .venv && . .venv/bin/activate
pip install -r requirements_test.txt -r requirements_lint.txt
ruff check . && ruff format --check .
pytest tests --covtests/test_live.py runs the whole integration against a real Backrest server and is
skipped unless BACKREST_LIVE_HOST is set (see the module docstring).