{"id":43,"date":"2019-05-18T01:09:44","date_gmt":"2019-05-17T23:09:44","guid":{"rendered":"http:\/\/blog.nikster.de\/wordpress\/?p=43"},"modified":"2019-05-18T01:09:44","modified_gmt":"2019-05-17T23:09:44","slug":"how-to-set-up-a-puppet-infrastructure","status":"publish","type":"post","link":"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/18\/how-to-set-up-a-puppet-infrastructure\/","title":{"rendered":"How to set up a puppet infrastructure"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">What is puppet and why would I need it?<\/h4>\n\n\n\n<p>Puppet is an open source configuration management tool, that can help you to manage lots of servers without writing customized scripts for setup and maintenance for each one or each group of them.<br>It&#8217;s very powerful and comes with lots of modules already, for nearly every task you face.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">What&#8217;s this about<\/h4>\n\n\n\n<p>In this post I&#8217;ll cover how to set up a&#8221; puppet master&#8221; (control server), managing different environments on it (for teams and\/or test\/production) with r10k, writing a simple module, connecting a host to the master and configure it automatically.<br>The master will be puppet5, so we can fully utilize the power of hiera, which allows us to separate data (configs) from code (modules).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Pre-requisites<\/h4>\n\n\n\n<ul class=\"wp-block-list\"><li>Im using a vm with debian9 and 4GB RAM, once you start connecting many servers though, you&#8217;ll need much more RAM.<\/li><li>with puppet it is important to have ntp setup correctly on all hosts (apt-get install ntp should take care of everything)<\/li><li>make sure the master knows himself (\/etc\/hosts: 127.0.1.1       puppetmaster.your.domain  puppetmaster)<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"> Installation<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"deb http:\/\/apt.puppetlabs.com stretch puppet\" >> \/etc\/apt\/sources.list.d\/puppet.list\nwget apt.puppetlabs.com\/pubkey.gpg\napt-key add pubkey.gpg\napt-get update\napt-get install puppet-master-passenger<\/code><\/pre>\n\n\n\n<p>We&#8217;ll use puppetmaster with apache passenger here, this is more than sufficient for even big environments.<br>puppetserver is the future though, as it is more scalable in very large environments.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Setup<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>root@puppetmastertest:~# ls \/etc\/puppet\/\nauth.conf  code  hiera.yaml  puppet.conf<\/code><\/pre>\n\n\n\n<p>You&#8217;ll find the above structure in \/etc\/puppet.<br><strong>hiera.yaml<\/strong> basically describes the hierarchy puppet should search to lookup host(grou) infromation, Delete it for now, we&#8217;ll use it in our environments later.<br><strong>auth.conf<\/strong> is used to control catalog and ssl information your hosts are allowed to access (<strong>leave it, it should be sufficient for now<\/strong>).<br><strong>puppet.conf<\/strong> contains your log- and ssl paths, as well as a facter path and more (can be extended, see: https:\/\/puppet.com\/docs\/puppet\/5.3\/config_file_main.html) important for now are the log and ssl locations and also the path for facter.<br>(Enter the example from the next box into your puppet.conf)<br>The directory <strong>code<\/strong> contains modules and hieradata, normally everything is stored just there, but well use several environments, so we&#8217;ll first have to create the right structure.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[main]\nlogdir=\/var\/log\/puppet\nvardir=\/var\/lib\/puppet\nssldir=\/var\/lib\/puppet\/ssl\nrundir=\/var\/run\/puppet\nfactpath=$vardir\/lib\/facter\n\n[master]\nvardir = \/var\/lib\/puppet\ncadir  = \/var\/lib\/puppet\/ssl\/ca\nssl_client_header = SSL_CLIENT_S_DN\nssl_client_verify_header = SSL_CLIENT_VERIFY\ncertname = puppetmaster\ndns_alt_names = puppetmaster, puppetserver.your.domain<\/code><\/pre>\n\n\n\n<p>The [main] Section is pretty self explanatory, logs are stored in <strong>logdir<\/strong> and most other &#8220;stuff&#8221; related to the function of  puppet is stored in <strong>$vardir<\/strong> or related directories.<br>SSL-Certificates (as well as requests) from the clients are stored in <strong>$ssldir<\/strong> (We&#8217;ll come to that later), the reports for the puppetruns are stored under $vardir\/state and so on. <strong>$factpath<\/strong> is where puppet will look for custom facts.<br>The main section can be <strong>the same for master and clients<\/strong> but must not be.<br><br>The [master] section is specifically for the master itself.<br>Important here are <strong>dns_alt_names<\/strong> and <strong>certname<\/strong>, because puppetmaster brings it&#8217;s own CA (you can also use your own, but we won&#8217;t cover that here), so set especially dns_alt_names to whatever you think is useful when calling the master from the clients. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">connecting a client<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"deb http:\/\/apt.puppetlabs.com stretch puppet\" >> \/etc\/apt\/sources.list.d\/puppet.list\nwget apt.puppetlabs.com\/pubkey.gpg\napt-key add pubkey.gpg\napt-get update\napt-get install puppet<\/code><\/pre>\n\n\n\n<p>Let&#8217;s connect our first client and leave the directories for now. We&#8217;ll cover them once this works.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[main]\nserver = puppetmaster.your.domain\ncertname = puppettest1.your.domain\nenv = prod<\/code><\/pre>\n\n\n\n<p>Delete the master section.<br><strong>server<\/strong> is the fqdn of our puppetmaster<br><strong>certname<\/strong> is the name we want for our ssl servercertificate. This is a fact and will be important when working with facts later (e.g. in hiera.yaml)<br><strong>env<\/strong> is prod for now, because as long as we haven&#8217;t configured the master otherwise this is the only environment available. We&#8217;ll configure at least two later though, a testing and a productive environment.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>root@puppettest1:~# puppet agent -vot\nInfo: Caching certificate for ca\nInfo: csr_attributes file loading from \/etc\/puppet\/csr_attributes.yaml\nInfo: Creating a new SSL certificate request for puppettest1.your.domain\nInfo: Certificate Request fingerprint (SHA256): E5:71:47:CE:94:9B:A9:DC:DC:37:B7:92:89:BA:DD:78:75:D5:CC:72:06:A5:32:AF:83:8D:B0:5A:E9:81:3F:88\nInfo: Caching certificate for ca\nExiting; no certificate found and waitforcert is disabled<\/code><\/pre>\n\n\n\n<p>Use the above command to connect the client to the puppetmaster. puppet automatically creates a csr.<br>You can view and sign it on the master like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>puppet cert list\n  \"puppettest1.your.domain\" (SHA256) E5:71:47:CE:94:9B:A9:DC:DC:37:B7:92:89:BA:DD:78:75:D5:CC:72:06:A5:32:AF:83:8D:B0:5A:E9:81:3F:88\n\nroot@puppetmaster:~# puppet cert sign puppettest1.your.domain\nSigning Certificate Request for:\n  \"puppettest1.your.domain\" (SHA256) E5:71:47:CE:94:9B:A9:DC:DC:37:B7:92:89:BA:DD:78:75:D5:CC:72:06:A5:32:AF:83:8D:B0:5A:E9:81:3F:88\nNotice: Signed certificate request for puppettest1.your.domain\nNotice: Removing file Puppet::SSL::CertificateRequest puppettest1.your.domain at '\/var\/lib\/puppet\/ssl\/ca\/requests\/puppettest1.your.domain.pem'<\/code><\/pre>\n\n\n\n<p>If something goes wrong with signing (or you need to migrate a node), you may issue &#8220;puppet cert clean $certname&#8221; and delete the certificate files in $ssldir on the client. Then repeat the above.<br><strong>Tip:<\/strong> In large environments you will want to autosign certificates (policybased or just everything is up to you), read here on how to do this: https:\/\/puppet.com\/docs\/puppet\/5.3\/ssl_autosign.html<br><br>However, you should have a connected node by now. Let&#8217;s move on, filling it with stuff.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">configuring the master<\/h4>\n\n\n\n<p>I&#8217;d recommend to do all configuration of the environments in a git repository (check out how to do this: <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/06\/how-to-install-gitlab-and-work-with-it\/\">here<\/a>), leaving the management up to r10k.<br>However, you can just take the examples and put it into the respective directories:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>\/etc\/puppet\/code\/environments\/test<\/li><li>\/etc\/puppet\/code\/environments\/production<\/li><\/ul>\n\n\n\n<p>Whatever you do, you should have at least two environments. One for testing and one for production.<\/p>\n\n\n\n<p>In your repository (or in prod\/test) create the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi environment.conf\nmodulepath          = site-modules:modules:$basemodulepath\nconfig_version      = 'scripts\/config_version.sh $environmentpath $environment'<\/code><\/pre>\n\n\n\n<p>This contains the path where puppet should look for modules and the path for config_version.sh (needed to manage the environments with r10k).<br>You may look these up with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>puppet config print basemodulepath\n\/etc\/puppet\/code\/modules:\/usr\/share\/puppet\/modules\n\npuppet config print environment\nproduction\n\npuppet config print environmentpath\n\/etc\/puppet\/code\/environments<\/code><\/pre>\n\n\n\n<p>Create a Puppetfile in your repository and either use prod and test branch, or just create (for now) identical files in prod\/test folders:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>forge \"http:\/\/forge.puppetlabs.com\"\nmoduledir = 'modules'\n\n# Get a specific release from GitHub\n#mod 'puppet-gitlab',\n#   :git    => 'https:\/\/github.com\/voxpupuli\/puppet-gitlab' ,\n#   :ref    => '3.0.2'\n\n#mod 'helloworld', :local => true\n#mod 'base', :local => true\n#mod 'docker', :local => true\n#mod 'kubernetes', :local => true\n#mod \"puppetlabs\/inifile\"\n#mod \"puppetlabs\/stdlib\"\n#mod \"puppetlabs\/apt\"<\/code><\/pre>\n\n\n\n<p>The above is just an example, but a good one to walk you through it.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>forge<\/strong> is the location of an external url to get (forge based) modules from, I use the official puppelabs forge.<\/li><li><strong>moduledir<\/strong> tells puppet where to install these modules (relative to path)<\/li><li><strong>mod<\/strong> contains all attributes of the respective module. <br>Let&#8217;s take the first block, the name of the module is &#8216;puppet-gitlab&#8217; but I use another git source than the standard one  (<strong>:git<\/strong> =&gt; &#8216;http:\/\/$modulegit&#8217;), also I want a specific version (<strong>:ref <\/strong>=&gt; &#8216;3.0.2&#8217;).<br>In everyday work you&#8217;ll most probably want to use specific version in production environment, after you&#8217;ve tested them and &#8220;latest&#8221; (this is fetched as a default if you don&#8217;t provide a version) in test environments.<br>Try it out, with hiera properly configured (later), you&#8217;ll get a fully configured and operational gitlab server in no time.<br>However, when working with r10k, it will wipe everything that is not referenced (so don&#8217;t forget to commit your changes and push them before running it). So there is one more important parameter:<\/li><li> <strong>:local =&gt; true<\/strong><br>This is to indicate that r10k should not try to download this module from somewhere but also should not wipe it, because (most likely) it&#8217;s one of your self written modules (I&#8217;ll cover helloworld, base and docker later, so that you get the idea on how to write basic modules and how to combine them to sets).<br>Best create a git repo for those modules and later clone\/pull them separately if needed. <\/li><li>I commented nearly everything for now but you may already uncomment the last two modules:<br>&#8220;puppetlabs\/stdlib&#8221; and &#8220;puppetlabs\/apt&#8221; as they are pretty useful and I use them in every setup.<br>check it out: https:\/\/forge.puppet.com\/puppetlabs\/stdlib. inifile is useful when using the gitlab module.<\/li><\/ul>\n\n\n\n<p>Create the hiera.yaml in your repo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi hiera.yaml\n\n---\nversion: 5\ndefaults:\n  data_hash: yaml_data\n  datadir: hieradata\nhierarchy:\n  - name: nodes\n    path: nodes\/%{trusted.certname}.yaml\n  - name: Common\n    path: common.yaml<\/code><\/pre>\n\n\n\n<p>This tells hiera that it should use yaml (data_hash), could be json as well but I haven&#8217;t tried that at all.<br>Also it references the directory where hiera should look for configuration data (this is where our cluster\/note$resourceconfiguration goes).<br>Important is the hierarchy, because it tells hiera <strong>how<\/strong> and where to look for data.<br>It&#8217;s best to let hiera look from the <strong>most<\/strong> to the <strong>least<\/strong> specific definition.<br>In this example we create a simple hierarchy (under hieradata, which is a folder in our repo):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir hieradata\nmkdir nodes\ntouch nodes\/yourserver.your.domain.yaml<\/code><\/pre>\n\n\n\n<p>This way, if the agent connects the master the master looks under nodes (as configured) and finds a <strong>trusted.certname<\/strong>.yaml because it&#8217;s the certname of the client. Hiera stops here at the most specific match and starts applying whatever config we put into nodes\/yourserver.your.domain.yaml.<br>Next, create a file named common.yaml under hieradata.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>touch hieradata\/common.yaml<\/code><\/pre>\n\n\n\n<p><br>This file will contain the configuration everything that has no specific match.<br>As you can see, you may extend and improve this structure according to your needs, maybe naming your servers\/clusters FunctionDepartmentLocationVlan.your.domain or whatever and have different paths for different combinations of what may be implied by this structure at your company.<br>You may also specify <strong>different merge strategies<\/strong> for hiera like stop at first match or merge most and least specific, etc.<br>You get the idea. Let&#8217;s stick with our example for now, but if you are interested, read here: https:\/\/puppet.com\/docs\/puppet\/4.10\/hiera_merging.html<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi r10k.yaml\n\ncachedir: '\/var\/cache\/r10k'\nsources:\n   yourdepartment:\n    basedir: '\/etc\/puppet\/code\/environments'\n    remote: 'https:\/\/gitlab.your.domain\/youruser\/puppetcontrolrepo.git'\n    prefix: true<\/code><\/pre>\n\n\n\n<p>Create the above file in your git repo (if you&#8217;ve decided not to use git, which is not recommended, skip this).<br>This tells r10k where to fetch the environments (I named it yourdepartment, you may configure as much as you like, to allow different teams to build their own puppet environment for example or just to separate things from each other).<br><strong>prefix<\/strong> is the important option here, because it tells r10k to prefix the environments with the respective branch names.<br>So if you have a production and a test branch for &#8220;yourdepartment&#8221; in your gitlab repo, they will be checked out separateley.<br>This allows you to set the environment of some nodes (either in \/etc\/..\/puppet.conf or on the commandline with env=yourenvironment_master or &#8211;environment=yourenvironment_test) so that you can use them for testing or production, just as you need.<br><strong>I recommend you keep this in your git repo under version control.<\/strong> But you need copy it to <strong>\/etc\/r10k.yaml<\/strong> on your master (if you like, create another repo for that).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir modules\nmkdir manifests<\/code><\/pre>\n\n\n\n<p>Our initial structure is complete. commit and push your code into git (no git? ignore) and do a &#8220;checkout -b test&#8221; to create a test branch while you&#8217;re at it.<br>Then install r10k on your master.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gem install r10k<\/code><\/pre>\n\n\n\n<p>Now clone your repo initially (so that r10k.yaml exists, you may also just copy it there)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone https:\/\/gitlab.your.domain\/youruser\/puppetcontrolrepo \/etc\/puppet\/code\/environments\/yourdepartment_master<\/code><\/pre>\n\n\n\n<p>Your master branch is checked out. From now on r10k will take care about updating the environment, installing modules and so on (after you&#8217;ve pushed to git of course and ran te appropriate commands).<br>I would advise to either run r10k regularly via cron or on demand using git as a trigger or some ssh command when running the master for several teams.<br>However, let&#8217;s check out the important commands, like checking the syntax of your puppetfile.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/etc\/puppet\/code\/environments\/yourdepartment_master# r10k puppetfile check\nSyntax OK<\/code><\/pre>\n\n\n\n<p>Then let&#8217;s see what r10k would do (dry-run):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/etc\/puppet\/code\/environments\/yourdepartment_master# r10k deploy display -v\n---\n:sources:\n- :name: :yourdepartment\n  :basedir: \"\/etc\/puppet\/code\/environments\"\n  :prefix: true\n  :remote: https:\/\/gitlab.your.domain\/youruser\/puppetcontrolrepo.git\n  :environments: []<\/code><\/pre>\n\n\n\n<p>If everything seems right, let&#8217;s deploy our environment:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>r10k deploy environment -v -p\n\nroot@puppetmastertest:\/etc\/puppet\/code\/environments# r10k deploy environment -v -p\nWARN     -> The r10k configuration file at \/etc\/r10k.yaml is deprecated.\nWARN     -> Please move your r10k configuration to \/etc\/puppetlabs\/r10k\/r10k.yaml.\nINFO     -> Using Puppetfile '\/etc\/puppet\/code\/environments\/test_master\/Puppetfile'\nINFO     -> Using Puppetfile '\/etc\/puppet\/code\/environments\/test_test\/Puppetfile'\nINFO     -> Deploying environment \/etc\/puppet\/code\/environments\/test_master\nINFO     -> Environment test_master is now at 7d56685293dae8a68673b7ba1009e8ceea51571a\nINFO     -> Deploying Puppetfile content \/etc\/puppet\/code\/environments\/test_master\/modules\/helloworld\n[...]<\/code><\/pre>\n\n\n\n<p>Ignore the warnings, they tell you that we&#8217;re not using the &#8220;official&#8221; puppet package from puppetlabs but the one from the debian repository (one uses \/etc\/puppet and the other \/etc\/puppetlabs\/).<\/p>\n\n\n\n<p>You now have r10k management for your puppetmaster! Let&#8217;s go on and write some basic modules.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">writing basic modules<\/h4>\n\n\n\n<p>Either develop your modules in the <strong>modules folder<\/strong> you created in your git puppet repository or use a different one (or several), that depends on your setup and company structure.<br>Create a <strong>site.pp<\/strong> file in your manifests folder.<br>In the days of old these contained node configurations but here we tell hiera how to lookup and merge all the classes it finds and put them in the catalog (this is the <strong>merge strategy<\/strong>, mentioned further above).<br>More on the topic: https:\/\/puppet.com\/docs\/puppet\/5.3\/hiera_automatic.html<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>notify { \"Using $environment\" :\n    message => \"Processing catalog from the $environment environment.\" ,\n}\n\nlookup ('classes', Array[String], 'unique').include<\/code><\/pre>\n\n\n\n<p>The interesting part is the lookup statement.<br>The notify statement is just for debug purposes. It always shows the environment used on the client.<br>Let&#8217;s create a base module which we can use on all of our hosts:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p modules\/base\/manifests\nmkdir -p modules\/base\/files\nmkdir -p modules\/base\/manifests\/openssh<\/code><\/pre>\n\n\n\n<p>Our base module will contain an openssh module and a bashrc module (you can download much better modules from puppetlabs, this is just to get the idea)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi modules\/base\/manifests\/openssh.pp\n\nclass base::openssh {\n   class { base::openssh::install: }\n}\n\nvi modules\/base\/manifests\/openssh\/install.pp\n\nclass base::openssh::install {\n   package { \"openssh-client\":\n      ensure => present,\n   }\n   package { \"openssh-server\":\n      ensure => present,\n   }\n}<\/code><\/pre>\n\n\n\n<p>In our base module we create an openssh.pp file which contains a reference openssh::install class. We could have defined it in the file itself, but later, if you add to this rather rudimentary openssh module or create your own,you&#8217;ll want to design them as modular as possible. SO you could add e.g a configure.pp and so on. However, this will make sure, that always the latest version of ssh client and server will be installed on our node (in prod you may want to work with a specific version).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>root@puppettest1:~# puppet resource package openssh-client\npackage { 'openssh-client':\n  ensure => '1:6.7p1-5+deb8u8',\n}<\/code><\/pre>\n\n\n\n<p>On a host where you have some package installed you can let puppet tell you about it&#8217;s attributes and then write your code accordingly.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>root@puppettest1:~# puppet resource user root\nuser { 'root':\n  ensure           => 'present',\n  comment          => 'root',\n  gid              => '0',\n  home             => '\/root',\n  password         => '$........onbZvbm0',\n  password_max_age => '99999',\n  password_min_age => '0',\n  shell            => '\/bin\/bash',\n  uid              => '0',\n}<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/puppet.com\/docs\/puppet\/5.3\/type.html\">https:\/\/puppet.com\/docs\/puppet\/5.3\/type.html<\/a> (or use puppet describe $resourcename)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi modules\/base\/manifests\/bashrc.pp\n\nclass base::bashrc {\n  \nfile { '\/root\/.bashrc':\n  ensure  => 'present',\n  group   => '0',\n  mode    => '0644',\n  owner   => '0',\n  source  => \"puppet:\/\/\/modules\/base\/bashrc\/bashrc\"\n}\n}\n\nvi modules\/base\/files\/bashrc\/bashrc\n#just copy a bashrc that you like and add:\n#additional paths\nPATH=$PATH:\/opt\/puppetlabs\/puppet\/bin<\/code><\/pre>\n\n\n\n<p>This is our second module in our base module, it creates a bashrc on our nodes. Notice the source parameter. We could write our content directly (parameter is &#8220;content&#8221;) but we store the file separately and tell puppet were to find it.<br>This translates to &#8221; modules\/base\/files\/bashrc\/bashrc&#8221;, puppet skips &#8220;files&#8221; in the path&#8230;<br><br>from now on puppet will be in your PATH on all of your host.<br>Let&#8217;s put it together:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi modules\/base\/manifests\/init.pp\n\nclass base {\n   class { base::openssh: }\n   class { base::bashrc: }\n}<\/code><\/pre>\n\n\n\n<p>Every module needs an init.pp! Here we define a class &#8220;base&#8221; that consist of our two new classes. But even if you are developing a new module I&#8217;d recommend that you put only basics into init.pp and keep everything as modular as possible.<br>Now let&#8217;s define our nodes.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">defining a node<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>vi hieradata\/common.yaml\n\n---\nclasses:\n   - base<\/code><\/pre>\n\n\n\n<p>Let&#8217;s put our base class in our common.yaml file that we&#8217;ve touched earlier (don&#8217;t forget to commit\/push). We want ssh and bashrc on all of our hosts so it fits best in our least specific definition.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>puppet agent -vv --test --environment yourdepartment_test\n\nInfo: Using configured environment 'yourdepartment_test'\nInfo: Retrieving pluginfacts\nInfo: Retrieving plugin\nInfo: Loading facts\nInfo: Caching catalog for yourhost.your.domain\nInfo: Applying configuration version 'puppetserver-yourdepartment_test-caab813140e'\nNotice: Processing catalog from the yourdepartment_test environment.\nNotice: \/Stage[main]\/Base\/Notify[Using Base Class!]\/message: defined 'message' as 'Using Base Class!'\nNotice: \/Stage[main]\/Base::Openssh\/Notify[Using Openssh Test class!]\/message: defined 'message' as \nNotice: \/Stage[main]\/Base::Bashrc\/Notify[Using bashrc class!]\/message: defined 'message' as 'Using bashrc class!'\nInfo: Stage[main]: Unscheduling all events on Stage[main]\nNotice: Applied catalog in 0.62 seconds<\/code><\/pre>\n\n\n\n<p>Your node now has a new bashrc and ssh-packages provisioned.<br>On a more specific node (hieradata\/nodes\/yourserver.your.domain.yaml) use the gitlab class from puppetlabs maybe:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>---\nclasses:\n    - gitlab\n\ngitlab::external_url: 'http:\/\/gitlabmaster.your.domain'\ngitlab::gitlab_rails:\n  time_zone: 'Europe\/Berlin'\n  gitlab_email_enabled: false\n  gitlab_default_theme: 4\n  gitlab_email_display_name: 'Gitlab'\ngitlab::sidekiq:\n  shutdown_timeout: 5<\/code><\/pre>\n\n\n\n<p>From now on, do all your configuration changes in your git test branch, pull it on the master automatically with r10k try it on your test nodes, merge into master if appropriate, run the agent and always be sure about what&#8217;s configured where and the state of your nodes!<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"> Tips:<\/h4>\n\n\n\n<ul class=\"wp-block-list\"><li>create cronjobs on the master for r10k and on the clients for puppetruns.<\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>I&#8217;ve learned a lot from these books I read ages ago (they should be free on the web by now but also greatly outdated):<\/p>\n\n\n\n<p>&#8220;Pro Puppet&#8221;, James Turnbull and Jeffrey McCune, APress<br>&#8220;Learning puppet 4&#8221;, Jo Rhett, O&#8217;reilly<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>What is puppet and why would I need it? Puppet is an open source configuration management tool, that can help you to manage lots of servers without writing customized scripts for setup and maintenance for each one or each group of them.It&#8217;s very powerful and comes with lots of modules already, for nearly every task &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/18\/how-to-set-up-a-puppet-infrastructure\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;How to set up a puppet infrastructure&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25],"tags":[29,28,27,15,26],"class_list":["post-43","post","type-post","status-publish","format-standard","hentry","category-puppet","tag-automation","tag-continuous-delivery","tag-continuous-integration","tag-debian","tag-puppet","entry"],"_links":{"self":[{"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/43","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=43"}],"version-history":[{"count":4,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/43\/revisions"}],"predecessor-version":[{"id":57,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/43\/revisions\/57"}],"wp:attachment":[{"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=43"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=43"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}