Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: I built a simple, open-source tool to manage servers and SSH keys (github.com/d3witt)
133 points by d3witt 3 months ago | hide | past | favorite | 90 comments



I see that you're getting hammered in this thread, so I want to say a few things:

1. Great job on shipping! Whether or not the people in this thread find this tool useful, I want to congratulate you on putting together something you're ready to share with the world.

2. I'd love to hear the story of what prompted you to create this tool. Was it an issue you had? Did you set out to make something easier?

3. Not everything has to be useful to everybody. It's OK if this is something you find useful and no one else does.

Cheers


That was very well put. I noticed an increasing negativity in Show HN posts lately. The usual inquisitive and supportive comments are being replaced with straight up negative and dismissive ones (or maybe it was always like this and people being nice is just a fabricated memory of mine)


I think there are multiple reasons for that.

The first is an increased fatigue caused by some poor quality posts OR posts presenting the same thing again and again just by opportunism (e.g. boilerplates where people just share their thing as an Ad). Therefore, the trust has decreased and people start asking themselves "what's hidden behind".

Another reason might be related to the surge of cyberattacks of all kinds. Lots of comments here are not super nice, but they are polite and ask good and legitimate questions, especially regarding cybersecurity.

As long as people are polite, argumented criticism should be appreciated.


Not a fabricated memory, I've noticed the same trend. And I thought, maybe it's because being controversial is the norm lately. I hoped HN would be immune to it though.


Definitely. As for the purpose of the tool and the issues, they will become clearer after the next couple of releases.


That's a deeply troubling non-answer right there.


> As for the purpose of the tool and the issues, they will become clearer after the next couple of releases.

... wth


So, congratulations on releasing your project but I'm not sure what problem are you trying to solve.

Please add some use-cases to make it clear where exactly does it come in, because once I add a key in my ssh config, I'm pretty much there. For more complicated tasks I use ansible.


Thanks!

- No need to remember server IPs - Viking gives you an overview with simple machine ls and key ls commands - A more modern and intuitive API - Works consistently across all platforms - Close to the Docker API

Sure, it’s only the first release. It may not seem like much now, but with feedback, the project will move closer to the goal.


>No need to remember server IPs

On your local machine under ~/.ssh/config you can add something like

#PERSONAL

Host vpn-us

    HostName 1.2.3.4

    User my_fun_username

    Port 1212

now you can ssh using

ssh vpn-us

(above is the same as the following command --> ssh my_fun_username@1.2.3.4 -p1212)


Also you can organize servers into different config files and Include them your base config,.

  $ cat .ssh/config
  # Fictitious example
  Include work.config
  Include personal.config
  $ 
https://man7.org/linux/man-pages/man5/ssh_config.5.html


This looks very useful. I did not know this. Thank you!


Hope it helps. I use the configs as a source of truth and have a dozen or so different included files. This way the servers are grouped logically similar to ansible enventories (which I generate using the different configs). Running a command against all servers in one or more configs is simple this way:

  $ grep '^Host' .ssh/<config file> | awk '{print $2}' | while read hst; do ssh $hst '<remote command>' 2> /dev/null < /dev/null; done


One thing I wish ~/.ssh/config had was more slightly powerful matching. I think all you get for dynamic matches is * and ? instead of a regex syntax. Works probably 99% of the time.


It seems there are many aspects of the OpenSSH suite you are unfamiliar with.

I would personally prefer using well-known tools over installing someone's latest project to handle something as sensitive as my SSH credentials.

Installing code instead of editing my .ssh/config seems like a gigantic risk.


> No need to remember server IPs

If I put my server's IP in my ~/.ssh/config, I don't need to remember it, and the autogenerated `~/.ssh/known_hosts` file will ensure that the IP doesn't change after my first time connecting. Is there some functionality beyond this in terms of remembering server IPs?


Like other commentators have already mentioned but the openssl suite already solves these problems and even more complex ones

For example:

Specifying different keys different servers

Host github.com

    User git

    IdentityFile ~/.ssh/id_rsa_github
Host myserver

    User username

    IdentityFile ~/.ssh/id_rsa_myserver
Reuse SSH connections for multiple sessions

https://blog.scottlowe.org/2015/12/11/using-ssh-multiplexing...

https://blog.poespas.me/posts/2024/04/27-optimizing-ssh-conn...

Host *

    ControlMaster auto

    ControlPath ~/.ssh/sockets/%r@%h-%p

    ControlPersist 600
Other than that, you can also do ssh agent forwarding, port forwarding etc. These are all crucial functions that user like me need when we access remote machines.

I hope you take this as constructive criticism and not a knockdown on your work. You've created and released something that's great but this site usually brings more advanced users.


