I'm trying to configure an EC2 with known SSH host keys on boot using cloud-init in a cloudformation template. But now I can't SSH into the server. It's tricky to debug :-)

Here's the userdata part of my EC2 fragment from my template:

    "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
      "#cloud-config", "\n",
      "ssh_keys:", "\n",
      "- rsa_private: |", "\n",
      "    -----BEGIN RSA PRIVATE KEY-----", "\n",
      "    MIIEowCBAAKCAQF71D8K9C/+K0a2fO+S9s441kSI44lF5ml++ewD+Mp115x9", "\n",
      "    /XwwTlvqxCIpxdzpzq4xXEqH48StHyYIjAOPxoS1/QG0Ti6OqU893PpukLdmV", "\n",
      "    kLZKn2ph4fTT2aMl...", "\n",
      "    -----END RSA PRIVATE KEY-----", "\n",
      "rsa_public: ssh-rsa AAAAB...", "\n",

I also have entries for (ec)dsa_public/private as per the docs.

Is there some weirdness with cloudinit where I have to also specify ssh_authorized_keys as well? I assume my keypair's public key isn't now being pushed onto my EC2 by Amazon...

  • 4
    Never put your private key in any configuration, it's called private for a reason -- this key is supposed to reside on a trusted machine (e.g. your laptop). – galaxy Sep 3 '15 at 11:31

The UserData from your question is basically a shell script that runs at first boot of your instance. See the documentation on UserData for more details on that.

If you want to configure a set of public keys, you can use AWS::CloudFormation::Init instead.

In the files section, declare the authorized_keys file:

"files" : {                                                                                                                                                                                                                                                                               
  "/home/ec2-user/.ssh/authorized_keys" : {                                                                                                                                                                                                                                               
    "content" : { "Fn::Join" : ["", [                                                                                                                                                                                                                                                     
      { "Fn::FindInMap" : [ "Admins", "userx", "sshPublicKey"] }, "\n",                                                                                                                                                                                                                
      { "Fn::FindInMap" : [ "Admins", "usery", "sshPublicKey"] }, "\n"                                                                                                                                                                                                                 
    ]] },                                                                                                                                                                                                                                                                                 
    "mode" : "000600",                                                                                                                                                                                                                                                                    
    "owner" : "ec2-user",                                                                                                                                                                                                                                                                 
    "group" : "ec2-user"                                                                                                                                                                                                                                                                  

The user data in this example comes from the Mappings section of the cloudformation template:

"Admins" : {                                                                                                                                                                                                                                                                          
  "userx" : { "sshPublicKey" : "ssh-rsa AAAABxxxxx...xxxxBSES/H userx" },
  "usery" : { "sshPublicKey" : "ssh-rsa AAAABxxxxx...xxxxKM+aSe usery" }

Please test it first by using a different filename instead of authorized_keys, as indeed you will be locked out of your instance when you make the slightest mistake.


I needed to do this because I didn't have the keys to our prod env in AWS to ssh into instances to debug why CFN deployment was failing. For various reasons, including that I was troubleshooting something that had gone wrong with cfn-init itself, I found it a better strategy to add the following line to the top of UserData and pass the parameter tempSSHkey to CFN:

           Fn::Base64: !Sub |
               #!/bin/bash -ex
               sudo echo 'ssh-rsa ${tempSSHkey} temp-ssh-key' >> /home/admin/.ssh/authorized_keys

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.