Looking for a way to sync dotfile content between different machines without introducing security issues
I switch between three computers and have never been able to keep my dotfiles in sync. I cannot put them into source control because they contain sensitive data. So, my question is: how do I share my dotfiles between my different computers in a secure manner? Even a simple solution limited to syncing bash functions from one machine to another would be great.
3 answers
A first quick solution I hacked up was to sync via NAS. Synology NAS served as a synchro point. I synced via git repo. etckeeper
was used to sync machine config, pass
was used to sync passwords.
So, for me it was to use git commands.
Pass: https://www.passwordstore.org/ ArchWiki on it: https://wiki.archlinux.org/title/Pass
Etckeeper: https://ubuntu.com/server/docs/tools-etckeeper ArchWiki on it: https://wiki.archlinux.org/title/Etckeeper
Storage of very important files in git, but encrypted: git secret (singular) and git secrets (plural). Tool repo: https://github.com/sobolevn/git-secret Secrets, plural, tool repo: https://github.com/awslabs/git-secrets
git secret
encrypts a file with credentials and allows you to store only the encrypted one, along with info who can decrypt the file.
git secrets
prevents you from submitting files by accident.
0 comment threads
The following users marked this post as Works for me:
User | Comment | Date |
---|---|---|
paulsweatte |
Thread: Works for me Thanks! Excellent explanation with the perfect balance of what, why, and how. |
Nov 11, 2023 at 03:04 |
It depends on how much sensitive they are. I have three classes.
1) Very sensitive directories
Partitions
For my ~/.ssh/
, ~/.password-store/
, ~/.gnupg/
, and ~/.abook/
, I have a drive with 4 partitions, one for each directory, each of them encrypted with LUKS2.
https://wiki.archlinux.org/title/Dm-crypt/Device_encryption
The relevant fstab(5) entries look like this:
/dev/mapper/alx-usb-g /home/alx/.gnupg ext4 noauto,defaults,user=alx
/dev/mapper/alx-usb-s /home/alx/.ssh ext4 noauto,defaults,user=alx
/dev/mapper/alx-usb-p /home/alx/.password-store ext4 noauto,defaults,user=alx
/dev/mapper/alx-usb-a /home/alx/.abook ext4 noauto,defaults,user=alx
When I log into my computer, I go to TTY1 (to avoid the GUI possibly leaking my key strokes), log in as root, and run these 4 commands:
cryptsetup open /dev/sda1 alx-usb-g && mount /home/alx/.gnupg/
cryptsetup open /dev/sda3 alx-usb-p && mount /home/alx/.password-store/
cryptsetup open /dev/sda2 alx-usb-s && mount /home/alx/.ssh/
cryptsetup open /dev/sda5 alx-usb-a && mount /home/alx/.abook/
And enter the passphrases.
I give 1 GiB to each of these partitions.
Devices
I have a desktop and a laptop. Each of them has a different external drive. That serves me as a backup too, so if one of them burns or something, I have the other one immediately available (or soon, if I'm traveling). For the laptop, the drive is an SD card that is inserted so I don't lose it. For the desktop, it's a USB drive.
Then, I also have a few other copies as backups, which I gave to my closest family members.
SLC
Common flash drives, when using them every day like this, burn really fast. I've seen two flash drives burn in less than 1 year of life time.
Soon after that, I decided to only use industrial-grade SLC drives. They are rated for long enough that should live more than I. They cost in the order of 100$, but it's worth it. If you add up all the cheap drives that will burn in your lifetime, it kind of compensates; and you save some headaches.
I don't know if I should recommend any, but if you want me to, I can add some links in the comments.
git(1)
Each of those partitions is a git repository. In other words, they contain a ./.git/
directory. That allows me to revert mistakes, and to control which directory is ahead of which, and if I added something in both drives, I can rebase one of them on top of the other easily.
All the commits are PGP-signed, to catch anyone actually trying to pervert those drives, if they managed to access them.
Syncing
To sync them, I reboot my computer, disconnect internet, and run in TTY1.
I have a ~/keyring/
directory (with similar fstab(5) rules) where I mount the other drive's partitions. Of course all of these directories have 700
rights.
I have a different remote name for each drive I have, even though they're all routed to the same URI: something like git remote add dad file:///home/alx/keyring/gnupg/
. That way, I know how much each of the backups is lagging, so I can update them if necessary.
When syncing them, I git fetch laptop
and git fetch desktop
(or git fetch dad
, when updating my dad's backup), each one from the other, and then git merge --ff-only
, or git rebase -i
; whatever is appropriate. Of course, I check that all commits are signed with my key before any of that.
I always sync them from the same device, which reduces the number of machines that I need to keep extra secure. Of course, all of my machines should be secure, but in the one I sync my sensitive partitions I want extra security.
2) My master GPG secret key.
If I was paranoid in the above, this one gets even better. :)
In my ~/.gnupg/
directory, the master secret key is not present. The file is a symlink to a file in ~/.gnupg/master/
, which is a 5th partition in my drives. The encryption and the passphrase of that partition is of course stronger than the rest, as is the passphrase of the key itself compared to the pasphrase of the subkeys.
The fstab(5) entry is similar to the others:
/dev/mapper/alx-usb-m /home/alx/.gnupg/master ext4 noauto,defaults,user=alx
And the command for mounting it is what you'd expect too:
cryptsetup open /dev/sda4 alx-usb-m && mount /home/alx/.gnupg/master/
See how it's a symlink (in fact a dangling symlink, most of the time):
alx@debian:~/.gnupg$ ls -la private-keys-v1.d
total 20
drwx------ 2 alx alx 4096 Oct 23 14:38 .
drwx------ 7 alx alx 4096 Nov 10 22:29 ..
-rw------- 1 alx alx 4023 Aug 21 23:23 0C0B7B1234106D55818588B4485C2ACA120C4B5D.key
-rw------- 1 alx alx 4025 Aug 21 23:23 475A8304BB3174BA47FF29314339D4DF86914F1E.key
-rw------- 1 alx alx 4025 Aug 21 23:23 6A552C8983356B9CAEE603E9479C6F8E1BE380E5.key
lrwxrwxrwx 1 alx alx 54 Oct 23 14:38 97AF8E589026666589B1DE3C6E46324BDCF78223.key -> ../master/97AF8E589026666589B1DE3C6E46324BDCF78223.key
I never mount that partition unless I really need it, and I only mount it always in the same computer. And of course, the computer is always air-gapped when I do so, and always in TTY1.
3) Anything else
For other dot-files, I have them in a public git repository. If there's any password in them, I replace it with ...
before making a commit. When I install the files in my computer, I replace the few passwords with the actual value. However, in most (currently, all) cases, I don't need passwords there, and can run pass show ...
within the configuration files.
Previously, the only passwords were in my .gitconfig
and in my .muttrc
. They had the IMAP and SMTP passwords. However, now I use mbsync(1) for syncing IMAP, which allows running a command for getting the password at runtime, so I have this in my .mbsyncrc
: PassCmd "pass show email/gmail/alx.manpages/imap"
. And I've configured git-send-email(1) to use mutt(1) for sending mail, with this in my .gitconfig
: sendmailcmd = mutt -H - && true
. In my .muttrc
, I have set smtp_pass = "`pass show www/foss/kernel/smtp/pass`"
.
Still, if I wanted some more privacy, I could make the repository private. Since it runs in my own server at home, I can set it to only provide SSH access. So far, I didn't see a need.
Git is a very good way to sync dotfiles. There are other sync methods, but git also gives you version control, which is the other crucial part of the dotfile approach.
Dealing with secrets in git is not unique to dotfiles. All sorts of projects encounter this issue. For example, a webapp may need to store the database admin password but it is also risky to commit that to git. There are many ways to handle this - you should look for general help about "how to handle secrets in git".
As an example, some simple and common approaches are:
- Somehow isolate the secret into its own file like
admin-password.txt
, and add that file to.gitignore
. Be careful not to accidentally rename the file and commit your secret. If necessary, create aadmin-password.sample.txt
with a dummy secret to demonstrate correct syntax. - Store the secret outside the git repo, such as in
~/secrets/password.txt
. Ensure that the git repo knows the path at which to look for this.
The idea is that most of your dotfiles are not that sensitive, so you let git handle those because it will do a better job. The few parts that are sensitive are synced through some other means alternative/parallel to git. There are ways of securely syncing secrets that are impractical for a whole git repo, but not for a handful of passwords and such.
As a note, you can run your own instance of a Git server, like Gitlab, and create a private repository. This would keep your entire repo reasonably safe. However, if you want high security it is still bad practice to commit secrets to git regardless of the server you use (and even if you don't ever push to a remote).
For the secrets, you can use some cloud sync like Syncthing or Nextcloud. Simply ensure that the file sync program is set up on each machine to sync to the same location (you can do this with the dotfiles) and then have the dotfiles look for secrets there.
You can also use a public file share such as Dropbox or S3, if you encrypt your secrets and keep the encryption key out of the service. This is generally considered safe, although if you leak the encryption key you potentially also leak the secrets themselves.
For that matter, some people encrypt secrets and commit them to git, in which case it's not a big problem. However, you have to keep in mind that if you ever leak the key later, the secret encrypted with that key is still in the git history. That's okay if you're able to respond to key leakage by rotating all your secrets.
0 comment threads