دیپلوی خودکار پروژه با Git Hook (Push-to-Deploy) روی سرور مجازی و اختصاصی
برای پروژههای کوچک و متوسط، راهاندازی یک ابزار CI/CD کامل مثل Jenkins یا GitLab CI گاهی بیش از حد لازم است. اگر فقط میخواهید با یک git push کد روی سرور آپدیت شود، یک راه بسیار سادهتر وجود دارد: استفاده از Git hook به نام post-receive. این روش که به آن Push-to-Deploy هم میگویند، بدون نصب هیچ ابزار اضافهای روی سرور مجازی یا اختصاصی شما کار میکند.
در این مقاله مرحله به مرحله یاد میگیرید چطور یک ریپازیتوری bare روی سرور بسازید، یک post-receive hook بنویسید و با یک push ساده پروژه را دیپلوی کنید.
دیپلوی خودکار با Git Hook چطور کار میکند؟
ایده اصلی این است که سرور، بهجای یک ریپازیتوری معمولی، یک ریپازیتوری bare دارد. ریپازیتوری bare فایلهای پروژه را نشان نمیدهد، فقط تاریخچه و آبجکتهای گیت را نگه میدارد و برای دریافت push طراحی شده است.
وقتی از کامپیوتر خودتان به این ریپازیتوری push میکنید، گیت بهصورت خودکار اسکریپتی به نام post-receive را که داخل پوشه hooks/ ریپازیتوری قرار دارد اجرا میکند. داخل همین اسکریپت میتوانید هر کاری بخواهید انجام دهید: چکاوت کردن آخرین کد به یک پوشه مشخص، نصب dependencyها، ریاستارت کردن سرویس و غیره.
نتیجه اینکه کل فرآیند دیپلوی به یک دستور خلاصه میشود:
git push production main

