เลือกใช้ Git server ตัวไหนดี: Forgejo, Gitea หรือ cgit
เปรียบเทียบ 4 ทางเลือกติดตั้ง Git server ด้วยตนเองตามปริมาณ RAM ที่ใช้จริง ตั้งแต่ bare repo ผ่าน SSH ไปจนถึง GitLab เพื่อดูว่า VPS ขนาด 1 GB รองรับตัวเลือกใดได้บ้าง
คุณควรเลือกใช้ Git server แบบ self-hosted ตัวใด
Git server แบบ self-hosted ไม่ได้มีเพียงผลิตภัณฑ์เดียว และปริมาณ RAM (random access memory) บน VPS ของคุณจะเป็นตัวกำหนดว่าคุณสามารถใช้งานเวอร์ชันใดได้บ้าง Git ไม่จำเป็นต้องมี daemon ของตัวเอง: repository เปล่า (bare repository) ร่วมกับบัญชี SSH (secure shell) ก็เพียงพอที่จะเป็นเซิร์ฟเวอร์ที่ใช้งานได้บนเครื่องขนาดเล็กที่สุดที่คุณสามารถเช่าได้ ทุกสิ่งที่เหนือไปจากระดับนี้คือเว็บแอปพลิเคชันที่คุณเลือกติดตั้งเพิ่มเติม และการขยับขึ้นไปแต่ละระดับต้องใช้หน่วยความจำที่ VPS ขนาดเล็กอาจไม่มีให้
มี 4 ระดับให้เลือก เริ่มจาก bare repository ผ่าน SSH ซึ่งไม่มีบริการใดที่ต้องเปิดพอร์ตเพิ่มเติมนอกเหนือจากที่มีอยู่เดิม ต่อมาคือ cgit ซึ่งเป็นเว็บสำหรับอ่านข้อมูลที่รวดเร็วและไม่ต้องใช้ฐานข้อมูล ถัดมาคือ Forgejo หรือ Gitea ซึ่งเป็นระบบจัดการซอร์สโค้ดเต็มรูปแบบที่มีระบบบัญชีผู้ใช้, ระบบติดตามปัญหา (issues) และ pull requests โดยใช้หน่วยความจำเพียงไม่กี่ร้อยเมกะไบต์ สุดท้ายคือ GitLab ซึ่งต้องการเซิร์ฟเวอร์ที่มีขนาดใหญ่กว่าตัวเลือกอื่นหลายเท่า
ให้ตัดสินใจจากงานที่คุณต้องทำ จากนั้นจึงตรวจสอบตัวเลขหน่วยความจำเทียบกับแผนบริการที่คุณใช้งานอยู่
ปริมาณ RAM ที่แต่ละตัวเลือกต้องการจริง
มีเพียงสองโครงการเท่านั้นที่ระบุตัวเลขความต้องการฮาร์ดแวร์ไว้ ให้ถือว่าตัวเลขที่ประกาศเป็นเพียงค่าขั้นต่ำไม่ใช่การรับประกัน และควรวัดค่าจาก instance ของคุณเองเมื่อรันงานจริงด้วย systemd-cgtop หรือ ps -o rss= -C forgejo
The data behind this chart
[
{
"label": "Gitea, small team",
"ram_gb": 1
},
{
"label": "GitLab, memory constrained",
"ram_gb": 8
},
{
"label": "GitLab, single node baseline",
"ram_gb": 16
}
]Gitea ระบุว่า RAM ขนาด 1 GB พร้อม CPU 2 คอร์ เพียงพอสำหรับทีมและโครงการขนาดเล็ก และระบุว่า Raspberry Pi 3 ก็เพียงพอสำหรับภาระงานขนาดเล็ก GitLab ระบุว่า RAM ขนาด 16 GB เป็นค่าพื้นฐานสำหรับการติดตั้งแบบโหนดเดียว และ 8 GB เป็นค่าต่ำสุดสำหรับสิ่งที่หน้าเว็บของตนเรียกว่าสภาพแวดล้อมที่จำกัดหน่วยความจำ ส่วน Forgejo ไม่ได้ระบุความต้องการฮาร์ดแวร์ไว้เลย เนื่องจากเป็น fork ของ Gitea และมีพฤติกรรมการทำงานที่คล้ายกัน ตัวเลขของ Gitea จึงเป็นแนวทางที่ใกล้เคียงที่สุดที่คุณมี
นั่นหมายความว่าบน VPS ขนาด 1 GB: bare repositories และ cgit สามารถทำงานได้โดยมีพื้นที่เหลือ เพราะทั้งสองตัวไม่ได้รัน service แบบ resident ส่วน Forgejo หรือ Gitea จะเริ่มทำงานและให้บริการทีมขนาดเล็กบน SQLite ได้ แต่เนื่องจากคุณกำลังใช้งานอยู่ที่ระดับขั้นต่ำตามเอกสาร จึงควรปิด PostgreSQL และ CI (continuous integration) runner บนเครื่องนั้น หากหน้าเว็บหายไปโดยไม่มีข้อความแจ้งเตือน ให้รัน sudo dmesg -T | grep -i oom แล้วมองหาบรรทัดที่คล้ายกับ Out of memory: Killed process 1181 (forgejo) ซึ่งหมายความว่า kernel out of memory killer ได้สั่งยุติการทำงานของโปรเซสไปแล้ว สำหรับ GitLab บนเครื่องขนาด 1 GB นั้นไม่ใช่ปัญหาเรื่องการปรับจูน แต่มันไม่สามารถรันได้จริง
Tier 0: การใช้ bare repository ผ่าน SSH
Git ไม่มี network daemon ที่คุณต้องเริ่มทำงาน git push ผ่าน SSH จะรัน git-receive-pack ที่ฝั่งปลายทางในฐานะกระบวนการ Unix ปกติ ดังนั้นบัญชีใดก็ตามที่คุณสามารถเข้าถึงได้ด้วย key จะกลายเป็น Git remote ทันที ให้สร้างบัญชีหนึ่งบัญชีสำหรับเก็บ repository และเก็บ repository เหล่านั้นไว้นอก home directory ของบัญชีนั้น เนื่องจากบน Ubuntu 24.04 นั้น home directory ใหม่จะมีโหมดเป็น 0750 ซึ่งจะทำให้ web view ที่เพิ่มเข้ามาในภายหลังไม่สามารถอ่านข้อมูลภายในได้
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 จะสร้าง repository ที่ไม่มี working copy ซึ่งเป็นสิ่งที่เซิร์ฟเวอร์ควรมี การ push เข้าไปยัง repository ที่มี working copy จะถูกปฏิเสธด้วย refusing to update checked out branch: refs/heads/main และนั่นเป็นข้อผิดพลาดที่พบบ่อยที่สุดในระดับนี้
ตอนนี้ให้เพิ่ม key เข้าไปในบัญชีและ clone repository ออกมา
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_keysgit 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) แสดงว่าไม่ผ่านการยืนยันตัวตน ให้ตรวจสอบ log ของเซิร์ฟเวอร์ด้วย sudo journalctl -u ssh -n 20 หากพบข้อความ Authentication refused: bad ownership or modes for file /home/git/.ssh/authorized_keys แสดงว่า file mode ไม่ถูกต้อง เนื่องจาก sshd จะเพิกเฉยต่อไฟล์ key ที่ผู้ใช้อื่นสามารถเขียนได้
จากนั้นให้จำกัดสิทธิ์การเข้าถึง shell ของบัญชีนั้น
command -v git-shell | sudo tee -a /etc/shells
sudo chsh -s "$(command -v git-shell)" gitgit-shell จะยอมรับเฉพาะคำสั่งไม่กี่คำสั่งที่ Git ส่งผ่าน SSH เท่านั้น ดังนั้นการล็อกอินแบบโต้ตอบจะหยุดลงพร้อมกับข้อความแทนที่จะแสดง prompt:
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.นั่นคือทั้งหมดของเซิร์ฟเวอร์นี้ ไม่มีฐานข้อมูลและไม่มี web process ที่ต้องอัปเกรด สิ่งที่คุณสูญเสียไปคือทุกอย่างที่ forge มีให้: ไม่มีการเรียกดูผ่านเว็บ, ไม่มีระบบติดตามปัญหา (issue tracker), ไม่มี pull request และไม่มีการกำหนดสิทธิ์รายผู้ใช้ ทุก key ในไฟล์นั้นสามารถอ่านและเขียนทุก repository ที่ผู้ใช้ git เป็นเจ้าของได้
ระดับ 1: cgit ให้มุมมองผ่านเว็บโดยไม่ต้องใช้ฐานข้อมูล
cgit เป็นโปรแกรม CGI (common gateway interface) ที่เขียนด้วยภาษา C เว็บเซิร์ฟเวอร์จะเรียกใช้งานโปรแกรมนี้หนึ่งครั้งต่อหนึ่งคำขอ โดยโปรแกรมจะอ่านข้อมูล repository โดยตรงจากดิสก์และไม่มีการเก็บสถานะใดๆ ของตนเอง 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ชี้เป้าไปยังไดเรกทอรีของ repository ใน /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/gitscan-path จะทำการไล่ดูไดเรกทอรีดังกล่าวและแสดงรายการ repository ทั้งหมดที่พบ ดังนั้นเมื่อมีการสร้าง bare repo ใหม่ขึ้นมา มันจะปรากฏในรายการโดยไม่ต้องตั้งค่าเพิ่มเติม cache-size คือจำนวนของหน้าเว็บที่แคชไว้ และการแคชจะถูกปิดใช้งานหากค่านี้เป็นศูนย์ โปรดอ่านสิ่งที่แพ็กเกจของคุณติดตั้งไว้แล้วใน /etc/cgitrc ก่อนที่จะเพิ่มบรรทัดใดๆ เนื่องจากแพ็กเกจของ Debian และ Ubuntu มีการตั้งค่าเริ่มต้นมาให้แล้ว
แต่ละรายการจะแสดงบรรทัดแรกของไฟล์ description ใน repository นั้นๆ ดังนั้น bare repo ที่สร้างใหม่จะแสดงชื่อว่า Unnamed repository; edit this file 'description' to name the repository. ให้แก้ไขปัญหานี้ทีละ 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 Listenroot /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 แสดงว่า socket unit ไม่ได้ทำงานหรือกำลังฟังอยู่ที่ path อื่น บรรทัด systemctl show จะแสดง path ที่ใช้งานจริง
มีข้อจำกัดสองประการที่ควรทราบก่อนเริ่มใช้งาน cgit เป็นแบบอ่านได้อย่างเดียวและไม่มีระบบล็อกอิน ดังนั้นทุกอย่างภายใต้ scan-path จะเป็นสาธารณะ: ควรเก็บ repository ส่วนตัวไว้นอกไดเรกทอรีดังกล่าว หรือใช้ HTTP basic authentication ครอบทั้งเว็บไซต์ไว้ และเนื่องจาก CGI ทำงานในฐานะผู้ใช้ของเว็บเซิร์ฟเวอร์ ผู้ใช้รายนั้นจึงจำเป็นต้องมีสิทธิ์เข้าถึง /srv/git และอ่านไฟล์ในแต่ละ repository ได้ ไดเรกทอรีที่ผู้ใช้ไม่สามารถเข้าถึงได้จะแสดงผลเป็นรายการว่างเปล่าแทนที่จะแสดงข้อผิดพลาด
Tier 2: Forgejo หรือ Gitea สำหรับจัดการ issues และ pull requests
Forgejo และ Gitea มีแนวคิดเดียวกัน คือเป็น Go binary ไฟล์เดียวที่ทำหน้าที่เป็น web forge ซึ่งรองรับผู้ใช้, องค์กร, issues, pull requests, releases, package registry และระบบ CI ในตัว การติดตั้งทำได้เพียงใช้ binary ร่วมกับ SQLite ซึ่งเป็นเหตุผลว่าทำไมซอฟต์แวร์เหล่านี้จึงทำงานบนฮาร์ดแวร์ที่ GitLab ไม่สามารถรันได้ ไฟล์ Compose ด้านล่างนี้เป็นไฟล์ที่ระบุไว้ในเอกสารประกอบของ Forgejo โดยใช้ image tag ตามที่ระบุไว้ ณ เดือนสิงหาคม 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 status line หากคุณยังไม่ได้ตั้งค่าการใช้งานครั้งแรก อาจมีการ redirect ไปยัง /install ซึ่งยังคงหมายความว่าบริการทำงานอยู่ หาก container หยุดทำงานแทน สาเหตุที่พบบ่อยคือเรื่องสิทธิ์การเข้าถึง (ownership): ไดเรกทอรี ./forgejo ต้องเป็นของ UID (user id) ที่ระบุใน USER_UID ไม่เช่นนั้นกระบวนการจะไม่สามารถเขียนข้อมูลลงในไดเรกทอรีของตนเองได้ Docker Compose บน VPS ได้อธิบายโครงสร้างไฟล์และกฎเรื่อง volume ownership ไว้โดยละเอียด
การตั้งค่าสองรายการในหน้า setup จะเป็นตัวกำหนดว่า clone URL จะทำงานได้หรือไม่ พอร์ต SSH ต้องเป็น 222 เนื่องจากไฟล์ Compose ทำการแมปพอร์ต 222 ของโฮสต์ไปยังพอร์ต 22 ของ container และโดเมนต้องเป็นชื่อที่ผู้ใช้พิมพ์จริง หากตั้งค่าผิดพลาด หน้า repository ทุกหน้าจะแสดงคำสั่ง clone ที่ใช้งานไม่ได้สำหรับทุกคนที่คัดลอกไปใช้ ทั้งสองค่านี้จะอยู่ในส่วน [server] ของไฟล์ app.ini ในภายหลัง โดยระบุเป็น SSH_PORT, SSH_DOMAIN และ ROOT_URL
สำหรับการใช้งานแบบสาธารณะ ให้เปิดพอร์ตเว็บเฉพาะบน loopback address ('127.0.0.1:3000:3000') และใช้ nginx เป็นหน้าด่านเพื่อจัดการ TLS (transport layer security) การติดตั้ง Gitea ใช้วิธีเดียวกันจาก image gitea/gitea หรือติดตั้งเป็น binary ไฟล์เดียวพร้อม systemd unit หนึ่งตัวและไฟล์ app.ini หนึ่งไฟล์ โดยรุ่นเสถียรปัจจุบันคือ 1.27.1 ณ เดือนสิงหาคม 2026
ควรใช้ SQLite ต่อไปตราบเท่าที่ทำได้ เพราะจะทำให้ instance มีเพียงกระบวนการเดียวและไฟล์เดียว และสามารถกลับมาทำงานได้หลังรีบูตโดยไม่ต้องมีบริการอื่นมาคอยดูแล PostgreSQL จะคุ้มค่าเมื่อมีผู้ใช้หลายคนเขียนข้อมูลพร้อมกัน เนื่องจาก SQLite จะจัดลำดับการเขียนข้อมูล และการรัน CI นานๆ จะมีการเขียนข้อมูลตลอดเวลา ทั้งสองโปรเจกต์สามารถย้าย instance ที่มีอยู่ไปยัง PostgreSQL ได้ในภายหลัง ดังนั้นการตัดสินใจนี้จึงไม่ใช่ข้อผูกมัดถาวร
Forgejo หรือ Gitea: อะไรคือความแตกต่างที่แท้จริง
ทั้งสองโครงการมีต้นกำเนิดร่วมกัน โดย Gitea แยกตัว (fork) ออกมาจาก Gogs ในปี 2016 ต่อมาในช่วงปลายปี 2022 สิทธิ์ในการควบคุมโดเมนและเครื่องหมายการค้าของ Gitea ได้ถูกโอนไปยังบริษัทที่ชื่อว่า Gitea Ltd ส่งผลให้ผู้ดูแลโครงการจำนวนหนึ่งร่วมกับ Codeberg ได้เริ่มพัฒนา Forgejo ขึ้นมา Forgejo เผยแพร่โดย Codeberg e.V. ซึ่งเป็นสมาคมไม่แสวงหาผลกำไรที่จดทะเบียนในประเทศเยอรมนี และได้เปลี่ยนสัญญาอนุญาตจาก MIT มาเป็น GPLv3 (GNU general public license version 3) ในปี 2024 ส่วน Gitea ยังคงใช้สัญญาอนุญาตแบบ MIT และมีการพัฒนาโดยมีบริษัทเชิงพาณิชย์ให้การสนับสนุน
ในแง่การใช้งานประจำวัน ชุดฟีเจอร์ของทั้งสองมีความใกล้เคียงกันมาก แต่เส้นทางการเปลี่ยนผ่านระหว่างกันนั้นทำได้ยาก Forgejo v10.0 ซึ่งออกเมื่อเดือนมกราคม 2025 เป็นเวอร์ชันสุดท้ายที่สามารถรองรับฐานข้อมูลจาก Gitea ได้โดยตรง และรองรับเฉพาะ Gitea v1.22 หรือเก่ากว่าเท่านั้น ในขณะที่ Gitea ได้ก้าวไปถึงเวอร์ชัน 1.27.1 ณ เดือนสิงหาคม 2026 ดังนั้น อินสแตนซ์ของ Gitea ในปัจจุบันจึงไม่มีวิธีการเปลี่ยนไปใช้ Forgejo แบบแทนที่ได้ทันที (in-place switch) ที่รองรับอย่างเป็นทางการ คุณควรเลือกตัวใดตัวหนึ่งก่อนที่จะเริ่มใส่ข้อมูล และให้ถือว่าการย้ายในภายหลังคือการส่งออก (export) และนำเข้า (re-import) ข้อมูลใหม่ทั้งหมด
กฎสั้นๆ ในการตัดสินใจเลือก หากคุณให้ความสำคัญกับธรรมาภิบาลหรือต้องการให้โครงการอยู่ภายใต้การดูแลขององค์กรไม่แสวงหาผลกำไร ให้เลือกใช้ Forgejo หากคุณต้องการฐานผู้ใช้งานที่ใหญ่กว่าและตัวเลือกในการสนับสนุนเชิงพาณิชย์ ให้เลือกใช้ Gitea ทั้งสองโครงการมีการดูแลรักษาแบบเปิดเผยและมีการออกเวอร์ชันใหม่บ่อยครั้ง โดย Forgejo จะออกเวอร์ชันเสถียรทุกสามเดือนและเวอร์ชัน LTS (long term support) ปีละหนึ่งครั้ง ซึ่ง ณ เดือนสิงหาคม 2026 เวอร์ชันปัจจุบันคือ v16.0.2 และเวอร์ชัน LTS คือ v15.0.6
ระดับ 3: ต้นทุนของ GitLab ก่อนเริ่มใช้งานจริง
GitLab CE เป็นซอฟต์แวร์อีกระดับหนึ่ง อินสแตนซ์หนึ่งชุดประกอบด้วยบริการที่ทำงานร่วมกันหลายตัว ได้แก่ Puma สำหรับเว็บแอปพลิเคชัน, Sidekiq สำหรับงานเบื้องหลัง, PostgreSQL, Redis, Gitaly สำหรับการเข้าถึง repository และ nginx ที่ทำหน้าที่เป็นหน้าด่าน แพ็กเกจ Omnibus จะติดตั้งบริการเหล่านี้รวมกัน ซึ่งทำให้การติดตั้งทำได้ง่าย แต่ก็ทำให้มีความต้องการหน่วยความจำขั้นต่ำที่สูงมาก
หน้าเอกสารความต้องการของ GitLab ระบุว่าต้องใช้ RAM 16 GB และ 8 vCPU เป็นค่าพื้นฐานสำหรับการติดตั้งบนโหนดเดียว โดยระบุว่า 8 GB เป็นค่าต่ำสุดสำหรับสภาพแวดล้อมที่มีข้อจำกัดด้านหน่วยความจำ หน้าเดียวกันนี้ยังแนะนำให้ปิดการใช้งาน swap เนื่องจากหากมีการทำ swapping ขณะที่ระบบรับภาระงานหนัก จะทำให้อินสแตนซ์ทำงานได้แย่ลงอย่างมาก ตัวเลขเหล่านี้เป็นข้อมูลที่เผยแพร่อย่างเป็นทางการ ณ เดือนสิงหาคม 2026 และมีแนวโน้มเพิ่มสูงขึ้นตามกาลเวลา ดังนั้นโปรดตรวจสอบหน้านี้อีกครั้งก่อนที่คุณจะกำหนดขนาดเซิร์ฟเวอร์
คุณจะได้รับฟีเจอร์ที่ใช้งานได้จริงแลกกับทรัพยากรที่เสียไป เช่น container registry, package registry, การจัดการสิทธิ์ที่ละเอียด, ฟีเจอร์ด้านการปฏิบัติตามกฎระเบียบและการตรวจสอบ (audit) รวมถึง CI ที่ผ่านการทดสอบในระดับสเกลใหญ่มาแล้ว หากไม่มีใครในทีมของคุณระบุได้ว่าต้องการฟีเจอร์ใดจากรายการเหล่านี้ในไตรมาสนี้ แสดงว่าคุณกำลังจ่ายเงินค่า VPS ขนาดใหญ่ขึ้นโดยไม่ได้รับประโยชน์ใดๆ กลับมาเลย
รูปแบบการเข้าถึงผ่าน SSH: ผู้ใช้ git หนึ่งบัญชีกับกุญแจจำนวนมาก
ทุกระดับชั้นที่นี่ใช้วิธีการยืนยันตัวตนแบบเดียวกัน โดยมีบัญชีผู้ใช้ Unix หนึ่งบัญชีชื่อ git และกุญแจสาธารณะทั้งหมดจะถูกเก็บไว้ใน ~/.ssh/authorized_keys ของบัญชีนั้น การยืนยันตัวตนขึ้นอยู่กับกุญแจ ส่วนการอนุญาตสิทธิ์จะขึ้นอยู่กับตัวเลือกที่คุณระบุไว้หน้ากุญแจในบรรทัดเดียวกัน
บรรทัดกุญแจแบบปกติจะมอบสิทธิ์ทั้งหมดที่บัญชีนั้นทำได้ให้กับผู้ถือครองกุญแจ แต่การใช้ forced command จะจำกัดสิทธิ์ให้เหลือเพียงการใช้งาน Git เท่านั้น:
restrict,command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptoprestrict ซึ่งมีให้ใช้งานตั้งแต่ OpenSSH 7.2 จะปิดการทำ port forwarding, agent forwarding, X11 และการจัดสรร PTY (pseudo terminal) ทั้งหมดในคำสั่งเดียว ส่วน command= จะเข้ามาแทนที่คำสั่งที่ไคลเอนต์ร้องขอด้วยคำสั่งที่คุณกำหนด ซึ่ง Git ยังคงทำงานได้ตามปกติเนื่องจาก Git จะส่งคำขอผ่าน $SSH_ORIGINAL_COMMAND
ระบบ Forge จะเขียนไฟล์ดังกล่าวให้คุณโดยอัตโนมัติ ซึ่งนี่คือความแตกต่างที่แท้จริงระหว่างระดับ 0 และระดับ 2 โดย Forgejo และ Gitea จะเขียนไฟล์ authorized_keys ใหม่โดยให้หนึ่งบรรทัดต่อหนึ่งกุญแจที่ลงทะเบียนไว้ แต่ละบรรทัดจะมี forced command ที่ระบุชื่อกุญแจตามรหัสในฐานข้อมูล:
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 aliceforced command ดังกล่าวคือวิธีที่ทำให้บัญชี Unix บัญชีเดียวที่ใช้ร่วมกันสามารถแยกสิทธิ์ตามรายบุคคลได้ โดย key-3 จะแจ้งให้ระบบ Forge ทราบว่าผู้ใช้คนใดกำลังเชื่อมต่อเข้ามา และระบบจะตรวจสอบสิทธิ์ของผู้ใช้นั้นกับ repository ก่อนที่จะมีการย้ายข้อมูลใดๆ ห้ามแก้ไขไฟล์ดังกล่าวด้วยตนเองบนเครื่องที่จัดการโดย Forge เพราะระบบจะเขียนไฟล์ทับใหม่จากฐานข้อมูลและบรรทัดที่คุณเพิ่มไว้จะหายไป Deploy keys ก็ใช้กลไกเดียวกันนี้ โดย deploy key คือกุญแจ SSH ปกติที่ลงทะเบียนไว้กับ repository เดียว ซึ่งมักจะเป็นแบบอ่านอย่างเดียว โดยการตรวจสอบจะเกิดขึ้นในระบบ Forge แทนที่จะเป็นใน sshd
มีสองนิสัยที่สำคัญยิ่งกว่าการตั้งค่าใดๆ ที่กล่าวมาข้างต้น คือการออกกุญแจหนึ่งดอกต่อหนึ่งคนหรือหนึ่งเครื่อง ห้ามใช้กุญแจร่วมกันเด็ดขาด เพราะการเพิกถอนกุญแจที่ใช้ร่วมกันหมายถึงคุณต้องเปลี่ยนกุญแจใหม่ให้กับทุกคนพร้อมกัน และต้องลบกุญแจทิ้งทันทีในวันที่พนักงานลาออก เนื่องจากกุญแจเก่าที่ค้างอยู่ในไฟล์นั้นคือช่องทางเข้าสู่ระบบถาวรที่ไม่มีใครคอยตรวจสอบ การจัดการกุญแจ SSH บนเซิร์ฟเวอร์อย่างถูกวิธี ครอบคลุมถึงประเภทของกุญแจและรหัสผ่าน ซึ่งทั้งหมดนี้สามารถนำมาประยุกต์ใช้ได้โดยไม่ต้องเปลี่ยนแปลง หากคุณเพิ่งเริ่มใช้งานเซิร์ฟเวอร์ใหม่ สิบนาทีแรกบน VPS ใหม่ คือสิ่งที่คุณควรทำก่อนที่จะนำ repository ไปวางไว้บนนั้น
ฉันสามารถรัน GitHub Actions บนเซิร์ฟเวอร์ Git ของตัวเองได้หรือไม่
คุณสามารถรันเวิร์กโฟลว์ที่เขียนด้วยไวยากรณ์ของ GitHub Actions ได้ แต่คุณไม่สามารถรัน GitHub ได้ โดย Forgejo Actions ได้ถูกเปิดใช้งานเป็นค่าเริ่มต้นตั้งแต่ Forgejo v1.21 เป็นต้นไป ซึ่งจะอ่านไฟล์เวิร์กโฟลว์จาก .forgejo/workflows ในแต่ละที่เก็บข้อมูล (repository) ส่วน Gitea Actions ก็ทำงานในลักษณะเดียวกันโดยอ่านจาก .gitea/workflows ทั้งสองระบบจำเป็นต้องมีโปรแกรมตัวที่สองที่เรียกว่า runner ซึ่งต้องติดตั้งและลงทะเบียนกับอินสแตนซ์ของคุณโดยใช้โทเค็นจากการตั้งค่าของผู้ดูแลระบบ (admin settings) การกระทำ (actions) ที่เผยแพร่ไว้จำนวนมากสามารถรันได้โดยไม่ต้องแก้ไข แต่การกระทำใดก็ตามที่เรียกใช้ GitHub API หรือคาดหวังโครงสร้างพื้นฐานที่โฮสต์โดย GitHub จะไม่สามารถทำงานได้
โปรดวางแผนรับมือกับผลกระทบสองประการ ประการแรก runner จะเริ่มคอนเทนเนอร์สำหรับทุกงาน ดังนั้นจึงจำเป็นต้องมี container engine และจัดสรรหน่วยความจำแยกต่างหาก ซึ่งเป็นเหตุผลว่าทำไมจึงไม่ควรติดตั้งไว้บนเครื่องขนาด 1 GB เครื่องเดียวกับที่รัน forge ประการที่สอง runner จะดำเนินการตามที่ไฟล์เวิร์กโฟลว์ระบุไว้ทุกประการ ซึ่งเอกสารของ Forgejo ได้ระบุไว้อย่างชัดเจนว่า runner จะดำเนินการรันโค้ดจากระยะไกล (remote code execution) ดังนั้นหากเป็นไปได้ควรแยกโฮสต์สำหรับ runner โดยเฉพาะ หรืออย่างน้อยที่สุดควรใช้ผู้ใช้ที่ไม่มีสิทธิ์พิเศษ (unprivileged user) และใช้โทเค็นการลงทะเบียนที่จำกัดขอบเขตไว้เพียงที่เก็บข้อมูลเดียว
หากที่เก็บข้อมูลของคุณยังคงอยู่บน GitHub และคุณต้องการเพียงแค่ทรัพยากรประมวลผลบนฮาร์ดแวร์ที่คุณควบคุมเอง นั่นจะเป็นการตั้งค่าที่แตกต่างออกไปและมีขั้นตอนที่ต่างกัน: a self-hosted GitHub Actions runner จะเชื่อมต่อกับที่เก็บข้อมูลบน GitHub โดยไม่จำเป็นต้องใช้ขั้นตอนเหล่านี้ หากคุณยังคงพิจารณาถึงต้นทุนในการย้ายออก what GitHub actually gives you จะช่วยแยกแยะระหว่างการโฮสต์ Git กับเครือข่ายที่ล้อมรอบบริการนั้นไว้
การสำรองข้อมูล: repository เป็นเพียงสถานะส่วนหนึ่งเท่านั้น
Bare repository เป็นเพียงไดเรกทอรี ดังนั้นการคัดลอกจึงเป็นการคัดลอกทุกอย่างที่อยู่ภายใน การทำ mirror clone จากเครื่องอื่นถือเป็นการสำรองข้อมูลที่แท้จริง และสามารถอัปเดตข้อมูลในตัวได้ทันที:
git clone --mirror git@vps.example.com:/srv/git/project.git
cd project.git && git remote updateคำสั่งนี้จะดึงทุก ref และทุก object มาทั้งหมด แต่จะไม่ดึง server-side hooks หรือไฟล์ description มาด้วย ดังนั้นหากคุณมีการใช้งาน hooks ควรสำรองข้อมูลในระดับไฟล์ของไดเรกทอรีนั้นไว้ด้วย
ระบบ forge จะเก็บข้อมูล issues, pull requests, ผู้ใช้งาน, keys และสิทธิ์ต่างๆ ไว้ในฐานข้อมูล การคัดลอกเฉพาะ repository จะทำให้ข้อมูลเหล่านี้สูญหายไปทั้งหมด ทั้งสองโปรเจกต์มีคำสั่ง dump สำหรับเขียนฐานข้อมูล, repository, การตั้งค่า และไฟล์แนบลงในไฟล์ archive เดียวกัน:
sudo -u git forgejo dump -c /etc/forgejo/app.ini -f /var/backups/forgejo-dump.zipหากใช้งานผ่าน Docker คำสั่งเดียวกันนี้จะต้องรันภายใน container และ path ของการตั้งค่าจะขึ้นอยู่กับ image ที่ใช้ ดังนั้นควรตรวจสอบให้แน่ใจก่อนพิมพ์คำสั่ง:
docker compose exec server ls /data/gitea/conf
docker compose exec -u git server forgejo dump -c /data/gitea/conf/app.iniให้รันคำสั่งในฐานะผู้ใช้งานที่เป็นเจ้าของข้อมูล และเขียนไฟล์ archive ลงในไดเรกทอรีที่ผู้ใช้งานนั้นมีสิทธิ์เขียน จากนั้นให้คัดลอกไฟล์ archive ออกจากเซิร์ฟเวอร์ เพราะการสำรองข้อมูลที่เก็บไว้เพียงบนเครื่องที่ถูกสำรองข้อมูลนั้น ไม่ถือว่าเป็นการสำรองข้อมูลที่ปลอดภัย การกู้คืนข้อมูลเป็นขั้นตอนที่คนมักมองข้าม: ให้ลองแตกไฟล์ dump ลงในเครื่องสำรองตั้งแต่วันนี้ เพื่อให้คุณเรียนรู้ขั้นตอนในสถานการณ์ปกติ แทนที่จะต้องมาเรียนรู้ในขณะที่ระบบเกิดปัญหาจริง
เลือกตามสถานการณ์
สำหรับผู้ใช้คนเดียวที่มีแล็ปท็อปและ VPS โดยไม่จำเป็นต้องเรียกดูผ่านเบราว์เซอร์: ให้ใช้ bare repositories ผ่าน SSH วิธีนี้ไม่มีบริการส่วนเกินให้รันและไม่มีสิ่งที่ต้องอัปเกรด
กรณีเดียวกันแต่ต้องการอ่านโค้ดผ่านเบราว์เซอร์และส่งลิงก์ได้: ให้เพิ่ม cgit เข้าไป วิธีนี้ยังคงไม่ต้องใช้ฐานข้อมูลและไม่มีบริการที่ต้องรันค้างไว้ในหน่วยความจำ
สำหรับทีมที่ต้องการรีวิวโค้ดและติดตามปัญหา (issue tracking): ให้ใช้ Forgejo หรือ Gitea โดยต้องมี RAM ขนาด 2 GB ขึ้นไป หากงาน CI เริ่มมีปริมาณมาก ให้ย้าย CI runner ไปยังเซิร์ฟเวอร์เครื่องที่สอง
สำหรับองค์กรที่ต้องการ container registry และระบบตรวจสอบย้อนกลับ (audit trails) โดยมีงบประมาณ RAM สำหรับเซิร์ฟเวอร์ 16 GB: ให้ใช้ GitLab หากมีทรัพยากรน้อยกว่านี้ ไม่แนะนำให้เริ่มใช้งาน
การขยับขยายจากสามระดับแรกทำได้ง่ายและประหยัด เนื่องจากทั้งสามระดับใช้ Git repositories แบบปกติที่จัดเก็บอยู่บนดิสก์ ให้เริ่มต้นจากระดับต่ำสุดที่ตอบโจทย์การใช้งานของคุณ หากคุณกำลังพิจารณาว่ามีบริการอื่นใดที่ควรติดตั้งบนเซิร์ฟเวอร์เดียวกัน รายการบริการที่คุ้มค่าแก่การ self-host จะช่วยเปรียบเทียบ Git server กับบริการอื่นๆ ที่ต้องแย่งชิงทรัพยากร RAM ในเครื่องเดียวกัน
FAQ
VPS ขนาด 1 GB สามารถรัน Forgejo หรือ Gitea ได้หรือไม่?
ได้ สำหรับทีมขนาดเล็กที่ใช้ SQLite และไม่มีแอปพลิเคชันอื่นที่กินทรัพยากรสูงรันอยู่บนเครื่องเดียวกัน เอกสารของ Gitea ระบุว่า RAM ขนาด 1 GB และ CPU 2 คอร์ เพียงพอสำหรับการใช้งานในทีมและโปรเจกต์ขนาดเล็ก ส่วน Forgejo เป็น fork ของ Gitea ที่มีลักษณะการทำงานเหมือนกัน ห้ามติดตั้ง PostgreSQL หรือ CI runner เพิ่มบนเครื่องนี้ หากบริการหยุดทำงานโดยไม่มีข้อความผิดพลาดใน log ของตัวเอง ให้รันคำสั่ง sudo dmesg -T | grep -i oom หากพบชื่อ process ในบรรทัดที่ถูกระบุว่าถูก kill แสดงว่า kernel ทำการเรียกใช้ out of memory killer วิธีแก้ไขคือการขยายสเปกเครื่องแทนการปรับแต่งค่า flag
Forgejo และ Gitea แตกต่างกันอย่างไร?
ทั้งสองโครงการมีประวัติ codebase และฟีเจอร์ส่วนใหญ่ร่วมกัน Gitea fork มาจาก Gogs ในปี 2016 และ Forgejo fork มาจาก Gitea ในช่วงปลายปี 2022 หลังจากสิทธิ์ในเครื่องหมายการค้า Gitea ถูกโอนไปยังบริษัทแห่งหนึ่ง Forgejo เผยแพร่โดย Codeberg e.V. ซึ่งเป็นองค์กรไม่แสวงหาผลกำไรในเยอรมนี ภายใต้สัญญาอนุญาต GPLv3 ส่วน Gitea ยังคงใช้สัญญาอนุญาต MIT และมีบริษัทสนับสนุน ความแตกต่างในทางปฏิบัติคือเส้นทางการย้ายข้อมูล Forgejo v10.0 ซึ่งออกเมื่อเดือนมกราคม 2025 เป็น release สุดท้ายที่สามารถอ่านฐานข้อมูลจาก Gitea ได้โดยตรง และรองรับเฉพาะ Gitea v1.22 หรือเก่ากว่าเท่านั้น ดังนั้น instance ของ Gitea ในปัจจุบันจึงไม่มีวิธีการสลับมาใช้ Forgejo แบบ in-place ที่รองรับอย่างเป็นทางการ
ฉันสามารถรัน GitHub Actions workflows บนเซิร์ฟเวอร์ Git ที่ self-host เองได้หรือไม่?
ทั้ง Forgejo Actions และ Gitea Actions สามารถรัน workflow ที่เขียนด้วยไวยากรณ์ YAML ของ GitHub Actions ซึ่งอ่านจาก .forgejo/workflows และ .gitea/workflows คุณต้องติดตั้งโปรแกรม runner แยกต่างหากและลงทะเบียนกับ instance ของคุณ Action ที่เผยแพร่ไว้จำนวนมากสามารถทำงานได้โดยไม่ต้องแก้ไข แต่ action ใดก็ตามที่เรียกใช้ GitHub API จะไม่สามารถทำงานได้ เนื่องจาก runner จะประมวลผลโค้ดจาก repository ของคุณและเริ่ม container แยกสำหรับแต่ละ job คุณจึงควรแยกเครื่องสำหรับรันงานนี้ หรืออย่างน้อยต้องรันด้วย user ที่ไม่มีสิทธิ์พิเศษ และไม่ควรนำไปรันบนเซิร์ฟเวอร์ขนาด 1 GB ที่กำลังรันตัว forge อยู่แล้ว
ฉันจะสำรองข้อมูลเซิร์ฟเวอร์ Git ที่ self-host เองได้อย่างไร?
สำหรับ bare repositories การใช้ git clone --mirror จากเครื่องอื่นจะคัดลอกทุก ref และ object ออกมา และการใช้ git remote update ภายใน mirror นั้นจะเป็นการอัปเดตข้อมูล สำหรับ Forgejo หรือ Gitea ตัว repository เป็นเพียงส่วนหนึ่งของสถานะระบบเท่านั้น เนื่องจาก issues, pull requests, ผู้ใช้งาน และ key ต่างๆ จะถูกเก็บไว้ในฐานข้อมูล ให้ใช้คำสั่ง dump ที่มีมาให้ในตัวคือ sudo -u git forgejo dump -c /etc/forgejo/app.ini หรือใช้คำสั่งเดียวกันภายใน container หากติดตั้งผ่าน Docker ให้คัดลอกไฟล์ archive ออกจากเซิร์ฟเวอร์ และลองกู้คืนข้อมูลลงในเครื่องสำรองอย่างน้อยหนึ่งครั้งเพื่อให้มั่นใจว่าขั้นตอนการทำงานถูกต้อง