diff --git a/roles/debian_server/files/apt-download-updates b/roles/debian_server/files/apt-download-updates
new file mode 100755
index 0000000000000000000000000000000000000000..9af11f833a8a7b4f0095deede3d38e9f4821434e
--- /dev/null
+++ b/roles/debian_server/files/apt-download-updates
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -eu
+
+apt-get update
+apt-get dist-upgrade --download-only --yes
+apt-get autoclean
+
diff --git a/roles/debian_server/files/daily b/roles/debian_server/files/daily
deleted file mode 100755
index 6f0df3fad5047575887e1768205fd345a867f42e..0000000000000000000000000000000000000000
--- a/roles/debian_server/files/daily
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-set -eu
-
-apt-get update
-apt-get dist-upgrade --download-only --yes
-apt-get autoclean
-
-if command -v flatpak >/dev/null 2>&1
-then
-    flatpak --system update --appstream
-    flatpak --system update --assumeyes
-    flatpak --system uninstall --unused --assumeyes
-fi
-
-fwupdmgr --assume-yes get-updates
-
-if  [ "$(apt list --upgradable 2>/dev/null | wc -l)" -gt '1' ] || \
-    [ -n "$(fwupdmgr --assume-yes get-updates)" ]
-then
-    curl "https://notify.shore.co.il/send?message=$(hostname --short)%20has%20pending%20updates."
-fi
diff --git a/roles/debian_server/files/flatpak-update b/roles/debian_server/files/flatpak-update
new file mode 100755
index 0000000000000000000000000000000000000000..b159b06c004865a83aaf6aa521c658fbd5973289
--- /dev/null
+++ b/roles/debian_server/files/flatpak-update
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -eu
+
+if ! which flatpak >/dev/null
+then
+    echo 'Flatpak not installed, exiting.'
+    exit
+fi
+
+flatpak --system update --appstream
+flatpak --system update --assumeyes
+flatpak --system uninstall --unused --assumeyes
diff --git a/roles/debian_server/files/fw-update b/roles/debian_server/files/fw-update
new file mode 100755
index 0000000000000000000000000000000000000000..485c3f2deaf0a4e7f3983da0051b6f9ed70019b4
--- /dev/null
+++ b/roles/debian_server/files/fw-update
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -eu
+
+# First to download an updated list silently.
+fwupdmgr --assume-yes get-updates 1>/dev/null
+
+# Now to check if there are pending updates.
+if [ "$(fwupdmgr --assume-yes get-updates | wc -l)" -gt 1 ]
+then
+    echo 'Available firmware updates.'
+    exit 2
+else
+    echo 'Firmware is up to date.'
+    exit 0
+fi
diff --git a/roles/debian_server/files/needrestart.service b/roles/debian_server/files/needrestart.service
deleted file mode 100644
index bfac450f73295360ea106ba6a6a2c54e2a35f69d..0000000000000000000000000000000000000000
--- a/roles/debian_server/files/needrestart.service
+++ /dev/null
@@ -1,9 +0,0 @@
-# vim: filetype=systemd
-[Unit]
-Description=Check if a restart is needed
-ConditionACPower=true
-After=network-online.target
-
-[Service]
-Type=oneshot
-ExecStart=/bin/sh -c 'needrestart -p || curl "https://notify.shore.co.il/send?message=$(hostname --short)%%20needs%%20to%%20be%%20restarted."'
diff --git a/roles/debian_server/files/needrestart.timer b/roles/debian_server/files/needrestart.timer
deleted file mode 100644
index d6342be3c4b93f3071e56ac4913c9d403aff3057..0000000000000000000000000000000000000000
--- a/roles/debian_server/files/needrestart.timer
+++ /dev/null
@@ -1,9 +0,0 @@
-# vim: filetype=systemd
-[Unit]
-Description=Check if a restart is needed
-
-[Timer]
-OnCalendar=daily
-
-[Install]
-WantedBy=multi-user.target
diff --git a/roles/debian_server/files/update.service b/roles/debian_server/files/update.service
deleted file mode 100644
index 50ba6d4e3d1e810837e847087020650aafe76044..0000000000000000000000000000000000000000
--- a/roles/debian_server/files/update.service
+++ /dev/null
@@ -1,9 +0,0 @@
-# vim: filetype=systemd
-[Unit]
-Description=Background system updates
-ConditionACPower=true
-After=network-online.target
-
-[Service]
-Type=oneshot
-ExecStart=daily
diff --git a/roles/debian_server/tasks/btrfs.yml b/roles/debian_server/tasks/btrfs.yml
index 013e7f98f8899f8f41dfad6c767c1238ec66a307..2e48dac1d3caffd47929349a24f58cf89d5f1a0d 100644
--- a/roles/debian_server/tasks/btrfs.yml
+++ b/roles/debian_server/tasks/btrfs.yml
@@ -1,4 +1,12 @@
 ---
