38

My work tends to involves using SSH to connect to various machines, and then using vim to edit files on those machines. The problem is that I have to constantly copy my .vimrc file around. It's very annoying to open vim and not have any settings. Is it possible to carry my vim settings around with me from machine to machine without manually copying it everywhere?

Apreche
  • 1,405
  • 4
  • 17
  • 20
  • @duffbeer703: yeah, like `set background=dark` or `set background=light`, something that *no* Linux distribution touches and is *completely* unobtrusive for the user. – Hubert Kario Jun 21 '13 at 09:47
  • Without having read the answers yet, I feel like this is theoretically possible as ssh-agent and x-term can be transferred over, but on the other hand those are specifically handled by ssh & I assume there are multiple workarounds to handle crazy edge cases. – trysis Jan 06 '18 at 14:50

16 Answers16

49

Instead of bringing .vimrc to each server you need to work on, why not edit the remote files from your local vim:

In vim/gvim, run:

:e scp://remoteuser@server.tld//path/to/document

or start vim like this:

vim scp://remoteuser@server.tld//path/to/document

This opens the file seamingly in place (it actually copies the file locally), and when you save, it sends the edited file back to the server for you.

It asks for an ssh password, but this can be streamlined via ssh keys.

As others have mentioned the only drawback of this method is that you don't get path/file competion as you would when working directly on the machine.

For more info, check out the following tutorial.

Tom Feiner
  • 16,758
  • 8
  • 29
  • 24
  • +1 for the scp:// hint but I think this solution could be a bit cumbersome if you need to copy the path each time you edit a file. – chmeee Jun 29 '09 at 20:38
  • 1
    Yeah, this is too cumbersome. I have to do lots of poking around the remote machines to find the files I want, and often have to edit with sudo privilege. – Apreche Jun 30 '09 at 15:15
  • +1 this works really well for me. thanks :) – Darragh Enright Apr 17 '12 at 12:36
  • There are cases where you need to log into a main server (login.example.com) then from there login to a local server (top.secret.example.com) – puk Sep 18 '12 at 00:48
  • It works nicely if you mount the remote file structure into your local directory, for example with fusermount. – relet Jul 03 '15 at 13:15
24

I feel your pain. I have all my ~/.*rc files under version control (Subversion), has worked great since I started in 1998, using CVS. One way to do it, is to check out all your rc files like this when you stand in your home directory:

svn co svn+ssh://user@host/path/to/repo/trunk/home/user .
A    .signature
A    .vimrc
A    .bashrc
A    .screenrc
A    .psqlrc
[...]
Checked out revision 7645.

This way the config files will also be synced and updated across the various computers when you run svn update.

sunny256
  • 861
  • 7
  • 8
  • 3
    I guess this is as good as it gets. The trick is that I have to setup a repository on a machine that is accessible from all the other machines. With a secure network topology, that's not always easy. – Apreche Jun 30 '09 at 15:16
  • I started doing this recently, it is amazing. I don't know how I survived without it. – richo Dec 30 '10 at 22:46
  • 5
    Maybe use git or some other distributed version control system. In that case it is enough to have access to a machine where the config files are checked out. – ptman Jan 28 '11 at 10:47
19

You could make a bash script to copy it automatically every time you log in, like this:

#!/usr/bin/env bash

scp ~/.vimrc $1:
ssh $1

You can call it ssh_vim, for instance. It's not an ideal solution but will solve your problem.

You can improve it to check first if there is already there. If you are not always running ssh from the same machine, you could change the script to get the file from scp from another machine.

EDIT1

On a related note, you could also mount the remote machine's filesystem with sshfs. That way you benefit from your environment and tools (not only .vimrc) and you have shell completion (which you don't have using scp://).

EDIT2

I just found out that you can source your .vimrc file using scp://, like this:

:source scp://you@your_computer//yourpath/.vimrc

This works from the vim command line but at the moment I don't know how to automate it. It doesn't seem to work either with the '-u' switch nor in the .vimrc nor with $VIMINIT.

EDIT3

I found it! You can do this to start vim with a .vimrc taken from your host of reference:

vim -c ':source scp://you@your_computer//yourpath/.vimrc'

Option '-c' executes the command right after launching vim.

You can create an alias in your shell of choice to avoid typing. In bash it would be like this:

alias vim="vim -c ':source scp://you@your_computer//yourpath/.vimrc'"
chmeee
  • 7,270
  • 3
  • 29
  • 43
  • 2
    This only works if the computer you are ssh'ing *into* can connect back to the computer you are ssh'ing *from*. This is not always the case, for example if your computer is behind NAT. – trysis Jan 11 '18 at 03:38
17

If you're using public-key authentication, you can use this in your ~/.ssh/config:

Host *
   PermitLocalCommand yes
   LocalCommand bash -c 'scp -P %p %d/.vimrc %u@%n: &>/dev/null &'

I like it better than the script trick suggested above since it doesn't mess the invocation of the ssh command (when specifying extra parameters, etc.)

