wawa
wawa

Reputation: 5084

Run PuPHPet through Vagrant managed server on a remote server

So I built a VM using http://puphpet.com/ which works fine as local VM. My goal now is to use the same stuff on my prod server, so I won't have to write all the puppet stuff by my self and more important to have one puppet setup for dev and prod so they are realy equally set up. To manage the remote server with Vagrant i use this plugin: https://github.com/tknerr/vagrant-managed-servers (I'm not posting in their issues, cause the "problem" is somewhere in my Vagrantfile.

This is/was my Vagrant File for testing. It works perfect, but without all the Puppet stuff.
Vagrant File:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# current dir
dir = File.dirname(File.expand_path(__FILE__))

Vagrant.configure("2") do |config|
    #
    # local machine
    #
    # vagrant up dev
    # vagrant ssh dev
    #
    config.vm.define "dev", primary: true do |dev_config|
        dev_config.vm.box = "puphpet/ubuntu1404-x64"
        dev_config.vm.network :private_network, ip: "192.168.300.51"
    end
    #
    # remote machine
    #
    # vagrant up prod --provider=managed
    # vagrant ssh prod
    #
    config.vm.define "prod", autostart:false do |prod_config|
        prod_config.vm.box = "tknerr/managed-server-dummy"
        prod_config.vm.provider :managed do |managed_config, override|
            managed_config.server = "xxx.xxx.xxx.xxx"
            override.ssh.username = "user.name"
            override.ssh.private_key_path = "#{dir}/puphpet/files/dot/ssh/id_rsa"
            override.ssh.port = "2222"
        end
    end
end

Then I tried to add the Puppet stuff to my Vagrant file and I ended up with this monster, that is still able to connect to my prod server, but unfortunately the "vagrant provision" command doesn't run successfully.

Monster Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

# load yaml for configs
require 'yaml'
# current dir
dir = File.dirname(File.expand_path(__FILE__))
# load config
configValues = YAML.load_file("#{dir}/puphpet/config.yaml")
data         = configValues['vagrantfile-local']

Vagrant.require_version '>= 1.6.0'

