SSD Nodes Learn Hosting plans →
راهنماها Matt Connorتوسط Matt Connor

بهترین سرور Git خودمیزبان: مقایسه Forgejo، Gitea و cgit

برای راه اندازی سرور Git روی VPS با رم 1 GB کدام گزینه مناسب است؟ مقایسه مصرف رم در cgit، Forgejo، Gitea و GitLab به همراه بررسی نیازهای سخت افزاری هر سرویس برای میزبانی بهینه.

کدام سرور Git خودمیزبان (self-hosted) را باید اجرا کنید

یک سرور Git خودمیزبان تنها یک محصول خاص نیست و میزان RAM (حافظه دسترسی تصادفی) در VPS شما تعیین می‌کند که کدام نسخه از آن را می‌توانید داشته باشید. Git به هیچ daemon اختصاصی نیاز ندارد: یک مخزن bare به همراه یک حساب SSH (پوسته امن)، همین حالا هم روی کوچک‌ترین سروری که می‌توانید اجاره کنید، یک سرور فعال است. هر چیزی فراتر از این سطح، یک برنامه وب است که انتخاب می‌کنید در کنار آن اجرا شود و هر پله ارتقا، هزینه‌ای از نظر حافظه دارد که ممکن است یک VPS کوچک از عهده آن برنیاید.

چهار سطح وجود دارد. یک مخزن bare روی SSH، بدون اینکه هیچ سرویس اضافه‌ای در حال گوش دادن باشد. cgit، یک رابط وب سریع و فقط‌خواندنی بدون نیاز به دیتابیس. Forgejo یا Gitea، یک پلتفرم کامل با قابلیت مدیریت حساب‌ها، issueها و pull requestها که به چند صد مگابایت حافظه نیاز دارد. GitLab، که انتظار دارد سروری با چندین برابر ظرفیت گزینه‌های دیگر در اختیار داشته باشد.

بر اساس کاری که باید انجام دهید تصمیم بگیرید، سپس مقدار حافظه مورد نیاز را با پلنی که برای آن هزینه پرداخت می‌کنید، مطابقت دهید.

میزان رم مورد نیاز برای هر گزینه

تنها دو مورد از این پروژه‌ها عدد مشخصی برای سخت‌افزار منتشر کرده‌اند. ارقام منتشرشده را به عنوان حداقلِ مطلق در نظر بگیرید، نه یک تضمین؛ پس از راه‌اندازی نمونه خود، میزان مصرف را با systemd-cgtop یا ps -o rss= -C forgejo اندازه‌گیری کنید.

نمودارRAM the projects document, official docs, October 2026
داده‌های پشت این نمودار
[
  {
    "label": "Gitea, small team",
    "ram_gb": 1
  },
  {
    "label": "GitLab, memory constrained",
    "ram_gb": 8
  },
  {
    "label": "GitLab, single node baseline",
    "ram_gb": 16
  }
]

پروژه Gitea میزان 1 GB رم به همراه 2 هسته CPU را برای تیم‌ها و پروژه‌های کوچک کافی می‌داند و Raspberry Pi 3 را برای بارهای کاری سبک مناسب معرفی می‌کند. GitLab میزان 16 GB رم را به عنوان حداقلِ پایه برای نصب تک‌گره (single node) و 8 GB را به عنوان پایین‌ترین حد برای محیط‌هایی که در مستندات خود «محدود از نظر حافظه» نامیده، ذکر کرده است. Forgejo هیچ نیازمندی سخت‌افزاری منتشر نکرده است. از آنجا که این پروژه یک fork از Gitea است و رفتاری مشابه دارد، عدد اعلام‌شده برای Gitea نزدیک‌ترین راهنمای موجود برای شماست.

این موضوع در یک VPS با 1 GB رم به این معناست که: مخازن خام (bare repositories) و cgit بدون مشکل اجرا می‌شوند و فضای خالی باقی می‌ماند، زیرا هیچ‌کدام سرویس مقیم در حافظه ندارند. Forgejo یا Gitea اجرا خواهند شد و می‌توانند به یک تیم کوچک روی SQLite سرویس‌دهی کنند، اما چون شما دقیقاً روی حداقلِ اعلام‌شده هستید، PostgreSQL و CI (یکپارچه‌سازی مداوم) را روی آن سرور فعال نکنید. اگر رابط وب بدون نمایش خطا ناپدید شد، دستور sudo dmesg -T | grep -i oom را اجرا کنید و به دنبال خطی شبیه به Out of memory: Killed process 1181 (forgejo) بگردید؛ این یعنی قابلیت OOM Killer (قاتل کمبود حافظه) در هسته سیستم‌عامل، آن را متوقف کرده است. اجرای GitLab روی یک سرور 1 GB با تنظیمات نرم‌افزاری حل نمی‌شود؛ این برنامه روی چنین سیستمی اجرا نخواهد شد.

