Dùng proxy tĩnh trong GitHub Actions / CI runner khi gọi API Việt Nam

CI runner (GitHub-hosted ubuntu-latest) thường có IP datacenter nước ngoài, thay đổi theo VM. Khi job cần gọi API chỉ cho phép IP Việt Nam, hoặc cần evidence geo VN trong pipeline, gắn proxy tĩnh vào bước curl / script là cách đơn giản — không phải tự host runner trong nước.

Khi nào cần proxy tĩnh trên CI?

  • Integration test gọi sandbox cổng VN chỉ whitelist IP
  • Smoke landing / API theo IP VN trong PR check
  • Đồng bộ dữ liệu với hệ thống nội địa yêu cầu IP nguồn ổn định
  • Cron nightly lấy báo cáo từ API chỉ mở với IP đã đăng ký

Proxy xoay trên CI thường gây fail ngẫu nhiên khi upstream gắn session theo IP. Proxy tĩnh giữ cùng exit IP giữa các bước trong một workflow (và giữa các đêm nếu bạn không đổi IP trên panel).

Thông số đã xác nhận

Proxy tĩnh dân cư: 1.000đ/ngày hoặc 30.000đ/30 ngày; Viettel / VNPT / FPT; HTTP hoặc SOCKS5; mạng dân cư thật, IP sạch. Xem proxy IP tĩnh. Checker: check-proxy.

Lưu secret trên GitHub

Repository → Settings → Secrets and variables → Actions:

Secret Ví dụ
PROXY_URL http://USER:PASS@HOST:PORT
EXPECTED_EXIT_IP IP hiện trên panel

Không commit proxy vào YAML. Tránh echo "$PROXY_URL" — GitHub mask một phần nhưng password phức tạp vẫn có rủi ro lộ qua log lỗi.

Workflow mẫu

yaml
name: vn-api-via-static-proxy on: workflow_dispatch: schedule: - cron: '0 19 * * *' # ~02:00 ICT jobs: call-vn-api: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Verify exit IP via static proxy env: PROXY_URL: ${{ secrets.PROXY_URL }} EXPECTED_EXIT_IP: ${{ secrets.EXPECTED_EXIT_IP }} run: | set -euo pipefail IP=$(curl -fsS -x "$PROXY_URL" --max-time 25 https://api.ipify.org) echo "exit IP: $IP" if [ -n "${EXPECTED_EXIT_IP:-}" ] && [ "$IP" != "$EXPECTED_EXIT_IP" ]; then echo "IP lệch panel" >&2 exit 1 fi - name: Call Vietnam API through proxy env: PROXY_URL: ${{ secrets.PROXY_URL }} run: | curl -fsS -x "$PROXY_URL" --max-time 30 \ -H "Accept: application/json" \ "https://example.vn/api/ping"

Python trong job (tuỳ chọn)

yaml
- uses: actions/setup-python@v5 with: python-version: '3.12' - run: pip install requests - name: Python call via proxy env: PROXY_URL: ${{ secrets.PROXY_URL }} run: | python - <<'PY' import os, requests p = os.environ["PROXY_URL"] proxies = {"http": p, "https": p} r = requests.get("https://api.ipify.org", proxies=proxies, timeout=25) print("exit", r.text) PY

Self-hosted runner vs proxy tĩnh

Self-hosted runner trong VN giải quyết IP nguồn nhưng tốn vận hành (máy, patch, bảo mật). Proxy tĩnh trên GitHub-hosted là bước nhẹ: giữ CI managed, chỉ "mượn" exit IP dân cư khi cần. Nhiều team dùng cả hai: self-hosted cho job nặng, proxy tĩnh cho job nhẹ/geo.

Lưu ý vận hành

  1. GitHub-hosted runner IP thay đổi — lớp ổn định phía exit là proxy tĩnh.
  2. Tôn trọng rate limit / ToS API đích; schedule không spam.
  3. Sau đổi IP proxy: cập nhật secret EXPECTED_EXIT_IP.
  4. Cần mask thêm: echo "::add-mask::$PROXY_URL" (cẩn thận vẫn không echo password ra step khác).
  5. Ưu tiên HTTP proxy nếu image runner chưa cấu hình SOCKS client.
  6. Job fail sớm ở bước verify IP — đừng gọi API nghiệp vụ khi IP sai.

Checklist trước khi bật schedule

  • Secret đúng gói tĩnh, smoke-test local bằng curl
  • Workflow chỉ chạy trên branch / environment cần thiết
  • Alert (email/Slack) khi job fail vì IP lệch hoặc 407
  • Tài liệu nội bộ ghi ngày hết hạn gói proxy (30 ngày / gia hạn)

Với mẫu trên, pipeline gọi API Việt Nam qua IP dân cư cố định mà không phải chuyển hết CI sang máy trong nước.