Heroku and Public Keys: The Full Monty
When you first install the Heroku Toolbelt on your machine, there’s a good chance you will run into a problem with pushing your code via git to the Heroku remote. The common issue is an error message that looks something like this:
Permission denied (publickey).
fatal: Could not read from remote repository.
What you are seeing here is a problem with how your private/public key pairs are configured between your computer and the Heroku server. If you already know what public/private key pairs are, you can skip ahead to the explanation of how to fix this.
A private/public key pair, in layperson’s terms, is like tearing a sheet of paper into two parts, and then holding onto one of them as your “secret.” The other piece of paper can be duplicated as many times as you wish and given out to the public. When you want to confirm to someone that you were the person that held the original sheet of paper before it was torn, you produce your “secret” half, and show that the two parts join exactly along the tear.
With key pairs, an algorithmic cryptography technique called public-key generation guarantees that the pair you generate is unique to you – using our analogy above, the zig-zags on your private half of the sheet of the paper cannot be duplicated by someone else. Understanding how that happens, mathematically speaking, is beyond the scope of this blog post 🙂
This is a very useful property because it allows you to share the public part “publicly,” and then use the private part to identify yourself. Strictly speaking, what happens during the process of public-key based encryption is that the holder of the public key “signs” a piece of information using the public part of your key pair. The algorithms work to ensure that only the private key can be used to “un-sign” this piece of information. If only you have access to the private part (and you should be the only possessor of the private part so guard it very carefully!), then only you will be able to un-sign and thereby identify the piece of information that was signed by the other party. Typically this piece of information is a very large random number that would be extremely hard to just get lucky and guess at.
So what went wrong with your Heroku push then? Like many other server systems, your code on Heroku is protected using public key crytography. When you attempt to upload your code to Heroku, the Heroku server will “challenge” you to un-sign a random number which it has encrypted using your public key part. This implies that you should have added this part to Heroku in the first place, which you do by logging in and then “uploading” the public key.
heroku login # You will be prompted for your email and password
When you attempt to add a key, the Heroku Toolbelt will figure out where your key pairs are stored by querying your local SSH installation. Typically, this is stored in your home directory in a folder called .ssh. The structure of the files is conventionally in the form pairname and pairname.pub. If you use the ssh-keygen command to create a key pair, the default behavior is to store the private key in a file called id_rsa, and the public key in a file called id_rsa.pub. When you run the keys:add command, therefore, its default behavior is to look for these two files. This is important to note – it’s what trips up a lot of people because their OS installation or their account configuration for some reason didn’t use the default names when creating the keys but they will still be used when Heroku tries to locate them.
If you already have a public key but it’s not prefixed with id_rsa, you can change the default behavior by adding a file named config in your .ssh folder. The config file format will specify which key prefix to use for which domain you are authenticating yourself on – in the case of Heroku, the domain is heroku.com.
Another issue could be that someone (hopefully, you!) has already uploaded a public key part to Heroku, but the machine you are now using to do development on doesn’t have the corresponding private key in your store. You can check what Heroku keys are already present, if any, by simply typing in heroku keys at the command line. You will see a truncated version of your public key with the first few and last few characters which you can compare to any public keys you already have. If you didn’t create these keys (Horrors! That’s not a good sign – someone might have hacked into your account!), or if you don’t have the private key any more (which might happen if you had to re-install your OS, say), then you can simply start over with heroku keys:clear – this will remove all of Heroku’s copies of your public keys, and you can go back to running heroku keys:add to start with the key pair that you do have in your possession now.