راهاندازی سرور گیت اختصاصی با Gitea روی سرور مجازی و اختصاصی
برای میزبانی کدهای یک تیم همیشه لازم نیست مخزنها را به سرویسهایی مانند GitHub یا GitLab بسپارید. با راهاندازی Gitea روی سرور میتوانید مخزنهای خصوصی، حسابهای کاربران، کلیدهای SSH و دسترسی اعضای تیم را روی زیرساخت خودتان مدیریت کنید.
Gitea یک سرویس سبک برای میزبانی Git است و امکاناتی مانند رابط وب، Pull Request، Issue، Webhook، مدیریت سازمان و احراز هویت دومرحلهای دارد. مصرف منابع آن نیز معمولاً از پلتفرمهای بزرگتر کمتر است؛ بنابراین برای تیمهای کوچک و متوسط، پروژههای داخلی و محیطهایی که کنترل داده اهمیت دارد، گزینه مناسبی است.
در این راهنما Gitea را با Docker Compose روی Ubuntu نصب میکنیم، PostgreSQL را بهعنوان پایگاه داده در نظر میگیریم و با Nginx و گواهی رایگان Let’s Encrypt دسترسی HTTPS میسازیم. دستورها برای VPS و سرور اختصاصی یکساناند.
انتخاب VPS یا سرور اختصاصی برای Gitea
نوع سرور را باید بر اساس تعداد کاربران، حجم مخزنها، تعداد عملیات همزمان و سرویسهای جانبی انتخاب کنید. خود Gitea سبک است، اما Git LFS، رجیستری پکیجها، Actions و تعداد زیاد عملیات clone یا push میتوانند مصرف دیسک، شبکه و پردازنده را افزایش دهند. برای یک تیم کوچک با چند ده مخزن، یک VPS با ۲ هسته پردازنده، ۲ تا ۴ گیگابایت رم و فضای SSD معمولاً نقطه شروع مناسبی است. اگر فایلهای حجیم نگه میدارید یا runnerهای CI را روی همان ماشین اجرا میکنید، منابع بیشتری لازم خواهید داشت.
| نوع زیرساخت | کاربرد مناسب | مزیت اصلی | محدودیت |
|---|---|---|---|
| سرور مجازی | تیم کوچک، پروژه شخصی و محیط توسعه | هزینه کمتر و ارتقای ساده منابع | منابع پردازنده ممکن است اشتراکی باشد |
| سرور اختصاصی | تیم بزرگ، مخزنهای حجیم و بار زیاد | منابع پایدار و کنترل کامل سختافزار | هزینه و مسئولیت نگهداری بیشتر |
| سرویس SaaS عمومی | تیمی که مدیریت زیرساخت نمیخواهد | شروع سریع و نگهداری کمتر | کنترل کمتر روی داده و محدودیتهای سرویسدهنده |
بهتر است runnerهای سنگین CI را از سرور اصلی Gitea جدا کنید. اجرای buildهای پرمصرف روی همان سرور میتواند پاسخگویی رابط وب، عملیات Git و پایگاه داده را مختل کند.
پیشنیازهای نصب
در این آموزش فرض میکنیم موارد زیر آمادهاند:
- یک سرور Ubuntu 22.04 یا 24.04 با دسترسی کاربر دارای مجوز sudo
- یک دامنه یا زیردامنه مانند git.example.com
- رکورد DNS از نوع A که به IPv4 سرور اشاره میکند
- دسترسی ورودی به پورتهای 22، 80 و 443
- فضای ذخیرهسازی کافی برای مخزنها و نسخههای پشتیبان
اگر سرور IPv6 دارد، رکورد AAAA را نیز فقط زمانی اضافه کنید که مسیر IPv6 و فایروال آن درست تنظیم شده باشد. وجود رکورد AAAA معیوب ممکن است دسترسی برخی کاربران و صدور گواهی را با مشکل مواجه کند.
ابتدا بستههای سیستم را بهروز کنید:
sudo apt update
sudo apt upgrade -y
سپس Docker و افزونه Compose را از مخزن Ubuntu نصب کنید:
sudo apt install -y docker.io docker-compose-v2 nginx certbot python3-certbot-nginx
sudo systemctl enable --now docker nginx
برای اطمینان از نصب صحیح، نسخه ابزارها را ببینید:
docker --version
docker compose version
nginx -v
ساخت ساختار پروژه و فایل Docker Compose
برای نگهداری تنظیمات، یک مسیر مشخص بسازید. در این نمونه تمام فایلهای اجرایی در /opt/gitea قرار میگیرند:
sudo mkdir -p /opt/gitea
sudo chown "$USER":"$USER" /opt/gitea
cd /opt/gitea
رمز پایگاه داده را با یک مقدار طولانی و تصادفی جایگزین کنید. بهتر است متغیرهای حساس را در فایل .env نگه دارید:
nano .env
محتوای نمونه:
POSTGRES_DB=gitea
POSTGRES_USER=gitea
POSTGRES_PASSWORD=replace-with-a-long-random-password
دسترسی فایل را محدود کنید:
chmod 600 .env
اکنون فایل compose.yaml را بسازید:
services:
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- gitea-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
server:
image: gitea/gitea:1
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
USER_UID: "1000"
USER_GID: "1000"
GITEA__database__DB_TYPE: postgres
GITEA__database__HOST: db:5432
GITEA__database__NAME: ${POSTGRES_DB}
GITEA__database__USER: ${POSTGRES_USER}
GITEA__database__PASSWD: ${POSTGRES_PASSWORD}
GITEA__server__DOMAIN: git.example.com
GITEA__server__ROOT_URL: https://git.example.com/
GITEA__server__SSH_DOMAIN: git.example.com
GITEA__server__SSH_PORT: "2222"
GITEA__server__START_SSH_SERVER: "true"
GITEA__security__INSTALL_LOCK: "true"
volumes:
- gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:3000:3000"
- "2222:22"
networks:
- gitea-network
volumes:
gitea-data:
postgres-data:
networks:
gitea-network:
مقادیر git.example.com را با دامنه واقعی خود جایگزین کنید. اتصال پورت 3000 فقط روی 127.0.0.1 باعث میشود رابط وب Gitea مستقیماً از اینترنت در دسترس نباشد و درخواستها از Nginx عبور کنند.
در این پیکربندی، SSH داخلی Gitea از پورت 2222 میزبان استفاده میکند؛ زیرا پورت 22 معمولاً در اختیار سرویس SSH سیستمعامل است. کاربران در این حالت مخزن را با نشانی مشابه زیر دریافت میکنند:
git clone ssh://git@git.example.com:2222/team/project.git
پورت 2222 را در فایروال باز کنید (برای پیکربندی دقیقتر قوانین، به راهاندازی فایروال nftables روی سرور لینوکس نگاه کنید):
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw allow 2222/tcp
sudo ufw enable
قبل از فعالکردن UFW مطمئن شوید قانون OpenSSH اضافه شده است؛ در غیر این صورت ممکن است نشست مدیریتی بعدی به سرور برقرار نشود.
اجرای Gitea و ساخت حساب مدیر
سرویسها را اجرا کنید:
cd /opt/gitea
docker compose up -d
وضعیت کانتینرها را بررسی کنید:
docker compose ps
docker compose logs --tail=100 server
بهدلیل فعالبودن INSTALL_LOCK، نصب تعاملی وب غیرفعال است. حساب مدیر را از داخل کانتینر ایجاد کنید:
docker compose exec -u git server gitea admin user create \
--username admin \
--password 'replace-with-another-strong-password' \
--email admin@example.com \
--admin \
--must-change-password
استفاده مستقیم از رمز در خط فرمان ممکن است آن را در تاریخچه پوسته نگه دارد. پس از ساخت حساب، دستور مربوط را از history حذف کنید یا حساب مدیر را با روش تعاملی و ملاحظات امنیتی محیط خود بسازید.
پیکربندی Nginx بهعنوان Reverse Proxy
یک فایل تنظیمات برای دامنه Gitea ایجاد کنید:
sudo nano /etc/nginx/sites-available/gitea
تنظیم اولیه HTTP:
server {
listen 80;
listen [::]:80;
server_name git.example.com;
client_max_body_size 512M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300;
}
}
مقدار client_max_body_size سقف اندازه بدنه درخواست در Nginx است. آن را متناسب با سیاست مخزنها و Git LFS تنظیم کنید؛ عدد بزرگتر بهتنهایی محدودیتهای دیگر Gitea یا شبکه را تغییر نمیدهد. برای تنظیمات تکمیلی worker و timeout میتوانید به بهینهسازی Nginx هم مراجعه کنید.
سایت را فعال و تنظیمات را آزمایش کنید:
sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/gitea
sudo nginx -t
sudo systemctl reload nginx
اکنون باید رابط Gitea از طریق http://git.example.com باز شود. اگر خطای 502 دریافت میکنید، ابتدا خروجی docker compose ps و سپس لاگهای کانتینر Gitea و Nginx را بررسی کنید.
فعالکردن HTTPS رایگان
بعد از انتشار رکورد DNS و دسترسی صحیح دامنه روی پورت 80، گواهی TLS را با Certbot دریافت کنید:
sudo certbot --nginx -d git.example.com
Certbot گواهی را دریافت میکند، تنظیمات Nginx را تغییر میدهد و امکان انتقال HTTP به HTTPS را پیشنهاد میکند. وضعیت تمدید خودکار را با این دستور آزمایش کنید:
sudo certbot renew --dry-run
پس از فعالشدن HTTPS، وارد پنل شوید و در بخش تنظیمات سرور بررسی کنید که URL عمومی با https://git.example.com/ یکسان باشد. مقدار نادرست ROOT_URL میتواند لینکهای اعلان، callbackها، clone URL و تغییر مسیر ورود را خراب کند.
افزودن کلید SSH و ساخت اولین مخزن
روی رایانه کاربر یک کلید Ed25519 بسازید؛ اگر کلید مناسبی از قبل دارید، نیازی به ساخت دوباره نیست:
ssh-keygen -t ed25519 -C "developer@example.com"
محتوای کلید عمومی را نمایش دهید:
cat ~/.ssh/id_ed25519.pub
کلید عمومی را در Gitea از مسیر تنظیمات حساب و بخش SSH/GPG Keys اضافه کنید. سپس ارتباط را آزمایش کنید:
ssh -T -p 2222 git@git.example.com
برای انتقال یک پروژه موجود به مخزن تازه:
cd existing-project
git remote add origin ssh://git@git.example.com:2222/team/project.git
git push -u origin main
اگر شاخه اصلی پروژه master یا نام دیگری دارد، همان نام را در دستور push وارد کنید.
تنظیمات امنیتی پس از نصب
در دسترس قرارگرفتن صفحه ورود پایان کار نیست. برای کاهش ریسک، ثبتنام عمومی را غیرفعال کنید و حسابها را مدیر سیستم بسازد. همچنین احراز هویت دومرحلهای را برای مدیران و کاربران دارای دسترسی حساس فعال کنید.
چند اقدام عملی دیگر عبارتاند از:
- دسترسی مدیریتی SSH سرور را به کلید عمومی محدود کنید (جزئیات کاملتر در امنسازی دسترسی SSH به سرور لینوکس).
- ورود مستقیم کاربر root و ورود با رمز را پس از آزمایش کلید SSH ببندید.
- Docker، سیستمعامل، Nginx، PostgreSQL و تصویر Gitea را منظم بهروزرسانی کنید.
- دسترسی سازمانها و مخزنها را بر پایه حداقل مجوز لازم تعریف کنید.
- برای تلاشهای مکرر ورود، ابزارهایی مانند Fail2ban یا محدودسازی نرخ در پراکسی را بررسی کنید.
- Gitea Actions را فقط در صورت نیاز فعال کنید و runner را یک محیط قابل اعتماد فرض نکنید.
Runner کد workflow را اجرا میکند. اگر کاربران غیرقابل اعتماد اجازه تغییر workflow داشته باشند، اجرای runner روی همان میزبان Gitea میتواند دامنه آسیب را بیشتر کند. جداسازی runner در ماشین یا شبکهای مستقل انتخاب امنتری است؛ برای نمونهای از راهاندازی یک runner خودمیزبان جدا، به راهاندازی GitLab Runner خودمیزبان روی سرور مجازی و اختصاصی نگاه کنید.
نسخه پشتیبان و بازیابی
مخزن گیت تنها بخش داده نیست. حسابها، Issueها، Pull Requestها، Webhookها و تنظیمات در پایگاه داده و مسیر داده Gitea نگهداری میشوند. بنابراین کپیکردن پوشه repositoryها بهتنهایی نسخه پشتیبان کامل نمیسازد. اگر میخواهید در دسترسبودن پایگاه داده را هم فراتر از بکاپ دورهای تضمین کنید، راهاندازی Replication و Failover خودکار در PostgreSQL را ببینید. برای تهیه خروجی منطقی از PostgreSQL میتوانید از دستور زیر استفاده کنید:
cd /opt/gitea
docker compose exec -T db pg_dump \
-U gitea \
-d gitea > gitea-database.sql
علاوه بر پایگاه داده، از volume مربوط به gitea-data نیز نسخه پشتیبان بگیرید. روش دقیق آن به ابزار بکاپ و محل ذخیرهسازی شما بستگی دارد. فایلهای پشتیبان را روی همان دیسک سرور نگه ندارید؛ خرابی دیسک یا حذف سرور میتواند نسخه اصلی و بکاپ را همزمان از بین ببرد.
بازیابی را دورهای روی یک سرور آزمایشی تمرین کنید. بکاپی که فرایند restore آن آزمایش نشده باشد، تضمینی برای بازگشت سرویس نیست. بهتر است دوره نگهداری، رمزنگاری فایلها و زمان قابلقبول بازیابی نیز از قبل مشخص شود.
بهروزرسانی Gitea با وقفه کنترلشده
پیش از ارتقا، یادداشتهای انتشار نسخه مقصد را بخوانید و از داده و پایگاه داده بکاپ بگیرید. سپس تصویر جدید را دریافت و کانتینر را بازسازی کنید:
cd /opt/gitea
docker compose pull
docker compose up -d
docker compose logs -f --tail=100 server
استفاده از برچسب کلی 1 ارتقاهای همان شاخه اصلی را دریافت میکند. برای کنترل بیشتر میتوانید نسخه دقیق تصویر را در فایل Compose ثبت کنید و پس از آزمایش، آن را مرحلهبهمرحله تغییر دهید. این روش بازتولید محیط و بررسی تغییرات را سادهتر میکند.
خطاهای رایج در راهاندازی Gitea روی سرور
خطای 502 Bad Gateway معمولاً یعنی Nginx به پورت 3000 دسترسی ندارد یا کانتینر Gitea هنوز آماده نشده است. اتصال محلی را با دستور زیر آزمایش کنید:
curl -I http://127.0.0.1:3000
اگر clone از طریق SSH کار نمیکند، بازبودن پورت 2222 در فایروال، نگاشت پورت Docker و مقدار SSH_PORT را بررسی کنید. دستور ssh -v نیز جزئیات مذاکره اتصال و کلید انتخابشده را نشان میدهد.
اگر لینکها به HTTP برمیگردند یا callback ورود اشتباه است، مقادیر ROOT_URL، DOMAIN و هدر X-Forwarded-Proto در Nginx را کنترل کنید. برای خطاهای push فایلهای بزرگ نیز محدودیت Nginx، فضای آزاد دیسک، تنظیمات Git LFS و timeout پراکسی را جداگانه بررسی کنید.
جمعبندی
با نصب Docker، اجرای Gitea و PostgreSQL، قرار دادن Nginx در جلوی سرویس و فعالکردن HTTPS، یک سرور گیت اختصاصی در اختیار دارید که دادهها و سیاست دسترسی آن زیر کنترل خودتان است. نگهداری چنین سرویسی شامل پایش فضای دیسک، نصب بهروزرسانیها، مدیریت کاربران و آزمایش منظم نسخه پشتیبان نیز میشود. برای شروع روی یک زیرساخت قابل ارتقا میتوانید مشخصات و پلنهای سرور مجازی ابری آریانت را بررسی کنید. اگر مخزنها حجیماند، کاربران همزمان زیادی دارید یا بار CI به منابع ثابت نیاز دارد، سرور اختصاصی انتخاب مناسبتری برای ارزیابی است.