سطح 0: مخزن خام (bare) روی SSH

Git هیچ daemon شبکه‌ای ندارد که نیاز به راه‌اندازی داشته باشد. git push از طریق SSH، دستور git-receive-pack را در سمت مقصد به عنوان یک پردازش معمولی Unix اجرا می‌کند، بنابراین هر حسابی که بتوانید با یک کلید به آن دسترسی پیدا کنید، از قبل یک Git remote محسوب می‌شود. یک حساب کاربری برای مخازن بسازید و مخازن را خارج از دایرکتوری home آن نگه دارید، زیرا در Ubuntu 24.04 دایرکتوری‌های home جدید با مجوز 0750 ایجاد می‌شوند و یک رابط وب که بعداً اضافه شود، نمی‌تواند محتویات آن را بخواند.

sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' \
  --group --disabled-password --home /home/git git
sudo install -d -m 0755 -o git -g git /srv/git
sudo -u git git init --bare /srv/git/project.git

--bare یک مخزن بدون working copy ایجاد می‌کند که همان چیزی است که یک سرور باید داشته باشد. push کردن به مخزنی که دارای working copy است با خطای refusing to update checked out branch: refs/heads/main رد می‌شود و این رایج‌ترین اشتباه در این سطح است.

حالا به حساب کاربری یک کلید بدهید و آن را clone کنید.

sudo -u git install -d -m 700 /home/git/.ssh
sudo -u git tee -a /home/git/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptop
EOF
sudo -u git chmod 600 /home/git/.ssh/authorized_keys
git remote add origin git@vps.example.com:/srv/git/project.git
git push -u origin main

اولین push موفق با * [new branch] main -> main پایان می‌یابد. موردی که با git@vps.example.com: Permission denied (publickey) تمام شود، احراز هویت نشده است؛ بنابراین لاگ سرور را با sudo journalctl -u ssh -n 20 بخوانید. خطی که Authentication refused: bad ownership or modes for file /home/git/.ssh/authorized_keys را نشان می‌دهد به این معنی است که مجوز فایل اشتباه است، زیرا sshd کلیدهایی که سایر کاربران امکان نوشتن در آن‌ها را دارند، نادیده می‌گیرد.

سپس دسترسی shell را از حساب کاربری بگیرید.

command -v git-shell | sudo tee -a /etc/shells
sudo chsh -s "$(command -v git-shell)" git

git-shell فقط دستورات محدودی را که Git از طریق SSH ارسال می‌کند می‌پذیرد، بنابراین ورود تعاملی (interactive login) اکنون به جای نمایش prompt، با یک پیام متوقف می‌شود:

fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.

این تمام چیزی است که سرور شامل می‌شود. هیچ دیتابیسی وجود ندارد و هیچ پردازش وبی برای به‌روزرسانی نیست. چیزی که از دست می‌دهید تمام امکاناتی است که یک forge ارائه می‌دهد: بدون مرورگر مخازن، بدون سیستم ردیابی issue، بدون pull request و بدون مجوزهای سطح کاربر. هر کلیدی که در آن فایل باشد، می‌تواند تمام مخازنی را که کاربر git مالک آن‌هاست، بخواند و بنویسد.

لایه 1: cgit نمای وب را بدون نیاز به پایگاه داده ارائه می‌دهد

cgit یک برنامه CGI (رابط دروازه مشترک) است که با زبان C نوشته شده است. وب‌سرور این برنامه را به ازای هر درخواست اجرا می‌کند؛ cgit مخازن را مستقیماً از روی دیسک می‌خواند و هیچ وضعیتی را در خود ذخیره نمی‌کند. توزیع Ubuntu 24.04 این برنامه را در بخش universe ارائه می‌دهد.

sudo apt update
sudo apt install -y cgit fcgiwrap nginx
sudo install -d -o www-data -g www-data /var/cache/cgit

آن را به مسیر مخازن در /etc/cgitrc هدایت کنید:

