diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 07bb123a5e3384c786cee29929ca0727c2f1838d..8a7187ca5fe5a4cbfc1744a5351deed9a4676a28 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -11,10 +11,10 @@ repos:
       - id: detect-private-key
       - id: trailing-whitespace
   - repo: https://git.shore.co.il/ansible/ansible-pre-commit.git
-    rev: v0.8.0
+    rev: v0.10.0
     hooks:
       - id: ansible-syntax-check
-        files: bootstrap\.yaml|router\.yaml
+        files: bootstrap\.yaml|update\.yaml|renew-certs\.yaml
         types: [yaml]
   - repo: https://github.com/ansible/ansible-lint
     rev: v4.3.7
diff --git a/update.yaml b/update.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7e83fcea730c7766e75941cc4d2d2afc14e73c61
--- /dev/null
+++ b/update.yaml
@@ -0,0 +1,127 @@
+---
+- name: Group hosts by package manager
+  hosts:
+    - all
+  tasks:
+    - name: Group hosts by package manager
+      group_by:
+        key: pkg_mgr_{{ ansible_pkg_mgr }}
+      tags:
+        - always
+
+- name: Update Debian hosts
+  hosts:
+    - pkg_mgr_apt
+  tasks:
+    - name: Update packages
+      apt:
+        autoclean: true
+        purge: true
+        update_cache: true
+        upgrade: dist
+      register: apt_upgrade
+
+    - name: Remove no-longer needed dependecies
+      apt:
+        autoremove: true
+        purge: true
+
+    - name: Update firmware
+      command: fwupdmgr --assume-yes update
+      register: fwupdmgr
+      changed_when: fwupdmgr.stdout_lines|length > 0
+
+    - name: Set reboot needed fact
+      set_fact:
+        reboot_needed: "{{ apt_upgrade is changed or fwupdmgr is changed }}"
+  tags:
+    - debian
+    - update
+
+- name: Update OpenWRT hosts
+  hosts:
+    - pkg_mgr_opkg
+  tasks:
+    - name: Update package list
+      command: opkg update
+      changed_when: false
+
+    - name: Update packages
+      # We run through sort so that we don't run 2 instances fo opkg at once.
+      shell: |-
+        opkg list-upgradable | awk '{print $1}' | sort | xargs -rn1 opkg upgrade
+      register: opkg_upgrade
+      changed_when: opkg_upgrade.stdout_lines|length > 0
+
+    - name: Set reboot needed fact
+      set_fact:
+        reboot_needed: "{{ opkg_upgrade is changed }}"
+  tags:
+    - openwrt
+    - update
+
+- name: Update OpenBSD hosts
+  hosts:
+    - pkg_mgr_openbsd_pkg
+  tasks:
+    - name: Apply system patches
+      command: syspatch
+      register: syspatch
+      changed_when: syspatch.stdout_lines|length > 0
+
+    - name: Update packages
+      openbsd_pkg:
+        name: "*"
+        state: latest
+      register: pkg_upgrade
+
+    - name: Update firmware
+      command: fw_update -a
+      register: fw_update
+      changed_when: fw_update.stdout_lines|length > 0
+
+    - name: Set reboot needed fact
+      set_fact:
+        reboot_needed: >-
+          {{ syspatch is changed or
+          pkg_upgrade is changed or
+          fw_update is changed }}
+  tags:
+    - openbsd
+    - update
+
+- name: Reboot NS1
+  hosts:
+    - ns1
+  tasks:
+    - name: Reboot
+      when: reboot_needed
+      reboot:
+  tags:
+    - reboot
+
+- name: Reboot EA6350
+  hosts:
+    - ea6350
+  tasks:
+    - name: Reboot
+      when: reboot_needed
+      command: reboot
+
+    - name: Wait to re-establish the connection
+      wait_for_connection:
+  tags:
+    - reboot
+
+- name: Reboot the rest
+  hosts:
+    - all:!ns1:!ea6350
+  tasks:
+    - name: Wait to re-establish the connection
+      wait_for_connection:
+
+    - name: Reboot
+      when: reboot_needed
+      reboot:
+  tags:
+    - reboot