Vagrant: share folder as non root user

March 05, 2015Raphaël Dubigny3 min read

If you ever tried to sync folder between a host machine and a guest one with vagrant over nfs, you may have noticed that everything is ok until you need your shared folder to be owned by a non root user.

Syncing over NFS as non root

I read this good article which describes the solution: share the same UID:GID between your host and your guest.

To provision my base box I use Ansible. The plan is to create a user on the guest with Ansible. This user will have the same uid and guid than the user who runs the vagrant up but with custom username and group name.

Ansible provides a lookup function that allows you to run shell command on your host and bring the result into your guest. That’s how I used it.

myproject/playbook.yml

---
- hosts: stage
sudo: yes
gather_facts: true
roles:
- { role: user }

myproject/hosts/stage

app_user=georges
app_group=georges
home_path=/home/georges

myproject/roles/user/tasks/main.yml

---
- name: Create specific app group
group: gid={{ lookup('pipe', 'id -g') }} name={{ app_group }} state=present

- name: Create specific app user
user: uid={{ lookup('pipe', 'id -u') }} name={{ app_user }} group={{ app_group }} state=present home={{ home_path }}

myproject/Vagrantfile

[...]
config.vm.synced_folder "../host_shared", "/home/georges/guest_shared", type: "nfs", create: true
config.vm.provision :ansible do |ansible|
ansible.inventory_path = "hosts/stage"
ansible.sudo = true
ansible.playbook = "playbook.yml"
end
[...]

Run vagrant up and here you go! Your folders will now be owned by user georges in your guest machine.

Pitfalls

Here are four pitfalls in witch I throw myself in.

  1. 1. The simplest solution would be to use the UID environment variable, but for some reason UID seems not to be available whith lookup. An alternate solution would be using a temp variable export USER_ID=$UID, and then {{ lookup('env', 'USER_ID') }}. It will work, but requires modifying your host environment specifically for this fix, which I did not want to do.
  2. 2. My research leads me to use rsync rather than NFS. Indeed, rsync allows you to choose a custom owner for your shared folder:

    config.vm.synced_folder "../host_shared", "/home/georges/guest_shared", type: "rsync", user: "georges", group: "georges", create: true

    . The user an group options will not work with NFS. Again, this is not a good solution: rsync took more than 4 seconds in most of the cases to sync the files of my project.

  3. 3. Beware that you may have conflicts with host’s UIDs and guest’s ones. For me it went like clockwork since my host was an Ubuntu, meaning that custom user’s UID starts at 1000, and my guest box was a CentOs with no UID upper than 500.
  4. 4. You may encouter the following problem: the first sync may result in guest synced folder owned by root. This is because the user with your UID is not created at first vagrant up. See [this thread](https://github.com/mitchellh/vagrant/issues/936) for more information. I solved it by adding a file action in my ansible playbook to change the ownership of this folder: file: path=/home/georges/guest_shared state=directory mode=755 owner={{ app_user }} group={{ app_group }}. This is not clean but it works.
Raphaël Dubigny

Raphaël Dubigny

Web Developer at Theodo