Ansible git Clone via SSH: Deploy Keys & Repository Guide
By Luca Berton · Published 2024-01-01 · Category: installation
How to clone git repositories via SSH with Ansible. Configure deploy keys, accept host keys, manage private repos, and automate git-based deployments.

How to checkout git repository via SSH?
ansible.builtin.git clones a private Git repository over SSH by specifying an SSH URL as repo and providing the path to an SSH deploy key via key_file. Set accept_newhostkey: true on the first run to avoid host-key prompts, and pin version to a tag or commit hash for reproducible deployments.
See also: ansible.builtin.git Module: Clone & Checkout Git Repositories (Guide)
Ansible checkout git repository
Today we're talking about Ansible modulegit.
The full name is ansible.builtin.git which means is part of the collection of modules "builtin" with ansible and shipped with it.
This module is pretty stable and out for years.
The purpose is to Deploy software (or files) from git checkouts in our managed hosts.
If you would like to fetch via SSH please refer to: Checkout git repository HTTPS - Ansible module git
Parameters and Return Values
The parameter list is pretty wide but I'll summarize the most useful.
- repo _path_
- dest _string_
- update _boolean_
- key_file _path_ - SSH private key
- after _string_
See also: Ansible git Module: Clone Repos & Checkout Commits (ansible.builtin.git Guide)
Demo
Let's jump in a real-life playbook to checkout a git repository with Ansible
- git_ssh.yml
---
- name: git module Playbook
hosts: all
vars:
repo: "git@github.com:lucab85/ansible-pilot.git"
dest: "/home/devops/ansible-pilot"
sshkey: "~/.ssh/id_rsa"
tasks:
- name: ensure git pkg installed
ansible.builtin.yum:
name: git
state: present
update_cache: true
become: true
- name: checkout git repo
ansible.builtin.git:
repo: "{{ repo }}"
dest: "{{ dest }}"
key_file: "{{ sshkey }}"
Conclusion
Now you know how to checkout git repository via SSH with Ansible.
See also: Failed to Connect via SSH in Ansible: Full Troubleshooting Guide
SSH Authentication Methods
Deploy key (recommended)
- name: Install deploy key
ansible.builtin.copy:
content: "{{ vault_deploy_key }}"
dest: /home/deploy/.ssh/deploy_key
owner: deploy
mode: '0600'
no_log: true
- name: Clone private repo
ansible.builtin.git:
repo: git@github.com:myorg/private-repo.git
dest: /opt/myapp
version: main
key_file: /home/deploy/.ssh/deploy_key
accept_hostkey: trueSSH agent forwarding
# ansible.cfg
[ssh_connection]
ssh_args = -o ForwardAgent=yes- name: Clone using forwarded agent
ansible.builtin.git:
repo: git@github.com:myorg/private-repo.git
dest: /opt/myapp
accept_hostkey: trueSSH config on remote host
- name: Configure SSH for GitHub
ansible.builtin.copy:
content: |
Host github.com
IdentityFile ~/.ssh/deploy_key
StrictHostKeyChecking accept-new
dest: /home/deploy/.ssh/config
owner: deploy
mode: '0600'Pre-add Host Keys
- name: Add GitHub host key
ansible.builtin.known_hosts:
name: github.com
key: "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl"Complete Deployment Playbook
---
- name: Deploy app from Git (SSH)
hosts: webservers
become: true
tasks:
- name: Install git
ansible.builtin.package:
name: git
state: present
- name: Deploy SSH key
ansible.builtin.copy:
content: "{{ vault_deploy_ssh_key }}"
dest: /home/www-data/.ssh/deploy_key
owner: www-data
mode: '0600'
no_log: true
- name: Clone repository
ansible.builtin.git:
repo: git@github.com:myorg/webapp.git
dest: /var/www/webapp
version: main
key_file: /home/www-data/.ssh/deploy_key
accept_hostkey: true
force: true
become_user: www-data
register: git_result
notify: restart webapp
- name: Show deployed version
debug:
msg: "Deployed {{ git_result.after[:8] }}"SSH vs HTTPS
| Method | Pros | Cons |
|---|---|---|
| SSH | No password in URLs, deploy keys | Key management, port 22 |
| HTTPS | Works through firewalls | Token in URL if logged |
FAQ
"Permission denied (publickey)" fix
- Check key permissions:
chmod 600 deploy_key - Ensure key is added to GitHub as deploy key
- Verify key_file path is correct
- Check key ownership matches become_user
Clone Repository
- name: Clone repository
ansible.builtin.git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
version: main
become: true
become_user: deployClone with SSH Key
- name: Deploy SSH key
ansible.builtin.copy:
content: "{{ vault_deploy_key }}"
dest: /home/deploy/.ssh/deploy_key
owner: deploy
mode: '0600'
become: true
- name: Clone with specific key
ansible.builtin.git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
key_file: /home/deploy/.ssh/deploy_key
accept_hostkey: true
version: main
become: true
become_user: deployCheckout Specific Branch/Tag
# Branch
- git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
version: develop
# Tag
- git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
version: v2.5.0
# Specific commit
- git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
version: abc123def456HTTPS Clone
- ansible.builtin.git:
repo: https://github.com/myorg/myapp.git
dest: /opt/myapp
version: mainDeployment Pattern
---
- name: Deploy application
hosts: webservers
become: true
vars:
app_version: v2.5.0
app_dir: /opt/myapp
tasks:
- name: Clone/update repository
ansible.builtin.git:
repo: git@github.com:myorg/myapp.git
dest: "{{ app_dir }}"
version: "{{ app_version }}"
force: true
register: git_result
become_user: deploy
notify: restart app
- name: Install dependencies
ansible.builtin.pip:
requirements: "{{ app_dir }}/requirements.txt"
virtualenv: "{{ app_dir }}/venv"
when: git_result.changed
- name: Run migrations
ansible.builtin.command:
cmd: "{{ app_dir }}/venv/bin/python manage.py migrate"
chdir: "{{ app_dir }}"
when: git_result.changed
run_once: true
handlers:
- name: restart app
service: name=myapp state=restartedKey Parameters
| Parameter | Description |
|---|---|
repo | Repository URL (SSH or HTTPS) |
dest | Local clone path |
version | Branch, tag, or commit hash |
key_file | SSH private key path |
accept_hostkey | Auto-add host to known_hosts |
force | Discard local changes |
depth | Shallow clone depth |
update | Pull if already cloned (default: true) |
single_branch | Clone only specified branch |
recursive | Initialize submodules |
Shallow Clone (Faster)
- git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
depth: 1
single_branch: true
version: mainFAQ
"Permission denied (publickey)" error?
- Check SSH key permissions:
chmod 600 ~/.ssh/deploy_key - Ensure
accept_hostkey: trueor add GitHub to known_hosts - Check the key is added to the repository's deploy keys
How do I handle local changes?
force: true discards local changes. Without it, the task fails if there are uncommitted changes.
Can I clone submodules?
- git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
recursive: true # Init and update submodulesClone via SSH
- ansible.builtin.git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
version: main
accept_hostkey: true
become: true
become_user: deployDeploy Key Setup
# 1. Generate deploy key
- community.crypto.openssh_keypair:
path: /home/deploy/.ssh/deploy_key
type: ed25519
owner: deploy
mode: '0600'
become: true
# 2. Clone with specific key
- git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
key_file: /home/deploy/.ssh/deploy_key
accept_hostkey: true
become: true
become_user: deploySSH Config for Multiple Repos
# Deploy SSH config for multiple GitHub repos
- copy:
content: |
Host github-myapp
HostName github.com
User git
IdentityFile ~/.ssh/myapp_deploy_key
IdentitiesOnly yes
Host github-config
HostName github.com
User git
IdentityFile ~/.ssh/config_deploy_key
IdentitiesOnly yes
dest: /home/deploy/.ssh/config
owner: deploy
mode: '0600'
become: true
# Use custom host alias
- git:
repo: git@github-myapp:myorg/myapp.git
dest: /opt/myappAccept Host Key Safely
# Option 1: accept_hostkey (adds on first connect)
- git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myapp
accept_hostkey: true
# Option 2: Pre-populate known_hosts
- known_hosts:
name: github.com
key: "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl"
state: present
become: true
become_user: deploySSH Agent Forwarding
# ansible.cfg
# [ssh_connection]
# ssh_args = -o ForwardAgent=yes
# Then git uses your local SSH agent
- git:
repo: git@github.com:myorg/myapp.git
dest: /opt/myappFull Deploy Playbook
- hosts: webservers
become: true
vars:
app_repo: git@github.com:myorg/myapp.git
app_version: v2.5.0
deploy_user: deploy
tasks:
- name: Ensure deploy user SSH directory
file:
path: "/home/{{ deploy_user }}/.ssh"
state: directory
owner: "{{ deploy_user }}"
mode: '0700'
- name: Deploy SSH key
copy:
src: keys/deploy_key
dest: "/home/{{ deploy_user }}/.ssh/deploy_key"
owner: "{{ deploy_user }}"
mode: '0600'
- name: Clone/update repository
git:
repo: "{{ app_repo }}"
dest: /opt/myapp
version: "{{ app_version }}"
key_file: "/home/{{ deploy_user }}/.ssh/deploy_key"
accept_hostkey: true
become_user: "{{ deploy_user }}"
register: git_result
notify: restart app
- name: Install dependencies
command: /opt/myapp/install.sh
when: git_result.changedFAQ
"Permission denied (publickey)" error?
Check: key file permissions (must be 0600), correct user (become_user), key added to GitHub/GitLab as deploy key.
How to use with GitLab?
Same approach — just change github.com to your GitLab hostname. Deploy keys work identically.
Can I use HTTPS instead?
Yes, but SSH keys are more secure than embedding tokens in URLs. For HTTPS: repo: https://{{ token }}@github.com/myorg/repo.git
Related Articles
Category: installation
Watch the video: Ansible git Clone via SSH: Deploy Keys & Repository Guide — Video Tutorial