Upload
others
View
24
Download
3
Embed Size (px)
Citation preview
CreatingDevelopmentEnvironmentswithVagrantSecondEdition
TableofContents
CreatingDevelopmentEnvironmentswithVagrantSecondEdition
Credits
AbouttheAuthor
AbouttheReviewers
www.PacktPub.com
Supportfiles,eBooks,discountoffers,andmore
Whysubscribe?
FreeaccessforPacktaccountholders
Preface
Whatthisbookcovers
Whatyouneedforthisbook
Whothisbookisfor
Conventions
Readerfeedback
Customersupport
Downloadingtheexamplecode
Errata
Piracy
Questions
1.GettingStartedwithVagrant
IntroducingVagrant
RequirementsforVagrant
Gettingstarted
InstallingVirtualBox
InstallingVagrant
Summary
2.ManagingVagrantBoxesandProjects
CreatingourfirstVagrantproject
ManagingVagrant-controlledguestmachines
PoweringupaVagrant-controlledvirtualmachine
Suspendingavirtualmachine
Resumingavirtualmachine
Shuttingdownavirtualmachine
Startingfromscratch
UpdatingbasedonVagrantfilechanges
ConnectingtothevirtualmachineoverSSH
Managingintegrationbetweenhostandguestmachines
Portforwarding
Syncedfolders
Networking
Autorunningcommands
ManagingVagrantboxes
AddingVagrantboxes
ListingVagrantboxes
Checkingforupdates
RemovingVagrantboxes
RepackagingaVagrantbox
Updatingthecurrentenvironment’sbox
ToomanyVagrants!
Summary
3.ProvisioningwithPuppet
Provisioning
Puppet
CreatingmodulesandmanifestswithPuppet
Puppetclasses
DefaultPuppetmanifests
Resources
Resourcerequirements
Resourceexecutionordering
Thenotify,subscribe,andrefreshonlyparameters
Executingresourcesinstages
Installingsoftware
Updatingourpackagemanager
Installingthenginxpackage
Runningthenginxservice
Filemanagement
Copyingafile
Creatingasymlink
Creatingfolders
Creatingmultiplefoldersinonego
Cronmanagement
Runningcommands
Managingusersandgroups
Creatinggroups
Creatingusers
Updatingthesudoersfile
Creatingconfigurableclasses
Puppetmodules
UsingPuppettoprovisionservers
Summary
4.UsingAnsible
UnderstandingAnsible
InstallingAnsible
Creatinganinventory
CreatingAnsibleplaybooks
Modules–whatAnsiblecando
Installingsoftware
Updatingourpackagemanager
Installingthenginxpackage
Runningthenginxservice
Understandingfilemanagement
Copyingafile
Creatingasymlink
Creatingfolders
Managingcron
Runningcommands
Managingusersandgroups
Creatinggroups
Creatingusers
UsingAnsibleroles
UsingAnsibletoprovisionservers
Summary
5.UsingChef
KnowingaboutChef
CreatingcookbooksandrecipeswithChef
Resources–whatChefcando
Installingsoftware
Updatingourpackagemanager
Installingthenginxpackage
Runningthenginxservice
Understandingfilemanagement
Copyingafile
Creatingasymlink
Creatingfolders
Creatingmultiplefoldersinasingleprocesswithlooping
Managingcron
Runningcommands
Managingusersandgroups
Creatinggroups
Creatingusers
Updatingthesudoersfile
Knowingcommonresourcefunctionalities
UsingChefcookbooks
UsingCheftoprovisionservers
Summary
6.ProvisioningVagrantMachineswithPuppet,Ansible,andChef
ProvisioningwithinVagrant
ProvisioningwithPuppetonVagrant
UsingPuppetinstandalonemode
Puppetprovisioninginaction
UsingPuppetinclient/servermode
ProvisioningwithAnsibleonVagrant
ProvisioningwithChefonVagrant
UsingChef-solo
UsingChefinclient/servermode
ProvisioningwithSSH–arecap
Usingmultipleprovisionersonasingleproject
Overridingprovisioningviathecommandline
Summary
7.WorkingwithMultipleMachines
UsingmultiplemachineswithVagrant
Definingmultiplevirtualmachines
ConnectingtothemultiplevirtualmachinesoverSSH
Networkingthemultiplevirtualmachines
Provisioningthemachinesseparately
Destroyingamultimachineproject
Summary
8.CreatingYourOwnBox
Gettingstarted
PreparingtheVirtualBoxmachine
VirtualBoxGuestAdditions
Vagrantauthentication
Vagrantuserandadmingroup
Thesudoersfile
Insecurepublic/privatekeypair
Provisioners
InstallingPuppet
InstallingChef
CleaninguptheVM
Export
Summary
9.HashiCorpAtlas
Discoveringboxes
Installingnewboxes
Updatingexistingboxes
Checkingforoutdatedboxes
Distributingboxes
SharingandconnectingwithAtlas
LoggingVagrantintoVagrantCloud
SharingaVagrantvirtualmachineoverHTTP(S)
SharingandconnectingtoaVagrantvirtualmachine
Summary
A.ASampleLEMPStack
CreatingtheVagrantproject
CreatingthePuppetmanifests
InstallingNginx
InstallingPHP
InstallingtheMySQLmodule
Defaultmanifest
InstallingNginxandPHP
Hostnameconfiguration
E-mailsendingservices
MySQLconfiguration
Launchingthevirtualmachine
Summary
Index
CreatingDevelopmentEnvironmentswithVagrantSecondEdition
CreatingDevelopmentEnvironmentswithVagrantSecondEditionCopyright©2015PacktPublishing
Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.
Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthor,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.
PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.
Firstpublished:August2013
Secondedition:March2015
Productionreference:1050315
PublishedbyPacktPublishingLtd.
LiveryPlace
35LiveryStreet
BirminghamB32PB,UK.
ISBN978-1-78439-702-9
www.packtpub.com
CreditsAuthor
MichaelPeacock
Reviewers
JonathanBardo
AnirudhBhatnagar
CommissioningEditor
UshaIyer
AcquisitionEditors
RichardBrookes-Bland
EllenBishop
ContentDevelopmentEditor
SriramNeelakantan
TechnicalEditor
MrunalM.Chavan
CopyEditor
RashmiSawant
ProjectCoordinator
AboliAmbardekar
Proofreaders
SimranBhogal
MariaGould
PaulHindle
Indexer
MonicaAjmeraMehta
ProductionCoordinator
ArvindkumarGupta
CoverWork
ArvindkumarGupta
AbouttheAuthorMichaelPeacockisanexperiencedsoftwaredeveloperandteamleadfromNewcastle,UK,withadegreeinsoftwareengineeringfromtheUniversityofDurham.
Afterspendinganumberofyearsrunninghisownwebagency,andsubsequently,workingdirectlyforanumberofsoftwarestart-ups,henowrunshisownsoftwaredevelopmentagency,workingonarangeofprojectsforanarrayofdifferentclients.
HeistheauthorofCreatingDevelopmentEnvironmentswithVagrant,PHP5SocialNetworking,PHP5E-CommerceDevelopment,Drupal7SocialNetworking,andSellingonlinewithDrupale-CommerceandBuildingWebsiteswithTYPO3,allbyPacktPublishing.TheotherpublicationsMichaelhasbeeninvolvedinincludeAdvancedAPISecurity,MobileWebDevelopment,JenkinsContinuousIntegrationCookbook,andDrupalforEducationandE-Learning;fortheseheactedasatechnicalreviewer.
Michaelhasalsopresentedatanumberofusergroupsandtechnicalconferences,includingPHPUKConference,DutchPHPConference,ConFoo,PHPNE,PHPNW,andCouldConnectSantaClara.
YoucanfollowMichaelonTwitter(@michaelpeacock),orfindoutmoreabouthimthroughhiswebsite(www.michaelpeacock.co.uk).
I’dliketothanktheteamatPacktPublishingfortheirhelpingettingthisrevisededitionofthebookpublished,andthetechnicalreviewersforensuringtechnicalaccuracyinthebook.
AbouttheReviewersJonathanBardoisaMontreal-basedwebdeveloperwithakeeninterestfornewtechnologiesandautomation.Hehasworkedformanylarge-scalewebsitesdealingwithmillionsofdailyvisitorsonvariousplatforms.Whenheisnotprogramming,helikestowatchagoodTVshowortravelsomewherehehasneverbeenbefore.Ifyouseehimridinghismotorcycleorskiingdownahill,justsayhi!Heisveryfriendly!
Jonathanrunshisownconsultingcompany,whichletshimmeetallsortsofinterestingclients,suchasFoxBroadcasting(USA),RogersDigitalMedia(Canada),andYellowPagesGroup(Canada).
Aspecialthankstoeveryonewhohasbeenapartofmyjourneysofar!Iwouldn’tbeherewithoutalltheincrediblepeopleIworkedwitheveryday.
AnirudhBhatnagarisaprincipalconsultantatXebia.Hestartedhiscareerasadeveloperworkinginproduct-basedcompaniessuchasAdobe.
AnirudhhasbeenworkingmostlywithJava-basedtechnologystacksthatuseSpring,Hibernate,XML,webservices,REST,CMS,SSO,ESB,andLiferay.
Duringthelastfewyears,AnirudhhasbeenadvocatingContinuousDeliveryandisinterestedintechnologiessuchasChef,Puppet,Jenkins,Vagrant,Docker,andmanymore.Heregularlycontributestothecommunityviablogs,articles,meetups,conferences,andopensourceprojects.
Moredetailsabouthimcanbefoundonhisblog(http://anirudhbhatnagar.com).
www.PacktPub.com
Supportfiles,eBooks,discountoffers,andmoreForsupportfilesanddownloadsrelatedtoyourbook,pleasevisitwww.PacktPub.com.
DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusat<[email protected]>formoredetails.
Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.
https://www2.packtpub.com/books/subscription/packtlib
DoyouneedinstantsolutionstoyourITquestions?PacktLibisPackt’sonlinedigitalbooklibrary.Here,youcansearch,access,andreadPackt’sentirelibraryofbooks.
Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser
FreeaccessforPacktaccountholdersIfyouhaveanaccountwithPacktatwww.PacktPub.com,youcanusethistoaccessPacktLibtodayandview9entirelyfreebooks.Simplyuseyourlogincredentialsforimmediateaccess.
PrefaceWeb-basedsoftwareprojectsareincreasinglycomplicated,witharangeofdifferentdependencies,requirements,andinterlinkingcomponents.Swappingbetweenprojects,whichrequiredifferentversionsofthesamesoftware,becomestroublesome.Gettingteammembersupandrunningonnewprojectsbecomestime-consuming.
Vagrantisapowerfultoolusedtocreate,manage,andworkwithvirtualizeddevelopmentenvironmentsforyourprojects.Bycreatingavirtualenvironmentforeachproject,theirdependenciesandrequirementsareisolated,theyalsodon’tinterferewiththesoftwareinstalledonyourownmachinesuchasWAMPorMAMP.Colleaguescanbeupandrunningonanewprojectinminuteswithasinglecommand.WithVagrant,wecanwipetheslatecleanifwebreakourenvironmentandbebackupandrunninginnotime.
WhatthisbookcoversChapter1,GettingStartedwithVagrant,introducestheconceptofvirtualization,itsimportanceintheroleofthedevelopmentenvironment,andwalksyouthroughtheVagrantinstallationprocess.
Chapter2,ManagingVagrantBoxesandProjects,walksyouthroughcreatingVagrantprojects,exploringandconfiguringtheVagrantfile,andworkingwithbaseboxes.
Chapter3,ProvisioningwithPuppet,exploresPuppet,theprovisioningtool,andhowtocreatePuppetmanifeststoprovisionaserver.
Chapter4,UsingAnsible,exploresAnsible,theprovisioningtool,andhowtocreateAnsibleplaybookstoprovisionaserver.
Chapter5,UsingChef,exploresChef,theprovisioningtool,andhowtocreateChefrecipestoprovisionaserver.
Chapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef,discusseshowtousePuppet,Ansible,andChefwithinthecontextofVagranttoprovisiondevelopmentenvironments.
Chapter7,WorkingwithMultipleMachines,exploresusingVagranttocreateandmanageprojectsthatusemultiplevirtualmachines,whichcommunicatewitheachother.
Chapter8,CreatingYourOwnBox,discussestheprocessofcreatingyourownbaseboxforusewithinaVagrantproject.
Chapter9,HashiCorpAtlas,walksyouthroughusingVagrantSharetoshareSSHandHTTP(S)accesstoaVagrant-managedmachine,andhowtousetheservicesprovidedthroughtheVagrantCloud.
Appendix,ASampleLEMPStack,walksyouthroughtheprocessofcreatingaLEMPserverwithinanewVagrantproject.
WhatyouneedforthisbookYouwillneedaWindows,OSX,orLinuxcomputerwithVagrantandOracleVirtualBoxinstalled,althoughtheinstallationprocessforthesewillbediscussedinChapter1,GettingStartedwithVagrant.
WhothisbookisforThisbookisforsoftwaredevelopers,developmentmanagers,andtechnicalteamleaderswhowanttohaveamoreefficient,robust,andflexibledevelopmentenvironmentfortheirprojectsandfortheirteam.
ConventionsInthisbook,youwillfindanumberofstylesoftextthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestyles,andanexplanationoftheirmeaning.
Codewordsintext,databasetablenames,foldernames,filenames,fileextensions,pathnames,dummyURLs,userinput,andTwitterhandlesareshownasfollows:“AfterinstallingVagrant,weranthevagrantcommandtocheckwhetheritwasinstalledcorrectly.”
Ablockofcodeissetasfollows:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.box="base"
end
Whenwewishtodrawyourattentiontoaparticularpartofacodeblock,therelevantlinesoritemsaresetinbold:
---
-hosts:default
tasks:
-name:updateaptcache
apt:update_cache=yes
-name:ensurenginxisinstalled
apt:pkg=nginxstate=present
-name:writethenginxconfigfile
template:src=nginx-default-site.confdest=/etc/nginx/sites-
available/default.conf
notify:
-restartnginx
-name:ensurenginxisrunning
service:name=nginxstate=started
handlers:
-name:restartnginx
service:name=nginxstate=restarted
Anycommand-lineinputoroutputiswrittenasfollows:
ansible-playbookour-playbook.yml-iour-inventory-file
Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,inmenusordialogboxesforexample,appearinthetextlikethis:“Again,onOSX,thefirststepistodouble-clickontheVagrant.pkgicon.”
NoteWarningsorimportantnotesappearinaboxlikethis.
TipTipsandtricksappearlikethis.
ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook—whatyoulikedormayhavedisliked.Readerfeedbackisimportantforustodeveloptitlesthatyoureallygetthemostoutof.
Tosendusgeneralfeedback,simplysendane-mailto<[email protected]>,andmentionthebooktitleviathesubjectofyourmessage.
Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideonwww.packtpub.com/authors.
CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.
DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesforallPacktbooksyouhavepurchasedfromyouraccountathttp://www.packtpub.com.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks—maybeamistakeinthetextorthecode—wewouldbegratefulifyouwouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheerratasubmissionformlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedonourwebsite,oraddedtoanylistofexistingerrata,undertheErratasectionofthattitle.Anyexistingerratacanbeviewedbyselectingyourtitlefromhttp://www.packtpub.com/support.
PiracyPiracyofcopyrightmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.Ifyoucomeacrossanyillegalcopiesofourworks,inanyform,ontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.
Pleasecontactusat<[email protected]>withalinktothesuspectedpiratedmaterial.
Weappreciateyourhelpinprotectingourauthors,andourabilitytobringyouvaluablecontent.
QuestionsYoucancontactusat<[email protected]>ifyouarehavingaproblemwithanyaspectofthebook,andwewilldoourbesttoaddressit.
Chapter1.GettingStartedwithVagrantDevelopingmodernweb-basedapplicationscanbecomplicated!
Thetechnologybehindourprojectsisbecomingmoreadvancedanddiverse.Whereonceprojectsranwithsimplyawebserver,adatabase,andasetprogramminglanguage,nowweusetoolsbuiltinavarietyofdifferentlanguages.Weusecomponentsanddependenciesthatneedtobeinstalled,andtheirmanagedversions,andoftenprojectsneedtorunacrossmultiplemachines.
Differentprojectshavetheirownrequirementsanddependencies,whichareoftenincompatiblewithoneanother.AlegacyprojectmightrequireaspecificversionofPHPorspecificversionsofextensionsforApache,whereasanotherprojectmightrequireanewerversionofPHPandrunningonNginx.Projectswitchinginthisscenarioisnoteasy.
Often,weneedtoworkwithteamsofpeople,someofwhichmightbeusingtheirownequipment,workingremotely,andcontractors.Thisrequiresyoutoensurethateveryonerunsthesamedevelopmentenvironment,regardlessoftheirownsystemanditsconfiguration,theinfrastructurechangesforprojectsaretrackedandmadeavailabletotheteam,andtheprojectsetupisfastfornewteammembers.
Combiningthesethreefactorsandsettinguptraditionaldevelopmentenvironmentsisbecomingmoredifficult,lessrelevant,andlesshelpfulfordevelopers.
Asprojectsgetmorecomplicated,it’salsoeasyforauxiliaryconfigurationstobeforgottenabout.Backgroundworkers,messagequeues,cronjobs,andmultiserverconfigurationsneedtobemanaged,distributedtotheentireteam,andthenwhenthetimecomes,appliedtotheprojectwhenitgetsdeployedintoaproductionenvironment.
Virtualizeddevelopmentenvironmentscanhelpwiththis.Insteadofhavingtobattleconfigurationswhenworkingonotherprojects,eachprojectcansimplyhaveitsownvirtualizedenvironment.Itcanhaveitsowndedicatedwebserver,databaseserver,andtheversionsoftheprogramminglanguageandotherdependenciesitneeds.Becauseitisvirtualized,itdoesn’timpactonotherprojects;justshutitdownandbootuptheenvironmentfortheotherproject.
Withavirtualizedenvironment,thedevelopmentenvironmentscanalsomimictheproductionenvironment.Youdon’tneedtoworryaboutwhethersomethingwillworkwhenitgetsdeployed,ifitisbeingdevelopedonamachinewiththeexactsamesoftwareconfiguration.EvenifyoudeployonaLinuxmachinebutdeveloponWindows,yourvirtualizedenvironmentcanbeLinux,runningthesamedistributionasyourproductionenvironment.
Whileavirtualizedenvironmentmakesdifferentprojectsandtheirdependencieseasiertomanageandseparate,theyarenottheeasiestofthingstoconfigureandmanage.Theystillneedtobeconfiguredtoworkwiththeprojectinquestion,whichofteninvolvessomelevelofsystemadministrationskills,andweneedtoconnecttotheseenvironmentsandworkwiththem.Theyalso,bydesign,arenotveryportable.Youneedtoexportalarge
imageofthevirtualizedenvironmentandsharethatwithyourcolleagues,andkeepingthatimageuptodateasprojectsevolvecanbecumbersome.Thankfully,thereisatoolthatcanmanagethesevirtualizedenvironmentsforus,andprovideasimpleinterfacetoconfigurethem;aninterfacethatinvolvesstoringconfigurationsinsimpleplaintextfiles,whichareeasytosharewithcolleagues,keepingeveryoneuptodateastheprojectchanges.ThistoolisVagrant.
IntroducingVagrantVagrant(http://www.vagrantup.com/)isapowerfuldevelopmenttoolthatletsyoumanageandsupportthevirtualizationofyourdevelopmentenvironment.Insteadofrunningallyourprojectslocallyonyourowncomputer,havingtojugglethedifferentrequirementsanddependenciesofeachproject,Vagrantletsyouruneachprojectinitsowndedicatedvirtualenvironment.
Vagrantprovidesacommand-lineinterfaceandacommonconfigurationlanguagethatallowsyoutoeasilydefineandcontrolvirtualmachinesthatrunonyourownsystems,butwhichtightlyintegrate,andalsoallowsyoutodefinehowyourownmachineandthevirtualmachineinteract.Thiscaninvolvesyncingfolderssuchthattheprojectcode,whichyoueditusingtheIDEonyourcomputer,issyncedsothatitrunsontheVagrantdevelopmentenvironment.
Vagrantusesproviderstointegratewiththethird-partyvirtualizationsoftware,whichprovidesthevirtualizedmachinesforourdevelopmentenvironment.ThedefaultproviderisforOracleVirtualBox;however,therearecommercialproviderstoworkwithVMwareFusionandalsopluginsforVagranttoworkwithAmazonWebServices.Theentireconfigurationisstoredinsimpleplaintextfiles.TheVagrantconfiguration(Vagrantfile),andtheconfigurationthatdefineshowourVagrantmachinesareconfigured(typicallyShellscripts,Ansibleplaybooks,ChefcookbooksorPuppetmanifeststhatVagranthasbuilt-insupportfor,asprovisioners)aresimplywrittenintextfiles.Thismeansthatwecaneasilysharetheconfigurationsandprojectswithcolleagues,usingversioncontrolsystemssuchasGit.
WhenusingVagrant,thenexttimeyouneedtogobacktoapreviousproject,youdon’tneedtoworryaboutanypotentialconflictswithchangesmadetoyourdevelopmentenvironment(forexample,ifyouhaveupgradedPHP,MySQL,orApacheonyourlocalenvironmentorwithintheVagrantenvironmentforanotherproject),asthedevelopmentenvironmentfortheseprojectsarecompletelyself-contained.Ifyoubringanewmemberintotheteam,theycanbeupandrunningwithyourprojectsinminutes.Vagrant,alongwithitsintegrationwithprovisioners,willtakecareofallthesoftwareandservicesneededtoruntheprojectontheirmachine.IfyouhaveoneprojectthatusesonewebserversuchasApache,andanotheronethatusesNginx,Vagrantletsyouruntheseprojectsindependently.Ifyourproject’sproductionenvironmentinvolvesmultipleservers(perhapsonefortheWebandoneforthedatabase),Vagrantletsyouemulatethatwithseparatevirtualserversonyourmachine.
WithVagrant:
YourdevelopmentenvironmentcanmimictheproductionenvironmentIntegratedprovisioningtoolssuchasPuppet,Chef,andAnsibleallowyoutostoretheconfigurationinastandardformat,whichcanalsobeusedtoupdateproductionenvironmentsEachprojectisseparateinitsownvirtualizedenvironment,soissuesasaresultofconfigurationandversiondifferencesfordependenciesondifferentprojectsarea
thingofthepastNewteammemberscanbeonboardedtonewprojectsaseasyasgitclone&&vagrantup
“Itworksonmymachine”asaresponsetobugsisathingofthepastTheheadacheoflinkingcodethatyouwriteonyourownmachinetoyourvirtualizeddevelopmentenvironmentistakencareofthroughsyncedfoldersTheenvironmentcanactasifitwasyourlocalmachineandmapthewebserverport(80)ofyourdevelopmentmachinetoyourdevelopmentenvironmentifyouwish,oryoucanaccessitasyouwouldanothermachineonyournetworkYoucanletcolleaguesviewyourowndevelopmentenvironmentaswellaseasilysharethedevelopmentenvironmentYoucanshareaccesstoyourowndevelopmentenvironmentovertheInternettodemoyourprojectortogetsupportfromacolleagueYourlocalWAMPorMAMPinstallationswillbegatheringdust!
Inthischapter,wewillcoverthefollowingtopics:
DiscusstherequirementsandprerequisitesforVagrantInstallOracleVirtualBoxInstallVagrantVerifythatVagrantwassuccessfullyinstalled
OncewehaveVagrantanditsprerequisitesonourmachine,wecanthentakealookatusingitforourfirstproject.
RequirementsforVagrantVagrantcanbeinstalledonLinux,Windows,andMacOSX,andalthoughitusesRuby,thepackageincludesanembeddedRubyinterpreter.TheonlyotherrequirementisavirtualizationprovidersuchasOracleVirtualBoxorVMwareFusion.TheOracleVirtualBoxproviderisavailableforfreeandisthedefaultproviderforVagrant.So,wewilluseandinstallVirtualBoxinordertouseVagrantduringthecourseofthisbook.Otherprovidersareavailable,includingoneforVMwareFusionorWorkstation,whichisavailableasacommercialadd-on(http://www.vagrantup.com/vmware).
GettingstartedNowthatweknowwhatsoftwareweneedinordertogetVagrantrunningonourmachine,let’sstartinstallingVirtualBoxandVagrantitself.
InstallingVirtualBoxVirtualBox(https://www.virtualbox.org/)isanopensourcetoolsponsoredbyOraclethatletsyoucreate,manage,andusevirtualmachinesonyourowncomputer.
VirtualBoxisagraphicalprogramwithacommand-lineinterfacethatletsyouvisuallycreatevirtualmachines,allocateresources,loadexternalmediasuchasoperatingsystemCDs,andviewthescreenofthevirtualmachine.Vagrantwrapsontopofthisandprovidesanintuitivecommand-lineinterfacealongwiththeintegrationofadditionaltools(includingintegrationswithprovisionersandalsoHashiCorpAtlas(formerly,VagrantCloud)thatallowyoutofindanddistributebaseserverimagesandshareaccesstoyourVagrantenvironments),sothatwedon’tneedtoworryabouthowVirtualBoxworksorwhattodowithit;Vagranttakescareofthisforus.
ThefirststageistodownloadtheinstallerfromtheVirtualBoxdownloadspage(https://www.virtualbox.org/wiki/Downloads),asshowninthefollowingscreenshot.Weneedtoselecttheoptionthatisappropriateforourcomputer(OSX,Windows,Linux,orSolaris):
NoteAtthetimeofwritingthis,Vagrantsupportsversions4.0.xthrough4.3.xofVirtualBox;earlierversionsarenotsupported.
Oncedownloaded,let’sopenitandruntheinstaller.OnOSX,thisinvolvesclickingontheVirtualBox.pkgicon,asshowninthefollowingscreenshot.OnWindows,simplyopeningtheinstalleropenstheinstallationwizard.OnLinux,therearepackagesavailablethatcanbeinstalledthroughyourchosenpackagemanager,seehttps://www.virtualbox.org/wiki/Linux_Downloadsformoreinformation.
Beforetheinstallerruns,itfirstcheckswhetherthecomputeriscapableofhavingVirtualBoxinstalled.WeneedtoclickonContinuetobegintheinstallationprocess,asshowninthefollowingscreenshot.WhilethisprocesswillvaryfromOSXtoWindowstoLinux,theprocessisverysimilaracrossallplatforms.TherearefullydetailedinstallationinstructionsforallplatformsontheVirtualBoxwebsite(https://www.virtualbox.org/manual/ch02.html).
Thefirststepintheprocessprovidesuswithanintroductiontotheinstallationprocessandremindsusastowhatweareactuallyinstalling:
Next,theinstallerinformsusastohowmuchspaceitwilluseonourcomputer,andprovidesuswiththeoptiontocustomizetheinstallationifwewanttoChangeInstallLocation…,andinstallthesoftwareinanotherlocation(perhapsanotherdiskdriveifourdiskgetsfull).
Let’sleavethedefaultinstalllocationasitis,andclickontheInstallbuttontoinstallVirtualBoxonourcomputer:
Afterbeingpromptedtoprovideadministrativeprivileges,theinstallerthenautomaticallyinstallsVirtualBoxforus:
Oncetheinstallationhasfinished,weareshownaconfirmationscreenwiththeoptionofclickingonClosetoclosetheinstaller:
NowwehavesuccessfullyinstalledVirtualBox!
InstallingVagrantNowthatwehavetheprerequisitesinstalledonourcomputer,wecanactuallyinstallVagrantitself.ThisprocessissimilartothatofinstallingVirtualBox.First,let’sdownloadtherelevantinstallerfromtheVagrantdownloadpage(http://www.vagrantup.com/downloads.html):
Let’sopentheinstallerandstarttheprocess.Again,onOSX,thefirststepistodouble-clickontheVagrant.pkgicon:
Wenowneedtofollowtheinstallationstepsthatareprovided;thisisverysimilartotheearlierstepsforVirtualBox,andformostofthesoftwarepackagesingeneral.Youmightbepromptedtoprovideyourcomputer’sadministrativeuserprivilegesforthesoftwaretobeinstalled.
Let’sverifythatVagranthasbeensuccessfullyinstalled.Wecandothisbyopeningaterminalwindow(cmdonWindows)andrunningthevagrantcommand:
TheprecedingscreenshotshowsthatwehavesuccessfullyinstalledVagrant,andweareabletorunit.
Runningthevagrantcommandonitsownlistsarangeofcommonsubcommands,whichwecanrunwithinVagrant,aswellasinstructionsonhowtoaccessthehelpinformationonVagrantandanyofitssubcommands.WecanaccessthehelpinformationonVagrantanditssubcommandsbyaddingthehflag,-h,totheendofthecommandwhenwerunit.
SummaryInthischapter,wediscussedthebenefitsofusingvirtualizeddevelopmentenvironmentsandspecifically,Vagrant.WetheninstalledOracleVirtualBox,whichisthevirtualizationproviderVagrantusesbydefault,andweinstalledVagrant.AfterinstallingVagrant,weranthevagrantcommandtocheckwhetheritwasinstalledcorrectly.
NowthatwehaveVagrantandaproviderinstalled,wecannowmoveontousingVagranttosetupandmanagesomeofourdevelopmentprojectsinavirtualdevelopmentenvironment.Inthenextchapter,wewillcreateourfirstproject,learnabouttheconfigurationfile,andmanageourVagrantcontrolledmachines.
Chapter2.ManagingVagrantBoxesandProjectsInthischapter,wewilllearnthebasicsofusingVagrant.Wewilltakealookatinitializingprojects,importingbaseboxestobeusedasouroperatingsystem,andcontrollingthevirtualmachinebypoweringonandoff,suspendingandresuming,andconnectingtothebox.Finally,wewillalsolearnhowtoconfiguresomeofthekeyintegrationpointsbetweenourownmachineandourVagrant-controlledvirtualmachine,including:
PortforwardingFoldermappingNetworking
CreatingourfirstVagrantprojectNowthatwehaveVagrantinstalledonourmachine,let’stakealookatcreatingVagrantprojects.AnyfoldercanactasaVagrantproject;itonlyrequiresaspecialconfigurationfile,calledtheVagrantfile,withinit.Vagrantusesthisfiletosetupthevirtualmachines(guests)andmanagetheirintegrationwithourcomputer(orhostmachine).
VagranthasacommandtocreateaVagrantfilewithinthecurrentdirectoryyouarein,withinyourcomputer’sterminal:thevagrantinitcommand.Tocreateanewproject,let’screateanewfolderanywhereinoursystem–ideally,somewhereeasilyreachable,thenweneedtogointothisfolder,andruntheinitcommand:
VagrantwillthencreateaVagrantfilewithinthatfolder,andshowusaconfirmationmessage:
IfwetakealookatthecontentsofthisVagrantfilefilethatwascreated,wewillseearangeofconfigurationoptions.Mostoftheoptionsarecommentedout(astheyareprefixedwitha#character)togiveusanideaofhowwecanconfiguretheproject.
Thereareonlyfourlinesofactualusableconfigurationinthefile,asshownhere:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.box="base"
end
TipDownloadingtheexamplecode
Youcandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
DifferentversionsofVagrantusedifferentstructuresandinstructionswithintheirVagrantfilefiles.TomakeVagrantbackwardcompatible,thevarioussettingsarewrappedinablockofcodethatcontainstheversionoftheconfigurationtobeused.ConfigurationVersion2iscompatiblewithVagrantVersion1.1uptoVersion2.0.x(whenreleased).
Withinhere,wehaveasingleoption—thetypeofVagrantboxtouse.AVagrantboxisanimageofanoperatingsystemthatisconfiguredtoworkwithVagrant.
WecangenerateaVagrantfilewithouttheillustrativecommentsbyprovidingtheminimaloption(-mor--minimal,forexample,vagrantinit--minimal).
InordertobootourVagrantmachine,werunthevagrantupcommand:
AsVagrantdoesn’tknowwhattheboxbaseis,ourprojectisunabletoboot.WhileVagrantprojectshavetheirconfigurationstoredwithintheirprojectsfolder,boxesareinstalledgloballyonyourcomputerandcanbesharedacrossprojects.IfVagrantdoesn’thaveaboxinstalledwiththatname,itwilleithertrytodownloaditfromtheURLprovidedintheVagrantfile(ifthereisoneprovided)oritwilllookfortherelevantboxinHashiCorpAtlas(formerlyVagrantCloud).HashiCorp,thecompanybehindVagrant,providesofficialboxesforthelatestLongTermSupportversionofUbuntu(thisboxishostedonanddistributedthroughVagrantCloud;wewilldiscussthisinmoredetailinChapter9,HashiCorpAtlas).Tousethisbox,wesimplypassthenameoftheboxtotheinitcommand(orupdatetheVagrantfile).AswealreadyhaveaVagrantfileinplaceforourproject,weneedtousetheforceoptiontooverridetheexistingfile(-for--force):
vagrantinit--forcehashicorp/precise64
NowifwetrytorunourVagrantproject,Vagrantwilllookforthebox,andthistime,itwilldownloadtheprecise64boxfromVagrantCloud,foruseinourproject:
Typically,boxesareminimalinstallationsofoperatingsystemsthatcontainonlywhatisrequiredfortheoperatingsystemtofunction,toolstointegratewithVagrant,andaminimalamountofothertools.ThisprovidesgreaterflexibilitywhenitcomestousingVagranttomanageprojects,aswecandecideexactlywhatsoftwareweneedtorunonourvirtualmachineforourprojecttofunction,withouthavingtoworryabouttheconflictingversionsofthesaidsoftware.Someexistingboxesmayhavemoresoftwareinstalled,andofcourse,wemaywanttopackageaboxthatcontainssomeofthekeysoftwareourprojectsneed(particularly,usefulasabackupforuserswithunreliableInternetconnections).
NoteWhileweareusingcommandstoinitializeourVagrantprojectsinthischapter,thesearesimplyquickwaystocreateaVagrantfilefilewithsomeprepopulatedvalues.AVagrantfilefileistheconfigurationfilethatdefineshowVagrantshouldusetheproject(suchasoperatingsystemtobeused,virtualmachinestobootup,syncedfolders,forwardedports,andsoon).Wecan,ofcourse,createthisfileourselveswithinthefolderwewishtouseasourproject.
ManagingVagrant-controlledguestmachinesThevirtualmachines,whichVagrantcontrolsforus,stillneedtobemanagedandworkedwith.WehaveseenthatwecanstartaVagrantprojectwithvagrantup.Let’slearnmoreaboutthiscommand,andseehowtoperformotheroperationsonournewvirtualmachine.
PoweringupaVagrant-controlledvirtualmachineAswehavejustseen,wecanpowerupavirtualmachineusingthevagrantupcommand.Withthiscommand,VagrantwillfirstcheckwhetheraVagrantenvironmenthasalreadybeensetup.Ifapreviouslysuspendedenvironmentisfound,itwillresumethatenvironment.
Iftheenvironmentwasnotpreviouslysuspended,Vagrantthencheckswhetherthebaseboxhasalreadybeendownloadedontothemachine.Ifithasn’t,itwilldownloadit,asitdidforuswhenwebootedourprojectwiththeprecise64boxforthefirsttime.
Vagrantwillthenperformthefollowingactions:
1. Copythebasebox(remember,baseboxesaremanagedgloballyonourhostcomputer,soittakesacopyforeachmachinemanagedbyit).
2. Createanewvirtualmachinewiththerelevantprovider(thedefaultbeingVirtualBox).
3. Forwardanyconfiguredports;bydefault,itwillforwardport22(theSSHport)onthevirtualmachinetoport2222onthehost.ThiswillallowustoconnecttothevirtualmachineoverSSH.
4. Boot(powerup)thevirtualmachine.5. Configureandenablenetworking,sothatwecancommunicatewiththevirtual
machine.6. Mapsharedfoldersbetweenthehostandtheguest(bydefault,itwillmapthefolder
thatcontainstheVagrantprojectto/vagrantontheguestmachine).7. RunanyprovisioningtoolsthataresetupsuchasPuppet,Chef,orSSHcommands
orscripts.
TheactionsperformedbyVagrantwilllooksomethinglikethis:
SuspendingavirtualmachineWecansavethecurrentstateofthevirtualmachinetothedisk(suspendit)sothatwecanresumeitlater.Ifwerunvagrantsuspend,itwillsuspendtheVMandstopitfromconsumingourmachine’sresources,exceptforthediskspaceitwilloccupy,readyforustouseagainlater:
ResumingavirtualmachineInordertouseapreviouslysuspendedvirtualmachine,wesimplyrunvagrantresume:
ShuttingdownavirtualmachineWecanshutdownarunningvirtualmachineusingthevagranthaltcommand.ThisinstructstheVMtostopallrunningprocessesandshutdown.Touseitagain,weneedtorunvagrantup,whichwillpoweronthemachine;provisioningistypicallyonlyranonthefirstvagrantupcommand.Toensurethatprovisioningrunswhenwebootupasavedmachinesubsequently,wecanusethe--provisionflag.
StartingfromscratchSometimes,thingsgowrong.It’snotinconceivablethatwemightmakesomechangestoourvirtualmachine,andfindoutthatitnolongerworks.Thankfully,sincewehaveabasebox,configurationfile,andprovisioningfiles,whichareallstoredseparately,wecaninstructVagranttodestroyourvirtualmachine,andthencreateitagain,usingtheconfigurationstosetitup.Thisisdoneviathedestroycommand,andthenweneedtousetheupcommandtostartitagain:
vagrantdestroy
vagrantup
Ofcourse,ifweupdateourVagrantfile,provisioningmanifests,orapplicationcodethatcanalsobreakthings;soitisimportantthatweuseaversioncontrolsystemtoproperlymanageourproject’scodeandconfiguration,sothatwecanundothechangestheretoo;Vagrantcanonlydosomuchtohelpus!
UpdatingbasedonVagrantfilechangesIfwemakechangestoourVagrantfile,thesechangeswon’tapplyuntilwenextshutdownandpoweronourvirtualmachine.Asthisisn’tveryconvenient,thereisahandyreloadcommandthatwillshutdownthemachine,reloaditsconfigurationbasedontheVagrantfileasitcurrentlyis,andbootitupagain:
vagrantreload
Runningthiscommandyieldsthefollowingresult:
ConnectingtothevirtualmachineoverSSHIfwerunthevagrantsshcommand,VagrantwillthenconnecttothevirtualmachineoverSSH.Alternatively,wecanSSHtolocalhostwithport2222,andthiswilltunnelintothevirtualmachine,usingthedefaultforwardedSSHport.
IfwerunVagrantonaWindowsmachine,wewon’thaveabuilt-inSSHclient.WecanuseaclientsuchasPuTTYtoconnecttoVagrant.PuTTYcanbedownloadedfromhttp://www.chiark.greenend.org.uk/~sgtatham/putty/.MoreinformationonhowtoconfigurePuTTYtoworkwithVagrantisavailableontheVagrantwebsite(http://docs-v1.vagrantup.com/v1/docs/getting-started/ssh.html).
ManagingintegrationbetweenhostandguestmachinesWithoutanyformofintegrationbetweenthehostmachineandtheguest,wewouldsimplyhaveabarebonesvirtualserverrunningontopofourownoperatingsystem,whichisnotparticularlyuseful.Weneedourownmachinetobecapableofintegratingtightlywiththeguest(virtualmachine).
PortforwardingAlthoughthevirtualmachineisrunningonourownmachine,becauseofvirtualization,itactsandbehaveslikeacompletelydifferentmachine.Sometimes,thisiswhatwewant;however,theremightbetimeswewanttohavethevirtualmachinebehavealmostasanextensionofourownmachine.Onewaytodothisisthroughportforwarding,wherewecantunnelaportfromthevirtualmachinetoaportonthehostmachine.If,forexample,wehaveawebserverrunningonourownmachine,weobviouslydon’twanttomapthewebserverportfromVagrantontothesameport;otherwise,therewouldbeaconflict.Instead,wecanmapittoanotherport.Ifwemapthewebserverportonthevirtualmachinetoport8888onthehost,thennavigatingtohttp://localhost:8888onourownmachinewouldshowusthewebservicewerunontheguest,despitethefactthatthelocalhostreferstoourhostmachine.
TheportforwardingisdonevialinesintheVagrantfilefile;wesimplyprovidetheguestandhostportswewishtomap:
config.vm.network:forwarded_port,guest:80,host:8888
IfwehaveotherVagrantmanagedvirtualmachinesonourcomputer,whichwewishtorunsimultaneously,wecanenableauto_correctonspecificports.Thisway,ifaconflictisfound(forexample,twovirtualmachinestryingtomaptothesameport),onevirtualmachinewilltryadifferentportinstead:
,auto_correct:true
Portsbelowacertainrangeneedelevatedorrootprivilegesonthehostmachine,soyoumaybeaskedforyouradministrativepassword.
SyncedfoldersSyncedfoldersallowustoshareafolderbetweenthehostandtheguest.Bydefault,VagrantsharesthefolderthatcontainstheVagrantproject/vagrantonthevirtualmachine.WecanusethefollowingcommandinourVagrantfiletosyncmorefoldersifwewish:
config.vm.synced_folder"/Users/michael/assets/""/var/www/assets"
ThefirstparameteristhepathtothefolderonourmachineandthesecondisthemountpointontheVM.Ifweusearelativepathonourmachine,itwouldberelativetotheprojectfolder.
Ifwewanttooverridethedefaultsyncedfolder,wecandothistoo:
config.vm.synced_folder".","/var/another/folder"
TheNetworkFileSystem(NFS)cangiveusbetterperformancewithsyncedfoldersthanthedefaultsettings.Thiswon’thaveanyeffectonWindowshosts,andonLinux/OSX,hostswillrequirerootprivileges.WecanenableNFSonapersyncedfolderbasisbyaddingthefollowingcommandtotheprecedingline:
,type:"nfs"
NetworkingBydefault,ourVagrantvirtualmachinesareonlyaccessiblefromthemachineswerunVagranton,andothermachinesinournetworkwon’tbeabletoaccessthem.Ifwemapportstoourhost,thenwecansharetheservicesrunningonthevirtualmachinewithourcolleagueswithinournetwork.IfwewanttoallowourcolleaguestoaccessourVagrantmanagedvirtualmachinesdirectly,wecanattachthevirtualmachinetoourinternalnetwork,andVirtualBoxwillbridgethenetworkbetweenourmachineandthevirtualmachine,andtheinternalnetworkbetweenourmachineandtherestofthemachinesinourhomeoroffice.
config.vm.network"private_network",ip:"10.11.100.200"
ThisapproachisalsousefulwhenwantingtohavemultipleVagrantprojectsrunningatthesametime;iftheyarewebprojects,theycanallexposeport80,butondifferentIPaddresses,andifwewant,wecanmapthesetothehostnamesinourhostsfile.
NoteThehostsfileisafileonacomputerthatmapsadomainnametoanIPaddress.ThiscanbeusedtopreventthecomputerfromhavingtolookuptheIPaddressforadomainandisusefulforlocallyhostedsites,aswecanmanuallylinktheIPaddresstoadomainname,justforourlocalmachine.OnOSXandLinux,thehostsfileisstoredas/etc/hosts,andonWindowsitisstoredasC:\Windows\System32\Drivers\etc\hosts.
Ifwewanttoshareaccesstoourvirtualmachineordemosomethingrunningonit,wecanuseVagrantSharethroughVagrantCloud,whichwewilldiscussinChapter9,HashiCorpAtlas.
ItisalsopossibletohavetheIPaddressassignedviaDHCP(typically,thiswillmeanthatyournetwork’srouterwillassignitanIPaddress):
config.vm.network"private_network",type:"dhcp"
AutorunningcommandsOneofthekeyconceptswithinVagrantisprovisioning.Thisinvolvesturningabasicvirtualmachinewithabaseoperatingsystemintoaserverthatisreadytorunforyourproject,meetingyourrequirements.Togofromthebaseoperatingsystemtoafullyfledgedmachine,weneedtouseaprovisioningtooltoinstallthesoftwareandconfigurethemachine.ThereareanumberofkeyprovisioningoptionswithinVagrant:
ShellPuppetAnsibleChef
Puppet,Ansible,andChefareallthird-partytoolsthatVagrantsupportsoutofthebox,andprovidespecificlanguagestoconfigureserversinanagnosticwaythatcanbeusedfordifferentoperatingsystems.Thenextthreechapterswilldiscussthesetoolsinmoredetail.Vagrantalsosupportssomeotherprovisioningtools,includingSalt,Docker,andCFEngine.
SSHprovisioninginvolvesrunningaseriesofcommandsonthevirtualmachineoverSSHwhenthemachineisfirstsetup.
TherearetwokeywaysinwhichwecanuseSSHprovisioning.WecaneitherdirectlyrunacommandfromourVagrantfileorwecanrunthecontentsofascript.
ThefollowinglineinourVagrantfilewillruntheinlinecommandprovided:
config.vm.provision"shell",inline:"sudoapt-getupdate"
Alternatively,wecantellVagranttorunaparticularshellscript(thelocationofthescriptspecifiedisrelativetoourprojectroot,thatis,/vagrant):
config.vm.provision"shell",path:"provision.sh"
Thisshellscriptcouldcontainallofthecommandsweneedtoconvertabaseboxintoabox,whichsupportsourprojectandapplication,perhapsinstallingwebanddatabaseservers.
ManagingVagrantboxesWecanmanageVagrantboxesusingthevagrantboxcommand.Let’srunthiscommandwiththehelpflag(--help)andseewhatsubcommandsareavailable:
vagrantbox--help
Runningthiscommandgivesthefollowingresult:
Therearesixavailablebox-relatedsubcommands.Witheachofthese,wecanprovidethe--helpflagtoseewhatadditionalargumentsareavailable.Theavailablebox-relatedsubcommandsare:
add:Thiscommandaddsanewboxlist:Thiscommandlistsallboxesinstalledoutdated:Thiscommandcheckswhetheranyboxeshaveupdatesavailableremove:Thiscommandremovesaboxfromthehostrepackage:ThiscommandconvertsaVagrantenvironmentintoadistributableboxupdate:ThiscommandwillupdatetheboxbeingusedbythecurrentrunningVagrantenvironment
AddingVagrantboxesTheaddsubcommandallowsustoaddanewbox.Ittakesasingleargumentandanumberofoptionalflags.Theargumentisaname,URL,orpathtoaboxfile.Ifanameisprovided,VagrantwilldownloadtheboxfromVagrantCloud.IfweprovideaURLorpathtoaboxstoredelsewhere,weneedtogiveVagrantanametouse.Thisisprovidedwiththe--nameoptionalflag.
Someotheroptionalflagsthatmightbeusefulinclude:--force,whichwilltellVagranttoremoveapre-existingboxwiththesamename;--clean,whichwilltellVagranttocleananytemporarydownloadedfiles;and--provider,whichallowsustospecifyanotherprovidertobackthebox(thedefaultproviderbeingVirtualBox,however,thereareprovidersavailableforVagrant,includingVMwareandAmazonEC2).
Thefollowingcommandwilladdanewpacktbox,andifanexistingoneisfound,itwilloverrideit:
vagrantboxadd––forcepackthttp://our-server.vagrant/packt.box
Theprocessofaddingaboxmaytakeawhile,asmostVagrantboxeswillbeatleast200MBbig.Oncedownloaded,theboxwillbeextractedandavailableforustouseinourVagrantprojects,asweobservedwhenwestartedourfirstprojectearlierinthechapter.
ListingVagrantboxesThelistsubcommandwilllisttheboxesinstalledwithinVagrant,alongwiththeproviderthatbacksthebox:
vagrantboxlist
Runningthiscommandgivesthefollowingoutput:
CheckingforupdatesBoxes,whichareprovidedbyVagrantCloud,mayberegularlyupdated;wecanusetheoutdatedsubcommandtoseewhetherthereareupdatesavailable:
RemovingVagrantboxesWecanremovetheboxwiththeremovesubcommand.Weneedtoprovidethenameoftheboxtoberemoved.Optionally,wecanalsospecifytheproviderandtheversionoftheboxtoberemovedwiththe--providerand--box-versionflags,respectively.Thefollowingexamplewillremoveourprecise64boxforVirtualBox:
vagrantboxremovehashicorp/precise64--providervirtualbox
Runningthiscommandgivesthefollowingoutput:
RepackagingaVagrantboxTherepackagesubcommandletsusconvertaVagrantenvironmentcompletewithanycustomizationswehavemadetoit,suchassoftwarewehaveinstalledonit,intoaboxthatwecanreuseanddistributetoothers.WewillusethiscommandinChapter8,CreatingYourOwnBox.
Updatingthecurrentenvironment’sboxWecanusetheupdatesubcommandtoupdatetheboxinuseonthecurrentVagrantenvironment:
vagrantboxupdate
Alternatively,wecanupdateaspecificbox,whichisn’ttiedtothecurrentenvironment,usingthe--boxflagtoprovidethenameofthebox(andthe--provideroptiontooifwewish).
ToomanyVagrants!OncewestartusingVagrantonarangeofprojects,thelackofaGUIcanmakeiteasytolosetrackofwhichprojectsarerunningorsuspendedonyourmachine.Thisisespeciallyannoyingwhenyouwanttobootupanewproject,butanexistingVagrantprojectiseithercausingaconflictorconsumingtoomanyresourcesonyourmachine.Thankfully,thereisnowacommandtolistallactiveVagrantenvironmentsonyourhost,forexample,
ThiscommandliststheIDs,names,providers,andstatesofourVagrantprojectsaswellasthedirectorytheyarerunningin:
WecanappendtheIDtotheendofthevagrantcommandtorunthecommandagainstthatmachine,withouthavingtogointothatfolder,forexample:
vagrantsuspend77e5115
SummaryInthischapter,wecreatedprojectswithVagrant,importedabaseboxtouse,andbootedourVagrantenvironment.WealsolookedatthecommandsneededtomanagetheseboxesandtheVagrantvirtualmachines.WelookedathowwecanconfigureourVagrantenvironmentwithnetworking,syncedfolders,andforwardedports,andhowtoprovisionsoftwareonourvirtualmachinewithSSHcommands.WhenitbecomesaproblemtohavemultipleVagrantprojectsrunning,wenowknowhowtolocatetheserunningprojectswiththeglobal-statuscommand.
Inthenextchapter,wewilltakealookathowtousePuppet,oneoftheprovisioningtoolssupportedbyVagrant.Wewillcoverinstallingandconfiguringservices,managingfilesandfolders,runningcommands,andmanagingusersandscheduledtasks.
Chapter3.ProvisioningwithPuppetVagrantisaverypowerfultoolprimarilybecauseofthefollowingkeyconceptsitcanmanageforus:
VirtualizationProvisioningBoxdistributionSharing
InChapter1,GettingStartedwithVagrantandChapter2,ManagingVagrantBoxesandProjects,welearnedtouseVagranttomanagevirtualmachinesforus.Whilethisisuseful,atthisstage,thesevirtualmachinesaredumb;theyhaveverylittlesoftwareinstalledforustouse,andtheyarecertainlynotconfiguredforourprojects.
TherearetwoapproacheswecanusetosetupaVagrant-managedvirtualmachinewithallthesoftwarerequiredforaproject:
UseabaseboxthatispreconfiguredwiththesoftwareordevelopmentstackthatwerequireProvisiontheexactsoftwareandconfigurationthatwerequireusingaprovisioningtool
Preconfiguredbaseboxesareusefulandhavetheirplace.IfwewerealwaysusingaspecificconfigurationorwewerecreatingaVagrantenvironmentforanopensourceprojectwewerereleasing,aconfiguredboxmightbethebestoption.Inthatinstance,aconfiguredbaseboxwillquicklygetusersupandrunningontheproject.Thedownsideisthatitisn’teasytochangetheconfigurationastheneedsoftheprojectchange,andcertainelementssuchascronjobsandbackgroundworkerswouldstillneedtobeconfiguredseparately.
Provisioning,however,automatestheprocessofturningabasemachineintoonethatisconfiguredforusewithaspecificproject.
Inthischapter,wewillquicklytakealookatthebasicsofPuppet,oneofthevariousprovisioningoptionsavailablewithinVagrant.Wewon’tlookatitwithinaVagrantcontextjustyet;wewillsimplytakealookathowaPuppetworks,andhowwecanuseit.InChapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef,wewilltakealookathowtoconnectwhatwewilllearninthischapterwithVagrantitself.Inthischapter,wewilllearnthefollowingtopics:
HowPuppetworksThebasicsbehindPuppetmodulesandmanifestsHowtousePuppettoperformthefollowingtasks:
InstallsoftwareManagefilesandfolderswithinthefilesystemManagecronjobsRuncommands
Manageusersandgroups
CreatingconfigurableclassesHowtousethird-partyPuppetmodulesandPuppetForgeHowtomanuallyrunPuppettoprovisionamachine
Puppetitselfisalargetopicandthesubjectofseveralbooks.ForamoredetailedlookatPuppet,PacktPublishinghassometitlesdedicatedtoit:
Puppet2.7Cookbook,JohnArundel(http://www.packtpub.com/puppet-2-7-for-reliable-secure-systems-cloud-computing-cookbook/book)Puppet3:BeginnersGuide,JohnArundel(http://www.packtpub.com/puppet-3-beginners-guide/book)
ProvisioningWithinthiscontext,provisioningistheprocessofsettingupavirtualmachinesothatitcanbeusedforaspecificpurposeorproject.Typically,thisinvolvesinstallingsoftware,configuringthesoftware,managingservicesrunningonthemachine,andevensettingupusersandgroupsonthemachine.
Foraweb-basedsoftwareproject,provisioningwilllikelyentailtheinstallationofawebserver,aprogramminglanguage,andadatabasesystem.Configurationchangeswillbeneededtosetupadatabaseonthedatabasesystemandtoallowthewebservertowritetospecificfolders(todealwithuseruploads).
Withoutthisprovisioningprocess,wewouldhaveanalmostvanillainstallofanoperatingsystem,whichcontainsasyncedcopyofourprojectfolder;thisvanillainstallwouldn’tbeusableasadevelopmentenvironmentforourproject.Provisioningtakesustothenextlevelandgivesusafullyworkingenvironmentforourproject.
PuppetPuppetisaprovisioningtoolthatwecanusetosetupaserverforuseforaproject.TheconfigurationthatdetermineshowtheserverneedstobesetupcanbestoredwithinourVagrantprojectandcanbesharedwithteammatesthroughaversioncontrol,ensuringeveryonegetsanup-to-datecopyoftherequireddevelopmentenvironment.
Informationabouthowaservershouldbeconfigured,thatis,itssoftware,files,users,andgroups,iswrittenintofilesknownasthePuppetmanifests.ThesemanifestsarewrittenusingPuppet’sownlanguage,whichisaRubydomain-specificlanguage.Puppettakesthisinformationandcompilesitintoacatalogthatisspecificfortheoperatingsystemitisbeingappliedto.Thecatalogisthenappliedtothemachine.
Forourpurposes,wewillusePuppetinstandalonemode(thisisalsohowVagrantusesit).Standalonemodemeansthateverythingrunsfromonemachine.Puppetalsohasclient-servercapabilities,whereyoucandefinethePuppetmanifestsforalltheserversinyourinfrastructure,onacentralhost,anditkeepsyourindividualserversattherequiredlevelofconfiguration.
Puppetisidempotent,whichmeansrunningPuppetonamachinemultipletimeshasthesameeffectasrunningitonlyonce.Ineffect,Puppetensuresthatconditionsaremet,andiftheyarenot,itwillperformactionstoensurethattheyaremet,forexample,PuppetwouldinstallNginxifitwasn’talreadyinstalled.Ifitwasalreadyinstalled,itwoulddonothing.ThismeanswecanreprovisionwithPuppetmanytimeswithoutanydetrimentaleffect.ThisisusefulaswecanuseittokeeptheserverinsyncwithourPuppetmanifestsiftheyweretochange.
CreatingmodulesandmanifestswithPuppetPuppetismadeupofamanifestfileandanumberofmodules(whichalsocontainmanifestsandotherresources).Thedefaultmanifestspecifieswhichmodulesaretobeused,anddependingonthemodule,providescustomizationoptionsforit(forexample,thePuppetmoduleforsupervisord(http://supervisord.org/),aprocesscontrolsystem,allowsustospecifyanynumberofprocessesthatshouldbemanagedusingsupervisordthroughthemoduleitself).
ModulesmakeuseofresourceswithinPuppettocontrolandconfigurethemachine,andthesemodulescanbeimportedtoruninaspecificsequence,throughstages.
PuppetclassesPuppetmodulestypicallyconsistofclasses,which,inturn,utilizeanumberofresourcetypes(inthisexample,thepackageresourcetype,toinstallasoftwarepackage)toachieveaspecificrequirementforourserver.Iteffectivelyallowsustobundleanumberoftheseresourcetypesinaway,whichmeanswecansimplyincludetheclassbyitsname,andhavealloftheinstructionsexecutedfromwithinit.
Aclassinitsmostbasicformisstructuredasfollows:
classnginx{
package{"nginx":
ensure=>present,
require=>Exec['apt-getupdate']
}
}
ForitsmostbasicusewithinVagrant,classessuchasthesewillbesavedasdefault.ppwithinthemodules/nginx/manifests/folder.Theclasscancontainmanyresourcetypestoachieveadesiredgoal(forinstance,installingtheApachepackageisn’tthesameaspreparingthewebserverfullyforaproject,relatedtaskscanbebundledintothesameclass).
DefaultPuppetmanifestsForagivenproject,Puppetmodulesaretypicallyalllocatedinaspecificmodulesdirectory.Manymodulescanbecustomizedwhentheyarerun,anexamplebeingthesupervisordmodule;itsimplyprovidesthestructureforustocustomizeforeachprocesswewantittomanage.
Becauseofthis,weneedtohaveadefaultPuppetmanifestthatincludesalistofmodulestoberunandanyconfigurationsforthem.BecausePuppetisawareofourmodulefolderlocationwhenwerunit(andwhenitisrunthroughVagrant),wejustlistthemodulestobeincludedandrun.
Abasicmanifestthatwillincludeandrunthenginxclasswewroteearlierwouldbeasfollows:
import"nginx"
includenginx
Imentionedthesupervisormodule(https://github.com/plathrop/puppet-module-supervisor)afewtimesasamodulethatisdesignedtobeusedformultipledifferentthings,whichcanbecustomizedbythedeveloperusingit.
NoteSupervisordisthenameofthesoftware,however,thePuppetmodulewearegoingtousetomanagesupervisordiscalledsupervisor(no“d”)—sowatchoutforthat!
Supervisordisatoolthatmaintainsanumberofrunningprocesses,forexample,ifyouhaveabackgroundworkerinawebapplicationtoresizeimages,thesupervisormightberesponsibleforkeepingfiveworkersrunningatanyoneinstance,respawningthemwhenonehasfinished.ThefollowingisanexampleofhowthismodulewouldbeusedinadefaultPuppetmanifest:
supervisor::service{
'resize_images':
ensure=>present,
command=>'/usr/bin/php/vagrant/app/consoleimg:resize',
user=>'root',
group=>'root',
autorestart=>true,
startsecs=>0,
num_procs=>5,
require=>[Package['php5-cli'],Package['beanstalkd']];
}
supervisor::service{
email':
ensure=>present,
command=>'/usr/bin/php/vagrant/app/consoleemail',
user=>'root',
group=>'root',
autorestart=>true,
startsecs=>0,
num_procs=>5,
require=>[Package['php5-cli'],Package['beanstalkd']];
}
Here,weareinstructingPuppettousethesupervisordmoduletwicetosetupandmanagetwoworkersforus.Foreachoftheworkers,wehaveasetoffiveprocessestoberun,andwehavesettheuserandgrouptorunthem.WehavedefinedPHP’scommand-lineinterfaceandthebeanstalkdworkerqueueasrequirementsfortheworkers.ThisillustratesthepowerthatPuppetmoduleshave.
ResourcesPuppetprovidesarangeofresourcetypesthatwecanutilizetocreateourconfigurationfiles.Theseresourcetypesaretranslatedandcompileddependingontheoperatingsystembeingused.Forexample,ifweweretousethepackageresourcetypetoinstallsomesoftware,thiswoulduseapt-getonUbuntuandYumonFedoraoperatingsystems.A
smallnumberofresourcetypesareoperatingsystemspecific,forexamplethescheduled_taskresourcetypeisdesignedspecificallyforWindows,andthecrontypeisdesignedforLinuxandUnix-basedsystems.
Resourcetypesavailableinclude:
Cron:ThisresourcetypeisusedtomanagecronjobsonLinux-andUnix-basedsystemsExec:Thisresourcetypeisusedtoruncommandsattheterminal/commandpromptFile:ThisresourcetypeisusedtomanageandmanipulatefilesandfoldersonthefilesystemGroup:ThisresourcetypeisusedtomanageusergroupsPackage:ThisresourcetypeisusedtoinstallsoftwareService:ThisresourcetypeisusedtomanagerunningservicesonthemachineUser:Thisresourcetypeisusedtomanageuseraccountsonthemachine
Whenresourcetypesareuseddirectly(forexample,weusethePackageresourcetypetoinstallsomesoftware),theyareusedinlowercase(package).However,whenwerefertoaresourcetypewehaveused,forexample,asarequirementforanotherPuppetaction,wereferencethemwithaleadingcapitalletter(Package).
Anexampleofthisisasfollows:
package{"nginx":
ensure=>present,
require=>Exec['apt-getupdate']
}
WetellPuppettoinstallthenginxpackage(lowercase“p”forpackage),butwhenwespecifytherequirementofapreviouslyexecutedexeccommand,weusealeadingcapitalletter.TheoptionswithinthisinstructionforPuppet(ensureandrequirekeywords)arecalledparameters.
AfulllistofresourcetypesisavailableonthePuppetwebsiteathttp://docs.puppetlabs.com/references/latest/type.html.
Whenusingaresourcetype,anameisprovided(intheprecedinginstance,thisisnginx),thisisoftendualpurpose,servingbothasawayforustoreferencetheaction(inthiscase,thepackagebeinginstalled)andalsoasaninstruction(inthiscase,whatpackagePuppetneedstoinstall).WhenitcomestotheExecresourcetype,thenameisthecommandwewishtorun.Bydefault,weneedtoprovidethefullpathtothecommandthatwerun.Wecanavoidthisbyprovidingthepathfromwhichthecommandshouldberunasaparameter.
Resourcerequirements
CertainthingsthatwedowithPuppetwillrequireotheractionstohavebeenperformedfirst.Thesecanbedefinedusingtherequireparameter,andwecanspecifymultiplerequirements.
IfweneedtorunorinstallsomethingafterboththeMySQLServerandtheMySQLclient
packageshavebeeninstalled,wewillusetherequireparametertodefinethemasfollows:
require=>[Package['mysql-client'],Package['mysql-server']]
ThisdefinesanarrayofmultiplerequirementsasadependencyforourPuppetcode.
ResourceexecutionorderingSometimes,weneedtorunspecificblocksofthePuppetcodebeforeotherblocks.Inmostcases,wecanusetherequire,notify,andsubscribeparameterstogetaroundthisproblem.
Thenotify,subscribe,andrefreshonlyparametersSometimes,wewanttohaveaPuppetcommandrunmultipletimeswhenothercommandshavefinished.Oneexampleistorestartthenginxservice.Wewillperformthefollowingsteps:
1. Importanewconfigurationfile.2. Addnewvirtualhosts.
Wecanusethenotifyparametertoinstructonecommandtotriggeranothertoberun.Ineffect,thisnotifiesthenextcommandtotellitthattherehavebeenchangesmadeelsewhere,whichrequiresthatcommandtonowrun.
Inthefollowingexample,werequireaPuppetmanagedconfigurationfiletobecopiedtoourPuppetmanagedmachine.ThecoderequiresNginxtobeinstalledbeforeitisrun,andafterthefilehasbeencopiedacross,itwillnotifythenginxservicetoberestarted.Importantly,thisnotificationwillberuneachtimethefilechanges,butwon’tbetriggeredwhenitrunswherethefileisunchanged:
file{'/etc/nginx/sites-available/default':
source=>"puppet:///modules/nginx/default",
owner=>'root',
group=>'root',
notify=>Service['nginx'],
require=>Package['nginx']
}
Thiscanbealsobeachievedusingthesubscribeandrefreshonlyparameters,whichworkintheoppositewaytonotify.Thesubscribeparameterinstructsthecommandtoruneverytimeanyofthecommandsinthesubscribeoptionhavebeenrun.
Therefreshonlyparameter,whensettotrue,instructsthecommandtoonlyrunwhenoneofthecommandsitsubscribestohasrun(leavingthisoutwouldmeanthecommandisalsoruninitsownright):
service{"nginx":
refreshonly=>false,
subscribe=>File['/etc/nginx/sites-available/default'],
}
Here,thecommandtoreloadNginxwillonlyberunwhenthenewconfigurationfilehasbeenloaded.Wecan,ofcourse,extendthesubscribeparametertocontainotherthingssuchasmodulesandotherconfigurations,asdiscussedearlier.
TipOnlyservice,exec,andmountresourcetypescanberefreshed.
ExecutingresourcesinstagesWhererequire,notify,andsubscribearenotsuitableforourusecase,wecanusestages.Puppethasadefaultstage,withinwhichallcommandsrun.Wecancreateourown
stages,whichrunbeforeorafterthisstagethatallowustoforcecommandstoberuninspecificorders.
WecandefinestageswithinourdefaultPuppetmanifestandtheninstructPuppettoruncertainclassesfromwithinthatstage.If,forexample,wewantedtorunourNginxclassbeforeanythingelse,wecancreateastagetorunfirst,andputtheNginxclasswithinthatstageasfollows:
stage{'first':before=>Stage[main]}
class{'nginx':stage=>first}
Thiscreatesastagecalledfirst,andanythingassignedtothisstagewillbeexecutedbeforethedefaultPuppetstage;next,itplacestheNginxclasswithinthatstage.Oncewehaveanamedstage,suchasfirst,wecanthencreateotherstages,whichcanrunbeforethisonetoo.
NoteStagesareusefulwhenyouneedtogrouptheorderingofcertaintasks,however,theycannormallybeavoidedthroughtheproperuseofrequire,notify,andsubscribe,whichshouldbeusedinsteadwherepossible.
InstallingsoftwareLet’ssaywewanttoinstallNginxonourserver.Therearethreetypicalstepsinvolvedinthisprocess:
1. Updatingourpackagemanager.2. Installingthenginxpackage.3. Runningthenginxservice.
Becausethefirststepisdifferent,dependingontheoperatingsystemwearerunning,wewouldwanttoeithermovethisoutofPuppetatalaterstageorlookatusingamoduletoabstractitout,however,wewilluseitwithinPuppetforthetimebeing.Anyoperatingspecificcommands(suchasthese)arewrittenforUbuntu,whichistheoperatingsystemweareusingwithVagrant.IfyouarenotusingUbuntu,theExeccommandshouldberewrittentoupdatethepackagemanageronyoursystem.
NoteThisexampleispurelytoillustratetheprocessofputtingtogetherasimplemodule.TherearemanyexistingmodulesavailableonPuppetForge,whichwewillcometolater.
UpdatingourpackagemanagerInordertoupdateourpackagemanager,weneedtorunacommandontheserver.ThiscanbeachievedusingtheExecresourcewithinPuppet:
exec{'apt-getupdate':
command=>'/usr/bin/apt-getupdate',
timeout=>0
}
ThisinstructsPuppettoruntheapt-getupdatecommand.Wehavesetatimeoutofzerosothatifittakesawhile(andafterafreshinstallationofanoperatingsystemthroughVagrant,itmight),Puppetwillrunitforaslongasittakes,overridingthedefaulttimeout.
NoteThisisn’tthemostelegantofapproaches,especiallywithitbeingoperatingsystemspecificandsubsequentlyarequirementformostofourothercommands.InAppendix,ASampleLEMPStack,wewillbuildaLEMPserverprojectwithVagrantandPuppet,andintheexample,weuseVagrant’sSSHprovisioningoptionstoupdatethepackagemanagerbeforeweinstalltheothersoftware.Mostbaseboxesdon’thaveup-to-datepackagedetailstosavespaceandduetotheirage,soupdatingthepackagemanagerisrequired.
InstallingthenginxpackageWecanusethePackageresourcetoensurethatNginxisinstalled,andifitisn’t,itwillbeinstalledasfollows:
package{"nginx":
ensure=>present,
require=>Exec['apt-getupdate']
}
Here,wetoldPuppettoensurethatthenginxpackageispresent.Weaddedourapt-getupdatecommandasaprerequisite,soweknowthatourpackageswillbeuptodate.
RunningthenginxserviceFinally,tomakesurethatNginxisrunning,weusetheServiceresourcetoensurethatthenginxserviceisrunning.Obviously,thiscan’tberunifNginxisn’tinstalled,sothenginxpackageisaprerequisite:
service{"nginx":
ensure=>running,
require=>Package['nginx']
}
FilemanagementWecanusetheFileresourcewithinPuppettomanagefilesandfolderswithinthefilesystem.Let’stakealookatsomeexamples,whichallowusto:
CopyfilesCreatesymlinksCreatefoldersCreatemultiplefoldersinonego
CopyingafileOnecommonfileoperationwemightwanttoperformwouldbetotakeaconfigurationfilefromourprojectandcopyitintoourvirtualmachine.OneparticularusecasewouldbeanNginxconfigurationfile;wemightwanttodefinesomevirtualhostsandothersettingsinafile,whichwecansharewithourcolleagues.
TipWhilethisworkswellandcangetusupandrunningquickly,therearemodulesouttherethatallowustoconfigureNginxandothertypesofsoftwaredirectlyfromPuppet.Thistypicallyworksbythemoduleofstoringatemplatefile(acopyoftheconfigurationfilewithplaceholdersinit)andthen,insertingdatathatwedefinewithinPuppetintothetemplate,andcopyingthefileontothemachine.However,forthesakeofthisintroductorychapter,wewilljustcopyafileacross.
Thefileresourcetypeallowsustocreatefiles,folders,andsymlinks.Inordertocreateafile(orreplacethecontentsofanexistingfilewithanotherfile),wesimplytellPuppetwhatfilewewanttocreateorreplace(thedestination),thesource(thatis,thefiletobecopiedandputintothedestination),andtheuserandgroupwhoshouldownthefile:
file{'/etc/nginx/sites-available/default':
source=>'puppet://modules/nginx/default',
owner=>'root',
group=>'root',
require=>Package['nginx']
}
AsthisisanNginxconfigurationfile,itisworthensuringthatNginxisalreadyinstalled;otherwise,Nginxwilloverridethiswhenitinstallsthefirsttimeandthiswouldn’tmaketheprocessidempotent.
TipHere’ssomethingtonoteaboutfilelocations:thesourcefileintheprecedingfileresourcecodeisheldwithinaVagrantenvironmentandthePuppetmoduleitself.Wecanprovidetwokindsoffilepaths:eitherthefullpathtothefileonthemachine,whichPuppetisrunningon(ourVagrantenvironment),suchas/vagrant/path/to/defaultorapathrelativetoPuppetmodules.ThesePuppetpathsarestructuredlikethis:puppet:///modules/nginx/default.Thedifferenceyouwillnoteisthatitautomaticallylooksforinthefiles/folderwithinthenginxfolder;wedon’tneedtospecifythat.
CreatingasymlinkIfweomitthesourceparameterandinsteadaddanensureparameter,andsetthattolink,wecancreateasymlink.Atargetisusedtodefinewherethesymlinkshouldpointto,asshowninthefollowingcode:
file{'/var/www/vendor':
ensure=>'link',
target=>'/vagrant/vendor',
require=>Package['nginx']
}
CreatingfoldersSimilartotheprecedingsymlinkcode,thistime,wesimplyneedtosetensuretoadirectory.Thiswillthencreateadirectoryforusasfollows:
file{"/var/www/uploads":
ensure=>"directory",
owner=>"www-data",
group=>"www-data"
mode=>777,
}
Wecanusethemodeparametertosetthepermissionsofthefolder(thisalsocanbeusedforfileswecreateandmanage).
CreatingmultiplefoldersinonegoInmanywebprojects,wemightneedtocreateanumberoffolderswithinourserversorourVagrantvirtualmachines.Inparticular,wemightwanttocreateanumberofcachefoldersfordifferentpartsofourapplication,orwemightwanttocreatesomeuploadfolders.
Inordertodothis,wecansimplycreateanarraythatcontainsallofthefolderswewanttocreate.Wecanthenusethefileresourcetypeandpassthearraytocreatethemall,asfollows:
$cache_directories=[
"/var/www/cache/",
"/var/www/cache/pages",
"/var/www/cache/routes",
"/var/www/cache/templates",
]
file{$cache_directories:
ensure=>"directory",
owner=>"www-data",
group=>"www-data",
mode=>777,
}
CronmanagementThecronresourcetypeletsususePuppettomanagecronjobs,whichweneedtorunonthemachine.Weprovideaname,inthiscase,web_cron,thecommandtorun,theusertorunthecommandas,andthetimesatwhichtorunthecommand,asshowninthefollowingcode:
cron{web_cron:
command=>"/usr/bin/php/vagrant/cron.php",
user=>"root",
hour=>[1-4],
minute=>[0,30],
}
Puppetprovidesuswithdifferentconfigurationoptionstodefinethetimesatwhichacronshouldberun,whichincludesthefollowing:
Hour:Thisvalueisbetween0and23inclusiveMinute:Thisvalueisbetween0and59inclusiveMonth:Thisvalueisbetween1and12inclusiveMonthDay:Thisvalueisbetween1and31inclusiveWeekday:ThisvalueisSunday(7or0)toSaturday(6)
Ifoneoftheseisomittedfromtheconfiguration,thenPuppetrunsitforeachoneoftheavailableoptions(thatis,ifweomitmonth,itwillrunforJanuarythroughtoDecember).Whendefiningthedatesandtimes,wecaneitherprovidearange,forexample,[1-5]orspecifics,suchas[1,2,10,12].
RunningcommandsTheExecresourcetypeallowsustoruncommandsthroughtheterminalonthemachineweareprovisioning.OnecaveatwiththeexeccommandisthatifyoureprovisionwithPuppet,itwillrerunthecommand,whichcanbedamagingdependingonthecommand.WhatwecandowiththeExecresourcetypeissetthecreatesparameter.ThecreatesparametertellsPuppetthatafilewillbecreatedwhenthecommandisrun,andifPuppetfindsthatfile,itknowsthatithasalreadybeenrunandwon’trunitagain.
Takeforexample,thefollowingconfiguration;thiswillusethePHPcomposertooltodownloaddependencies.Thecommanditselfcreatesafilecalledcomposer.lock(wecan,ofcourse,usetheexeccommanditselftocreateafilemanually,perhapsusingthetouchcommand).Becauseofthelockfilethatiscreated,wecanusethecreatesparametertopreventthecommandfrombeingexecutedifithaspreviouslybeenexecutedandhascreatedthelockfile,asshowninthefollowingcode:
exec{"compose":
command=>'/bin/rm-rfv/var/www/repo/vendor/*&&/bin/rm–f
/var/www/repo/composer.lock&&/usr/bin/curl–s
http://getcomposer.org/installer|/usr/bin/php&&cd
/var/www/repo&&/usr/bin/php/var/www/repo/composer.
pharinstall',
require=>[Package['curl'],Package['git-core']],
creates=>"/var/www/repo/composer.lock",
timeout=>0
}
ManagingusersandgroupsTheuserandgroupresourcetypesletuscreateandmanageusersandgroups.TherearedifferencesbetweendifferentoperatingsystemsastowhatPuppetcandowiththeusersandgroupsandhowthisworks.ThecodeinthefollowingsectionistestedonUbuntu,Linux.MoreinformationonthedifferencesforusersandgroupsondifferentplatformscanbefoundonthePuppetwebsiteathttp://docs.puppetlabs.com/references/latest/type.html#user.
CreatinggroupsThesimplestwaytocreateagroupissimplytosettheensureparametertopresent:
group{"wheel":
ensure=>"present",
}
CreatingusersTocreateauser,thebasicinformationweshouldprovideisasfollows:
TheusernameThefactthatwewanttheusertoexist(ensure=>present)Thegroup(gid)theusershouldbepartofTheshelltousefortheuserThehomedirectoryfortheuserIfwewantPuppettomanagethehomedirectoryfortheuser,inthiscase,itwillcreatethefolderforusifitdoesnotexistThepasswordfortheuserTherequirementsthatweneedthewheelgroupinplacefirst
Thecodethatwillthencreateouruserisasfollows:
user{"developer":
ensure=>"present",
gid=>"wheel",
shell=>"/bin/bash",
home=>"/home/developer",
managehome=>true,
password=>"passwordtest",
require=>Group["wheel"]
}
UpdatingthesudoersfileIt’sallwellandgoodbeingabletocreateusersandgroupsonourmachine,however,onethingthatwecan’tdousingtheuserandgroupresourcetypesisdefineauserorgroupashavingelevatedprivileges,unlesswemaketheuserapartoftherootgroup.
Wecanuseanexeccommandtopushsometexttotheendofoursudoersfile;thetextweneedtopushjusttellsthefilethatwewanttogivethewheelgroupthesudoprivileges,asshowninthefollowingcode:
exec{"/bin/echo\"%wheelALL=(ALL)ALL\">>/etc/sudoers":
require=>Group["wheel"]
}
Thiscode,however,willcontinuallyaddthislinetothefileeachtimeitisrun,whichwedon’twant,however,aswelearnedearlier,wecaninstructtheexecresourcestoonlyrunatcertaintimes.Thankstosubscribeandrefreshonly:
exec{"/bin/echo\"%wheelALL=(ALL)ALL\">>/etc/sudoers":
subscribe=>Group["wheel"],
refreshonly=>true
}
Thisstillisn’tideal,asifwedecidetochangethewheelgroupthenthiswouldbererun,soideally,wemightkeepthesudoersfilewithinourPuppetconfigurationinsteadandusePuppettomanagethechangestoit.
CreatingconfigurableclassesOnelimitationthatourentirePuppetcodehassofarinthischapteristhatwiththeexceptionofthecontentsofsomefiles,theconfigurationisallfixed.IfwewanttoreusesomeofthePuppetcodeonanotherproject,wemightneedtochangethingssuchasvariablenames,pathstofiles,orotherproject-orenvironment-specificproperties.
Tomakeourcodemoreflexible,wecanputthecodeintoaclass,anduseclassparameterstodynamicallyinjectvariablesintotheclass.
Aclassis,atitssimplestlevel,amethodofgroupingrelatedcodetogether;however,wecanusethemtobuildreusableandconfigurablemodules.IfwetakethecomposerExecresourceillustratedearlier,wecanstarttomakethatreusablebyputtingitintoaclass:
classcomposer{
exec{"compose":
command=>'/bin/rm-rfv/var/www/repo/vendor/*&&/bin/rm–f
/var/www/repo/composer.lock&&/usr/bin/curl–s
http://getcomposer.org/installer|/usr/bin/php&&cd/var/www/repo&&
/usr/bin/php/var/www/repo/composer.pharinstall',
require=>[Package['curl'],Package['git-core']],
creates=>"/var/www/repo/composer.lock",
timeout=>0
}
}
Whilewecannowmoreeasilypullthisintoanotherproject,wearelockeddownintermsofthelocationofthecomposerfileandalsootherparametersthatmightberequired.Wealsorequiretwopackages:wewouldeitherrequirethatthedeveloperaddstheseelsewheretotheirPuppetcode,orwewouldincludethemhere,however,includingthemherewouldconflictwithothermodulesandreducesflexibility.Classparametersletuspassinformationtoaclasswhenitisused;thisinformationcanbeusedtocontrolthecodewithintheclassandalsoconfigurepartsoftheclass.
ForourComposerclass,wemightwanttoletthedeveloperusingitdecidewhetherthedependenciesareinstalledbythemoduleornot,andalsoprovidepathstobeusedbythemodule.Classparametersaredefinedinbracketsimmediatelyaftertheclassnameandcanhavedefaultvalues,soiftheyareomitted,theirdefaultsareused.
Wecanthenusecontrolstatementstodecidewhetherthedependenciesshouldbeinstalled,andwecanpullinthecontentsofavariableusing${variable}:
classcomposer($install_deps=true,$path='/var/www/repo/',
$composer_home='/var/www/'){
if($install_deps==true){
package{"curl":
ensure=>present
}
package{"git-core":
ensure=>present
}
}
exec{"compose":
command=>"/bin/rm-rfv${path}vendor/*&&cd${path}&&
/usr/bin/curl-shttp://getcomposer.org/installer|/usr/bin/php&&
COMPOSER_HOME=\"${composer_home}\"/usr/bin/php${path}composer.phar
install",
require=>[Package['curl'],Package['git-core'],Package['php5-
cli']],
creates=>"${path}composer.lock",
timeout=>0
}
}
Now,whenwewanttousethisclass,wepassthevaluesalongwiththesevariablenames.BecauseofthewayPuppetworks,theorderingoftheparametersdoesn’tmater;theyarepassedassociativelywiththeircorrespondingvariablenames,asshowninthefollowingcode:
class{
'composer':
install_deps=>true
}
PuppetmodulesTherearemanyexisting,well-written,reusablePuppetmodulesfreelyavailabletouse.PuppetForgeisacollectionofmodules,whichisavailableathttp://forge.puppetlabs.com/.Itisalwaysworthcheckingwhetherthereisanexistingmodulethatsolvesyourproblembeforewritingyourown.
UsingPuppettoprovisionserversWearegoingtotakealookathowtousePuppetwithVagrantinChapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef,however,Puppetcanalsoberunindependently.IfPuppetisinstalled(itwillbeonmostVagrantbaseboxes,butifyouwanttorunitonanothermachine,itmightnotbe,soinstallitfirst),youcanusetheapplysubcommand,passingwithitthelocationofthemodulesfolderandthedefaultmanifesttoapply,asfollows:
puppetapply--modulepath=/home/michael/provision/modules
/home/michael/provision/manifests/default.pp
SummaryInthischapter,wehadawhirlwindtourofPuppetandexploredthevariouswaysinwhichwecoulduseittoprovisionaserverforourprojects.WeinstalledsoftwarewiththePackageresource,managedcronjobswiththeCronresource,managedusersandgroupswiththeUserandGroupresources,andrancommandswiththeExecresource.TomanageexecutionorderanddependencyrelationshipswithPuppet,welookedatusingRequire,Subscribe,Notify,andRefreshonly.Welookedathowmodules,classes,andstagesworkaswellashowtouseclassparameterstoconfigurereusablePuppetcode.Finally,welookedathowtousePuppettoprovisionamachine.
Inthenextchapter,wewilltakealookatAnsible,anotherprovisioningtoolthathassupportbuiltintoVagrant.
Chapter4.UsingAnsibleAnsibleisanotherprovisioningtoolsupportedbyVagrantthatmakesiteasyforustotakeabaseoperatingsysteminstallationandturnitintoafull-fledgedserverthatsuitstheneedsofourproject.
Inthischapter,wewillquicklytakealookatthebasicsofAnsible.Wewon’tlookatitwithinaVagrantcontextjustyet;wewillsimplytakealookathowAnsibleworks,andhowwecanuseit.InChapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef,wewilltakealookathowtoconnectwhatwewilllearninthischapterwithVagrantitself.Inthischapter,wewilllearnthefollowingtopics:
HowAnsibleworksHowtouseAnsibletoperformthefollowingtasks:
InstallingsoftwareManagingfilesandfolderswithinthefilesystemManagingcronjobsRunningcommandsManagingusersandgroups
Howtousethird-partyAnsiblerolesHowtomanuallyrunAnsibletoprovisionamachine
Ansibleitselfisalargetopicandsubjectofseveralbooks.ForamoredetailedlookatAnsible,PacktPublishinghassometitlesdedicatedtoprovisioningwithAnsible:
LearningAnsible:https://www.packtpub.com/networking-and-servers/learning-ansibleAnsibleConfigurationManagement:https://www.packtpub.com/networking-and-servers/ansible-configuration-management
UnderstandingAnsibleAnsibleisanITautomationtoolthatprovidesprovision,orchestration,andconfigurationmanagementfeatures.UnlikewithPuppetandChef,Ansibledoesn’trequireanysoftwaretobepreinstalledontheserver,otherthananSSHservice,astheheavyliftingisdonebyourowncomputerthatconnectstoourAnsible-managedserversandinstructstheserveronhowitneedstochange.
LikePuppetandChef,Ansibleisalsoidempotent.ThismeanseachtimewerunAnsible,itwillonlyperformactionswhereachangeisrequired—soifweinstalltheNginxwebserver,thefirstrunofAnsiblewillinstallitandsubsequentrunswon’tbecauseitknowsNginxisalreadyinstalled.
AnsibleconfigurationiswritteninYamlAin’tMarkupLanguage(YAML),whichmakestheconfigurationeasytoreadandwrite.
Conceptually,Ansibleconfigurationismadeupofplaybooksthataremadeupofplays,whicharemadeupoftasks.Aplaybookistheconfigurationforanentiresystemorenvironment,whichismappedtospecificserversorhoststhroughplays—differentplayscanbeappliedtodifferentgroupsofserversatdifferenttimesfromthesameplaybook.Eachplaycontainsanumberoftasks,which,inturn,makecallstoAnsiblemodules.Inamoreadvancedcontext,wecanmakeuseofroleswithinAnsible(reusablefunctionality)suchthatourplaybooksmightsimplybeamappingofhoststoroles.However,forthepurposesofthischapter,wewillputtasksandmodulecallsdirectlyinourplaybook.
ModuleswithinAnsiblearesimilarincontexttoresourceswithinPuppet.Therearemodulestodealwithmanydifferentkindsofoperationsonaserver,whichwewilldiscussshortly.
InstallingAnsibleBecauseAnsibledoesn’trequireanysoftwaretobeinstalledontheserverside,wecan’tsimplyconnecttoaVagrantvirtualmachineandtryoutAnsiblebecauseitisn’tinstalledonthere!Inordertouseit,bothtotryitout,andalsowhenitcomestointegratingwithVagrant,weneedtoinstallAnsibleonourowncomputer,whichisknownasthecontrolmachine.
AlthoughAnsiblecanbeusedtomanageWindowsServers,itcannotberunfromaWindowscontrolmachine.
PackagesareavailableformanyLinuxdistributions,andAnsiblecanbeinstalledonOSXusingHomebreworPython’spip.Completedetailsofthedifferentoperatingsystemsareavailableonlineathttp://docs.ansible.com/intro_installation.html.
NoteAlthoughwedon’tneedanythinginstalledontheserverbeingmanaged,wedoneedSSHaccesstothemachine,andunlessweinstalladditionalpluginsforAnsible,wewillalsoneedtohavepublicandprivatekeyssetup,sothatwecanconnecttothemachinewewishtomanageoverSSHwithoutapasswordfromourcontrolmachine.
CreatinganinventoryWhenwerunAnsibletoprovisionorconfigureamachine,Ansibletakesthehostswewanttoapplytheconfigurationto,fromourplaybooks.Itthenlooksupthesemachinesinitsinventory,whichspecifytheaddressesandconnectiondetailsforthesemachines,sothatAnsiblecanconnecttotheminordertochecktheirstatusandruntheprovisioningtasks.
Ataminimum,theinventoryneedstocontainanameandanIPaddressforeachserverthatwewantAnsibletomanage.However,thereareadditionalconfigurationswecanprovide,forexample,settingtheusertoconnectas,thepasswordtouse(whichrequiresadditionalconfiguration),theporttoconnectthrough,andifweneedtotunneltotheserverthroughanother.Anexampleofcreatinganinventoryisasfollows:
defaultansible_ssh_host=192.168.100.123
AlthoughwearelookingatAnsibleoutsidethecontextofVagrant,westillmightwanttouseAnsible,independently,toconnecttoandconfigureaVagrant-managedvirtualmachinesothatwecantestitinisolation.InChapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef,wewilllearnhowtodothiswithinVagrantitself.Ifwedothis,weneedtoprovidetheport.Wemightalsowishtochangetheuserthatweconnectastoroot,andensurethataspecificSSHkeyisusedfortheconnectionasfollows:
defaultansible_ssh_host=127.0.0.1ansible_ssh_port=2222
ansible_ssh_user=rootansible_ssh_private_key=~/.ssh/id_rsa
Thisinventoryfileissimplyaplaintextfilesavedsomewhereonourcontrolmachine.Bydefault,Ansiblewilllookforafilecalled/etc/ansible/hosts,whichitexpectstobetheinventory,however,whenwerunAnsible,wecanpointtoourowninventoryfileelsewhere,whichwewilldolaterinthischapter.
CreatingAnsibleplaybooksAswediscussed,anAnsibleplaybookisaYAMLfile.ThefollowingexampleisasimpleplaybookthatcontainsinstructionstoupdatetheAptpackagemanagerclassonthemachinecalledbydefaultinourinventory:
---
-hosts:default
tasks:
-name:updateaptcache
apt:update_cache=yes
Wecanrunthisplaybookbyrunningtheansible-playbookour-playbook.yml-iour-inventory-filecommand.Ansiblewillthenlookupthatthisplaybookistobeappliedtothedefaultmachine,thedefaultmachine’sdetails,connecttoit,andifappropriate,runthecommand.Wewillwalkthroughtheexecutionprocessshortly.
Tasksareexecutedintheorderthattheyappearwithintheplaybook.However,wehavetheoptiontocallothertaskstoberunlateronceanactioniscompleted,throughtheuseofhandlers,whichwewilldiscussshortly.
NoteBecauseplaybooksarewritteninYAML,theformatandspacing/indentationinthesefilesiscritical.Incorrectindentationcancausefilestonotbeparsedcorrectly.
Modules–whatAnsiblecandoAnsiblemodulesaresimilartoPuppetresources,andwecanusethemtoinstallandmanagepackages,servers,users,files,cronjobs,andsoon.
Themodulesavailableinclude:
Apt:ThisisusedtomanageaptpackagesGit:ThisisusedtomanageanddeployfromgitrepositoriesService:ThisisusedtomanagerunningservicesontheserverCopy:Thisisusedtocopyfiles
Eachmodulecanbeconfiguredwithdifferentproperties,aswewilldiscussinthischapter.AcompletelistofthemodulesisavailablefromtheAnsiblewebsiteathttp://docs.ansible.com/list_of_all_modules.html.
InstallingsoftwareLet’ssaywewanttoinstallNginxonourserver.Therearethreestepsinvolvedinthisprocess:
1. Updatingourpackagemanager.2. Installingthenginxpackage.3. Runningthenginxservice.
UpdatingourpackagemanagerWecanusetheaptmodule(http://docs.ansible.com/apt_module.html)toupdatetheaptpackagemanager’scache,whichistheequivalentofperforminganapt-getupdatecommand:
-name:updateaptcache
apt:update_cache=yes
Theupdate_cacheparametercanalsobeprovidedwhenwerunotherapt-relatedtasks,soinsteadofadedicatedtaskforit,wecaninsteadspecifythatwhenweinstallNginx,thepackagemanager’scachemustbeuptodate.
InstallingthenginxpackageWecanusetheaptmodule(http://docs.ansible.com/apt_module.html)toensurethatNginxisinstalled,andifitisn’t,itwillbeinstalledasfollows:
-name:ensurenginxisinstalled
apt:pkg=nginxstate=presentupdate_cache=yes
Here,wetoldAnsibletoensurethatthestateofthenginxpackageispresent,andthatweshouldupdatethepackagemanager’scachebeforeinstallingit.Therearedifferentstatesavailable,includingthelateststatestoensurethatwehavethelatestversionofapackagepresent,orabsenttoensurethatapackageisnotinstalledontheserver.
RunningthenginxserviceFinally,tomakesurethatNginxisrunning,weusetheservicemodule.WhileNginxwillautomaticallyrunwhenweinstallit,wecanconnecttoournewserverandaltersettingsorservicesbymistake.Ifthishappens,wecansimplyreruntheprovisioner,asNginxwillalreadybeinstalled,soitwon’treinstallit,buttheservicemodulewillforcetheservertostartthenginxservice.Wecanusetheenabledparametertoensurethattheserviceisconfiguredtostartautomaticallywhenthesystembootsnext:
-name:ensurenginxisrunning
service:name=nginxstate=startedenabled=yes
UnderstandingfilemanagementWecanusethefile,copy,andtemplatemoduleswithinAnsibletomanagefilesandfolderswithinthefilesystem.Let’stakealookatsomeexamples,whichallowustoperformthefollowing:
CopyfilesCreatesymlinksCreatefolders
CopyingafileOnecommonfileoperationwemightwanttoperformwouldbetotakeaconfigurationfilefromourprojectandcopyitintoourvirtualmachine.OneparticularusecasewouldbeanNginxconfigurationfile;wemightwanttodefinesomevirtualhostsandothersettingsinafile,whichwecansharewithourcolleagues.
TipWhilethisworkswellandcangetusupandrunningquickly,therearerolesouttherethatallowustoconfigureNginxandothersoftwaredirectlyfromAnsible.Thistypicallyworksbytheroleofstoringatemplatefile(acopyoftheconfigurationfilewithplaceholdersinit)andthen,insertingdatathatwedefinewithinourplaybookintothetemplate,andcopyingthefileontothemachine.However,forthesakeofthisintroductorychapter,wewilljustcopyafileacross.
Thetemplatemodule(http://docs.ansible.com/template_module.html)allowsustocopyafilefromourcontrolmachineontothemachinebeingprovisionedasfollows:
-name:writethenginxconfigfile
template:src=nginx-default-site.confdest=/etc/nginx/sites-
available/default.confowner=www-datagroup=www-data
AsthisisourNginxconfigurationfile,itmakessenseforustoreloadorrestartNginxwhenthisfilechangestoensurethattheupdatedconfigurationisappliedtotheserver.Wedothisintwostages:
1. Wesetourtasktonotifyahandleronceitisdone.2. Wecreateahandler,whichisonlyactivatedwhenitisnotified,torestartNginx.
Thefollowingisaplaybookthatupdatestheaptcache,installsNginx,ensuresthattheserviceisrunning,copiestheconfigurationfile,andthenensuresthatNginxisrestartedwhenthatfilechangesthroughanotifyoperationandahandler.Thenotifyandhandlerscodesectionsarehighlightedarefollows:
---
-hosts:default
tasks:
-name:updateaptcache
apt:update_cache=yes
-name:ensurenginxisinstalled
apt:pkg=nginxstate=present
-name:writethenginxconfigfile
template:src=nginx-default-site.confdest=/etc/nginx/sites-
available/default.conf
notify:
-restartnginx
-name:ensurenginxisrunning
service:name=nginxstate=started
handlers:
-name:restartnginx
service:name=nginxstate=restarted
CreatingasymlinkThefilemodule(http://docs.ansible.com/file_module.html)allowsustocreatesymboliclinkstotheexistingfilesandfoldersinthefilesystem.If,forinstance,wewanttomapapublicfolderwithinourwebserversrootdirectorytoafolderwithinourVagrantsharedfolder,wecandothisasfollows:
-name:makeourVagrantsyncedfolderourwebroot
file:src=/vagrantdest=/var/www/siteowner=www-datagroup=www-data
state=link
CreatingfoldersWecanalsousethefileresourcetypetocreatefolders;thisisparticularlyusefulforscenariossuchasfolderstoholdfiles(avatars,attachments,andsoon)uploadedbyusersofawebapplication:
-name:createanuploadsfolder
file:path=/var/www/uploadsowner=www-datagroup=www-datamode=0777
state=directory
Wecanusethemodeparametertosetthepermissionsofthefolder,andtheownerandgroupparameterstosettheuserandgroupswhoownthedirectory(thesealsocanbeusedforfileswecreateandmanagetoo).Finally,thestateparameterisusedtoensurethatthepathprovidedisafolder.
ManagingcronThecronmodule(http://docs.ansible.com/cron_module.html)letsususeAnsibletomanagecronjobs,whichweneedtorunonthemachine.Weprovideaname(whichisarequiredparameter),inthiscase,web_cron,thecommandtorun,theusertorunthecommand,andthetimesatwhichtorunthecommand,asshowninthefollowingcode:
-name:Runsomecron
cron:name="web_cron"hour="1-4"minute="0,30"job="/usr/bin/php
/vagrant/cron.php"
Ansibleprovidesuswithvariousdifferentconfigurationoptionstodefinethetimesatwhichacronshouldberun.Theseinclude:
Hour:Thisvalueisbetween0and23inclusiveMinute:Thisvalueisbetween0and59inclusiveMonth:Thisvalueisbetween1and12inclusiveDay:Thisvalueisbetween1and31inclusiveWeekday:ThisvalueisfromSunday(0)toSaturday(6)
Ifoneoftheseisomittedfromtheconfiguration,thenAnsiblerunsitforeachoneoftheavailableoptions(thatis,ifweomitmonth,itwillrunforJanuarythroughtoDecember),asithasadefaultvalueof*.Whendefiningthedatesandtimes,wecaneitherprovidearange,forexample,1-5orspecifics,suchas1,2,10,12.
RunningcommandsThecommandandshellmodulesallowustoruncommandsthroughtheterminalonthemachineweareprovisioning.Thedifferencebetweenthetwoisthattheshellmodulewillrunthecommandsthroughashellontheremotesystem.Soifweneedtoaccessenvironmentvariablesoroperators,suchas&,|,>,and<,thenweneedtousetheshellmodule.
ManagingusersandgroupsTheuserandgroupmodules(http://docs.ansible.com/user_module.htmlandhttp://docs.ansible.com/group_module.html)letuscreateandmanageusersandgroups.
CreatinggroupsWesimplyprovideaname.Bydefault,thestateparameterissettopresent:
-name:createsomenewgroup
group:name=newgroupstate=present
CreatingusersTocreateauserwecanusetheusermodule(http://docs.ansible.com/user_module.html);theminimuminformationweneedagainistheusername.However,wecanalsospecifytheirgroup,password(providingacryptedhashasperhttp://docs.ansible.com/faq.html#how-do-i-generate-crypted-passwords-for-the-user-module),andevenwhetheranSSHkeycanbegeneratediftheuserdoesnothaveone:
-name:createanewuser
user:name=ournewusergroup=newgroupstate=present
UsingAnsiblerolesTherearemanyexisting,well-written,reusableAnsiblerolesfreelyavailabletouse.Theserolestypicallymanagelargeaspectsofserverfunctionalityinonereusablebundle,forexample,thereisanNginxroletomanageNginxandconfiguresiteswithit.TherearemanyrolesavailableonAnsibleGalaxy(https://galaxy.ansible.com/),soitisworthcheckingtheseoutbeforewritingourowncode!
UsingAnsibletoprovisionserversOncewehaveaplaybookandinventoryfile,wecanruntheansible-playbookcommandtoanalyzeourplaybook,andensurethattheconfigurationforthematchingserversinourinventoryfileisupdated:
ansible-playbookour-playbook.yml-iour-inventory-file
Whenthiscommandwasrunforthefirsttimeagainstaparticularserver,theoutputwassomethinglikethis:
Let’swalkthroughthisscreenshottoseewhatisgoingon:
1. First,Ansiblepullsthefilestogetherandcheckswhethereverythingisvalid.2. Next,itgathersfactsabouttherelatedmachinesitneedstoconnectto.Thisisdone
byconnectingoverSSHandfindingoutinformation,suchasspecification,networkingdetails,andsoon.
3. Next,itrunsthroughthetasksinourplaybook.Wheninstallingandwritingourconfigurationfiles,Ansibleneedstomakeachange,becauseitisn’tinstalledandthefileisn’tthere.
4. Onceinstalled,Nginxautomaticallystarts,sothetasktoensurethatitisrunningdoesn’tdoanything(thiscomesbacktotheidempotencyofAnsible).AstheconfigurationfilewritingnotifiesthehandlertorestartNginx,Nginxisthenrestartedattheend.
5. Finally,weseearecap,threechangesweremade,andfivetasksresultedinanokresponse.
Onsubsequentruns,theoutputlookslikethis:
Therearetwodifferences:firstly,Ansibledoesn’tneedtodoanything,soeverythingisgreenandwegetfourokresults.Again,thisisbecauseAnsibleisidempotent,soitonlydoesthingswhenachangetothesystemisrequired.Secondly,becausewedidn’tnotifytheNginxrestarthandler,thehandlerwasn’tevenrunasatask,whichiswhyourrecapnumberhasdroppedto4,andtherewasnorelatedoutputforthehandler.
SummaryInthischapter,welearnedaboutAnsible,theITautomationtool.Welookedathowitworks,andhowtocreateaninventoryfilesoAnsiblecanmanagedifferentservers,andhowtowriteplaybooks,whichcanworkwithsomeofthedifferentmodules.
Weinstalledthesoftwareandlearnedtoupdatethepackagemanagercachewiththeaptmodule,andpackagesthatareserviceswerethenstartedandmanagedwiththeservicemodule.ThetemplatemoduleallowedustocopyfilesfromourcontrolmachinetotheAnsible-managedmachine.Inordertotriggerservicereloads,welookedintonotifyinghandlersafterspecifictasksoccur.
Tocreateandmanage,files,folders,andsymlinksthefilemodulewasused,andweusedthecronmoduletocreateandmanagecronjobs.Usersandgroupswerecreatedandmanagedwiththeuserandgroupmodulesandfinallywelookedintorunningcommandswiththecommandandshellmodules.
Inthenextchapter,wewilltakealookatChef,thefinalprovisionerthatwewilldiscussinthisbook,andalsodiscusshowwecanuseittoprovisionservers.
Chapter5.UsingChefChefisanotherprovisioningtoolsupportedbyVagrantthatmakesiteasyforustotakeabaseoperatingsysteminstallationandturnitintoafull-fledgedserversuitedtotheneedsofourproject.
Inthischapter,wewillquicklytakealookatthebasicsofChef.Wewon’tlookatitwithinaVagrantcontextjustyet;wewillsimplytakealookathowChefworks,andhowwecanuseit.InChapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef,wewilltakealookathowtoconnectwhatwewilllearninthischapterwithVagrantitself.Inthischapter,wewilllearnthefollowingtopics:
HowChefworksThebasicsbehindChefcookbooksandrecipesHowtouseCheftoperformthefollowingtasks:
InstallingsoftwareManagingfilesandfolderswithinthefilesystemManagingcronjobsRunningcommandsManagingusersandgroups
Howtousethird-partyChefcookbooksandrecipesHowtomanuallyrunCheftoprovisionamachine
Chefitselfisalargetopicandthesubjectofseveralbooks.ForamoredetailedlookatChef,PacktPublishinghassometitlesdedicatedtoprovisioningwithChef:
ChefInfrastructureAutomationCookbook,http://www.packtpub.com/chef-infrastructure-automation-cookbook/bookInstantChefStarter,http://www.packtpub.com/chef-starter/book
KnowingaboutChefChefisaprovisioningtoolthatwecanusetosetupaserverforuseforaproject.Theconfiguration,whichdetermineshowtheserverneedstobesetup,canbestoredwithinourVagrantprojectandcanbesharedwithteammatesthroughversioncontrol,ensuringthateveryonegetsanup-to-datecopyoftherequireddevelopmentenvironment.
Informationabouthowaservershouldbeconfigured,thatis,itssoftware,files,users,andgroups,iswrittenintofilesknownasChefrecipes.TheserecipesarewrittenasRubyfiles.Cheftakesthisinformationandmatchesittoprovidersthatareusedtoexecutetheconfigurationonthemachineinacompatibleway.
Forourpurposes,wewilluseChef-solo,whichisitsstandalonemode(thisisalsohowVagrantusesit).Chef-solomeansthateverythingrunsfromonemachine.Chefalsohasclient-servercapabilities,whereyoucandefinetheChefcookbooksandrolesforalltheserversinyourinfrastructureonacentralhost,anditkeepsyourindividualserversattherequiredlevelofconfiguration.
AswithPuppet,Chefisalsoidempotent,whichmeansrunningChefonamachinemultipletimeshasthesameeffectasrunningitonlyonce.
CreatingcookbooksandrecipeswithChefChefinstructionsarerecipesthatarebundledtogetherincookbooks.Acookbookcontainsatleastonerecipe,whichperformssomeactions.Cookbookscancontainmultiplerecipesandotherresourcessuchastemplatesandfiles.
Atitsmostbasiclevel,acookbookisafolder(namedasthenameofthecookbook)thatcontainsatleastarecipesfolder,whichcontainsatleastadefaultrecipefile,default.rb.Filesaretypicallystoredinafilesfolderwithinthecookbookfolderandtemplatefileswithinthetemplatesfolder.
NoteWhilebothPuppetandChefuseRuby,Puppetisadomain-specificlanguage,whichmakesitlookandfeellikeitsownlanguage,whereasChefisstructuredmorelikeRubyitself.
Resources–whatChefcandoChefusesresourcestodefinetheactionsandoperationsthatcanbeperformedagainstthesystem.ResourcesaremappedtoaChefcode,whichvariesdependingontheplatform/operatingsystembeingused.Forexample,onanUbuntumachine,thepackageresourceismappedtoapt-get.Someofthesesystem-specificinstructionscanalsobeaccesseddirectlyviatheirownresources,apt_package.Forexample,thisisusedtomanagepackagesonUbuntu-andDebian-basedsystems,whereasusingthepackageresource,Chefwillworkoutwhichpackagemanagertousebasedontheoperatingsystem.
Resourcetypesavailableinclude:
cron:ThisresourcetypeisusedtomanagecronjobsonLinux-andUnix-basedsystemsexecute:Thisresourcetypeisusedtoruncommandsattheterminal/commandpromptfile:Thisresourcetypeisusedtomanageandmanipulatefilesandfoldersonthefilesystemgroup:Thisresourcetypeisusedtomanageusergroupspackage:Thisresourcetypeisusedtoinstallsoftwareservice:Thisresourcetypeisusedtomanagerunningservicesonthemachinetemplate:ThisresourcetypeisusedtomanagefilecontentswithanembeddedRubytemplateuser:Thisresourcetypeisusedtomanageuseraccountsonthemachine
Eachresourcecanbeconfiguredwithdifferentattributes,aswewilldiscussinthischapter.AcompletelistoftheresourcetypesisavailableontheOpscodewebsite(OpscodeisthecompanybehindChef)athttp://docs.opscode.com/resource.html.
InstallingsoftwareLet’ssaywewanttoinstallNginxonourserver.Therearethreestepsinvolvedinthisprocess:
1. Updatingourpackagemanager.2. Installingthenginxpackage.3. Runningthenginxservice.
Becausethefirststepisdifferentdependingontheoperatingsystemwearerunning,wemightwanttomovethisoutofChefatalaterstage;however,wewilluseitwithinChefforthetimebeing.Anyoperatingspecificcommands(suchasthis)arewrittenforUbuntu,whichistheoperatingsystemweareusingwithVagrant.
UpdatingourpackagemanagerInordertoupdateourpackagemanager,weneedtorunacommandontheserver.ThiscanbeachievedusingtheexecuteresourcewithinChefasfollows:
execute"apt-getupdate"do
ignore_failuretrue
end
ThisinstructsCheftoruntheapt-getupdatecommand.Asthenameoftheresource(thepartprovidedinquotesafterthenameoftheresource)isthecommandwewanttorun,thiswillbeexecuted.Ifweuseafriendlynameinstead,thenwewouldneedtoprovideacommandattributeasfollows:
execute"update-package-manager"do
command"apt-getupdate"
ignore_failuretrue
end
Bydefault,theexecuteresourceshaveatimeoutof3,600seconds,however,thiscanbeoverriddenbygivingatimeoutattributetotheresourceandatimevalue,forexample:
execute"apt-getupdate"do
ignore_failuretrue
timeout6000
end
InstallingthenginxpackageWecanusethepackageresourcetoensurethatNginxisinstalled,andifitisn’t,itwillbeinstalledasfollows:
package"nginx"do
action:install
end
Here,wetoldCheftoensurethatthenginxpackageisinstalled.Providedthatwehaveincludedtherecipeorcookbookthatcontainstheapt-getupdatecommandbeforetheprecedingcode,ourpackagemanagerwillbeuptodate.
RunningthenginxserviceFinally,tomakesurethatNginxisrunning,weusetheserviceresource.AswellasensuringNginxrunswhenitisfirstinstalled,thisalsoensuresthatifwemakeanychangestoourserver(andaccidentallystopNginx),wecansimplyreruntheprovisioner.AsNginxwillalreadybeinstalleditwon’treinstallit,buttheserviceresourcewillforceCheftoenablethenginxservice(soitautomaticallystartsonsystemboot),andstarttheservicewhenthecommandisrun,asfollows:
service"nginx"do
supports:status=>true,:restart=>true,:reload=>true
action[:enable,:start]
end
ThesupportspropertyisalistofattributesthatinstructChefonhowtomanageaparticularservice.Theactionensuresthatweenabletheservice(tohaveitrunwhenthemachinebootsup)andruntheservice(so,wedon’thavetowaitforarestart).
UnderstandingfilemanagementWecanusecookbook_file,directory,link,andtemplateresourceswithinCheftomanagefilesandfolderswithinthefilesystem.Let’stakealookatsomeexamples,whichallowusto:
CopyfilesCreatesymlinksCreatefoldersCreatemultiplefoldersinonego
CopyingafileOnecommonfileoperationwemightwanttoperformwouldbetotakeaconfigurationfilefromourprojectandcopyitintoourvirtualmachine.OneparticularusecasewouldbeanNginxconfigurationfile;wemightwanttodefinesomevirtualhostsandothersettingsinafile,whichwecansharewithourcolleagues.
TipWhilethisworkswellandcangetusupandrunningquickly,therearemodulesouttherethatallowustoconfigureNginxandothersoftwaredirectlyfromChef.Thistypicallyworksbythemodulestoringatemplatefile(acopyoftheconfigurationfilewithplaceholdersinit)andtheninsertingdatawedefinewithinChefintothetemplateaswellascopyingthefileontothemachine.However,forthesakeofthisintroductorychapter,wewilljustcopyafileacross.
Thecookbook_fileresourceallowsustocopyafilefromaChefcookbookontothemachineasfollows:
cookbook_file"/etc/nginx/sites-available/default"do
backupfalse
action:create_if_missing
end
Becauseweomittedthesourceandpathattributes,Chefmakessomeassumptions.Ittakesthebasename(ineffect,thelastelement)ofthenameandusesthisasthesource(thebasenameof/etc/nginx/sites-available/defaultbeingthedefault)andusesthenameasthepath(destination).Thesourcefileshouldbelocatedinthefilesfolderwithinthecookbook’sownfolder.
AsthisisanNginxconfigurationfile,itisworthensuringthatNginxisalreadyinstalled;otherwise,Nginxwilloverridethiswhenitinstallsthefirsttime,andthiswouldn’tmaketheprocessidempotent.Wecandothisbynotifyingthenginxservice,forexample:
cookbook_file"/etc/nginx/sites-available/default"do
backupfalse
action:create_if_missing
notifies:restart,"service[nginx]",:delayed
end
ThedelayedoptionallowsalloftheserestartrequeststobequeuedupandexecutedattheendofChef’sexecution;theoppositeofthisbeingimmediately.
CreatingasymlinkThelinkresourceallowsustocreatesymboliclinkstotheexistingfilesandfoldersonthefilesystem.If,forinstance,wewanttomapapublicfolderwithinourwebserver’srootdirectorytoafolderwithinourVagrantsharedfolder,wecandothisasfollows:
link"/var/www/public"do
to"/vagrant/src/public"
end
CreatingfoldersWecanusethedirectoryresourcetocreatefolders;thisisparticularlyusefulforscenariossuchasfolderstoholdfiles(avatars,attachments,andsoon)uploadedbyusersofawebapplication:
directory"/var/www/uploads"do
owner"root"
group"root"
mode00777
action:create
end
Wecanusethemodeparametertosetthepermissionsofthefolder,andtheownerandgroupparameterstosettheuserandgroupswhoownthedirectory(thesealsocanbeusedforfileswecreateandmanagetoo).Finally,the:createactionisusedtoensurethatthefolderiscreated.
CreatingmultiplefoldersinasingleprocesswithloopingInmanywebprojects,wemightneedtocreateanumberoffolderswithinourserversorourVagrantvirtualmachines.Inparticular,wemightwanttocreateanumberofcachefoldersfordifferentpartsofourapplication,orwemightwanttocreatesomeuploadfolders.
Inordertodothis,wecansimplycreateanarraythatcontainsallofthefolderswewanttocreate.Wecanthenusethedirectoryresourcetypeandloopthroughalistofdirectorynames:
%w{dir1dir2dir3}.eachdo|dir|
directory"/tmp/mydirs/#{dir}"do
mode00777
owner"www-data"
group"www-data"
action:create
end
end
ManagingcronThecronresourcetypeletsususeCheftomanagecronjobsthatweneedtorunonthemachine.Weprovideaname,inthiscase,web_cron,thecommandtorun,theusertorunthecommand,andthetimesatwhichtorunthecommand,asshowninthefollowingcode:
cron"web_cron"do
action:create
command"/usr/bin/php/vagrant/cron.php"
user"root"
hour"1-4"
minute"0,30"
end
Chefprovidesuswithvariousdifferentconfigurationoptionstodefinethetimesatwhichacronshouldberun;theseinclude:
hour:Thisvalueisbetween0and23inclusiveminute:Thisvalueisbetween0and59inclusivemonth:Thisvalueisbetween1and12inclusiveday:Thisvalueisbetween1and31inclusiveweekday:ThisvalueisSunday(0)-Saturday(6)
Ifoneoftheseisomittedfromtheconfiguration,thenChefrunsitforeachoneoftheavailableoptions(thatis,ifweomitmonth,itwillrunfromJanuarythroughtoDecember).Whendefiningthedatesandtimes,wecaneitherprovidearange,forexample,1-5,orspecifics,suchas1,2,10,12.Wecanalsoprovideanemailtopropertytoe-mailtheresultingoutputfromthecrontoane-mailaddressofourchoice.
RunningcommandsTheexecuteresourceallowsustoruncommandsthroughtheterminalonthemachineweareprovisioning.OnecaveatwiththeexeccommandisthatifyoureprovisionwithChefitwillrerunthecommand,whichcanbedamagingdependingonthecommand.Whatwecandowiththeexecuteresourceissetthecreatesparameter.ThecreatesparametertellsChefthatafilewillbecreatedwhenthecommandisrun;ifCheffindsthatfile,itknowsthatithasalreadybeenrun,anditwon’trunitagain.
Take,forexample,thefollowingconfiguration;thiswouldusethePHPcomposertooltodownloaddependencies.Thecommanditselfcreatesafilecalledcomposer.lock(wecan,ofcourse,usetheexeccommanditselftocreateafilemanually,perhapsusingthetouchcommand).Becauseofthelockfilethatiscreated,wecanusethecreatesparametertopreventthecommandfrombeingexecutedmultipletimeswhenalockfileisfound:
execute"compose"do
command"/bin/rm-rfv/var/www/repo/vendor/*&&/bin/rm–f
/var/www/repo/composer.lock&&/usr/bin/curl–s
http://getcomposer.org/installer|/usr/bin/php&&cd
/var/www/repo&&/usr/bin/php/var/www/repo/composer
.pharinstall"
creates"/var/www/repo/composer.lock"
timeout6000
end
ManagingusersandgroupsTheuserandgroupresourcetypesletuscreateandmanageusersandgroups.TherearedifferencesbetweendifferentoperatingsystemsastowhatChefcandowiththeusersandgroupsandhowthisworks.
CreatinggroupsThesimplestwaytocreateagroupissimplytosettheactionto:create,asfollows:
group"wheel"do
action:create
end
CreatingusersTocreateauser,weshouldprovidethefollowingbasicinformation:
TheusernameThefactthatwewanttocreatetheuserThegroup(gid)theusershouldbepartofTheshelltousefortheuserThehomedirectoryfortheuserWhetherwewantCheftomanagethehomedirectoryfortheuser;inthiscase,itwillcreatethefolderforusifitdoesnotexistThepasswordfortheuser
Thecodethatwillthencreateouruserisasfollows:
user"developer"do
action:create
gid"wheel"
shell"/bin/bash"
home"/home/developer"
supports{:manage_home=>true}
password"passwordtest"
end
UpdatingthesudoersfileIt’sallwellandgoodbeingabletocreateusersandgroupsonourmachine,however,onethingthatwecan’tdousingtheuserandgroupresourcetypesisdefineauserorgroupashavingelevatedprivileges,unlesswemaketheuserapartoftherootgroup.
Wecanuseanexeccommandthroughtheexecuteresourcetopushsometexttotheendofoursuodersfile;thetextweneedtopushsimplytellsthefilethatwewanttogivethewheelgroupsudoprivileges.Thecommandwewillneedtoexecuteisasfollows:
/bin/echo\"%wheelALL=(ALL)ALL\">>/etc/sudoers
KnowingcommonresourcefunctionalitiesThereisalsoasetofcommonfunctionalityavailabletoallresources.Thiscommonfunctionalityincludes:
Theabilitytodonothingwiththe:nothingactionSharedattributesavailabletoallresources:ignore_failure,provider,retries,retry_delay,andsupportsThenot_ifandonly_ifconditionstoensurethatactionsonlyrunwhencertainconditionsaremet;thesearecommandsthatarerunanddependingontheirreturnvalue,recipes,andresourcescanbeignoredTherearenotificationstoinstructotherresourcesthatanotheractionhasbeencompleted,orforaresourcetotakeactionifanotherresourcechanges(subscribes)
UsingChefcookbooksTherearemanyexisting,well-written,reusableChefcookbooksfreelyavailabletouse.TheOpscodecommunitysitecontainsacollectionofthemathttp://community.opscode.com/cookbooks.Itisalwaysworthcheckingwhetherthereisanexistingcookbookthatsolvesyourproblembeforewritingyourown.
UsingCheftoprovisionserversWewilltakealookathowtouseChefwithVagrantinChapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef;however,Chefcanalsoberuninitsownright.ProvidedChefisinstalled(itwillbeonmostVagrantbaseboxes,butifyouwanttorunitonanothermachine,itmightnotbe,soinstallitfirst),youcanusethechef-solocommand,passingwithitthelocationofaconfigurationfiletouse,andaJSONfilethatcontainsattributeswewishtouse(thisshouldincludetherublist,whichisthelistofrecipesandcookbookswewishtouse),asfollows:
chef-solo–c/home/michael/chefconfig.rb–j
/home/michael/attributes.json
Therearesomeusefullinksinthislistyoucanrefertoformoreinformation
Chef-soloconfiguration:http://docs.opscode.com/config_rb_solo.htmlApplyrecipestorunlists:http://docs.chef.io/recipes.html#apply-to-run-listsAnatomyofaChefrun:https://github.com/jhotta/chef-fundamentals-ja/blob/master/slides/anatomy-of-a-chef-run/01_slide.mdCheftutorial:http://www.mechanicalfish.net/configure-a-server-with-chef-solo-in-five-minutes/
SummaryInthischapter,wehadawhirlwindtourofChefandexploredthevariouswayswecoulduseittoprovisionaserverforourprojects.Thisincludedhowtoinstallsoftwarepackageswiththepackageresourceandrunserviceswiththeserviceresource.Wealsomanagedcronjobswiththecronresource,managedusersandgroups,andrancommands.Finally,welookedathowrecipesandcookbookswork,andhowwecanuseCheftoprovisionaserver.
Inthenextchapter,wewilltakealookathowtousebothChefandPuppettoprovisionamachinewithinthecontextofVagrant.
Chapter6.ProvisioningVagrantMachineswithPuppet,Ansible,andChefInChapter3,ProvisioningwithPuppet,Chapter4,UsingAnsible,andChapter5,UsingChef,wehadanintroductiontoPuppet,Chef,andAnsible,whichareprovisioningtoolswithsupportbuiltintoVagrant.However,weonlylookedathowthetoolsworkedinageneralway;wedidn’tlookathowtousethemwithVagrant.
Inthischapter,youwilllearnthefollowingtopics:
UsingPuppetwithinVagrantUsingChefwithinVagrantUsingAnsiblewithinVagrantRecappinghowtoprovisionwiththebuilt-inSSHprovisionerWorkingwithmultipleprovisionersHowwecanoverridetheprovisioningtoolsthroughthecommandline
ProvisioningwithinVagrantVagrantreliesonbaseboxesfortheguestvirtualmachines;thesearespecificallypreconfiguredvirtualmachineimagesthathavecertainsoftwarepackagespreinstalledandpreconfigured.PuppetandChefaretwosuchsoftwarepackagesthatarepreinstalled(AnsibleiscontrolledbyVagrantitselfonthehostmachine,soitisn’tinstalledonthevirtualmachine,butrequiresanSSHconnectiontothevirtualmachine).Vagranthasitsowninterfacethroughtothesepackagesfromthehostmachine.ThismeanswecanprovidesomeconfigurationinourVagrantfile,andVagrantwillpassthisinformationtotherelevantprovisionersontheguestVM.
ProvisioningwithPuppetonVagrantVagrantsupportstwomethodsofusingPuppet:
PuppetinstandalonemodeusingthepuppetapplycommandontheVMPuppetinclient/servermode,wherebytheVM(usingthePuppetagent)willbeconfiguredfromacentralserver
Let’stakealookathowtoconfigureVagrantwithPuppetusingthesetwodifferentmethods.
UsingPuppetinstandalonemodePuppetstandaloneisthesimplestwaytousePuppetwithVagrant.WesimplytellVagrantwherewehaveputourPuppetmanifestsandmodules,andwhatmanifestshouldberun.ThesmallestamountofconfigurationweneedwithinourVagrantfileinordertousePuppetisthis:
config.vm.provision"puppet"do|puppet|
end
ThisshouldgowithintheVagrant.configure("2")do|config|…endblockofcodewithintheVagrantfile.
Alongwiththisconfiguration,wewillneedaPuppetmanifestcalleddefault.ppinthemanifestsfolderofourprojectroot.Vagrantwillthenusethistoprovisionthemachine.
ThiswillinstructVagranttorunthePuppetprovisionereitherwhenthemachinebootsupforthefirsttimeorifwerunthevagrantprovisioncommand.ThedefaultVagrantPuppetsetupwillmakethefollowingassumptions,unlessweoverridethesettings:
ManifestswillbelocatedinthemanifestsfolderModuleswillalsobelocatedinthemanifestsfolder(wemaywanttopointtheseelsewhere,especiallyifweareusingthird-partymodules,tokeepthemseparate)Themanifestfiletousewillbedefault.pp(Itwillobviouslybewithinthemanifestsfolder;itcanbeusefultooverridethisifweusePuppetmodulesandmanifestswithinthesameprojectformultipleenvironments.WemayhaveamanifestforourVagrantVM,oneforourproductionenvironmentandoneforauseracceptancetestingplatform,forexample.)
Wecanmodifytheseoptionsbyprovisioningconfigurationoptions,asopposedtojusttellingVagranttoprovisionwithPuppet.WhencreatingprojectsthataremanagedbyVagrant,Iliketoputallmyprovision-relatedfileswithintheprovisionfolder.Inordertooverridethese,withinthePuppetconfigurationforVagrant,wecanthenspecifyoptionsforthelocationofthePuppetmanifests(puppet.manifests_path),thenameofthePuppetmanifesttoapply(puppet.manifests_file),andthelocationofanyPuppetmodules,whichwemayreferencewithinourPuppetmanifest(puppet.module_path).Thefollowingcustomizestheseoptions:
config.vm.provision"puppet"do|puppet|
puppet.manifests_path="provision/puppet/manifests"
puppet.manifest_file="default.pp"
puppet.module_path="provision/puppet/modules"
end
Itisimportantforustohavetheabilitytoatleastchangethemanifestfile,asVagrantalsosupportsamulti-VMenvironment,whereasingleprojectcanhaveanumberofvirtualmachines(forexample,awebserverandadatabaseserver).Withthissetup,wewillneedtotellVagrantwhichmanifestfiletouseforeachofthemachines,sothatthewebservercanbeproperlyconfiguredasawebserverandthedatabaseserverasadatabaseserver.
PuppetprovisioninginactionWiththeknowledgewegainedofcreatingPuppetmodulesandmanifestsfromChapter3,ProvisioningwithPuppet,wecannowpointourVagrantconfigurationatthesefiles,andseeitinaction.IfwerunaVagrantfileonaproject,whichissuitablyconfigured,wewillseetheoutputofPuppetapplyingitssettingstoourvirtualmachineintheterminalwindow,asshowninthefollowingscreenshot:
TheconsoleoutputhighlightsdetailsofeachPuppetinstructionthatisrun,including:
Thestagetheinstructioniswithin(thisisthePuppetstage,aswediscussedinChapter3,ProvisioningwithPuppet,whichallowsustogroupclassestogethertocontroltheorderingofcertainactions)ThemoduleTheresourcetypeTheresourcenameWhethertheinstructionwasexecutedsuccessfully
UsingPuppetinclient/servermodeAsdiscussedearlier,wecanalsorunPuppetwithinourVagrantenvironmentinclient/servermodeusingthePuppetagentonthevirtualmachine.Theconfigurationrequiredforthisisminimal;wesimplytellVagranttheaddressofthePuppetserverweareusingandthenameofournode(thevirtualmachinewearesettingup):
config.vm.provision"puppet_server"do|puppet|
puppet.puppet_server="puppet.internal.michaelpeacock.co.uk"
puppet.puppet_node="vm.internal.michaelpeacock.co.uk"
end
ThenodenameisthereferenceforthemachinewithinthePuppetserver,sothePuppetserverknowshowourVMshouldbeconfigured.ThenodenameisalsousedtogenerateanSSLcertificatesothattheVMcanauthenticatewiththePuppetserver(moredetailsonthisareavailableonthePuppetwebsite,https://puppetlabs.com,andthePuppetblog,https://puppetlabs.com/blog/deploying-puppet-in-client-server-standalone-and-massively-scaled-environments.
ProvisioningwithAnsibleonVagrantInordertouseAnsiblewithinaVagrantproject,weneedtotellVagrantwheretheplaybookandinventoryfilesare:
config.vm.provision"ansible"do|ansible|
ansible.playbook="provision/ansible/playbook.yml"
end
Ansibleneedstoknowwhichmachinestoprovision;unlikewithotherprovisioners,wherethisisexplicitlyknownfromtheVagrantfileconfiguration,Ansibleusesaninventoryfiletoconfigurethis.TheinventoryfilecontainsalistofenvironmentnamesandIPaddresses;weusethisfiletorestrictwhichcommandsAnsiblerunsonspecificenvironments.Wecanomitthisfile,andVagrantwillgenerateoneforallofthevirtualmachinesitmanagesforusinthecurrentproject.
Wecanalsocreateourowninventoryfile.Ataminimum,itneedstoknowthenameofthevirtualmachine(fromourVagrantfile)andtheIPaddress.Toprovideonlythesetwopiecesofinformation,thisrequiresthevirtualmachinetoberunningonitsownIPaddress(pertheVagrantfilenetworkingconfiguration):
defaultansible_ssh_host=10.11.100.123
Alternatively,wecanprovidetheSSHporttouse,sothatAnsiblecanconnectfromourhostmachinetoourvirtualmachine:
defaultansible_ssh_host=127.0.0.1ansible_ssh_port=2222
TotellVagrantandAnsibleaboutourowncustominventoryfile,weneedtoaddittoourVagrantfileasfollows:
config.vm.provision"ansible"do|ansible|
ansible.playbook="provision/ansible/playbook.yml"
ansible.inventory_file="provision/ansible/inventory"
end
ProvisioningwithChefonVagrantVagrantalsosupportstwomethodsofusingChef:
Chef-soloChefinclient/servermodewithChefclient
Let’stakealookathowtoconfigureVagrantwithChefusingthesetwodifferentmethods.
UsingChef-soloChef-soloistheChefequivalentofPuppetstandalone.
ThesimplestwaytousethiswithinourprojectissimplytoprovideaChefrunlisttoVagrant;thistellsVagrantwhichcookbooksshouldbeapplied.ThefollowingisanexampleoftellingVagranttousethePHPcookbook:
config.vm.provision"chef_solo"do|chef|
chef.add_recipe"php"
end
ThistakesthePHPcookbookfromthedefaultcookbooksfolderandappliesittothevirtualmachine.
AswithPuppet,Vagrantmakessomeassumptionsbydefault;theyareasfollows:
Cookbooksarestoredinthecookbooksfolderwithintheprojectroot.Thechef.cookbooks_pathsettingallowsustooverridethecookbooksfolderlocation.Wecaneitherprovideasinglepathoranarrayofpaths(wrappedinsquarebrackets,separatedwithcommas)ifwewantVagrantandCheftolookinarangeoffoldersforourcookbooks.ThefollowingcodewillgointoourVagrantfiletotellVagranttooverridethecookbooksfolderwithprovision/cookbooks:
config.vm.provision"chef_solo"do|chef|
chef.cookbooks_path="provision/cookbooks"
end
WecanalsouseChefrolesbyproviding:
ThelocationoftherolesfolderTheroleswewishtoaddtotheVM
MoreinformationonChefrolescanbefoundontheOpscodewebsite(http://docs.opscode.com/essentials_roles.html).
ThefollowingcodeinourVagrantfilewillsetupourprojecttouseChefroles:
config.vm.provision"chef_solo"do|chef|
chef.roles_path="provision/roles"
chef.add_role("web")
end
UsingChefinclient/servermodeLikePuppet,Chefalsohasaclient/servermethodtoprovisionmachinesusingChefclientontheVM.TouseChefclient,weneedtotellVagrantwheretheChefserverislocated(throughthechef.chef_server_urlsetting),andprovidetheauthorizationkeythatwillbeusedtoauthenticatetheVMwiththeserver(throughthechef.validation_key_pathsetting).
ThefollowingcodeinourVagrantfilewillinstructVagranttoprovisionfromaChefserver:
config.vm.provision"chef_client"do|chef|
chef.chef_server_url="http://chef.internal.michaelpeacock.
co.uk:4000/"chef.validation_key_path="key.pem"
end
WecanalsooverridetherunlistthattheChefserverprovidesforourVMbymanuallyaddingrolesandrecipestothisconfiguration.IfwehavespecifieddifferentenvironmentsonourChefserver,wecanspecifywhichenvironmentwewanttousewiththechef.environmentconfiguration.
TipVagrantVMsthatuseChefserverwillhavethecorrespondingnodeandcliententriesontheChefserver,whichisnamedwiththehostnameoftheVM.IfwedestroytheVMandrecreateit,Chefwillgenerateanerrorbecausetheclientandnodeentriesarealreadypresentontheserver.WeneedtoremovethesefromtheChefserverwhenwedestroyaVM.ThiscanbedoneusingtheknifetoolfromChef,knifenodedeleteour-vm-hostname&&knifeclientdeleteour-vm-hostname.
ProvisioningwithSSH–arecapAswediscussedinChapter2,ManagingVagrantBoxesandProjects,wecaninstructVagranttorunaseriesofSSHcommandsontheVM.Thiscanbeusedtoprovisiontheserver.
TherearetwowaystouseSSHprovisioning:
Path:ThisprovidesafiletoexecuteInline:Thisisusedtoprovidespecificcommandstorun
Bothoftheseareshownasfollows:
config.vm.provision"shell",path:"provision/setup.sh"
config.vm.provision"shell",inline:"apt-getinstallapache2"
UsingmultipleprovisionersonasingleprojectWecanusemultipleprovisionerswithinasingleprojectifwewish;wesimplyneedtoputthemintheorderwewishforthemtobeexecutedwithinourVagrantfile.ThefollowingcommandwillfirstrunanSSHcommandbeforeprovisioningwithPuppet:
Vagrant.configure("2")do|config|
Config.vm.box="ubuntu/trusty64"
config.vm.provision"shell",inline:"apt-getupdate"
config.vm.provision"puppet"do|puppet|
puppet.manifests_path="provision/puppet/manifests"
puppet.manifest_file="default.pp"
puppet.module_path="provision/puppet/modules"
end
end
Usingmultipleprovisionerscanbeuseful,especiallyifoneismoresuitedatspecifictasksthananother,orifwerequiresomeprerequisites.Forexample,whenusingPuppetandChefinclient/servermode,theyneedtohaveanSSHkeytocommunicatewiththeserver.WecanuseashellprovisionertoinstructtheVMtodownloadthekeyswepreparedfromasecurelocation,beforethePuppetorChefprovisionerskickin.
OverridingprovisioningviathecommandlineTheremaybeinstanceswherewewanttorestrictorenforcetheexecutionofprovisioningorevenaspecificprovisionerwithinaproject.Thefollowingcommandsareallexecutedfromthehostmachine:
WecancancelarunningprovisionbypressingCMD+Cattheterminal.WecaninstructVagranttorerunprovisioningonaVMusingthevagrantprovisioncommand.Wecanalsoadd--no-provisiontotheupcommandtoinstructVagranttonotruntheprovisioningtoolswhenperformingtheupaction,forexample,vagrantup--no-provision.Bydefault,Vagrantwillonlyprovisionwhenitfirstbootsamachine.Forsubsequentbootsofanexistingmachine,Vagrantknowsthatthemachinesareconfigured,anditwillnotprovisionthem.Wecanoverridethiswiththe--provisionoption,forexample,vagrantup--provision.Wecanalsoprovisionwithjustaspecificprovisionershouldwewish,forexample,ifwewanttoinstructVagranttojustrunPuppetinstandalonemode(inaprojectthathasmultipleprovisionersconfigured),weneedtorunvagrantprovision--provision-with=puppet.
SummaryInthischapter,welearnedhowwecanapplyourknowledgeofPuppetandCheffromChapter3,ProvisioningwithPuppet,Chapter4,UsingAnsible,andChapter5,UsingChef,andconfigureVagranttousethesetoolstoprovisionourvirtualmachines.
WestartedoffbylearningtousePuppetinstandalonemodethatusesthepuppetapplycommandtoapplylocallystoredmanifestsandmodulesontothemachine.Then,wecontinuedusingPuppetintheclient/servermodethatusesthePuppetagenttoretrievetheconfigurationfromacentralservertoprovisionthemachine.
WethenlearnedhowtouseAnsibletorunplaybooksonspecificmachinesalongwiththefundamentalsofChef-solo,whichapplieslocallystoredcookbooksandrecipestothemachine.ItalsoincludedtheusageofChefinclient/servermode,whichusestheChefclienttoretrievetheconfigurationfromacentralservertoprovisionthemachine.
OtherstandardprovisionerswerealsocheckedusingSSHprovisioningandmultipleprovisioningoptionsforthesameproject.Finally,weroundedoffbyrunningmultipleprovisionerswithinasingleproject,overridingprovisioningonthecommandlineandrerunningtheprovisioningtoolswithvagrantprovision.
Now,wehavefullymasteredhowtosetup,use,andmanageVagrantalongwiththeprovisioningtoolstoworkonasinglemachineproject.InChapter7,WorkingwithMultipleMachines,wewilltakealookathowtouseVagrantandourknowledgeofprovisionerstomanageamultimachineproject,withprovisionersconfiguringdifferentmachinesfordifferentpurposesforusewithintheproject,forexample,awebserverandadatabaseserver.
Chapter7.WorkingwithMultipleMachinesSofar,wehaveseenhowwecangetVagranttoastagewhereourdevelopmentenvironmentiscontainedinVagrant-managedvirtualmachines,withoneofthekeyaspectsbeingthatthesevirtualmachinesmimicourproductionenvironment.Itgivesustheflexibilityofbeingabletoencapsulatethedevelopmentenvironmentfordifferentprojectssothatwecaneasilyswitchfromonetoanotherwithouthavingtomodifythesoftwareonourownmachines.
Inmanycases,thefeatureswelearnedsofarareenough.However,webprojectsarebecomingmoreandmorecomplex,withdeveloperscontinuallyimproving,havingtodealwithmultiplemachinesintheirarchitecturetohelpwithscalabilityandstability.Whileitcanbesaidthatscalabilityandstabilityissueswon’timpactourdevelopmentenvironment(aswewon’thavehugeamountsoftrafficcomingtoourdevelopmentenvironment,unlessweload-testit),wewanttoensurethatthecouplingbetweenserverswithinourcode(suchasapplicationcodeconnectingtoaremotedatabase)worksinourdevelopmentenvironmentbeforeweputtheprojectonline.
Thankfully,Vagranthassupportforrunningmultiplevirtualmachinesatthesametimewithinthesameproject.Wecanusethistotestmultimachinearchitecturesanddistributedsystemsonourownlocalmachinebeforeweshareourchangeswithcolleaguesinastagingenvironment,andbeforetheprojectgoeslive.Replicatingamultimachineenvironmentindevelopmentgreatlyhelpsusimprovethereliabilityofourprojectsandinstillsconfidenceintheworkthatwedo.
Inthischapter,wewilllearnthefollowingtopics:
HowtorunmultiplevirtualmachineswithinasingleVagrantprojectHowtoprovidedifferentdistinctconfigurationtothesevirtualmachines,includingthefollowing:
NamesIPaddressesonaprivatenetworksothattheycancommunicatewithoneanotherBaseboxesProvisioningSharedfolders
HowtoconnecttothedifferentvirtualmachinesoverSSHwithouthavingtoknoworremembertheirIPaddresses
UsingmultiplemachineswithVagrantInordertousemultiplevirtualmachineswithinourproject,weneedtotellVagrantaboutthem,andweneedtoprovideadditionalconfigurationfortheindividualvirtualmachines.
DefiningmultiplevirtualmachinesWithinthestandardVagrantprojectconfigurationfile,wecantellVagrantthatwewishtoassignanametoavirtualmachinebeingmanagedbytheproject.Withinthissubconfiguration,weprovidetheinformationVagrantneedsthatisspecifictothatVM.
Thesyntaxforthesubconfigurationsisasfollows:
config.vm.define:name_of_the_vmdo|name_of_the_vm|
#configurationspecifictothevirtualmachine
end
Thisisappliedtoaprojectthatrequirestwovirtualmachines,namedserver1andserver2,bothrunningtheprecise64box:
#-*-mode:ruby-*-
#vi:setft=ruby:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.define:server1do|server1|
server1.vm.box="hashicorp/precise64"
end
config.vm.define:server2do|server2|
server2.vm.box="hashicorp/precise64"
end
end
ConnectingtothemultiplevirtualmachinesoverSSHWhenourmultiplemachinesbootupinourmultimachineproject,VagrantautomaticallymapsdifferentportsfromourhostmachinetotheSSHportsonthevariousguestmachines.
Let’stakealookattheconsoleoutputwhenbootingaVagrantprojectwithtwovirtualmachineswithinit:
Asshownintheprecedingscreenshot,VagrantmapstheSSHportonthevirtualmachinedesignatedserver1toport2222onthehostmachine,andtheSSHportofthemachinedesignatedserver2totheport2200.
ThisgivesustheopportunityofsimplyusingthestandardSSHcommandfromaterminal(orthelikesofPuTTYonaWindowsmachine),toconnecttolocalhostwiththeportnumberthatVagrantassignstoeachmachine.
Toconnecttothemachinethatismappedtoport2200,wesimplyrunthesshvagrant@localhost–p2200command.The–p2200optiontellsthecommandtouseanonstandardport,andspecifiestheportwewishtouse,inthiscase2200.
Alternatively,wecanusethevagrantsshcommandtoconnecttothevirtualmachines.Thedifferenceisthatinamultivirtualmachineenvironment,wemustalsoprovidethenameofthevirtualmachine.Forexample,vagrantsshserver1.Thisisthemostcommonusageofconnectingtoamachine,ratherthandirectlyconnectingtothevirtualmachineviaitsIPaddress.
NetworkingthemultiplevirtualmachinesInasinglevirtualmachineproject,theIPaddressofthevirtualmachineisn’tthatimportant.Inamultivirtualmachineproject,however,itismorelikelythatwewantthetwomachinestocommunicatewithoneanotherdirectly;inordertodothis,weneedtobeawareoftheirIPaddresses,orweneedtoforwardnonconflictingportstothelocalhostinstead.AswewanttohaveourVagrantprojectsdistributedtoourteammembers,andsomeoftheseteammembersmaybewithinthesameoffice,weneedto:
PredefinetheIPaddresssothatanyofourprojectscodethatneedstocommunicatewiththeothervirtualmachinecandoso,withouttheotherteammembersneedingtochangeconfigurationsEnsurethatthevirtualmachinesarerunningonaprivatenetworkonlythatareattachedtothemachineoftheuserrunningit;thiswillpreventtheIPaddressconflictswithinthenetwork
Inordertodothis,wesimplyusethenetworkingoptions,whichwelearnedinChapter2,ManagingVagrantBoxesandProjects.Becausewewantthevirtualmachinestoruninaprivatenetwork,itmakessensetousearangeofprivateIPaddresses,whicharedifferenttoyourownnetwork.Forexample,mynetworkrangeis192.168.1.xxx,soIwillusetherange10.11.1.xxxformyvirtualmachinenetwork(theIPaddressrangesareasubsetoftherangeofaddressespreassignedforinternalnetworks),asshowninthefollowingcode:
#-*-mode:ruby-*-
#vi:setft=ruby:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.define:server1do|server1|
server1.vm.box="hashicorp/precise64"
server1.vm.network"private_network",ip:"10.11.1.100"
end
config.vm.define:server2do|server2|
server2.vm.box="hashicorp/precise64"
server2.vm.network:private_network,ip:"10.11.1.101"
end
end
Let’stestthisoutandtestwhetherwecanconnectfromonemachinetotheother:
1. Poweruptheproject(vagrantup).2. Connecttoserver1(vagrantsshserver1).3. Pingserver2fromserver1(ping10.11.1.101).
Theoutputshowsthatweareabletocommunicateoverthenetworkfromserver1toserver2asfollows:
ProvisioningthemachinesseparatelyAsthevirtualmachinesinourprojectsaregoingtobeusedfordifferentpurposes,weneedtousedifferentprovisioningforthemachines,sotheybothhaveonlythesoftwareandconfigurationsneededtodotheirjob.
Wetaketheprovisioningcode,whichwelearnedinChapter3,ProvisioningwithPuppet,andChapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef,andweplacetherelevantcodewithinthevirtualmachine’ssubconfiguration.Therearesomekeychangesthatweneedtomake:
TheopeninglineoftheprovisioncodemustreferencetheservernameofthevirtualmachineitrelatestoForPuppet,weshoulduseadifferentmanifestfileforthetwovirtualmachinesForChef,wewillapplydifferentrolestothedifferentmachines
ThefollowingcodeprovisionsboththemachinesusingPuppet.TheybothrelyonthesamesetofPuppetmodules,thesamepaththatpointstothemanifestsfolder,however,theybothusedifferentmanifeststosetuptheprojects(alternatively,wecanconfigurethemachinesandidentifythemasnodestoaPuppetmastertoretrievetheappropriateconfiguration):
#-*-mode:ruby-*-
#vi:setft=ruby:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.define:server1do|server1|
server1.vm.box="hashicorp/precise64"
server1.vm.network"private_network",ip:"10.11.1.100"
server1.vm.provision:puppetdo|puppet|
puppet.manifests_path="provision/puppet/manifests"
puppet.manifest_file="server1.pp"
puppet.module_path="provision/puppet/modules"
end
end
config.vm.define:server2do|server2|
server2.vm.box="hashicorp/precise64"
server2.vm.network:private_network,ip:"10.11.1.101"
server2.vm.provision:puppetdo|puppet|
puppet.manifests_path="provision/puppet/manifests"
puppet.manifest_file="server2.pp"
puppet.module_path="provision/puppet/modules"
end
end
end
Withintheprovisionsforeachmachine,wewouldneedtoensurethatweallowboththemachinestocommunicatewithoneanother.Forexample,bydefault,aMySQLServerwon’tacceptconnectionsfromaremoteserver,sowewouldneedtomodify(orreplace)theconfigurationfilewithonethatallowsthis,orwewouldneedtouseaPuppetmoduleorChefcookbookthatallowsustomodifythisconfigurationvalue.
TipYoushouldcheckthedocumentationforanysoftwareyouarecommunicatingwithoverthenetworktoseehowitneedstobeconfigured.WithMySQL,youneedtoeditthemy.cnffile,andsetthebindaddressto0.0.0.0.
DestroyingamultimachineprojectIfwewanttocompletelyremovethevirtualmachinesforourprojectfromourhostmachine,wecanusethevagrantdestroycommand,aswithnormalprojects.ThedifferencebeingthatVagrantwillaskustoconfirmtheremovalofeachmachinewithintheproject:
SummaryInthischapter,wesetupaVagrantprojectthatusesmultiplevirtualmachines.Duringthecourseofthischapter,welearnedhowtocreatemultiplevirtualmachineswithinasingleproject.Inordertoachievethis,wealsolookedathowtoassignspecificnamestotheseindividualmachines,howtoconnecttotheindividualmachinesoverSSH(aspreviouslyvagrantsshwouldtakeustojustasinglemachine),andhowtoconfiguretheindividualmachines,specifyingIPaddresses,baseboxes,anddifferentprovisioningoptionsforthem.
Now,welearnedthevastmajorityofVagrant’sfunctionalityandhowtouseitwithindifferentprojectscenarios.Inthenextchapter,wewilltakealookathowtobuildourowncustombaseboxtousewithourprojects,configuringablankoperatingsysteminstallationintoacompatiblebaseimage.
Chapter8.CreatingYourOwnBoxSofar,wehaveusedVagrantwiththefreelyavailablebaseboxes.TherearealsomanyotherexistingbaseVagrantboxesoutthere.InChapter9,HashiCorpAtlas,wewilltalkabouthowwecandiscoveranddistributebaseboxes.WhenwediscussedVagrantboxesinitiallyinChapter1,GettingStartedwithVagrant,andChapter2,ManagingVagrantBoxesandProjects,welearnedabouthowwecanexportaVagrantenvironmentintoanewbasebox.
Creatinganewbaseboxinvolvesuseithertakinganexistingbox,makingchangestoit,andexportingit,orcreatinganewvirtualmachineentirely,installingtheoperatingsystemandbuildingupabaseboxforexport.Inthischapter,wewilltakealookathowwecantakeaLinuxinstallationdiskandturnitintoaworkingVagrantbasebox,whichwecanfurthercustomizeasmuchaswelike.
Inthischapter,youwilllearnaboutthefollowingtopics:
HowtocreateanewVirtualBoxmachine,suitablyconfiguredforVagrantHowtoinstalltheVirtualBoxGuestAdditionsHowtosetuptheLinuxinstallationtoletVagrantloginHowtoinstallPuppetHowtoinstallChefHowtocleanuptheboxHowtoexporttheVMintoabasebox
GettingstartedInordertocreateanewbasebox,weneedtodownloadacopyoftheoperatingsystemwewanttouse(wewilluseUbuntuServerVersion13.0464-bitfromhttp://releases.ubuntu.com/raring/).WethenneedtouseVirtualBoxtocreateavirtualmachine,poweredbytheoperatingsystemwehavedownloaded.Next,weneedtoconfigurethevirtualmachineforVagrant.Finally,weneedtoexportthevirtualmachineintoaVagrantbasebox.
TipYoucanalsouseotherdistributionsofLinuxorevenWindowsifyouwish.Specificswillvarywiththeoperatingsystemused,soyouwillneedtoconsulttherelevantdocumentation.
TherequirementsforanewbaseboxaredetailedontheVagrantwebsite(https://docs.vagrantup.com/v2/boxes/base.html).
PreparingtheVirtualBoxmachineInordertocreatethevirtualmachinewithVirtualBox,weneedtoopentheVirtualBoxandclickontheNewbuttonintheupper-leftcorneroftheVirtualBoxtostarttheprocess:
Let’snamethemachinevagrant-ubuntu-raring.ThisistheformatrecommendedbyVagrant.SelectLinuxintheTypedropdownandVersionasUbuntu(64bit):
Vagrantrecommendssettingamemoryallocationof360MB.Thisistypicallysufficientforabaseinstallation,anduserscanoverridethiswithintheirVagrantfileiftheyneedmoreresources:
Weneedourvirtualmachinetohavesomestorageallocation,solet’sselectCreateavirtualharddrivenow:
WeneedtoselectVMDK(VirtualMachineDisk)asthedisktype:
Weneedtocreateadrive,whichisdynamicallyallocated:
Let’sgivethedriveamaximumlimitof40.00GB;theVagrantdocumentationsuggeststhatthisistypicallysufficientformanyprojects:
ClickingonCreatewillthensavethevirtualmachinewithinVirtualBox.Weneedtomakesomeadditionalconfigurationchanges,whicharenotapartofthecreationwizard,solet’sclickontheVMontheleft-handsideofthescreen,andthenclickontheSettingsbutton:
ThefirstadditionalchangeisAudio,solet’sturnthisoff:
WeneedtoensurethatthenetworkadapterconfiguredwithinVirtualBoxisenabledandusesNAT.Withoutthis,Vagrantwon’twork:
Finally,let’sturnoffUSBsupport,asthisisgenerallynotrequired:
Nowweneedtoswitchonthevirtualmachine.Whenitpowerson,itasksustoselectastartupdisk,whichcontainstheoperatingsystemwewishtoinstall.Clickingonthefoldericononthisscreenletsusselectacustomfile;inourcase,thiswillbeourubuntu-13.04-server-amd64.isofile.
Thevirtualmachinewillthenbootfromtheimagefileandtakeustotheinstallationprocess.Weshouldfollowthisprocesstosetupthemachine.
TherearesomespecificvaluesforsomethingsthatVagrantexpects,sowhereverappropriateweshouldensurethatwesetthemasfollows:
Byconvention,theoperatingsystem’shostnameshouldbeofthevagrant-operating-system-nameformat,forexample,vagrant-ubuntu-raringThedomainisvagrantup.comTherootpasswordisvagrantThemainaccountusernameisvagrantThemainaccountpasswordisvagrant
Inmostothercases,thedefaultoptionswillbefine,aswewillconfigureotheraspectslater.Whenpromptedastoanypackagestoinstallbydefault,weshouldselecttoinstallopenssh-server.
VirtualBoxGuestAdditionsFirst,let’slogintoournewvirtualmachinewithinVirtualBox.Onceloggedin,attheterminal,weshouldrunapt-getupdatetoupdateourpackagemanager.
VagranthasasetoftoolscalledGuestAdditionsthatprovidesomekeyintegrationpointsbetweenthevirtualmachineandVirtualBox;thisincludessupportforsharedfoldersandnetworkingintegration.
Toinstallthesetools,oncetheVMisrunning,weshouldclickontheDevicesmenuwithinVirtualBoxandclickonInstallGuestAdditions…(Host+D):
ThissimplybootsavirtualCDwithinthevirtualmachine;westillneedtoactuallyinstalltheGuestAdditions,asfollows:
1. Thefirststepistoinstallaprerequisite,whicharetheLinuxheaders:
sudoapt-getinstalllinux-headers-$(uname-r)build-essential
2. Next,wewillmountthevirtualCD,whichVirtualBoxhasloadedupintoafolderwithintheVM:
sudomount/dev/cdrom/media/cdrom
3. Finally,wewillruntheinstallationcommand:
sudosh/media/cdrom/VBoxLinuxAdditions.run
VagrantauthenticationVagrantcommunicateswithbaseboxesoverSSH.Vagrantitselfhasaprivatekey,forwhichweneedtoinstallthecorrespondingpublickeyintothevirtualmachine.Vagrantexpectsaspecificuserwithapredefinedpasswordtoalsobewithinthemachine,andtheuserneedstobeconfiguredsothatitisn’tpromptedforthepasswordwhenattemptingtoperformactionsthatrequireelevatedprivileges(sudo).
VagrantuserandadmingroupProvidedwecreatedtheVagrantuserduringtheinstallationprocess(asperthemainaccountuserandpasswordmentionedearlier),wethenneedtocreateanadmingroupandaddtheVagrantusertothisgroup.
First,weneedtocreatethegroup:
Sudogroupaddadmin
ToaddtheVagrantusertothisgroup,runthefollowingcommand:
Sudousermod-a-Gadminvagrant
ThesudoersfileInordertostopthevirtualmachineaskingfortheuser’spasswordwhenrunningelevatedactions,weneedtomodifythesudoersfile.Thisisafilethattellstheoperatingsystemwhichuserscanperformelevatedactionsandthesettingsaroundthem.Moreinformationcanbefoundathttps://help.ubuntu.com/community/Sudoers.Weneedtoaddaconfigurationlinetothisfile,whichtellstheoperatingsystemnottopromptforthepassword.Becausethefileisveryimportant,andanincorrectconfigurationwouldbreaktheoperatingsystem,thereisaprogrambuiltintoUbuntu,whichwon’tsaveifthefileisnoteditedcorrectly.
First,let’srunthisprogram:
visudo
Atthebottomofthefile,let’saddthislinetopreventtheoperatingsystemfrompromptingforthepassword:
%adminALL=(ALL)NOPASSWD:ALL
AnotherrequirementofVagrantisthatweaddthefollowinglinenearthetopofthefile:
Defaultsenv_keep="SSH_AUTH_SOCK"
Wealsoneedtodisablerequirettyinthesudoersfilebycommentingouttheappropriatelineasfollows:
#Defaultrequiretty
Tiprequirettyisanoptionthatrequiresuserstohaveaphysicalconnectiontoaserverinordertorunthesudocommands.
Insecurepublic/privatekeypairTheinsecurepublicandprivatekeypairispubliclyavailableathttps://github.com/mitchellh/vagrant/tree/master/keys/.
TipAnupcomingversionofVagrantwillchangehowVagrantworkswiththeseinsecurekeys.Whendetected,theywillbereplacedwithnewkeysforyourmachine;however,attimeofwriting,thishasnotyetbeenreleased.
Weneedtocopythecontentsofthepublickeyandpasteitintotheauthorized_hostsfile.ProvidedweareloggedinastheVagrantuser,wecanrunthefollowingcommandtoletuseditthisfile:
nano~/.ssh/authorized_hosts
Ifthe.sshfolderdoesnotalreadyexist,wefirstneedtocreateitusingthemkdircommand.Alternatively,wecandownloadthefilecontentsandputitstraightintotheauthorized_hostsfile:
wget
https://raw.github.com/mitchellh/vagrant/master/keys/
vagrant.pub–O~/.ssh/authorized_hosts
NoteThe.sshdirectoryneedstohavepermissionsof0700,andtheauthorized_hostsfileneedstohavepermissionsof0644(chmod0644~/.ssh/authorized_keys).
ProvisionersBecauseVagrantprovidessupportforprovisioners,weshouldinstalltheseintothevirtualmachinesothatVagrantcantellthemtoprovisionourenvironments.
InstallingPuppetPuppetisinstalledusingthebuilt-inpackagemanager:
sudoapt-getinstallpuppet
TipTheversionofPuppetinthevariousoperatingsystemrepositoriesmaybeslightlydated.PuppetcanalsobeinstalledmanuallyorviatherepositorysiteprovidedbyPuppetLabs.MoreinformationisavailableonthePuppetlabswebsiteathttp://docs.puppetlabs.com/guides/installation.html.
InstallingChefAspertheChefdocumentationathttps://www.chef.io/download-chef-client/,wecangetasinglecommandtoinstallChefforus:
curl-Lhttps://www.chef.io/chef/install.sh|sudobash
CleaninguptheVMBeforewepackageupthevirtualmachineintoaVagrantbasebox,let’scleanupsomeofthefilesweused.Wemadeuseofthetmpfolder,solet’semptythis.Weshouldalsocleanupourpackagemanager’scache,asthisusesadditionalspacewhenthebaseboxispackaged:
rm–rf/tmp/*
sudoapt-getclean
ExportFinally,weuseVagrant’spackagesubcommandonthehostmachine(nottheguest)topackageupthebox:
vagrantpackage--basevagrant-ubuntu-raring
ThecompletedetailsofthepackagesubcommandareavailableontheVagrantwebsite(http://docs.vagrantup.com/v2/cli/package.html).
SummaryInthischapter,welearnedhowtocreate,abaseboxforourVagrantprojectsfromscratch.Thiscanbeusedtocreatebaseboxesfromoperatingsystems,whichdon’tnecessarilyhaveboxesavailabletodownload.
Now,weknowhowtocreate,manage,distribute,andevenbuilddevelopmentenvironmentsfromscratchforourprojects!
Next,wewilltakealookatVagrantCloud,whichletsussearchforanddiscoverdifferentbaseboxesaswellaslettingusdistributeourownbox—eithertothepublicortoaprivateteam.VagrantCloudalsohasthefunctionalitytoallowustoshareourVagrantdevelopmentenvironmentwithothers—bethattodemonstratethefunctionalitywehavebuiltonaVagrant-supportedproject,ortoprovideSSHaccesstoateammemberwhocanhelpuswithsupportissues.
Chapter9.HashiCorpAtlasHashiCorpAtlas(https://atlas.hashicorp.com),formerlyVagrantCloud,isasuiteofonlineservicesprovidedbyHashiCorp(thecommercialcompanybehindVagrant),whichaddsadditionalcapabilitiestoVagrantandbringstogethermanyoftheiropensourcecomponents.Primarily,Atlassupportstwofeatures:
VagrantShare:TheabilitytoshareaccesstoyourVagrantenvironmentandtoallowotherstoremotelyconnecttoitVagrantboxdiscoveryandsharing:TheabilitytoshareVagrantboxeswithothers,hostingthemetadataforboxes,theirversions,andfacilitatingboxupdates
Thesefeaturesareavailablefreeofcharge,thoughpayingcustomerscangainaccesstoadditionalfunctionality,includingthefollowing:
CustomandstaticdomainnamesforVagrantSharePrivateboxesthatcanbesharedwithspecificteamsprivatelyBoxhosting:VagrantCloudwillactuallystoretheboxfileontheirplatformaswellasthemetadataSupportforWindowsandMacVagrantboxesGranularsupportforuseraccesscontrols
Inthischapter,youwilllearnaboutthefollowingtopics:
HowtodiscoveranduseboxesprovidedonAtlasHowtodistributeyourownboxesonAtlasHowtoallowotherstoconnecttoyourVagrantmachinethroughAtlasHowtoshareyourVagrantmachinethroughAtlas
DiscoveringboxesTheAtlaswebsitecontainsadirectoryofpublicboxesforVagrant(https://atlas.hashicorp.com/boxes/search).Withinthisdirectory,wecansearchforthespecificoperatingsystemordistributionversionthatweareinterestedin:
Foreachresult,wecanseetheboxname,whichisformattedasthenameofthedistributorfollowedbyaslash,followedbythenameordistributionname.Inthefollowingcase,wehavetheUbuntu12.04LTSreleasethatHashiCorphasprovided(namedhashicorp/precise64):
Ifweclickinabox,wecanseewhichproviderstheboxsupports.Inthiscase,wecanusetheboxwithVirtualBox,VMwareFusion,andHyper-V.Itisimportanttouseboxesthatsupporttheproviderweareusing—notallboxessupportallproviders.
InstallingnewboxesToinstallapublicbox,weusethevagrantboxaddcommand,andpassthenameofthebox:
vagrantboxaddhashicorp/precise64
ThenameoftheboxcaneitherbeaURLorfilepathtoanexistingboxfile(forexample,ifwehaveonestoredonournetworkthatwewishtouse)oranAtlasboxname,likeintheprecedingcommand.
UpdatingexistingboxesOneofthekeybenefitsofusingAtlasforboxdiscoveryisthatchangesandversionsoftheseboxescanbemanaged.Ifaparticularboxcontainsabugorsecurityvulnerability,distributorsmayupdatetheirboxestofixtheseissues,orcontainnewfunctionality.Thiscanbeuseful,asitsavesustheneedtoupdateourprovisioningconfigurationtomaketheseupdates.
WheninaVagrantprojectsfolder,wecanrunthefollowingcommandtocheckforupdatesfortheprojectsboxandupdateit:
vagrantboxupdate
Thiswilldownloadthenewbox;however,wewon’tseetheeffectofthenewboxunlesswedestroyourVagrantmachineandrebuilditfromtheupdatedbox.
Ifwewanttoupdateaspecificbox,asopposedtotheonethatistiedtotheprojectwearein,wecanusetheboxflagtoprovidethenameoftheboxwewanttoupdate:
vagrantboxupdate--boxthe-box/name
CheckingforoutdatedboxesWecanquicklychecktoseewhetheranyoftheboxesweinstalledareoutofdate,byrunningthefollowingcommand:
vagrantboxoutdated--global
Ifweomittheglobalflag,thenthecommandisonlywithinthecontextofthecurrentVagrantprojectwiththeflagitrelatestoallboxesinstalled:
DistributingboxesTodistributeboxeswithAtlas,weneedtocreateanaccountandlogintotheAtlaswebsite(https://atlas.hashicorp.com/account/new).Theusernamethatweselectwhenregisteringisusedastheprefixforboxeswedistribute—unless,ofcourse,wegoontoapaidplan,whichhasorganizationalsupport,orwecollaboratewithothersonabox.Onceloggedin,weneedtoclickontheCreateBoxlinktogototheboxcreationform(https://atlas.hashicorp.com/boxes/new).
Onthispage,weneedtoprovideanameanddescriptionforourbox.Asweareonthefreeplan,wecannotmakethisaprivatebox,soitwillbemadepublic:
AstheboxesdistributedthroughAtlascanbeversioned,toletusrolloutnewupdatestousersofthebox,weneedtocreateaninitialversionforthebox,alongwithadescriptionofwhattheversioncontains:
Next,weneedtoclickonCreatenewprovidertoaddanewproviderthatissupportedbythisversionofthebox:
Finally,wespecifytheprovider,andprovideaURLtowheretheboxcanbedownloaded.WiththefreeversionofAtlas,weneedtoprovidealinktothebox,asthereisnostorageallowanceforVagrantCloudtohostthefileforus:
Onceaboxhasbeencreatedandpublished,itcanbediscoveredandinstalled,aswediscussedintheDiscoveringboxessection,bythepublic,orbyususingthenameoftheboxinourVagrantfile,forexample,mkpeacock/testbox.
SharingandconnectingwithAtlasWithAtlas,therearethreenewVagrantcommandsatourdisposal,whichareasfollows:
vagrantconnect
vagrantshare
vagrantlogin
LoggingVagrantintoVagrantCloudInordertoshareourVagrantenvironment,weneedtoconnectourVagrantinstallationtoourVagrantCloudaccount.Wecanchecktoseewhetherthisisalreadythecasebyrunningthefollowingcommand:
vagrantlogin--check
Thiswillchecktoseewhetherwearealreadyloggedin:
Aswearenotloggedin,weneedtorunvagrantlogininordertologin.First,wearepromptedforourusernameore-mailaddressfromAtlas,andthenforourpassword:
Onceloggedin,wecanusethelogoutflagtologoutofAtlas:
vagrantlogin--logout
SharingaVagrantvirtualmachineoverHTTP(S)InordertosharethewebinterfacewithaVagrantvirtualmachine,thevirtualmachinemusteitherhaveitsownIPaddressonourlocalnetworkoranHTTP(S)portforwardedfromtheguesttothehostmachine.Vagrantrequiresthissothatyourhostmachinecanconnecttotherelevantportonyourvirtualmachine.
ProvidedwehaveeithergiventhevirtualmachineitsownnetworkaddressorforwardaporttoarecognizableHTTP(S)port,thenwecanrunthevagrantsharecommandtocreateapublicURLforthismachine.WecanalsospecifytheHTTPandHTTPSportsthatweareusingonthevirtualmachineifVagrantdoesn’tdetectthemwiththe--httpand--httpsflags:
Afterrunningvagrantshare,VagrantwillgenerateanameandURLtoaccessthesharefrom.Asweareonafreeplan,wecannotcustomizeorreserveURLs.Ourterminalsessionisnowlockedtorunthissharingsession,soweneedtoleavethisrunning.IfwevisittheURLinabrowser,weshouldbeabletoseewhateverwebservicewearerunningonourvirtualmachine:
Tostopsharing,weneedtoclosetheterminalorstopthevagrantsharecommandfromrunning:
SharingandconnectingtoaVagrantvirtualmachineBydefault,vagrantshareonlysharesHTTP(S)traffic.Wecan,however,passthe--sshflagtoalsoshareSSHaccessthatwillallowotherVagrantuserstoconnecttothemachine:
vagrantshare--ssh
Afterrunningthiscommand,wewillbepromptedtoprovideandconfirmapasswordtobeusedtoencrypttheSSHkeysothattheusersarerequiredtoprovideapasswordwhentheyconnect.Ifrequired,thiscanbeomittedwiththe--ssh-no-passwordflaginsteadof--ssh.WecanalsomakeasingleuseSSHconnectionwith--ssh-once,asshowninthefollowingscreenshot:
Aswitharegularsharecommand,wegetaURLandaname.WecanpreventHTTP(S)frombeingsharedbypassingthe--disable-httpflag.
Oncethesharingprocessisrunning,wecanprovidethenameandpasswordtowhomeverwewanttobeabletoconnecttothemachine.Theysimplyrunthevagrantconnect--sshdifficult-elephant-4464command(wherethelastparameteristhenameoftheconnectiongeneratedbyAtlas)tostartaconnectionwiththemachine,andprovidethepasswordwhenprompted:
TheuseristhenloggedintotheVagrantmachine!
SummaryInthischapter,welearnedabouttheextrafunctionalityofferedbytheVagrantCloudservice.
Wediscoveredhowtofindthird-partyVagrantboxesforusewithourprojects,howtocheckforupdatesforboxesthatuseAtlas,andhowtodistributeourownbaseboxesthroughAtlas.Finally,welookedatauthenticatingwithAtlastoshareourVagrantenvironmentwithourcolleagues.
NowthatweknowmoreaboutthefunctionalityofferedbyVagrant,wecanuseiteffectivelyinourprojects!
AppendixA.ASampleLEMPStackNowthatwehaveagoodknowledgeofusingVagranttomanagesoftwaredevelopmentprojectsandhowtousethePuppetprovisioningtool,let’stakealookathowtousethesetoolstobuildaLinux,Nginx,MySQL,andPHP(LEMP)developmentenvironmentwithVagrant.
Inthisappendix,youwilllearnthefollowingtopics:
HowtoupdatethepackagemanagerHowtocreateaLEMP-baseddevelopmentenvironmentinVagrant,includingthefollowing:
HowtoinstalltheNginxwebserverHowtocustomizetheNginxconfigurationfileHowtoinstallPHPHowtoinstallandconfigureMySQLHowtoinstalle-mailsendingservices
WiththeexceptionofMySQL,wewillcreatesimplePuppetmodulestoinstallandmanagethesoftwarerequired.ForMySQL,wewillusetheofficialPuppetmodulefromPuppetLabs;thismodulemakesitveryeasyforustoinstallandconfigureallaspectsofMySQL.
CreatingtheVagrantprojectFirst,wewanttocreateanewproject,solet’screateanewfoldercalledlemp-stackandinitializeanewubuntu/trusty64Vagrantprojectwithinitbyexecutingthefollowingcommands:
mkdirlemp-stack
cdlemp-stack
vagrantinitubuntu/trusty64ub
TheeasiestwayforustopullintheMySQLPuppetmoduleistosimplyadditasagitsubmoduletoourproject.Inordertoaddagitsubmodule,ourprojectneedstobeagitrepository,solet’sinitializeitasagitrepositorynowtosavetimelater:
gitinit
Tomakethevirtualmachinereflectiveofareal-worldproductionserver,insteadofforwardingthewebserverportonthevirtualmachinetoanotherportonourhostmachine,wewillinsteadnetworkthevirtualmachine.Thismeansthatwewouldbeabletoaccessthewebserverviaport80(whichistypicalonaproductionwebserver)byconnectingdirectlytothevirtualmachine.
InordertoensureafixedIPaddresstowhichwecanallocateahostnameonournetwork,weneedtouncommentthefollowinglinefromourVagrantfilebyremovingthe#fromthestartoftheline:
#config.vm.network"private_network",ip:"192.168.33.10"
TheIPaddresscanbechangeddependingontheneedsofourproject.
AsthisisasampleLEMPstackdesignedforweb-basedprojects,let’sconfigureourprojectsdirectorytoarelevantwebfolderonthevirtualmachine:
config.vm.synced_folder".","/var/www/project",type:"nfs"
Wewillstillneedtoconfigureourwebservertopointtothisfolder;however,itismoreappropriatethanthedefaultmappinglocationof/vagrant.
BeforewerunourPuppetprovisionertoinstallourLEMPstack,weshouldinstructVagranttoruntheapt-getupdatecommandonthevirtualmachine.Withoutthis,itisn’talwayspossibletoinstallnewpackages.So,let’saddthefollowinglinetoourVagrantfilewithinthe|config|block:
config.vm.provision"shell",inline:"apt-getupdate"
AswewillputourPuppetmodulesandmanifestsinaprovisionfolder,weneedtoconfigureVagranttousethecorrectfoldersforourPuppetmanifestsandmodulesaswellasthedefaultmanifestfile.AddingthefollowingcodetoourVagrantfilewilldothisforus:
config.vm.provision:puppetdo|puppet|
puppet.manifests_path="provision/manifests"
puppet.module_path="provision/modules"
puppet.manifest_file="vagrant.pp"
end
CreatingthePuppetmanifestsLet’sstartbycreatingsomefoldersforourPuppetmodulesandmanifestsbyexecutingthefollowingcommands:
mkdirprovision
cdprovision
mkdirmodules
mkdirmanifests
Foreachofthemoduleswewanttocreate,weneedtocreateafolderwithintheprovision/modulesfolderforthemodule.Withinthisfolder,weneedtocreateamanifestsfolder,andwithinthis,ourPuppetmanifestfile,init.pp.Structurally,thislookssomethinglikethefollowing:
|--provision
||--manifests
||`--vagrant.pp
|`--modules
||--ourmodule
||--manifests
|`--init.pp
`--Vagrantfile
InstallingNginxLet’stakealookatwhatisinvolvedtoinstallNginxthroughamoduleandmanifestfileprovision/modules/nginx/manifests/init.pp.First,wedefineourclass,passinginavariablesothatwecanchangetheconfigurationfileweuseforNginx(usefulforusingthesamemodulefordifferentprojectsordifferentenvironmentssuchasstagingandproductionenvironments),thenweneedtoensurethatthenginxpackageisinstalled:
classnginx($file='default'){
package{"nginx":
ensure=>present
}
TipNotethatwehavenotclosedthecurlybracketforthenginxclass.Thatisbecausethisisjustthefirstsnippetofthefile;wewillcloseitattheend.
BecausewewanttochangeourdefaultNginxconfigurationfile,weshouldupdatethecontentsoftheNginxconfigurationfilewithoneofourown(thiswillneedtobeplacedintheprovision/modules/nginx/filesfolder;unlessthefileparameterispassedtotheclass,thefiledefaultwillbeused):
file{'/etc/nginx/sites-available/default':
source=>"puppet:///modules/nginx/${file}",
owner=>'root',
group=>'root',
notify=>Service['nginx'],
require=>Package['nginx']
}
Finally,weneedtoensurethatthenginxserviceisactuallyrunningonceithasbeeninstalled:
service{"nginx":
ensure=>running,
require=>Package["nginx"]
}
}
Thiscompletesthemanifest.Wedostill,however,needtocreateadefaultconfigurationfileforNginx,whichissavedasprovision/modules/nginx/files/default.Thiswillbeusedunlesswepassafileparametertothenginxclasswhenusingthemodule.Thesamplefilehereisabasicconfigurationfile,pointingtothepublicfolderwithinoursyncedfolder.Theservernameoflemp-stack.localmeansthatNginxwilllistenforrequestsonthathostnameandwillservecontentfromourprojectsfolder:
server{
listen80;
root/var/www/project/public;
indexindex.phpindex.htmlindex.htm;
server_namelemp-stack.local;
location/{
try_files$uri$uri//index.php?$query_string;
}
location~\.php${
try_files$uri=404;
fastcgi_split_path_info^(.+\.php)(/.+)$;
#fastcgi_pass127.0.0.1:9000;
fastcgi_paramSERVER_NAME$host;
fastcgi_passunix:/var/run/php5-fpm.sock;
fastcgi_indexindex.php;
fastcgi_intercept_errorson;
includefastcgi_params;
}
location~/\.ht{
denyall;
}
location~*\.(jpg|jpeg|gif|css|png|js|ico|html)${
access_logoff;
expiresmax;
}
location~*\.svgz{
add_headerContent-Encoding"gzip";
}
}
TipBecausethisconfigurationfilelistensforrequestsonlemp-stack.local,weneedtoaddarecordtothehostsfileonourhostmachine,whichwillredirecttrafficfromlemp-stack.localtotheIPaddressofourvirtualmachine.
InstallingPHPToinstallPHP,weneedtoinstallarangeofrelatedpackages,includingtheNginxPHPmodule.Thiswouldbeinthefileprovision/modules/php/manifests/init.pp.
Onmorerecent(withinthepastfewyears)LinuxandPHPinstallations,PHPusesahandlercalledphp-fpmasabridgebetweenPHPandthewebserverbeingused.ThismeansthatwhennewPHPmodulesareinstalledorPHPconfigurationsarechanged,weneedtorestartthephp-fpmserviceforthesechangestotakeeffect,whereasinthepast,itwasoftenthewebserversthatneededtoberestartedorreloaded.
TomakeoursimplePHPPuppetmoduleflexible,weneedtoinstallthephp5-fpmpackageandrestartitwhenothermodulesareinstalled,butonlywhenweuseNginxonourserver.Toachievethis,wecanuseaclassparameter,whichdefaultstotrue.Thisletsususethesamemoduleinserversthatdon’thaveawebserver,andwherewedon’twanttohavetheoverheadoftheFPMservice,suchasaserverthatrunsbackgroundjobsorprocessing:
classphp($nginx=true){
Ifthenginxparameteristrue,thenweneedtoinstallphp5-fpm.Sincethispackageisonlyinstalledwhentheflagissettotrue,wecannothavePHPanditsmodulesrequiringornotifyingthephp-fpmpackage,asitmaynotbeinstalled;soinsteadweneedtohavethephp5-fpmpackagesubscribetothesepackages:
if($nginx){
package{"php5-fpm":
ensure=>present,
subscribe=>[Package['php5-dev'],Package['php5-curl'],
Package['php5-gd'],Package['php5-imagick'],Package['php5-mcrypt'],
Package['php5-mhash'],Package['php5-pspell'],Package['php5-json'],
Package['php5-xmlrpc'],Package['php5-xsl'],Package['php5-mysql']]
}
}
TherestofthemanifestcanthensimplybetheinstallationofthevariousPHPmodulesthatarerequiredforatypicalLEMPsetup:
package{"php5-dev":
ensure=>present
}
package{"php5-curl":
ensure=>present
}
package{"php5-gd":
ensure=>present
}
package{"php5-imagick":
ensure=>present
}
package{"php5-mcrypt":
ensure=>present
}
package{"php5-mhash":
ensure=>present
}
package{"php5-pspell":
ensure=>present
}
package{"php5-xmlrpc":
ensure=>present
}
package{"php5-xsl":
ensure=>present
}
package{"php5-cli":
ensure=>present
}
package{"php5-json":
ensure=>present
}
}
InstallingtheMySQLmoduleBecausewearegoingtousethePuppetmoduleforMySQLprovidedbyPuppetLabs,installingthemoduleisverystraightforward;wesimplyadditasagitsubmoduletoourprojectwiththefollowingcommand:
gitsubmoduleaddhttps://github.com/puppetlabs/puppetlabs-mysql.git
provision/modules/mysql
TipYoumightwanttouseaspecificreleaseforthismodule,asthecodechangesonasemi-regularbasis.Astablereleaseisavailableathttps://github.com/puppetlabs/puppetlabs-mysql/releases/tag/3.1.0.
DefaultmanifestFinally,weneedtopullthesemodulestogether,andinstallthemwhenourmachineisprovisioned.Todothis,wesimplyaddthefollowingmodulestoourvagrant.ppmanifestfileintheprovision/manifestsfolder.
InstallingNginxandPHPWeneedtoincludeournginxclassandoptionallyprovideafilenamefortheconfigurationfile;ifwedon’tprovideone,thedefaultwillbeused:
class{
'nginx':
file=>'default'
}
SimilarlyforPHP,weneedtoincludetheclassandinthiscase,passannginxparametertoensurethatitinstallsPHP5-FPMtoo:
class{
'php':
nginx=>true
}
HostnameconfigurationWeshouldtellourVagrantvirtualmachinewhatitshostnameisbyaddingahostresourcetoourmanifest:
host{'lemp-stack.local':
ip=>'127.0.0.1',
host_aliases=>'localhost',
}
E-mailsendingservicesBecausesomeofourprojectsmightinvolvesendinge-mails,weshouldinstalle-mailsendingservicesonourvirtualmachine.Asthesearesimplytwopackages,itmakesmoresensetoincludetheminourVagrantmanifest,asopposedtotheirownmodules:
package{"postfix":
ensure=>present
}
package{"mailutils":
ensure=>present
}
MySQLconfigurationBecausetheMySQLmoduleisveryflexibleandmanagesallaspectsofMySQL,thereisquiteabitforustoconfigure.Weneedtoperformthefollowingsteps:
1. Createadatabase.2. Createauser.3. Givetheuserpermissiontousethedatabase(grants).4. ConfiguretheMySQLrootpassword.5. InstalltheMySQLclient.6. InstalltheMySQLclientbindingsforPHP.
TheMySQLserverclasshasarangeofparametersthatcanbepassedtoconfigureit,includingdatabases,users,andgrants.So,first,weneedtodefinewhatthedatabases,users,andgrantsarethatwewanttobeconfigured:
$databases={
'lemp'=>{
ensure=>'present',
charset=>'utf8'
},
}
$users={
'lemp@localhost'=>{
ensure=>'present',
max_connections_per_hour=>'0',
max_queries_per_hour=>'0',
max_updates_per_hour=>'0',
max_user_connections=>'0',
password_hash=>'MySQL-Password-Hash',
},
}
NoteThepassword_hashparameterhereisforahashgeneratedbyMySQL.YoucangenerateapasswordhashbyconnectingtoanexistingMySQLinstanceandrunningaquerysuchasSELECTPASSWORD('password').
Thegrantmapsouruseranddatabaseandspecifieswhatpermissionstheusercanperformonthatdatabasewhenconnectingfromaparticularhost(inthiscase,localhost—sofromthevirtualmachineitself):
$grants={
'lemp@localhost/lemp.*'=>{
ensure=>'present',
options=>['GRANT'],
privileges=>['ALL'],
table=>'lemp.*',
user=>'lemp@localhost',
},
}
WethenpassthesevaluestotheMySQLserverclass.WealsoprovidearootpasswordforMySQL(unlikeearlier,thisisprovidedinplaintext),andwecanoverridetheoptionsfromtheMySQLconfigurationfile.ThisisunlikeourownNginxmodulethatprovidesafullfile—inthisinstance,theMySQLmoduleprovidesatemplateconfigurationfileandthechangesarereplacedinthattemplatetocreateaconfigurationfile:
class{'::mysql::server':
root_password=>'lemp-root-password',
override_options=>{'mysqld'=>{'max_connections'=>'1024'}},
databases=>$databases,
users=>$users,
grants=>$grants,
restart=>true
}
Aswewillhaveawebserverrunningonthismachine,whichneedstoconnecttothisdatabaseserver,wealsoneedtheclientlibraryandtheclientbindingsforPHP,sothatwecanincludethemtoo:
include'::mysql::client'
class{'::mysql::bindings':
php_enable=>true
}
LaunchingthevirtualmachineInordertolaunchournewvirtualmachine,wesimplyneedtorunthefollowingcommand:
Vagrantup
AsperChapter6,ProvisioningVagrantMachineswithPuppet,Ansible,andChef,weshouldnowseeourVMbootandthevariousPuppetphasesexecute.Ifallgoeswell,weshouldseenoerrorsinthisprocess.
SummaryInthischapter,welearnedaboutthestepsinvolvedincreatingabrandnewVagrantproject,configuringittointegratewithourhostmachine,andsettingupastandardLEMPstackusingthePuppetprovisioningtool.NowyoushouldhaveabasicunderstandingofVagrantandhowtouseittoensurethatyoursoftwareprojectsaremanagedmoreeffectively!
IndexA
Ansibleabout/UnderstandingAnsibleplaybooks/UnderstandingAnsibleinstalling/InstallingAnsibleoperatingsystems,URL/InstallingAnsibleinventory,creating/Creatinganinventoryplaybooks,creating/CreatingAnsibleplaybooksmodules/Modules–whatAnsiblecandosoftware,installing/Installingsoftwarecronmodule/Managingcroncommands,running/Runningcommandsusermodule,URL/Managingusersandgroupsgroupmodule,URL/Managingusersandgroupsroles,using/UsingAnsiblerolesGalaxy,URL/UsingAnsiblerolesused,forserverprovision/UsingAnsibletoprovisionserversprovisioningwith/ProvisioningwithAnsibleonVagrant
Ansible,filemanagementabout/Understandingfilemanagementfile,copying/Copyingafilesymlink,creating/Creatingasymlinkfolders,creating/Creatingfoldersgroupmodule,creating/Creatinggroupsusermodule,creating/Creatingusers
Ansiblesoftware,installingpackagemanager,updating/Updatingourpackagemanagernginxpackage,installing/Installingthenginxpackagenginxservice,running/Runningthenginxservice
aptmoduleURL/Updatingourpackagemanager,Installingthenginxpackage
Atlasboxes,discovering/Discoveringboxesboxes,URL/Discoveringboxesnewboxes,installing/Installingnewboxesexistingboxes,updating/Updatingexistingboxesoutdatedboxes,checkingfor/Checkingforoutdatedboxesaccount,URL/Distributingboxesboxes,distributing/Distributingboxesboxcreationform,URL/Distributingboxessharingwith/SharingandconnectingwithAtlas
connectingwith/SharingandconnectingwithAtlasVagrant,connectingtoVagrantCloud/LoggingVagrantintoVagrantCloudVagrantvirtualmachine,sharingoverHTTP(S)/SharingaVagrantvirtualmachineoverHTTP(S)Vagrantvirtualmachine,connectingto/SharingandconnectingtoaVagrantvirtualmachineVagrantvirtualmachine,sharingto/SharingandconnectingtoaVagrantvirtualmachine
authentication,Vagrantabout/Vagrantauthenticationadmingroup/Vagrantuserandadmingroupusergroup/Vagrantuserandadmingroupsudoersfile/Thesudoersfile
CChef
about/KnowingaboutChefcookbooks,creatingwith/CreatingcookbooksandrecipeswithChefrecipes,creatingwith/CreatingcookbooksandrecipeswithChefresources/Resources–whatChefcandocronresourcetype,managing/Managingcroncommands,running/Runningcommandsusers,managing/Managingusersandgroupsgroups,managing/Managingusersandgroupsgroups,creating/Creatinggroupsusers,creating/Creatinguserssudoersfile,updating/Updatingthesudoersfilecommonresourcefunctionalities/Knowingcommonresourcefunctionalitiesused,forprovisioningservers/UsingCheftoprovisionserversURL,fortutorial/UsingCheftoprovisionserversonVagrant,provisioningwith/ProvisioningwithChefonVagrant-solousing/UsingChef-soloroles,URL/UsingChef-solousing,inclient/servermode/UsingChefinclient/servermodeinstalling/InstallingChef
Chef,filemanagementabout/Understandingfilemanagementfile,copying/Copyingafilesymlink,creating/Creatingasymlinkfolders,creating/Creatingfoldersmultiplefolders,creatinginsingleprocesswithlooping/Creatingmultiplefoldersinasingleprocesswithlooping
Chef,resourcetypescron/Resources–whatChefcandoexecute/Resources–whatChefcandofile/Resources–whatChefcandogroup/Resources–whatChefcandopackage/Resources–whatChefcandoservice/Resources–whatChefcandotemplate/Resources–whatChefcandouser/Resources–whatChefcandoURL/Resources–whatChefcando
Chef,softwareinstallingabout/Installingsoftwarepackagemanager,updating/Updatingourpackagemanagernginxpackage,installing/Installingthenginxpackagenginxservice,running/Runningthenginxservice
Chef-solousing/UsingChef-solo
Chef-soloconfigurationURL/UsingCheftoprovisionservers
Chefcookbooksusing/UsingChefcookbooks
Chefrun,anatomyURL/UsingCheftoprovisionservers
client/servermodePuppetusing/UsingPuppetinclient/servermode
commandsautorunning/Autorunningcommands
configurableclasses,Puppetcreating/Creatingconfigurableclasses
cookbookscreating,withChef/CreatingcookbooksandrecipeswithChef
cronmoduleURL/Managingcron
Ffilemodule
URL/Creatingasymlink
Ggroupmodule
URL/ManagingusersandgroupsGuestAdditions,VirtualBox
about/VirtualBoxGuestAdditions
Hhostandguestmachineinteraction,managing
about/Managingintegrationbetweenhostandguestmachinesportforwarding/Portforwardingsyncedfolders/Syncedfoldersnetworking/Networking
hostnameconfiguring/Hostnameconfiguration
Iinventory,Ansible
creating/Creatinganinventory
LLEMPserver/Updatingourpackagemanager
Mmanifests
about/Defaultmanifestnginx,installing/InstallingNginxandPHPPHP,installing/InstallingNginxandPHPhostnameconfiguration/Hostnameconfiguratione-mailsendingservices/E-mailsendingservicesMySQLconfiguration/MySQLconfiguration
modules,Ansibleabout/Modules–whatAnsiblecandoApt/Modules–whatAnsiblecandoGit/Modules–whatAnsiblecandoService/Modules–whatAnsiblecandoCopy/Modules–whatAnsiblecandoURL/Modules–whatAnsiblecando
multimachineprojectdestroying/Destroyingamultimachineproject
multipleprovisionersusing,onsingleproject/Usingmultipleprovisionersonasingleproject
multiplevirtualmachinesusing,withVagrant/UsingmultiplemachineswithVagrantdefining/Definingmultiplevirtualmachinesconnecting,overSSH/ConnectingtothemultiplevirtualmachinesoverSSHnetworking/Networkingthemultiplevirtualmachinesprovisioning/Provisioningthemachinesseparately
MySQLinstalling/InstallingtheMySQLmoduleconfiguring/MySQLconfiguration
NNetworkFileSystem(NFS)/Syncedfoldersnetworking
about/Networkingnginx
installing/InstallingNginx,InstallingNginxandPHPnotifyparameter/Thenotify,subscribe,andrefreshonlyparameters
OOpscodecommunitysite,Chefcookbooks
URL/UsingChefcookbooks
Ppackagesubcommand/Exportparameters/ResourcesPHP
installing/InstallingPHP,InstallingNginxandPHPportforwarding
about/Portforwardingproject
creating/CreatingourfirstVagrantprojectprovisioners
about/ProvisionersPuppet,installing/InstallingPuppetChef,installing/InstallingChef
provisioningabout/ProvisioningwithVagrant/ProvisioningwithinVagrantwithPuppet,onVagrant/ProvisioningwithPuppetonVagrantwithAnsible,onVagrant/ProvisioningwithAnsibleonVagrantwithAnsible,onVagrant/ProvisioningwithAnsibleonVagrantwithChef,onVagrant/ProvisioningwithChefonVagrantwithSSH/ProvisioningwithSSH–arecapoverriding,viacommandline/Overridingprovisioningviathecommandline
provisioning,optionsShell/AutorunningcommandsPuppet/AutorunningcommandsAnsible/AutorunningcommandsChef/Autorunningcommands
Puppetabout/Puppetidempotentfeature/Puppetused,forcreatingmodules/CreatingmodulesandmanifestswithPuppetused,forcreatingmanifests/CreatingmodulesandmanifestswithPuppetclasses/Puppetclassesdefaultmanifests/DefaultPuppetmanifestsresource/Resourcesnotifyparameter/Thenotify,subscribe,andrefreshonlyparameterssubscribeparameter/Thenotify,subscribe,andrefreshonlyparametersrefreshonlyparameter/Thenotify,subscribe,andrefreshonlyparametersfilemanagement/Filemanagementcronresourcetype,managing/Cronmanagementcommands,running/Runningcommandsuserresourcetype,managing/Managingusersandgroups,Creatingusersgroupresourcetype,managing/Managingusersandgroups
userresourcetype,URL/Managingusersandgroupssudoersfile,updating/Updatingthesudoersfileconfigurableclasses,creating/Creatingconfigurableclassesmodules/Puppetmodulesused,forserverprovision/UsingPuppettoprovisionserversprovisioningwith,onVagrant/ProvisioningwithPuppetonVagrantusing,instandalonemode/UsingPuppetinstandalonemodeprovisioning,inaction/Puppetprovisioninginactionusing,inclient/servermode/UsingPuppetinclient/servermodeURL/UsingPuppetinclient/servermodeblog,URL/UsingPuppetinclient/servermodeinstalling/InstallingPuppet
Puppet,filemanagementabout/Filemanagementfile,copying/Copyingafilesymlink,creating/Creatingasymlinkfolders,creating/Creatingfoldersmultiplefolders,creating/Creatingmultiplefoldersinonego
Puppet,resourcetypes/Resourcestypes,URL/Resourcesrequisites/Resourcerequirementsexecution,ordering/Resourceexecutionorderingexecuting,instages/Executingresourcesinstages
Puppet,resourcetypescron/Resourcesexec/Resourcesfile/Resourcesgroup/Resourcespackage/Resourcesservice/Resourcesuser/Resources
PuppetForgeURL/Puppetmodules
Puppetmanifestscreating/CreatingthePuppetmanifestsnginx,installing/InstallingNginxPHP,installing/InstallingPHPMySQLmodule,installing/InstallingtheMySQLmoduleURL/InstallingtheMySQLmodule
Puppetsoftware,installingabout/Installingsoftwarepackagemanager,updating/Updatingourpackagemanagernginxpackage,installing/Installingthenginxpackage
nginxservice,running/RunningthenginxservicePuTTY
URL/ConnectingtothevirtualmachineoverSSH
Rrecipes
creating,withChef/CreatingcookbooksandrecipeswithChefrecipes,Chef
URL/UsingCheftoprovisionserversrefreshonlyparameter/Thenotify,subscribe,andrefreshonlyparameters
Sservers
provisioning,Chefused/UsingCheftoprovisionserversSSH
provisioningwith/ProvisioningwithSSH–arecapmultiplevirtualmachines,connectingto/ConnectingtothemultiplevirtualmachinesoverSSH
SSHprovisioningabout/Autorunningcommands
standalonemodePuppetusing/UsingPuppetinstandalonemode
subscribeparameter/Thenotify,subscribe,andrefreshonlyparameterssudoersfile
URL/Thesudoersfileabout/Thesudoersfile
/Thesudoersfilesupervisord
URL/CreatingmodulesandmanifestswithPuppetabout/DefaultPuppetmanifests
supervisormoduleURL/DefaultPuppetmanifests
symlinkcreating/Creatingasymlink
syncedfoldersabout/Syncedfolders
Ttemplatemodule
URL/Copyingafile
Uusermodule
URL/Managingusersandgroups,Creatingusers
VVagrant
about/IntroducingVagrant,ToomanyVagrants!URL/IntroducingVagrant,RequirementsforVagrant,ConnectingtothevirtualmachineoverSSHconfigurationfile/IntroducingVagrantrequisites/RequirementsforVagrantVirtualBox,installing/InstallingVirtualBoxinstalling/InstallingVagrantdownloadpage/InstallingVagrantproject,creating/CreatingourfirstVagrantproject,CreatingtheVagrantproject-controlledguestmachines,controlling/ManagingVagrant-controlledguestmachinesvirtualmachine,poweringup/PoweringupaVagrant-controlledvirtualmachinevirtualmachine,suspending/Suspendingavirtualmachinevirtualmachine,resuming/Resumingavirtualmachinevirtualmachine,shuttingdown/Shuttingdownavirtualmachineprovisioning,options/Autorunningcommandsprovisioningwith/ProvisioningwithinVagrantprovisioning,withChef/ProvisioningwithChefonVagrantmultiplevirtualmachines,using/UsingmultiplemachineswithVagrantdocumentation,URL/Gettingstartednewbasebox,URL/Gettingstartedauthentication/Vagrantauthentication
Vagrantauthenticationinsecurepublickeypair/Insecurepublic/privatekeypairinsecureprivatekeypair/Insecurepublic/privatekeypair
Vagrantboxesmanaging/ManagingVagrantboxesaddsubcommand/ManagingVagrantboxes,AddingVagrantboxeslistsubcommand/ManagingVagrantboxes,ListingVagrantboxesoutdatedsubcommand/ManagingVagrantboxes,Checkingforupdatesremovesubcommand/ManagingVagrantboxes,RemovingVagrantboxesrepackagesubcommand/ManagingVagrantboxes,RepackagingaVagrantboxupdatesubcommand/ManagingVagrantboxes,Updatingthecurrentenvironment’sboxadding/AddingVagrantboxeslisting/ListingVagrantboxesupdates,checkingfor/Checkingforupdatesremoving/RemovingVagrantboxesrepackaging/RepackagingaVagrantboxcurrentenvironmentsbox,updating/Updatingthecurrentenvironment’sbox
Vagrantboxes,Atlasdiscovering/Discoveringboxesnewboxes,installing/Installingnewboxesexistingboxes,updating/Updatingexistingboxesoutdatedboxes,checkingfor/Checkingforoutdatedboxesdistributing/Distributingboxes
Vagrantvirtualmachine,Atlassharing,overHTTP(S)/SharingaVagrantvirtualmachineoverHTTP(S)
VirtualBoxinstalling/InstallingVirtualBox
VirtualBoxmachinepreparing/PreparingtheVirtualBoxmachine
virtualmachinecleaningup/CleaninguptheVMlaunching/Launchingthevirtualmachine
virtualmachine,Vagrant-controlledmanaging/ManagingVagrant-controlledguestmachinespoweringup/PoweringupaVagrant-controlledvirtualmachinesuspending/Suspendingavirtualmachineresuming/Resumingavirtualmachineshuttingdown/Shuttingdownavirtualmachinestarting,fromscratch/StartingfromscratchoffVagrantfilechanges,updating/UpdatingbasedonVagrantfilechangesconnectingto,overSSH/ConnectingtothevirtualmachineoverSSH
YYamlAin’tMarkupLanguage(YAML)
about/UnderstandingAnsible