Publishing my server’s /etc repository

, .

Motivation

Fairly soon after I started playing with my own private server (I seem to have purchased it in November 2014 and the first Git commit dates to February 2015), I started tracking its configuration in a Git repository. I didn’t add everything in /etc (that is, the .gitignore is just *), but I felt that I wanted to be able to have a history of changes, with the ability to roll them back later if necessary, or at least understand why a setting was in place. I started tracking just the configuration of the email services, but later added other things as well. When I moved servers, I found the repository really useful as well.

However, eventually I found myself posting more and more parts of the repository publicly, usually via GitHub gists: I had managed to put together this nice bit of configuration, and I wanted others to benefit from it as well! Sometimes I posted just the configuration files, but sometimes I even posted the full Git commit (i. e., in git format-patch format) because I wanted to include the commit message as well. At this point, it seemed only logical to publish the repository. The rest of this post describes how I went about doing that.

Sensitive information

The first step was, of course, to deal with any sensitive information that might lurk in the repository. I had never added any really sensitive information to it (things like SSH server keys, X.509 certificate keys, the shadow file…), but I couldn’t just assume that I could publish everything as-is: for a while, I had used the repository with the full expectation that it would not be published, as evidenced in the commit message of commit 6eb85275be:

This repository will stay private anyways, and I don’t think there’s actually any very sensitive information in the torrc. (The keys etc. are in the data directory under /var.)

So, when I had some spare time during 34C3, I cloned the /etc repository to my laptop and went through the entire git log --patch, looking for anything that I might not want to make public.

In the end, I didn’t find any smoking guns, but I did decide that I wanted to redact the postfix/virtual file – I don’t want a full list of all valid email addresses on my domain to be public – and I also needed to rephrase one commit message which mentioned the not-yet-public name of a certain project. (I also took the opportunity to fix innocent typos in two other commit messages.)

To redact the postfix/virtual file while still keeping it under version control, I decided to use git-crypt, which transparently encrypts files in a Git repository using Git’s filter mechanism (see gitattributes(5)).

Rewriting history

As I was going to rewrite history, I also wanted to update all commit hashes I had used in commit messages, so I found all commits whose messages might have mentioned another commit with git log --grep '[0-9a-f]\{7,\}' and added those that weren’t false positives to the text file where I had already collected the commits I needed to redact for other reasons.

Then, in a temporary clone of the repository (/etc needed to remain functional, of course!), I started the big rebase: git rebase --interactive --root. I marked the root commit (the one that added postfix/virtual) for editing, and all the others where the commit message needed rephrasing to reword.

When the first commit was reached, I added the following postfix/.gitattributes file to the commit:

virtual filter=git-crypt diff=git-crypt
virtual-mailbox-users filter=git-crypt diff=git-crypt
I amended the commit and then checked with git cat-file -p @:postfix/virtual | less that the content recorded in Git was really encrypted. Then I continued the rebase.

Unfortunately, one consequence of the encryption is that patches cannot be applied, so the rebase was interrupted on every commit that touched the encrypted files. Fortunately, this wasn’t too hard to resolve: I could just restore the unencrypted file from the original commit (when Git said that it could not apply 641464f... Postfix: add lots of virtual addresses, I ran git cat-file -p 641464f:postfix/virtual >| postfix/virtual), add it to the index, and it would be encrypted through the regular filter process once git rebase --continue amended the commit.

For the other commits, I just found the new commit hash in the git log and replaced the hash in the commit message.

At the end, I added a README.md (hidden in the .github directory), uploaded it to GitHub, and done! And here it is.