root-title=Git on example.com
css=/cgit.css
logo=/cgit.png
cache-size=1000
cache-root=/var/cache/cgit
snapshots=tar.gz zip
scan-path=/srv/git

scan-path آن دایرکتوری را پیمایش کرده و تمام مخازن یافت‌شده را فهرست می‌کند، بنابراین یک مخزن bare جدید بدون نیاز به پیکربندی اضافی نمایش داده می‌شود. cache-size تعداد صفحات کش‌شده است و تا زمانی که مقدار آن صفر باشد، کش غیرفعال می‌ماند. پیش از افزودن خطوط جدید، محتویات فایلی که پکیج شما در /etc/cgitrc قرار داده است را مطالعه کنید، زیرا پکیج‌های Debian و Ubuntu به‌صورت پیش‌فرض تنظیماتی را در آن اعمال می‌کنند.

هر ورودی، خط اول فایل description مخزن را نمایش می‌دهد، بنابراین یک مخزن bare جدید با عنوان Unnamed repository; edit this file 'description' to name the repository. فهرست می‌شود. این مورد را برای هر مخزن یک‌بار اصلاح کنید:

echo 'Project X, internal tooling' | sudo -u git tee /srv/git/project.git/description
فایل سایت nginx و نحوه بررسی آن
server {
    listen 80;
    server_name git.example.com;
    root /usr/share/cgit;

    try_files $uri @cgit;

    location @cgit {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
        fastcgi_param PATH_INFO $uri;
        fastcgi_param QUERY_STRING $args;
        fastcgi_param HTTP_HOST $server_name;
        fastcgi_pass unix:/run/fcgiwrap.socket;
    }
}
sudo systemctl enable --now fcgiwrap.socket
sudo nginx -t && sudo systemctl reload nginx
systemctl show fcgiwrap.socket -p Listen

root /usr/share/cgit فایل‌های cgit.css و cgit.png را به‌عنوان فایل‌های ساده سرو می‌کند و try_files سایر درخواست‌ها را به CGI در /usr/lib/cgit/cgit.cgi می‌سپارد. مشاهده صفحه 502، همراه با connect() to unix:/run/fcgiwrap.socket failed (2: No such file or directory) در /var/log/nginx/error.log، به این معناست که واحد سوکت در حال اجرا نیست یا در مسیر دیگری گوش می‌دهد. خط systemctl show مسیری که واقعاً استفاده می‌شود را چاپ می‌کند.

پیش از استفاده از این ابزار، دانستن دو محدودیت ضروری است. cgit فقط‌خواندنی (read-only) است و قابلیت ورود (login) ندارد، بنابراین تمام محتویات تحت scan-path عمومی هستند: مخازن خصوصی را در آن دایرکتوری قرار ندهید یا از احراز هویت HTTP basic در ابتدای کل سایت استفاده کنید. همچنین، CGI با کاربر وب‌سرور اجرا می‌شود، بنابراین آن کاربر باید اجازه پیمایش /srv/git و خواندن هر مخزن را داشته باشد. دایرکتوری‌هایی که کاربر اجازه ورود به آن‌ها را ندارد، به‌جای نمایش خطا، به‌عنوان یک فهرست خالی نشان داده می‌شوند.

لایه 2: استفاده از Forgejo یا Gitea برای مدیریت Issues و Pull Requests

Forgejo و Gitea از یک ایده پیروی می‌کنند: یک فایل باینری Go که یک پلتفرم توسعه نرم‌افزار (Forge) شامل کاربران، سازمان‌ها، Issues، Pull Requests، نسخه‌های منتشر شده (releases)، مخزن پکیج و سیستم CI داخلی را ارائه می‌دهد. کل نصب شامل یک فایل باینری و دیتابیس SQLite است؛ به همین دلیل روی سخت‌افزارهایی که GitLab توان اجرای روی آن‌ها را ندارد، به‌راحتی اجرا می‌شوند. فایل Compose زیر همان فایلی است که در مستندات Forgejo آمده و از تگ ایمیج مربوط به اکتبر 2026 استفاده می‌کند.

networks:
  forgejo:
    external: false

services:
  server:
    image: codeberg.org/forgejo/forgejo:16
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    networks:
      - forgejo
    volumes:
      - ./forgejo:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - '3000:3000'
      - '222:22'
docker compose up -d
docker compose ps
curl -sI http://127.0.0.1:3000 | head -1