اگر به جای یک ریپازیتوری bare ساده، به یک سرور گیت کامل با رابط وب و مدیریت چند پروژه نیاز دارید، راهاندازی سرور گیت اختصاصی با Gitea هم میتواند جایگزین مناسبی باشد؛ همان ایده post-receive hook روی آن هم قابل استفاده است.
پیشنیازها
- یک سرور مجازی یا اختصاصی با دسترسی SSH (کافی است Git روی آن نصب باشد)
- یک کاربر مشخص برای دیپلوی (توصیه میشود root نباشد)
- پروژهای که محلی روی آن با Git کار میکنید
مرحله ۱: ساخت ریپازیتوری bare روی سرور
ابتدا با SSH به سرور وصل شوید و یک پوشه برای نگهداری ریپازیتوریهای bare بسازید:
ssh deploy@your-server-ip
mkdir -p /var/repo
cd /var/repo
git init --bare myproject.git
دستور git init --bare یک ریپازیتوری بدون working directory میسازد؛ یعنی فایلهای پروژه داخل همین پوشه دیده نمیشوند، فقط تاریخچه commitها ذخیره میشود.
در کنار آن یک پوشه جدا هم برای فایلهای واقعی پروژه (همان چیزی که سرویس شما از روی آن اجرا میشود) میسازیم:
mkdir -p /var/www/myproject
مرحله ۲: نوشتن post-receive hook
داخل پوشه ریپازیتوری bare، یک فایل hooks آماده (hooks/post-receive.sample) وجود دارد. فایل جدیدی به نام post-receive (بدون پسوند .sample) در همان مسیر بسازید:
nano /var/repo/myproject.git/hooks/post-receive
محتوای زیر را در آن قرار دهید:
#!/bin/bash
set -e
TARGET="/var/www/myproject"
GIT_DIR="/var/repo/myproject.git"
BRANCH="main"
while read oldrev newrev ref
do
if [ "$ref" = "refs/heads/$BRANCH" ]; then
echo "در حال دیپلوی شاخه $BRANCH..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
cd $TARGET
npm install --production
pm2 restart myproject
echo "دیپلوی با موفقیت انجام شد."
fi
done
چند نکته درباره این اسکریپت:
git --work-tree ... checkout -fهمان چیزی است که فایلهای پروژه را از ریپازیتوری bare به پوشه واقعی (/var/www/myproject) منتقل میکند.- خطوط
npm installوpm2 restartرا متناسب با استک پروژه خودتان عوض کنید؛ برای یک پروژه PHP ممکن است بهجای این دو خطcomposer installو ریاستارت PHP-FPM لازم باشد. اگر هنوز Node.js و npm روی سرور نصب نیست، اول آن را نصب کنید (نمونه برای CentOS: نصب Node.js و npm در CentOS 7). set -eباعث میشود اگر یکی از دستورات با خطا مواجه شد، اسکریپت متوقف شود و دیپلوی ناقص بهعنوان موفق گزارش نشود.
در نهایت باید فایل قابل اجرا شود:
chmod +x /var/repo/myproject.git/hooks/post-receive
مرحله ۳: اضافه کردن سرور بهعنوان remote
از کامپیوتر محلی خودتان، داخل پوشه پروژه، یک remote جدید اضافه کنید:
git remote add production deploy@your-server-ip:/var/repo/myproject.git
مرحله ۴: تست دیپلوی
همین الان میتوانید اولین push را بزنید:
git push production main
اگر همه چیز درست باشد، خروجی مشابه زیر را روی ترمینال خودتان میبینید (همان چیزی که داخل post-receive با echo چاپ کردهاید):
در حال دیپلوی شاخه main...
دیپلوی با موفقیت انجام شد.
از این به بعد، هر بار که روی شاخه main به سرور production push کنید، کد بهصورت خودکار آپدیت و سرویس ریاستارت میشود.
نکات امنیتی
چند نکته قبل از استفاده از این روش روی محیط عملیاتی را در نظر بگیرید:
- بهجای رمز عبور، از کلید SSH برای اتصال به کاربر دیپلوی استفاده کنید (راهنمای کاملتر: امنسازی دسترسی SSH به سرور لینوکس).
- کاربر دیپلوی را به حداقل دسترسی لازم محدود کنید؛ نیازی نیست این کاربر دسترسی root داشته باشد.
- اگر چند نفر روی پروژه کار میکنند، فقط افرادی که باید دیپلوی کنند را به سرور دسترسی بدهید، نه کل تیم.
- فایل
post-receiveروی سرور قرار دارد و قابل ویرایش توسط هرکسی با دسترسی SSH است؛ این فایل را هم مثل کد پروژه جدی بگیرید و دسترسی نوشتن روی آن را محدود کنید.
مقایسه Push-to-Deploy با CI/CD کامل
قبل از انتخاب این روش، خوب است بدانید در کجا جایش هست و کجا نیست:
| ویژگی | Push-to-Deploy (Git Hook) | CI/CD کامل (Jenkins, GitLab CI) |
|---|---|---|
| زمان راهاندازی | چند دقیقه | چند ساعت تا چند روز |
| نیاز به سرویس اضافه | ندارد | دارد (runner، pipeline config) |
| اجرای تست خودکار | ندارد (باید خودتان داخل hook اضافه کنید) | پشتیبانی کامل |
| دیپلوی روی چند سرور | با اسکریپت دستی ممکن است | بهصورت built-in |
| مناسب برای | پروژههای کوچک و شخصی، MVP | پروژههای تیمی با چند محیط |
| قابلیت rollback | محدود، باید دستی مدیریت شود | معمولاً built-in |
برای یک پروژه شخصی یا یک MVP که روی یک سرور مجازی اجرا میشود، Git hook معمولاً کافی است. اگر تیم شما چند نفره است یا نیاز به تست خودکار و دیپلوی روی چند محیط (staging، production) دارید، سراغ یک ابزار CI/CD واقعی بروید؛ برای نمونه راهاندازی GitLab Runner خودمیزبان روی سرور مجازی و اختصاصی میتواند نقطه شروع خوبی باشد.
چه زمانی به این روش بسنده نکنید
اگر پروژه شما این موارد را دارد، بهتر است از یک ابزار CI/CD جدیتر استفاده کنید:
- اجرای تستهای خودکار قبل از دیپلوی
- دیپلوی همزمان روی چند سرور یا چند دیتاسنتر
- نیاز به rollback سریع در صورت خطا
- چند محیط مجزا (development، staging، production) با تنظیمات متفاوت
در این موارد، Git hook بهعنوان یک لایه اولیه خوب است اما جای یک pipeline واقعی را نمیگیرد.
جمعبندی
دیپلوی خودکار با Git hook یک راه سریع و بدون وابستگی اضافه برای آپدیت کردن پروژه با یک git push است. کافی است یک ریپازیتوری bare بسازید، یک اسکریپت post-receive بنویسید و remote سرور را به پروژه محلی اضافه کنید. این روش برای پروژههای کوچک، شخصی یا MVP روی یک سرور مجازی یا اختصاصی گزینه مناسبی است؛ وقتی پروژه بزرگتر شد، میتوانید همین زیرساخت را به یک pipeline کاملتر ارتقا دهید.
اگر هنوز سرور مناسبی برای اجرای این آموزش ندارید، میتوانید با یک سرور مجازی شروع کنید که منابع آن متناسب با رشد پروژه قابل افزایش است:




