How to load fish configuration from a remote repository?

1.2k Views Asked by At

I have a zillion machines in different places (home network, cloud, ...) and I use fish on each of them. The problem is that I have to synchronize their configuration every time I change something in there.

Is there a way to load the configuration from a remote repository? (= a place where it would be stored, not necessarily git but ideally I would manage them in GitHub). In such a case I would just have a one liner everywhere.

  • I do not care too much about startup time, loading the config each time would be acceptable
  • I cannot push the configuration to the machines (via Ansible for instance) - not of them are reachable from everywhere directly - but all of them can reach Internet
2

There are 2 best solutions below

1
On BEST ANSWER

There are two parts to your question. Part one is not specific to fish. For systems I use on a regular basis I use Dropbox. I put my ~/.config/fish directory in a Dropbox directory and symlink to it. For machines I use infrequently, such as VMs I use for investigating problems unique to a distro, I use rsync to copy from my main desktop machine. For example,

rsync --verbose --archive --delete -L --exclude 'fishd.*' krader@macpro:.config .

Note the exclusion of the fishd.* pattern. That's part two of your question and is unique to fish. Files in your ~/.config/fish directory named with that pattern are the universal variable storage and are currently unique for each machine. We want to change that -- see https://github.com/fish-shell/fish-shell/issues/1912. The problem is that file contains the color theme variables. So to copy your color theme requires exporting those vars on one machine:

set -U | grep fish_color_

Then doing set -U on the new machine for each line of output from the preceding command. Obviously if you have other universal variables you want synced you should just do set -U and import all of them.

0
On

Disclaimer: I wouldn't choose this solution myself. Using a cloud storage client as Kurtis Rader suggested or a periodic cron job to pull changes from a git repository (+ symlinks) seems a lot easier and fail-proof.


On those systems where you can't or don't want to sync with your cloud storage, you can download the configuration file specifically, using curl for example. Some precious I/O time can be saved by utilizing HTTP cache control mechanisms. With or without cache control, you will still need to create a connection to a remote server each time (or each X times or each Y time passed) and that wastes quite some time already.

Following is a suggestion for such a fish script, to get you started:

#!/usr/bin/fish

set -l TMP_CONFIG /tmp/shared_config.fish

curl -s -o $TMP_CONFIG -D $TMP_CONFIG.headers \
 -H "If-None-Match: \"$SHARED_CONFIG_ETAG\"" \
 https://raw.githubusercontent.com/woj/dotfiles/master/fish/config.fish

if test -s $TMP_CONFIG
  mv $TMP_CONFIG ~/.config/fish/conf.d/shared_config.fish
  set -U SHARED_CONFIG_ETAG (sed -En 's/ETag: "(\w+)"/\1/p' $TMP_CONFIG.headers)
end

Notes:

  • Warning: Not tested nearly enough
  • Assumes fish v2.3 or higher.
  • sed behavior varies from platform to platform.
  • Replace woj/dotfiles/master/fish/config.fish with the repository, branch and path that apply to your case.

You can run this from a cron job, but if you insist to update the configuration file on every init, change the script to place the configuration in a path that's not already automatically loaded by fish, e.g.:
mv $TMP_CONFIG ~/.config/fish/shared_config.fish
and in your config.fish run this whole script file, followed by a
source ~/.config/fish/shared_config.fish