Hẳn nhiều developer và sysadmin từng rơi vào tình cảnh trớ trêu: Bạn vừa setup xong một con máy chủ cấu hình mạnh, cài cắm đầy đủ môi trường, hăm hở chạy CI/CD pipeline, nhưng terminal lại báo runner Offline hoặc job build cứ treo ở trạng thái Queued vô thời hạn. Nguyên nhân thường không nằm ở máy chủ lỗi mạng, mà do chính sách tường lửa (Firewall) khắt khe của doanh nghiệp đã chặn đứng các kết nối ra ngoài.
Việc thiết lập Self-Hosted GitHub Actions trên VPS vấp phải rào cản lớn khi đụng độ các chính sách bảo mật mạng nội bộ. Bạn không thể yêu cầu đội Security mở toang mọi cổng mạng (unrestricted outbound) vì rủi ro rò rỉ dữ liệu, nhưng pipeline thì vẫn phải chạy để đảm bảo tiến độ dự án. Việc ứng dụng giải pháp kiểm soát Outbound Traffic bằng Proxy nhằm bảo mật CI/CD Pipeline trên VPS là chìa khóa để gỡ rối bài toán này.
Vậy làm sao để cấu hình proxy chuẩn xác, định tuyến lưu lượng minh bạch nhằm thuyết phục đội Security phê duyệt mà vẫn giữ an toàn cho toàn bộ hạ tầng lõi? Xử lý triệt để lỗi mất kết nối, bảo mật thông tin xác thực proxy và tích hợp công nghệ Runner Container Hooks ra sao? Cùng giải phẫu chi tiết quy trình hạ tầng này ngay dưới đây.
Nỗi đau CI/CD: Khi Firewall công ty chặn đứng tiến trình build code
Chính sách default-deny (mặc định từ chối toàn bộ) là tiêu chuẩn bảo mật cơ bản để bảo vệ mạng nội bộ doanh nghiệp. Dù vậy, nó lại là tác nhân chính khiến các tiến trình CI/CD bị tê liệt. Nhiều quản trị viên lầm tưởng máy chủ đặt ở vùng ngoại vi (như DMZ) sẽ thông suốt mạng, nhưng firewall kiểm soát rất gắt gao cả chiều kết nối đi (outbound).
Dưới đây là các chốt chặn thường gặp khiến pipeline của bạn thất bại:
- Lệ thuộc vào các kho lưu trữ bên thứ ba (Third-party registries): Workflow của bạn thường cần kéo base image từ Docker Hub (
registry-1.docker.io), tải thư viện từ NPM (registry.npmjs.org) hoặc PyPI. Các lệnhnpm installhaydocker pullsẽ ngay lập tức dính lỗi network i/o timeout nếu firewall không cho phép lưu lượng đi qua. - Rào cản khi cấp quyền bằng IP tĩnh: Nền tảng vận hành trên hạ tầng đám mây với dải IP động khổng lồ, thay đổi liên tục. Nếu team Network yêu cầu danh sách IP tĩnh để cấu hình firewall, pipeline của bạn sớm muộn cũng sẽ gãy khi các node luân chuyển IP.
- Lỗi SSL Inspection phá vỡ chuỗi tin cậy: Các Proxy/Firewall cấp doanh nghiệp thường đánh chặn, giải mã và mã hóa lại gói tin HTTPS bằng Root CA nội bộ (TLS Interception). Các công cụ chạy trong Runner (Docker Daemon, curl, python) mặc định không nhận diện chứng chỉ nội bộ này, dẫn đến thông báo lỗi bảo mật phổ biến:
x509: certificate signed by unknown authority.

