From 3497688ab98a793f570d72441619f1aeb065e292 Mon Sep 17 00:00:00 2001 From: Andreas Ntaflos Date: Wed, 6 Jul 2016 19:14:45 +0200 Subject: [PATCH] Add tip to "Automatically install or update dotfiles when ssh'ing into a remote machine" --- Tips-and-Tricks.md | 48 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/Tips-and-Tricks.md b/Tips-and-Tricks.md index 570aa4b..d433119 100644 --- a/Tips-and-Tricks.md +++ b/Tips-and-Tricks.md @@ -1,2 +1,46 @@ -**How can I have different groups of tasks for different hosts with different configurations?** -See [here](https://github.com/anishathalye/dotbot/pull/11#issuecomment-73082152) for information on using machine-specific configs. \ No newline at end of file +## How can I have different groups of tasks for different hosts with different configurations? + +See [here](https://github.com/anishathalye/dotbot/pull/11#issuecomment-73082152) for information on using machine-specific configs. + +## Automatically install or update dotfiles when ssh'ing into a remote machine (or: let my dotfiles follow me) + +In your local `~/.ssh/config`: + +``` +Host some.remote.host.example.com + PermitLocalCommand yes + # Unfortunately ssh does not support line breaks in config files + LocalCommand ssh -o PermitLocalCommand=no %n "which git >/dev/null && ([[ -d ~/dotfiles ]] && (echo "Updating dotfiles on %h ..." && cd ~/dotfiles && git pull -q && ./install >/dev/null) || (echo "Installing dotfiles on %h ..." && git clone -q https://github.com/MYNAMESPACE/dotfiles && ./dotfiles/install >/dev/null))" +``` + +Relevant part broken down for readability: + +```bash +LocalCommand ssh -o PermitLocalCommand=no %n "which git >/dev/null && ([[ -d ~/dotfiles ]] && \ + (echo "Updating dotfiles on %h ..." && cd ~/dotfiles && git pull -q && ./install >/dev/null) || \ + (echo "Installing dotfiles on %h ..." && git clone -q https://github.com/MYNAMESPACE/dotfiles && ./dotfiles/install >/dev/null))" +``` + +The main attraction here is the clever use of `LocalCommand`: + +> `LocalCommand` Specifies a command to execute on the *local* machine after successfully connecting to the server. + +We use `LocalCommand` to run a *second* SSH session to connect to the same remote machine and execute the defined command line in that SSH session. So what happens is this: + +1. Initiate SSH connection to remote machine (`ssh user@some.remote.host.example.com`) +2. If the connection is successful (including authentication) then `LocalCommand` is executed +3. The `LocalCommand` initiates a second SSH connection to the same remote machine and executes the command line specified. This commandline updates or installes the dotfiles. + + The second SSH connection sets `-o PermitLocalCommand=no` so that *no local command* is executed for that SSH connection. Without this setting each SSH connection would initiate another SSH connection, which would initiate another SSH connection, ad infinitum. Wo don't want that. +4. When the command line of the second SSH connection is finished then the `LocalCommand` is finished +5. The initial SSH session is finally established and the remote shell becomes available + +The command line is in Bash syntax so adapt it if you use a different shell. + +First we check if `git` is even available (if it is not then nothing more will happen). Then, if there is a `dotfiles` directory in the user's home we `cd` into it, run `git pull` and `install`, thus updating the local dotfiles repository and installing any new or changed files or symlinks. + +If there isn't a `dotfiles` repository in the user's home we do a fresh installation by cloning the dotfiles repo from Github and running the `install` command. + +Obviously this `LocalCommand` is executed every time you connect to the remote machine so it will take a few seconds before your remote shell becomes available. + +This works best if you use public key authentication (or GSSAPI/Kerberos authentication) so SSH doesn't ask for a password when logging in. If you do use password authentication then you will need to enter your password once for each of the two SSH connections. \ No newline at end of file