خلاصه سریع: اگر کد پروژهتان روی GitHub است، میتوانید با GitHub Actions فرایند Deploy روی یک VPS لینوکسی را خودکار کنید. در این روش با هر Push به شاخه اصلی، Workflow اجرا میشود، تستها را انجام میدهد و سپس از طریق SSH به سرور متصل میشود تا نسخه جدید برنامه را دریافت و سرویس را Restart کند. نکته کلیدی این است که کلید SSH و اطلاعات حساس را داخل Repository قرار ندهید و از GitHub Secrets استفاده کنید.
GitHub Actions چیست و چه کمکی به Deploy روی VPS میکند؟
GitHub Actions سیستم اتوماسیون داخلی GitHub است که Workflowها را در پاسخ به رویدادهایی مثل Push، Pull Request یا اجرای دستی اجرا میکند. برای یک پروژه روی VPS، Workflow میتواند مراحل تست، Build و در نهایت استقرار را پشت سر هم انجام دهد.
بهجای اینکه بعد از هر تغییر دستی وارد سرور شوید، git pull بزنید و سرویس را Restart کنید، یک Workflow تکرارپذیر دارید که همان مراحل را با قواعد مشخص انجام میدهد. این دقیقاً جایی است که CI/CD از یک مفهوم نظری به یک فرایند عملی تبدیل میشود.
معماری ساده این روش
یک سناریوی متداول چهار بخش دارد:
- Repository در GitHub: کد و فایل Workflow در آن قرار دارد.
- GitHub Actions Runner: Jobهای تست و Deploy را اجرا میکند.
- SSH: کانال امن اتصال Runner به VPS است.
- VPS لینوکسی: برنامه، وبسرور یا Docker Compose روی آن اجرا میشود.
در این مدل، Secretهای اتصال مثل Host، Username و Private Key در بخش Secrets نگهداری میشوند و نباید بهصورت مستقیم داخل فایل YAML نوشته شوند.
پیشنیازها
برای اجرای این آموزش به یک Repository در GitHub، یک VPS لینوکسی با دسترسی SSH، یک کاربر Deploy و پروژهای که روی سرور قابل اجرا باشد نیاز دارید. اگر هنوز سرور ندارید، میتوانید پلنهای سرور مجازی وانسرور را متناسب با منابع موردنیاز پروژه بررسی کنید.
روی سرور بهتر است Deploy را با کاربر اختصاصی انجام دهید و تا جای ممکن از ورود مستقیم با root برای فرایند خودکار استفاده نکنید. همچنین فقط پورتهای ضروری را در فایروال باز نگه دارید.
مرحله اول: ساخت کاربر Deploy روی سرور
در Ubuntu میتوانید یک کاربر جداگانه بسازید:
sudo adduser deployسپس فقط دسترسیهایی را که پروژه واقعاً نیاز دارد به این کاربر بدهید. اصل مهم این است که Workflow نباید بیش از نیازش Permission داشته باشد.
اگر برنامه در مسیر /var/www/myapp قرار دارد، مالکیت و Permission آن مسیر را طوری تنظیم کنید که کاربر Deploy بتواند عملیات لازم را انجام دهد، بدون اینکه دسترسی گسترده غیرضروری بگیرد.
مرحله دوم: ساخت SSH Key مخصوص Deploy
برای اتوماسیون بهتر است یک کلید اختصاصی Deploy بسازید؛ یعنی از کلید شخصی روزمره خودتان استفاده نکنید.
روی سیستم امن خودتان:
ssh-keygen -t ed25519 -C "github-actions-deploy"Public Key را به فایل ~/.ssh/authorized_keys کاربر Deploy روی سرور اضافه کنید. Private Key باید محرمانه بماند و در مرحله بعد داخل GitHub Secret ذخیره شود.
مرحله سوم: تعریف GitHub Secrets
در Repository به Settings و سپس Secrets and variables مربوط به Actions بروید و Secretهای موردنیاز را بسازید. نامها میتوانند اینها باشند:
VPS_HOSTبرای IP یا Hostname سرورVPS_USERبرای نام کاربر DeployVPS_SSH_KEYبرای Private KeyVPS_PORTدر صورتی که SSH روی پورتی غیر از 22 است
Secretها را داخل کد Commit نکنید. GitHub Actions برای نگهداری اطلاعات حساس مکانیزم Secrets دارد و Workflow باید آنها را در زمان اجرا دریافت کند.
مرحله چهارم: ساخت Workflow
در Repository پوشه زیر را بسازید:
.github/workflows/و یک فایل مثل deploy.yml داخل آن قرار دهید. یک ساختار ساده میتواند با Push روی شاخه main اجرا شود:
name: Deploy to VPS
on:
push:
branches: ["main"]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: echo "Replace with your real test command"
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- name: Deploy over SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.VPS_SSH_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=accept-new
${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }}
'cd /var/www/myapp && git pull --ff-only && ./deploy.sh'
این مثال عمداً ساده است. در پروژه واقعی بهتر است Host Key سرور را از قبل Pin کنید و به جای اعتماد اولیه خودکار، Fingerprint مورد انتظار را کنترل کنید.
چرا Job تست باید قبل از Deploy اجرا شود؟
اگر Workflow مستقیماً هر Push را روی Production منتشر کند، یک خطای ساده میتواند سرویس را از دسترس خارج کند. با قرار دادن Job تست قبل از Deploy و استفاده از needs: test، مرحله استقرار فقط زمانی اجرا میشود که تستها موفق باشند.
بسته به پروژه، این مرحله میتواند شامل Unit Test، Lint، Build یا بررسی Configuration باشد. مقاله CI/CD و نقش آن در DevOps دید کلیتری درباره این زنجیره ارائه میدهد.
اسکریپت Deploy روی VPS بهتر از دستورهای طولانی داخل Workflow است
بهجای اینکه دهها دستور سروری را داخل YAML قرار دهید، یک اسکریپت مثل deploy.sh روی سرور یا در Repository نگهداری کنید. نمونه ساده:
#!/usr/bin/env bash
set -euo pipefail
cd /var/www/myapp
npm ci
npm run build
sudo systemctl restart myapp
مزیت این روش این است که منطق استقرار قابل تست و نگهداریتر میشود. برای PHP/Laravel ممکن است دستورات Composer، Migration کنترلشده و Restart سرویس PHP-FPM یا Queue Worker لازم باشد؛ برای Node.js نیز ممکن است systemd یا Process Manager استفاده شود.
Deploy پروژه Docker Compose با GitHub Actions
اگر برنامه با Docker Compose اجرا میشود، اسکریپت Deploy میتواند Imageهای جدید را Pull کند و استک را بهروزرسانی کند:
#!/usr/bin/env bash
set -euo pipefail
cd /opt/myapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
برای آشنایی با ساختار Compose، Volume، Network و نکات Production میتوانید مقاله Docker Compose چیست؟ را بخوانید.
امنیت SSH در GitHub Actions
چند نکته در Production اهمیت زیادی دارد:
- برای Deploy از کلید اختصاصی استفاده کنید.
- Private Key را فقط در Secret نگه دارید.
- کاربر Deploy را محدود کنید و از root مستقیم دوری کنید.
- Host Key سرور را Pin کنید تا خطر حمله Man-in-the-Middle کاهش یابد.
- اگر امکان دارد دسترسی SSH را با فایروال، VPN یا راهکارهای کنترل دسترسی محدودتر کنید.
- Secretهای Production را از Secretهای Staging جدا نگه دارید.
استفاده از GitHub Environments برای Production
برای پروژههای جدیتر، Environment جداگانهای با نام production تعریف کنید. این کار امکان جداسازی Secretهای Production و اعمال Protection Ruleها را فراهم میکند. در تیمها میتوان Deploy نهایی را به Approval دستی وابسته کرد تا هر Push بدون بررسی به Production نرود.
Rollback را قبل از اولین Deploy طراحی کنید
اتوماسیون Deploy بدون Rollback ناقص است. حداقل باید بدانید اگر نسخه جدید خراب بود چگونه به نسخه قبلی برمیگردید. چند راه رایج عبارتاند از نگهداری Releaseهای قبلی، استفاده از Image Tag نسخهدار در Docker، Deploy بر اساس Commit SHA و نگهداری Backup قبل از Migrationهای حساس.
از تگهایی مثل latest بهعنوان تنها مرجع نسخه Production استفاده نکنید. نسخهای که Deploy میشود باید قابل شناسایی و بازگشت باشد.
خطاهای رایج
Permission denied (publickey)
معمولاً Private Key اشتباه است، Public Key روی کاربر درست نصب نشده یا Permission فایلهای SSH مناسب نیست. روی سرور ~/.ssh و authorized_keys را بررسی کنید.
Host key verification failed
Runner نمیتواند هویت Host را تأیید کند. راه حرفهای این است که Host Key مورد انتظار را از قبل در known_hosts قرار دهید، نه اینکه بررسی Host Key را کاملاً غیرفعال کنید.
Workflow موفق است ولی برنامه بهروز نشده
مسیر پروژه، شاخه Git، Permission کاربر و خروجی اسکریپت Deploy را بررسی کنید. استفاده از set -euo pipefail کمک میکند اسکریپت در صورت خطا بیصدا ادامه ندهد.
Migration باعث Downtime شده است
Migrationهای دیتابیس را بخشی از استراتژی Deploy بدانید. تغییر Schema باید تا حد ممکن Backward-compatible باشد و قبل از عملیات پرریسک Backup معتبر داشته باشید.
چکلیست Production
- تستها قبل از Deploy اجرا میشوند.
- SSH Key اختصاصی و محدود است.
- Secretها داخل Git نیستند.
- Host Key سرور کنترل میشود.
- کاربر Deploy دسترسی حداقلی دارد.
- نسخه Deploy شده با Commit یا Tag مشخص است.
- Rollback از قبل تعریف شده است.
- Backup و مانیتورینگ بعد از Deploy وجود دارد.
سوالات متداول
آیا GitHub Actions میتواند مستقیم به VPS وصل شود؟
بله. یکی از روشهای رایج استفاده از SSH است. اطلاعات اتصال باید در Secrets نگهداری شوند و دسترسی کاربر Deploy محدود باشد.
آیا Private Key را داخل deploy.yml قرار دهیم؟
خیر. کلید خصوصی، Password، Token و سایر اطلاعات حساس نباید داخل Repository Commit شوند. آنها را در GitHub Secrets نگهداری کنید.
آیا هر Push باید مستقیماً روی Production Deploy شود؟
نه لزوماً. برای پروژههای حساس بهتر است تست، Environment Protection، Approval یا شاخه مخصوص Release داشته باشید.
برای Docker Compose هم میتوان از GitHub Actions استفاده کرد؟
بله. Workflow میتواند پس از اتصال SSH، دستورهایی مثل docker compose pull و docker compose up -d را اجرا کند. بهتر است Imageها نسخهدار باشند و Rollback طراحی شده باشد.
آیا GitHub Actions جایگزین ابزارهای کامل CD است؟
برای بسیاری از پروژههای کوچک و متوسط کاملاً کافی است، اما در معماریهای پیچیدهتر ممکن است ابزارهای تخصصی Deployment، GitOps یا Orchestration مناسبتر باشند.
جمعبندی
GitHub Actions میتواند Deploy دستی روی VPS را به یک فرایند تکرارپذیر تبدیل کند: کد Push میشود، تست اجرا میشود و در صورت موفقیت، مرحله استقرار از طریق SSH انجام میگیرد. بخش مهم کار خود YAML نیست؛ امنیت Secretها، محدود کردن کاربر Deploy، کنترل Host Key، نسخهبندی Release و داشتن Rollback است که این Workflow را برای Production قابل اتکا میکند.
منابع: GitHub Docs: Deploying with GitHub Actions، Docker Docs: Using secrets with GitHub Actions.