Vì sao Self-Hosted GitHub Actions trên VPS là giải pháp lý tưởng?
Thay vì sử dụng hạ tầng runner mặc định do nền tảng cấp phát, việc vận hành Self-Hosted GitHub Actions trên VPS mang lại ưu thế lớn về mặt kiểm soát tài nguyên phần cứng (RAM, CPU chuyên biệt), tái sử dụng cache môi trường build cục bộ và tối ưu chi phí hạ tầng.
Giá trị kỹ thuật cốt lõi của giải pháp này nằm ở cơ chế kết nối và định tuyến lưu lượng:
Cơ chế hoạt động an toàn outbound-only
Hệ thống Runner hoạt động theo mô hình Long-Polling (thăm dò kéo dài) qua cổng HTTPS 443. Khi ứng dụng chạy, nó chủ động gửi yêu cầu (outbound) để truy vấn xem có job nào đang chờ không. Bạn không cần mở bất kỳ cổng kết nối vào (inbound port) nào trên máy chủ, qua đó triệt tiêu rủi ro bị rà soát cổng (port scanning) từ internet.
Vai trò của Corporate Proxy
Dù chỉ dùng kết nối outbound, việc cho phép máy chủ mở mạng tự do ra ngoài vẫn tiềm ẩn nguy cơ bảo mật như rò rỉ dữ liệu (data exfiltration) hoặc thiết lập kết nối ngược (reverse shell) nếu pipeline vô tình chạy đoạn mã độc. Việc so sánh sự khác biệt giữa SOCKS5 và HTTP(s) Proxy để biết khi nào nên dùng sẽ giúp bạn chọn đúng loại giao thức cho hạ tầng của mình.
Đó là lý do sử dụng Corporate Proxy (Proxy doanh nghiệp) kết hợp cùng Runner là thiết kế kiến trúc mang tính chuẩn mực:
- Kiểm soát bằng tên miền (Domain Whitelisting): Proxy phân giải lưu lượng ở tầng ứng dụng (Layer 7), cho phép team Security cấp quyền chuẩn xác cho các domain thay vì chật vật quản lý dải IP động.
- Bạn có thể tham khảo cách xây dựng Internal Proxy Gateway trên VPS Linux để quản lý và tối ưu Rate-Limit cho API AI nhằm ứng dụng kiến trúc này vào các hệ thống lớn.
- Ghi log và Audit minh bạch: Mọi request tải dependencies hay push code đều lưu lại trong
access.logcủa proxy, đáp ứng các tiêu chuẩn tuân thủ bảo mật khắt khe.
Cơ chế kết nối và danh sách domain chuẩn cần xin IT whitelist
Để xin cấp quyền mở mạng (whitelist) từ đội ngũ IT/Security suôn sẻ, bạn cần trình bày một danh sách domain chuẩn xác. Đừng yêu cầu mở *.github.com một cách chung chung, vì hệ thống cần kết nối đa dạng hơn thế.
Nền tảng cung cấp một endpoint API chính thức đóng vai trò nguồn tham chiếu để trích xuất dải IP và Wildcard Domain.
Bạn có thể chạy lệnh cURL sau trực tiếp trên Terminal để lấy danh sách cập nhật theo thời gian thực:
curl -L \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/meta
Các endpoint thiết yếu bắt buộc phải có trong whitelist:
Nếu đội Security từ chối rule wildcard (ký tự đại diện *), bạn cần yêu cầu mở đích danh các endpoint nền tảng sau để tiến trình CI/CD không bị đứt gãy:
api.github.com: Yêu cầu bắt buộc để runner xác thực và tải cấu hình.codeload.github.com: Endpoint đảm nhận việc tải mã nguồn (source code) của repository dưới dạng file zip/tarball khi chạy action checkout.vstoken.actions.githubusercontent.com: Dịch vụ cấp phát token bảo mật ngắn hạn.pipelines.actions.githubusercontent.com: Kênh giao tiếp long-polling để nhận job.results-receiver.actions.githubusercontent.com: Cổng tiếp nhận để hệ thống upload log và báo cáo trạng thái.
Hãy gửi danh sách FQDN (Fully Qualified Domain Name) này cho đội Network để họ cập nhật vào rule của Corporate Proxy.
Thiết lập Self-Hosted GitHub Actions trên VPS qua Proxy
Dưới đây là quy trình 4 bước tiêu chuẩn để triển khai môi trường CI/CD tuân thủ nguyên tắc an toàn thông tin, đảm bảo luồng traffic đi mượt mà qua tường lửa công ty.
Bước 1: Chuẩn bị hạ tầng, tạo user riêng (non-root) và verify SHA256
Hết sức tránh việc chạy Runner bằng tài khoản root. Bất kỳ thay đổi hệ thống ngoài ý muốn nào từ pipeline cũng có thể làm hỏng cấu hình máy chủ. Nếu gặp sự cố đăng nhập do phân quyền sai, bạn có thể xem lại 10 nguyên nhân phổ biến và cách sửa lỗi không SSH được vào VPS Linux.
Khởi tạo một tài khoản người dùng chuyên biệt và phân quyền thư mục:
Tạo user non-root:
sudo useradd -m -s /bin/bash github-runner
Cấp quyền thao tác với Docker (nếu pipeline cần build image):
sudo usermod -aG docker github-runner
Tạo thư mục làm việc và cấp quyền sở hữu:
sudo mkdir -p /home/github-runner/actions-runner
sudo chown -R github-runner:github-runner /home/github-runner/actions-runner
Tiếp theo, tải mã nguồn runner và xác minh tính toàn vẹn của tệp cài đặt (Checksum).
CẢNH BÁO VẬN HÀNH (Cập nhật 2026):
Hệ thống nền tảng hiện đang thực thi chính sách minimum-version enforcement (áp dụng mạnh tay trong giai đoạn tháng 7 đến tháng 9 năm 2026). Nếu sysadmin sử dụng file cài đặt quá cũ hoặc bỏ quên server không patch update định kỳ, hệ thống sẽ chặn kết nối hoàn toàn, biến cảnh báo thành sự cố sập mạng (outage) toàn diện. Hãy luôn kiểm tra trang Releases để tải bản vá mới kịp thời.
Chuyển sang user github-runner và truy cập thư mục làm việc:
sudo -iu github-runner
cd ~/actions-runner
Tải phiên bản v2.337.0 (Kiểm tra bản cập nhật nếu có):
curl -o actions-runner-linux-x64-2.337.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.337.0/actions-runner-linux-x64-2.337.0.tar.gz
So khớp mã băm SHA-256 tương ứng:
echo "8cc95e1e695dcdfc3456bbd4ef8d6179b5c5eac33ce0c6d36e2f1db55c0cd94d actions-runner-linux-x64-2.337.0.tar.gz" | shasum -a 256 -c
Nếu hệ thống trả về thông báo OK, tiến hành giải nén bằng lệnh tar xzf actions-runner-linux-x64-2.337.0.tar.gz.
Bước 2: Đăng ký Runner và vòng đời Ephemeral
Ephemeral Runner (Runner chạy một lần) là cơ chế thiết lập tự động hủy đăng ký và dọn dẹp dữ liệu tạm thời ngay sau khi hoàn thành một job độc lập. Nó giải quyết nguy cơ rò rỉ trạng thái (state leakage) hoặc đầy ổ đĩa do cache cũ tích tụ.
Tuy nhiên, nếu bạn cấu hình cờ --ephemeral trên một VPS tĩnh, tiến trình sẽ dừng hoạt động sau khi chạy xong. Với các kiến trúc hạ tầng hiện đại cấp doanh nghiệp, các kỹ sư DevOps thường triển khai Actions Runner Controller (ARC) trên Kubernetes. ARC tự động scale-up pods mới sạch sẽ khi có job và tiêu hủy pod khi hoàn tất.
Nếu vẫn cấu hình thủ công trên máy chủ ảo phục vụ chạy job liên tục, lệnh đăng ký cơ bản sẽ như sau:
./config.sh \
--url https://github.com/Ten-To-Chuc/Ten-Repo \
--token <MÃ_TOKEN_LẤY_TỪ_NỀN_TẢNG> \
--name "vps-runner-internal" \
--labels "linux,x64,corporate-proxy"
Bước 3: Bảo mật thông tin Proxy qua Systemd (thay vì file .env thuần)
Theo cách cấu hình truyền thống, thông tin proxy thường được đặt vào file .env. Tuy nhiên, việc lưu trữ thông tin dưới dạng user:password plain text trong thư mục hoạt động của runner mang lại rủi ro bảo mật nếu có nhiều user cùng truy cập máy chủ VPS.
Để đạt chuẩn hạ tầng khắt khe, bạn nên sử dụng cấu hình Systemd. Đặt thông tin proxy vào một file môi trường riêng biệt được phân quyền nghiêm ngặt, ngăn chặn việc rò rỉ mật khẩu:
Tạo thư mục và file cấu hình bảo mật:
sudo mkdir -p /etc/actions-runner/
sudo nano /etc/actions-runner/proxy-creds.env
Khai báo thông số proxy:
https_proxy=http://proxy-user:[email protected]:8080
http_proxy=http://proxy-user:[email protected]:8080
no_proxy=localhost,127.0.0.1,api.congty.local
(Lưu ý kỹ thuật: Tham số no_proxy chỉ nhận diện hostname, không nhập dải IP hoặc CIDR vì hệ thống sẽ tự động bỏ qua).
Phân quyền bảo vệ tệp tin:
sudo chown root:root /etc/actions-runner/proxy-creds.env
sudo chmod 600 /etc/actions-runner/proxy-creds.env
Cài đặt service và chỉ định file môi trường bằng lệnh edit Systemd:
sudo ./svc.sh install github-runner
sudo systemctl edit actions.runner.*.service
Thêm block này vào trình chỉnh sửa để Systemd nạp chứng chỉ khi khởi chạy:
[Service]
EnvironmentFile=/etc/actions-runner/proxy-creds.env
Nạp lại cấu hình và khởi động: sudo systemctl daemon-reload && sudo ./svc.sh start.
Bạn có thể xem thêm hướng dẫn sử dụng systemctl để sửa lỗi VPS bằng các lệnh start, stop, restart dịch vụ để nắm vững các luồng xử lý này.
Bước 4: Thiết lập Proxy cho Docker và ứng dụng Runner Container Hooks
Đây là rào cản khiến nhiều pipeline sụp đổ. Dù Runner đã nhận proxy, nhưng hệ thống Docker lại hoạt động với vòng đời khác biệt, tạo ra 2 điểm hạn chế lớn: Docker Daemon và Docker Client.
4.1. Điểm hạn chế của Docker Daemon (Dành cho lệnh Pull/Build):
Khi workflow gọi lệnh docker pull, tác vụ được xử lý bởi Docker Daemon. Daemon không tự động đọc file proxy của Runner, dẫn đến treo mạng. Bạn cần cấu hình systemd drop-in.
Tạo thư mục và cấu hình proxy cho Docker:
sudo mkdir -p /etc/systemd/system/docker.service.d/
sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf
Thêm thông số (bao gồm cả docker.internal):
[Service]
Environment="HTTP_PROXY=http://proxy.congty.com:8080"
Environment="HTTPS_PROXY=http://proxy.congty.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,docker.internal,.congty.local"
Nạp lại cấu hình: sudo systemctl daemon-reload && sudo systemctl restart docker.
4.2. Khắc phục Điểm hạn chế Docker Client & Runner Container Hooks:
Nếu workflow sử dụng Docker container actions, nền tảng sẽ khởi chạy một container con để chạy các lệnh build. Container con này mặc định không biết đường ra internet.
Cách 1 (Truyền thống): Cấu hình Docker Client cho user github-runner qua file ~/.docker/config.json:
{
"proxies": {
"default": {
"httpProxy": "http://proxy.congty.com:8080",
"httpsProxy": "http://proxy.congty.com:8080",
"noProxy": "localhost,127.0.0.1,docker.internal"
}
}
}
Cách 2 (Tiên tiến – Enterprise level): Tận dụng công nghệ Runner Container Hooks.
Với các action chạy lệnh docker build phức tạp, container vẫn có thể rớt mạng do thiếu cờ --build-arg. Bằng cách cấu hình biến môi trường ACTIONS_RUNNER_CONTAINER_HOOKS, runner sẽ tự động chèn (inject) mọi cấu hình mạng và chứng chỉ CA vào các container con một cách minh bạch. Phương pháp native này giúp team DevOps tiết kiệm hàng chục giờ đồng hồ sửa đổi code trong hàng trăm file workflow hiện hữu.

