Fix lỗi Ansible git Module 'Host key verification failed' khi Clone qua SSH

intermediate🔧 Ansible2026-06-19| Ansible 2.9+, Ubuntu 20.04/22.04, Debian, RHEL/CentOS — remote host clone từ GitHub, GitLab, Bitbucket, hoặc Git server riêng qua SSH

Error Message

fatal: [remote-host]: FAILED! => {"changed": false, "cmd": "/usr/bin/git clone ...", "msg": "Host key verification failed.\r\nfatal: Could not read from remote repository."}
#ansible#git#ssh#clone

Lỗi gặp phải

fatal: [remote-host]: FAILED! => {"changed": false, "cmd": "/usr/bin/git clone ...", "msg": "Host key verification failed.\r\nfatal: Could not read from remote repository."}

Lỗi này xuất hiện khi module git của Ansible cố clone qua SSH (git@github.com:... hoặc ssh://...) nhưng host key của máy chủ từ xa chưa có trong ~/.ssh/known_hosts. Cụ thể, Ansible kiểm tra người dùng đang chạy task trên máy đích — không phải trên control node của bạn.

SSH chặn kết nối đến các host chưa được xác nhận. Ansible chạy không tương tác, nên không có lời nhắc để chấp nhận key — nó đơn giản là thất bại hoàn toàn.

Nguyên nhân

Hầu hết mọi người đều nghĩ vấn đề nằm ở Ansible control node. Thực ra không phải vậy. Quá trình kiểm tra known_hosts xảy ra trên máy chủ từ xa — máy đang được cấu hình. Máy chủ đó chưa từng SSH đến Git server của bạn trước đây, nên không có bản ghi nào về host key.

Bốn tình huống thường gây ra lỗi này:

  • Provisioning máy chủ mới — đây là lần clone đầu tiên nó thực hiện
  • Chuyển từ URL clone HTTPS sang SSH
  • IP hoặc key của Git server đã thay đổi (GitHub đã thay thế RSA key vào tháng 3 năm 2023)
  • Chạy task với tư cách người dùng khác như deploy, người chưa có known_hosts

Cách xử lý 1: Điền trước known_hosts bằng ssh-keyscan (Khuyến nghị)

Thêm một task trước task git để scan và đăng ký host key:

- name: Add GitHub to known_hosts
  ansible.builtin.known_hosts:
    name: github.com
    key: "{{ lookup('pipe', 'ssh-keyscan github.com') }}"
    state: present

- name: Clone repository
  ansible.builtin.git:
    repo: git@github.com:yourorg/yourrepo.git
    dest: /opt/app
    version: main

Với GitLab hoặc máy chủ riêng, thay github.com bằng host của bạn:

- name: Add GitLab to known_hosts
  ansible.builtin.known_hosts:
    name: gitlab.example.com
    key: "{{ lookup('pipe', 'ssh-keyscan gitlab.example.com') }}"
    path: /home/deploy/.ssh/known_hosts
    state: present

Tham số path rất dễ bị bỏ qua. Nếu bỏ qua, Ansible mặc định dùng /etc/ssh/ssh_known_hosts. Nhưng nếu task git chạy với tư cách deploy, SSH client của người dùng đó sẽ kiểm tra /home/deploy/.ssh/known_hosts thay vào đó. Luôn đặt path rõ ràng để khớp với người dùng đang thực hiện clone.

Cách xử lý 2: Dùng accept_hostkey (Nhanh nhưng đã bị loại bỏ)

Các phiên bản Ansible cũ hơn có tham số accept_hostkey trực tiếp trên module git:

- name: Clone repository
  ansible.builtin.git:
    repo: git@github.com:yourorg/yourrepo.git
    dest: /opt/app
    version: main
    accept_hostkey: yes  # deprecated in Ansible 2.12+

Ansible đã loại bỏ tham số này từ phiên bản 2.12. Nếu bạn đang thấy cảnh báo [DEPRECATION WARNING]: The 'accept_hostkey' argument is deprecated, hãy chuyển sang Cách xử lý 1 ngay — tham số này sẽ ngừng hoạt động hoàn toàn trong các phiên bản tương lai.

Cách xử lý 3: Cố định thủ công Host Key

Chạy ssh-keyscan trong lúc thực thi task sẽ thực hiện một lần gọi mạng trực tiếp. Nếu bạn muốn pin một key cụ thể — hoặc môi trường của bạn chặn SSH ra ngoài qua cổng 22 — hãy lấy key một lần từ control node:

# On your control node:
ssh-keyscan github.com 2>/dev/null

Sao chép kết quả và nhúng trực tiếp vào playbook của bạn:

- name: Add GitHub host key
  ansible.builtin.known_hosts:
    name: github.com
    key: "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GkZH"
    state: present

GitHub công bố fingerprint chính thức trên trang tài liệu SSH key fingerprints của họ — hãy xác minh key ở đó trước khi pin vào môi trường production.

Cách xử lý 4: Cấu hình SSH trên máy chủ từ xa (Giải pháp cuối cùng)

Khi bạn kiểm soát được máy chủ từ xa và cần giải phóng nhanh, bạn có thể tắt kiểm tra host key nghiêm ngặt qua cấu hình SSH:

- name: Disable StrictHostKeyChecking for git server
  ansible.builtin.blockinfile:
    path: /home/deploy/.ssh/config
    create: yes
    mode: '0600'
    owner: deploy
    block: |
      Host github.com
        StrictHostKeyChecking no
        UserKnownHostsFile /dev/null

Chỉ áp dụng cách này cho mạng nội bộ hoặc môi trường CI cô lập. StrictHostKeyChecking no sẽ chấp nhận bất kỳ host key nào một cách âm thầm — kể cả key từ kẻ tấn công MITM. Không dùng cách này trong môi trường production.

Kiểm tra sau khi xử lý

SSH vào máy chủ từ xa và xác nhận key đã được đăng ký:

# Check system-wide known_hosts
grep github.com /etc/ssh/ssh_known_hosts

# Or check user-level
grep github.com ~/.ssh/known_hosts

# Test the SSH connection directly
ssh -T git@github.com
# Expected: Hi username! You've successfully authenticated...

Chạy lại playbook của bạn. Task git sẽ thực thi thành công mà không còn lỗi host key.

Lưu ý thêm

  • Sai đường dẫn known_hosts: Đường dẫn rất quan trọng. Task chạy với tư cách root cần key trong /root/.ssh/known_hosts hoặc /etc/ssh/ssh_known_hosts. Task chạy với tư cách deploy cần key trong /home/deploy/.ssh/known_hosts. Luôn chỉ định path rõ ràng trong task known_hosts — đừng để Ansible tự đoán.
  • GitHub thay thế RSA key năm 2023: GitHub đã thay thế RSA host key vào tháng 3 năm 2023. Các RSA key được cố định trước thời điểm đó sẽ thất bại. Hãy chuyển sang ED25519 key — key này chưa thay đổi và bảo mật hơn.
  • Nhiều Git server: Tập hợp tất cả các task known_hosts vào một role dùng chung hoặc khối pre_tasks. Mọi host đều được chuẩn bị trước khi bất kỳ lệnh git clone nào chạy.
  • CI/CD pipelines: Nếu GitHub Actions hoặc GitLab CI chạy các playbook Ansible của bạn, runner cũng gặp vấn đề tương tự. Thêm bước ssh-keyscan vào phần cài đặt pipeline trước khi gọi Ansible.
  • Máy chủ riêng dùng cổng không chuẩn: Dùng ssh-keyscan -p 2222 git.example.com và đặt name: "[git.example.com]:2222" trong task known_hosts — ký hiệu ngoặc vuông là bắt buộc.

Related Error Notes