diff --git a/src/knot/common/systemd.c b/src/knot/common/systemd.c
index c3ee68f362bc121d3877f118142091ff13e726e2..0c37a0740ce1d499b111990f3ee0c9a478b1b8dc 100644
--- a/src/knot/common/systemd.c
+++ b/src/knot/common/systemd.c
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -14,6 +14,7 @@
     along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -82,3 +83,58 @@ void systemd_stopping_notify(void)
 	sd_notify(0, "STOPPING=1\nSTATUS=");
 #endif
 }
+
+#define DBUS_NAME "cz.nic.knotd"
+
+static sd_bus *_dbus = NULL;
+
+int systemd_dbus_open(void)
+{
+#ifdef ENABLE_SYSTEMD
+	if (_dbus != NULL) {
+		return KNOT_EOK;
+	}
+
+	int ret = 0;
+	if ((ret = sd_bus_open_system(&_dbus)) < 0) {
+		return ret;
+	}
+
+	/* Take a well-known service name so that clients can find us */
+	if ((ret = sd_bus_request_name(_dbus, DBUS_NAME, 0)) < 0) {
+		systemd_dbus_close();
+		return ret;
+	}
+#endif
+	return KNOT_EOK;
+}
+
+void systemd_dbus_close(void)
+{
+#ifdef ENABLE_SYSTEMD
+	_dbus = sd_bus_unref(_dbus);
+#endif
+}
+
+static int emit_generic_event(const char * event, const char *types, ...) {
+	int ret;
+	if (_dbus == NULL) {
+		return KNOT_EOK;
+	}
+#ifdef ENABLE_SYSTEMD
+	va_list args;
+	va_start(args, types);
+	if ((ret = sd_bus_emit_signalv(_dbus, "/cz/nic/knotd", DBUS_NAME".events", event, types, args)) < 0) {
+		va_end(args);
+		return ret;
+	}
+	va_end(args);
+	return KNOT_EOK;
+#endif
+	return KNOT_ENOTSUP;
+}
+
+int systemd_dbus_emit_xfr_done(unsigned char *zone)
+{
+	return emit_generic_event("On_XFR_Done", "s", zone);
+}
diff --git a/src/knot/common/systemd.h b/src/knot/common/systemd.h
index efa4044175f4fea2eac7c58d23b8b528c402f7a6..d3e31d1bad0737e3fe0eefc8c41d098d1559cd05 100644
--- a/src/knot/common/systemd.h
+++ b/src/knot/common/systemd.h
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -46,3 +46,29 @@ void systemd_reloading_notify(void);
  * \brief Notify systemd about service is stopping.
  */
 void systemd_stopping_notify(void);
+
+#ifdef ENABLE_SYSTEMD
+#include <systemd/sd-bus.h>
+#else
+#define sd_bus void
+#endif
+
+/*!
+ * \brief Creates unique D-Bus sender reference (common for whole process).
+ * \retval KNOT_EOK on successful create of reference.
+ * \retval Negative value on error.
+ */
+int systemd_dbus_open(void);
+
+/*!
+ * \brief Closes D-Bus.
+ */
+void systemd_dbus_close(void);
+
+/*!
+ * \brief Emit event signal in specific format.
+ * \param zone Zone name.
+ * \retval KNOT_EOK on successful send.
+ * \retval Negative value on error.
+ */
+int systemd_dbus_emit_xfr_done(unsigned char *zone);
diff --git a/src/utils/knotd/main.c b/src/utils/knotd/main.c
index a8a14777c3cd8efbd49d31cb91b576c9e2027212..2ebc56fd2dc5094af2b83c2298902e92c81629f7 100644
--- a/src/utils/knotd/main.c
+++ b/src/utils/knotd/main.c
@@ -466,9 +466,14 @@ int main(int argc, char **argv)
 		log_levels_add(LOG_TARGET_STDOUT, LOG_SOURCE_ANY, LOG_MASK(LOG_DEBUG));
 	}
 
+	if (systemd_dbus_open() != KNOT_EOK) {
+		log_warning("failed to open system dbus, check the permissions");
+	}
+
 	/* Set up the configuration */
 	int ret = set_config(confdb, config, max_conf_size);
 	if (ret != KNOT_EOK) {
+		systemd_dbus_close();
 		log_close();
 		return EXIT_FAILURE;
 	}
@@ -482,6 +487,7 @@ int main(int argc, char **argv)
 	if (ret != KNOT_EOK) {
 		log_fatal("failed to initialize server (%s)", knot_strerror(ret));
 		conf_free(conf());
+		systemd_dbus_close();
 		log_close();
 		return EXIT_FAILURE;
 	}
@@ -494,6 +500,7 @@ int main(int argc, char **argv)
 		server_wait(&server);
 		server_deinit(&server);
 		conf_free(conf());
+		systemd_dbus_close();
 		log_close();
 		return EXIT_FAILURE;
 	}
@@ -507,6 +514,7 @@ int main(int argc, char **argv)
 		server_wait(&server);
 		server_deinit(&server);
 		conf_free(conf());
+		systemd_dbus_close();
 		log_close();
 		return EXIT_FAILURE;
 	}
@@ -524,6 +532,7 @@ int main(int argc, char **argv)
 		server_wait(&server);
 		server_deinit(&server);
 		conf_free(conf());
+		systemd_dbus_close();
 		log_close();
 		return EXIT_FAILURE;
 	}
@@ -562,6 +571,7 @@ int main(int argc, char **argv)
 		server_deinit(&server);
 		rcu_unregister_thread();
 		pid_cleanup();
+		systemd_dbus_close();
 		log_close();
 		conf_free(conf());
 		return EXIT_FAILURE;
@@ -591,6 +601,8 @@ int main(int argc, char **argv)
 	/* Unhook from RCU. */
 	rcu_unregister_thread();
 
+	systemd_dbus_close();
+
 	log_info("shutting down");
 	log_close();