خط curl باید یک خط وضعیت HTTP را چاپ کند. پیش از آنکه تنظیمات اولیه (first-run setup) را به پایان برسانید، ممکن است با یک redirect به /install مواجه شوید که همچنان به معنای فعال بودن سرویس است. اگر کانتینر متوقف (exit) می‌شود، دلیل معمول آن مشکلات مالکیت فایل (ownership) است: دایرکتوری ./forgejo باید متعلق به UID (شناسه کاربری) تعریف شده در USER_UID باشد، در غیر این صورت پردازش نمی‌تواند در دایرکتوری داده‌های خود بنویسد. مقاله Docker Compose روی VPS این ساختار فایل و قانون مالکیت volumeها را به‌طور کامل پوشش می‌دهد.

دو پاسخ در صفحه تنظیمات اولیه تعیین می‌کنند که آیا URLهای clone کار می‌کنند یا خیر. پورت SSH باید 222 باشد، زیرا فایل Compose پورت 222 میزبان را به پورت 22 کانتینر نگاشت می‌کند و دامنه نیز باید همان نامی باشد که کاربران واقعاً تایپ می‌کنند. اگر هر یک از این دو مورد اشتباه باشد، تمام صفحات مخزن، دستور cloneای را ارائه می‌دهند که برای هر کسی که آن را کپی کند، با خطا مواجه می‌شود. هر دو مورد بعداً در بخش [server] از فایل app.ini و به عنوان SSH_PORT، SSH_DOMAIN و ROOT_URL قابل تغییر هستند.

برای یک نمونه عمومی (public instance)، پورت وب را فقط روی آدرس loopback ('127.0.0.1:3000:3000') منتشر کنید و برای TLS (امنیت لایه انتقال) از nginx در مقابل آن استفاده کنید. Gitea نیز به همان روش از طریق ایمیج docker.gitea.com/gitea که در مستنداتش آمده، یا به عنوان یک فایل باینری تکی با یک unit در systemd و یک فایل app.ini نصب می‌شود. نسخه پایدار فعلی آن v28.1.0 است که در 6 اکتبر 2026 منتشر شده است. با انتشار v28.0.0 در پایان سپتامبر، این پروژه پیشوند قدیمی 1. را کنار گذاشت، بنابراین نسخه بعد از 1.27، عدد 28 است، نه 1.28.

تا زمانی که می‌توانید از SQLite استفاده کنید. این کار باعث می‌شود نمونه شما به یک پردازش و یک فایل محدود بماند و پس از reboot بدون نیاز به نظارت بر سرویس اضافی، به‌درستی بالا بیاید. PostgreSQL زمانی ارزش هزینه کردن را دارد که چندین نفر همزمان در حال نوشتن باشند، زیرا SQLite عملیات نوشتن را سریال‌سازی می‌کند و اجرای طولانی‌مدت CI به‌طور مداوم در حال نوشتن است. هر دو پروژه امکان انتقال یک نمونه موجود به PostgreSQL را در آینده فراهم می‌کنند، بنابراین این تصمیمی نیست که در آن گرفتار شوید.

تفاوت واقعی Forgejo و Gitea

ریشه این دو پروژه مشترک است. Gitea در سال 2016 از Gogs منشعب شد. در اواخر سال 2022، کنترل دامنه و علامت تجاری Gitea به شرکتی به نام Gitea Ltd واگذار شد و تعدادی از نگهدارندگان پروژه به همراه Codeberg، پروژه Forgejo را آغاز کردند. Forgejo توسط Codeberg e.V. منتشر می‌شود که یک انجمن غیرانتفاعی ثبت‌شده در آلمان است و در سال 2024 مجوز خود را از MIT به GPLv3 (مجوز عمومی همگانی گنو نسخه 3) تغییر داد. Gitea همچنان با مجوز MIT باقی مانده و با پشتیبانی تجاری توسعه می‌یابد.

در استفاده روزمره، مجموعه قابلیت‌های این دو به هم نزدیک است، اما مسیر مهاجرت بین آن‌ها این‌طور نیست. نسخه Forgejo v10.0 که در ژانویه 2025 منتشر شد، آخرین نسخه‌ای بود که می‌توانست دیتابیس Gitea را مستقیماً بپذیرد و آن هم فقط از Gitea v1.22 یا قدیمی‌تر. Gitea تا اکتبر 2026 به نسخه v28.1.0 رسیده است، بنابراین در یک نمونه فعلی Gitea، هیچ روش پشتیبانی‌شده‌ای برای سوئیچ درجا به Forgejo وجود ندارد. پیش از آنکه دیتابیس خود را با داده پر کنید، یکی را انتخاب کنید و هرگونه جابه‌جایی بعدی را به عنوان یک عملیات export و re-import در نظر بگیرید.

