41

My Vagrant box is build from a base linux (scientific linux), during provisioning (using shell scripts), Apache is installed.

I recently changed the Vagrant file (v2) to:

config.vm.synced_folder "public", "/var/www/sites.d/example.com",
   :owner => "apache", :group => "apache"

Which works well if the box is already provisioned and just rebooted.

Now, after a vagrant destroy && vagrant up I get the error:

mount -t vboxsf -o uid=`id -u apache`,gid=`id -g apache` 
   /var/www/sites.d/example.com /var/www/sites.d/example.com
id: apache: User does not exist

Which is clear - as during the initial run, apache is not yet installed.

An ugly workaround would of course be to do the basic provisioning with that synced_folder commented out, comment it in and then reboot.

Is there any clean trick to solve that? Especially in a way that vagrant up always runs without interruptions, even if the box is new.

Alex
  • 32,506
  • 16
  • 106
  • 171
  • 1
    How are you installing Apache? One option would be to create the synced folder with user vagrant and then change the owner in your provisioning script/cookbook/etc. after Apache is installed. – pauljm Jul 31 '13 at 18:42
  • Apache is installed via yum. The document root is a shared folder. I am not sure what happens if I change the owner of this folder -> would also change the owners on the shared folder in the host system? But basically vagrant is enforcing a user when mounting, I do not think that works (but did not try) – Alex Aug 01 '13 at 08:57
  • I don't think changing ownership on the guest folder affects permissions on the host folder (see http://stackoverflow.com/questions/13566201/can-i-modify-the-ownership-for-a-shared-folder-in-vagrant). My assumption is that the host folder gets the user running vagrant as its owner. If it did try to sync owners between guest and host, there would be serious problems, since the host machine has a different set of users than the guest. I think changing owners after installing apache will work. – pauljm Aug 01 '13 at 17:40
  • What they do in there - to change the owner - is done via the ":owner" param in the Vagrant file and exactly what I tried in the original question. – Alex Aug 02 '13 at 13:14
  • You'd have to make the change in whatever provisioner is running yum. Only question I'd have is whether the change would be sticky on a reboot. – pauljm Aug 02 '13 at 22:43
  • http://jeremykendall.net/2013/08/09/vagrant-synced-folders-permissions/ – Esteban Mar 06 '14 at 06:16
  • I've read that this problem may be specific to VirtualBox because shared folders in other systems may let you change the owner, though I haven't tried this myself with anything other than VirtualBox. – David Winiecki Apr 11 '15 at 06:31

5 Answers5

27

If you can fix the uid/gid values you can use these in the mount command - they don't have to relate to an existing user/group

I do this with a user that is later created by puppet using fixed (matching)uid / gid values

config.vm.synced_folder "foo", "/var/www/foo",
   id: "foo", :mount_options => ["uid=510,gid=510"]
Sean Burlington
  • 873
  • 10
  • 13
  • I created a `kevin` user with a `uid/gid` of *1000*: `$ cat /etc/passwd | grep kevin` .... `kevin:x:1000:1000::/home/kevin:/bin/bash `, yet adding this entry to my `.kitchen.yml` did not work - `["c:/dev/share", "/path/to/share", "create: true", "type: rsync", "mount_options: [uid=1000]"]`. The `/path/to/share` directory is still owned by `vagrant` – Kevin Meredith Apr 29 '14 at 16:26
  • 2
    For rsync instead of using the mount_options you would use the options `owner:1000`, `group:1000` – littleforest May 08 '14 at 00:20
  • 2
    How do you tell the Apache installation what uid and gid to use for the apache user and group? – Jake Wilson Jun 14 '15 at 16:39
9

This is what I did:

config.vm.synced_folder "./MyApp", "/opt/MyApp", owner: 10002, group: 1007, create: true

config.vm.provision :shell do |shell|
  shell.inline = "groupadd -g 1007 myapp;
                  useradd -c 'MyApp User' -d /opt/MyApp -g myapp -m -u 10002 myapp;"
end

Instead of use the user name and group (as a text) use the uid and gid. Then create the group and user with those ids. This is because the error in fact is:

mount -t vboxsf -o uid=`id -u myapp`,gid=`getent group myapp | cut -d: -f3` opt_MyApp /opt/MyApp
...
id: myapp: No such user

The id command was not able to recognize the user. So, switching to uid and gid the command id won't be used by vagrant.

The only warning I got with this approach is that user home directory (/opt/MyApp) already exist, but I can live with that, or you can change the useradd command to ignore the home directory if already exists.

Before that, the workaround I used is:

vagrant up; vagrant provision; vagrant reload

But, it not nice neither clean.

Johandry
  • 121
  • 1
  • 4
8

Ryan Sechrest has dealt extensively with this problem.

One of the presented solutions is:

Set permissions of directories to 777 and files to 666

config.vm.synced_folder "/Users/ryansechrest/Projects/Sites", 
  "/var/www/domains", mount_options: ["dmode=777", "fmode=666"]
Markus Schulte
  • 4,171
  • 3
  • 47
  • 58
  • config.vm.synced_folder ".", "/var/www/website", id: "webroot", :owner => "4444",:group => "4444" worked better for me, this mounts the vboxsf shared volume with uid/gid and you then create a user with the same during provision – nick fox May 08 '17 at 10:23
2

How I solved this was that I first configure the share to Vagrantfile with no user or group information. Then in the provisioning phase I unmount the share and remount it with proper user and group information. e.g.:

exec {
'umount /share/location':
  command => 'umount /share/location';
} -> exec {
'mount /share/location':
  command => 'mount -t vboxsf -o uid=`id -u apache`,gid=`id -g apache` /share/name /share/location'

You can check the share name from virtualbox or by running the provisioning with debug flag and non working settings (it prints out the actual mount command). I know this is kinda workaround and might not work in every situation, but it worked for me.

kontulai
  • 876
  • 5
  • 19
0

In my case i don't need the synced_folder to be mounted during provision phase. So i disable the synced_folder if the guest is not provisioned.

Check if it's provisioned in the Vagrantfile is a hack but it works.

And for me it's fair enough doing

vagrant up   # To build and provision the first time
vagrant halt # An intermediate step to mount the folder
vagrant up   # To have the folder mounted

So my Vagrantfile is something like:

def provisioned?(vm_name='default', provider='virtualbox')
  File.exist?(".vagrant/machines/#{vm_name}/#{provider}/action_provision")
end

Vagrant.configure(2) do |config|
  [ ... ]
  config.vm.synced_folder "../geoserver_data", "/var/lib/geoserver_data",
    disabled: !provisioned?,
    owner: "tomcat7",
    group: "tomcat7"
  [ ... ] 
Francisco Puga
  • 23,869
  • 5
  • 48
  • 64