Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create /home/vagrant/trellis bindfs mount with proper permissions #705

Merged
merged 3 commits into from
Dec 28, 2016

Conversation

fullyint
Copy link
Contributor

@fullyint fullyint commented Dec 9, 2016

Fixes an issue where Ansible, running in a VM on a Windows host, throws an error while interpreting a .vault_pass file as executable.

ERROR! Problem running vault password script / v a g r a n t / . v a u l t _ p a s s ([Errno 8]
Exec format error). If this is not a script, remove the executable bit from the file.

This PR implements a variation of @aoe's approach, using vagrant-bindfs to mount the /vagrant share with non-executable permissions. This PR makes a separate bindfs mount for /vagrant/bin executable, the only items that need to be executable, as far as I know.

Punishing details below.

NFS performance

I could have wrapped the new vagrant-bindfs mounts (lines 85-87) in a conditional for Windows only, but it seems simpler without. I compared times from 20 trials of a test playbook that runs various Ansible local_action tasks on the VM from a regular VirtualBox share (current Trellis) and from an NFS share (result of this PR). The NFS mean time of 23.245 seconds (SD = 2.018) was slightly faster than the VB share mean of 23.603 seconds (SD = 2.401), but the difference was not statistically significant, p = 0.613. This suggests that changing to NFS doesn't incur any performance hit.

Pipelining

Performance tests while preparing this PR also examined setting pipelining = True in ansible.cfg.

By default, this option is disabled to preserve compatibility with sudoers configurations that have requiretty (the default on many distros), but is highly recommended if you can enable it.

The Trellis Ubuntu Xenial distro does not have requiretty in /etc/sudoers, so 👍 pipelining.

Repeating the performance tests mentioned above, but with pipelining enabled, the NFS mean time of 18.238 seconds (SD = 0.323) was again slightly faster than the VB share mean of 18.618 seconds (SD = 0.188), and the difference statistically significant, p < 0.001 (very small difference nonetheless). This again suggests that changing to NFS doesn't incur any performance hit.

Mount options

I tested various combinations of mount_options: ['rw', 'vers=3', 'tcp', fsc', 'actimeo=1'] that appear in various internet reports of how to speed up NFS performance on Vagrant. According to nfsstat -m (command run on the VM) our nfs shares automatically apply the rw and vers=3. The other options occasionally achieved tiny improvements that were statistically significant, but their effect size was so small they seemed negligible and not worth including.

The fsc would require installing and enabling cachefilesd on the VM, then remounting the NFS shares, which would complicate the vagrant up process, unless we start using a vagrant box with cachefilesd already installed/enabled.

The tcp option is said to be slower, but helpful if NFS is used over "lossy networks." This didn't feel applicable, and testing results didn't show a clear benefit.

The actimeo option to set file attribute cache times would perhaps improve gulp watch response times if gulp were being run on the VM (example), but the Roots recommendation is to run gulp on the host machine.

I also tested these mount options on the NFS share with the site files. The 20 iterations of touch site/web/app/themes/sage/assets then measuring the gulp watch build times and Browsersync page load times with a VM running roots/sage 8.5.0 again occasionally showed statistically significant differences, but again they had negligibly small effect sizes, so I omitted all mount options for site. Perhaps someone will want to revisit these mount options with Sage 9 when it's released.

Permissions on .vault_pass

A nice thing about @aoe's approach of .vault_pass into a new vault/ dir is the p: '0000,u=rD' so g and o have no permissions for .vault_pass. However, for Trellis to sync a vault/ directory by default, the directory would have to always be present, whether added to Trellis core, or created by every user, which seems impractical. Users who want tighter permissions on just .vault_pass can create their own directory and sync it as @aoe suggested. Even then, .vault_pass would still be readable by vagrant user, the user that I imagine will be used by all accessing the VM.

@@ -67,11 +67,13 @@ Vagrant.configure('2') do |config|
fail_with_message "vagrant-hostmanager missing, please install the plugin with this command:\nvagrant plugin install vagrant-hostmanager"
end

bin_path = File.join(ANSIBLE_PATH.sub(__dir__, '/vagrant'), 'bin')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line after this please 👼

@arashohadi
Copy link

Hi @fullyint!

I just tried implementing the changes from this pull request (was on 8453c53).

I am on a Windows host and using Winnfsd. On 8453c53 everything works fine and Winnfsd is able to mount the shared folders that I have.

But when running vagrant up with the changes from this file, it seems the winnfsd.exe starts up but instantly crashes (noted in Task Manager).

Running vagrant up --debug gives me this information when trying to mount (which is not so strange considering the .exe has crashed).

set -e
mkdir -p /vagrant-nfs
mount -o vers=3,udp,vers=3,udp,nolock 192.168.50.1:/C/Projects/Trellis /vagrant-nfs
if command -v /sbin/init && /sbin/init --version | grep upstart; then
  /sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=/vagrant-nfs
fi


Stdout from the command:



Stderr from the command:

mount.nfs: Connection timed out

Just let me know if you need more information from me to help you.

@arashohadi
Copy link

arashohadi commented Dec 12, 2016

Some more information:

  • Tried upgrading vagrant-winnfsd from 1.3.0 to 1.3.1. Didn't help unfortunately, same behavior as above.
  • I also tried upgrading vagrant-bindfs from 0.4.9 to 1.0.1. This gave another interesting error directly after running the vagrant up command.
vagrant-bindfs:
* Destination path '/vagrant/bin' is part of a reserved subtree for Vagrant use

I looked at the repo and found this commit gael-ian/vagrant-bindfs@f07ab7c. Especially this line is interesting

Remember that Vagrant use `/vagrant` on guest side as a shared directory dedicated to provisioning and configuration. Binding a folder to `/vagrant` or one of its subfolders will fail.

@fullyint
Copy link
Contributor Author

@arashohadi Thank you for testing. Your information is very helpful. After updating my vagrant-bindfs plugin, I too get the '/vagrant/bin' is part of a reserved subtree error.

If vagrant-bindfs won't allow a mountpoint in /vagrant, one option could be to put the mountpoint in the vagrant user's home directory, changing the PR to something like this:

- bin_path = File.join(ANSIBLE_PATH.sub(__dir__, '/vagrant'), 'bin')
+ bin_path = File.join(ANSIBLE_PATH.sub(__dir__, '/home/vagrant/trellis'), 'bin')

    if Vagrant::Util::Platform.windows? and !Vagrant.has_plugin? 'vagrant-winnfsd'
      wordpress_sites.each_pair do |name, site|
        config.vm.synced_folder local_site_path(site), remote_site_path(name, site), owner: 'vagrant', group: 'www-data', mount_options: ['dmode=776', 'fmode=775']
      end
-     config.vm.synced_folder '.', '/vagrant', mount_options: ['dmode=755', 'fmode=644']
+     config.vm.synced_folder '.', '/home/vagrant/trellis', mount_options: ['dmode=755', 'fmode=644']
      config.vm.synced_folder File.join(ANSIBLE_PATH, 'bin'), bin_path, mount_options: ['dmode=755', 'fmode=755']
    else
      if !Vagrant.has_plugin? 'vagrant-bindfs'
        fail_with_message "vagrant-bindfs missing, please install the plugin with this command:\nvagrant plugin install vagrant-bindfs"
      else
        wordpress_sites.each_pair do |name, site|
          config.vm.synced_folder local_site_path(site), nfs_path(name), type: 'nfs'
          config.bindfs.bind_folder nfs_path(name), remote_site_path(name, site), u: 'vagrant', g: 'www-data', o: 'nonempty'
        end
-       config.vm.synced_folder '.', '/vagrant-nfs', type: 'nfs'
+       config.vm.synced_folder '.', '/vagrant', type: 'nfs'
-       config.bindfs.bind_folder '/vagrant-nfs', '/vagrant', o: 'nonempty', p: '0644,a+D'
+       config.bindfs.bind_folder '/vagrant', '/home/vagrant/trellis', o: 'nonempty', p: '0644,a+D'
        config.bindfs.bind_folder bin_path, bin_path, perms: '0755'
      end
    end

    provisioner = Vagrant::Util::Platform.windows? ? :ansible_local : :ansible
-   provisioning_path = Vagrant::Util::Platform.windows? ? ANSIBLE_PATH.sub(__dir__, '/vagrant') : ANSIBLE_PATH
+   provisioning_path = Vagrant::Util::Platform.windows? ? ANSIBLE_PATH.sub(__dir__, '/home/vagrant/trellis') : ANSIBLE_PATH

This change would require users to cd ~/trellis after vagrant up (instead of cd /vagrant).

I don't know if that will resolve the winnfsd crashing problem, however.
I will set myself up with a Windows box for testing, but I can't get to it for a few days.
Again, thank you very much for testing!

@fullyint
Copy link
Contributor Author

I added a commit based on the diff above. It works on my Windows 10 with encrypted vault.yml files and .vault_pass.

On the VM, the /vagrant directory will still exist with the same content as before but there will be a new /home/vagrant/trellis directory with the needed permissions on files and directories.

Windows users would switch to running Ansible commands from ~/trellis. Although non-Windows users could continue with /vagrant, we might as well make it the general rule to say, "find your Trellis files on the VM in ~/trellis." I augmented the post_up_message to that effect.

Does anyone see any problem with this change to /home/vagrant/trellis?

Note that if the Vagrantfile is moved to the parent directory on the host machine, /vagrant on the VM will have the site and trellis subdirectories like in the past, but ~/trellis on the VM will still have just the Trellis files,

I think only the Windows docs would need a few minor updates.

@fullyint fullyint changed the title Make vagrant share entirely non-executable except bin Create /home/vagrant/trellis bindfs mount with proper permissions Dec 28, 2016
@fullyint fullyint merged commit 041d8bd into master Dec 28, 2016
@fullyint fullyint deleted the vagrant-share branch December 30, 2016 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants