Bối cảnh: Khi GitHub không đủ cho đội nhóm nội bộ
Đội mình có 5 developer và 2 sysadmin — nhỏ nhưng đủ lớn để GitHub Free dần trở thành vấn đề. CI minutes trên repo private hết nhanh hơn mình kỳ vọng. Một số dự án nội bộ không được phép đưa code lên cloud. Và khi thử tự host GitLab Runner, build time giảm rõ rệt — không còn phụ thuộc vào băng thông upload ra server GitHub nữa.
Lý do chọn Fedora Server thực ra khá cá nhân — đã dùng Fedora desktop 2 năm rồi, quen tay. Package cập nhật nhanh hơn CentOS hay Rocky Linux, kernel mới, SELinux policy cũng được vá thường xuyên hơn. GitLab CE chạy ngon trên Fedora, miễn là bạn không làm điều mà hầu hết hướng dẫn hay gợi ý: tắt SELinux và firewalld cho nhanh.
Spec tối thiểu: 4GB RAM, 2 CPU, 20GB disk. Nhưng đó là “tối thiểu” theo nghĩa literal — GitLab khi idle đã ngốn khoảng 2.5–3GB RAM rồi. Định chạy thêm GitLab Runner trên cùng máy? Chuẩn bị 8GB cho chắc.
Cài đặt GitLab CE
Chuẩn bị hệ thống
Cập nhật hệ thống và cài các dependency cần thiết trước:
sudo dnf update -y
sudo dnf install -y curl policycoreutils openssh-server openssh-clients postfix
sudo systemctl enable --now sshd postfix
Cài GitLab CE từ repo chính thức
GitLab cung cấp script cài đặt repo tự động, sau đó cài package bình thường qua DNF:
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
sudo EXTERNAL_URL="http://gitlab.yourdomain.com" dnf install -y gitlab-ce
Thay gitlab.yourdomain.com bằng domain hoặc IP thực tế. Chạy nội bộ với IP tĩnh thì dùng http://192.168.1.100 cũng được. Sau khi cài xong, GitLab tự chạy gitlab-ctl reconfigure lần đầu — quá trình này mất khoảng 3–5 phút, hoàn toàn bình thường.
Cấu hình chi tiết
Xử lý SELinux — đừng tắt đi
Điểm này khác biệt nhất so với hầu hết hướng dẫn mình từng đọc. Nhiều bài bảo chạy setenforce 0 hoặc set SELINUX=disabled trong /etc/selinux/config cho nhanh. Mình không làm vậy — server production mà tắt SELinux là bỏ đi cả một lớp bảo vệ chỉ để tiết kiệm vài phút setup. GitLab CE thực ra chỉ cần một số boolean được bật là đủ:
# Cho phép GitLab kết nối mạng (cần cho webhook, email)
sudo setsebool -P httpd_can_network_connect on
sudo setsebool -P httpd_can_network_relay on
# Fix file context cho thư mục data của GitLab
sudo semanage fcontext -a -t gitlab_shell_t "/var/opt/gitlab(/.*)?"
sudo restorecon -Rv /var/opt/gitlab/
# Kiểm tra SELinux có đang block gì không
sudo ausearch -m avc -ts recent | grep gitlab
Nếu vẫn còn lỗi SELinux sau khi bật boolean, đọc audit log rồi tạo custom policy:
sudo ausearch -m avc -ts recent | audit2allow -M gitlab-custom
sudo semodule -i gitlab-custom.pp
Cách này an toàn hơn tắt SELinux nhiều — chỉ cho phép đúng những operation GitLab cần. Thêm nữa, đọc audit log giúp bạn hiểu GitLab thực sự đang làm gì bên dưới, hữu ích khi cần troubleshoot sau này.
Cấu hình firewalld
GitLab cần HTTP (80) và HTTPS (443). SSH clone dùng chung port 22 với system SSH nên không cần mở thêm:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
# Kiểm tra lại
sudo firewall-cmd --list-all
Nếu GitLab chạy trên port tùy chỉnh (ví dụ 8080), thêm rule tương ứng:
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Tinh chỉnh gitlab.rb
File cấu hình chính là /etc/gitlab/gitlab.rb. Mình để các setting sau trên production:
# /etc/gitlab/gitlab.rb
# URL chính — phải đúng, dùng HTTPS nếu có SSL
external_url 'https://gitlab.yourdomain.com'
# Cấu hình SMTP (ví dụ Gmail)
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.gmail.com"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "[email protected]"
gitlab_rails['smtp_password'] = "app-password-here"
gitlab_rails['smtp_domain'] = "gmail.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
# Giới hạn RAM cho Puma web server
puma['worker_processes'] = 2
puma['min_threads'] = 1
puma['max_threads'] = 4
# Giảm Sidekiq workers để tiết kiệm RAM
sidekiq['concurrency'] = 10
# Giữ backup 7 ngày
gitlab_rails['backup_keep_time'] = 604800
Áp dụng thay đổi:
sudo gitlab-ctl reconfigure
Bật HTTPS với Let’s Encrypt
GitLab CE tích hợp sẵn Let’s Encrypt, thêm vào gitlab.rb:
letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['[email protected]']
letsencrypt['auto_renew'] = true
letsencrypt['auto_renew_hour'] = 3
letsencrypt['auto_renew_day_of_month'] = "*/7"
sudo gitlab-ctl reconfigure
sudo gitlab-ctl renew-le-certs
Kiểm tra và Monitoring
Đăng nhập lần đầu
Lấy mật khẩu root tạm thời (tồn tại trong 24 giờ):
sudo cat /etc/gitlab/initial_root_password
Đăng nhập vào http://your-gitlab-url với tài khoản root và mật khẩu đó, rồi đổi ngay. Đừng để qua ngày hôm sau.
Kiểm tra trạng thái service
sudo gitlab-ctl status
Output bình thường trông như sau — tất cả service đều ở trạng thái run:
run: alertmanager: (pid 1234) 120s
run: gitaly: (pid 1236) 120s
run: nginx: (pid 1240) 120s
run: postgresql: (pid 1242) 120s
run: redis: (pid 1244) 120s
run: sidekiq: (pid 1246) 120s
run: puma: (pid 1248) 120s
Nếu service nào down thì restart từng cái:
sudo gitlab-ctl restart puma
sudo gitlab-ctl restart sidekiq
Health check và kiểm tra database
# Chạy health check toàn diện
sudo gitlab-rake gitlab:check
# Test gửi email (chạy trong Rails console)
sudo gitlab-rails console
# Trong console gõ:
Notify.test_email('[email protected]', 'GitLab Test', 'Test email').deliver_now
Monitoring với Prometheus và Grafana
GitLab tích hợp sẵn Prometheus và Grafana. Bật Grafana trong gitlab.rb:
grafana['enable'] = true
grafana['http_port'] = 3000
sudo gitlab-ctl reconfigure
# Truy cập: http://your-gitlab-url/-/grafana
Dashboard Grafana hiển thị CPU/RAM của từng service (Puma, Sidekiq, Gitaly, PostgreSQL), request rate và latency. Mình hay mở tab này khi có deployment lớn để xem ngay bottleneck ở đâu — tiết kiệm thời gian debug khá đáng kể.
Backup tự động
# Tạo backup thủ công
sudo gitlab-backup create
# Xem backup đã tạo
ls -lh /var/opt/gitlab/backups/
Thêm vào crontab của root để backup tự động lúc 2 giờ sáng:
sudo crontab -e
# Thêm dòng sau:
0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1
Các lỗi hay gặp sau 6 tháng chạy production
- 502 Bad Gateway: Thường là Puma chưa khởi động xong. Chờ 1–2 phút hoặc chạy
sudo gitlab-ctl restart puma. - SELinux block git operations: Chạy
sudo ausearch -m avc | grep gitrồi tạo policy như hướng dẫn ở trên. - Disk đầy nhanh: GitLab CI artifacts và container registry ăn disk rất nhanh. Đặt
artifacts_expire_introng CI settings của từng project và dọn registry định kỳ bằngsudo gitlab-ctl registry-garbage-collect. - RAM cao bất thường: Sidekiq đôi khi có memory leak sau nhiều ngày chạy — thêm
sidekiq['enable_sidekiq_cluster'] = falsehoặc restart định kỳ qua cron.
Thêm cảnh báo đơn giản khi disk gần đầy:
# Thêm vào crontab
*/30 * * * * df -h /var/opt/gitlab | awk 'NR==2 {gsub(/%/,"",$5); if ($5+0 > 80) print "GitLab disk usage: " $5 "%"}' | grep -q "%" && echo "Disk alert" | mail -s "GitLab Disk High" [email protected]
Sau 6 tháng chạy production, GitLab CE trên Fedora ổn định hơn mình kỳ vọng ban đầu. SELinux phiền nhất trong tuần đầu — cứ phát hiện thêm operation cần policy mới. Nhưng khi đã xong, cả tháng không cần đụng tới. Phần đáng nhất vẫn là CI/CD nội bộ với GitLab Runner: build time giảm rõ, không lo hết minutes, không phụ thuộc vào đường truyền upload ra ngoài.

