Secret management with compose
Out of the box yeet
provides no secret management by itself, instead we rely on providing environment variables via env
files which we recommend are encrypted using something like git-crypt
. There are many ways to encrypt files but we will explain a workflow using git-crypt
here.
The short version
The short version of the workflow is that a .gitattributes
file tells git-crypt
which files to encrypt in a git repo. These files are transparently encrypted when committed and are therefore safe to put into a public git repo. However, if the aim of a public git repo is to share your configurations with the world then encrypting the entire contents of compose.yaml
defeats that objective. Therefore we opt to encrypt an env
vars file instead and then import those vars into the compose file on the remote host.
For example, take the following minimal compose.yaml
example:
---
services:
librespeed:
image: lscr.io/linuxserver/librespeed
ports:
- 8008:80
environment:
- PASSWORD=${PASSWORD}
Pair it with an env
file in the same directory as the compose.yaml
itself which contains:
PASSWORD=password123
Docker will interpolate the values from the env
file directly into your container at runtime.
The clever part comes when pairing this approach with git-crypt
because now we can encrypt just the env
file simply by naming it env.enc
and creating a .gitattributes
file with a pattern matching rule like so:
.gitattributes !filter !diff
**/*.enc filter=git-crypt diff=git-crypt
**/*.enc.* filter=git-crypt diff=git-crypt
**/*.enc/** filter=git-crypt diff=git-crypt
Copy your env.enc
file across to your remote hosts yeet
service directory with scp like so:
scp env.enc librespeed@yeethost:env
Then redeploy the service with:
yeet run librespeed librespeed/compose.yaml
If you'd like to verify the env vars are successfully picked up, run docker exec -it librespeed sh -c 'echo $PASSWORD'
on the remote yeet
host where the container is running.
git-crypt workflow
Here's a quick end to end guide for using git-crypt
to perform the above.
Installation
You'll need to install git-crypt
- full instructions are provided via the git-crypt GitHub repo. This guide continues once git-crypt
is installed.
GPG keys
git-crypt
relies on GPG keys and OpenPGP for encryption. If you don't have a GPG key already it is simple to create one - note you need the gpg toolchain installed :
gpg --full-gen-key
# answer the prompts as you wish or with following:
# 1) RSA and RSA
# keysize (default is 3072) - 4096
# key validity length - up to you
# GnuPG needs to construct a user ID to identify your key
# complete the prompts appropriately
#
# When happy with your selections, press O (Okay) to create the keypair
Verify the keys known to the system now includes your newly created key with:
gpg --list-keys
# /Users/alice/.gnupg/pubring.kbx
------------------------------
pub rsa4096/0xEB4F8DBF8DBF8DB3 2024-12-27 [SC]
Key fingerprint = F8DB F8DB F8DB F8DB F8DB F8DB F8DB F8DB F8DB 1463
uid [ultimate] alice <[email protected]>
sub rsa4096/0xF8DBF8DB07C2F8DB 2024-12-27 [E]
Configuration basics
Enter into your git repo directory. Make sure you are on the main/master branch, with no outstanding changes, initialize git-crypt, and add the key to repo. For example:
$ cd git-repo # we assume this is already an initialized git repo
$ git-crypt init
$ git-crypt add-gpg-user [email protected]
In the background git-crypt
already committed a change (a new .gpg file in the .git-crypt directory), so now do:
git push
git-crypt encryption instructions
git-crypt
is now set up and ready to be instructed which files to encrypt. The files you choose to encrypt are governed by the contents of the .gitattributes
file.
The following example file will automatically encrypt any file which containers .enc somewhere in its filename. This could be secrets.enc
or secrets.enc.yaml
or even a directory named enc
- they will be committed to GitHub as encrypted files all transparently to you. Note you can lock or unlock the files with git-crypt lock / unlock
if you'd prefer files in your local working tree are encrypted too.
Put this file in the root of your git repo named .gitattributes
. Note there is a separate .git-crypt
directory containing a file named the same which should not be modified.
.gitattributes !filter !diff
**/*.enc filter=git-crypt diff=git-crypt
**/*.enc.* filter=git-crypt diff=git-crypt
**/*.enc/** filter=git-crypt diff=git-crypt
Commit this file to git. You can now create files with names which match the pattern in the .gitattributes
file.
You might at first wonder if git-crypt is doing anything. But once you commit and push your .enc
file it will automatically be encrypted and only viewable by someone with your PGP key (hopefully that's only you!). You'll be asked for a passphrase in addition to the key, so keep that safe too.
Check the status of any files you think should be matched by this rule with git-crypt status
:
$ git-crypt status
encrypted: uptime-kuma/env.enc
not encrypted: ../../.gitattributes
...
not encrypted: ../../hosts.ini
Multiple machines
It's likely you'll want to access this git repo and yeet
from multiple machines. You'll need to copy your GPG key over, or add that GPG identity to the repo. Export the private key (and store it with care!) using:
$ gpg --export-secret-key -a > secretkey.asc
Then copy that file wherever you need it and import it on the other end with
$ gpg --import secretkey.asc
Once the keyfiles have served their purose securely delete them with:
$ shred secretkey.asc
$ rm secretkey.asc
env file configuration
Create a file named env.enc
in the root of the service directory alongside the compose file you used to deploy the service with yeet
.
Copy your env.enc
file across to your remote hosts yeet
service directory with scp like so:
scp env.enc librespeed@yeethost:env
Then redeploy the service with:
yeet run librespeed librespeed/compose.yaml
If you'd like to verify the env vars are successfully picked up, run docker exec -it librespeed sh -c 'echo $PASSWORD'
on the remote yeet
host where the container is running.