I spent more than a day trying to figure out how to connect via ssh using a private key but without a result.. all languages some to have an example when it comes to ssh except erlang/elixir which I don’t know why it’s that hard.
The only example I can find is using username/password, but I want to ssh to another machine using username and private ssh key (id_ed25519),
If you are using OTP, it’s always worth checking out the official documentation. Here is how to configure custom keypairs for servers and the next paragraph is for clients: ssh — OTP 29.0.2 (ssh 6.0.1)
The parameters that can be sent to the client/daemon are also clearly documented, take a look through them: ssh — OTP 29.0.2 (ssh 6.0.1)
Ok I believe this is so easy for you so please just add that one line or 2 missing lines where I have put a placeholder for completion (my private key is located in /home/me/.ssh/id_ed25519)
ssh_options = [
{:user, user},
{:silently_accept_hosts, true},
{:user_interaction, false},
# ====== please just fill in here those easy missing lines ======
]
{:ok, conn} <- :ssh.connect(ip, port, ssh_options, 5000)
BTW I am really newbie to OTP, but I am sure you an experienced on these stuff.
For the record, I re-read the comment you are referring to three times and hereby I admit it does not have wording “it is easy to do.”
It suggests reading docs. Which is the great advice, btw. You might also read something about SSH in a nutshell, because your attempt to pass the username alongside with the file hints you are not quite familiar with it.
As far as I can tell the only way to do this is to implement a ssh_client_key_api callback.
The default is to look for the key files in the .ssh folder, this you can override with user_dir option.
I have never used it myself, but saw a reference to a package called librarian that seems to support it.
If you want to write it yourself, you can look at how they do it.
A good starting point IMO is the example in the :ssh user guide.
That shows the general shape of things (connect/session_channel/exec) but doesn’t really use the messages, or answer your original question.
For the “using the messages” part, take a look at how SSHEx does it - the whole file is worth reading, but this is where the actual {:ssh_cm, ...} messages get handled:
For the second half, there are two behaviours that :ssh depends on but the one we care about is :ssh_client_key_api. That’s implemented by two modules supplied with :ssh, :ssh_file and :ssh_agent which use either files or the SSH agent. :ssh_file is the default, but you can pass an alternative implementation via the :key_cb option to :ssh.connect.
HOWEVER
:ssh_client_key_api has more moving parts than just “here is a key”, it also deals with known hosts. SSHEx includes an implementation you could use / model after:
It’s too bad this conversation didn’t result in documenting a solution to the use case of connecting using ed25519. I’m trying to use bootleg which is build on top of sshkit and ssh_client_key_api. Right now, I can’t determine if the problem is with those (somewhat outdated) project or if it’s just me
Thanks for this branch. I’ve got a pretty stock bootleg and sshkit but now that I’ve used your branch of ssh_client_key_api I’m able to authenticate with ed25519!
It’s too bad that Labzero isn’t maintaining bootleg and ssh_client_key_api because they are good solutions for exactly what I’m trying to do.