+- name: Install btrfs packages
+  apt:
+    cache_valid_time: 3600
+    name:
+      - btrfs-progs
+      - monitoring-plugins-btrfs
+    state: present
+
 - name: Copy btrfs backup script
   copy:
     dest: /usr/local/sbin/btrfs-backup
@@ -7,34 +15,37 @@
     owner: root
     src: btrfs-backup
 
-- name: Create btrfs scrub services
-  # yamllint disable rule:line-length
-  loop: &btrfs_devices |-
-    {{ ansible_facts.mounts|selectattr("fstype", "equalto", "btrfs")|map(attribute="device")|unique }}
-  # yamllint enable rule:line-length
+- name: Install btrfs scrub services and timers
+  loop: &loop
+    - service
+    - timer
   ansible.builtin.template:
-    dest: /etc/systemd/system/scrub{{ name }}.service
+    dest: /etc/systemd/system/btrfs_scrub{{ name }}.{{ item }}
     mode: 0o0644
-    src: scrub.service.j2
-  vars: &btrfs_vars
-    device: '{{ item }}'
-    name: '{{ item|replace("/", "_") }}'
+    src: btrfs_scrub.{{ item }}.j2
+  vars: &vars
+    name: '{{ device|replace("/", "_") }}'
+  tags: [scrub]
+
+- name: Enable btrfs scrub timers
+  ansible.builtin.systemd:
+    enabled: true
+    name: btrfs_scrub{{ name }}.timer
+    state: started
+  vars: *vars
   tags: [scrub]
 
-- name: Create btrfs scrub timers
-  loop: *btrfs_devices
+- name: Install btrfs check services and timers
+  loop: *loop
   ansible.builtin.template:
-    dest: /etc/systemd/system/scrub{{ name }}.timer
+    dest: /etc/systemd/system/btrfs_check{{ name }}.{{ item }}
     mode: 0o0644
-    src: scrub.timer.j2
-  vars: *btrfs_vars
-  tags: [scrub]
+    src: btrfs_check.{{ item }}.j2
+  vars: *vars
 
-- name: Enable the btrfs scrub timers
-  loop: *btrfs_devices
+- name: Enable the btrfs check timers
   ansible.builtin.systemd:
     enabled: true
     name: scrub{{ name }}.timer
     state: started
-  vars: *btrfs_vars
-  tags: [scrub]
+  vars: *vars
diff --git a/roles/debian_server/tasks/main.yml b/roles/debian_server/tasks/main.yml
index e66f448419effeaaa514b17d738dc20a913db13b..4e8145ab91220363292f9b7519cda7441ef4fe9f 100644
--- a/roles/debian_server/tasks/main.yml
+++ b/roles/debian_server/tasks/main.yml
@@ -32,16 +32,13 @@
     cache_valid_time: 3600
     name:
       - amd64-microcode
-      - btrfs-progs
       - cryptsetup
       - curl
       - docker.io
-      - fwupd
       - git
       - intel-microcode
       - libpam-mount-bin
       - make
-      - needrestart
       - python3-cryptography
       - rsync
       - tmux
@@ -66,7 +63,7 @@
     value: "640000"
 
 - name: Configure the SSH daemon
-  include_tasks:
+  ansible.builtin.include_tasks:
     file: '{{ playbook_dir }}/tasks/sshd_config.yaml'
   tags:
     - always
@@ -98,58 +95,38 @@
     regexp: '^{{ item }}:'
     state: present
 
-- name: Copy update script
-  ansible.builtin.copy:
-    dest: /usr/local/sbin/daily
-    mode: 0o0755
-    src: daily
-
-- name: Copy update service and timer
-  loop:
-    - update.service
-    - update.timer
-  ansible.builtin.copy:
-    dest: /etc/systemd/system
-    mode: 0o0644
-    src: '{{ item }}'
-  notify:
-    - Systemd daemon reload
-
-- name: Enable the update timer
-  ansible.builtin.systemd:
-    enabled: true
-    name: update.timer
-    state: started
-
-- name: Copy the need restart service and timer
-  loop:
-    - needrestart.service
-    - needrestart.timer
-  ansible.builtin.copy:
-    dest: /etc/systemd/system
-    mode: 0o0644
-    src: '{{ item }}'
-  notify:
-    - Systemd daemon reload
-
-- name: Enable the need restart timer
-  ansible.builtin.systemd:
-    enabled: true
-    name: needrestart.timer
-    state: started
-
 - name: Include Docker tasks
   ansible.builtin.include_tasks:
     file: docker.yml
