- GitLab CE (Community Edition) là full DevOps platform open-source: Git hosting + CI/CD + Container Registry + Issue tracker.
- Self-host trên VPS 8GB RAM, 80GB SSD. Setup bằng Omnibus package (1 lệnh apt) hoặc Docker.
- CI/CD runner riêng có thể chạy trên VPS khác để không nặng GitLab server. Mỗi pipeline có executors: shell, docker, kubernetes.
- Tiết kiệm: GitLab.com Premium 29 USD/user/tháng. Self-host CE free unlimited user (chỉ cần VPS ~50 USD).
- Bài này hướng dẫn full: cài, config, tạo project, viết .gitlab-ci.yml multi-stage, register runner, deploy automation.
GitHub là chuẩn cho code hosting public, nhưng cho code private nội bộ công ty Việt Nam, GitLab Community Edition đang là lựa chọn phổ biến: free unlimited user, full DevOps stack từ Git hosting tới CI/CD tới Container Registry, data hoàn toàn nội bộ. Bài này hướng dẫn dựng GitLab CE production trên VPS, viết pipeline CI/CD đầy đủ build-test-deploy, register runner riêng để tiết kiệm tài nguyên server chính.
Test trên Cloud VPS 80 (8GB RAM, 80GB SSD CEPH) chạy Ubuntu 24.04. Workload thử nghiệm: 5 dev, 20 repository, 100 pipeline/ngày, vài Docker image build/push. Sau bài này bạn có một "GitHub nội bộ" + CI/CD chạy unlimited, không phụ thuộc GitHub Actions quota.
GitLab CE so với GitHub Enterprise, Gitea
| Tiêu chí | GitLab CE | GitHub Enterprise (self) | Gitea |
|---|---|---|---|
| License | MIT (CE) | Commercial | MIT |
| Giá | Free | 21 USD/user/tháng | Free |
| CI/CD built-in | Có | GitHub Actions | Gitea Actions (mới) |
| Container Registry | Có | Có | Có (mới) |
| Issue tracker | Đầy đủ | Đầy đủ | Cơ bản |
| RAM yêu cầu | 8 GB | 16+ GB | 512 MB |
| Phù hợp | Team 5-100 | Enterprise lớn | Cá nhân/team rất nhỏ |
GitLab CE đầy đủ tính năng nhất trong nhóm free. Gitea nhẹ hơn nhưng CI/CD chưa stable bằng. GitHub Enterprise đắt.
Bước 1: Yêu cầu VPS
- Tối thiểu 4 vCPU, 8 GB RAM, 80 GB SSD cho 5-20 dev.
- Khuyến nghị 8 vCPU, 16 GB RAM cho 50+ dev và nhiều pipeline.
- OS: Ubuntu 22.04/24.04 LTS hoặc AlmaLinux 9.
- Domain để đặt subdomain gitlab.your-domain.com.
- Tách runner ra VPS khác để không nặng GitLab server (khuyến nghị).
Bước 2: Cài GitLab CE bằng Omnibus
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo EXTERNAL_URL="https://gitlab.your-domain.com" apt install -y gitlab-ce
Quá trình cài mất 5-10 phút. Omnibus package gồm GitLab Rails, Sidekiq, Postgres, Redis, Nginx, Puma, Gitaly, Workhorse, Mattermost (optional), Container Registry. Tất cả trong 1 deb, dễ update.
Reconfigure (chạy mỗi khi sửa /etc/gitlab/gitlab.rb):
sudo gitlab-ctl reconfigure
Lấy root password ban đầu:
sudo cat /etc/gitlab/initial_root_password
Truy cập https://gitlab.your-domain.com, login user "root" + password. Đổi password ngay trong Profile.
Bước 3: Cấu hình HTTPS với Let's Encrypt
GitLab Omnibus có built-in Let's Encrypt. Sửa /etc/gitlab/gitlab.rb:
external_url 'https://gitlab.your-domain.com'
letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['[email protected]']
letsencrypt['auto_renew'] = true
letsencrypt['auto_renew_hour'] = 3
sudo gitlab-ctl reconfigure
GitLab tự xin cert, configure Nginx HTTPS. Auto renew 3 giờ sáng.
Bước 4: Disable signup public
Tránh bot register spam. Vào Admin Area > Settings > General > Sign-up restrictions:
- Uncheck "Sign-up enabled".
- Hoặc giữ enabled + "Require admin approval" + "Domain restriction" (chỉ email @your-domain.com).
Bạn invite user qua Members trong Project hoặc Admin Area.
Bước 5: Tạo project và clone
- Sidebar > New project > Create blank project.
- Project name "myapp", Visibility Private.
- Copy git URL: [email protected]:root/myapp.git.
- Add SSH key vào Profile > SSH Keys.
- Local:
git clone [email protected]:root/myapp.git.
Bước 6: Viết .gitlab-ci.yml đầu tiên
stages:
- build
- test
- deploy
variables:
NODE_VERSION: "20"
build:
stage: build
image: node:20-alpine
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- node_modules/
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
test:
stage: test
image: node:20-alpine
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- node_modules/
policy: pull
script:
- npm test
coverage: '/Liness*:s*(d+.d+)/'
deploy:
stage: deploy
image: alpine:latest
only:
- main
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | ssh-add -
- mkdir -p ~/.ssh && chmod 700 ~/.ssh
- ssh-keyscan $DEPLOY_HOST >> ~/.ssh/known_hosts
script:
- rsync -avz --delete dist/ deploy@$DEPLOY_HOST:/var/www/myapp/
- ssh deploy@$DEPLOY_HOST "pm2 reload myapp"
Commit và push. Pipeline tự chạy: build > test > deploy. Vào Project > Pipelines xem progress.
Variable SSH_PRIVATE_KEY và DEPLOY_HOST set trong Settings > CI/CD > Variables (marked as Protected, Masked).
Bước 7: Register GitLab Runner trên VPS khác
Mặc định GitLab dùng runner shared (chạy trên cùng server). Tách runner ra giảm load:
Trên VPS runner (Cloud VPS 50):
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt install -y gitlab-runner
sudo gitlab-runner register
Wizard hỏi:
- URL: https://gitlab.your-domain.com
- Token: lấy từ Admin Area > CI/CD > Runners > Register an instance runner
- Description: "vps-runner-01"
- Tags: linux,docker,vn
- Executor: docker (recommended)
- Default image: alpine:latest
Runner đăng ký xong, hiện online trong GitLab UI. Pipeline mới sẽ chạy trên runner này.
Bước 8: Container Registry
GitLab CE có Container Registry built-in. Bật trong /etc/gitlab/gitlab.rb:
registry_external_url 'https://registry.your-domain.com'
sudo gitlab-ctl reconfigure
Trong .gitlab-ci.yml build và push image:
build-image:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $CI_REGISTRY_IMAGE:latest
Image lưu trong registry GitLab, pull về production qua:
docker login registry.your-domain.com
docker pull registry.your-domain.com/root/myapp:latest
Bước 9: Merge Request workflow
- Dev tạo branch feature/xxx.
- Push branch, GitLab gợi ý "Create merge request".
- Tạo MR, gán reviewer.
- Pipeline tự chạy trên branch.
- Reviewer comment, request change.
- Dev push fix, pipeline rerun.
- Approved + pipeline pass > Merge.
- Pipeline trên main tự chạy deploy stage.
Setup Branch Protection: Settings > Repository > Protected branches > main. Tick "Require approval from code owners". Đảm bảo không ai push thẳng vào main.
Backup GitLab
sudo gitlab-backup create STRATEGY=copy
# File trong /var/opt/gitlab/backups/
sudo cp /etc/gitlab/gitlab-secrets.json /backup/ # CRITICAL
sudo cp /etc/gitlab/gitlab.rb /backup/
Cron daily:
0 3 * * * /opt/gitlab/bin/gitlab-backup create CRON=1
0 4 * * * rclone copy /var/opt/gitlab/backups/ b2:gitlab-backup/
QUAN TRỌNG: gitlab-secrets.json chứa key encrypt. Mất file này = không restore được dù có data backup.
Update GitLab
sudo apt update
sudo apt install gitlab-ce
sudo gitlab-ctl reconfigure
GitLab có policy update theo major version path (15.x > 16.0.x > 16.x latest > 17.0.x). Đọc upgrade docs khi nhảy major. Backup trước.
Monitor và performance
GitLab có Prometheus + Grafana built-in. Bật trong gitlab.rb:
prometheus_monitoring['enable'] = true
grafana['enable'] = true
Truy cập https://gitlab.your-domain.com/-/grafana xem dashboard built-in. Quan trọng: theo dõi RAM Sidekiq (job queue), Postgres connection, Nginx request rate.
Lỗi phổ biến
- 502 Bad Gateway: GitLab chưa start xong (mất 60-120 giây sau reboot). Đợi rồi reload.
- "Repository is empty" sau clone: chưa tạo branch main. Initialize repo bằng button trong UI.
- Pipeline stuck "pending": không có runner online với tag tương ứng. Kiểm tra Admin > Runners.
- Out of memory: Sidekiq ngốn RAM khi nhiều job. Tăng VPS RAM hoặc giảm sidekiq['max_concurrency'].
- Disk full /var/opt/gitlab: log Postgres và Sidekiq lớn. Đặt logrotate hoặc giảm log level.
FAQ
GitLab CE thiếu tính năng gì so với Premium/Ultimate?
Premium thêm: code owner enforcement nâng cao, multi-level approval, merge train, audit log mở rộng. Ultimate thêm security scanning (SAST, DAST), license compliance, value stream analytics. Cho 95 phần trăm team SaaS Việt Nam, CE đủ.
GitLab CE có hỗ trợ SSO không?
Có. OAuth Google, GitHub, Microsoft built-in. SAML cũng có nhưng nhiều cấu hình hơn. LDAP/AD cho enterprise. Config trong /etc/gitlab/gitlab.rb section omniauth_providers.
Chạy GitLab + nhiều runner trên 1 VPS được không?
Được nếu VPS đủ RAM (16GB+). Nhưng khi pipeline build nặng (Docker, multi-arch), runner ngốn CPU/disk, ảnh hưởng response GitLab. Tách runner ra VPS riêng là best practice cho team 5+ dev.
Có thể import từ GitHub sang GitLab không?
Có. Settings > Import project > GitHub. Cần GitHub Personal Access Token. Tool tự import code, branch, issue, PR (thành MR), label, milestone. Mất 5-30 phút tùy repo lớn.
GitLab có CI cache giữa các pipeline không?
Có. Cache: key + paths trong .gitlab-ci.yml. Runner lưu cache vào volume riêng (Docker), reuse cho pipeline tiếp theo. Tăng tốc đáng kể cho npm install, pip install.
Cloud VPS đủ RAM cho GitLab CE + runner dedicated
Cloud VPS TND sẵn AlmaLinux 9, Ubuntu 22/24, Debian 12/13. SSD CEPH, snapshot 1-click, backup hằng ngày, network 200Mbps trong nước. Combo: VPS 80 chạy GitLab + VPS 50 chạy runner, tiết kiệm chi phí tổng so với GitLab.com Premium.
Xem 8 cấu hình Cloud VPS →