یک قاعده کلی برای انتخاب: اگر حاکمیت پروژه برای شما اهمیت دارد یا می‌خواهید پروژه تحت نظر یک نهاد غیرانتفاعی باقی بماند، از Forgejo استفاده کنید. اگر به دنبال پایگاه نصب بزرگ‌تر و گزینه پشتیبانی تجاری هستید، Gitea را انتخاب کنید. هر دو پروژه به‌صورت متن‌باز نگهداری می‌شوند و به‌طور مرتب نسخه جدید ارائه می‌دهند: Forgejo هر سه ماه یک نسخه پایدار و هر سال یک نسخه LTS (پشتیبانی بلندمدت) منتشر می‌کند؛ تا اکتبر 2026، نسخه v16.0.5 نسخه جاری و v15.0.9 نسخه LTS است. Forgejo از نسخه v16 تا 29 اکتبر 2026 و از نسخه v15 تا 15 ژوئیه 2027 پشتیبانی می‌کند، بنابراین پیش از تثبیت یک نسخه اصلی، صفحه انتشار آن را بررسی کنید.

سطح 3: هزینه‌های GitLab پیش از هرگونه استفاده

نرم‌افزار GitLab CE در ردهٔ متفاوتی قرار دارد. هر نمونه (instance) از این نرم‌افزار، مجموعه‌ای از سرویس‌های همکار است: Puma برای اپلیکیشن وب، Sidekiq برای پردازش‌های پس‌زمینه، PostgreSQL، Redis، Gitaly برای دسترسی به مخازن و nginx در لایهٔ جلویی. بستهٔ Omnibus تمامی این موارد را یکجا نصب می‌کند که باعث سادگی نصب، اما افزایش حداقل حافظهٔ مورد نیاز می‌شود.

صفحهٔ نیازمندی‌های GitLab، مقدار 16 GB رم و 8 vCPU را به عنوان حداقل استاندارد برای نصب روی یک گره (node) تعیین کرده است و 8 GB را به عنوان پایین‌ترین حد برای محیط‌های با محدودیت حافظه ذکر می‌کند. همین صفحه توصیه می‌کند که swap را غیرفعال کنید، زیرا استفاده از swap تحت بار کاری، عملکرد نمونه را به‌شدت کاهش می‌دهد. این ارقام تا اکتبر 2026 معتبر هستند و با گذشت سال‌ها افزایش یافته‌اند؛ بنابراین پیش از انتخاب اندازهٔ سرور، حتماً دوباره این صفحه را مطالعه کنید.

در ازای این بودجه، امکانات واقعی دریافت می‌کنید: container registry، package registry، سطوح دسترسی دقیق، قابلیت‌های انطباق و حسابرسی (audit)، و CI که در مقیاس‌های بزرگ تست شده است. اگر هیچ‌کس در تیم شما نمی‌تواند موردی از این لیست را نام ببرد که در این فصل به آن نیاز داشته باشد، شما در حال پرداخت هزینه برای یک VPS بزرگ‌تر هستید بدون آنکه بهره‌ای از آن ببرید.

مدل دسترسی SSH: یک کاربر git و چندین کلید

هر لایه در اینجا به روش یکسانی احراز هویت می‌شود. یک حساب کاربری یونیکس به نام git وجود دارد و تمام کلیدهای عمومی در فایل ~/.ssh/authorized_keys آن حساب قرار می‌گیرند. احراز هویت بر عهده کلید است. مجوزدهی نیز همان گزینه‌هایی است که در ابتدای همان خط و پیش از کلید می‌نویسید.

یک خط کلید ساده، هر دسترسی که آن حساب کاربری داشته باشد را به دارنده کلید می‌دهد. یک دستور اجباری (forced command) دسترسی را به Git محدود می‌کند:

restrict,command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptop

گزینه restrict که از OpenSSH 7.2 در دسترس است، port forwarding، agent forwarding، X11 و تخصیص PTY (ترمینال مجازی) را در یک کلمه غیرفعال می‌کند. گزینه command= هر درخواستی که کلاینت ارسال کرده باشد را با دستوری که شما نام می‌برید جایگزین می‌کند؛ Git همچنان کار می‌کند زیرا درخواست خود را در $SSH_ORIGINAL_COMMAND ارسال می‌کند.

