How to Configure SSH Key Authentication for actions/checkout: A Complete Guide
Set the ssh-key input to provide a private SSH key, and the action automatically configures GIT_SSH_COMMAND with a temporary key file and combined known_hosts to authenticate git operations without exposing credentials in your workspace.
The actions/checkout action supports SSH key authentication as an alternative to the default GITHUB_TOKEN for cloning private repositories and submodules. When you configure SSH key authentication for actions/checkout, the action handles secure key storage, host verification, and automatic cleanup through its internal git authentication helper. This implementation ensures your private keys never persist in the repository workspace beyond the job execution.
How SSH Authentication Works Internally
When you provide the ssh-key input, the action executes a multi-step authentication sequence defined in src/git-auth-helper.ts. The configureSsh() method orchestrates this process, creating temporary files and environment variables that git uses for subsequent operations.
Secure Key Storage
The action writes your private key to a unique temporary file in $RUNNER_TEMP with strict permissions. According to the source code in src/git-auth-helper.ts (lines 55-63), the file is created with mode 0600 (read/write for owner only) and stored outside the workspace to prevent accidental commits. This temporary path is then referenced in subsequent SSH commands.
Host Verification Setup
The action builds a combined known_hosts file that merges three sources (lines 78-99):
- The runner's existing
~/.ssh/known_hosts(if present) - Any user-provided hosts from the
ssh-known-hostsinput - An implicit entry for
github.comadded automatically by the action
This merged file is written to $RUNNER_TEMP, ensuring that strict host key checking can be enforced without modifying the runner's permanent SSH configuration.
GIT_SSH_COMMAND Construction
The action constructs a custom SSH command that forces git to use the temporary credentials. As implemented in lines 103-113 of src/git-auth-helper.ts:
this.sshCommand = `"${sshPath}" -i "$RUNNER_TEMP/${path.basename(this.sshKeyPath)}"`
if (this.settings.sshStrict) {
this.sshCommand += ' -o StrictHostKeyChecking=yes -o CheckHostIP=no'
}
this.sshCommand += ` -o "UserKnownHostsFile=$RUNNER_TEMP/${path.basename(this.sshKnownHostsPath)}"`
This command is exported as the GIT_SSH_COMMAND environment variable for the remainder of the step. When persist-credentials: true (the default), the action additionally stores this configuration in the local repository's .git/config via git config core.sshCommand (lines 115-117), enabling subsequent git commands in later steps to use the same authentication.
Automatic Cleanup
After the job completes, the removeSsh() method (lines 336-366) removes the temporary key file, the temporary known_hosts file, and clears any core.sshCommand entries from the git configuration. This ensures credentials are not left on the runner after the workflow finishes.
Configuration Inputs and Parameters
The following inputs in action.yml control SSH authentication behavior:
ssh-key: The private SSH key (typically stored as a repository secret) used for authentication. When provided, the action bypasses the defaultGITHUB_TOKENauthentication.ssh-known-hosts: Additional SSH host keys to trust, useful for self-hosted Git servers or enterprise environments. These are merged with the runner's existing known hosts and the implicitgithub.comentry.ssh-strict: When set totrue, addsStrictHostKeyChecking=yesandCheckHostIP=noto the SSH command, preventing connections to hosts with unrecognized keys.ssh-user: Overrides the defaultgituser for the remote URL, used when constructing URL rewrite rules in the git configuration.persist-credentials: Whentrue(default), stores the SSH command in.git/configfor use by subsequent steps. Whenfalse, credentials are only available for the initial checkout.
Security Considerations
The implementation in src/git-auth-helper.ts incorporates several security measures:
- File Permissions: The private key is written with
0600permissions, ensuring only the current user can read the file. - Temporary Storage: All sensitive files are stored in
$RUNNER_TEMP, which is isolated from the repository workspace and cleaned up after the job. - Credential Persistence: The raw key is never written to
.git/config; only thecore.sshCommandpath reference is stored whenpersist-credentialsis enabled. - Submodule Isolation: When checking out submodules, the action configures SSH authentication individually for each submodule to maintain credential isolation.
Practical Configuration Examples
Basic SSH Checkout for Private Repositories
Provide the SSH private key as a repository secret to authenticate the checkout:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
ssh-strict: true
persist-credentials: true
In this configuration, the action writes the key to $RUNNER_TEMP, constructs the GIT_SSH_COMMAND, and persists the configuration for later git operations in the workflow.
SSH Authentication with Custom Known Hosts
For self-hosted Git servers or additional security hardening, provide custom host keys:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
ssh-known-hosts: |
git.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDIhz2GK/XCYzP8L4e8...
git.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...
ssh-strict: true
The action merges these entries with the existing known_hosts and the default github.com entry.
SSH Authentication for Submodules
When checking out repositories with private submodules, the SSH configuration is automatically propagated to submodule operations:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
submodules: recursive
persist-credentials: true
The configureSubmoduleAuth method (lines 215-229 in src/git-auth-helper.ts) ensures that each submodule receives the same core.sshCommand configuration, allowing recursive checkout of private submodules without additional authentication steps.
Summary
- Primary Method: Use the
ssh-keyinput to enable SSH authentication; the action handles all configuration throughsrc/git-auth-helper.ts. - Temporary Credentials: Keys are stored in
$RUNNER_TEMPwith0600permissions and never touch the workspace directly. - Host Verification: The
ssh-known-hostsinput and automaticgithub.comentry provide secure host key verification when combined withssh-strict: true. - Persistence: Set
persist-credentials: trueto enable subsequent git commands to use the same SSH configuration via.git/configentries. - Cleanup: The
removeSsh()method automatically removes all temporary files and configuration after the job completes.
Frequently Asked Questions
How do I configure SSH key authentication for actions/checkout with a passphrase-protected key?
Passphrase-protected keys are not supported directly by the action. You must provide the unencrypted private key as the ssh-key input. Store the key as a GitHub Secret and use OpenSSL to decrypt it in a previous step if necessary, or generate a new key pair without a passphrase specifically for GitHub Actions automation.
Where does actions/checkout store the SSH key during workflow execution?
The action writes the SSH key to a unique file in $RUNNER_TEMP (the runner's temporary directory) with permissions set to 0600. This location is outside the repository workspace and is automatically cleaned up after the job completes, as implemented in the removeSsh() method in src/git-auth-helper.ts.
Can I use SSH key authentication for actions/checkout with submodules?
Yes. When you provide the ssh-key input and set submodules: recursive or submodules: true, the action configures SSH authentication for each submodule individually. The configureSubmoduleAuth function in src/git-auth-helper.ts sets the core.sshCommand configuration in each submodule's .git/config, enabling authentication for nested private repositories.
What is the difference between using ssh-key and GITHUB_TOKEN for authentication?
The ssh-key input uses SSH protocol authentication with a private key, while the default GITHUB_TOKEN uses HTTPS with a temporary personal access token. SSH keys are required for accessing repositories outside the current GitHub instance or when specific SSH-based workflows are mandated. The GITHUB_TOKEN is automatically scoped to the current repository and its forks, whereas SSH keys provide broader access depending on the key's configuration.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →