I have a private GitHub repository that I keep all my config files in. Realistically, a private GitHub repo is probably enough for personal security and I could commit secret things configs into this repo unencrypted. But if you don’t want to trust GitHub with your secret data, or if you want to push your config files to a bare repo hosted somewhere less private and secure, or check them out somewhere insecure, then it’d be a good idea to encrypt any secret data before committing it to git.
git-crypt is a git extension that
can transparently encrypt files before they get committed to git, and decrypt
them after they get checked out from git. You tell it which files to encrypt
.gitattributes files, so you can mix encrypted and unencrypted files
in the same git repo. It will even store encrypted diffs when you change
encrypted files, so you can still see line-by-line diffs of encrypted content
git log -p.
To install git-crypt on Ubuntu 15.10+ just do
sudo apt-get install git-crypt,
on Ubuntu < 15.10 you have to install it from source:
sudo apt-get install -y build-essential libssl-dev git clone https://github.com/AGWA/git-crypt.git cd git-crypt make sudo make install
To enable git-crypt on a git repo cd into the repo, init git crypt, and add your GPG key:
git crypt init git crypt add-gpg-user <KEY ID>
(To get your GPG key ID run
gpg --list-keys, you can add as many GPG keys
as you want this way if you want to share the encrypted contents with others.)
After git cloning a repo with git-crypt files in it you need to decrypt it by running:
git crypt unlock
From now on git-crypt will transparently encrypt and decrypt files for you when you commit and check them out as normal.
You now need to add
.gitattributes files to tell git-crypt which files to
encrypt. It’s easy to accidentally commit unencrypted files that you thought
were going to be encrypted, by having them not match
that you thought they would match. For that reason it’s best to use the
.gitattributes file to encrypt top-level files only, and give any
subdirs with encrypted files their own
.gitattributes files. Here’s my
.gitattributes file that encrypts my
files, as well as all
_msmtprc filter=git-crypt diff=git-crypt _mutt.password.* filter=git-crypt diff=git-crypt _offlineimap.passwords.* filter=git-crypt diff=git-crypt _transifexrc filter=git-crypt diff=git-crypt
And here’s my
secret/.gitattributes file that encrypts everything in the
secret subdir using
* filter=git-crypt diff=git-crypt .git* !filter !diff README !filter !diff
Notice the additional rules to prevent files like
.gitignore and the
.gitattributes files, and any
README file, from being encrypted. You can
.gitattributes file into any directory that should be encrypted.
Make sure you commit the .gitattributes files into the git repo.
Before committing secret files, run
git crypt status to check which files
are encrypted and which aren’t. You can get a list of all files that will be
encrypted before commit with:
git crypt status | ack ' encrypted'
Or list the encrypted or unencrypted status of all files in the
git crypt status | ack '_ssh'
You want to check for both files that should be encrypted but aren’t, and also
files that should not be encrypted but are (including
.gitignore files in encrypted subdirectories - these should not be encrypted).
Purging unencrypted sensitive content
If you accidentally commit some unencrypted sensitive content that should have
been encrypted, it’s not enough to just roll back the branch as the commit will
still be in your
.git directory (and will still propagate into the
directories of any clones).
You can use BFG Repo-Cleaner to clean out sensitive content. To install it:
sudo apt-get install openjdk-7-jre wget 'http://repo1.maven.org/maven2/com/madgag/bfg/1.12.5/bfg-1.12.5.jar'
It’s a good idea to backup your repo before using BFG on it, in case you accidentally delete something you didn’t want to:
git clone --mirror /path/to/your/repo /path/to/your/repo.backup
Then, for example to purge the
java -jar bfg-1.12.5.jar --delete-folders '_ssh' .git git reflog expire --expire=now --all git gc --prune=now --aggressive
— Sean Hammond,