One tricky part of mirroring your highly customized Linux system (with a distro like archlinux) to a new machine is the gpg-related stuff. For example, I use pass as my password manager, which uses a gpg key to encrypt/decrypt your passwords. Properly migrating this setup to a new machine turned out to be quite a chore. But here is how I did it.
Setup on the old-machine
Here is what I have on the old-machine:
- A gpg key pair (let’s call it with a fake key id
0xFFFFFFFF
) that was used to initialize and encrypt the password-store; - A remote git repo that backs up all the passwords.
This means the password-store was originally set up as follows:
$ pass init 0xFFFFFFFF --path ~/.local/share
$ pass git init
$ pass git remote add origin https://url/to/your/repo.git
Now you can generate, modify and organize passwords using pass
commands and
store them under ~/.local/share
with a simple structure. I would also sync
with the remote repo whenever there is a change. For this, good news is that
pass
automatically stages and commits changes (with an auto-generated
descriptive message) so all you need to do is a push command.
$ pass git push origin master
Transfer you gpg keys
We use the following gpg command to export the key to a file:
$ gpg -a --export-secret-keys 0xFFFFFFFF > my-sec-gpg.key
The -a
flag turns on ASCII
armoring which is a
printable format of the key to help you back it up. If you open the file, you will see
those “random” ASCII characters. Note that to actually extract the private key
information from this file, the passphrase (originally used to construct the
key pair) is still required. In other words, the file my-sec-gpg.key
is still
encrypted and the level of security depends on the strength of your passphrase.
Choose a very strong passphrase always; write it down somewhere instead of
storing it in your computer.
For our purpose, we don’t need to export the public key since it’s
embedded in my-sec-gpg.key
.
Finally, after copying this key file to an encrypted device (see next section), we
should wipe the file like this (using rm
is not secure):
$ shred -vu my-sec-gpg.key
This archwiki page has very useful information on securely wiping disks.
Next up, we transfer the key file using an encrypted USB stick to the new-machine.
Make an encrypted USB stick
A brief guide on how to encrypt a USB stick is in order. We will use the LUKS (Linux Unified Key Setup) format. A detailed documentation can be found at this archwiki page.
We need:
- A USB stick, obviously. BACK UP YOUR DATA since it’s gonna get erased.
- The kernel module
dm_crypt
. This module does the encryption and to load it (in case it’s not):$ modprobe dm_crypt
- A program called
cryptsetup
. This program provides a userland interface fordm-crypt
. If you are running arch, it should be already installed as a dependency ofsystemd
.
Now plug in the USB stick. I pre-wiped its data with dd
and created a single
partition using the whole space with fdisk
. My machine reads it as
/dev/sdb1
. I’ll use a fake identifier /dev/sdbX
in the following.
To encrypt this partition, do
sudo cryptsetup luksFormat /dev/sdbX
When successful, run
sudo cryptsetup luksFormat /dev/sdbX
You should see a screenful of information - the LUKS header information. These are the unencrypted part of the device that contains metadata of the encryption (cipher, keyslots, hash values, etc.).
The usual mounting command goes like sudo mount /dev/sdXY /mnt
where
/dev/sdXY
is the address of the device and /mnt
is the specified mount
point. To mount the newly encrypted device, however, we need the following
extra steps. First, we need to set a password to the encrypted device:
sudo cryptsetup open /dev/sdbX usb
This will prompt you to enter a password. Make it strong and write it down
somewhere safe to back up. The last parameter, usb
, is the name assigned to
the device, usually descriptive of its function, hence usb
in our case. After
this, a new address, /dev/mapper/usb
, is created for the partition. And this
will be the address we use to mount the device.
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
...
sdd 8:48 1 28.8G 0 disk
└─sdd1 8:49 1 28.8G 0 part
└─usb 254:0 0 28.8G 0 crypt
Now you can mount it:
$ sudo mount /dev/mapper/usb /mnt
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
...
sdd 8:48 1 28.8G 0 disk
└─sdd1 8:49 1 28.8G 0 part
└─usb 254:0 0 28.8G 0 crypt /mnt
Copy the key file. When successful, shred the key:
$ cp my-sec-gpg.key /mnt
$ shred -vu my-sec-gpg.key
Now unmount the device and close the device mapper:
$ sudo umount /mnt
$ sudo cryptsetup close usb
Onto the new-machine
If you have read this far, you know what you are gonna do on the new-machine: (1) plug in the USB stick, (2) open the LUKS container (you will be prompted for the password you set), (3) mount the encrypted device, (4) make a copy of the secret key file to the new-machine.
Then, import the key:
$ gpg --import my-sec-key.gpg
$ # when successful...
$ shred -vu my-sec-gpg.key
After importing the key you created the password-store with in the old-machine, repeat the steps to set it up on the new-machine:
$ pass init 0xFFFFFFFF --path ~/.local/share
$ pass git init
$ pass git remote add origin https://url/to/your/repo.git
If you make a git-pull now, there will be a merge conflict error. This is
because the pass git init
command automatically makes a couple of local
commits upon initiation, which are not part of the remote master branch (which
has the initiation commits from the old-machine). So back up your local branch
and pull and move to the repo master branch:
$ pass git fetch --all
$ pass git branch backup-branch
$ pass git reset --hard origin/master
You can now decrypt and access your passwords using the imported secret key.
Job not done though! To generate and renew passwords, you would need encryption with the public key. We have the public key in the new-machine, but we still need to validate it. This is a cruicial step in public-key cryptography since public keys, due to being public, are prone to tampering. Validation is the step where you affirm their ownership. We do this within gpg’s console-mode:
$ gpg --edit-key 0xFFFFFFFF
gpg (GnuPG) 2.4.5; Copyright (C) 2024 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
...
(personal key info omitted)
...
gpg> trust
Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision?
5
Job done! Now your have your familiar password management environment on the new-machine.
As a final word, here are some nice tools/extensions I use on top of pass
:
- passmenu: access your password-store with the suckless menu tool dmenu;
- pass-update: generate and replace passwords with an easy flow.