Skip to content

Instantly share code, notes, and snippets.

@huksley
Last active July 24, 2025 09:57
Show Gist options
  • Save huksley/f083691cb061ca50013bff5f1753934a to your computer and use it in GitHub Desktop.
Save huksley/f083691cb061ca50013bff5f1753934a to your computer and use it in GitHub Desktop.
Example of NodeJS which works with SystemD notify protocol
const { DgramSocket } = require("node-unix-socket");
const http = require("node:http");
/**
* Implements notify mechanism for systemd services which created with systemd.
*
* See all kinds of messages which can be sent to systemd
* https://man.archlinux.org/man/sd_notify.3.en#WELL-KNOWN_ASSIGNMENTS
*
* @param {string} message - The message to send
* @returns {Promise<void>}
*/
const sdNotify = async message => {
const notifySocket = process.env.NOTIFY_SOCKET;
if (!notifySocket) {
return;
}
if (!message?.trim()) {
return;
}
return new Promise((resolve, reject) => {
const socket = new DgramSocket();
const buffer = Buffer.from(message);
socket.sendTo(
buffer,
0,
buffer.length,
notifySocket,
(/** @type {Error | undefined} */ cause) => {
if (cause) {
reject(new Error("Failed to send systemd notify: " + message, { cause }));
} else {
resolve(undefined);
}
}
);
});
};
sdNotify("STATUS=Starting");
sdNotify("MAINPID=" + process.pid);
const server = http.createServer(function (req, res) {
res.writeHead(200, {
"Content-Type": "text/plain"
});
res.end("OK");
});
const main = async () => {
await sdNotify("READY=1");
await sdNotify("STATUS=Running");
server.listen(process.env.PORT ? parseInt(process.env.PORT, 10) : 8080);
}
process.on("SIGINT", async () => {
await sdNotify("STOPPING=1");
server.close();
process.exit(1);
});
process.on("SIGTERM", async () => {
await sdNotify("STOPPING=1");
server.close();
process.exit(0);
});
main();
[Unit]
Description=App
After=network.target
# Limit 5 restarts
StartLimitIntervalSec=1h
StartLimitBurst=5
[Service]
Type=notify
WorkingDirectory=/home/ubuntu/app
ExecStart=/usr/bin/env node app.js
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=app
{
"name": "app",
"version": "0.1.1",
"license": "MIT",
"private": false,
"repository": "https://gist.github.com/huksley/f083691cb061ca50013bff5f1753934a/",
"main": "app.js",
"dependencies": {
"node-unix-socket": "^0.2.7"
}
}
@huksley
Copy link
Author

huksley commented Jul 24, 2025

sudo cp app.service /etc/systemd/system/app.service
sudo systemctl daemon-reload
sudo systemctl reset-failed app
sudo systemctl start app
sudo systemctl restart app
sudo systemctl status app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment