Today I had a problem with watch tasks like grunt-contrib-watch not noticing changes to files inside my Vagrant VM’s NFS share. To avoid this I wanted to edit the files over SSH using Emacs' tramp-mode, but because of NFS share UID differences it proved difficult. NFS is set by Vagrant to write as the correct user, but because the host machine’s UID doesn’t match the VM’s vagrant user, the files appear read-only from the VM’s perspective. (With a Mac host at least the files are owned by 501:dialout, instead of vagrant:vagrant.) This confuses TRAMP mode and ends up with an RSI inducing amount of “File X is write-protected; try to save anyway? (yes or no)” messages. It took far too long to figure out a way around it but, I got there in the end with help from the good folks on #vagrant and #emacs. Here’s a snippet to brutally disable the warnings:

(add-hook 'find-file-hook
          (lambda ()
            (when (file-remote-p (buffer-file-name))
              (set (make-local-variable 'inhibit-read-only) t)
              (fset (make-local-variable 'file-writable-p) (lambda (filename) t))
              (set (make-local-variable 'buffer-read-only) nil))))

Here’s hoping Vagrant will support something like this :nfs_guest feature soon, it certainly sounds like the developers are on the case. But in the meantime at least I can get on with some coding!

Cheers, Dave.

Edit:

I’ve also written a shell script to help workaround this problem for other developers on the team (who don’t use Emacs). The script watches for changes locally and touches the corresponding file over SSH.

#!/bin/bash
while true
do
    find . -mtime -1s -type f -exec vagrant ssh -c "touch ~/remote/base/path/{}" \;
    sleep 1
done

(It assumes the Vagrantfile is in the project root, and that ~/remote/base/path is the path to your project, in the NFS mount, on the remote machine.)