+  tags:
+    - always
 
 - name: Include web tasks
   ansible.builtin.include_tasks:
     file: web.yml
+  tags:
+    - always
+
+- name: Include maintenance tasks
+  ansible.builtin.include_tasks:
+    file: maintenance.yml
+  tags:
+    - always
 
 - name: Include btrfs tasks
+  # yamllint disable rule:line-length
+  loop: |-
+    {{ ansible_facts.mounts|selectattr("fstype", "equalto", "btrfs")|map(attribute="device")|unique }}
+  # yamllint enable rule:line-length
+  loop_control:
+    loop_var: device
   ansible.builtin.include_tasks:
     file: btrfs.yml
+  tags:
+    - always
 
 - name: Include  Toolbox tasks
   ansible.builtin.import_tasks:
     file: toolbox.yml
+  tags:
+    - always
diff --git a/roles/debian_server/tasks/maintenance.yml b/roles/debian_server/tasks/maintenance.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9cf3e1d4d1c8849e0e23817bfb4feba1ac2ff6eb
--- /dev/null
+++ b/roles/debian_server/tasks/maintenance.yml
@@ -0,0 +1,62 @@
+---
+- name: Install maintenance packages
+  ansible.builtin.apt:
+    cache_valid_time: 3600
+    install_recommends: false
+    name:
+      - fwupd
+      - monitoring-plugins-basic
+      - needrestart
+    state: present
+
+- name: Download My Nagios Plugin Wrapper
+  ansible.builtin.get_url:
+    dest: /usr/local/bin/mnpw
+    mode: 0o0755
+      # yamllint disable-line rule:line-length
+    url: https://git.shore.co.il/api/v4/projects/167/packages/generic/mnpw/v0.1.2/mnpw
+
+- name: Create a directory for periodic scripts and Nagios plugins
+  ansible.builtin.file:
+    mode: 0o0755
+    path: /usr/local/share/shore-maintenance
+    state: directory
+
+- name: Copy periodic scripts and Nagios plugins
+  loop:
+    - apt-download-updates
+    - flatpak-update
+    - fw-update
+  ansible.builtin.copy:
+    dest: /usr/local/share/shore-maintenance/
+    group: root
+    mode: 0o0755
+    owner: root
+    src: '{{ item }}'
+
+- name: Install Systemd services and timers for maintenance tasks
+  loop: |-
+    {{ maintenance_tasks|product(["service", "timer"]) }}
+  vars:
+    command: '{{ item[0]["command"] }}'
+    description: '{{ item[0]["description"] }}'
+    frequency: '{{ item[0]["frequency"] }}'
+    name: '{{ item[0]["name"] }}'
+    unit: '{{ item[1] }}'
+  ansible.builtin.template:
+    dest: /etc/systemd/system/{{ name }}.{{ unit }}
+    mode: 0o0644
+    src: maintenance-task.{{ unit }}.j2
+  notify:
+    - Systemd daemon reload
+
+- name: Enable the Systemd timers for maintenance tasks
+  loop: '{{ maintenance_tasks }}'
+  ansible.builtin.systemd:
+    enabled: true
+    name: '{{ name }}.timer'
+    state: started
+  vars:
+    name: '{{ item["name"] }}'
+  notify:
+    - Systemd daemon reload
diff --git a/roles/debian_server/tasks/toolbox.yml b/roles/debian_server/tasks/toolbox.yml
index e7b7193b728cd46bef47b068a2d7dfa07a6a5927..1a8b2016c11c5f2ddee69cbb8a3d4618b70f81bd 100644
--- a/roles/debian_server/tasks/toolbox.yml
+++ b/roles/debian_server/tasks/toolbox.yml
@@ -28,14 +28,6 @@
         that:
           - toolbox_podman_repo_base_url is defined
 
-    - name: APT install prerequisites
-      apt:
-        cache_valid_time: 3600
-        name:
-          - apt-transport-https
-        state: present
-        update_cache: true
-
     - name: Add the Podman repo key
       apt_key:
         state: present