یک پلتفرم مدیریت مخزن (forge) این فایل را برای شما می‌نویسد و این تفاوت اصلی بین لایه 0 و لایه 2 است. Forgejo و Gitea فایل authorized_keys را با یک خط به ازای هر کلید ثبت‌شده بازنویسی می‌کنند که هر کدام شامل یک دستور اجباری است که کلید را با شناسه دیتابیسی آن مشخص می‌کند:

command="/usr/local/bin/forgejo --config=/etc/forgejo/app.ini serv key-3",no-port-forwarding,no-x11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice

آن دستور اجباری روشی است که یک حساب کاربری یونیکس مشترک به مجوزهای اختصاصی هر کاربر تبدیل می‌شود: key-3 به پلتفرم می‌گوید کدام کاربر در حال اتصال است و پیش از جابجایی هرگونه آبجکت، دسترسی آن کاربر به مخزن را بررسی می‌کند. این فایل را در سروری که توسط یک پلتفرم مدیریت می‌شود به‌صورت دستی ویرایش نکنید، زیرا فایل از روی دیتابیس بازنویسی می‌شود و خطی که اضافه کرده‌اید حذف خواهد شد. کلیدهای استقرار (deploy keys) نیز از همین مکانیزم استفاده می‌کنند: یک کلید استقرار، یک کلید SSH معمولی است که برای یک مخزن خاص ثبت شده و معمولاً فقط‌خواندنی است، با این تفاوت که بررسی دسترسی به‌جای sshd، در داخل پلتفرم انجام می‌شود.

دو عادت بیش از هر پیکربندی دیگری اهمیت دارند. برای هر شخص یا هر ماشین یک کلید اختصاصی صادر کنید و هرگز از کلید مشترک استفاده نکنید، زیرا ابطال یک کلید مشترک به معنای تعویض آن برای همه افراد به‌طور همزمان است. همچنین کلیدها را در همان روزی که فردی سازمان را ترک می‌کند حذف کنید، چرا که یک کلید قدیمی در آن فایل، یک راه ورود دائمی است که هیچ‌کس آن را زیر نظر ندارد. مدیریت صحیح کلیدهای SSH روی سرور انواع کلیدها و عبارات عبور (passphrases) را پوشش می‌دهد و تمام آن موارد در اینجا نیز بدون تغییر صدق می‌کنند. اگر سرور جدید است، ده دقیقه اول روی یک VPS جدید کاری است که باید پیش از قرار دادن مخازن روی آن انجام دهید.

آیا می‌توانم GitHub Actions را روی سرور Git شخصی خود اجرا کنم؟

شما می‌توانید workflowهایی که با سینتکس GitHub Actions نوشته شده‌اند را اجرا کنید، اما نمی‌توانید خودِ GitHub را اجرا کنید. قابلیت Forgejo Actions از نسخه Forgejo v1.21 به‌صورت پیش‌فرض فعال شده است و فایل‌های workflow را از مسیر .forgejo/workflows در هر مخزن می‌خواند. Gitea Actions نیز به همین صورت عمل کرده و فایل‌ها را از .gitea/workflows می‌خواند. هر دو سیستم به یک برنامه جانبی به نام runner نیاز دارند که باید نصب شده و با استفاده از توکنی که از بخش تنظیمات مدیریت دریافت می‌کنید، در instance شما ثبت شود. بسیاری از actionهای منتشرشده بدون تغییر اجرا می‌شوند؛ اما هر چیزی که GitHub API را فراخوانی کند یا انتظار زیرساخت‌های میزبانی‌شده توسط GitHub را داشته باشد، کار نخواهد کرد.

دو پیامد را در نظر بگیرید. runner برای هر job یک container را اجرا می‌کند، بنابراین به یک موتور کانتینر و بودجه حافظه (RAM) اختصاصی نیاز دارد؛ به همین دلیل نباید آن را روی همان سرور 1 GB که forge روی آن قرار دارد، نصب کنید. همچنین، runner هر دستوری که در فایل workflow نوشته شده باشد را اجرا می‌کند؛ مستندات Forgejo به‌صراحت بیان می‌کنند که runner در واقع اجرای کد از راه دور (remote code execution) را انجام می‌دهد. تا حد امکان آن را روی یک میزبان (host) مجزا قرار دهید، یا حداقل از یک کاربر بدون دسترسی‌های ویژه (unprivileged user) و یک توکن ثبت با محدودیت دسترسی به یک مخزن خاص استفاده کنید.

