Deploy อัตโนมัติด้วย Git บน VPS ไม่ต้อง FTP อีกต่อไป
การ deploy ด้วย FTP หรือ copy ไฟล์ด้วยมือทุกครั้งเสียเวลาและเสี่ยงผิดพลาด ใช้ Git bare repository บน VPS ร่วมกับ post-receive hook เพื่อให้ git push ครั้งเดียว deploy ให้อัตโนมัติ
แนวคิด
- สร้าง bare repository บน VPS (
/var/repo/mysite.git) - เขียน hook
post-receiveให้ checkout ไฟล์ไปที่ web root - บนเครื่องตัวเอง:
git push vps main→ deploy ทันที
ขั้นที่ 1: ตั้งค่าบน VPS
# สร้าง user สำหรับ deploy (ถ้ายังไม่มี)
adduser deploy
usermod -aG www-data deploy
# สร้าง bare repo
mkdir -p /var/repo/mysite.git
cd /var/repo/mysite.git
git init --bare
ขั้นที่ 2: เขียน post-receive Hook
nano /var/repo/mysite.git/hooks/post-receive
#!/bin/bash
TARGET="/var/www/html/mysite"
GIT_DIR="/var/repo/mysite.git"
BRANCH="main"
while read oldrev newrev ref; do
if [[ $ref = refs/heads/$BRANCH ]]; then
echo "Deploying $BRANCH..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
echo "Done."
fi
done
chmod +x /var/repo/mysite.git/hooks/post-receive
ขั้นที่ 3: ตั้งค่า Permission
mkdir -p /var/www/html/mysite
chown -R deploy:www-data /var/www/html/mysite
chown -R deploy:deploy /var/repo/mysite.git
ขั้นที่ 4: เพิ่ม Remote บนเครื่องตัวเอง
# ใน project directory บนเครื่องตัวเอง
git remote add vps deploy@your-vps-ip:/var/repo/mysite.git
# Deploy ครั้งแรก
git push vps main
เพิ่ม Hook สำหรับ Restart Service
ถ้าแอปต้องการ restart หลัง deploy เพิ่มใน hook:
# ต่อท้ายใน post-receive หลัง checkout
systemctl restart php8.3-fpm
# หรือ
pm2 restart myapp
/home/deploy/.ssh/authorized_keys บน VPS เพื่อไม่ต้องพิมพ์รหัสผ่านทุกครั้งที่ pushทดสอบ workflow
# บนเครื่องตัวเอง
echo "test" >> README.md
git add README.md
git commit -m "test deploy"
git push vps main
# ดูว่า hook ทำงานและไฟล์ถูก copy ไป web root
สรุป
หลังตั้งค่าครั้งเดียว การ deploy ง่ายเหมือนพิมพ์ git push vps main ลดโอกาสผิดพลาดจากการ copy ไฟล์ และมี Git history เป็น audit trail ตลอดเวลา
ตรวจสอบว่า Deploy ทำงานถูกต้อง
# ดู output ที่ terminal หลัง git push
git push vps main
# ควรเห็น: "Deploying main..." และ "Done."
# ตรวจไฟล์ใน web root บน VPS
ls -la /var/www/html/mysite/
# ทดสอบว่าเว็บ response
curl -I https://example.com
exec > /tmp/deploy.log 2>&1 ที่บรรทัดแรกของ post-receive เพื่อ debug ง่ายขึ้น แล้วดูด้วย tail -f /tmp/deploy.logแก้ปัญหาที่พบบ่อย
Error: "Permission denied (publickey)" ตอน git push
SSH public key ยังไม่ได้เพิ่มบน VPS ตรวจสอบและเพิ่ม:
# บนเครื่องตัวเอง: copy public key
cat ~/.ssh/id_rsa.pub
# บน VPS: ใส่ใน authorized_keys ของ user deploy
mkdir -p /home/deploy/.ssh
nano /home/deploy/.ssh/authorized_keys
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh
Error: "remote: bash: post-receive: Permission denied"
ลืม chmod +x ให้ hook file:
chmod +x /var/repo/mysite.git/hooks/post-receive
ls -la /var/repo/mysite.git/hooks/post-receive
# ต้องเห็น -rwxr-xr-x
Error: ไฟล์ถูก push แต่ไม่ปรากฏใน web root
อาจเป็น branch name ไม่ตรง hook ใช้ main แต่ push ไป master:
# ดู branch ปัจจุบัน
git branch
# ถ้าชื่อ master ให้ rename
git branch -m master main
git push vps main
Error: hook รันแต่ไฟล์ไม่ถูก overwrite
ตรวจสิทธิ์ user deploy ต้องเขียนได้:
ls -la /var/www/html/ | grep mysite
chown -R deploy:www-data /var/www/html/mysite
Error: "error: src refspec main does not match any"
ยังไม่ได้ commit ใดๆ บนเครื่องตัวเอง ต้องมี commit ก่อนถึง push ได้:
git add .
git commit -m "initial commit"
git push vps main
คำถามที่พบบ่อย
จะ deploy หลาย project บน VPS เดียวกันได้ไหม?
ได้ สร้าง bare repo แยกกันได้เลย เช่น /var/repo/site1.git, /var/repo/site2.git แต่ละตัวมี hook และ target directory เป็นของตัวเอง
จะ rollback ไปเวอร์ชันก่อนหน้าได้ไหม?
ได้ เพราะ Git เก็บ history ครบ:
# revert แล้ว push ใหม่
git revert HEAD
git push vps main
Environment variable จัดการยังไง?
ไม่ควร commit .env ไฟล์เข้า repo ให้สร้างไฟล์ .env บน VPS โดยตรง แล้วเพิ่มใน .gitignore
ใช้กับ GitHub Actions แทน bare repo ได้ไหม?
ได้ แต่วิธี bare repo ทำงานได้เองโดยไม่ต้องพึ่ง third party และ push ครั้งเดียวถึง VPS เลย ไม่ผ่าน cloud