How to Use actions/checkout with Private Repositories: Authentication Methods Explained
Yes, actions/checkout fully supports private repositories, but you must configure authentication using the default GITHUB_TOKEN for the same repository, a Personal Access Token (PAT) for different repositories, or an SSH key for secure Git operations.
The actions/checkout action is the standard way to clone repositories in GitHub Actions workflows. When working with private repositories, the action handles authentication securely through multiple methods depending on whether you're accessing the workflow's own repository or an external one.
Authentication Scenarios for Private Repositories
Checkout the Same Private Repository (Automatic)
When your workflow runs in a private repository and you need to checkout that same repository, actions/checkout works out-of-the-box. The action automatically uses the default ${{ github.token }} (the GITHUB_TOKEN provided to the workflow), which is scoped to the repository that owns the workflow.
In src/input-helper.ts (lines 39-41), the token input defaults to the workflow's GITHUB_TOKEN, allowing immediate read access without extra configuration:
- uses: actions/checkout@v7
# No extra inputs – the default GITHUB_TOKEN suffices
Checkout a Different Private Repository (PAT Required)
To checkout a private repository different from the one triggering the workflow, you must supply a Personal Access Token (PAT) with appropriate repository permissions. Pass the token via the token input, which the action injects as an HTTP header for Git operations.
According to the README.md (line 291), the PAT requires repo scope (or finer-grained permissions) for the target repository:
- uses: actions/checkout@v7
with:
repository: my-org/my-private-tools # owner/repo of the private repo
token: ${{ secrets.MY_PAT }} # PAT with appropriate repo scopes
path: tools # optional, where to place the repo
SSH Authentication
For environments requiring SSH-based authentication, provide an SSH private key via the ssh-key input. You can optionally specify known hosts via ssh-known-hosts to prevent man-in-the-middle attacks.
In src/input-helper.ts (lines 42-48), the action handles sshKey and sshKnownHosts inputs, adding the key to the Git config and removing it after the job completes:
- uses: actions/checkout@v7
with:
repository: my-org/my-ssh-repo
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} # SSH private key
ssh-known-hosts: |
github.com ssh-rsa AAAAB3Nza...
ssh-strict: true # optional, enforce host-key checking
How Authentication Works Under the Hood
The action implements secure credential handling through two key components:
Input Processing – The getInputs() function in src/input-helper.ts parses workflow inputs (token, ssh-key, repository, etc.) and builds an IGitSourceSettings object that drives the checkout flow. The repository input defaults to ${{ github.repository }}, but when a different owner/repo is supplied, the action uses the provided token or SSH key to authenticate against the target host.
Authentication Configuration – The src/git-auth-helper.ts file creates temporary credentials for the Git operation. For token-based auth, it creates a temporary .extraheader entry using the format x-access-token:<token>. For SSH authentication, it configures a temporary SSH credential file. Both methods are removed in the post-step to prevent credential leakage.
Practical Code Examples
Checkout Multiple Private Repositories Side-by-Side
You can checkout multiple private repositories within the same job by specifying different paths and authentication tokens:
- name: Primary repo (public or private)
uses: actions/checkout@v7
with:
path: main
- name: Secondary private repo
uses: actions/checkout@v7
with:
repository: my-org/second-private
token: ${{ secrets.SECOND_PAT }}
path: second
Complete SSH Configuration
When using SSH authentication, ensure you provide the private key in the correct format and specify known hosts when ssh-strict is enabled:
- uses: actions/checkout@v7
with:
repository: my-org/private-repo
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
ssh-known-hosts: ${{ secrets.SSH_KNOWN_HOSTS }}
ssh-strict: true
Summary
- Same repository checkout: Uses the default
GITHUB_TOKENautomatically viasrc/input-helper.ts(lines 39-41) with no additional configuration required. - Different repository checkout: Requires a PAT passed via the
tokeninput with appropriate repository scopes. - SSH authentication: Supported via
ssh-keyandssh-known-hostsinputs, handled securely insrc/input-helper.ts(lines 42-48) and cleaned up post-job. - Security: Credentials are temporarily injected by
git-auth-helper.tsand removed after checkout to prevent leakage on self-hosted runners.
Frequently Asked Questions
Does actions/checkout work with private repositories without any configuration?
Yes, but only for the repository that triggered the workflow. The default GITHUB_TOKEN provided to the workflow run automatically authenticates access to the same private repository. For any other private repository, you must explicitly provide a PAT or SSH key.
Why do I need a PAT for a different private repository when I already have GITHUB_TOKEN?
The GITHUB_TOKEN is scoped only to the repository where the workflow runs. When you need to access a different private repository (cross-repository access), GitHub's security model requires explicit authorization through a PAT that has been granted access to the target repository.
Is the SSH key or token stored permanently on the runner?
No. According to the implementation in src/git-auth-helper.ts, the action creates temporary credential configurations (HTTP headers or SSH files) for the duration of the job only. The post-job cleanup step removes these credentials to prevent exposure on self-hosted runners or subsequent workflow runs.
Can I checkout multiple private repositories in one job?
Yes. You can invoke actions/checkout multiple times within the same job, specifying different repository names, path locations, and authentication tokens. Each invocation operates independently, allowing you to clone several private repositories side-by-side using different PATs if needed.
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 →