diff --git a/package/utils/system-notification/Makefile b/package/utils/system-notification/Makefile
new file mode 100644
index 0000000000..8dcbc190e6
--- /dev/null
+++ b/package/utils/system-notification/Makefile
@@ -0,0 +1,81 @@
+#
+# Copyright (C) 2021 TDT AG <development@tdt.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=system-notification
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Florian Eckert <fe@dev.tdt.de>
+PKG_LICENSE:=GPL-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/system-notification
+  SECTION:=base
+  CATEGORY:=Base system
+  TITLE:=System notification
+endef
+
+define Package/system-notification/description
+  This package provides a ubus backend that can be used to save system
+  notification. The notifications are not persistent. They are lost after
+  every reboot.
+
+  The following ubus methods are available:
+
+  add:
+  The <add> command adds a notification to the ubus backend.
+  ubus call system.notification add '{"title":"<string>","description":"<description>"}'
+  In addition, the following json string could be optional set.
+  * url: {"url": "<string>"} Additional information are available at this extrenal URL.
+  * opkg: {"package": "<string>"} Package can be updated.
+
+  remove:
+  The <remove> command removes a notification from the ubus backend.
+  ubus call system.notification remove '{"uuid": "<string>"}'
+
+  list:
+  The <list> command dumps all staged notification from the ubus backend.
+  ubus call system.notification list
+
+  flush:
+  The <flush> command removes all stage notification from the ubus backend.
+  ubus call system.notification flush
+endef
+
+define Build/Compile
+endef
+
+define Package/system-notification/postinst
+#!/bin/sh
+if [ -z "$${IPKG_INSTROOT}" ] && [ -x /etc/init.d/rpcd ]; then
+	/etc/init.d/rpcd restart
+fi
+exit 0
+endef
+
+define Package/system-notification/postrm
+#!/bin/sh
+if [ -z "$${IPKG_INSTROOT}" ] && [ -x /etc/init.d/rpcd ]; then
+	/etc/init.d/rpcd restart
+fi
+exit 0
+endef
+
+define Package/system-notification/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) ./files/usr/bin/system-notification \
+		$(1)/usr/bin/system-notification
+
+	$(INSTALL_DIR) $(1)/usr/libexec/rpcd
+	$(INSTALL_BIN) ./files/usr/libexec/rpcd/system.notification \
+		$(1)/usr/libexec/rpcd/
+endef
+
+$(eval $(call BuildPackage,system-notification))
diff --git a/package/utils/system-notification/files/usr/bin/system-notification b/package/utils/system-notification/files/usr/bin/system-notification
new file mode 100644
index 0000000000..7a60985eaf
--- /dev/null
+++ b/package/utils/system-notification/files/usr/bin/system-notification
@@ -0,0 +1,105 @@
+#!/bin/sh
+# Copyright (C) 2021 TDT AG <development@tdt.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
+#
+
+. /usr/share/libubox/jshn.sh
+
+remove() {
+	local uuid="$1"
+
+	json_init
+	json_add_string "uuid" "$uuid"
+	ubus call system.notification remove "$(json_dump)"
+	json_cleanup
+}
+
+list() {
+	local title description uuid timestamp
+
+	json_init
+	json_load "$(ubus call system.notification list)"
+	json_select "messages" 1>/dev/null 2>&1
+	[ $? -eq 0 ] || {
+		echo "No notifications are available"
+		return
+	}
+
+	json_get_keys notifications
+	for notification in $notifications; do
+		json_select "$notification"
+		json_get_vars title description uuid timestamp
+
+		echo "$title"
+		echo ""
+		echo "$description"
+
+		json_select "actions" 1>/dev/null 2>&1
+		if [ $? -eq 0 ]; then
+			json_get_keys actions
+			for action in $actions; do
+				json_select "$action"
+				local action
+				json_get_var entry action
+				[ "$entry" = "link" ] && {
+					local url
+					json_get_var url url
+					echo "- Check $url for more information"
+				}
+
+				[ "$entry" = "opkg" ] && {
+					local package
+					json_get_var package package
+					echo "- To upgrade, execute \"opkg upgrade $package\""
+				}
+				json_select ..
+			done
+			json_select ..
+		fi
+
+		local dstring
+		echo ""
+		dstring="$(date +"%Y-%m-%d %H:%M:%S" -d "@${timestamp}")"
+		echo "date: $dstring"
+		echo "uuid: $uuid"
+		echo "---"
+		json_select ..
+	done
+	json_select ..
+}
+
+usage() {
+	local msg="$1"
+
+	if [ -n "$msg" ]; then
+		echo "$msg"
+		echo ""
+	fi
+
+	echo "Usage: $(basename "$0") <command>"
+	echo ""
+	echo "commmand:"
+	echo ""
+	echo "remove <uuid>: Remove notification"
+	echo "list         : Show notification"
+}
+
+main() {
+	cmd="$1"
+	uuid="$2"
+
+	case "$cmd" in
+		remove)
+			remove "$uuid"
+			;;
+		list)
+			list
+			;;
+		*)
+			usage "Command not supported"
+	esac
+}
+
+main "$@"
diff --git a/package/utils/system-notification/files/usr/libexec/rpcd/system.notification b/package/utils/system-notification/files/usr/libexec/rpcd/system.notification
new file mode 100644
index 0000000000..aa32b967a1
--- /dev/null
+++ b/package/utils/system-notification/files/usr/libexec/rpcd/system.notification
@@ -0,0 +1,220 @@
+#!/bin/sh
+#
+# Copyright (C) 2021 TDT AG <development@tdt.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
+#
+
+. /usr/share/libubox/jshn.sh
+
+MESSAGE_DIR="/tmp/notification/messages.d"
+MESSAGE_MAX=20
+
+get_uuid() {
+	local file="$1"
+	local uuid
+
+	uuid="${file##*/}"
+
+	echo "${uuid%*.json}"
+}
+
+gen_uuid() {
+	cat /proc/sys/kernel/random/uuid
+}
+
+list() {
+	json_init
+
+	json_add_object "add"
+	json_add_string "title"
+	json_add_string "description"
+	json_add_string "url"
+	json_add_string "package"
+	json_close_object
+
+	json_add_object "remove"
+	json_add_string "uuid"
+	json_close_object
+
+	json_add_object "list"
+	json_close_object
+
+	json_add_object "flush"
+	json_close_object
+
+	json_dump
+}
+
+notification_add() {
+	local title="$1"
+	local description="$2"
+	local url="$3"
+	local package="$4"
+
+	local timestamp uuid
+
+	local code=-1
+	local msg="Unable to add notification"
+
+	timestamp="$(date +%s)"
+
+	uuid="$(gen_uuid)"
+	if [ -z "$uuid" ]; then
+		json_init
+		json_add_int "code" "-2"
+		json_add_string "message" "Unable to get uuid"
+		json_dump
+		return
+	fi
+
+	json_init
+	json_add_string title "$title"
+	json_add_string description "$description"
+	json_add_int timestamp "$timestamp"
+	[ -z "$url" ] || json_add_string "url" "$url"
+	[ -z "$package" ] || json_add_string "package" "$package"
+	json_dump > "${MESSAGE_DIR}/${uuid}.json"
+
+	if [ -f "${MESSAGE_DIR}/${uuid}.json" ]; then
+		code=0
+		msg="Notification added"
+	fi
+
+	local count=0
+	for file in "${MESSAGE_DIR}"/*.json; do
+		count=$((count + 1))
+		if [ "$count" -gt "$MESSAGE_MAX" ]; then
+			rm "${MESSAGE_DIR}/${file}"
+		fi
+	done
+
+	json_init
+	json_add_int "code" "$code"
+	json_add_string "message" "$msg"
+	json_dump
+}
+
+notification_remove() {
+	local uuid="$1"
+
+	local code=-1
+	local msg="Notification not found"
+
+
+	if [ -f "${MESSAGE_DIR}/${uuid}.json" ]; then
+		rm "${MESSAGE_DIR}/${uuid}.json"
+		code=0
+		msg="Notication removed"
+	fi
+
+	json_init
+	json_add_int "code" "$code"
+	json_add_string "message" "$msg"
+	json_dump
+}
+
+notification_list() {
+	local uuid title description timestamp url package
+
+	json_init
+	if [ -n "$(ls -A "$MESSAGE_DIR")" ]; then
+		json_add_array "messages"
+		for entry in "${MESSAGE_DIR}"/*.json; do
+			uuid="$(get_uuid "$entry")"
+
+			json_set_namespace dump old_cb
+			json_load_file "$entry"
+			json_get_vars title description timestamp url package
+			json_cleanup
+			json_set_namespace "$old_cb"
+
+			json_add_object ""
+			json_add_string uuid "$uuid"
+			json_add_string title "$title"
+			json_add_string description "$description"
+			json_add_int timestamp "$timestamp"
+			json_add_array actions
+			json_add_object
+			json_add_string action dismiss
+			json_close_object
+			[ -z "$url" ] || {
+				json_add_object
+				json_add_string action link
+				json_add_string url "$url"
+				json_close_object
+			}
+			[ -z "$package" ] || {
+				json_add_object
+				json_add_string action opkg
+				json_add_string package "$package"
+				json_close_object
+			}
+			json_close_array
+			json_close_object
+		done
+		json_close_array
+	fi
+	json_dump
+}
+
+notification_flush() {
+	local code=0
+	local msg="All notifications flushed"
+
+	rm "$MESSAGE_DIR"/*.json
+
+	json_init
+	json_add_int "code" "$code"
+	json_add_string "message" "$msg"
+	json_dump
+}
+
+call() {
+	local method="$1"
+
+	local title description url package uuid
+
+	case "$method" in
+		add)
+			read -r input;
+			json_load "${input}"
+			json_get_var title title
+			json_get_var description description
+			json_get_var url url
+			json_get_var package package
+			notification_add "$title" "$description" "$url" "$package"
+		;;
+		remove)
+			read -r input;
+			json_load "${input}"
+			json_get_var uuid uuid
+			notification_remove "$uuid"
+		;;
+		list)
+			notification_list
+		;;
+		flush)
+			notification_flush
+		;;
+	esac
+}
+
+main() {
+	local path="$1"
+	local method="$2"
+
+	mkdir -p "${MESSAGE_DIR}"
+
+	case "$path" in
+		list)
+			list
+		;;
+		call)
+			call "$method"
+		;;
+	esac
+}
+
+main "$@"
