1
0
Fork 0
mirror of synced 2024-11-22 08:15:34 -05:00

Add tip to "Automatically install or update dotfiles when ssh'ing into a remote machine"

Andreas Ntaflos 2016-07-06 19:14:45 +02:00
parent 7e99cee0de
commit 3497688ab9

@ -1,2 +1,46 @@
**How can I have different groups of tasks for different hosts with different configurations?** ## 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.
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.