اگر مخازن شما روی GitHub باقی می‌مانند و فقط می‌خواهید پردازش را روی سخت‌افزاری که کنترل می‌کنید انجام دهید، این یک سناریوی متفاوت با مراحل جداگانه است: یک self-hosted GitHub Actions runner به یک مخزن GitHub متصل می‌شود و به هیچ‌کدام از این تنظیمات نیاز ندارد. اگر هنوز در حال بررسی هزینه‌های خروج از GitHub هستید، آنچه GitHub واقعاً به شما ارائه می‌دهد تفاوت میزبانی Git و شبکه پیرامون آن را برای شما روشن می‌کند.

پشتیبان‌گیری: مخازن تنها نیمی از وضعیت هستند

یک مخزن bare در واقع یک دایرکتوری است، بنابراین کپی کردن آن، همه محتویاتش را کپی می‌کند. یک mirror clone از دستگاهی دیگر، یک پشتیبان واقعی محسوب می‌شود و در همان محل به‌روزرسانی می‌گردد:

git clone --mirror git@vps.example.com:/srv/git/project.git
cd project.git && git remote update

این دستور تمام refها و تمام objectها را دریافت می‌کند. این کار شامل hookهای سمت سرور یا فایل description نمی‌شود، بنابراین اگر از hookها استفاده می‌کنید، یک کپی در سطح فایل از دایرکتوری نیز تهیه کنید.

یک پلتفرم مدیریت مخزن (forge)، مسائل (issues)، درخواست‌های pull، کاربران، کلیدها و مجوزها را در دیتابیس خود نگه می‌دارد و کپی کردن صرفِ مخازن، تمام این اطلاعات را از دست می‌دهد. هر دو پروژه دستور dump را ارائه می‌دهند که دیتابیس، مخازن، پیکربندی و پیوست‌ها را در یک آرشیو می‌نویسد:

sudo -u git forgejo dump -c /etc/forgejo/app.ini -f /var/backups/forgejo-dump.zip

در Docker، همین دستور در داخل container اجرا می‌شود و مسیر پیکربندی به image بستگی دارد، بنابراین پیش از تایپ کردن بررسی کنید:

docker compose exec server ls /data/gitea/conf
docker compose exec -u git server forgejo dump -c /data/gitea/conf/app.ini

دستور را با کاربری که مالک داده‌هاست اجرا کنید و آرشیو را در دایرکتوری بنویسید که آن کاربر اجازه نوشتن در آن را دارد. سپس آرشیو را از سرور خارج کنید، زیرا پشتیبانی که فقط روی همان ماشینی که از آن نسخه تهیه شده وجود داشته باشد، پشتیبان نیست. بازیابی مرحله‌ای است که افراد از آن غافل می‌شوند: همین حالا یک dump را روی یک سیستم جایگزین باز کنید تا این فرآیند را در شرایط آرام یاد بگیرید، نه در زمان بروز قطعی.

انتخاب بر اساس سناریو

یک نفر با یک لپ‌تاپ و یک VPS، بدون نیاز به مرورگر: استفاده از bare repositories از طریق SSH. هیچ سرویس اضافه‌ای در حال اجرا نیست و نیازی به ارتقا وجود ندارد.

همان سناریو، به‌علاوه نیاز به خواندن کد در مرورگر و ارسال لینک به آن: اضافه کردن cgit. همچنان بدون دیتابیس و بدون نیاز به سرویس‌های مقیم در حافظه.

یک تیم که کدهای یکدیگر را بازبینی کرده و issueها را پیگیری می‌کند: استفاده از Forgejo یا Gitea، با حداقل 2 GB رم. زمانی که حجم کارها واقعی شد، CI runner را به یک سرور دوم منتقل کنید.

یک سازمان که به container registry و audit trail نیاز دارد، با بودجه 16 GB رم برای سرور: GitLab. با بودجه کمتر از این مقدار، آن را راه‌اندازی نکنید.

ارتقا از سه سطح اول ارزان است، زیرا در تمام آن‌ها مخازن، دایرکتوری‌های معمولی Git روی دیسک هستند. از پایین‌ترین سطحی که کار شما را راه می‌اندازد شروع کنید. اگر در حال بررسی این هستید که چه سرویس‌های دیگری ارزش قرارگیری روی همان سرور را دارند، لیست کوتاه سرویس‌هایی که ارزش self-hosting دارند، یک سرور Git را در کنار سایر سرویس‌هایی که برای آن مقدار رم رقابت می‌کنند، قرار می‌دهد.

