I’ve created a new blueprint, this time to use the new schedule helper.
Please take a look here: Scheduled auto-update for Home Assistant - Blueprints Exchange - Home Assistant Community (home-assistant.io)
- I haven’t changed this one to not mess up with existing implementations, so if you want to use that new one, create a new automation based on that one and remove your previous automation based on the old blueprint.
=======================================================
So, I finally got some time to create a Blueprint to help keeping Home Assistant updated automatically.
ATTENTION: Before you jump to the Blueprint, please take a look on those discussions around this topic and make sure you understand the risks related to auto-updating Home Assistant:
- How to keep everything automatically up to date? - Configuration - Home Assistant Community (home-assistant.io)
- Auto Update feature for Core/Supervisor - Feature Requests - Home Assistant Community (home-assistant.io)
Note: You might want to consider this other Blueprints (which I wasn’t aware of its existence before I published my Blueprint):
Please provide feedback. It’s quite hard to extensively test this as updates are not easy to un-install.
Change log:
- 2022-06-08 07:10 UTC:
- First time published
- 2022-06-27 14:52 UTC:
- Added an option to pause/override the automation based in an binary state entity (to avoid updates when your house is in party mode, as an example
- Split update of core items (first) and OS (last).
*2022-09-08 14:58 UTC: - Removed the protection which was preventing a new back if another backup was done in the past 2 hours.
- This was entirely breaking the backup triggers when Google Drive Backup add-on wasn’t running.
- Removing this was a workaround. I will come back soon with an alternative to better manage backup.
- For now I’ve chosen the safe side, backing up always when a new update is available and backup is selected.
- 2022-09-09 09:25 UTC:
- Removed another reference to the Google Drive backup sensor.
- Removed another reference to the Google Drive backup sensor.
This is the Blueprint:
blueprint:
name: Home Assistant Auto-update
description: 'Update Home Assistant automatically when a new update is available.
Note 1 => HACS updates NOT included.
Note 2 => Home Assistant may restart automatically as part of the update process.
IMPORTANT => Use under your own risk. Please see the discussions on Home Assistant community around the risks involved on auto-updating the system.'
domain: automation
source_url: https://community.home-assistant.io/t/auto-update-home-assistant/429015
input:
backup_bool:
name: Create a full backup before start the updates?
#description: Note => This automation will skip the backup if another backup was completed in the last two hours before starting the updates.
default: true
selector:
boolean:
schedule_time:
name: Schedule time
description: Remember that Home Assistant may restart after an update, so please avoid sensitive times.
default: '03:00:00'
selector:
time:
schedule_isoweekdays:
name: Week days
description: You can select multiple days of week for run the auto-updates.
default: ['1','2','3','4','5','6','7']
selector:
select:
#mode: list
multiple: true
options:
- label: Monday
value: "1"
- label: Tuesday
value: "2"
- label: Wednesday
value: "3"
- label: Thursday
value: "4"
- label: Friday
value: "5"
- label: Saturday
value: "6"
- label: Sunday
value: "7"
schedule_monthday:
name: Earliest day in the month to update Home Assistant.
description: 'Usually a new major version of Home Assistant is available on the begining of every month. Some people consider those release as not stable enough and prefer to avoid those versions, not updating the system until the mid of the month (day 15).
Note => If you select a day higher than 28 the updates won''t run every month.'
default: 21
selector:
number:
min: 1
max: 31
step: 1
mode: slider
update_exclusions:
name: (optional) Exclusions
description: 'Select the items that should NOT be included on the automated updates.
=> Use this if you want to keep some add-on on an specific version and avoid auto-updates to it.'
default: false
selector:
entity:
multiple: true
domain: update
actions_pre_update:
name: (optional) Pre-update actions
description: 'Actions to execute before the backup or any update starts.
You can use this to send notifications, turn on/off devices or activate scenes before starting the updates.
Note => Please be aware that all actions will run right before the update process, which can happens over-night. Take this in account when selecting your actions.
Note => The variable "\{\{ pending_updates \}\}" is available for your automations and contains the list of pending updates.'
default: []
selector:
action: {}
actions_pos_update:
name: (optional) Pos-update actions
description: 'Actions to execute AFTER the update process finishes.
You can use this to send notifications, turn on/off devices or activate scenes after applying the updates.
Note => Please be aware that all actions will run right before the update process, which can happens over-night. Take this in account when selecting your actions.
Note => The variable "\{\{ pending_updates \}\}" is available for your automations and contains the list of pending updates.
** IMPORTANT ** => Some updates will automatically restart Home Assistant, causing the automation to interrupt before finishing, preventing the pos-updates actions to be executed. If you have critical actions to run after an update, consider including also in another automation based on Home Assistant start.'
default: []
selector:
action: {}
pause_entities:
name: (Optional) Pause update entities
description: 'You can select one or more entities to pause the updates. If any of the selected entities is "On" or "True" the system won''t be updated on the schedule time.
You can use this to hold your updates when you have a party at home, or when you are on vacations and don''t want to be concerned about updates on Home Assistant.'
default: [ ]
selector:
entity:
multiple: true
domain: [input_boolean, binary_sensor, switch]
mode: restart #if the automation is kept running forever, it will restart on the next schedule.
max_exceeded: warning #It's not expected to have the automation running multiple instances of itself.
variables:
pending_updates: >-
{{ states.update | selectattr('state','eq','on') | rejectattr('entity_id', 'in', input_update_exclusions_processed) | list }}
input_backup_bool: !input backup_bool
input_schedule_isoweekdays: !input schedule_isoweekdays
input_schedule_monthday: !input schedule_monthday
input_update_exclusions: !input update_exclusions
input_update_exclusions_processed: >-
{% if input_update_exclusions %}
{{ input_update_exclusions }}
{% else %}
[ ]
{% endif %}
input_pause_entities: !input pause_entities
input_pause_entities_selected: >-
{% if input_pause_entities %}
true
{% else %}
false
{% endif %}
input_pause_entities_processed: >-
{% if input_pause_entities_selected %}
{{ input_pause_entities }}
{% else %}
[ ]
{% endif %}
trigger:
- platform: time
at: !input schedule_time
id: Time based
condition:
- condition: template
value_template: >-
{{ (states.update | selectattr('state','eq','on') | rejectattr('entity_id', 'in', input_update_exclusions_processed) | list | count | int(0)) > 0 }}
- condition: template
value_template: >-
{{ (now().day >= ((input_schedule_monthday) | int(0))) }}
- condition: template
value_template: >-
{{ (now().isoweekday() | string in input_schedule_isoweekdays ) }}
- condition: or
conditions:
- condition: template
value_template: >-
{{ ( input_pause_entities_selected == false ) }}
- condition: state
entity_id: !input pause_entities
state: 'off'
action:
########## Starting ##########
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: >-
Variables:
input_backup_bool: {{ input_backup_bool }},
input_schedule_isoweekdays: {{ input_schedule_isoweekdays }},
input_schedule_monthday: {{ input_schedule_monthday }},
input_update_exclusions: {{ input_update_exclusions }},
input_update_exclusions_processed: {{ input_update_exclusions_processed }}
input_notifications_dest: {{ input_notifications_dest }},
input_notifications_dest_processed: {{ input_notifications_dest_processed }}
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
domain: update
message: A new update is available for Home Assistant.
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
domain: update
message: >-
List of updates:
- {{ states.update
| selectattr('state','eq','on')
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='name') | list | join('
- ') }}
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Running pre-update actions...
- choose:
- conditions:
- '{{ true }}'
sequence: !input actions_pre_update
default: []
########## Backup ##########
- if:
# - condition: and
# conditions:
# - condition: template
# value_template: >-
# {{ ( input_backup_bool ) }}
# - condition: template
# value_template: >-
# {{ ((as_timestamp(now()) - as_timestamp(state_attr('sensor.backup_state', 'last_backup'))) > 3600) }}
- condition: template
value_template: >-
{{ ( input_backup_bool ) }}
## {{ ( input_backup_bool ) and ((as_timestamp(now()) - as_timestamp(state_attr('sensor.backup_state', 'last_backup'))) > 7200) }}
then:
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Backing up Home Assistant.
- service: hassio.backup_full
data:
compressed: true
# - wait_template: >-
# {{ ((as_timestamp(now()) - as_timestamp(state_attr('sensor.backup_state', 'last_backup'))) <= 7200) }}
# continue_on_timeout: true
# timeout: '3600' #3600
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Backup triggered.
else: []
########## Update add-ons (Standard) ##########
- if:
- condition: template
value_template: >-
{{ (states.update
| selectattr('state','eq','on')
| rejectattr('entity_id', 'in', ['update.home_assistant_core_update','update.home_assistant_operating_system_update','update.home_assistant_supervisor_update','update.home_assistant_google_drive_backup_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='entity_id')
| list | count | int(0) ) > 0
}}
then:
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Updating add-ons (Standard).
- service: update.install
data: {}
target:
entity_id: >-
{{ states.update
| selectattr('state','eq','on')
| rejectattr('entity_id', 'in', ['update.home_assistant_core_update','update.home_assistant_operating_system_update','update.home_assistant_supervisor_update','update.home_assistant_google_drive_backup_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_proccessed)
| map(attribute='entity_id')
| list
}}
- wait_template: >-
{{ (states.update
| selectattr('state','eq','on')
| rejectattr('entity_id', 'in', ['update.home_assistant_core_update','update.home_assistant_operating_system_update','update.home_assistant_supervisor_update','update.home_assistant_google_drive_backup_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='entity_id')
| list | count | int(0) ) < 1
}}
continue_on_timeout: true
timeout: '3600' #3600
else: []
########## Update add-ons (Critical) ##########
- if:
- condition: template
value_template: >-
{{ (states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_google_drive_backup_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='entity_id')
| list | count | int(0) ) > 0
}}
then:
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Updating add-ons (Critical).
- service: update.install
data: {}
target:
entity_id: >-
{{ states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_google_drive_backup_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_proccessed)
| map(attribute='entity_id')
| list
}}
- wait_template: >-
{{ (states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_google_drive_backup_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='entity_id')
| list | count | int(0) ) < 1
}}
continue_on_timeout: true
timeout: '3600' #3600
else: []
########## Update core items ##########
- if:
- condition: template
value_template: >-
{{ (states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_core_update','update.home_assistant_supervisor_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='entity_id')
| list | count | int(0) ) > 0
}}
then:
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Updating core items.
- service: update.install
data: {}
target:
entity_id: >-
{{ states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_core_update','update.home_assistant_supervisor_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_proccessed)
| map(attribute='entity_id')
| list
}}
- wait_template: >-
{{ (states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_core_update','update.home_assistant_supervisor_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='entity_id')
| list | count | int(0) ) < 1
}}
continue_on_timeout: true
timeout: '3600' #3600
########## Update OS ##########
- if:
- condition: template
value_template: >-
{{ (states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_operating_system_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='entity_id')
| list | count | int(0) ) > 0
}}
then:
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Updating OS.
- service: update.install
data: {}
target:
entity_id: >-
{{ states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_operating_system_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_proccessed)
| map(attribute='entity_id')
| list
}}
- wait_template: >-
{{ (states.update
| selectattr('state','eq','on')
| selectattr('entity_id', 'in', ['update.home_assistant_operating_system_update'])
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='entity_id')
| list | count | int(0) ) < 1
}}
continue_on_timeout: true
timeout: '3600' #3600
########## Update all remaining items ########## => this chaches up if some update item was left behind
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Updating all remaining items (if any).
- service: update.install
data: {}
target:
entity_id: >-
{{ states.update
| selectattr('state','eq','on')
| rejectattr('entity_id', 'in', input_update_exclusions_proccessed)
| map(attribute='entity_id')
| list
}}
- wait_template: >-
{{ (states.update | selectattr('state','eq','on') | rejectattr('entity_id', 'in', input_update_exclusions_processed) | list | count | int(0)) < 1 }}
continue_on_timeout: true
timeout: '3600' #3600
########## Ending ##########
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: All updates done.
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: >-
Remaining updates:
- {{ states.update
| selectattr('state','eq','on')
| rejectattr('entity_id', 'in', input_update_exclusions_processed)
| map(attribute='name') | list | join('
- ') }}
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Running pos-update actions...
- choose:
- conditions:
- '{{ true }}'
sequence: !input actions_pos_update
default: []
- service: logbook.log
data:
name: Auto-update
entity_id: '{{ this.entity_id }}'
message: Done!