Essentially you wrap via CLI what you can code in ~/.ssh/config, I'm not so sure how this could be comfy.


Right, I don't see the point of this at all. If anything it seems like more of a pain in the ass than just using ssh directly.


SSH already has host and key management via the user's config file.

I somewhat understand the desire for an SSH client that behaves like the Docker shell, but it needs some features that actually set it apart.

How about putting different hosts into groups, and then running a command on the group so that every machine in the group runs the same command?

How about managing both hosts and users so that I can easily log into a system as different users for different purposes?

How about adding some security features to make key management more secure than the standard "everything in the .ssh directory" strategy?

Maybe add some SCP/SFTP features so that moving files from host to host is easier. Maybe even have a package you can install on remote hosts so that they can transfer files directly between each other when asked to from an outside terminal.


> How about putting different hosts into groups, and then running a command on the group so that every machine in the group runs the same command?

That can be done with a simple awk/fzf script, which would even allow me to interactively chose the hosts from the ones configured in the ssh config.

> How about managing both hosts and users so that I can easily log into a system as different users for different purposes?

The ssh config already allows doing that:

    Host prod-as-foo
        HostName domain.of.prod.server
        User foo
        Identity File ~./ssh/foo.key

    Host prod-as-bar
        HostName domain.of.prod.server
        User bar
        Identity File ~./ssh/bar.key
> How about adding some security features to make key management more secure than the standard "everything in the .ssh directory" strategy?

IdentityFile keys can be setup to be symmetrically encrypted, requiring a password on use.

The keyfiles can also be loaded via `ssh-agent(1)`, allowing to directly use non-local keyfiles (source: `man ssh`)

> Maybe add some SCP/SFTP features so that moving files from host to host is easier.

Both `scp` and `sftp` already use the ssh config file.


"putting different hosts into groups" - it's on my radar "Maybe add some SCP/SFTP features so that moving files from host to host is easier." - sounds good, I'll check


> No need to remember server IPs

Umm, DNS?

> with feedback, the project will move closer to the goal

What goal? That was the question you replied to.


Question: What is the specific advantage I get from using

    $ viking machine add --name deathstar --key starkey 168.112.216.50
    $ viking exec --tty deathstar /bin/bash
Over putting the following in my ~/.ssh/config

    Host deathstar
        HostName 168.112.216.50
        User my_user
        IdentityFile ~/.ssh/starkey
And then just typing

    $ ssh deathstar

?


as someone who dislikes config files to an extreme degree (hidden information, commands stop being portable) a modern cli that allows me to manage my configurations seems very useful


> as someone who dislikes config files to an extreme degree

This tool has a config as well. From the repos readme:

    Viking saves data locally. Set VIKING_CONFIG_DIR env variable for a custom directory. Use viking config to check the current config folder.
> hidden information

What exactly is "hidden" about ~/.ssh/config ? It's a plaintext file in a format that is the same across every single machine that uses openssh, which is pretty much every *nix box on the planet.

> commands stop being portable

How is using literal `ssh` not portable? If you're talking about the ssh config: That is a plaintext file that can be checked into a repo and simply downloaded to any machine I want. And again: viking too has a config.

> a modern cli

    host=$(
        awk '$1 == "Host" && $2 != "*" {print $2}' "$HOME/.ssh/config" |
        fzf --reverse
    )
    [[ -n host ]] && ssh "$host"
There. I just built a modern, interactive tool to chose a server from my ssh config. It requires only fzf as a non-standard dependency, a tool that is present in pretty much every package repository.

> allows me to manage my configurations

    vim ~/.ssh/config
There. A powerful, searchable, portable way to manage my SSH configuration. I can even use comments, and have access to all ssh settings available. All dependencies come preinstalled on most *nix boxes.


While mature and time-honored, not modern, utilities like sed and envsubst go a long way to managing any config. Making a "modern cli" application that wraps existing functions is like giving someone a fish, as opposed to teaching them to fish with stable and ubiquitously available tools.

Create entry (using a template and exported variables):

  $ envsubst < .ssh/template.config >> .ssh/config
Read entry (assuming the 4 line template):

  $ sed -n /<Host entry>/,+3p .ssh/config
Update entry: Delete and Create

Delete entry (assuming the 4 line template):

  $ sed -i /<Host entry>/,+3d .ssh/config


this site has only two audiences. nerds and mba's.

you're in a nerd thread, and will be downvoted without comments by starting an unwillingness to deep knowledge for the sake of knowledge.

if this were a mba thread the opposite would happen.

that said, shame on you for wanting ignorance!


