I have been using http://www.puphpet.com successfully to generate vagrant+puppet environments for a number of projects. Then this week I got tasked with writing a prototype for a project using Laravel 4. Since I'm not going to be the one working on the project full time, I figured it would be best to make a VM environment for it that the next person can just clone for the repo. Not having much experience with Laravel 4 I got everything to run in the dev environment just fine. Then I tried to run the first migration and here the problems start with the app/storage
file permissions.
1. app/storage must be writable by the web user
Fine, took out id: vagrant from the synced folder provisioning and set the owner & group to www-data like so:
config.vm.synced_folder "./www", "/var/www", owner: "www-data", group: "www-data"
2. Artisan can only be run from inside the vagrant box to have access to the DB
Fine, vagrant ssh
and run artisan from the www folder.
3. app/storage & app/database have to be writable by the vagrant user in order to use migrations
Grrr, ok, added the following awful piece of code to the vagrant file (note, tried to do this in Puppet first and it didn't take):
config.vm.provision :shell, :inline =>
"usermod -a -G www-data vagrant"
4. app/storage & app/database are not writeable by the group
Argh!!! Ok, let's try this Puppet directive:
file { "/var/www/app/storage":
source => "/var/www/app/storage/",
mode => 0775,
ensure => 'directory',
owner => 'www-data',
group => 'www-data',
recurse => true
}
Nope, doesn't work. Tried to do the same with the Puppet exec {}
directive to no effect. It seems that permissions for the vagrant synced folder are set by the host machine, not the guest.
Finally ended up manually changing the permissions for the folder in the host machine. Is there any simpler way to do this? I would really just like to be able to give the next dev a worry free environment they can clone from the repo, not have them re-setup everything after cloning.
UPDATE
We've figured out that if we change the Apache run user, vagrant doesn't override it on reload. So we've done that manually and it's working better than changing the synced folder's permissions & owner. Now we're just trying to figure out how to make that change manually in Puppet.
After some discussion on Twitter, figured out the following:
There's a constraint from VirtualBox on vagrant that does not allow you to set permissions for the synced folder from inside the guest OS. See this issue on github.
You can use the following code to set the synced folder permissions from the vagrant file:
config.vm.synced_folder ".", "/vagrant", :mount_options => ["dmode=777","fmode=666"]
Or you can change the Apache runtime user to vagrant from the puppet manifest like so:
exec { "change_httpd_user":
command => "sed -i 's/www-data/vagrant/g' /etc/apache2/envvars",
onlyif => "/bin/grep -q 'www-data' '/etc/apache2/envvars'",
notify => Service['apache2'],
require => Package['apache2'],
}
file { "/var/lock/apache2":
ensure => "directory",
owner => "vagrant",
group => "vagrant",
require => Exec['change_httpd_user'],
}
Or any combination of the above