Vagrant.configure("2") do |master_config|
    #
    # local machine
    #
    # vagrant up dev
    # vagrant ssh dev
    #
    master_config.vm.define "dev", primary: true do |config|
      config.vm.box     = "#{data['vm']['box']}"
      config.vm.box_url = "#{data['vm']['box_url']}"

      if data['vm']['hostname'].to_s.strip.length != 0
        config.vm.hostname = "#{data['vm']['hostname']}"
      end

      if data['vm']['network']['private_network'].to_s != ''
        config.vm.network 'private_network', ip: "#{data['vm']['network']['private_network']}"
      end

      data['vm']['network']['forwarded_port'].each do |i, port|
        if port['guest'] != '' && port['host'] != ''
          config.vm.network :forwarded_port, guest: port['guest'].to_i, host: port['host'].to_i
        end
      end

      if !data['vm']['post_up_message'].nil?
        config.vm.post_up_message = "#{data['vm']['post_up_message']}"
      end

      if Vagrant.has_plugin?('vagrant-hostmanager')
        hosts = Array.new()

        if !configValues['apache']['install'].nil? &&
            configValues['apache']['install'].to_i == 1 &&
            configValues['apache']['vhosts'].is_a?(Hash)
          configValues['apache']['vhosts'].each do |i, vhost|
            hosts.push(vhost['servername'])

            if vhost['serveraliases'].is_a?(Array)
              vhost['serveraliases'].each do |vhost_alias|
                hosts.push(vhost_alias)
              end
            end
          end
        elsif !configValues['nginx']['install'].nil? &&
               configValues['nginx']['install'].to_i == 1 &&
               configValues['nginx']['vhosts'].is_a?(Hash)
          configValues['nginx']['vhosts'].each do |i, vhost|
            hosts.push(vhost['server_name'])

            if vhost['server_aliases'].is_a?(Array)
              vhost['server_aliases'].each do |x, vhost_alias|
                hosts.push(vhost_alias)
              end
            end
          end
        end

        if hosts.any?
          contents = File.open("#{dir}/puphpet/shell/ascii-art/hostmanager-notice.txt", 'r'){ |file| file.read }
          puts "\n\033[32m#{contents}\033[0m\n"

          if config.vm.hostname.to_s.strip.length == 0
            config.vm.hostname = 'puphpet-dev-machine'
          end

          config.hostmanager.enabled           = true
          config.hostmanager.manage_host       = true
          config.hostmanager.ignore_private_ip = false
          config.hostmanager.include_offline   = false
          config.hostmanager.aliases           = hosts
        end
      end

      if Vagrant.has_plugin?('vagrant-cachier')
        config.cache.scope = :box
      end

      config.vm.usable_port_range = (data['vm']['usable_port_range']['start'].to_i..data['vm']['usable_port_range']['stop'].to_i)

      if data['vm']['chosen_provider'].empty? || data['vm']['chosen_provider'] == 'virtualbox'
        ENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox'

        config.vm.provider :virtualbox do |virtualbox|
          data['vm']['provider']['virtualbox']['modifyvm'].each do |key, value|
            if key == 'memory'
              next
            end
            if key == 'cpus'
              next
            end

            if key == 'natdnshostresolver1'
              value = value ? 'on' : 'off'
            end

            virtualbox.customize ['modifyvm', :id, "--#{key}", "#{value}"]
          end

          virtualbox.customize ['modifyvm', :id, '--memory', "#{data['vm']['memory']}"]
          virtualbox.customize ['modifyvm', :id, '--cpus', "#{data['vm']['cpus']}"]

          if data['vm']['hostname'].to_s.strip.length != 0
            virtualbox.customize ['modifyvm', :id, '--name', config.vm.hostname]
          end
        end
      end

      if data['vm']['chosen_provider'] == 'vmware_fusion' || data['vm']['chosen_provider'] == 'vmware_workstation'
        ENV['VAGRANT_DEFAULT_PROVIDER'] = (data['vm']['chosen_provider'] == 'vmware_fusion') ? 'vmware_fusion' : 'vmware_workstation'

        config.vm.provider 'vmware_fusion' do |v|
          data['vm']['provider']['vmware'].each do |key, value|
            if key == 'memsize'
              next
            end
            if key == 'cpus'
              next
            end

            v.vmx["#{key}"] = "#{value}"
          end

          v.vmx['memsize']  = "#{data['vm']['memory']}"
          v.vmx['numvcpus'] = "#{data['vm']['cpus']}"

          if data['vm']['hostname'].to_s.strip.length != 0
            v.vmx['displayName'] = config.vm.hostname
          end
        end
      end

      if data['vm']['chosen_provider'] == 'parallels'
        ENV['VAGRANT_DEFAULT_PROVIDER'] = 'parallels'

        config.vm.provider 'parallels' do |v|
          data['vm']['provider']['parallels'].each do |key, value|
            if key == 'memsize'
              next
            end
            if key == 'cpus'
              next
            end

            v.customize ['set', :id, "--#{key}", "#{value}"]
          end

          v.memory = "#{data['vm']['memory']}"
          v.cpus   = "#{data['vm']['cpus']}"

          if data['vm']['hostname'].to_s.strip.length != 0
            v.name = config.vm.hostname
          end
        end
      end

      ssh_username = !data['ssh']['username'].nil? ? data['ssh']['username'] : 'vagrant'

      config.vm.provision 'shell' do |s|
        s.path = 'puphpet/shell/initial-setup.sh'
        s.args = '/vagrant/puphpet'
      end
      config.vm.provision 'shell' do |kg|
        kg.path = 'puphpet/shell/ssh-keygen.sh'
        kg.args = "#{ssh_username}"
      end
      config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh'
      config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh'

      config.vm.provision :puppet do |puppet|
        puppet.facter = {
          'ssh_username'     => "#{ssh_username}",
          'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'],
          'vm_target_key'    => 'vagrantfile-local',
        }
        puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}"
        puppet.manifest_file  = "#{data['vm']['provision']['puppet']['manifest_file']}"
        puppet.module_path    = "#{data['vm']['provision']['puppet']['module_path']}"

        if !data['vm']['provision']['puppet']['options'].empty?
          puppet.options = data['vm']['provision']['puppet']['options']
        end
      end

      config.vm.provision :shell do |s|
        s.path = 'puphpet/shell/execute-files.sh'
        s.args = ['exec-once', 'exec-always']
      end
      config.vm.provision :shell, run: 'always' do |s|
        s.path = 'puphpet/shell/execute-files.sh'
        s.args = ['startup-once', 'startup-always']
      end
      config.vm.provision :shell, :path => 'puphpet/shell/important-notices.sh'

      if File.file?("#{dir}/puphpet/files/dot/ssh/id_rsa")
        config.ssh.private_key_path = [
          "#{dir}/puphpet/files/dot/ssh/id_rsa",
          "#{dir}/puphpet/files/dot/ssh/insecure_private_key"
        ]
      end

      if !data['ssh']['host'].nil?
        config.ssh.host = "#{data['ssh']['host']}"
      end
      if !data['ssh']['port'].nil?
        config.ssh.port = "#{data['ssh']['port']}"
      end
      if !data['ssh']['username'].nil?
        config.ssh.username = "#{data['ssh']['username']}"
      end
      if !data['ssh']['guest_port'].nil?
        config.ssh.guest_port = data['ssh']['guest_port']
      end
      if !data['ssh']['shell'].nil?
        config.ssh.shell = "#{data['ssh']['shell']}"
      end
      if !data['ssh']['keep_alive'].nil?
        config.ssh.keep_alive = data['ssh']['keep_alive']
      end
      if !data['ssh']['forward_agent'].nil?
        config.ssh.forward_agent = data['ssh']['forward_agent']
      end
      if !data['ssh']['forward_x11'].nil?
        config.ssh.forward_x11 = data['ssh']['forward_x11']
      end
      if !data['vagrant']['host'].nil?
        config.vagrant.host = data['vagrant']['host'].gsub(':', '').intern
      end
    end
    #
    # remote machine
    #
    # vagrant up prod --provider=managed
    # vagrant ssh prod
    #
    master_config.vm.define "prod", autostart:false do |prod_config|
        prod_config.vm.box = "tknerr/managed-server-dummy"
        prod_config.vm.provider :managed do |managed_config, override|
            managed_config.server = "xxx.xxx.xxx.xxx"
            override.ssh.username = "user.name"
            override.ssh.private_key_path = "#{dir}/puphpet/files/dot/ssh/id_rsa"
            override.ssh.port = "2222"
        end

        if Vagrant.has_plugin?('vagrant-hostmanager')
            hosts = Array.new()

            if !configValues['apache']['install'].nil? &&
                configValues['apache']['install'].to_i == 1 &&
                configValues['apache']['vhosts'].is_a?(Hash)
              configValues['apache']['vhosts'].each do |i, vhost|
                hosts.push(vhost['servername'])

                if vhost['serveraliases'].is_a?(Array)
                  vhost['serveraliases'].each do |vhost_alias|
                    hosts.push(vhost_alias)
                  end
                end
              end
            elsif !configValues['nginx']['install'].nil? &&
                   configValues['nginx']['install'].to_i == 1 &&
                   configValues['nginx']['vhosts'].is_a?(Hash)
              configValues['nginx']['vhosts'].each do |i, vhost|
                hosts.push(vhost['server_name'])

                if vhost['server_aliases'].is_a?(Array)
                  vhost['server_aliases'].each do |x, vhost_alias|
                    hosts.push(vhost_alias)
                  end
                end
              end
            end

            if hosts.any?
              contents = File.open("#{dir}/puphpet/shell/ascii-art/hostmanager-notice.txt", 'r'){ |file| file.read }
              puts "\n\033[32m#{contents}\033[0m\n"

              prod_config.hostmanager.enabled           = true
              prod_config.hostmanager.manage_host       = true
              prod_config.hostmanager.ignore_private_ip = false
              prod_config.hostmanager.include_offline   = false
              prod_config.hostmanager.aliases           = hosts
            end
          end

          if Vagrant.has_plugin?('vagrant-cachier')
            prod_config.cache.scope = :box
          end

          prod_config.vm.provision 'shell' do |s|
            s.path = 'puphpet/shell/initial-setup.sh'
            s.args = '/vagrant/puphpet'
          end
          prod_config.vm.provision 'shell' do |kg|
            kg.path = 'puphpet/shell/ssh-keygen.sh'
            kg.args = "user.name"
          end
          prod_config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh'
          prod_config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh'

          prod_config.vm.provision :puppet do |puppet|
            puppet.facter = {
              'ssh_username'     => "user.name",
              'provisioner_type' => "managed",
            }
            puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}"
            puppet.manifest_file  = "#{data['vm']['provision']['puppet']['manifest_file']}"
            puppet.module_path    = "#{data['vm']['provision']['puppet']['module_path']}"

            if !data['vm']['provision']['puppet']['options'].empty?
              puppet.options = data['vm']['provision']['puppet']['options']
            end
          end

          prod_config.vm.provision :shell do |s|
            s.path = 'puphpet/shell/execute-files.sh'
            s.args = ['exec-once', 'exec-always']
          end
          prod_config.vm.provision :shell, run: 'always' do |s|
            s.path = 'puphpet/shell/execute-files.sh'
            s.args = ['startup-once', 'startup-always']
          end
          prod_config.vm.provision :shell, :path => 'puphpet/shell/important-notices.sh'
    end
