├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── Vagrantfile ├── code ├── environments │ └── production │ │ ├── environment.conf │ │ ├── hieradata │ │ ├── common.yaml │ │ └── puppet.yaml │ │ ├── manifests │ │ └── site.pp │ │ └── site │ │ ├── common │ │ └── manifests │ │ │ └── init.pp │ │ ├── master │ │ └── manifests │ │ │ └── init.pp │ │ ├── profile │ │ └── manifests │ │ │ └── master.pp │ │ └── role │ │ └── manifests │ │ └── master.pp └── hiera.yaml └── puppetupgrade.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "code/environments/production/modules/puppetserver"] 2 | path = code/environments/production/modules/puppetserver 3 | url = https://github.com/camptocamp/puppet-puppetserver 4 | [submodule "code/environments/production/modules/stdlib"] 5 | path = code/environments/production/modules/stdlib 6 | url = https://github.com/puppetlabs/puppetlabs-stdlib 7 | [submodule "code/environments/production/modules/puppetdb"] 8 | path = code/environments/production/modules/puppetdb 9 | url = https://github.com/puppetlabs/puppetlabs-puppetdb 10 | [submodule "code/environments/production/modules/inifile"] 11 | path = code/environments/production/modules/inifile 12 | url = https://github.com/puppetlabs/puppetlabs-inifile 13 | [submodule "code/environments/production/modules/postgresql"] 14 | path = code/environments/production/modules/postgresql 15 | url = https://github.com/puppetlabs/puppetlabs-postgresql/ 16 | [submodule "code/environments/production/modules/concat"] 17 | path = code/environments/production/modules/concat 18 | url = https://github.com/puppetlabs/puppetlabs-concat 19 | [submodule "code/environments/production/modules/firewall"] 20 | path = code/environments/production/modules/firewall 21 | url = https://github.com/puppetlabs/puppetlabs-firewall 22 | [submodule "code/environments/production/modules/activemq"] 23 | path = code/environments/production/modules/activemq 24 | url = https://github.com/puppetlabs/puppetlabs-activemq 25 | [submodule "code/environments/production/modules/ruby"] 26 | path = code/environments/production/modules/ruby 27 | url = https://github.com/camptocamp/puppet-ruby 28 | [submodule "code/environments/production/modules/mcollective"] 29 | path = code/environments/production/modules/mcollective 30 | url = https://github.com/voxpupuli/puppet-mcollective 31 | [submodule "code/environments/production/modules/datacat"] 32 | path = code/environments/production/modules/datacat 33 | url = https://github.com/richardc/puppet-datacat 34 | [submodule "code/environments/production/modules/apt"] 35 | path = code/environments/production/modules/apt 36 | url = https://github.com/puppetlabs/puppetlabs-apt 37 | [submodule "code/environments/production/modules/java"] 38 | path = code/environments/production/modules/java 39 | url = https://github.com/puppetlabs/puppetlabs-java 40 | [submodule "code/environments/production/modules/buildenv"] 41 | path = code/environments/production/modules/buildenv 42 | url = https://github.com/camptocamp/puppet-buildenv 43 | [submodule "code/environments/production/modules/augeasproviders_core"] 44 | path = code/environments/production/modules/augeasproviders_core 45 | url = https://github.com/hercules-team/augeasproviders_core 46 | [submodule "code/environments/production/modules/augeas"] 47 | path = code/environments/production/modules/augeas 48 | url = https://github.com/camptocamp/puppet-augeas 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Roman Mueller 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | This is a bleeding edge playground repository to get more familiar with Puppet 4, future parser, cfacter, PuppetDB 3, MCollective and puppetserver 2. 3 | It is intended to be a quick way to spawn up a fully working Puppet 4 environment. 4 | It will automatically install the latest version of the full above stack. 5 | If it breaks because of a new version, let me know and I'll try to fix it. 6 | It was last suceessfully tested with: 7 | Puppet 4.8.1 8 | puppet-agent-1.8.1 9 | puppetserver-2.7.1 10 | puppetdb-4.3.0 11 | 12 | In the Vagrantfile there are 2 VMs defined. 13 | A puppetserver ("puppet") and a puppet node ("node1") both running CentOS 7.0. 14 | Classes get configured via hiera (see `code/environments/production/hieradata/*`). 15 | 16 | # Requirements 17 | I'm using Vagrant 1.7.3 and VirtualBox as the provisioner. 18 | I'm running this on Mac OS X but it should also run on other operating systems, but I haven't tested it. 19 | Older versions of Vagrant are not supported, as Puppet 4 support was only [added in 1.7.3](https://github.com/mitchellh/vagrant/issues/3740) 20 | 21 | Also tested and working on: SLES 11.3, VirtualBox-4.3-4.3.28_100309_sles11.0-1. 22 | 23 | The puppetserver VM is configured to use 3GB of RAM. 24 | The node is using the default (usually 512MB). 25 | 26 | # Usage 27 | After cloning the repository make sure the submodules are also updated: 28 | ``` 29 | $ git clone https://github.com/roman-mueller/puppet4-sandbox 30 | $ cd puppet4-sandbox 31 | $ git submodule update --init --recursive 32 | ``` 33 | 34 | Whenever you `git pull` this repository you should also update the submodules again. 35 | 36 | Now you can simply run `vagrant up puppet` to get a fully set up puppetserver. 37 | The `code/` folder will be a synced folder and gets mounted to `/etc/puppetlabs/code` inside the VM. 38 | 39 | If you want to attach a node to the puppetserver simply run `vagrant up node1`. 40 | Once provisioned it is automatically connecting to the puppetserver and it gets automatically signed. 41 | 42 | After that puppet will run automatically every 30 minutes on the node and apply your changes. 43 | You can also run it manually: 44 | ``` 45 | $ vagrant ssh node1 46 | [vagrant@node1 ~]$ sudo /opt/puppetlabs/bin/puppet agent -t 47 | Info: Caching certificate for node1 48 | Info: Caching certificate_revocation_list for ca 49 | Info: Caching certificate for node1 50 | Info: Retrieving pluginfacts 51 | Info: Retrieving plugin 52 | (...) 53 | Notice: Applied catalog in 0.52 seconds 54 | ``` 55 | 56 | PuppetDB gets installed and started by default. 57 | The local port 8080 gets forwarded to the Vagrant VM to port 8080. 58 | So you can access the PuppetDB dashboard via http://127.0.0.1:8080/dashboard/index.html. 59 | All necessary keys get created when it starts for the first time. 60 | The puppetserver is configured to store reports in the DB, so you can start playing with that too right away. 61 | The [PuppetDB CLI tools](https://docs.puppet.com/puppetdb/master/pdb_client_tools.html) are installed on the "puppet" node and should work right away: 62 | ``` 63 | [vagrant@puppet ~]$ /opt/puppetlabs/bin/puppet query 'nodes [ certname ]{ limit 10 }' 64 | [ { 65 | "certname" : "puppet" 66 | }, { 67 | "certname" : "node1" 68 | } ] 69 | ``` 70 | 71 | MCollective gets installed and configured as well. 72 | It should also work out of the box, and node1 will register after the initial Puppet run: 73 | ``` 74 | [root@puppet vagrant]# /opt/puppetlabs/bin/mco ping 75 | node1 time=29.86 ms 76 | puppet time=67.98 ms 77 | 78 | 79 | ---- ping statistics ---- 80 | 2 replies max: 67.98 min: 29.86 avg: 48.92 81 | ``` 82 | 83 | # Security 84 | This repository is meant as a non-production playground setup. 85 | It is not a guide on how to setup a secure Puppet environment. 86 | 87 | In particular this means: 88 | 89 | - Auto signing is enabled, every node that connects to the puppetserver is automatically signed. 90 | - MCollective uses a PSK and no SSL. 91 | - The MCollective client gets deployed on every agent that connects to the puppetserver. 92 | - Passwords or PSKs are not randomized and easily guessable. 93 | 94 | For a non publicly reachable playground this should be acceptable. 95 | 96 | 97 | # Hacks 98 | I wrote a shell provisioner ("puppetupgrade.sh") which updates `puppet-agent` before running it for the first time. 99 | That way newly spawned Vagrant environments will always use the latest available version. 100 | 101 | There is no DNS server running in the private network. 102 | All nodes have each other in their `/etc/hosts` files. 103 | 104 | Starting the puppetserver sometimes hits the systemd timeout (https://tickets.puppetlabs.com/browse/SERVER-557). 105 | To work around this, the file `/etc/systemd/system/puppetserver.service.d/local.conf` gets created which overrides the timeout and sets it to 500 seconds. 106 | 107 | # Tickets 108 | Working on the bleeding edge usually produces some problems and tickets, here are the ones opened while working on this repo: 109 | - https://tickets.puppetlabs.com/browse/PUP-4461 manifest changes are ignored when using hiera_include: fixed 110 | - https://tickets.puppetlabs.com/browse/CPR-186 PuppetDB 2.3.4 not in PC1 yum repositories: fixed 111 | - https://tickets.puppetlabs.com/browse/CPR-184 Puppet 4 repository "repodata" folder missing: fixed 112 | - https://tickets.puppetlabs.com/browse/CPR-183 puppetlabs-release-pc1 RPM missing: fixed 113 | - https://tickets.puppetlabs.com/browse/SERVER-557 systemd timeout is reached: still open 114 | - https://tickets.puppetlabs.com/browse/FACT-1117 cfacter not working on CentOS7: still open 115 | - https://tickets.puppetlabs.com/browse/MODULES-2487 improve ::firewall port deprecation warning 116 | - https://tickets.puppetlabs.com/browse/MODULES-2488 use dport instead of deprecated port 117 | 118 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure(2) do |config| 2 | 3 | config.vm.define "puppet", primary: true do |puppet| 4 | puppet.vm.hostname = "puppet" 5 | puppet.vm.box = "puppetlabs/centos-7.0-64-puppet" 6 | puppet.vm.box_version = "1.0.2" 7 | puppet.vm.network "private_network", ip: "10.13.37.2" 8 | puppet.vm.network :forwarded_port, guest: 8080, host: 8080, id: "puppetdb" 9 | 10 | puppet.vm.synced_folder "code", "/etc/puppetlabs/code" 11 | 12 | puppet.vm.provider :virtualbox do |vb| 13 | vb.memory = "3072" 14 | end 15 | 16 | puppet.vm.provision "shell", path: "puppetupgrade.sh" 17 | 18 | puppet.vm.provision "puppet" do |puppetapply| 19 | puppetapply.environment = "production" 20 | puppetapply.environment_path = ["vm", "/etc/puppetlabs/code/environments"] 21 | end 22 | end 23 | 24 | config.vm.define "node1", primary: true do |node1| 25 | node1.vm.hostname = "node1" 26 | node1.vm.box = "puppetlabs/centos-7.0-64-puppet" 27 | node1.vm.box_version = "1.0.2" 28 | node1.vm.network "private_network", ip: "10.13.37.3" 29 | 30 | node1.vm.provision "shell", path: "puppetupgrade.sh" 31 | node1.vm.provision "shell", inline: "/bin/systemctl start puppet.service" 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /code/environments/production/environment.conf: -------------------------------------------------------------------------------- 1 | # Each environment can have an environment.conf file. Its settings will only 2 | # affect its own environment. See docs for more info: 3 | # https://docs.puppetlabs.com/puppet/latest/reference/config_file_environment.html 4 | 5 | # Any unspecified settings use default values; some of those defaults are based 6 | # on puppet.conf settings. 7 | 8 | # If these settings include relative file paths, they'll be resolved relative to 9 | # this environment's directory. 10 | 11 | # Allowed settings and default values: 12 | 13 | modulepath = modules:site:$basemodulepath 14 | # manifest = (default_manifest from puppet.conf, which defaults to ./manifests) 15 | # config_version = (no script; Puppet will use the time the catalog was compiled) 16 | # environment_timeout = (environment_timeout from puppet.conf, which defaults to 0) 17 | # Note: unless you have a specific reason, we recommend only setting 18 | # environment_timeout in puppet.conf. 19 | -------------------------------------------------------------------------------- /code/environments/production/hieradata/common.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | classes: 3 | - common 4 | 5 | -------------------------------------------------------------------------------- /code/environments/production/hieradata/puppet.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | classes: 3 | - role::master 4 | 5 | -------------------------------------------------------------------------------- /code/environments/production/manifests/site.pp: -------------------------------------------------------------------------------- 1 | 2 | hiera_include('classes') 3 | 4 | -------------------------------------------------------------------------------- /code/environments/production/site/common/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # common class that gets applied to all nodes 2 | # See: "code/environments/production/hieradata/common.yaml" 3 | # It: 4 | # - configures /etc/hosts entries 5 | # - makes sure puppet is installed and running 6 | # - makes sure mcollective + client is installed and running 7 | # 8 | class common { 9 | 10 | # needed for rubygem-stomp 11 | yumrepo { 'puppetlabs-deps': 12 | ensure => 'present', 13 | baseurl => 'http://yum.puppetlabs.com/el/7/dependencies/$basearch', 14 | descr => 'Puppet Labs Dependencies El 7 - $basearch', 15 | enabled => '1', 16 | } 17 | 18 | host { 'puppet': 19 | ip => '10.13.37.2', 20 | } 21 | 22 | host { 'node1': 23 | ip => '10.13.37.3', 24 | } 25 | 26 | package { 'puppet-agent': 27 | ensure => installed, 28 | } 29 | 30 | service { 'puppet': 31 | ensure => running, 32 | enable => true, 33 | require => Package['puppet-agent'], 34 | } 35 | 36 | class { '::mcollective': 37 | middleware_hosts => [ 'puppet' ], 38 | psk => 'puppet', 39 | middleware_user => 'puppet', 40 | middleware_password => 'puppet', 41 | middleware_admin_user => 'puppet', 42 | middleware_admin_password => 'puppet', 43 | client => true, 44 | require => Yumrepo['puppetlabs-deps'], 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /code/environments/production/site/master/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # class to deploy master node: 2 | # - puppetserver 3 | # - puppetdb 4 | 5 | class master { 6 | 7 | include ::firewall 8 | 9 | # https://tickets.puppetlabs.com/browse/SERVER-557 10 | file { '/etc/systemd/system/puppetserver.service.d': 11 | ensure => 'directory', 12 | owner => 'root', 13 | group => 'root', 14 | mode => '0755', 15 | } 16 | 17 | firewall { '8140 accept - puppetserver': 18 | dport => '8140', 19 | proto => 'tcp', 20 | action => 'accept', 21 | } 22 | 23 | firewall { '61613 accept - activemq': 24 | dport => '61613', 25 | proto => 'tcp', 26 | action => 'accept', 27 | } 28 | 29 | file { '/etc/systemd/system/puppetserver.service.d/local.conf': 30 | ensure => 'file', 31 | content => "[Service]\nTimeoutStartSec=500", 32 | owner => 'root', 33 | group => 'root', 34 | mode => '0644', 35 | require => File['/etc/systemd/system/puppetserver.service.d'], 36 | } 37 | 38 | class { '::puppetserver': 39 | before => Service['puppet'], 40 | require => File['/etc/systemd/system/puppetserver.service.d/local.conf'], 41 | } 42 | 43 | file { '/etc/puppetlabs/puppet/autosign.conf': 44 | ensure => 'file', 45 | content => '*', 46 | owner => 'root', 47 | group => 'root', 48 | mode => '0644', 49 | require => Package['puppetserver'], 50 | notify => Service['puppetserver'], 51 | } 52 | 53 | class { '::puppetdb': 54 | ssl_listen_address => '0.0.0.0', 55 | listen_address => '0.0.0.0', 56 | open_listen_port => true, 57 | } 58 | class { '::puppetdb::master::config': 59 | puppetdb_server => 'puppet', 60 | strict_validation => false, 61 | manage_report_processor => true, 62 | enable_reports => true, 63 | # https://tickets.puppetlabs.com/browse/PDB-2591 64 | restart_puppet => false, 65 | } 66 | 67 | # require puppetserver class to make sure java is installed and avoid 68 | # puppetlabs/java dependency 69 | class { '::activemq': 70 | mq_broker_name => 'puppet', 71 | mq_admin_username => 'puppet', 72 | mq_admin_password => 'puppet', 73 | mq_cluster_username => 'puppet', 74 | mq_cluster_password => 'puppet', 75 | require => [ Yumrepo['puppetlabs-deps'], 76 | Class['puppetserver'], ], 77 | } 78 | 79 | # unsure why, but this folder does not get created and without it activemq 80 | # fails to work properly 81 | file { '/usr/share/activemq/activemq-data': 82 | ensure => 'directory', 83 | group => 'activemq', 84 | owner => 'activemq', 85 | mode => '0755', 86 | require => Class['activemq'], 87 | } 88 | 89 | package { 'puppet-client-tools': 90 | ensure => present, 91 | } 92 | 93 | } 94 | 95 | -------------------------------------------------------------------------------- /code/environments/production/site/profile/manifests/master.pp: -------------------------------------------------------------------------------- 1 | # profile to deploy a puppet master 2 | 3 | class profile::master { 4 | 5 | include ::master 6 | 7 | } 8 | -------------------------------------------------------------------------------- /code/environments/production/site/role/manifests/master.pp: -------------------------------------------------------------------------------- 1 | # Puppet master role 2 | 3 | class role::master { 4 | 5 | include ::profile::master 6 | 7 | } 8 | -------------------------------------------------------------------------------- /code/hiera.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | :backends: 3 | - yaml 4 | :hierarchy: 5 | - "%{::hostname}" 6 | - "common" 7 | 8 | :yaml: 9 | :datadir: 10 | -------------------------------------------------------------------------------- /puppetupgrade.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -f /etc/provisioned ] ; then 4 | # remove strange manually placed repo file 5 | /bin/rm -f /etc/yum.repos.d/puppetlabs* 6 | 7 | # install Puppet 4.x release repo 8 | /bin/yum -y install https://yum.puppetlabs.com/puppetlabs-release-pc1-el-7.noarch.rpm 9 | if [ $? -ne 0 ] ; then 10 | echo "Something went wrong installing the repository RPM" 11 | exit 1 12 | fi 13 | 14 | # install / update puppet-agent 15 | /bin/yum -y install puppet-agent 16 | if [ $? -ne 0 ] ; then 17 | echo "Something went wrong installing puppet-agent" 18 | exit 1 19 | fi 20 | 21 | echo "10.13.37.2 puppet" >> /etc/hosts 22 | 23 | touch /etc/provisioned 24 | fi 25 | 26 | --------------------------------------------------------------------------------