omribahumi
  • 321
  • 2
  • 4
  • 1
    this is the best. For me I had to change `%u@%n:` to `%r@%n:` because the ssh username differs from my laptop's username – Moshe Apr 23 '19 at 11:43
4

A couple of solutions:

1) Create an NFS share for your home folder and map it in multiple locations.

2) Create a small script to push your .vimrc to the server you are connecting to with an identity/key file. It could look something like this (pseudocode):

connectString = arg0  #username@ipaddress

scp -i ~/.ssh/indentity connectString:~/ ~/.vimrc
ssh -i ~/.ssh/indentity connectString
moshen
  • 1,534
  • 1
  • 9
  • 13
  • 1
    ssh keys will solve th plaintext password problem. – LiraNuna Jun 29 '09 at 19:19
  • what tool would you use to create an NFS share? – Wadih M. Jun 29 '09 at 19:26
  • @LiraNuna - seems you caught me before I had my 'duh' moment and edited my post. @Wadih - NFSD is usually installed on 'nix systems by default. You can also mount NFS shares by default (usually) as well. – moshen Jun 29 '09 at 20:11
  • 1
    NFS sharing is a good idea but will likely run into limited ability to deploy such things, especially in firewalled environments or locations where you dont want to modify production servers (especially with NFS) – ericslaw Jun 30 '09 at 01:18
  • You are correct ericslaw. I made the assumption that these were multiple machines within a single network. – moshen Jun 30 '09 at 15:05
  • Considering NFS-mounted home directories on production systems should be a last resort. For example, are you going to have redundant servers sharing a single point of failure like that? And NFS can be a failure point even if you don't think you're relying on it. A library path that touches it, a script that runs df, operations staff unable to log in to machines after a transient failure of the NFS server. Remember, NFS-mounted home directories mean widespread chaos and panic when the NFS server goes down. – carlito Jul 09 '09 at 21:56
4

The exact same answer as sunny256, but use git instead of SubVersion.

Keep one main branch with the files that is common for all computers, and have one branch for each new computer.

That way you can have almost the same files on most computers, and still not become to confused.

Johan
  • 795
  • 2
  • 7
  • 13
  • +1 A small question: I wonder if it's better to use external definitions for the common files in subversion? This way you can have them in one place and fetch to any branch – Eugene Yarmash Aug 22 '10 at 13:22
3

I know this is an old thread, But one way i do it is using sshfs which mounts the file system over fuse. The local vim does all of the editing, so there is no reason to copy .vimrc around.

THis does have the downside that another terminal will have to be open for any commands that need running on the remote server, But for editing i find this way the best.

It also has the added benifit of being able to use the system clipboard.

exussum
  • 529
  • 3
  • 8
2

I'm using https://github.com/andsens/homeshick to manage my dotfiles, and storing them on github.

Homeshick is written in 100% bash, and helps you manage "castles" which are just git repos that contain a /home/ directory. It has commands to move existing dot files into the repo and replace them with symlinks. And to symlink all the files in the repo in to your home directory on a new machine.

So the general idea is keep your dotfiles in a version control system, and symlink to them from the real path. This way your repo doesn't need to start from your home dir and contain a ton of files you don't ever want to add.

Aaron McMillin
  • 191
  • 1
  • 4
1

I use a makefile that has a list of all the servers that I log on to and when I make a change on my local machine, 'make' is run using the makefile automatically which updates all the servers with any changes or any plugins

Lloyd Moore
  • 111
  • 3
  • Seems more like a fancy way of doing a script. Make is great when building one file from another, but I wouldn't like to use it in a situation where every rule is a "`.PHONY.`" – anthony Aug 14 '19 at 03:02
1

If you are like me and have many development machines (Virtual Machines as well) for various reasons you can combine ssh keys, a smart bash_profile, and an RCS of your choice.

I would second using nfs/samaba/sshfs. One draw back is if you don't have network access all the time then you can't access what you need (flying, no wifi, firewalls, routing issues, etc). The machines that I keep in sync are not all reachable at the same time but I want to share information between them.

The following is how I went about it borrowing many ideas from the Internet.

.bash_profile could have something like this

$HOME/bin/shell_ssh_agent

I got this from a couple of places but can't find a link to it now. The shell_ssh_agent file:

#!/bin/bash

SSH_ENV=$HOME/.ssh/environment

#echo "starting"

