[portfolio](https://geonwoo.kim/en/portfolio) › Tools and open source

# sshift · SSH CLI with jump-server connections and password storage

https://geonwoo.kim/en/portfolio/sshift

Period: 2025.07 — 2025.08

At Biztalk I connected to more than 50 servers over SSH for patch work. Going through the jump server every time was tedious, so I put jump-server connections and encrypted password storage into one CLI.

Jump-server SSH to 50+ servers with one command

- [github](https://github.com/takealook97/sshift)

Team: Solo

Role: Design · Go CLI development · Homebrew distribution

Go · OpenSSH · sshpass · Homebrew

- Interactive server picker, direct connection by ID or name, and remote commands
- Add, edit, delete and list servers and jump relations
- Password and key authentication combinations for jump and target servers
- Encrypted password storage with an optional custom key
- JSON export and import of servers and jump relations
- Install through Homebrew, an install script or release binaries

## Jump relations that loop

Problem: Adding jump relations freely could create a loop where A goes through B and B goes back through A.

Solution: Before adding a relation, a depth-first search checks for a path from the target back to the source, and the relation is rejected if one exists. Saved jump relations never contain a loop.

## A changed format for jump relations

Problem: After jump relations moved to a graph format, server lists made by earlier versions might not load.

Solution: If the graph format cannot be read, sshift reads the old relation array and converts it into a graph. Users do not have to rebuild their server lists.

## Different authentication per server

Problem: At Biztalk, patching more than 50 servers meant going through a jump server for every connection. The jump server and the target often used different authentication, such as a password on one and a key on the other.

Solution: sshift builds the command from OpenSSH ProxyJump, ProxyCommand and sshpass depending on the password and key combination.

## Passwords stored in plain text

Problem: Storing passwords as-is in the server list exposed them to anyone who opened the file.

Solution: Passwords are encrypted with AES-CTR and a random IV, and the config files are readable only by their owner. Opening the server list file shows passwords only as ciphertext.


[offon · open-source Slack app for attendance and leave](https://geonwoo.kim/en/portfolio/offon-oss)