From the outside looking in, it's not at all clear what the tool is trying to solve. What exactly is made "easier"..? What does it do that ssh doesn't? Who is this for?

Many questions...


Three things I can see. Yes, I know these are achieved by using .ssh/config etc, I am just answering as a public service.

1. It links up addresses to host names so that you don’t have to remember ip addresses of servers. 2. It makes it easy to create keys and attach those keys to particular hosts, so reduces the effort required to separate keys depending on your host 3. It makes key rotation fairly easy 4. It replaces the ssh command syntax with a k8s or docker-like syntax for executing remote commands or entering a shell. So I suppose you don’t need to context switch?


> It links up addresses to host names so that you don’t have to remember ip addresses of servers.

Um.


Just imagine that DNS doesn't exist. Or hosts files. Or `~/.ssh/config`...


Well I can imagine working in a cheapo shop where you cannot have public technical domain or setting up DNS is "too much to spend on".

But hostfile well if you have to share it with 2-3 other people might be a hassle?


That's why ssh config allows setting up alias names for servers.


If you're managing a ton of servers manually, this makes a lot of sense.


~/.ssh/config is perfectly fine for that.


Nope.

I've used linux since the 1990s. Was friends with the founders of LinuxCare, met Torvalds. blah blah blah...

Since semi-retire from ops... and basically using windows for a few years without need to manage a linux box, youd be FN surprised how quickly basic knowledge evaporate at my age when not in use. I had to fn lookup how to add my keys to a box again.