Checklist bảo mật, sửa lỗi x509 và khắc phục nhanh mạng (troubleshooting)
Xử lý lỗi chứng chỉ x509 (TLS Interception)
Khi doanh nghiệp áp dụng giải mã HTTPS tại Corporate Proxy, tường lửa cấp phát một chứng chỉ nội bộ. Nếu máy chủ không nhận diện chứng chỉ này, các tiến trình sẽ văng lỗi x509: certificate signed by unknown authority.
Khắc phục theo luồng minh bạch, an toàn:
- Thêm CA gốc vào OS Trust Store: Copy file
.crtcủa công ty vào/usr/local/share/ca-certificates/và chạy lệnhsudo update-ca-certificates. Việc này giúp hệ điều hành (và các lệnh curl, wget) tin cậy proxy. - Cấu hình riêng cho Docker: OS Trust Store là chưa đủ vì Docker tự xác minh chứng chỉ độc lập. Bạn bắt buộc phải chép file CA của công ty vào thư mục
/etc/docker/certs.d/. Khởi động lại dịch vụ Docker để áp dụng.
Đặc biệt lưu ý: Tránh sử dụng các cờ như
curl -k(insecure) hoặc--tls-verify=falsetrong CI/CD pipeline để ép hệ thống bỏ qua lỗi SSL. Hành động này phá vỡ lớp bảo mật TLS, khiến dữ liệu truyền tải của ứng dụng lộ lọt và gặp rủi ro tấn công Man-in-the-Middle (MitM).

