Search code examples
githubherokusshvapor

How to setup Heroku to read a private repository linked to my server app using a SSH key?


Heroku does not find the right SSH key when deploying my Vapor application, and fails immediately. When trying to deploy my server on Heroku, I get this error as I added a private repository to my application.

(Before having added this private repository, the deployment worked with no issue)

Fetching [email protected]:MyName/MyRepository.git
warning: 'myrepository.git': skipping cache due to an error: Failed to clone repository [email protected]:MyName/MyRepository.git:
    Cloning into bare repository '/app/.cache/org.swift.swiftpm/repositories/MyRepository-65a67a5f'...
    Load key "/app/.ssh/id_rsa": error in libcrypto
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.
    Please make sure you have the correct access rights
    and the repository exists.
error: Failed to clone repository [email protected]:MyName/MyRepository.git:
    Cloning into bare repository '/tmp/build_e6a4655b/.build/repositories/MyRepository-65a67a5f'...
    Load key "/app/.ssh/id_rsa": error in libcrypto
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.
    Please make sure you have the correct access rights
    and the repository exists.
 !     Push rejected, failed to compile Swift app.
 !     Push failed

The private repository is set this way on my Vapor application's Package.swift file.

dependencies: [
  .package(url: "[email protected]:MyName/MyRepository.git", branch: "develop")
]

When deploying the Vapor app, Heroku looks for the app/.ssh/id_rsa key, but this is not the one I setup to use. I created a key named ~/ssh/id_heroku on my Mac, which I have setup on GitHub and Heroku with no issue.

I have used the buildpack https://github.com/heroku/heroku-buildpack-ssh-key.git on Heroku, which I added before the Vapor one on the Heroku application settings.

The .ssh/config file setup on my Mac looks this way:

Host heroku
  HostName heroku.com
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_heroku

Solution

  • Credits goes to @vzsg, from the Vapor Discord Channel.

    Private Github repos on Heroku (2023)

    1. No need to add an additional buildpack, as the https://github.com/vapor-community/heroku-buildpack does the work.
    2. Create a file called bin/pre_compile, in the root of the server app, with the following content:
    #!/bin/bash
    
    if [ ! -f Package.swift ]; then
        echo "File Package.swift does not exist."
        exit 1
    fi
    
    if [ -f "$ENV_DIR/GITHUB_USER" ]; then
      GITHUB_USER=`cat "$ENV_DIR/GITHUB_USER"`
    fi
    
    if [ -f "$ENV_DIR/GITHUB_AUTH_TOKEN" ]; then
      GITHUB_AUTH_TOKEN=`cat "$ENV_DIR/GITHUB_AUTH_TOKEN"`
    fi
    
    if [ -z "$GITHUB_USER" ]; then
        echo "GITHUB_USER is not set."
        exit 1
    fi
    
    if [ -z "$GITHUB_AUTH_TOKEN" ]; then
        echo "GITHUB_AUTH_TOKEN is not set."
        exit 1
    fi
    
    sed -i "s#git@github\.com:#https://$GITHUB_USER:[email protected]/#g" Package.swift
    
    1. Make the file executable and commit it to git:
    chmod +x bin/pre_compile
    git add bin/pre_compile
    git commit -m "Add pre_compile hook for private git repos"
    
    1. Create a personal access token with repo permissions:

    GitHub documentation

    1. Set two configuration variables: GITHUB_USER with your GitHub username (for which you created the token for and have access to the private repository), and GITHUB_AUTH_TOKEN with the newly creating token value:
    heroku config:set GITHUB_USER=<YOUR_GITHUB_USERNAME> GITHUB_AUTH_TOKEN=<YOUR_GITHUB_TOKEN>
    
    1. Deploy the database from Terminal or from the Heroku website.

    Note that the private repository, must be named starting with [email protected]:, and not https://github.com.