I am developing an application with PhP and client asked me to set up a vagrant machine and install every needed extensions and modules, so that with just one Vagrant up command the client will have the same environment as I have,
I firstly installed a vagrant machine from one of the boxes lsit
vagrant box add ubuntu1 http://goo.gl/KwQSa2
Then I run these commands:
vagrant init ubuntu1
vagrant up
in the directory that I made this file there is only a vagranrfile
The Question:
I need to know if I make any changes to my server for example, installing php or mysql how it is going to saved in the setting so that if I just give this file to my client he will be able to have an identical machine to mine with everything installed?
I mean there will be any changes to vagrantfile or I made some mistake and I had to install a machine with puppet?
thanks in advance
No, the vagrant file is not going to change as you install things in the VM.
If you want your client to have the same machine as you, you'll have to avoid installing softwares through the VM's shell. You should only use the provisioner, for everything, even mysql tables, apache virtual hosts etc..
And don't use vagrant box add ubuntu1 http://goo.gl/KwQSa2, add the box's url to the vagrantfile with:
config.vm.box_url = "http://goo.gl/KwQSa2"
Example puppet provisioning for a mysql/php server:
group { 'puppet':
ensure => 'present',
}
#
# Apache configuration
#
class { 'apache' :
default_mods => false,
default_confd_files => false,
mpm_module => 'prefork',
default_vhost => false,
sendfile => 'Off'
}
class { 'apache::mod::php' : } # mod_php
class { 'apache::mod::rewrite' : } # mod_rewrite
# VHost configuration
apache::vhost { 'dev.XXX.fr' :
port => '80',
docroot => '/var/sites/myXXX/web',
access_log => true,
access_log_file => 'XXX_access.log',
error_log => true,
error_log_file => 'XXX_error.log',
aliases => [{alias => '/myXXX', path => '/var/sites/toto/web'}],
directories => [{path => '/var/sites/myXXX/web', 'allow_override' => ['FileInfo', 'Indexes']}, {path => '/var/sites/toto/web', 'allow_override' => ['FileInfo', 'Indexes']}]
}
#
# Mysql configuration
#
class { '::mysql::server' :
root_password => 'XXX',
databases => {
'XXX' => {
ensure => 'present',
charset => 'utf8'
}
},
users => {
'XXX#localhost' => {
ensure => 'present',
password_hash => 'XXX' # XXXmdp
}
},
grants => {
'XXX#localhost/XXX' => {
ensure => 'present',
options => ['GRANT'],
privileges => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE'],
table => 'XXX.*',
user => 'XXX#localhost'
}
}
}
class { '::mysql::client' : }
package { 'php5-mysql' :
require => [Class['apache::mod::php'], Class['::mysql::server']],
ensure => 'present'
}
You will need the following modules:
apache
concat
mysql
stdlib
The puppet config above is just for the example, I highly encourage you to read there documentation which is really well done: http://docs.puppetlabs.com/learning/introduction.html
Honestly, puppet is a great tool, take the time to learn it.
One more thing, avoid using the shell provisionner, the commands are executed everytime you run "vagrant provision", puppet only executes changes. (I only use the shell provisionner for apt-get update and apt-get upgrade)
Vagrantfile is a recipe which tells Vagrant how to set up your machine. In a way, it serves as an installation automation tool (and of course does much more as well). If you do any changes to the machine after it was created, Vagrant would not know about that.
What I do is I create Vagrantfile and inside of it I specify a shell script which Vagrant will execute only once, after machine boots the first time.
VAGRANTFILE_API_VERSION = "2"
$bootstrap = <<SCRIPT
# Installing all dependencies and other required software.
# Add "-y" switch to make sure installation is fully automatic.
apt-get install -y python-software-properties
# Any other stuff I might want to do (like edit conf files)
...
SCRIPT
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise64"
config.vm.provision "shell", inline: $bootstrap
end
See the doc for config.vm.provision.
I do this inline for convienience, so all configuration is still kept in only one file.
Of course any configuration which is supported directly by Vagrant, is better kept out of this $bootstrap script.
Related
I am trying to instal node on a fresh vagrant box using puppet however when running the manifest i get the following errors on the box.
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Warning: Scope(Apt::Source[nodesource]): $include_src is deprecated and will be removed in the next major release, please use $include => { 'src' => false } instead
Warning: Scope(Apt::Source[nodesource]): $required_packages is deprecated and will be removed in the next major release, please use package resources instead.
Warning: Scope(Apt::Source[nodesource]): $key_source is deprecated and will be removed in the next major release, please use $key => { 'source' => https://deb.nodesource.com/gpgkey/nodesource.gpg.key } instead.
Warning: Scope(Apt::Key[Add key: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280 from Apt::Source nodesource]): $key_source is deprecated and will be removed in the next major release. Please use $source instead.
Error: undefined method `ref' for nil:NilClass on node vagrant-ubuntu-trusty-64.efiling.local
Error: undefined method `ref' for nil:NilClass on node vagrant-ubuntu-trusty-64.efiling.local
My vagrant file looks like this:
config.vm.provision :shell do |shell|
shell.inline = "mkdir -p /etc/puppet/modules;
puppet module install puppetlabs-apt;
puppet module install puppetlabs/nodejs"
end
config.vm.provision "puppet" do |puppet|
puppet.manifests_path = "manifests"
puppet.manifest_file = "default.pp"
end
This is my manifest file:
class { 'nodejs': }
The next part is to get vagrant to run the manifest file but I believe these errors are stopping this from happening.
This is all relatively new to me so looking for some guidance on the issue.
you should replace puppetlabs/nodejs by puppetlabs-nodejs so your Vagrantfile will look like
config.vm.provision :shell do |shell|
shell.inline = "mkdir -p /etc/puppet/modules;
puppet module install puppetlabs-apt;
puppet module install puppetlabs-nodejs"
end
Which version of puppet are you using ? I had to upgrade to newer version on my ubuntu box to make it work, I upgrade to puppet v3.8.4 to make it work - see below the log
==> default: Running provisioner: puppet...
==> default: Running Puppet with default.pp...
==> default: stdin: is not a tty
==> default: Warning: Setting templatedir is deprecated. See http://links.puppetlabs.com/env-settings-deprecations
==> default: (at /usr/lib/ruby/vendor_ruby/puppet/settings.rb:1139:in `issue_deprecation_warning')
==> default: Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
==> default: Warning: Scope(Apt::Source[nodesource]): $include_src is deprecated and will be removed in the next major release, please use $include => { 'src' => false } instead
==> default: Warning: Scope(Apt::Source[nodesource]): $required_packages is deprecated and will be removed in the next major release, please use package resources instead.
==> default: Warning: Scope(Apt::Source[nodesource]): $key_source is deprecated and will be removed in the next major release, please use $key => { 'source' => https://deb.nodesource.com/gpgkey/nodesource.gpg.key } instead.
==> default: Warning: Scope(Apt::Key[Add key: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280 from Apt::Source nodesource]): $key_source is deprecated and will be removed in the next major release. Please use $source instead.
==> default: Notice: Compiled catalog for ubuntu.localdomain in environment production in 0.71 seconds
==> default: Notice: /Stage[main]/Apt/Apt::Setting[conf-update-stamp]/File[/etc/apt/apt.conf.d/15update-stamp]/ensure: defined content as '{md5}0962d70c4ec78bbfa6f3544ae0c41974'
==> default: Notice: /Stage[main]/Apt/File[preferences]/ensure: created
==> default: Notice: /Stage[main]/Nodejs::Repo::Nodesource/Nodejs::Repo::Nodesource::Apt/Apt::Source[nodesource]/Apt::Key[Add key: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280 from Apt::Source nodesource]/Apt_key[Add key: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280 from Apt::Source nodesource]/ensure: created
==> default: Notice: /Stage[main]/Nodejs::Repo::Nodesource/Nodejs::Repo::Nodesource::Apt/Apt::Source[nodesource]/Apt::Setting[list-nodesource]/File[/etc/apt/sources.list.d/nodesource.list]/ensure: created
==> default: Notice: /Stage[main]/Apt::Update/Exec[apt_update]/returns: E: The method driver /usr/lib/apt/methods/https could not be found.
==> default: Error: /Stage[main]/Apt::Update/Exec[apt_update]: Failed to call refresh: /usr/bin/apt-get update returned 100 instead of one of [0]
==> default: Error: /Stage[main]/Apt::Update/Exec[apt_update]: /usr/bin/apt-get update returned 100 instead of one of [0]
==> default: Notice: /Stage[main]/Nodejs::Install/Package[nodejs]/ensure: ensure changed 'purged' to 'present'
==> default: Notice: Finished catalog run in 29.83 seconds
The SSH command responded with a non-zero exit status. Vagrant
assumes that this means the command failed. The output for this command
should be in the log above. Please read the output to determine what
went wrong.
fhenri#machine:~/project/examples/vagrant/ubuntu$ vagrant ssh
Welcome to Ubuntu 12.04.1 LTS (GNU/Linux 3.2.0-29-virtual x86_64)
* Documentation: https://help.ubuntu.com/
Last login: Thu Nov 19 06:46:10 2015 from 172.16.42.1
vagrant#ubuntu:~$ node -v
v0.6.12
--- This is an alternative method
This took a while to de-bug but the best approach I found to installing node on a server through puppet is to run a manual instal through puppet.
I found this repo, and took what I needed from the manifest file.
class apt_update {
exec { "aptGetUpdate":
command => "sudo apt-get update",
path => ["/bin", "/usr/bin"]
}
}
class othertools {
package { "git":
ensure => latest,
require => Exec["aptGetUpdate"]
}
package { "vim-common":
ensure => latest,
require => Exec["aptGetUpdate"]
}
package { "curl":
ensure => present,
require => Exec["aptGetUpdate"]
}
package { "htop":
ensure => present,
require => Exec["aptGetUpdate"]
}
package { "g++":
ensure => present,
require => Exec["aptGetUpdate"]
}
}
class nodejs {
exec { "git_clone_n":
command => "git clone https://github.com/visionmedia/n.git /home/vagrant/n",
path => ["/bin", "/usr/bin"],
require => [Exec["aptGetUpdate"], Package["git"], Package["curl"], Package["g++"]]
}
exec { "install_n":
command => "make install",
path => ["/bin", "/usr/bin"],
cwd => "/home/vagrant/n",
require => Exec["git_clone_n"]
}
exec { "install_node":
command => "n stable",
path => ["/bin", "/usr/bin", "/usr/local/bin"],
require => [Exec["git_clone_n"], Exec["install_n"]]
}
}
include apt_update
include othertools
include nodejs
I'm using rbvmomi gem to automate vsphere in ruby. I'm using vmware API StartProgramInGuest to run commands. The commands are given in a text file which is passed as an argument to GuestProgramSpec. One of the commands in the file requires a confirmation. Since the commands are passed in a text file, I'm not sure how to pass "yes" to the command. Any help would be appreciated.
gom = vim.serviceContent.guestOperationsManager
guest_auth = RbVmomi::VIM::NamePasswordAuthentication(
:interactiveSession => false,
:username => "user",
:password => "pass"
)
prog_spec = RbVmomi::VIM::GuestProgramSpec(
:programPath =>"/opt/system/bin/ssh",
:arguments => "-s /opt/system/etc/cli/default/main.par -f /home/admin/local.txt"
)
id = gom.processManager.StartProgramInGuest(
:vm => vm, :auth => guest_auth, :spec => prog_spec
)
Contents of local.txt :
show version > /home/admin/veriosn-1.txt
application upgrade appbundle.tar.gz local
show version > /home/admin/version-2.txt
First of all I am new to chef and vagrant.
I already have a working vagrant box based on an open source project at vdd. I am trying to add a chef recipe to it that checks out a git repo into a directory prepared by chef provisioner.
So I added a new recipe to in cookbooks/custom/my_example/default.rb and added an entry "recipe[my_example]" to the run_list in chef/roles/vdd.json. The recipe is supposed to checkout a git repository to a directory document_root which is declared in config.json and prepared with vdd_sites.rb recipe file. My custom chef recipe I have in cookbooks/custom/my_example/default.rb does the follwoing:
git "/var/www/drupal7" do
repository "https://github.com/drupal/drupal.git"
revision "master"
checkout_branch 'master'
action :sync
user 'vagrant'
group 'vagrant'
end
The relevant config json code is:
"vdd": {
"sites": {
"drupal8": {
"account_name": "root",
"account_pass": "root",
"account_mail": "box#example.com",
"site_name": "Drupal 8",
"site_mail": "box#example.com",
"vhost": {
"document_root": "drupal8",
"url": "drupal8.dev",
"alias": ["www.drupal8.dev"]
}
},
"drupal7": {
"account_name": "root",
"account_pass": "root",
"account_mail": "box#example.com",
"site_name": "Drupal 7",
"site_mail": "box#example.com",
"vhost": {
"document_root": "drupal7/docroot",
"url": "drupal7.dev",
"alias": ["www.drupal7.dev"]
}
}
}
}
And the code in vdd_sites.rb is:
if node["vdd"]["sites"]
node["vdd"]["sites"].each do |index, site|
include_recipe "database::mysql"
htdocs = defined?(site["vhost"]["document_root"]) ? site["vhost"]["document_root"] : index
# Avoid potential duplicate slash in docroot path from config.json input.
if htdocs.start_with?("/")
htdocs = htdocs[1..-1]
end
# Create subidrectores, allow for multiple layers deep.
htdocs = "var/www/" + htdocs
htdocs = htdocs.split(%r{\/\s*})
folder = "/"
for i in (0..htdocs.length - 1)
folder = folder + htdocs[i] + "/"
directory folder do
owner "vagrant"
group "vagrant"
mode "0755"
action :create
end
end
mysql_connection_info = {
:host => "localhost",
:username => "root",
:password => node["mysql"]["server_root_password"]
}
mysql_database index do
connection mysql_connection_info
action :create
end
end
end
However, nothing gets cloned in that directory. if I change the target destination to another directory in my recipe file it works fine. i.e. git "/var/www/anotherdir" do ...
I am not sure what's going on, is it the order of recipe execution?
Remove the checkout_branch line, you don't want that. Yes I know it sounds like you do, but you don't. Check the output from chef-client to make sure your recipe is actually running. You seem to be saying both of those snippets of code are vdd_sites?
I suspect your issue is that GIT doesn't much like having files (or directories) in the directories it's creating clones into. It appears to be as if /var/www/drupal7 at the very least has a subdir /docroot, and maybe a lot more files.
Suggest you create the clone first, then add these files.
I am trying to provision a vagrant VM to allow users to supply their own bash_profile.local but I don't want this file tracked in the vm's vcs repo. I have a tracked bash_profile.local.dist file that they can rename. How can I tell puppet to only create a file if the source file exists? It is currently working correctly but logs an error during provisioning and this is what I'm trying to avoid.
This is the manifest:
class local
{
file { '.bash_profile.local':
source => 'puppet:///modules/local/bash_profile.local',
path => '/home/vagrant/.bash_profile.local',
replace => false,
mode => 0644,
owner => 'vagrant',
group => 'vagrant',
}
}
You could abuse file in this way :
$a = file('/etc/puppet/modules/local/files/bash_profile.local','/dev/null')
if($a != '') {
file { '.bash_profile.local':
content => $a,
...
}
}
This is not exactly what you asked but you can supply multiple paths in the source, so you can have a default empty file if the user didn't supplied his own.
class local
{
file { '.bash_profile.local':
source => [
'puppet:///modules/local/bash_profile.local',
'puppet:///modules/local/bash_profile.local.default'
],
path => '/home/vagrant/.bash_profile.local',
replace => false,
mode => 0644,
owner => 'vagrant',
group => 'vagrant',
}
}
You can try something like this:
file { 'bash_profile.local':
ensure => present,
source => ['puppet:///modules/local/bash_profile.local', '/dev/null'],
path => '/home/vagrant/.bash_profile.local',
before => Exec['clean-useless-file'],
}
exec { 'clean-useless-file':
command => 'rm .bash_profile.local',
onlyif => 'test -s .bash_profile.local',
cwd => '/home/vagrant',
path => '/bin:/usr/bin',
}
If the admin don't make a copy of ".bash_profile.local" available in "modules/local/bash_profile.local", the file resource will use the second source and then create a blank file. Then, the "onlyif" test fails and the exec will remove the useless blank file.
Used this way this code can be a little cumbersome, but it's better than a provisioning failure. You may evaluate if retaining a blank .bash_profile.local file can be okay in your case. I normally use a variation of this, with wget instead of rm, to get a fresh copy of the file from the internet if it was not already made available as a source.
If you're using puppetmaster, be aware you can use it to provision the own server, presenting two versions of the catalog, according to the .bash_profile.local is present or not.
Attempting to Boot and provision a LAMP VM with Vagrant and Virtual box running on a Windows 7 64 bit host. But am getting the error message:
Could not match ? at /tmp/vagrant-puppet/manifests/default.pp:2 on node lucid32.hsd1.ca.comcast.net.
Searches don't find any helpful clues - they are unrelated to using Vagrant and discuss completely different scenarios.
C:\Users\rdavis\lamp-project>vagrant up
[default] VM already created. Booting if it's not already running...
[default] Clearing any previously set forwarded ports...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] -- 80 => 8080 (adapter 1)
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] Mounting shared folders...
[default] -- v-root: /vagrant
[default] -- configs: /configs
[default] -- manifests: /tmp/vagrant-puppet/manifests
[default] Running provisioner: Vagrant::Provisioners::Puppet...
[default] Running Puppet with /tmp/vagrant-puppet/manifests/default.pp...
stdin: is not a tty
Could not parse for environment production: Could not match ? at /tmp/vagrant-puppet/manifests/default.pp:2 on node lucid32.hsd1.ca.comcast.net.
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
cd /tmp/vagrant-puppet/manifests && puppet apply /tmp/vagrant-puppet/manifests/default.pp --detailed-exitcodes || [ $? -eq 2 ]
C:\Users\rdavis\lamp-project>
(A sub question, out of curiosity is: What is lucid32.hsd1.ca.comcast.net ?! This looks like a valid URL (but doesn't actually work (404)) - So what's it for?)
My setup:
Windows 7 64 bit
Installed VirtualBox
Installed Vagrant
Installed Puppet: https://downloads.puppetlabs.com/windows/
Installed Ruby: http://rubyinstaller.org/
Issued command:
vagrant box add base http://files.vagrantup.com/lucid32.box
Then attempted to setup a LAMP VM in a Windows 7 64 bit host based on:
http://ox86.tumblr.com/post/23734821654/painless-development-environments-with-virtualbox
...as follows:
mkdir lamp-project
cd lamp-project
C:\Users\rdavis\lamp-project>mkdir configs
C:\Users\rdavis\lamp-project>mkdir manifests
C:\Users\rdavis\lamp-project>vagrant init
Edited Vagrantfile inserted the following directly after Vagrant::Config.run do |config|
config.vm.box = “lucid32”
config.vm.provision :puppet do |puppet|
puppet.manifests_path = File.expand_path(“../manifests”, __FILE__)
end
config.vm.forward_port 80, 8080
config.vm.share_folder “configs”, “/configs”, File.expand_path(“../configs”, __FILE__)
Then created a default.pp puppet file (again, from reference 1 ) and put in the manifests folder as that reference 1 instructs
$config_path = "/configs”
$vagrant_base_path = "/vagrant”
Exec { path => "/bin:/usr/bin:/usr/local/bin” }
group { "puppet”: ensure => present }
exec { "apt-get update”: command => "apt-get update” }
class apache {
file { "/etc/apache2/sites-enabled/000-default":
ensure => file,
source => "${config_path}/000-default",
before => Service["apache2"],
}
exec { "enable-mod_rewrite":
require => Package["apache2"],
before => Service["apache2"],
command => "/usr/sbin/a2enmod rewrite"
}
package { "apache2":
ensure => present,
before => File["/etc/apache2/sites-enabled/000-default"],
}
service { "apache2":
ensure => running,
require => Package["apache2"]
}
}
class php {
package { "libapache2-mod-php5": ensure => present }
package { "php5": ensure => present }
package { "php5-cli": ensure => present }
package { "php5-dev": ensure => present }
package { "php5-mysql": ensure => present }
package { "php-pear": ensure => present }
exec { "pear upgrade":
command => "/usr/bin/pear upgrade",
require => Package["php-pear"],
}
}
class mysql {
package { "mysql-server":
require => Exec["apt-get update"],
ensure => present,
}
service { "mysql":
enable => true,
ensure => running,
require => Package["mysql-server"],
}
exec { "Set MySQL server root password":
require => Package["mysql-server"],
unless => "/usr/bin/mysqladmin -uroot -proot status",
command => "/usr/bin/mysqladmin -uroot password root",
}
}
include apache
include php
include mysql
Updated
Some invalid quoting e.g. see line $vagrant_base_path = "/vagrant”
All instances of ” have been corrected to "
Some invalid quoting e.g. see line $vagrant_base_path = "/vagrant”
All instances of ” have been corrected to "