FAQ

آیا یک VPS با 1 گیگابایت رم می‌تواند Forgejo یا Gitea را اجرا کند؟

بله، برای یک تیم کوچک، با استفاده از SQLite و در صورتی که بار پردازشی سنگین دیگری روی سرور نباشد. مستندات Gitea معمولاً 1 گیگابایت رم و 2 هسته CPU را برای تیم‌ها و پروژه‌های کوچک کافی می‌داند و Forgejo نیز که انشعابی (fork) از Gitea است، ساختار مشابهی دارد. PostgreSQL یا CI runner را روی چنین ماشینی نصب نکنید. اگر سرویس بدون ثبت خطا در لاگ خود ناپدید شد، دستور sudo dmesg -T | grep -i oom را اجرا کنید: مشاهده نام پردازش در خروجی به این معناست که OOM Killer هسته سیستم‌عامل آن را متوقف کرده است؛ در این حالت، ارتقای پلن سرور راهکار اصلی است و نه تغییر تنظیمات.

تفاوت Forgejo و Gitea چیست؟

این دو پروژه تاریخچه کدنویسی و اکثر قابلیت‌هایشان مشترک است. Gitea در سال 2016 از Gogs منشعب شد و Forgejo در اواخر سال 2022، پس از آنکه کنترل علامت تجاری Gitea به یک شرکت واگذار شد، از Gitea انشعاب یافت. Forgejo توسط Codeberg e.V.، یک سازمان غیرانتفاعی در آلمان، تحت مجوز GPLv3 منتشر می‌شود؛ در حالی که Gitea با مجوز MIT و تحت حمایت تجاری باقی مانده است. تفاوت عملی در مسیر مهاجرت است. نسخه Forgejo v10.0 که در ژانویه 2025 منتشر شد، آخرین نسخه‌ای بود که می‌توانست دیتابیس Gitea را مستقیماً بپذیرد (آن هم فقط از Gitea v1.22 یا قدیمی‌تر)، بنابراین در حال حاضر مسیر پشتیبانی‌شده‌ای برای تغییر مستقیم یک نمونه فعال Gitea به Forgejo وجود ندارد.

آیا می‌توانم ورک‌فلوهای GitHub Actions را روی یک سرور Git شخصی اجرا کنم؟

هم Forgejo Actions و هم Gitea Actions ورک‌فلوهایی را که با سینتکس YAML در GitHub Actions نوشته شده‌اند، از مسیرهای .forgejo/workflows و .gitea/workflows می‌خوانند. شما باید یک برنامه runner جداگانه نصب کرده و آن را در نمونه خود ثبت کنید. بسیاری از اکشن‌های منتشرشده بدون تغییر کار می‌کنند، اما مواردی که از API گیت‌هاب استفاده می‌کنند، کار نخواهند کرد. از آنجا که runner کدهای دلخواه را از مخازن شما اجرا کرده و برای هر job یک کانتینر جداگانه می‌سازد، آن را روی یک میزبان مجزا یا حداقل با یک کاربر بدون دسترسی‌های ویژه (unprivileged) اجرا کنید و از قرار دادن آن روی سرور 1 گیگابایتی که خودِ سرویس Git را میزبانی می‌کند، خودداری نمایید.

چگونه از یک سرور Git شخصی نسخه پشتیبان تهیه کنم؟

برای مخازن خام (bare repositories)، دستور git clone --mirror از یک ماشین دیگر تمام refها و objectها را کپی می‌کند و دستور git remote update در داخل آن mirror، محتوا را به‌روزرسانی می‌کند. برای Forgejo یا Gitea، مخازن تنها بخشی از وضعیت سیستم هستند، زیرا issues، pull requests، کاربران و کلیدها در دیتابیس ذخیره می‌شوند. از ابزار داخلی dump یعنی sudo -u git forgejo dump -c /etc/forgejo/app.ini استفاده کنید (یا همین دستور را در داخل کانتینر برای نصب‌های Docker اجرا کنید). فایل آرشیو را از سرور خارج کنید و یک بار آن را روی یک ماشین یدکی بازیابی کنید تا از صحت فرآیند اطمینان حاصل شود.

#git#self-hosting#forgejo#gitea#ssh