SelfHostCorner

Felix Bartels
Felix Bartels

Posted on • Originally published at blog.9wd.eu on

Storing secrects in git repositories with age

In my endeavor to rebuild my IT infrastructure (with a Gitops-ish approach in mind) I needed to take a short break to figure out how to securely store secrets inside of my git repository. There are multiple approaches to this and then there is of course also the possibility to not store any secret at all in git, but rather retrieve them at runtime from e.g. Vault. One popular solution when looking for "encrypt git repository" is git-crypt and while I have used it in the past it relies on gpg for encryption, which means I would need to add my private gpg keys to every system.

A more modern and easier to manage alternative to gpg encryption is age and it even allows encryption based on ssh keys, which to me means one less secret to manage. Age is supported by some tools that serve similar goals to git-crypt, like SOPS and agebox and while SOPS is probably a tool worth knowing it is rather on the complex side, since its meant to support complex workflows. For agebox on the other hand I could not really find a flow that would not lead to many unnecessary git changes, since it removes unencrypted/encrypted files from the working directory when encrypting secrets or decrypting stored files. So in the end I decided to rather use age directly and simplify the process by using the git clean/smudge filter.

The setup of this filter is pretty easy, especially since I will reuse my existing ssh keys. For the encryption of files I have added my public ssh key (called id_rsa4096.pub) to my git repository in the subfolder keys. For decrypting files my private ssh key can remain in my ~ /.ssh dir.

To add the fileencryption to my git configuration the following three commands need to be run. In case you want to add this to your "global" ssh config just remove the --local bits.

git config --local filter.ageencrypt.smudge "age -d -i ~/.ssh/id_rsa4096 -"
git config --local filter.ageencrypt.clean "age -R keys/id_rsa4096.pub -a -"
git config --local filter.ageencrypt.required true
Enter fullscreen mode Exit fullscreen mode

In case I would want to encrypt file for multiple recipients (or simply different ssh keys) the smudge filter can be extended to multiple keys by repeating -R keys/my_other_ssh_key.pub.

Which files should be encrypted is controlled through the .gitattributes file. For each file that should be encrypted simply add:

file-to-encypt.ext filter=ageencrypt
# example for my autorestic configuration:
.autorestic.yml filter=ageencrypt
Enter fullscreen mode Exit fullscreen mode

And from that moment on whenever the file gets modified, the only thing actually ending up in the git commit is the encrypted content of the file. Sadly this also means that it is no longer as easy to see changes over time, as everything git knows about is the encrypted text. If you have added the configuration only after the repository has been checked out a simply git checkout -- filename.ext to decrypt the file.

Top comments (0)