Last active
July 24, 2025 09:57
-
-
Save huksley/f083691cb061ca50013bff5f1753934a to your computer and use it in GitHub Desktop.
Example of NodeJS which works with SystemD notify protocol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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