end

Commandline Output:

C:\VirtualMachines\VagrantBoxes\APP01>vagrant provision
==> dev: VM not created. Moving on...
==> prod: Warning! The ManagedServers provider doesn't support any of the Vagrant
==> prod: high-level network configurations (`config.vm.network`). They
==> prod: will be silently ignored.
==> prod: Warning! Folder sync disabled because the rsync binary is missing.
==> prod: Make sure rsync is installed and the binary can be found in the PATH.
==> prod: Running provisioner: shell...
    prod: Running: C:/Users/Pascal/AppData/Local/Temp/vagrant-shell20141004-5396
-157lmpt.sh
==> prod: sudo: no tty present and no askpass program specified
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

chmod +x /tmp/vagrant-shell && /tmp/vagrant-shell /vagrant/puphpet

Stdout from the command:

Stderr from the command:

sudo: no tty present and no askpass program specified

As I understand it the problem is, that vagrant can't create the shared folders like it does with the VM's when it's on the remote server. Therefore it can't reach the Puppet files and breaks.

My Question: Is there a way to let Puppet run localy and just send the commands to the server (using ssh), or can I just copy the Puppet files to the server (not DRY, I know but then I'd just put them under version controll with git and use them on my local machine and on the remote)? Has anyone expirience with a setup like this (or a better solution)?

Edit: If this helps: My local machine runs Windows but the VM is an Ubuntu 14.04, on the remote machine is also an Ubuntu 14.04 running. im Using the latest version of vagrant.

Upvotes: 1

Views: 1397

Answers (1)

tuxar
tuxar

Reputation: 88

In my experience the output sudo: no tty present and no askpass program specified tells me that sudoer user.name should provide password.

We need

Password-less Sudo

This is important!. Many aspects of Vagrant expect the default SSH user to have passwordless sudo configured. This lets Vagrant configure networks, mount synced folders, install software, and more.

To begin, some minimal installations of operating systems don't even include sudo by default. Verify that you install sudo in some way.

After installing sudo, configure it (usually using visudo) to allow passwordless sudo for the "vagrant" user. This can be done with the following line at the end of the configuration file:

vagrant ALL=(ALL) NOPASSWD: ALL

Additionally, Vagrant doesn't use a pty or tty by default when connected via SSH. You'll need to make sure there is no line that has requiretty in it. Remove that if it exists. This allows sudo to work properly without a tty. Note that you can configure Vagrant to request a pty, which lets you keep this configuration. But Vagrant by default doesn't do this.

https://docs.vagrantup.com/v2/boxes/base.html

For Ubuntu the config file is /etc/sudoers and you should change

vagrant ALL=(ALL) NOPASSWD: ALL

with

user.name ALL=(ALL) NOPASSWD: ALL

Upvotes: 2

Related Questions