Cấu hình GitLab Runner cho CI/CD trên VPS

Bạn vừa cài xong GitLab CE trên VPS riêng, commit code lên remote, nhưng pipeline cứ đứng im ở trạng thái pending. Đó là vì GitLab chưa có runner nào để nhận job. Runner chính là "con ngựa kéo xe" trong CI/CD: nó nhận lệnh từ GitLab, chạy script trong pipeline, rồi trả kết quả về. Bài này mình sẽ hướng dẫn cài đặt và cấu hình GitLab Runner trên VPS Ubuntu 24.04 từ con số 0, bao gồm cả việc đăng ký runner và viết file .gitlab-ci.yml đầu tiên.
- Tóm tắt nhanh: Cài GitLab Runner bằng apt, đăng ký với token từ giao diện GitLab, chọn executor (shell hoặc docker), và bắt đầu dùng pipeline. Shell executor đơn giản nhưng thiếu cô lập, Docker executor sạch hơn nhưng cần cài Docker. Mọi cấu hình runner nằm trong
config.toml, tài liệu chính thức tạidocs.gitlab.com/runner.
Yêu cầu trước khi bắt đầu
- Một VPS chạy Ubuntu 24.04 LTS (hoặc Debian 12) với user có quyền
sudo. Nếu chưa có, bạn có thể thuê VPS Linux với full root, cài Ubuntu 24.04 ngay từ bước chọn OS. - Một instance GitLab đang chạy: dùng GitLab self-hosted trên VPS riêng, hoặc GitLab.com (miễn phí). Mình khuyên dùng GitLab CE tự host để không giới hạn số phút chạy pipeline.
- Quyền truy cập vào project hoặc group để lấy registration token (bạn cần vai trò Owner hoặc Maintainer).
Vì sao GitLab Runner thiết yếu trong CI/CD
GitLab CI/CD hoạt động theo mô hình client-server. GitLab server (web UI, API, lưu trữ code) chỉ có nhiệm vụ quản lý pipeline, hiển thị log, và giao việc. Còn việc thực thi lệnh thực tế, chạy test, build artifact, deploy lên server... đều do runner đảm nhận. Không có runner, GitLab đúng nghĩa là "ông vua không có lính".
Runner có thể chạy ở nhiều môi trường: trên chính VPS của bạn, trên máy tính cá nhân, hoặc trên một container. Mỗi runner có một hoặc nhiều tag để GitLab biết route job nào sang runner nào. Ví dụ runner có tag docker chỉ nhận job khai báo tag tương ứng trong .gitlab-ci.yml.
Trong bài này mình dùng shell executor cho ví dụ đơn giản nhất, rồi nâng lên docker executor để bạn thấy sự khác biệt. Cả hai đều phổ biến trong thực tế và bạn sẽ gặp chúng ở hầu hết mọi công ty dùng GitLab.
Bước 1 - Cài đặt GitLab Runner trên Ubuntu 24.04
GitLab cung cấp kho apt chính thức. Cách cài đặt chuẩn theo tài liệu của họ như sau:
# Thêm kho GitLab Runner
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
# Cài đặt gitlab-runner
sudo apt update
sudo apt install gitlab-runner -y
# Kiểm tra version và trạng thái service
gitlab-runner --version
systemctl status gitlab-runner --no-pager -l
Lệnh đầu tiên tải script thêm kho từ packages.gitlab.com. Script này tự động cấu hình apt và cài key GPG. Lưu ý bạn nên đọc script trước khi pipe vào bash (mở URL trên trình duyệt), nhưng với GitLab thì đây là cách họ chính thức khuyến nghị nên cũng yên tâm.
Verify: Lệnh gitlab-runner --version sẽ in ra phiên bản, ví dụ Version: 17.x.x. Lệnh systemctl status phải hiển thị active (running). Nếu service chưa chạy, dùng sudo systemctl enable --now gitlab-runner.
Bước 2 - Đăng ký Runner với GitLab
Có hai loại runner: shared runner (dùng chung cho toàn instance) và project runner (chỉ dùng cho một project). Trong bài này mình dùng project runner vì dễ demo và phù hợp nhu cầu cá nhân.
Lấy registration token:
- Vào project → Settings → CI/CD → Runners.
- Mục Project runners, nhìn thấy một token dạng
glrt-xxxxxxxx(hoặcxxxxxxxxvới bản cũ).
Sau khi có token, chạy lệnh đăng ký:
sudo gitlab-runner register
Script sẽ hỏi lần lượt các thông tin:
Enter the GitLab instance URL (for example, https://gitlab.com/):
# Nhập URL instance của bạn, ví dụ https://gitlab.example.com
Enter the registration token:
# Dán token lấy ở bước trên
Enter a description for the runner:
# Ví dụ: my-vps-runner
Enter tags for the runner (comma-separated):
# Ví dụ: docker, linux (bỏ trống nếu không muốn dùng tag)
Enter an executor:
# Chọn docker hoặc shell (dưới đây mình chọn docker)
Enter the default Docker image (for example, ruby:2.7):
# Nhập image mặc định, ví dụ alpine:latest
Sau khi hoàn tất, file cấu hình /etc/gitlab-runner/config.toml sẽ được tạo. Bạn có thể xem nội dung:
sudo cat /etc/gitlab-runner/config.toml
Verify: Quay lại trang Settings → CI/CD → Runners, runner mới hiện với trạng thái Online (chấm xanh). Nếu vẫn hiện "Offline", kiểm tra lại token và URL, hoặc xem log sudo journalctl -u gitlab-runner -n 50.
Bước 3 - Chọn executor: shell hay docker
Đây là quyết định quan trọng nhất khi cấu hình runner. Hai lựa chọn phổ biến:
| Tiêu chí | Shell executor | Docker executor |
|---|---|---|
| Cô lập môi trường | Không, chạy trực tiếp trên VPS | Có, mỗi job chạy trong container riêng |
| Yêu cầu cài đặt | Không cần thêm gì | Cần cài Docker trên VPS |
| Tốc độ | Nhanh, không tốn thời gian pull image | Chậm hơn do tạo container mới mỗi job |
| Độ an toàn | Script có thể ảnh hưởng toàn hệ thống | An toàn hơn, container bị xoá sau job |
| Phù hợp cho | Deployment, backup, thao tác hệ thống | Build & test code sạch sẽ, tái lập |
Mình thấy thực tế nhiều nhóm dùng cả hai: một runner shell cho các job deploy (cần truy cập server thật), một runner docker cho build/test (cần môi trường sạch). Bạn gắn tag cho từng runner để route job.
Với docker executor, bạn cần cài Docker trước. Xem bài cách cài Docker trên VPS Ubuntu nếu chưa có. Sau đó sửa file /etc/gitlab-runner/config.toml để dùng docker executor:
sudo nano /etc/gitlab-runner/config.toml
Tìm phần runner vừa đăng ký, đảm bảo có dạng:
[[runners]]
name = "my-vps-runner"
url = "https://gitlab.example.com"
token = "glrt-xxxxxxxx"
executor = "docker"
[runners.docker]
image = "alpine:latest"
volumes = ["/cache"]
cache_dir = "/cache"
Lưu file, rồi khởi động lại runner:
sudo systemctl restart gitlab-runner
Bước 4 - Viết file .gitlab-ci.yml đầu tiên
File .gitlab-ci.yml nằm ở root của repository, khai báo các job và script chạy. Dưới đây là ví dụ pipeline 3 job: test, build, deploy.
stages:
- test
- build
- deploy
variables:
APP_DIR: /var/www/myapp
test-job:
stage: test
script:
- echo "Running tests..."
- npm install
- npm test
build-job:
stage: build
script:
- echo "Building application..."
- npm run build
artifacts:
paths:
- dist/
deploy-job:
stage: deploy
script:
- echo "Deploying to production server..."
- sudo rsync -av --delete dist/ $APP_DIR/
environment: production
Giải thích từng phần:
stages: định nghĩa thứ tự các giai đoạn. Job cùng stage chạy song song, job stage sau chờ stage trước hoàn thành.variables: biến môi trường dùng chung cho mọi job.test-job / build-job / deploy-job: tên job tự đặt. Phầnscriptlà lệnh thực thi.artifacts: lưu file kết quả (ở đây là thư mụcdist/) để job sau hoặc bạn tải về.environment: đánh dấu job deploy lên production, hiển thị trong trang Operations.
Lưu ý với shell executor: user chạy runner là gitlab-runner, không có quyền sudo mặc định. Nếu job cần quyền deploy thật vào /var/www, bạn phải cấu hình sudo cho user này. Cách làm gọn: tạo file /etc/sudoers.d/gitlab-runner:
sudo nano /etc/sudoers.d/gitlab-runner
gitlab-runner ALL=(ALL) NOPASSWD: /usr/bin/rsync, /usr/bin/systemctl
Dòng trên cho phép user gitlab-runner chạy rsync và systemctl với quyền root mà không cần nhập mật khẩu. Chỉ khai báo đúng lệnh cần thiết, đừng cấp ALL.
Xử lý lỗi thường gặp khi cấu hình Runner
Dưới đây là 3 lỗi mình gặp nhiều nhất khi làm GitLab Runner trên VPS:
1. Runner offline hoặc không nhận job
Kiểm tra kết nối giữa runner và GitLab server:
sudo gitlab-runner verify
sudo journalctl -u gitlab-runner -n 50
Lỗi hay gặp là URL instance nhập sai (thiếu https:// hoặc nhập IP không đúng), hoặc token hết hạn. Với GitLab 16+, token dạng glrt- có thể đăng ký được nhiều lần, nhưng nếu token từ bản cũ bị thu hồi thì phải tạo lại ở giao diện.
2. Job pending mãi không chạy
Job pending nghĩa là GitLab không tìm thấy runner nào khớp. Nguyên nhân thường là tag mismatch: job khai báo tag docker nhưng runner chỉ có tag linux. Sửa một trong hai: xoá tag khỏi job, hoặc thêm tag cho runner trong config.toml. Nếu khai báo tags: [] trong job thì chỉ runner không có tag mới nhận.
3. Lỗi "Permission denied" khi job chạy lệnh sudo
Như đã nói ở Bước 4, user gitlab-runner không có quyền sudo mặc định. Kiểm tra file /etc/sudoers.d/gitlab-runner và nhớ chỉ định đúng đường dẫn lệnh rất cao (dùng which rsync để biết đường dẫn). Nếu vẫn fail, xem log job trên giao diện GitLab để biết lỗi chính xác từ dòng nào.
Nâng cao: dùng runner cho nhiều project bằng Docker
Một runner có thể phục vụ nhiều project. Với docker executor, mỗi job chạy trong container riêng dựa trên image bạn khai báo trong job (hoặc image mặc định trong config). Đây là cách sạch nhất để chạy CI/CD cho nhiều dự án mà không lo xung đột dependency giữa các project.
Ví dụ job dùng image Node.js riêng:
node-test:
image: node:20-alpine
script:
- npm install
- npm test
Runner sẽ tự pull image node:20-alpine từ Docker Hub về máy (lần đầu chậm, sau đó cache lại). Mỗi job không ảnh hưởng đến hệ thống chính - container bị xoá ngay khi job kết thúc.
Với nhiều project, bạn chỉ cần đăng ký runner ở cấp group thay vì project (Settings → CI/CD → Runners ở cấp group). Token group cho phép runner nhận job của mọi project trong group.
Một điểm nữa: nếu VPS của bạn có cấu hình thấp (2GB RAM), Docker executor sẽ ngốn tài nguyên hơn shell executor do phải chạy container. Với team nhỏ, đông nhất 2-3 project chạy pipeline song song, một VPS 4GB RAM là thoải mái. Cân nhắc dùng VPS Linux NVMe 4GB trở lên nếu bạn chạy docker executor thường xuyên.
Câu hỏi thường gặp
Shell executor hay Docker executor nên chọn cái nào?
Docker executor cho môi trường sạch, cô lập, tái lập được, phù hợp build và test. Shell executor nhanh, trực tiếp dùng hệ thống VPS, phù hợp deploy và thao tác server. Nhiều đội ngũ dùng cả hai với tag riêng.
Chi phí để chạy GitLab Runner trên VPS là bao nhiêu?
GitLab Runner là phần mềm mã nguồn mở, miễn phí. Bạn chỉ trả tiền VPS để chạy nó. Với nhu cầu cơ bản, VPS 2GB RAM chạy shell executor là đủ; dùng Docker executor nhiều thì nên 4GB trở lên. Xem bảng giá VPS để chọn gói phù hợp.
Runner có cần IP công khai không?
Không bắt buộc. Runner chủ động kết nối ra GitLab server (qua HTTP/HTTPS), nên có thể nằm sau NAT, VPN, hoặc trong mạng nội bộ. Chỉ cần VPS của bạn có thể truy cập được GitLab server theo chiều ra là đủ.
GitLab Runner có hỗ trợ Windows không?
Có. GitLab Runner chạy trên Windows Server (xem VPS Windows), dùng PowerShell executor. Tuy nhiên hầu hết hạ tầng CI/CD Linux vẫn phổ biến hơn vì image Docker đa dạng và chi phí thấp.
Làm sao để xoá một runner đã đăng ký?
Vào Settings → CI/CD → Runners, click icon xoá (thùng rác) cạnh runner. Sau đó trên VPS, xoá mục tương ứng trong /etc/gitlab-runner/config.toml rồi restart service: sudo systemctl restart gitlab-runner.
Bài viết liên quan
- Hướng dẫn cài GitLab CE trên VPS riêng chi tiết
- Triển khai CI/CD lên VPS với GitHub Actions và SSH
- Cách cài Docker trên VPS Ubuntu chi tiết từ A đến Z
- Chạy Node.js production trên VPS với PM2


