├── .gitignore ├── Puppetfile ├── README.md ├── environment.conf ├── hiera.yaml ├── hieradata ├── common.yaml ├── env │ ├── production.yaml │ └── staging.yaml ├── nodes │ ├── kf-stage.pfdev.de.yaml │ └── puppet.pfdev.de.yaml └── os │ └── .gitkeep ├── modules └── .gitkeep ├── site.pp ├── site ├── profile │ └── manifests │ │ ├── base.pp │ │ └── kirby.pp └── role │ └── manifests │ └── frontend.pp └── test ├── README.md ├── Vagrantfile ├── masterConf ├── puppet.conf.snippet └── r10k.yaml ├── puppet_bootstrap.sh └── puppet_master.sh /.gitignore: -------------------------------------------------------------------------------- 1 | test/.vagrant 2 | -------------------------------------------------------------------------------- /Puppetfile: -------------------------------------------------------------------------------- 1 | forge 'forge.puppetlabs.com' 2 | 3 | # Forge Modules to be included in our manifests. 4 | mod 'puppetlabs/ntp', '6.2.0' 5 | mod 'puppetlabs/stdlib' 6 | mod 'puppetlabs/apache', '2.1.0' 7 | mod 'puppetlabs-apt', '4.2.0' 8 | mod 'puppetlabs-concat', '4.0.1' 9 | mod 'puppet-php', '5.0.0' 10 | mod 'bzed-letsencrypt', '0.1.17' 11 | mod 'puppet-archive', '2.1.0' 12 | mod 'darin-zypprepo', '1.0.2' 13 | mod 'puppetlabs-inifile', '2.0.0' 14 | mod 'puppetlabs-vcsrepo', '2.0.0' 15 | mod 'camptocamp-openssl', '1.10.0' 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # plusForta puppet control repo. 2 | 3 | ## What this is 4 | 5 | This repository controls the configuration of all the servers in the plusForta fleet. 6 | 7 | It is set up in a roles and profiles configuration: 8 | * Nodes are assigned roles in their hiera configs (e.g. "frontend cms") 9 | * roles contain profiles ("e.g. kirby") 10 | * profiles include other modules as necessary ("e.g. apache") 11 | 12 | We use [r10k](https://github.com/puppetlabs/r10k) to manage the actual configuration 13 | on the puppetserver. This tool uses this repository to configure the final codebase. 14 | 15 | r10k does the following: 16 | * Checks out this repository 17 | * Copies each branch of the repo into a separate directory 18 | (e.g /etc/puppetlabs/code/environments/{$branch}) 19 | * For each environment, it runs through the Puppetfile file in the root and 20 | checks out the modules included in it. 21 | 22 | In this method the full puppet repository is created. 23 | 24 | ## How to develop against it 25 | 26 | * Check in your changes locally. 27 | * Follow the instructions in /test to setup a puppet server and testing nodes 28 | * run r10k deploy environment -p on the local puppet server 29 | * run puppet agent -t --environment="$branch" on your testing nodes. 30 | 31 | ## How to deploy it 32 | 33 | * push your changes to the cloud. 34 | * run r10k deploy environment -p on the puppetserver. 35 | * cross your fingers! 36 | -------------------------------------------------------------------------------- /environment.conf: -------------------------------------------------------------------------------- 1 | manifest = site.pp 2 | modulepath = site:$basemodulepath:modules 3 | -------------------------------------------------------------------------------- /hiera.yaml: -------------------------------------------------------------------------------- 1 | # /hiera.yaml 2 | --- 3 | version: 5 4 | 5 | defaults: # Used for any hierarchy level that omits these keys. 6 | datadir: hieradata # This path is relative to the environment -- /data 7 | data_hash: yaml_data # Use the built-in YAML backend. 8 | 9 | hierarchy: 10 | - name: "Per-node data" # Human-readable name. 11 | path: "nodes/%{trusted.certname}.yaml" # File path, relative to datadir. 12 | # ^^^ IMPORTANT: include the file extension! 13 | - name: "Per-OS defaults" 14 | path: "os/%{facts.os.family}.yaml" 15 | 16 | - name: "Per environment" 17 | path: "env/%{facts.stage}.yaml" 18 | 19 | - name: "Common data" 20 | path: "common.yaml" 21 | -------------------------------------------------------------------------------- /hieradata/common.yaml: -------------------------------------------------------------------------------- 1 | # This is included in every node in the fleet 2 | --- 3 | classes: 4 | - 'profile::base' 5 | 6 | ntp::servers: 7 | - 0.de.pool.ntp.org 8 | - 1.de.pool.ntp.org 9 | - 2.de.pool.ntp.org 10 | - 3.de.pool.ntp.org 11 | 12 | php::ensure: latest 13 | php::manage_repos: true 14 | php::fpm: true 15 | php::dev: true 16 | php::composer: true 17 | php::pear: true 18 | php::phpunit: false 19 | php::settings: 20 | 'PHP/max_execution_time': '90' 21 | 'PHP/max_input_time': '300' 22 | 'PHP/memory_limit': '64M' 23 | 'PHP/post_max_size': '32M' 24 | 'PHP/upload_max_filesize': '32M' 25 | 'Date/date.timezone': 'Europe/Berlin' 26 | 27 | apache::default_vhost: false 28 | -------------------------------------------------------------------------------- /hieradata/env/production.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusForta/puppet5-control-repo/3f7a69b02c9b6e98ea82c8b31685a8a2ffc6b844/hieradata/env/production.yaml -------------------------------------------------------------------------------- /hieradata/env/staging.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusForta/puppet5-control-repo/3f7a69b02c9b6e98ea82c8b31685a8a2ffc6b844/hieradata/env/staging.yaml -------------------------------------------------------------------------------- /hieradata/nodes/kf-stage.pfdev.de.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | classes: 3 | - role::frontend 4 | 5 | profile::kirby::hostname: "kf-stage.pfdev.de" 6 | profile::kirby::kirbykey: "no key yet" 7 | -------------------------------------------------------------------------------- /hieradata/nodes/puppet.pfdev.de.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | -------------------------------------------------------------------------------- /hieradata/os/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusForta/puppet5-control-repo/3f7a69b02c9b6e98ea82c8b31685a8a2ffc6b844/hieradata/os/.gitkeep -------------------------------------------------------------------------------- /modules/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusForta/puppet5-control-repo/3f7a69b02c9b6e98ea82c8b31685a8a2ffc6b844/modules/.gitkeep -------------------------------------------------------------------------------- /site.pp: -------------------------------------------------------------------------------- 1 | # Very small site.pp. 2 | 3 | 4 | 5 | # include all classes from hiera. 6 | 7 | hiera_include('classes') 8 | -------------------------------------------------------------------------------- /site/profile/manifests/base.pp: -------------------------------------------------------------------------------- 1 | # class profile::base 2 | # included for every system in the fleet. 3 | class profile::base { 4 | class { '::ntp': } 5 | } 6 | -------------------------------------------------------------------------------- /site/profile/manifests/kirby.pp: -------------------------------------------------------------------------------- 1 | # class profile:kirby::master defines a kirby installation 2 | 3 | # Setup the following: 4 | # * apache 5 | # * php-fpm 6 | # * php-mbstring 7 | # * registers for an SSL cert 8 | 9 | 10 | class profile::kirby ( 11 | $hostname, 12 | $kirbykey, 13 | ){ 14 | 15 | class {'::apache': 16 | 17 | } 18 | 19 | apache::vhost { $hostname: 20 | port => '80', 21 | docroot => '/var/www/kirby/public', 22 | custom_fragment => 'AddType application/x-httpd-php .php', 23 | } 24 | 25 | apache::fastcgi::server { 'php': 26 | host => '127.0.0.1:9000', 27 | timeout => 15, 28 | flush => false, 29 | faux_path => '/var/www/php.fcgi', 30 | fcgi_alias => 'php.fcgi', 31 | file_type => 'appalication/x-httpd-php', 32 | } 33 | 34 | class {'::php': 35 | extensions => { 36 | mbstring => { }, 37 | } 38 | } 39 | 40 | class {'::letsencrypt': 41 | domains => [ $hostname ], 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /site/role/manifests/frontend.pp: -------------------------------------------------------------------------------- 1 | # 2 | # This role defines all the profiles required for a frontend CMS server. 3 | # 4 | 5 | class role::frontend { 6 | 7 | include ::profile::kirby 8 | 9 | } 10 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # Testing Puppet 2 | 3 | This [Vagrantfile](./Vagrantfile) will create a test puppetserver and any test nodes you specify. 4 | 5 | ## How to use 6 | 7 | To use it, simply do the following: 8 | 9 | - verify the node(s) you want to test is present in the puppet repo and the Vagrantfile 10 | - Bring up the master 11 | 12 | ```bash 13 | vagrant up master 14 | ``` 15 | 16 | - Bring up any host nodes you specify 17 | 18 | ```bash 19 | vagrant up $hostname 20 | ``` 21 | 22 | _The master should work fine, but pay attention to the output when bringing up nodes - puppet is automatically run once the node is brought up, but if the node or modules have errors they will be displayed here._ 23 | 24 | Either way, once the node is up, you can ssh to the system by running: 25 | 26 | ```bash 27 | vagrant ssh $hostname 28 | ``` 29 | 30 | Once you're logged in you can run (as root) the following command to have puppet do its thing: 31 | 32 | ```bash 33 | puppet agent -t --server=puppet-test.pfdev.de 34 | ``` 35 | 36 | You can add the '--debug' flag to see more information about the puppet run. 37 | 38 | A few things to note: 39 | - Because we are using r10k on the test puppetserver, you will need to commit changes 40 | and then run 'r10k deploy environment -p' as root on the master VM. I recommend 41 | making a branch called local and testing your changes there before merging or rebasing 42 | into staging/production. 43 | - You might see errors about "execution expired" when replicating the puppet master classes to the client, this is ok. The VMs are slow and simply re-running the puppet agent line from above should fix it. 44 | 45 | If you need to destroy and recreate the client but not the master, you may run into certificate issues. You can either destroy the master and node(s), or run the following on the master/node(s) as root: 46 | On the master: 47 | ```bash 48 | puppet cert clean $fqdnOfNode 49 | ``` 50 | On the node: 51 | ```bash 52 | find /var/lib/puppet/ssl -name $fqdnOfNode.pem -delete 53 | ``` 54 | -------------------------------------------------------------------------------- /test/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | ## This is a Vagrantfile to test puppet. 5 | 6 | # list all our VMs, and their corresponding IP, OS and domain 7 | # (hashicorp-style): 8 | # - default 'os' is 'bento/ubuntu-16.04' 9 | # - default 'domain' is 'untangle.com' 10 | # FIXME: can perhaps be wrapped into a class at some point 11 | vms = { 'master' => { 'ip' => '192.168.33.10' }, 12 | 'kf-stage' => { 'ip' => '192.168.33.20' }, 13 | # 'kautionsfrei' => { 'ip' => '192.168.33.21', 14 | # 'domain' => 'kautionsfrei.de', 15 | # 'os' => "debian/jessie", }, 16 | } 17 | 18 | # Vagrantfile API/syntax version. Don't touch unless you know what 19 | # you're doing! 20 | VAGRANTFILE_API_VERSION = "2" 21 | 22 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 23 | # providers 24 | config.vm.provider "virtualbox" do |v| 25 | v.memory = 1024 26 | v.cpus = 2 27 | end 28 | 29 | config.vm.provider :lxc do |v, override| 30 | override.vm.box = "fgrehm/trusty64-lxc" 31 | end 32 | 33 | # provisioners 34 | config.vm.provision "puppetlabs source", 35 | type: "shell", 36 | path: "puppet_bootstrap.sh" 37 | 38 | config.vm.provision "server", type: "puppet_server" do |p| 39 | p.puppet_server = "puppet-test.pfdev.de" 40 | p.options = "--test --waitforcert=10 --environment='local'" 41 | end 42 | 43 | # VMs 44 | config.vm.define :master do |master| 45 | vm = vms['master'] 46 | # FIXME: those constants need to be defined somewhere else, 47 | # ideally in the future class that'll wrap a host definition 48 | master.vm.synced_folder "..", "/usr/src/puppet" 49 | # master.vm.synced_folder "../hieradata", "/etc/puppet/hieradata" 50 | # master.vm.synced_folder "../modules", "/etc/puppet/modules" 51 | # master.vm.synced_folder "../", "/etc/puppet/original" 52 | master.vm.hostname = "puppet-test.pfdev.de" 53 | master.vm.box = vm.fetch('name', 'bento/ubuntu-16.04') 54 | master.vm.network :private_network, ip: vm['ip'] 55 | config.vm.provider "virtualbox" do |v| 56 | v.memory = 3072 57 | v.cpus = 2 58 | end 59 | # here we override the "server" provisioner (defined above), so 60 | # this one VM doesn't get puppetized 61 | master.vm.provision "server", type: "puppet_server" do |p| 62 | p.options = "--disable" 63 | end 64 | # # let's also override the "puppetlabs source" provisioner, as 65 | # # running puppet_master.sh just afterwards will take care of it 66 | # # and we don't want to apt-get update twice. 67 | # # If we later decide to remove the sources setup from 68 | # # puppet_master.sh, this won't need to be overriden anymore 69 | # master.vm.provision "puppetlabs source", 70 | # type: "shell", 71 | # path: "/bin/true", 72 | # binary: true 73 | master.vm.provision "shell", 74 | type: "shell", 75 | path: "puppet_master.sh" 76 | end 77 | 78 | vms.each_pair do |name, vm| 79 | ip = vm['ip'] 80 | # FIXME: those constants need to be defined somewhere else, 81 | # ideally in the future class that'll wrap a host definition 82 | os = vm.fetch('os', 'bento/ubuntu-16.04') 83 | domain = vm.fetch('domain', 'pfdev.de') 84 | config.vm.define name.to_s do |node| 85 | node.vm.hostname = "#{name.gsub(/\..+/,"")}.#{domain}" 86 | node.vm.network :private_network, ip: ip 87 | node.vm.box = os 88 | # FIXME: handle that cleanly directly in the 'vms' hash, or in 89 | # some other datastructure 90 | if name == "graylog" then 91 | config.vm.provider "virtualbox" do |v| 92 | v.memory = 2048 93 | v.cpus = 2 94 | end 95 | elsif ["prod","tdprod"].include?(name) then 96 | config.vm.provider "virtualbox" do |v| 97 | v.memory = 6144 98 | v.cpus = 2 99 | end 100 | end 101 | end 102 | end 103 | 104 | end 105 | -------------------------------------------------------------------------------- /test/masterConf/puppet.conf.snippet: -------------------------------------------------------------------------------- 1 | # Enable autosign and setup dns_alt_names 2 | autosign = true 3 | dns_alt_names=puppet-test,puppet-test.pfdev.de,puppet-test.kautionsfrei.de,master.pfdev.de 4 | -------------------------------------------------------------------------------- /test/masterConf/r10k.yaml: -------------------------------------------------------------------------------- 1 | :cachedir: '/var/cache/r10k' 2 | 3 | # A list of git repositories to create 4 | :sources: 5 | # This will clone the git repository and instantiate an environment per 6 | # branch in /etc/puppetlabs/code/environments 7 | :my-org: 8 | remote: '/usr/src/puppet/' 9 | basedir: '/etc/puppetlabs/code/environments' 10 | -------------------------------------------------------------------------------- /test/puppet_bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # This bootstraps Puppet on Ubuntu 16.04 LTS. 4 | # 5 | set -e 6 | 7 | REPO_DEB_URL="https://apt.puppetlabs.com/puppet5-release-xenial.deb" 8 | #-------------------------------------------------------------------- 9 | # NO TUNABLES BELOW THIS POINT 10 | #-------------------------------------------------------------------- 11 | if [ "$EUID" -ne "0" ]; then 12 | echo "This script must be run as root." >&2 13 | exit 1 14 | fi 15 | 16 | # wipe out flaky default sources.list on jessie 17 | SOURCES_LIST="/etc/apt/sources.list" 18 | if grep -q jessie ${SOURCES_LIST} ; then 19 | echo "deb http://ftp.us.debian.org/debian jessie main" >| ${SOURCES_LIST} 20 | echo "deb http://security.debian.org jessie/updates main" >> ${SOURCES_LIST} 21 | fi 22 | 23 | # Install the PuppetLabs repo 24 | echo "Configuring PuppetLabs repo..." 25 | repo_deb_path=$(mktemp) 26 | wget --output-document=${repo_deb_path} ${REPO_DEB_URL} 2>/dev/null 27 | dpkg -i ${repo_deb_path} >/dev/null 28 | apt-get update >/dev/null 29 | 30 | echo "Installing Puppet..." 31 | apt-get install -y puppet-agent > /dev/null 32 | /opt/puppetlabs/bin/puppet resource service puppet ensure=running enable=true >/dev/null 33 | echo "Puppet installed!" 34 | -------------------------------------------------------------------------------- /test/puppet_master.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # This bootstraps a PuppetServer on Ubuntu 16.04 LTS. 4 | # 5 | set -e 6 | 7 | REPO_DEB_URL="https://apt.puppetlabs.com/puppet5-release-xenial.deb" 8 | 9 | #-------------------------------------------------------------------- 10 | # NO TUNABLES BELOW THIS POINT 11 | #-------------------------------------------------------------------- 12 | if [ "$EUID" -ne "0" ]; then 13 | echo "This script must be run as root." >&2 14 | exit 1 15 | fi 16 | 17 | # Install the PuppetLabs repo 18 | echo "Configuring PuppetLabs repo..." 19 | repo_deb_path=$(mktemp) 20 | wget --output-document=${repo_deb_path} ${REPO_DEB_URL} 2>/dev/null 21 | dpkg -i ${repo_deb_path} >/dev/null 22 | apt-get update >/dev/null 23 | 24 | echo "Upgrading all packages..." 25 | apt-get upgrade -y >/dev/null 26 | 27 | # Install Puppet 28 | echo "Installing Puppet Server..." 29 | apt-get install -y puppetserver >/dev/null 30 | 31 | echo "Puppet Server installed!" 32 | 33 | PUPPET_DIR="/etc/puppetlabs" 34 | 35 | # check to see if this is the first time we're provisioning. 36 | if grep -q "autosign" ${PUPPET_DIR}/puppet/puppet.conf 37 | then 38 | echo "Autosigning already configured..." 39 | else 40 | echo "Enable autosigning of certs and dns_alt_names" 41 | cat >${PUPPET_DIR}/puppet/puppet.conf 42 | fi 43 | 44 | # install r10k 45 | echo "Installing r10k..." 46 | gem install r10k >/dev/null 47 | mkdir -p ${PUPPET_DIR}/r10k/ 48 | cp /usr/src/puppet/test/masterConf/r10k.yaml ${PUPPET_DIR}/r10k/ 49 | 50 | # remove older keys & certificates 51 | rm -fr /var/lib/puppet/ssl/* 52 | 53 | echo "Restarting puppet" 54 | service puppetserver restart 55 | --------------------------------------------------------------------------------