The stuff I do

Managing a secrets directory in your eleventy site

- 1199 words -

← Posts

This blog is a platform for me to experiment with front end technologies and to write about random stuff I do on my free time. I keep everything versioned on Github in a public repository because it's easy and because so far I didn't have anything to keep secret in this repo. This changed recently so I decided to use EncFS to keep secret files encrypted in my Github repo and have them easily accessible on my local copy of the repo. Here is how I did it.

Context and requirements 🔗

Recently I started to collect pieces of wisdom I hear at my workplace. I intend to share this knowledge in some form because I believe it could be useful to a lot of my peers, but so far I'm not sure how I will do that so I want to keep track of them somewhere and this blog's repo is an easy place. So I started writing a couple of them in a draft and I also wrote the name of the coworkers who gave me these pieces of advice. Before I committed the document I realized that I was about to publish some personal thoughts of people I really appreciate and respect without asking for their consent, not cool.

So here is what I wanted to have:

To do that I opted for the following solution:

An important warning

The solution I'm presenting here is dealing with very low importance documents. I don't plan to store any applications secrets like an API key or any sensitive document. So while I'm confident this solution fits my threat model I am in no way encouraging you to use it in production without a proper review of your risks.

The tool 🔗

I'll be using EncFS a tool providing an encrypted file system in the user space: It translates the file system operations one would be doing into the equivalent encrypted operations on the file system.

The usage is quite simple:

encfs /path/to/secrets/ /path/to/cleartext

This command will take the /path/to/secrets/ directory and mount it in /path/to/cleartext/ one can then add any file or directory to the second directory and they will be stored encrypted in the first one.

Creating the directories 🔗

The first step is to create my two directories in my repo:

mkdir -p src/.secrets src/secrets

Then setting up the encrypted file system, one important detail: encfs only takes absolute paths. One can use ${PWD} to avoid having to write the whole path:

encfs ${PWD}/.secret ${PWD}/secret

On the first invocation encfs will show a prompt with several options to configure the encrypted volume, I didn't input anything as the standard mode seemed enough to me.

Then it asks for a password which will be used to encrypt/decrypt the volume. I used a strong password as my encrypted files will be available to anyone on Github I don't want the password to be easily brute forced. (If you do the same thing, please go with 50+ characters and use a password manager instead of your brain or a post-it note)

Once this is done a new file is created in the secret repository holding the configuration for next encfs invocations. From now on and until I unmount the clear directory every new file I create in it will be stored encrypted in the secret directory.

Adding some wrappers 🔗

Now I want this encrypted directory to be as seamless as possible in my local workflow, so I created the two following bash scripts:

# decrypt_secrets.sh

#!/usr/bin/env bash
CLEAR_DIR='src/secrets'
SECRET_DIR='src/.secrets'

# Check if there are some files in the clear directory
if [ -n "$(ls -A $CLEAR_DIR 2>/dev/null)" ]
then
  echo "Secrets repository seems already decrypted."
  exit 0
fi

mkdir -p "$CLEAR_DIR"
encfs "${PWD}/$SECRET_DIR" "${PWD}/$CLEAR_DIR"

This script will run when I build my site locally so it does the following:

# unmount_secrets.sh

#!/usr/bin/env bash
CLEAR_DIR='src/secrets'
fusermount -u "${PWD}/$CLEAR_DIR"

This one is not in my local CI. I use it when I'm done working to unmount the clear directory.

Configuring my build 🔗

With the decrypt_secrets.sh wrapper created I can update my package.json:

    "scripts": {
        "dev": "npm run build:clean && npm run secrets:decrypt && ELEVENTY_ENV=dev npx @11ty/eleventy --input=src --output=docs --serve",
        "build": "ELEVENTY_ENV=prod npx @11ty/eleventy --input=src --output=docs",
        "build:clean": "rm -rf docs",
        "secrets:decrypt": "./tools/secrets/decrypt_secrets",
        "secrets:unmount": "./tools/secrets/unmount_secrets"
    },

So now when I use npm run dev in my local environment my decryption script is run. However when my CI on Github runs npm run build my secrets are not touched.

Setting up the ignores 🔗

There is one last piece of configuration to add: the ignored files. Until now I only had a .gitignore file in my repo with two purposes:

Now I have a new directory src/secrets which I want eleventy to build (locally) but I don't want to track on git (since that would completely defeat the purpose of all this encryption thing I've been doing).

So I had to do the following:

Voila! 🔗

With this setup I am able to add my secret list of pieces of wisdom to my src/secrets/ directory, see it built when I run npm run dev, commit the content of src/.secrets/ once I am done and push the encrypted version of my file on Github 🎉

I hope that reading this article gave you an idea to experiment on your own project. Remember a side project doesn't have to be perfect it only have to be fun 😃

← Posts


Related posts

Posts in the same category: [eleventy]


Comments


Back to top