Serverless Puppet with control repo, Hiera, roles and profiles and Puppet Bolt
The traditional way of managing systems with Puppet is to install Puppet agent on the nodes being managed and point those agents to a Puppet server (more details here). This approach works well for environments with tens or hundreds of nodes, but is an overkill for small environments with just a handful of nodes. Fortunately nowadays Puppet Bolt enables you to push configurations to the managed nodes via SSH and WinRM. When using Bolt the catalog (desired state) is created on the computer running Puppet Bolt using facts from managed nodes and then sent to the managed nodes to be applied.
Short introduction to Packer and Vagrant
This article is a short introduction to Packer and Vagrant - tools that we often recommend to our customers but which may be a bit hard to understand if you have no previous expose to them.
Packer
Packer is used to “create identical machine images for multiple platforms from a single source configuration”. Packer works in a very simple fashion:
- It reads its configuration file
- It launches a virtual machine based on the “base box” you’ve defined. The base box would be a “vanilla” Linux distribution such as Ubuntu 20.04.
- It runs the provisioning scripts you’ve written on the base box (via SSH)
- It removes deployment-specific things (e.g. SSH host keys)
- It shuts down the VM
- It creates a VM image out of base box + your changes
After this you can distribute the base box to people and they will have an identical system at their disposal. If you need to modify the image you can just change the provisioning scripts and/or the base image and rebuild. The configuration file can and should be stored in version control repository.
OpenVPN server options in Azure
OpenVPN is among the best VPN solutions, especially when you need a cross-platform (Windows, Mac, Linux, Android, iOS) solution that just works. It is best suited for point to site (P2S) or “road warrior” setups where users access internal resources using a VPN client when on the road.
When setting up OpenVPN server in Azure you have several options at your disposal:
-
Set up your own open source OpenVPN 2 server
What Vagrant plugins actually are?
This was a revelation that came to me when fixing Vagrant on my Fedora 34 laptop: Vagrant plugins seem to be just Ruby gems installed into an isolated runtime environment, with “vagrant plugin” ensuring that the gems are installed in the correct place.
The same gems that you can install with “vagrant plugiin install” can be found using vanilla gem command:
$ vagrant plugin list
rexml (3.2.5, global)
vagrant-hostmanager (1.8.9, global)
vagrant-vbguest (0.29.0, global)
winrm (2.3.6, global)
winrm-elevated (1.2.3, global)
winrm-fs (1.3.5, global)
$ gem info --remote rexml
*** REMOTE GEMS ***
rexml (3.2.5)
Author: Kouhei Sutou
Homepage: https://github.com/ruby/rexml
An XML toolkit for Ruby
$ gem info --remote vagrant-vbguest
*** REMOTE GEMS ***
vagrant-vbguest (0.29.0)
Author: Robert Schulze
Homepage: https://github.com/dotless-de/vagrant-vbguest
A Vagrant plugin to install the VirtualBoxAdditions into the guest
VM
$ gem list|grep vagrant
<no output>
On the remote side you can find all the familiar Vagrant plugins as gems, but vanilla gem won’t find them installed locally, because they’re in a different path.
Managing self-hosted GitLab with Terraform
GitLab has an extensive API which allows managing its internal configuration such as users, groups and projects. The official GitLab Terraform provider builds on top of this API.
It assumed here that the Terraform controller (e.g. your laptop) is able to reach your GitLab instance’s TCP port 443 - if it can’t there’s no way Terraform’s API calls will work. The same approach should work with gitlab.com - you can probably (=untested) skip the base_url parameter in that case.
The four ways to install Puppet modules
When working with Puppet and Puppet modules in particular you quickly notice that there are several ways to manage module dependencies. Today I learned about a new way introduced in Puppet Bolt 3.x, so I thought I’d compile a list that celebrates this diversity:
-
metadata.json: used primarily to dependency metadata to Puppet Forge. Some tools like librarian-puppet and puppet-litmus use / can use this file to download dependency modules. The downside is that you can’t define the location of the modules, so you’re limited to Forge modules.
Notes about puppet-litmus testing
Puppet Litmus is a Puppet acceptance test harness that leverages on many existing, proven technologies. In the long run Litmus aims to replace Beaker. However, the latter is currently still the only way to run multi-machine (e.g. cluster) acceptance tests in a standardized way. For example we use Beaker for our Keycloak domain mode cluster tests in puppet-module-keycloak. On a high-level the test process is the same as with Beaker:
-
Provision the SUT (“System Under Test”)
Configuring ejabberd multi-user chatrooms
Ejabberd is a very flexible and scalable XMPP server. We use it because it can be configured using a simple yaml configuration file and managed via ejabberdctl commands. This makes it a good fit for our infrastructure as code approach. That said, ejabberd does require one to understand the XMPP protocol/jargon as it does not abstract away any of it. So simple things like creating chatrooms, limiting access to them and playing history backlog to users who connected them can be an effort if you’ve never done it.
Ejabberd message archiving and history playback
When using ejabberd in a company for multi-user chat (see my earlier blog post) people will quickly start complaining that they missed discussions because they had been offline. Ejabberd does play back last 20 messages when user joins a room, but that is too little for an active chatroom. The simplistic approach is to set history_size in mod_muc settings in ejabberd.yml to a higher value:
mod_muc:
history_size: 200
--- snip ---
This simplistic approach should work with any XMPP clients.
Creating custom facts programmatically
Writing static facts is fairly easy even with a low level of Ruby skills. Below is an example of a fact that returns true or false depending on whether the node has a /boot partition:
Facter.add(:has_bootfs) do
setcode do
if Facter.value(:mountpoints)['/boot'].nil?
false
else
true
end
end
end
As you can see above the required information was already inside the “mountpoints” fact of Facter.
Using the fact is easy: