Webhooks คืออะไร?
Webhook เป็นวิธีการสื่อสารจากระบบหนึ่ง (GitHub/GitLab) ไปยังแอปพลิเคชันของคุณ เมื่อมีเหตุการณ์เกิดขึ้น เช่น Push Code หรือ Merge Request ในแง่ของการพัฒนาบน ผู้ให้บริการโฮสติ้ง Cloud VPS หรือ Cloud Hosting ของเรา Webhooks เป็นเครื่องมือที่สำคัญในการสร้าง CI/CD Pipeline อัตโนมัติ ทำให้การ Deploy เป็นไปอย่างรวดเร็วและมีประสิทธิภาพ
วิธีการทำงานของ Webhooks
- ผู้ใช้ Push Code ไปยัง GitHub/GitLab
- GitHub/GitLab ส่ง HTTP Request ไปยัง URL ที่คุณลงทะเบียน
- Webhook Receiver ของคุณรับข้อมูลและตรวจสอบ Signature
- ดำเนินการ Deploy หรือ Action อื่นๆ โดยอัตโนมัติ
- ส่งคำตอบกลับไปยัง GitHub/GitLab
ตั้งค่า Webhook ใน GitHub
ขั้นตอน:
- ไปที่ Settings > Webhooks
- คลิก Add webhook
- ใส่ Payload URL (เช่น https://example.com/webhook/github)
- เลือก Content type เป็น application/json
- เลือก Events (Push, Pull Request, Release เป็นต้น)
- เปิด Active
- บันทึก
ตั้งค่า Webhook ใน GitLab
- ไปที่ Settings > Integrations > Webhooks
- ใส่ URL ของ Webhook Receiver
- เลือก Trigger Events (Push events, Merge requests, Tag push events)
- เพิ่ม Secret Token เพื่อความปลอดภัย
- คลิก Add webhook
สร้าง Webhook Receiver (Node.js)
const express = require('express');
const { execSync } = require('child_process');
const crypto = require('crypto');
const app = express();
app.use(express.json());
app.use(express.raw({ type: 'application/json' }));
function verifySignature(req, secret) {
const signature = req.headers['x-hub-signature-256'];
if (!signature) return false;
const body = req.rawBody || JSON.stringify(req.body);
const hash = crypto.createHmac('sha256', secret)
.update(body)
.digest('hex');
return `sha256=${hash}` === signature;
}
app.post('/webhook/github', (req, res) => {
if (!verifySignature(req, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Unauthorized');
}
const event = req.headers['x-github-event'];
const payload = req.body;
if (event === 'push') {
console.log('Received push event from:', payload.repository.name);
try {
const deployDir = process.env.DEPLOY_DIR || '/var/www/app';
execSync(`cd ${deployDir} && git fetch origin && git checkout ${payload.ref} && npm install && npm run build`, {
stdio: 'inherit'
});
console.log('Deploy successful for:', payload.ref);
res.status(200).send('Deploy successful');
} catch (error) {
console.error('Deploy failed:', error.message);
res.status(500).send('Deploy failed: ' + error.message);
}
} else if (event === 'pull_request') {
console.log('Received PR event:', payload.action);
res.status(200).send('PR event processed');
} else {
res.status(200).send('Event received but no action taken');
}
});
app.listen(3000, () => {
console.log('Webhook receiver running on port 3000');
console.log('Listening for GitHub webhooks...');
});
Webhook Receiver ด้วย PHP
<?php
// webhook-handler.php
$secret = $_ENV['WEBHOOK_SECRET'] ?? '';
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '';
// ตรวจสอบ Signature
if ($secret) {
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
die('Unauthorized');
}
}
$event = $_SERVER['HTTP_X_GITHUB_EVENT'] ?? '';
$data = json_decode($payload, true);
if ($event === 'push') {
error_log("Received push event to: " . $data['ref']);
$deploy_dir = $_ENV['DEPLOY_DIR'] ?? '/var/www/app';
$output = shell_exec("cd {$deploy_dir} && git fetch origin && git checkout {$data['ref']} && npm install && npm run build 2>&1");
error_log($output);
echo "Deploy successful";
} else {
echo "Event: $event processed";
}
?>
ความปลอดภัย Webhooks
- ตั้งค่า Secret Token และตรวจสอบ Signature ทุกครั้ง
- ใช้ HTTPS เสมอ เพราะข้อมูล Webhook ระบาย payload ของ code
- จำกัด IP addresses หากเป็นไปได้ (GitHub IP ranges)
- ตรวจสอบประเภท Event ที่ได้รับเพื่อหลีกเลี่ยงการดำเนินการที่ไม่จำเป็น
- จำกัดสิทธิ์ของ Deploy User ให้มีเฉพาะสิ่งที่จำเป็น
- บันทึก Log ของ Webhook Events ทั้งหมด
- ตั้งเวลา Timeout สำหรับการดำเนินการ Deploy
ตัวอย่างการตรวจสอบ Signature (GitHub)
const crypto = require('crypto');
function verifyGitHubSignature(req, secret) {
const signature = req.headers['x-hub-signature-256'];
const body = req.rawBody; // เก็บ raw body ก่อนแปลง JSON
if (!signature) {
console.warn('No signature found in request headers');
return false;
}
const hash = crypto.createHmac('sha256', secret)
.update(body)
.digest('hex');
const expectedSignature = `sha256=${hash}`;
const isValid = crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
return isValid;
}
app.post('/webhook/github', (req, res) => {
if (!verifyGitHubSignature(req, process.env.WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Unauthorized' });
}
// Deploy logic here
res.json({ success: true, message: 'Webhook verified' });
});
บูรณาการกับ Auto Deploy
การใช้ Webhooks ร่วมกับ Auto Deploy บน VPS ทำให้คุณสามารถสร้าง CI/CD Pipeline ที่สมบูรณ์ นอกจากนี้คุณสามารถศึกษาเพิ่มเติมเกี่ยวกับ GitHub Actions สำหรับ CI/CD และ การตั้งค่า Git Auto Deploy ด้วย SSH เพื่อสร้างระบบ Deploy ที่เข้มแข็งยิ่งขึ้น
Webhook ใน GitLab CI/CD
GitLab มี GitLab CI/CD Pipeline ที่รองรับ Webhooks อย่างเต็มที่ ซึ่งสามารถใช้งานได้บน Cloud VPS ของ ผู้ให้บริการโฮสติ้ง โดยไม่ต้องการ Configuration เพิ่มเติมมากมาย
การตรวจสอบและ Debugging
- ใน GitHub ให้ไปที่ Settings > Webhooks แล้วดู Recent Deliveries
- ตรวจสอบ Status Code และ Response Body
- ดู Request/Response Headers
- เปิด Debug Mode ในแอปพลิเคชันของคุณ
สรุป
Webhooks เป็นวิธีที่มีประสิทธิภาพและความปลอดภัยสูงในการสร้าง Auto Deploy Pipeline ที่ตอบสนองต่อการเปลี่ยนแปลงของ Code ในเวลาจริง ด้วยการตั้งค่า Signature Verification ที่ถูกต้อง คุณสามารถรับประกันความปลอดภัยของระบบ Deploy ของคุณได้