(After a 3-month long panel-interview with Google's Net Eng Team back in the day - my final panel question was:

"OK how do you do a global search and replace in VI?"

I *blanked* -- and I stated... "UH.... I'cant recall - id just google it"

They all laughed.

---

@OP -- look at the remote SSH extension in VSCode/Positron etc...

Its a really good little file/function/SSH manager.

Though Ill take a look at this.


If the issue is forgetting basic commands / configuration options then how does swapping one tool for another help? You'll just forget how to use the second tool instead.


The second tool could be more user friendly, thus easier to remember how to use it. Compare how this tool makes you generate a key vs the syntax of ssh-keygen.


Worth a chuckle from me too. I could and do type that all day, muscle memory. Verbalize it? Not a chance. There's a % in there somewhere.

There does seem to be a subset of questions that are really just "have you repeatedly used this tool in the last few months?". If you have, you'll probably be fast.


If you’re managing a ton of servers you are already using ansible or packer or salt or something.


You’d be surprised… a lot of especially legacy setups are very duct-taped together. Heck recently as last year I needed a three machine cluster and just did it manually instead of ansible.

I could definitely see the use of a tool like this if it was fleshed out a bit more.



(Or Userify installed with Ansible..)


That's a sensitive area for someone unknown to be touching.

You have no information about who you are or what you've done and you expect me to trust you with ssh keys and remotes?

The go.sum is concerning as well because now I need to trust all of those.

https://github.com/d3witt/viking/blob/main/go.sum


Yikes, for an app like that, that is way too many dependencies to cross check.

I would argue this should be 100% avoided in production environments at this time.


Agreed. The project could have been implemented as a simple to inspect bash script and yet it has enough dependencies to fill up my screen.


Good point.


I feel like some of these things are solved problems. We store our SSH authorized keys in LDAP, cache it with NSLCD. Backup keys are pushed during setup, rotated regularly. Everything audited through separate systems.


Congratulations on shipping your project!

Before I provide any feedback, I’m curious…

Your GitHub account appears to be a fresh account, using a pseudonym and a DuckDuckGo email address. What’s the reason for all of that? Are you a new developer? Did you simply not have a GitHub account because you never needed it? Is it just some privacy-related reason? Some other reason(s)?

I’d love some clarification on that, if you don’t mind.

To be clear, it’s perfectly fine to not have had a GitHub account—it’s just a bit unsettling when the very first project from a new and pseudonymous account is one dealing with servers and SSH keys.


What's the point of having different ssh key per server?

You are .pub is meant to be shared; even publicly. It's fine to have one ssh key for everything. It's also hard to think about a scenario where one ssh key in your machine is compromised, but not the others.


> What's the point of having different ssh key per server?

Identity protection perhaps. A public key could reveal that the same person is accesing two or more servers. Different keys per server hide that information.


That's a good point. Moreover, someone built[1] an SSH server that prints your name when you connect (because GitHub publishes SSH public keys of every user):

    ssh whoami.filippo.io
[1]: https://words.filippo.io/ssh-whoami-filippo-io/


> What's the point of having different ssh key per server?

I do have some use-cases where I use different ssh-keys per server/cluster:

- Setting up client's machines allow me to nuke the keypair when work is done and I no longer have access. Customers trust me to do this - they trusted me to set up their machines already.

- Belonging to different projects: so that when the project is finished, handed over or closed down, I can safely delete all keys associated with that, knowing for sure I'm not deleting keys that I did need after all.

- Having different levels - testing these levels. I set up servers in a way that there's sysadmins who have root/sudo, and `deploy` users that can only deploy apps (e.g. capistrano, ansible, k8s and so on) and maybe `sudo systemctl restart my-app` and/or read certain /var/log/some-log. I want to be sure that something does/does not work because of the correct keys, and not because one of the 12+ keys in my ssh-agent happens to be used instead.

So, in my case, I do have a lot of ssh-keys that I juggle with.

I wish there were just a version of ssh-agent/ssh-add though, with better UX. Looks like maybe viking is that?


I agree!

People should generate at least a single ssh key per client device. (On Userify, rotating your key is just a matter of pasting the new public key into your keybox in your dashboard.) One per client device will let you revoke/rotate only that key when it's compromised. This also helps keep you from copying the private key somewhere else (which you should never do).

It does look like this wants to be a replacement for ssh-agent/ssh-add; also check out GNU keychain by Daniel Robbins, which is in most distro repos.

(blatant plug - we actually developed Userify for these three use cases, especially on cloud instances with constantly changing IP's)


One key per laptop.


Some segregation is useful. If a key I use for work never touches my personal machine, that's a good thing. If my work laptop gets stolen I don't want to have to cycle my personal key, etc.

I guess the point I'm making is more for making decent keys to create sensible separation points, rather than having one for each machine though. Allowing work vs home vs foo vs bar


Right. We usually recommend a single key per client device (laptop, desktop, etc), because that way you can rotate that key if it gets lost/stolen without changing your other devices as well. This way, those private keys stay totally local to the device and never actually need to move, which is much safer. (I work at Userify.)


Here are a few use cases for having multiple SSH key per server: - use a different SSH key for each client machine: if the client machine is lost/compromised, just remove that key from the server's authorized_key - multiple accounts for the same server. This is useful for example to use multiple GitHub accounts

My github-keygen tool allows to manage your ~/.ssh/config for those GitHub use cases.

https://github.com/dolmen/github-keygen


Reads like some misguided attempt at improving security.

Maybe OP also moves private keys around and doesn't know private key ideally should never leave single machine and if you setup new laptop to connect to your servers one should generate new private key and upload new pub key and for backup ideally one should have spare laptop already set with keys.


You are very close to solving a real business problem. The problem is not "how can I have SSH aliases on my computer" but "how can we manage, company-wide, who can access which SSH servers."

My company currently uses YubiKeys to support hardware-based individual SSH keys. These SSH keys are distributed with Ansible. It works but is cumbersome and lacks a single pane of glass.

What we would like to have: a list of servers, a list of users, user roles (via sudoers), and a WebUI to manage all of it. And I don't know of any tool to do this. Of course, there are tools like Teleport or SSH CA instead of SSH keys, but they are for larger organizations and are overkill for my company.


You can do all that, including the YubiKeys, with 1Password for Teams, the Web UI to manage vaults with RBAC, the 1Password CLI and SSH Agent on machines, etc. See also the shell plugins.

https://developer.1password.com/docs/ssh/agent/security

https://developer.1password.com/docs/secrets-automation/#com...

https://1password.com/developer-security

https://1password.com/product/enterprise-password-manager

Or, depending on your use cases, check out Doppler:

https://docs.doppler.com/docs/workplace-team

https://community.doppler.com/t/generating-authorized-keys-f...


there is the AuthorizedKeyscommand feature that allows for a command to fetch keys not yet existing on a system. Gitlab uses it to fetch keys from a database, for central user and access management. They also ship a own sshd implementation which does kinda neat lookup things for very big databases.

theres already projects solving central ssh key management, for example:

https://github.com/ierror/ssh-permit-a38 (distributes via authorized keys)

https://github.com/netlore/OpenAKC

https://tenshidev.medium.com/centralized-ssh-authentication-...

and

https://docs.gitlab.com/ee/administration/operations/fast_ss...


Interesting use case, I'll definitely consider it. Thanks for sharing.


Is everyone just logging in as root or something?


I would rather require a tool to manage host keys. I really wish to write them along with the host configs in my `~/.ssh/config` instead of `known_hosts`. Additionally I think other host keys e.g. from GitHub should be delivered in a better way. For example, on Archlinux I would prefer getting them from package manager instead of being prompt during connection. Unfortunately host keys can only be written in `known_hosts` and `known_hosts` does not support importing or other method to seperate into different files.

EDIT: I was wrong. See comments.

Does anyone have any suggestions?


You can specify multiple files using either `GlobalKnownHostsFile` or `UserKnownHostsFile` options. Plus you can specify a command that will return host keys. See this entry in `man ssh_config`:

     KnownHostsCommand
             Specifies a command to use to obtain a list of host keys, [...]


Wow I didn't know that. I will definitely try it! Thx!


There's GlobalKnownHostsFile and UserKnownHostsFile. The global known hosts file is usually stored in /etc/ssh, linux distributions could store common ssh host keys in there.


Unfortunately, ArchLinux is not doing so. It is hard to define common though. I guess that's one of the reasons such package does not exist.


DNS SSHFP records


After having executed an involved ssh connection, my brain often opts to keep working on whatever I needed to use that remote machine for, instead of switching context and saving the details in ~/.ssh/config, even if I expect to use the connection details again.

So I understand the desire to manage both of those tasks, connecting and persisting, from one tool. I wrote a similar little utility that does this by adding a persist option to built-in ssh. https://github.com/emileindik/slosh


Very nice for a first project! (the clipboard integration is a nice touch)

Seeing this passion is great! TBH, some of the negative comments here might be warranted: SSH is an especially important and tricky area to start in as your first Github project or for those inexperienced in security.

However, we're always looking for people at Userify to help us build the next wave of SSH UX and who aren't afraid to put something out there. It's a lot of work to get things built and it's very exciting to see some new ideas. Hit me up if you want to talk!


Personally I prefer to manage my ssh config file manually and I like the way 'stormssh' shows the list of hosts and the options.

https://github.com/emre/storm


The goal is to simplify the entire server management and deployment process for personal/small team use case, extending beyond just handling SSH keys.


If this is the goal, then please tell me how the tool achieves it: What exactly is simpler to manage or deploy by using `viking` as opposed to ssh-config and ssh, and in what regard is it simpler?


You should really look into Ansible, and ssh_config...


why not just utilize a Certificate Authority?


CA's have a lot of management and logistical issues and potential for misuse. The simplicity and TOFU design of the SSH key system (which obv can bring along some issues of its own) can bring a lot of benefits, especially for people who don't want to introduce a CA or PKI.

(obligatory disclaimer, I work at Userify and we have a server-side product that automates SSH key management and distribution. For example, the CA design doesn't kick someone out once their access is removed, but Userify's shim actually terminates all of sessions instantly, like screen or tmux, across all of the servers they're logged into and removes (but retains for historical record) their home directory.)


> the CA design doesn't kick someone out once their access is removed, but Userify's shim actually terminates all of sessions instantly

I was a bit confused at first, I thought you were saying ssh certificates couldn't be revoked - but I see you're talking about signing the user out from existing sessions.

That is a fair point. I guess removing/locking a local user (in /etc/passwd, /etc/shadow) would typically leave any console logins alone too - unless other action is taken.

Certificates can of course be revoked:

http://www.ixany.org/articles/key-revocation-lists-on-openss...


Yes, you're exactly right. ( https://github.com/userify/shim/blob/master/shim.py#L209 )

We've thought about porting Userify to work with CA's too but haven't had many requests for that for some reason, even though I'm sure many companies do have CA's set up alongside their other PKI for SSH.


This sounds like Smallstep to me.


r/DIWhy material.


how does this compare to cassh

https://github.com/nbeguier/cassh


cassh is a manager for CA's in SSH. CA's were added to SSH to satisfy people who thought PKI was a good idea; it's not, and SSH pubkeys are far better IMO. Better to use a tool like Userify (or similar like SSH.com) for pubkey management.


At least certificates expire, and can list capabilities right in the certificate?


Not exactly. Yes, the certs expire, so they can't log in again, but existing sessions are not terminated.

With Userify, sessions (like tmux or screen) actually get terminated within seconds when the user's access is removed. That doesn't happen at all with certificates.

If someone's certificate expires, but they're still logged in, they'll stay logged in, because there is no mechanism to kill their session (and they can channel all kinds of things over their logged-in session).

That's an absolute nightmare for compliance.


Fair point - in the case of a revoked cert, it'd probably be feasible to just watch the revocation list and pkill a user's sessions - with an expired cert, I'm not sure if there's anywhere to watch for that state-change.

Probably the best one could do out of the box is set an 8 hour session limit or so?


assh is another project to consider, altough I falled back to just regular SSH config files and imports.


Yeah, you can go a long way with a single line added to the top of your .ssh/config like:

    Include ~/.ssh/config.d/2024/*




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: