# How to Configure SSH Key Authentication for actions/checkout: A Complete Guide

> Learn to configure SSH key authentication for actions/checkout. Securely authenticate Git operations using the ssh-key input for enhanced security without exposing credentials.

- Repository: [GitHub Actions/checkout](https://github.com/actions/checkout)
- Tags: how-to-guide
- Published: 2026-07-05

---

**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`](https://github.com/actions/checkout/blob/main/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`](https://github.com/actions/checkout/blob/main/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-hosts` input
- An implicit entry for `github.com` added 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`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts):

```typescript
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`](https://github.com/actions/checkout/blob/main/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 default `GITHUB_TOKEN` authentication.
- **`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 implicit `github.com` entry.
- **`ssh-strict`**: When set to `true`, adds `StrictHostKeyChecking=yes` and `CheckHostIP=no` to the SSH command, preventing connections to hosts with unrecognized keys.
- **`ssh-user`**: Overrides the default `git` user for the remote URL, used when constructing URL rewrite rules in the git configuration.
- **`persist-credentials`**: When `true` (default), stores the SSH command in `.git/config` for use by subsequent steps. When `false`, credentials are only available for the initial checkout.

## Security Considerations

The implementation in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) incorporates several security measures:

- **File Permissions**: The private key is written with `0600` permissions, 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 the `core.sshCommand` path reference is stored when `persist-credentials` is 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:

```yaml
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:

```yaml
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:

```yaml
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`](https://github.com/actions/checkout/blob/main/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-key` input to enable SSH authentication; the action handles all configuration through [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts).
- **Temporary Credentials**: Keys are stored in `$RUNNER_TEMP` with `0600` permissions and never touch the workspace directly.
- **Host Verification**: The `ssh-known-hosts` input and automatic `github.com` entry provide secure host key verification when combined with `ssh-strict: true`.
- **Persistence**: Set `persist-credentials: true` to enable subsequent git commands to use the same SSH configuration via `.git/config` entries.
- **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`](https://github.com/actions/checkout/blob/main/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`](https://github.com/actions/checkout/blob/main/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.