Title: git-crypt Subheading: How to encrypt the contents of a git repo with git-crypt. Tags: git Alias: /post/git-crypt/ 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](https://www.agwa.name/projects/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 using `.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 with `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: ```console $ 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: ```console $ git crypt init $ git crypt add-gpg-user ``` (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: ```console $ 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 `.gitattributes` globs that you thought they would match. For that reason it's best to use the top-level `.gitattributes` file to encrypt top-level files only, and give any subdirs with encrypted files their own `.gitattributes` files. Here's my top-level `.gitattributes` file that encrypts my `_msmtprc` and `_transifexrc` files, as well as all `_mutt.password.*` and `_offlineimap.passwords.*` files: _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 copy this `.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: ```console $ git crypt status | ack ' encrypted' ``` Or list the encrypted or unencrypted status of all files in the `_ssh` directory with: ```console $ 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 `.gitattributes` and `.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 `.git` directories of any clones). You can use [BFG Repo-Cleaner](https://rtyley.github.io/bfg-repo-cleaner/) to clean out sensitive content. To install it: ```console $ 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: ```console $ git clone --mirror /path/to/your/repo /path/to/your/repo.backup ``` Then, for example to purge the `_ssh` directory: ```console $ java -jar bfg-1.12.5.jar --delete-folders '_ssh' .git $ git reflog expire --expire=now --all $ git gc --prune=now --aggressive ```