# curl https://devtools.krishanchawla.com/raw/github-webhook-nodejs.txt GITHUB WEBHOOKS - NODE.JS Node.js Express and vanilla implementations for GitHub webhooks with signature verification Category: Git · Type: snippet Official docs: https://docs.github.com/en/webhooks ──────────────────────────────────────────────────────────── ## What is GitHub Webhooks? **GitHub Webhooks** allow you to receive real-time HTTP notifications when events occur in your repositories. This guide shows Node.js implementations using Express and vanilla HTTP with HMAC signature verification for secure automated deployments. --- ## 🟢 Node.js - Express Handler Express server for handling GitHub webhooks. ```js import crypto from "crypto"; import express from "express"; const app = express(); const SECRET = "your_secret"; app.use(express.raw({ type: "application/json" })); app.post("/webhook", (req, res) => { if (!verifySignature(req)) { return res.status(401).send("Invalid"); } const event = req.headers["x-github-event"]; if (event === "push") { require("child_process").exec("sh /path/to/deploy.sh"); } res.send("OK"); }); app.listen(3000); ``` ## 🔐 Node.js - Verify Signature Verify GitHub webhook signature in Node.js. ```js function verifySignature(req) { const signature = req.headers["x-hub-signature-256"]; const hmac = crypto.createHmac("sha256", SECRET); const digest = "sha256=" + hmac.update(req.body).digest("hex"); return signature === digest; } ``` **Install & Run:** ```bash npm install express node index.js # Production pm2 start index.js ``` ## Node.js - Vanilla (No Framework) HTTP server without Express framework. ```js import crypto from "crypto"; import http from "http"; const SECRET = "your_secret"; http.createServer((req, res) => { if (req.method !== "POST" || req.url !== "/webhook") { res.writeHead(404); return res.end("Not Found"); } let body = []; req.on("data", chunk => body.push(chunk)); req.on("end", () => { const payload = Buffer.concat(body).toString(); const signature = req.headers["x-hub-signature-256"]; if (!verifySignature(signature, payload)) { res.writeHead(401); return res.end("Invalid"); } if (req.headers["x-github-event"] === "push") { require("child_process").exec("sh /path/to/deploy.sh"); } res.end("OK"); }); }).listen(3001); ``` ## ✅ Node.js - Vanilla Verify Signature Signature verification for vanilla Node.js. ```js function verifySignature(signature, payload) { if (!signature) return false; const hmac = crypto.createHmac("sha256", SECRET); const digest = "sha256=" + hmac.update(payload).digest("hex"); return signature === digest; } ``` **Run:** ```bash # Development node server.js # Production pm2 start server.js ``` ## 📦 Package.json Required dependencies for Express version. ```json { "name": "github-webhook", "version": "1.0.0", "type": "module", "dependencies": { "express": "^4.18.0" } } ``` ## ⚙️ PM2 Setup Run with PM2 process manager for production. ```bash # Install PM2 npm install -g pm2 # Start application pm2 start index.js --name github-webhook # Auto-restart on boot pm2 startup pm2 save # Monitor pm2 logs github-webhook pm2 monit ``` ## 🔑 Environment Variables Store secret securely using environment variables. ```bash # .env file SECRET=your_webhook_secret_here PORT=3000 ``` ```js // Load environment variables import dotenv from 'dotenv'; dotenv.config(); const SECRET = process.env.SECRET; const PORT = process.env.PORT || 3000; ``` ## 🐳 Docker Deployment Containerize the Node.js webhook handler. ```dockerfile FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --production COPY . . EXPOSE 3000 CMD ["node", "index.js"] ``` Build and run: ```bash docker build -t github-webhook-node . docker run -p 3000:3000 -e SECRET=your_secret github-webhook-node ``` ## 🌐 Nginx Reverse Proxy Proxy webhook requests through Nginx. ```nginx server { listen 80; server_name webhook.example.com; location /webhook { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` ## 🔧 Systemd Service Run as a systemd service. Create `/etc/systemd/system/github-webhook.service`: ```ini [Unit] Description=GitHub Webhook Handler After=network.target [Service] Type=simple User=nodejs WorkingDirectory=/opt/webhook ExecStart=/usr/bin/node /opt/webhook/index.js Restart=on-failure Environment=SECRET=your_secret [Install] WantedBy=multi-user.target ``` Enable and start: ```bash sudo systemctl enable github-webhook sudo systemctl start github-webhook ``` ──────────────────────────────────────────────────────────── Full page: https://devtools.krishanchawla.com/devtools/github-webhook-nodejs More tools: https://devtools.krishanchawla.com