webfactory/ssh-agent

repository·master·Indexed 23 days ago

https://github.com/webfactory/ssh-agent

A GitHub Action that automates the setup of an SSH agent within a workflow to allow seamless access to private repositories. It loads private SSH keys into the agent, exports the SSH_AUTH_SOCK environment variable, and supports automatic configuration for GitHub Deploy Keys using key comments to map keys to specific repositories.

Tokens
2.6K
Snippets
7
Records
15
Agent score
31%

What's inside webfactory-ssh-agent

  1. How GitHub Deploy Keys are handled with key comments

    master

    When using GitHub Deploy Keys, GitHub servers only accept the first matching key. Because deploy keys are scoped to specific repositories, a standard SSH connection might fail if the wrong key is presented first.

    To solve this, the ssh-agent action uses key comments to map keys to specific repositories:

    1. Create key with comment: When generating your key, include the repository URL in the comment: ssh-keygen ... -C "git@github.com:owner/repo.git".
    2. Automatic Configuration: The action scans these comments and automatically configures Git (using url.<base>.insteadof) and SSH (using a custom hostname/mapping) to ensure that requests to specific repositories use the correct corresponding key.
  2. Understand the limitations of the ssh-agent action

    master

    The ssh-agent action has specific design constraints:

    • No File-based Keys: The action loads keys directly into memory (ssh-agent). It does not write keys to disk. Therefore, you cannot pass the key as a Docker build-arg or a mounted file. You must use the SSH agent socket forwarding method.
    • No Remote Configuration: If you use the agent to connect to a remote machine via ssh, the action will not automatically configure known_hosts or other SSH settings on that remote machine.
    • No Automatic ssh-keyscan: The action does not run ssh-keyscan for you. If you need to add host keys to known_hosts, you should do so via a shell command in your workflow.
  3. Use Deploy Keys with Swift Package Manager

    master
    By default, xcodebuild uses Xcode's built-in Git tooling, which lacks the URL remapping required to use GitHub Deploy Keys. To use deploy keys with Swift Package Manager, pass the -scmProvider system flag to your xcodebuild command.
  4. Pass SSH agent to Docker builds

    master

    When building Docker images using docker build, docker compose build, or the docker/build-push-action, you must explicitly pass the SSH agent socket to the build process to allow the use of private keys during the build.

    For standard CLI commands, use the --ssh default=${{ env.SSH_AUTH_SOCK }} flag.

    For the docker/build-push-action, use the ssh input.

          - name: Build and push
            id: docker_build
            uses: docker/build-push-action@v2
            with:
              ssh: |
                default=${{ env.SSH_AUTH_SOCK }}
  5. Install and use the `ssh-agent` GitHub Action

    master

    The ssh-agent action starts an SSH agent, exports the SSH_AUTH_SOCK environment variable, and loads one or more private SSH keys into the agent. This allows subsequent steps in your workflow (like git clone using SSH URLs) to access private repositories without manual authentication.

    Setup Steps

    1. Generate an SSH key: Create a dedicated SSH key for GitHub Actions (do not use personal keys). Ensure it has no passphrase.
    2. Add Public Key: Add the public SSH key as a 'Deploy Key' in the target private repository.
    3. Add Private Key to Secrets: In the repository running the action, go to Settings > Secrets and create a new secret (e.g., SSH_PRIVATE_KEY) containing the full content of the private key file (including -----BEGIN ... PRIVATE KEY----- and -----END ... PRIVATE KEY-----).
    4. Add to Workflow: Add the action step to your workflow file, preferably near the top after actions/checkout@v4.
    # .github/workflows/my-workflow.yml
    jobs:
        my_job:
            steps:
                - uses: actions/checkout@v4
                - uses: webfactory/ssh-agent@v0.9.0
                  with:
                      ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
  6. Use multiple deploy keys in Docker builds

    master

    If you need to use multiple GitHub deploy keys during a Docker build, forwarding the SSH agent socket is not enough. You must also provide the Git and SSH configuration files so Git can select the correct key for the specific repository.

    Workflow Steps:

    1. Run the ssh-agent action.
    2. Collect ~/.gitconfig and ~/.ssh into a directory within your Docker build context.
    3. Run the Docker build.

    Dockerfile Requirements: Copy the collected configuration into the image and update the paths (e.g., using sed to replace the runner home directory with the container's root home directory).

    Note: Use a multi-stage build to ensure these configuration files (which may contain repository URLs) do not persist in your final production image.

          - name: ssh-agent setup
            ...
    
          - name: Collect Git and SSH config files in a directory that is part of the Docker build context
            run: |
              mkdir root-config
              cp -r ~/.gitconfig  ~/.ssh root-config/
      
          - name: Docker build 
            # build-push-action | docker [compose] build | etc.
            ...
    # Copy the two files in place and fix different path/locations inside the Docker image
    COPY root-config /root/
    RUN sed 's|/home/runner|/root|g' -i.bak /root/.ssh/config
  7. Configure Cargo (Rust) to use private dependencies on Windows

    master

    When using private Git dependencies in Rust on Windows runners, Cargo may fail to clone them. You must force Cargo to use the Git CLI instead of its built-in implementation.

    You can do this in two ways:

    1. Via a shell step: Run a command to update the .cargo/config.toml file.
    2. Via environment variable: Set CARGO_NET_GIT_FETCH_WITH_CLI to true for the entire workflow.
    # Option 1: Shell step
          - name: Update cargo config to use Git CLI
            run: Set-Content -Path $env:USERPROFILE\.cargo\config.toml "[net]`ngit-fetch-with-cli = true"
    # Option 2: Environment variable
    env:
      CARGO_NET_GIT_FETCH_WITH_CLI: true
  8. Create SSH keys for use with the action

    master

    When generating keys to use with this action, ensure the key does not have a passphrase. The action requires the key to be usable without manual input.

    Recommended generation commands:

    • Ed25519 (Recommended): ssh-keygen -t ed25519 -a 100 -f path/to/keyfile
    • RSA (Legacy): ssh-keygen -t rsa -b 4096 -o -f path/to/keyfile
    ssh-keygen -t ed25519 -a 100 -f path/to/keyfile
  9. Use exported variables from ssh-agent

    master

    When the ssh-agent action runs, it automatically exports environment variables that allow subsequent steps in your workflow to communicate with the running SSH agent.

    Specifically, it exports:

    • SSH_AUTH_SOCK: The path to the authentication socket.
    • SSH_AGENT_PID: The process ID of the running ssh-agent.

    These variables are set as job-level environment variables, meaning they are available to all following steps in the same job.

  10. Automatic GitHub Deploy Key configuration

    master

    The action detects if any keys added to the agent are intended as GitHub Deploy Keys by inspecting their comments for a GitHub URL pattern (github.com:owner/repo).

    If a match is found, the action performs the following setup:

    1. Key Storage: Saves the public key to ~/.ssh/key-<sha256_hash> with 600 permissions.
    2. SSH Config: Appends a configuration block to ~/.ssh/config using the Host key-<sha256_hash>.github.com pattern to ensure the correct IdentityFile is used for that specific repository.
    3. Git Configuration: Configures Git to use the specific identity for GitHub URLs via insteadOf rules for:
      • https://github.com/owner/repo
      • git@github.com:owner/repo
      • ssh://git@github.com/owner/repo
  11. Troubleshoot: Invalid SSH Private Key Format

    master

    If you encounter the error Error loading key "(stdin)": invalid format, your private key is likely not in PEM format. The action requires PEM format.

    You can convert your key to PEM using the following command (ensure you have a backup first): ssh-keygen -p -f path/to/your/key -m pem

    ssh-keygen -p -f path/to/your/key -m pem
  12. Use multiple SSH keys in a single workflow

    master

    If you need to access multiple private repositories that use different deploy keys, you can pass multiple keys to the ssh-private-key input by providing them as a multi-line string. The ssh-agent will load all keys and attempt to use them in order during SSH connections.

    Caveat: Some SSH servers may abort connections after a certain number of failed key attempts. If you have too many keys, the correct one might not be reached.

                - uses: webfactory/ssh-agent@v0.9.0
                  with:
                      ssh-private-key: |
                            ${{ secrets.FIRST_KEY }}
                            ${{ secrets.NEXT_KEY }}
                            ${{ secrets.ANOTHER_KEY }}