Alex
Alex

Reputation: 35008

Vagrant chicken-and-egg: Shared folder with uid = apache user

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.

Upvotes: 41

Views: 9712

Answers (5)

Francisco Puga
Francisco Puga

Reputation: 25158

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"
  [ ... ] 

Upvotes: 0

Markus
Markus

Reputation: 4689

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"]

Upvotes: 8

Johandry
Johandry

Reputation: 121

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.

Upvotes: 9

Sean Burlington
Sean Burlington

Reputation: 929

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"]

Upvotes: 27

kontulai
kontulai

Reputation: 876

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.

Upvotes: 2

Related Questions