In my previous post, I talked about Puppet and how I intend to use this configuration management tool during the challenge.

Today, I will be showing you a puppet module I am working on for the automatic installation and configuration of OpenHAB.


Do keep in mind that the module will evolve over the course of the challenge, as I implement new features and functionality.


Puppet Module


The puppet module I created consists of different folders and files, each with a specific function. The structure is as follows:


pi@puppet:/etc/puppet/modules/openhab $ tree .
├── files
│   ├── openhab.items
│   ├──
│   ├── openhab.persist
│   ├── openhab.rules
│   └── openhab.sitemap
├── manifests
│   ├── configuration.pp
│   └── init.pp
└── templates
    └── openhab.cfg.erb




The "files" folder contains static files which will be copied to a specific location on the target node. The content of the files will not change, though the attributes such as file name, permissions, owner, etc ... could.


In this case, I have put my openhab configuration files with my specific sitemap, items, etc ... in that folder. Someone else using this puppet module, could replace these files with his own.




The manifests contain the logic of what should be configured and how. To keep a clear overview, the logic can be spread across different manifests.


In this particular case, two manifests were created:

  • init.pp: responsible for the installation of the openhab runtime
  • configuration.pp: responsible for the deployment of configuration files and accompanying openhab addons


Rather than explaining the full code of the manifests, I will highlight some interesting bits, helping you understand how I achieved certain things.


1) OpenHAB is not part of the APT repository by default. So in order to be able to install it, the correct source needs to be added:


apt::source { 'openhab':
  location => '',
  release => 'stable',
  repos => 'main',
  include_src => false,


This will add the source and automatically force a "apt-get update", making OpenHAB available for installation.


2) If OpenHAB is not installed, install it:


package { 'openhab-runtime':
  ensure => 'installed',


3) Make sure OpenHAB is running and automatically started at boot:


service { 'openhab':
  ensure => 'running',
  enable => true,


4) Make sure "openhab.cfg" is present in "/etc/openhab/configurations/", based on the "openhab.cfg.erb" template file. If the file is updated, restart the OpenHAB service to apply the new configuration:


file { '/etc/openhab/configurations/openhab.cfg':
  content => template('openhab/openhab.cfg.erb'),
  notify => Service['openhab'],



I hope this helps you understand the puppet manifest a little bit better and how it could apply to the deployment of other files and applications. For those of you interested in the full code, I invite you to have a look at the OpenHAB puppet module in the PiIoT GitHub repository I have created for this challenge, which will contain all files produced as part of this project. I will however replace all credentials and keys by dummy ones




This folder contains files of which the content has been templated to automatically be modified depending on certain variables in the manifests.


For example, if the variable "persistence" is set to true, it will add the MySQL Persistence section in the configuration file, along with the MySQL credentials and database defined in the configuration manifest.


It looks like this inside the templated "openhab.cfg" file:


<% if @persistence == true -%>
############################ SQL Persistence Service ##################################
# the database url like 'jdbc:mysql://<host>:<port>/<database>' (without quotes)
mysql:url=jdbc:mysql://localhost/<%= @db_name %>'

# the database user
mysql:user=<%= @db_user %>

# the database password
mysql:password=<%= @db_pass %>

# the reconnection counter

# the connection timeout (in seconds)
<% end -%>




Well, now that the openhab puppet module is explained, let's use it by performing a "puppet run" on the desired node.


pi@piiot1:~ $ sudo puppet agent -t


Et voila! That's all it takes to install, fully configure and start OpenHAB on any node, with the same, reproducible configuration.

You will want to read the "puppet run" output to see things are as expected.


For example, verify OpenHAB has been installed:


Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for piiot1.home
Info: Applying configuration version '1465327686'
Notice: /Stage[main]/Openhab/Apt::Key[openhab]/Exec[177ff3e62fb92bf7bc3ea298823a66b3db2d9c3f]/returns: executed successfully
Notice: /Stage[main]/Openhab/Apt::Source[openhab]/File[openhab.list]/ensure: created
Info: /Stage[main]/Openhab/Apt::Source[openhab]/File[openhab.list]: Scheduling refresh of Exec[apt_update]
Notice: /Stage[main]/Apt::Update/Exec[apt_update]: Triggered 'refresh' from 1 events
Notice: /Stage[main]/Openhab/Package[openhab-runtime]/ensure: created
Info: /Package[openhab-runtime]: Scheduling refresh of Service[openhab]
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/sitemaps/openhab.sitemap]/owner: owner changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/sitemaps/openhab.sitemap]/group: group changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/rules/openhab.rules]/owner: owner changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/rules/openhab.rules]/group: group changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/items/openhab.items]/owner: owner changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/items/openhab.items]/group: group changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/Package[openhab-addon-persistence-mysql]/ensure: ensure changed 'purged' to 'present'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/transform/]/owner: owner changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/transform/]/group: group changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/persistence/mysql.persist]/owner: owner changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab::Configuration/File[/etc/openhab/configurations/persistence/mysql.persist]/group: group changed 'openhab' to 'pi'
Notice: /Stage[main]/Openhab/Service[openhab]/enable: enable changed 'false' to 'true'
Notice: /Stage[main]/Openhab/Service[openhab]: Triggered 'refresh' from 1 events
Notice: Finished catalog run in 96.06 seconds


The output is readable enough to understand what is happening: First the sources were added, the repo was then updated, OpenHAB installed, configuration files deployed and finally OpenHAB was started. All with a single command.




I hope this post has helped you understand a little bit better how Puppet works and can be useful for consistent, reproducible installations. There is initially some effort in setting up the required modules, but not all of them need to be created from scratch like I did for OpenHAB. There is a community sharing puppet modules for various applications, so it is always good to check if something exists before creating your own (it is a good exercise though ).




Navigate to the next or previous post using the arrows.