function start_agent {
    #echo "reaping agents"
    killall ssh-agent
    #echo "Initialising new SSH agent..."
    /usr/bin/ssh-agent | sed 's/^echo/#echo/' > ${SSH_ENV}
    #echo succeeded
    chmod 600 ${SSH_ENV}
    . ${SSH_ENV}
    /usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
    . ${SSH_ENV}
    #echo "sourced ssh env"
    ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent > /dev/null || { start_agent; }
else
    start_agent;
fi

Now on first login you set up your keys. Log out and in and it just made life easier.

Put all your scripts in an RCS, this makes keeping development machines in sync easier. I use git. Authentication with git is via ssh so ssh keys help here too. Note at this point you could have used something like nfs. I would still be a fan of an RCS for a reason which I mention below.

The use case is

  1. login first time, keys get setup
  2. if RCS isn't set up check out your personal scripts (and update/merge when needed, this could even be part of your .bash_profile if you wanted it)
  3. edit vimrc, special scripts, etc and commit them
  4. when logged into other machines do an update/merge/checkout. This keeps everything in sync; ie no more copying files which sometimes you stomp over and you didn't want to.
  5. as a side benefit you get the power of an RCS. I sometimes make unfavorable changes to scripts or configs and need to roll back and the like.

Something I want to try next is wrap the initial login/setup in a makefile that I copy to the new machine. The makefile can then do the job of setting up your keys, RCS, etc. Obviously there is some overhead here but if you end up setting up a lot of machines this is:

  1. a time saver
  2. easier to keep the configurations and personal scripts of development machines in sync
  3. management of changes to scripts and configs.
rev
  • 113
  • 1
  • 8
1

sshrc solves this problem. You put your .vimrc in ~/.sshrc.d/ and then add export VIMINIT="let \$MYVIMRC='$SSHHOME/.sshrc.d/.vimrc' | source \$MYVIMRC" to `/.sshrc.

1

I wrote a simple tool for this that will allow you to natively transport your .vimrc file whenever you ssh, by using SSHd built-in config options in a non-standard way.

No additional svn,scp,copy/paste, etc required.

It is simple, lightweight, and works by default on all server configurations I have tested so far.

https://github.com/gWOLF3/viSSHous

Glenn W
  • 11
  • 1
0

Using variable VIMINIT:

export VIMINIT='set number'

and forwarding it to remote server:

ssh remoteuser@remoteserver -o SendEnv=LC_VIMINIT -t 'export VIMINIT=$LC_VIMINIT && bash'

is easy using .bash_profiles or .bashrc

export VIMINIT='
set number
'

export LC_VIMINIT=$VIMINIT

sshh (){
ssh -o SendEnv=LC_VIMINIT $1 -t 'export VIMINIT=$LC_VIMINIT && bash'

Now try run vim on remote server using sshh for connection:

sshh remoteuser@remoteserver

If You want to You can take your plugins to remote server as well:

export LC_VIMINIT="
set number
set nocompatible
filetype off
set rtp+=~/.[USER]_vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'VundleVim/Vundle.vim'


set shell=/bin/bash
call vundle#end()
filetype plugin indent on
"

export VIMINIT=$LC_VIMINIT

sshh (){
        if [[ $1 ]]; then
                ssh-copy-id $1 &>/dev/null &&
                rsync -lzr --partial --del ~/.[USER]_vim ${1}: &&
                ssh -o SendEnv=LC_VIMINIT $1 -t 'export VIMINIT=$LC_VIMINIT && bash';
        else
                echo "Provide remote user@host";
        fi
}
Apoc
  • 1
  • 1
0

I have the same situation, but it isn't just ".vimrc". I also have things like

  • bash configuration, prompting and functions,
  • ssh configuration and authorization files,
  • shell scripts I like to have handy.
  • of course my vimrc, but also some vim functions and syntax highlighting files.

My solution (started 30 years ago with "dist" originally!) is to set up a nightly cron to rsync a minimal home configuration to all the machines I work on, so that it updates nightly.

That way all the other machines I work with are kept up to date! I can just add a new machine to the 'accounts' list and do a single machine distribution to start it off.

Does not need to be much, and you can start small and make it more complex as you go. As you can imagine after 30 years my distribution is now rather complex, so I won't put it here. Needless to say it also does things like swap out some configuration for others for some networks, home cleanup (EG: trash, cache files), ensure home permissions are all correct, and so on.

NOTE I only allow password-less ssh login from one 'home' machine to all the rest, never back again! Any cross ssh is password protected.

anthony
  • 330
  • 2
  • 7
-1

You might consider an EXPECT script that allows you to set your path and environment (like EXRC variables) upon pressing a certain keystroke. Shouldn't be too long before someone posts a similar script.

When your server farms number more than a few dozen (think thousands) then having something easily setup your enviroment on a 'virgin' box is a real lifesaver

Often when I login to a box, it creates my homedir for the first time!

ericslaw
  • 1,562
  • 2
  • 13
  • 15
  • Expect is a very fragile way of doing anything. A different OS, Architecture, or even a upgrade, and it can break. Okay for something small, but not expandable as time goes on. – anthony Aug 14 '19 at 02:59
-1

It was realized with the following bash oneliner. Because it is done with Process Substitution, temporary files are not created.

ssh -t user@host '
bash --rcfile <(
    echo -e ' $(cat <(echo "function lvim() { vim -u <(echo "$(cat ~/.vimrc|base64)"|base64 -d) \$@ ; }") \
                    ~/dotfiles/{.bashrc,sh_function,sh_alias,bash_prompt} \
                    <(echo -e alias vim=lvim) | \
                    base64 
               ) ' \
    |base64 -d)'

https://gist.github.com/blacknon/a47083f3bbbd0374998bdf7e3b3396cc