Is there a single line command to tell SSH to add a provided public key to the local machine's authorized_keys file? A local version of ssh-copy-id?

I am writing a chef recipe and want to ensure a specific ssh public key is set for a certain user. I could overwrite the ~/.ssh/authorized_keys file each time, or attempt to some hacky way to add the line, but if there's an official command, it'll be more robust and prevent duplication.

Something like:

ssh-add-local-key "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDeblahdeblah user@somwhere"

For apt systems like Ubuntu or Debian there is an apt-add-repository command, so I wonder if there's a SSH equivalent.

Update: I know I could use "echo blah >> authorized_keys", but I want something idempotent, which I can run regularly. With >> the file will grow in size every time.

  • 4
    Usually I just use cat or similar to append the provided key to the keyfile. I agree that overwriting would be very bad, but you can avoid a specialist command without overwriting. – MadHatter supports Monica Oct 19 '17 at 9:47
  • cat id_rsa.pub >> /homedir/.ssh/authorized_keys or something like that. I use ansible to do the task – Federico Galli Oct 19 '17 at 10:02
  • If you do not want to cat it in there, you can of course just use ssh-copy-id you@localhost. Or you build some script (possibly grep -v the new key in the file and then append it to the output or similar), but be careful not to lock out yourself while testing it. – allo Oct 19 '17 at 15:10

I'm not aware of such a local command. I don't like ssh-copy-id foo@localhost (because it opens a SSH connection) and I even less like the error prone echo foo >> ~/.ssh/authorized_keys.

But since you're using chef, why don't you use the chef tools (mainly ruby) you have available?

For example:

ruby_block "authorized_keys" do
  block do
    file = Chef::Util::FileEdit.new("/home/#{username}/.ssh/authorized_keys")
    file.insert_line_if_no_match("/#{authorized_key}/", "#{authorized_key}")

insert_line_if_no_match documentation:

#insert_line_if_no_match(regex, newline) ⇒ Object

search the file line by line and match each line with the given regex if not matched, insert newline at the end of the file

This doesn't seem hacky all that much to me and provides an easy to understand way to solve your problem.

Another alternative would be Bill Warners answer to a similar question: https://stackoverflow.com/a/28283354/2376817


There's now a chef authorised keys cookbook. You simply add your key to your cookbook thus:

ssh_authorize_key 'bob@acme.com' do
  key 'AAAAB3NzaC1yc2EAAAADAQABAAABAQCctNyRouVDhzjiP[...]'
  user 'root'

Note that if you use this cookbook, any keys added by hand will be deleted.

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.