Encryption
How do I configure chezmoi to encrypt files but only request a passphrase the first time chezmoi init
is run?
The following steps use age for encryption.
This can be achieved with the following process:
- Generate an age private key.
- Encrypt the private key with a passphrase.
- Configure chezmoi to decrypt the private key if needed.
- Configure chezmoi to use the private key.
- Add encrypted files.
First, change to chezmoi's root directory:
$ chezmoi cd ~
Generate an age private key encrypted with a passphrase in the file
key.txt.age
with the command:
$ age-keygen | age --armor --passphrase > key.txt.age
Public key: age193wd0hfuhtjfsunlq3c83s8m93pde442dkcn7lmj3lspeekm9g7stwutrl
Enter passphrase (leave empty to autogenerate a secure one):
Confirm passphrase:
Use a strong passphrase and make a note of the public key
(age193wd0hfuhtjfsunlq3c83s8m93pde442dkcn7lmj3lspeekm9g7stwutrl
in this case).
Add key.txt.age
to .chezmoiignore
so that chezmoi does not try to create it:
$ echo key.txt.age >> .chezmoiignore
Configure chezmoi to decrypt the passphrase-encrypted private key if needed:
$ cat > run_once_before_decrypt-private-key.sh.tmpl <<EOF
#!/bin/sh
if [ ! -f "${HOME}/.config/chezmoi/key.txt" ]; then
mkdir -p "${HOME}/.config/chezmoi"
chezmoi age decrypt --output "${HOME}/.config/chezmoi/key.txt" --passphrase "{{ .chezmoi.sourceDir }}/key.txt.age"
chmod 600 "${HOME}/.config/chezmoi/key.txt"
fi
EOF
Specify the public and private keys for encryption.
age.recipient
must be your public key from above.
Make sure encryption
is added at the beginning, before any other sections.
encryption = "age"
[age]
identity = "~/.config/chezmoi/key.txt"
recipient = "age193wd0hfuhtjfsunlq3c83s8m93pde442dkcn7lmj3lspeekm9g7stwutrl"
Run chezmoi init --apply
to generate the chezmoi's config file and decrypt the
private key:
$ chezmoi init --apply
Enter passphrase:
At this stage everything is configured and git status
should report:
$ git status
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
.chezmoi.toml.tmpl
.chezmoiignore
key.txt.age
run_once_before_decrypt-private-key.sh.tmpl
nothing added to commit but untracked files present (use "git add" to track)
If you're happy with the changes you can commit them. All four files should be committed.
Add files that you want to encrypt using the --encrypt
argument to chezmoi
add
, for example:
$ chezmoi add --encrypt ~/.ssh/id_rsa
When you run chezmoi init
on a new machine you will be prompted to enter your
passphrase once to decrypt key.txt.age
. Your decrypted private key will be
stored in ~/.config/chezmoi/key.txt
.
How to re-encrypt encrypted files
To rotate from an expired GPG key to its replacement, or change from GPG to age encryption, the following steps can be used:
- Make sure you have applied all encrypted files (e.g.
chezmoi apply
decrypts files and places them in their destinations). - Update chezmoi configuration to use the new encryption method (examples: gpg, age, age with one-time passphrase).
- Remove all encrypted files from the state via
chezmoi forget
orchezmoi unmanage
. - Add them back with
chezmoi add --encrypt
.
Example: Migrate from GPG to age
Update chezmoi configuration to use age encryption (with chezmoi edit-config
or manually editing the corresponding template):
- encryption = "gpg"
- [gpg]
- recipient = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ encryption = "age"
+ [age]
+ recipient = "age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ identity = "/home/user/key.txt"
Re-encrypt the files with a script like this:
for encrypted_file in $(chezmoi managed --include encrypted --path-style absolute)
do
# optionally, add --force to avoid prompts
chezmoi forget "$encrypted_file"
# strip the .asc extension
decrypted_file="${encrypted_file%.asc}"
chezmoi add --encrypt "$decrypted_file"
done