diff --git a/roles/debian_server/templates/btrfs_check.service.j2 b/roles/debian_server/templates/btrfs_check.service.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d21bdb4933422a82bb410ac78ec374467a7ccd43
--- /dev/null
+++ b/roles/debian_server/templates/btrfs_check.service.j2
@@ -0,0 +1,9 @@
+# vim: filetype=systemd
+[Unit]
+Description=Check btrfs device {{ device }}
+After=local-fs.target
+After=network-online.target
+
+[Service]
+Type=exec
+ExecStart=mnpw --warn -- /usr/lib/nagios-btrfs/plugins/check_btrfs --mountpoint {{ device }}
diff --git a/roles/debian_server/files/update.timer b/roles/debian_server/templates/btrfs_check.timer.j2
similarity index 68%
rename from roles/debian_server/files/update.timer
rename to roles/debian_server/templates/btrfs_check.timer.j2
index d2471c45d7c3611e741acc3e2f3d60189e277d61..b70c7cb9f4aa5c9ae99c1ed7c851ffc9728d9293 100644
--- a/roles/debian_server/files/update.timer
+++ b/roles/debian_server/templates/btrfs_check.timer.j2
@@ -1,6 +1,6 @@
 # vim: filetype=systemd
 [Unit]
-Description=Background system updates
+Description=Check btrfs device {{ device }}
 
 [Timer]
 OnCalendar=daily
diff --git a/roles/debian_server/templates/scrub.service.j2 b/roles/debian_server/templates/btrfs_scrub.service.j2
similarity index 100%
rename from roles/debian_server/templates/scrub.service.j2
rename to roles/debian_server/templates/btrfs_scrub.service.j2
diff --git a/roles/debian_server/templates/scrub.timer.j2 b/roles/debian_server/templates/btrfs_scrub.timer.j2
similarity index 100%
rename from roles/debian_server/templates/scrub.timer.j2
rename to roles/debian_server/templates/btrfs_scrub.timer.j2
diff --git a/roles/debian_server/templates/maintenance-task.service.j2 b/roles/debian_server/templates/maintenance-task.service.j2
new file mode 100644
index 0000000000000000000000000000000000000000..a305c3c9d31748e69886eb402e0258f81aa2791c
--- /dev/null
+++ b/roles/debian_server/templates/maintenance-task.service.j2
@@ -0,0 +1,11 @@
+# vim: filetype=systemd
+[Unit]
+Description={{ description|default(name) }}
+ConditionACPower=true
+After=local-fs.target
+After=network-online.target
+
+[Service]
+Type=exec
+ExecStart={{ command }}
+
diff --git a/roles/debian_server/templates/maintenance-task.timer.j2 b/roles/debian_server/templates/maintenance-task.timer.j2
new file mode 100644
index 0000000000000000000000000000000000000000..bebc94e0e54ee62487aab7353be3ec5478eabe90
--- /dev/null
+++ b/roles/debian_server/templates/maintenance-task.timer.j2
@@ -0,0 +1,9 @@
+# vim: filetype=systemd
+[Unit]
+Description={{ description|default(name) }}
+
+[Timer]
+OnCalendar={{ frequency|default("daily") }}
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/debian_server/vars/main.yml b/roles/debian_server/vars/main.yml
index 5f233a332b2e9193b7e9a3d4bdc95898f8532ddd..7d5f06279f159e2ea71188176e96d99834d6eac2 100644
--- a/roles/debian_server/vars/main.yml
+++ b/roles/debian_server/vars/main.yml
@@ -1,4 +1,28 @@
 ---
+maintenance_directory: /usr/local/share/shore-maintenance
+
+maintenance_tasks:
+  - name: apt-check
+    description: Check for pending APT updates
+    command: mnpw --errors --warn -- /usr/lib/nagios/plugins/check_apt --list
+    frequency: daily
+  - name: apt-download-updates
+    description: Download pending APT updates for faster updates
+    command: '{{ maintenance_directory }}/apt-download-updates'
+    frequency: daily
+  - name: flatpak-update
+    description: Update flatpaks
+    command: '{{ maintenance_directory }}/flatpak-update'
+    frequency: daily
+  - name: fw-update
+    description: Check for available firmware updates
+    command: mnpw --errors -- {{ maintenance_directory }}/fw-update
+    frequency: daily
+  - name: needrestart
+    description: Check if a restart is needed
+    command: mnpw --errors --warn -- needrestart -p
+    frequency: daily
+
 # Hera and Odin are ElementaryOS releases based on Ubuntu Bionic and Focal
 # respectively.
 toolbox_podman_repo_base_url_mapping: