Show HN: Sendenv, a CLI tool to share environment variables (github.com)

83 points by aster0id ↗ HN
My weekend project sendenv is a CLI tool that lets you share environment variables securely with someone else. It is built on top of magic-wormhole which allows for safe, account-free data transfer. When you send variables using sendenv, it creates a one-time code. You give this code to the person who needs the variables. They use the code in their shell to load the variables. This is handy for quickly setting up new team members or copying local environment variables to another system.

Its currently in alpha obviously, but the core functionality works (I have tested sending vaults from a Macbook Air M1 to a ubuntu ec2 instance). I have a lot of follow up ideas to make this better, but wanted the community's feedback before I invest more time on this.

Thanks for reading!

22 comments

[ 3.5 ms ] story [ 60.0 ms ] thread
Before sendenv, but with magicwormhole (which it's built on top of):

    machine1 $ export var1=hello
    machine1 $ export -p var1 | wormhole send --text -
      On the other computer, please run wormhole receive 1-word-word

    machine2 $ eval "$(wormhole receive 1-word-word)"
    machine2 $ echo $var1
    hello

After sendenv:

    machine1 $ export var1=hello
    machine1 $ sendenv create-vault v
    machine1 $ sendenv add-var v
    machine1 $ sendenv send-vault v

    machine2 $ sendenv receive-vault
      Please logout and login again for the changes to take effect
    machine2 $ echo $var1 # doesn't work, needed to re-login
sendenv also writes to "~/.bash_profile", "~/.zshrc", which is fraught (i.e. on my system they're read-only files).

It also, just like the eval in the first example, has the downside of requiring you to completely trust the sender since they can send arbitrary code to execute that'll get written to your shell's rc file.

Basically, if you need to share ad-hoc env vars in a single terminal session, the wormhole snippet I posted above is fine.

If you want them to persist, probably use direnv to share them, ideally tracked in version control.

If you want them to persist system-wide, use ansible or some other configuration management.

The middle-ground, of wanting them to persist so much you write them to the shell rc, but not wanting them to be version controlled or configuration managed, seems like the worst of both worlds.

Fair criticism. I seek feedback like this, which is why I posted it here.

You could call `sendenv` syntactic sugar on top of the first example, allowing you to do things neatly in bulk instead of having to write ad hoc scripts. Additionally once you store a vault, you can send it any number of times Granted, its likely not a very frequent need, but still handy I guess.

Tracking secrets in version control is exactly what I wanted to sidestep by creating this. Sharing environment variables is an ad hoc manual process at my current company (and was the same way in previous workplaces as well).

Ansible or other centralized secret stores felt too heavy for something that should be simple.

The point of trusting the sender is applicable to anything you would send over magic wormhole, but I accept that this solution is more vulnerable given that it writes to rc files directly. I will be adding more validation at the receiver end before writing to rc files, as a response to this criticism.

> Sharing environment variables is an ad hoc manual process at my current company (and was the same way in previous workplaces as well).

It really shouldn’t be that way. If the data is meant to be selectively accessed, it should have access controls in place with Authentication, Authorization and Auditing. If its any employees discretion to share the data with another adhoc, I certainly hope the secret is not of great value.

Oh we share secrets using a password manager. But it's a long laundry list of secrets that you have to manually load into your system somehow. There's also an env file there somewhere but it's not up to date.

Eliminating the cognitive load of looking up the relevant secret, writing it manually into the RC file, testing whether it works (and starting over if it doesn't, because it's possible the secret is outdated) was one of the goals of creating this.

Sounds to me like a configuration-driven interface with the password manager is the appropriate solution here, then. I used this pattern to write config files out of secrets stored in SSM, which previously was ad-hoc secret sharing. FWIW I would never use Sendenv.
That is one solution yes, if you already have a password manager which gives APIs to work with it's secrets. Or a separate product like Doppler which is specialized for this use case. My idea was to avoid a central store, and honestly I don't intend to compete with these massive companies with my weekend long project. If a few people find it useful, I'm happy with it. Thanks for your feedback!
Why is logout and login required? Why not just source the profile after writing the changes? I must be missing something about how this works.
> sendenv also writes to "~/.bash_profile", "~/.zshrc", which is fraught (i.e. on my system they're read-only files).

> If you want them to persist system-wide, use ansible or some other configuration management.

I kind of understand not wanting to give other people the ability to mess with your shell, but why are these read-only?

Also, curious about the choice of Ansible...symlinks are a thing and the setup is really only as complicated as you make it. Building a mansion when you might only "need" a house with 1 or 2 bedrooms seems like an odd decision.

They're read-only because I use a dotfile manager for them, and that manager owns the contents of those files, so it doesn't want external changes to mess with them. I'm specifically using home-manager [0], but various other profile managers will also make them read-only... Especially since any changes to them will just be over-written next time you apply your dotfiles, right?

I think 'direnv' is really the way to go here for most cases you want to share environment variables between developer machines, but if you're managing user's shell rc files, then you might as well use proper configuration management, because ad-hoc appending strings to those rc files is the stuff of nightmares.

[0]: https://github.com/nix-community/home-manager

Ah, now I see...

The thing that really made dotfiles click for me was the switch to zsh in macOS + Armin Briegel's (of Scripting OS X) book, which laid out exactly how the transition was going to work. I'd done some basic things in `.bash_profile`, but this took it to another level entirely.

Tl;dr `zsh-newuser-install` is pretty idiot-proof, but it helps to know what the options are if you've never seen them before.

> sendenv also writes to "~/.bash_profile", "~/.zshrc"

Is there at least a prompt? I dislike and distrust tools which write to those files on their own. My shell’s startup files are organised how I want, with different sections depending on what’s relevant. It’s the entry point to every terminal session so I know what every line does. I don’t appreciate when a tool decides it’s OK to latch itself to every terminal session in a disorganised manner without permission, especially since those additions are seldom removed when the tool is uninstalled.

Fair point. I'll add a prompt. I was also planning to give users the ability to choose how the variables are set in general.

Cleaning up after uninstall is also a good idea.

Thanks for the feedback!

Not sure I’d use this. Might be fun to develop, but what’s wrong with a text file you copy to your bashrc or whatever?
That works too. There are just a lot of tiny cognitive humps to get over when you try to manage env variables manually.

1. Find the text file in the password manager 2. Most people will not be fully conscious of which shell they're using and where's the RC file for that shell, and what variables already exist in your system that you want to keep Vs which ones you want to replace.

I built this because I'd use this just to save me some mental energy. It's obviously possible to solve this in other ways as well.

Related tool: a friend and I created `diffenv` for developers to easily compare (diff) development environments including environment variables:

https://github.com/error-central/diffenv

Helps for debugging those times when you say, “well it runs fine on my machine, what’s different about your machine??”

That's cool!

Sendenv also performs a diff-ish to determine if the receiver is potentially overwriting existing values.

Ansible vault, anyone?
If yours is a massive company with resources to run separate centralised infrastructure for secrets management, sure. There are other nicer tools too - Doppler comes to mind.

I just wanted to build the simplest possible thing that would achieve the functionality.

I like how what you created lets you load variables into your system easily. Have you checked out Doppler Share? https://share.doppler.com/ It might be useful if you didn't want to use the command line for similar functionality.
Requires you to trust Doppler's servers to be secure enough. But I guess that is a given with Doppler overall. Definitely useful though!