Checklist bảo mật cốt lõi
- Cấm kỵ với Public Repository: Hệ thống khuyến cáo không dùng cấu hình tự lưu trữ (self-hosted) cho các dự án mã nguồn mở (Public Repo). Bất kỳ ai trên internet cũng có thể fork repo của bạn và tạo một Pull Request chứa mã độc. Pipeline sẽ tự động chạy đoạn mã đó trực tiếp trên máy chủ VPS, tạo điều kiện cho hacker chiếm quyền hệ thống. Hãy chỉ cấu hình runner cho Private Repository.
- Thiết lập vòng phòng thủ VPS: Đừng quên kết hợp các biện pháp bảo vệ hệ thống nền tảng. Bạn nên tham khảo cách bảo mật VPS Linux với UFW, Fail2Ban và Hardening SSH để thiết lập hệ thống phòng thủ an toàn.
- Xóa dọn môi trường: Nếu không dùng cờ ephemeral, hãy cấu hình các bước clean up workspace để tránh lộ lọt secret từ các job trước đó.
Khắc phục lỗi 407 Proxy Authentication Required
Proxy trả về HTTP 407 khi định danh người dùng bị sai. Nếu mật khẩu của bạn chứa ký tự đặc biệt (@, #, $), bạn phải URL-encode chúng trong file cấu hình (ví dụ: p@ssword chuyển thành p%40ssword).
Khắc phục lỗi DNS Timeout / ENOTFOUND
Trường hợp báo lỗi no such host do máy chủ không phân giải được tên miền: Nếu dùng Explicit Proxy (khai báo tường minh URL), proxy server sẽ đảm nhận việc phân giải DNS, runner chỉ cần kết nối tới IP của Proxy. Hãy phối hợp với Network team để rà soát lại file cache log trên Proxy server xem lưu lượng có bị rớt tại gateway hay không.
Bạn có thể áp dụng thêm kỹ thuật sử dụng journalctl để xem log và gỡ lỗi (troubleshoot) VPS Linux nhằm khoanh vùng lỗi nhanh chóng.
Câu hỏi thường gặp (FAQ)
1. Có cần mở port inbound trên tường lửa VPS để GitHub đẩy job về không?
Không. Runner hoạt động theo cơ chế long-polling (chủ động gọi outbound HTTPS qua port 443). Mọi kết nối đều do VPS khởi tạo từ bên trong, giúp các cổng mạng của bạn luôn đóng kín với thế giới bên ngoài.
2. Đã khai báo đầy đủ proxy trong file .env nhưng lệnh docker pull vẫn báo lỗi mạng. Tại sao?
File .env chỉ tác động đến tiến trình runner. Docker Daemon là một dịch vụ systemd độc lập. Bạn phải cấu hình proxy riêng cho Docker qua đường dẫn /etc/systemd/system/docker.service.d/http-proxy.conf.
3. Có thể dùng dải IP/CIDR (ví dụ: 192.168.1.0/24) trong biến no_proxy được không?
Không. Ứng dụng runner hiện tại chỉ hỗ trợ xử lý bằng hostname (FQDN). Nếu bạn chèn dải IP vào cấu hình no_proxy, hệ thống sẽ tự động bỏ qua chúng.
4. Gắn Self-Hosted Runner cho một dự án Public Repository (mã nguồn mở) có an toàn không?
Rất rủi ro. Bất kỳ ai cũng có thể tạo một Pull Request chứa script độc hại. CI/CD Pipeline sẽ chạy thẳng đoạn script đó trên VPS, mở đường cho hacker chiếm quyền điều khiển server của bạn. Chỉ nên dùng cho Private Repo.
5. Xử lý nhanh lỗi x509: certificate signed by unknown authority như thế nào?
Lỗi do tường lửa công ty đánh chặn và đổi chứng chỉ (TLS Interception). Cách giải quyết: Nạp file CA của công ty vào OS Trust Store (chạy update-ca-certificates) VÀ copy riêng file đó vào /etc/docker/certs.d/ để Docker Daemon nhận diện.
Kết luận
Việc triển khai Self-Hosted GitHub Actions trên VPS kết hợp cùng cấu hình Proxy đóng vai trò cầu nối giải quyết hài hòa bài toán tối ưu hóa quy trình tự động hóa (CI/CD) của giới developer và nguyên tắc kiểm soát mạng nghiêm ngặt của đội ngũ Security.
Bằng cách định tuyến lưu lượng minh bạch qua Corporate Proxy, thiết lập danh sách endpoint chi tiết, khắc phục triệt để điểm hạn chế cấu hình của Docker qua Container Hooks, và nạp Trust Store x509 chuẩn chỉ, bạn sẽ sở hữu một hạ tầng vận hành bền bỉ. Quy trình kỹ thuật vững chắc này đảm bảo dòng chảy công việc không bao giờ bị gián đoạn trước các hàng rào an ninh khắt khe của doanh nghiệp.
