A Guide to Git-Secret
Tags: api, git
Published: 2020-03-01 01:02:59

---
title: A Guide to Git-Secret
published: true
description: Managing API keys in source control is hard. Here's a possible solution. 
tags: api, git
---

# Git what?
[`Git-secret`](https://git-secret.io/) is a tool to manage API secrets in source control -- but it doesn't have to be just API keys. This git extension allows you to encrypt/decrypt any files as you push/pull from source control. This guide should walk you through:
- Why `git-secret`? What are the advantages and disadvantages?
- How do you set it up? And what does a normal workflow look like? 
- What are the alternatives? 

## Why `git-secret`?
`Git-secret` has a few key advantages that made our team use it:
- It lets you encrypt any kind of file, not just plain-text files!
- It lets you add multiple users to the keyring so that they can simultaneously encrypt/decrypt it. This is very valuable when you have a team of developers who all need access to the secret file.
- It works well on both Linux and Mac, and integrates seamlessly with git. 
- The setup is relatively simple and a lot of recurring tasks can be automated with simple scripts.

That said, there are a few disadvantages that we experienced:
- Since it encrypts the whole file, it often leads to conflicts that cannot be auto-merged because there is no specific part of the file that changed.
- For every new key added, the file has to be decrypted and re-encrypted. While there is no way around that in any solution, this may pollute the commit history.
- It does not have good Windows support and therefore must be used on Windows Subsystem for Linux.

## How to `git-secret`?

### Installation
If you are on Mac OS X, this tutorial assumes that you have [homebrew](https://brew.sh/) installed. It may be necessary to install some of the dependencies below.

If you are using Windows, you will have to use the Windows Subsystem for Linux to follow along. Some of the dependencies below do not have good support for Windows.

The first step is to make sure you have `git` installed and working, obviously. Most developers should have it installed already but you can run `git --version` just to make sure. If you are on a mac, run `brew install git`. If you are on a debian machine, run `sudo apt-get install git`. Similar installation commands would exist for other linux distributions. Visit [this site](https://www.atlassian.com/git/tutorials/install-git) to figure it out.

Next up, you will need `gnupg`. Again, most linux machines come with this pre-installed so you should be able to run `gpg --version` to verify this. Otherwise, install it with the following command: `sudo apt-get install gnupg`. On osx, you can install it with: `brew install gnupg`. Nothing fancy so far.

Finally, you will have to install `git-secret` itself. Detailed instructions can be found [here](https://git-secret.io/installation). On a mac, you can just run `brew install git-secret`. On debian, you can run the following:

```
echo "deb https://dl.bintray.com/sobolevn/deb git-secret main" | sudo tee -a /etc/apt/sources.list
wget -qO - https://api.bintray.com/users/sobolevn/keys/gpg/public.key | sudo apt-key add -
sudo apt-get update && sudo apt-get install git-secret
```

### Key Setup

The first thing you want to do is to generate a new GPG key that you will be using with git-secret. I used RSA & RSA with 4096-bit keys.
```
gpg --gen-key
```

Then, you need to import everyone else's keys. I set up a folder on our repo called `public_keys` and then added a shell script to automatically import/export all keys as following (fill `$EMAIL` with your local email used with your key, via a shell argument perhaps): 

```
gpg --import public_keys/* 
gpg --batch --yes -a -o public_keys/`echo $USER`.gpg --export $EMAIL
echo "Finished importing and exporting keys"
```

That's it! This syncs your local keyring with the keys of everyone on your team.

### Normal workflow

The steps to use the tool are simple from here on forward.  

**Step 0**: Add the secret file to `.gitignore`. Suppose you want to encrypt `config/.env`, then you want to add it to `.gitignore` so that you don't accidentally push it to source control. Also, `git-secret` will not let you add a file to the vault unless it is in your `.gitignore`.

**Step 1**: Add a file to git-secret.
```
git secret add config/.env
```

**Step 2**: Give people access to the file.
```
git secret tell <EMAIL>
```

Since we only used GPG for this repo, I could employ an automatic command to give access to everyone on my team. In general, this may not be a safe operation.

```
for i in `gpg -k | grep -Eo "[^<]+@\S+\.[^>]+"`; do
   git secret tell $i 
done
```

**Step 3**: Encrypt!
```
git secret hide
```

**Step 4**: Decrypt as you wish:
```
git secret reveal
```

Note that every time you grant access to new people, you should `reveal` and then `hide` so that the file is encrypted using new keys.

And that's pretty much it! You can find more detailed docs [here](https://git-secret.io/).

### Deploying

When deploying to production servers or CI, I inject a secret environment variable (e.g. through GitHub Secrets) that uses a base64 encoded string and the python `gnupg` package alongside `dotenv` to load the configuration file.

## What else, if not `git-secret`?
There are several other tools like [`ejson`](https://github.com/Shopify/ejson), [`blackbox`](https://github.com/StackExchange/blackbox), and [`git-crypt`](https://github.com/AGWA/git-crypt). Most of these tools either have a lot of installation steps, or use a very similar GPG based encryption system, or don't have all of the advantages listed in the first section above.

That said, there is a class of tools that use cloud-based keys like [`sops`](https://github.com/mozilla/sops) which might be more appropriate for larger teams. While it has a lot more boilerplate and setup involved, it may be a cleaner solution when the number of keys explode to a lot more than a handful, and the drawbacks of `git-secret` mentioned above can be addressed through this.