<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Deep-Dive on Puppeteers Oy</title>
		<link>https://www.puppeteers.net/categories/deep-dive/</link>
		<description>Recent content in Deep-Dive on Puppeteers Oy</description>
		<generator>Hugo</generator>
		<language>en-US</language>
		
		
		
		
			<lastBuildDate>Thu, 31 Oct 2024 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://www.puppeteers.net/categories/deep-dive/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Monitoring Azure with Prometheus</title>
				<link>https://www.puppeteers.net/blog/monitoring-azure-with-prometheus/</link>
				<pubDate>Thu, 31 Oct 2024 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/monitoring-azure-with-prometheus/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-kelly-2543201-trimmed-1.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://prometheus.io/&#34;&gt;Prometheus&lt;/a&gt; is a great tool for &amp;ldquo;cloud-native&amp;rdquo; metrics gathering and monitoring. It is particularly easy to manage with &lt;a href=&#34;https://www.puppeteers.net/learn/understanding-infrastructure-as-code-iac/&#34;&gt;infrastructure as code&lt;/a&gt; methods. Prometheus can collect metrics from various sources, including &lt;a href=&#34;https://azure.microsoft.com/en-us/products/monitor/&#34;&gt;Azure Monitor&lt;/a&gt;. You can use &lt;a href=&#34;https://github.com/webdevops/azure-metrics-exporter&#34;&gt;Azure Metrics Exporter&lt;/a&gt; to convert Azure Monitor metrics into Prometheus metrics, but doing so is definitely not trivial unless you&amp;rsquo;re pretty familiar with Prometheus, Azure Monitor and Microsoft Entra ID apps. This article tries to help you make monitoring Azure with Prometheus a breeze instead of a struggle. We won&amp;rsquo;t go into a lot of detail about Prometheus or Azure Monitor as there&amp;rsquo;s plenty of information available elsewhere about both of them. Also note that this article is about vanilla Prometheus, &lt;em&gt;not&lt;/em&gt; Microsoft&amp;rsquo;s &amp;ldquo;Azure Monitor managed service for Prometheus&amp;rdquo;.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Avoid double taxation when selling to the U.S</title>
				<link>https://www.puppeteers.net/blog/avoid-double-taxation-when-selling-to-the-u-s/</link>
				<pubDate>Thu, 03 Oct 2024 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/avoid-double-taxation-when-selling-to-the-u-s/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-karolina-grabowska-4386367.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;We sell digital products in &lt;a href=&#34;https://aws.amazon.com/marketplace/&#34;&gt;AWS Marketplace&lt;/a&gt;, &lt;a href=&#34;https://azuremarketplace.microsoft.com&#34;&gt;Azure Marketplace&lt;/a&gt; and &lt;a href=&#34;https://www.udemy.com/&#34;&gt;Udemy&lt;/a&gt; - see our &lt;a href=&#34;https://www.puppeteers.net/products/&#34;&gt;products page&lt;/a&gt; for detail. The end customers of our products are located around the world, including the Unites States of America. All the aforementioned platforms a located in the U.S. This means that they comply with the U.S. tax laws both on the state and federal level. &lt;a href=&#34;https://www.irs.gov/&#34;&gt;Internal Revenue Service&lt;/a&gt; (IRS) is responsible for collecting the federal taxes, which are relevant for this article. Foreign (e.g. European) corporations that sell (digital) products or services to U.S. customers need to prove to IRS that it should not withhold federal taxes from the income coming from U.S. end customers. The goal of this article is to help European corporations (companies) avoid double taxation: first by the IRS and then by the tax office of its own home country. We have all the basic information that a typical European corporation (company) needs to do to avoid double taxation when selling services or digital products to U.S. end customers.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Microsoft Entra ID multi-factor authentication in RDP</title>
				<link>https://www.puppeteers.net/blog/microsoft-entra-id-multi-factor-authentication-in-rdp/</link>
				<pubDate>Fri, 28 Jun 2024 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/microsoft-entra-id-multi-factor-authentication-in-rdp/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-olly-3760043.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;Microsoft Entra ID, formerly known as Azure Activate Directory (AAD), is replacing classic on-premise Active Directory installations slowly but surely. It replaces &amp;ldquo;legacy&amp;rdquo; protocols such as LDAP and Kerberos with &amp;ldquo;modern&amp;rdquo; protocols such as SAML, OIDC and OAuth2. However, the client-side support in various operating systems such as Windows, Linux and MacOS is spotty, to say the least. You can make things work, but only if the stars (or rather, bits) are aligned &lt;em&gt;just right&lt;/em&gt;. This article explains how multi-factor authentication in RDP works with Azure VMs when using Microsoft Entra ID. Note the emphasis on &lt;strong&gt;MFA&lt;/strong&gt;: without MFA you can make logins with Entra ID work more easily by using the normal username + password authentication in RDP.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Using Hiera with Ansible</title>
				<link>https://www.puppeteers.net/blog/using-hiera-with-ansible/</link>
				<pubDate>Fri, 07 Jun 2024 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/using-hiera-with-ansible/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-skitterphoto-63901.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.puppet.com/docs/puppet/8/hiera.html&#34;&gt;Hiera&lt;/a&gt; is a very powerful &amp;ldquo;key-value configuration data lookup system&amp;rdquo; used mainly, but not exclusively, with the &lt;a href=&#34;https://www.puppeteers.net/learn/what-is-puppet-and-how-does-it-work/&#34;&gt;Puppet&lt;/a&gt; configuration management and orchestration system. In Hiera data is stored in in yaml files in, as the name implies, a hierarchy or set of prioritized &lt;em&gt;levels&lt;/em&gt;. A typical Hiera lookup goes through the hierarchy starting from the highest-priority level and stops when it finds a match. That match could come from a node yaml file, a deployment (e.g. production or staging) yaml file or from site-wide yaml. What this essentially means is that you can define common, site-wide parameters at the lowest level of the hierarchy and override those when needed at higher levels. How does Hiera and Ansible work together, then? The short answer is &amp;ldquo;they don&amp;rsquo;t, really&amp;rdquo;, but the long answer is more complex than that.&lt;/p&gt;</description>
			</item>
			<item>
				<title>RHEL on Upcloud</title>
				<link>https://www.puppeteers.net/blog/rhel-on-upcloud/</link>
				<pubDate>Mon, 27 May 2024 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/rhel-on-upcloud/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-pixabay-86695.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://upcloud.com/&#34;&gt;Upcloud&lt;/a&gt; is a Finnish Cloud provider that focuses on high-quality services. There is no built-in support for installing RHEL on Upcloud, which is quite typical of &amp;ldquo;small Clouds&amp;rdquo;. Sometimes you don&amp;rsquo;t want to use clones (e.g. Rocky Linux) and need real RHEL instead. This is where this article comes handy, as the RHEL installation process in Upcloud is far from trivial. This article focuses on RHEL 9, but the process may work with older and newer versions as well. The process I describe here applies almost 1:1 to &lt;em&gt;any&lt;/em&gt; Linux operating system Upcloud does not natively support.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Buildbot build order: how to run certain builds before others?</title>
				<link>https://www.puppeteers.net/blog/buildbot-build-order-how-to-run-certain-builds-before-others/</link>
				<pubDate>Tue, 06 Feb 2024 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/buildbot-build-order-how-to-run-certain-builds-before-others/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/Buildbot-DependentScheler-in-action.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;The mechanisms for configuring Buildbot build order is documented fairly well. However, what that documentation lacks is a centralized place where ordering is explained. My personal goal was to run smoke tests first and if those don&amp;rsquo;t pass then cancel all other build requests. That seemed straightforward, but turned out not to be so. There were many, many ways that could in theory be achieved, but most of those did not work at all, or worked only partially. This article attempts to fill the &amp;ldquo;how do I order builds in Buildbot&amp;rdquo; gap, including what can and can&amp;rsquo;t be achieved with each strategy.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Install RHEL 9 on Hetzner Cloud</title>
				<link>https://www.puppeteers.net/blog/install-rhel-9-on-hetzner-cloud/</link>
				<pubDate>Fri, 20 Oct 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/install-rhel-9-on-hetzner-cloud/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-mateusz-salaciak-4275885-1024x682.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Scaling a mountain is about as easy as to install RHEL 9 in Hetzner Cloud in scalable way. At minimum, you need this article and lots of endurance to pull it off. &lt;a href=&#34;https://www.pexels.com/it-it/foto/casa-in-legno-marrone-sul-campo-di-erba-verde-vicino-a-montagne-e-alberi-verdi-4275885/&#34;&gt;Photo credit&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.hetzner.com/cloud&#34;&gt;Hetzner Cloud&lt;/a&gt; is a really good &amp;ldquo;small&amp;rdquo; Cloud with particularly good value for money. While it does not have hundreds of services like AWS or Azure, but it has most of the basic stuff. Hetzner cloud has built-in support for Red Hat Enterprise Linux (RHEL) clones such as Rocky Linux 9. However, you &lt;em&gt;cannot&lt;/em&gt; spin up real RHEL 9 instances without spending some time on it. This article will give you all the details you need to install RHEL 9 on Hetzner Cloud. We do that in a way that you can reuse your RHEL 9 installation to spin up multiple servers from one snapshot. This way you don&amp;rsquo;t have to run the RHEL installer for every RHEL server you want to spin up.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Blackbox Exporter ICMP module and selinux</title>
				<link>https://www.puppeteers.net/blog/blackbox-exporter-icmp-module-and-selinux/</link>
				<pubDate>Thu, 21 Sep 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/blackbox-exporter-icmp-module-and-selinux/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-pixabay-2748861-1024x682.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Blackbox Exporter ICMP module and selinux do not like each other. Same goes for systemd units and ICMP Echo sockets. However, with persistence, skill and a bit of luck you can make it all work together. &lt;a href=&#34;https://www.pexels.com/it-it/foto/foto-in-scala-di-grigi-del-filo-spinato-274886/&#34;&gt;Photo credit&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/prometheus/blackbox_exporter&#34;&gt;Blackbox Exporter&lt;/a&gt; is an exporter for the &lt;a href=&#34;https://prometheus.io/&#34;&gt;Prometheus&lt;/a&gt; monitoring system. It is able to probe a target, such as a host or an application from the outside. Blackbox Exporter does probing with modules such as http, tcp, dns, icmp and grpc (details &lt;a href=&#34;https://github.com/prometheus/blackbox_exporter/blob/master/CONFIGURATION.md&#34;&gt;here&lt;/a&gt;). The icmp module is special because it does privileged operations that require the CAP_NET_RAW capability and as well as custom selinux policies. This article aims to explain how you can make Blackbox Exporter ICMP module and selinux work together. &lt;strong&gt;NOTE:&lt;/strong&gt; you do not need any of these tricks if you use non-icmp Blackbox exporter modules.&lt;/p&gt;</description>
			</item>
			<item>
				<title>How to reduce RDS storage size in an automated way</title>
				<link>https://www.puppeteers.net/blog/how-to-reduce-rds-storage-size-in-an-automated-way/</link>
				<pubDate>Thu, 10 Aug 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/how-to-reduce-rds-storage-size-in-an-automated-way/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-jakub-zerdzicki-16978372.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;Amazon RDS is a relational database service available on Amazon Web Services. It is essentially a managed database server with a volume for the data. Both cost money. Having a large dataset is not the only reason have big volume: the volume size determines the number of I/O operations (IOPS) the volume can do. If you have high load on your RDS instance you may very well run out of IOPS which can result in a disaster. Scaling up the volume size is easy to avoid such disasters, but it is much more difficult to reduce RDS storage size. This is because downsizing RDS storage size &lt;a href=&#34;https://repost.aws/knowledge-center/rds-db-storage-size&#34;&gt;is not officially supported by AWS&lt;/a&gt;. If the load on your RDS instance goes down (e.g. due to refactoring), you may end up having a database with an oversized volume that costs lots of money for no reason.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Downsize AWS RDS Volume</title>
				<link>https://www.puppeteers.net/blog/downsize-aws-rds-volume/</link>
				<pubDate>Mon, 08 May 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/downsize-aws-rds-volume/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-pixabay-359641.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;It is trivial to downsize an AWS RDS &lt;em&gt;instance&lt;/em&gt;. It is equally trivial to upsize AWS RDS volumes. However, to downsize AWS RDS volume you need to jump through lots of hoops.&lt;/p&gt;&#xA;&lt;p&gt;So, why would you ever want to downsize an AWS RDS volume? One reason might be that you increased the volume size simply to get more burst credits for the &lt;em&gt;volume&lt;/em&gt;. Then you did refactoring that reduced the need to have that many credits and want to save money. Or maybe you genuinely had a huge amount of data on your RDS instance volume, removed some of it but got stuck with a huge volume.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Keycloak authorization services REST API: paths and payloads</title>
				<link>https://www.puppeteers.net/blog/keycloak-authorization-services-rest-api-paths-and-payload/</link>
				<pubDate>Fri, 24 Mar 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/keycloak-authorization-services-rest-api-paths-and-payload/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-alex-andrews-12038081.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://www.keycloak.org/docs/latest/authorization_services/index.html&#34;&gt;Keycloak Authorization Services&lt;/a&gt; allows you to offload your application&amp;rsquo;s authorization decisions to Keycloak instead of implementing them in your code. This way you can leverage Keycloak&amp;rsquo;s advanced features like 2FA without any additional development on your part. If you&amp;rsquo;re unfamiliar with the Authorization Services I suggest having a look at the &lt;a href=&#34;https://www.puppeteers.net/blog/keycloak-authorization-services-terminology/&#34;&gt;Keycloak authorization services terminology&lt;/a&gt; first. You may also be interested in &lt;a href=&#34;https://www.puppeteers.net/blog/adding-new-permission-to-shared-resources-with-keycloak-rest-api/&#34;&gt;our sample code&lt;/a&gt; for managing Keycloak authorization services programmatically. To be perfectly honest, there is no separate Keycloak authorization services REST API. While the authorization services do support the UMA &lt;a href=&#34;https://www.keycloak.org/docs/latest/authorization_services/#_service_protection_api&#34;&gt;Protection API&lt;/a&gt;, that API is only needed if you want your &lt;em&gt;resource servers&lt;/em&gt; (e.g. webapps) to be able manage their own authorization services configuration inside Keycloak. For example, you might want to provide your webapp users the capability to grant access (e.g. read, write) to their own resources to &lt;em&gt;other&lt;/em&gt; users. In this article we &lt;em&gt;will not&lt;/em&gt; cover the Protection API at all.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Debugging Keycloak OIDC token exchange</title>
				<link>https://www.puppeteers.net/blog/debugging-keycloak-oidc-token-exchange/</link>
				<pubDate>Wed, 22 Mar 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/debugging-keycloak-oidc-token-exchange/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-pixabay-532173.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;There&amp;rsquo;s no substitute for understanding what you&amp;rsquo;re doing, and that in turn is difficult without seeing what is happening. Debugging Keycloak OIDC problems without understanding what is happening under the hood is no exception to this rule. The purpose of this article is twofold:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Help you learn how Keycloak OIDC token exchange work&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Provide you with the tools to debug Keycloak OIDC token exchanges in production environments&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;For the purposes of this blog post I&amp;rsquo;ve been using the &lt;a href=&#34;https://github.com/PacktPublishing/Keycloak-Identity-and-Access-Management-for-Modern-Applications&#34;&gt;OpenID Connect Playground&lt;/a&gt; application from the book &lt;a href=&#34;https://www.packtpub.com/product/-keycloak-identity-and-access-management-for-modern-applications/9781800562493&#34;&gt;Keycloak - Identity and Access Management for Modern Applications&lt;/a&gt; from Packt Publishing. I can recommend that book for anyone who needs to understand Keycloak and in particular the protocols it supports (OAuth2, OIDC and SAML 2.0).&lt;/p&gt;</description>
			</item>
			<item>
				<title>Keycloak authorization services: terminology</title>
				<link>https://www.puppeteers.net/blog/keycloak-authorization-services-terminology/</link>
				<pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/keycloak-authorization-services-terminology/</guid>
				<description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.puppeteers.net/blog/adding-new-permission-to-shared-resources-with-keycloak-rest-api/&#34;&gt;Keycloak Authorization Services&lt;/a&gt; are built on top of well-known standards such as the &lt;a href=&#34;https://oauth.net/2/&#34;&gt;OAuth2&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/User-Managed_Access&#34;&gt;User-Managed Access&lt;/a&gt; specifications (UMA). You can manage Keycloak Authorization Services programmatically, if needed, as described in our other &lt;a href=&#34;https://www.puppeteers.net/blog/adding-new-permission-to-shared-resources-with-keycloak-rest-api/&#34;&gt;blog post&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;OAuth2 clients (such as front end applications) can obtain &lt;em&gt;access tokens&lt;/em&gt; from the server using the &lt;em&gt;token endpoint&lt;/em&gt; and use these tokens to access &lt;em&gt;resources&lt;/em&gt; protected by a &lt;em&gt;resource server&lt;/em&gt; (such as back end services).&lt;/p&gt;&#xA;&lt;p&gt;In the same way, Keycloak Authorization Services provide extensions to OAuth2 to allow access tokens to be issued based on the processing of all &lt;em&gt;policies&lt;/em&gt; associated with the &lt;em&gt;resource(s)&lt;/em&gt; or &lt;em&gt;scope(s)&lt;/em&gt; being requested. This means that resource servers can enforce access to their protected resources based on the &lt;em&gt;permissions&lt;/em&gt; granted by the server and held by an access token. In Keycloak Authorization Services the access token with permissions is called a &lt;em&gt;Requesting Party Token&lt;/em&gt; or &lt;em&gt;RPT&lt;/em&gt; for short.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Let&#39;s Encrypt on AWS: when, where and why</title>
				<link>https://www.puppeteers.net/blog/lets-encrypt-on-aws-when-where-and-why/</link>
				<pubDate>Wed, 15 Mar 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/lets-encrypt-on-aws-when-where-and-why/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/Canofworms1.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s Encrypt on AWS can be a can of worms if you don&amp;rsquo;t know what you&amp;rsquo;re doing. &lt;a href=&#34;https://commons.wikimedia.org/wiki/File:Canofworms1.png&#34;&gt;Photo credit&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://letsencrypt.org/how-it-works/&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; and the ACME protocol enable getting free (as in beer) TLS/SSL certificates. The main use for Let&amp;rsquo;s Encrypt is to enable HTTPS on web servers. Let&amp;rsquo;s Encrypt TLS certificates expire pretty quickly, in 3 months, but the idea is that renewal is automated so that you don&amp;rsquo;t ever really have to worry about expiration, unlike with commercial TLS certificates, which you typically need to manually renew every 12 months. Using Let&amp;rsquo;s Encrypt on &lt;a href=&#34;https://aws.amazon.com&#34;&gt;AWS&lt;/a&gt; is in &lt;em&gt;some cases&lt;/em&gt; a very viable option, but not so much in others. In many cases trying to use Let&amp;rsquo;s Encrypt certificates leads you down the path of Lovecraftian horrors and madness. Because &amp;ldquo;it all depends&amp;rdquo; I&amp;rsquo;ll try to explain when using Let&amp;rsquo;s Encrypt is viable in the AWS context and when you really should &lt;em&gt;just give up&lt;/em&gt; an use certificates generated by the Amazon Certificate Manager (&amp;ldquo;ACM&amp;rdquo;) instead.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Integrating Twilio SMS and Prometheus Alertmanager</title>
				<link>https://www.puppeteers.net/blog/integrating-twilio-sms-and-prometheus-alertmanager/</link>
				<pubDate>Thu, 16 Feb 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/integrating-twilio-sms-and-prometheus-alertmanager/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/prometheus-logo.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://prometheus.io/&#34;&gt;Prometheus&lt;/a&gt; is a widely used, cloud-native open source monitoring solution. Its alerting component is called &lt;a href=&#34;https://prometheus.io/docs/alerting/latest/alertmanager/&#34;&gt;Alertmanager&lt;/a&gt;, which can send alerts to email, Slack and elsewhere. Both Prometheus and Alertmanager fit very well into the &lt;a href=&#34;https://www.puppeteers.net/learn/understanding-infrastructure-as-code-iac/&#34;&gt;infrastructure as code model&lt;/a&gt; as well. &lt;a href=&#34;https://www.twilio.com/docs/sms&#34;&gt;Twilio SMS&lt;/a&gt; is a SMS sending service with consumption-based pricing model with an extensive API. With some effort you can integrate Twilio SMS and Prometheus together as described in this article.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Testing AlertManager webhooks with curl</title>
				<link>https://www.puppeteers.net/blog/testing-alertmanager-webhooks-with-curl/</link>
				<pubDate>Mon, 06 Feb 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/testing-alertmanager-webhooks-with-curl/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-steve-johnson-1256916-scaled.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://prometheus.io&#34;&gt;Prometheus&lt;/a&gt; is a Cloud-native metrics platforms that is very easy to manage with &lt;a href=&#34;https://www.puppeteers.net/learn/understanding-infrastructure-as-code-iac/&#34;&gt;infrastructure as code&lt;/a&gt; tools. Prometheus is often couple with Alertmanager which handles alerting and alert routing. AlertManager has good support for various alert transport (e.g. email or slack) but its alerting capabilities can be extended with custom webhooks. When AlertManager is configured to use a webhook in an alert route, it forwards alerts to an HTTPS/HTTP endpoint instead of handling transporting of the alert itself. AlertManager&amp;rsquo;s official documentation gives a rough idea of what kind of payload to use and how to configure the webhook in alertmanager.yaml. What is not documented is how you can send test alerts to the webhook &lt;em&gt;without&lt;/em&gt; having to trigger real (or fake) alerts in Prometheus. While using fake alerts does work, it is a slow, tedious and invasive process. This article shows one way for testing AlertManager webhooks with curl. In our case the target was to speed up testing of changes to &lt;a href=&#34;https://github.com/Swatto/promtotwilio&#34;&gt;promtotwilio&lt;/a&gt;.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Adding new permission with Keycloak authorization services REST API</title>
				<link>https://www.puppeteers.net/blog/adding-new-permission-to-shared-resources-with-keycloak-rest-api/</link>
				<pubDate>Sun, 15 Jan 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/adding-new-permission-to-shared-resources-with-keycloak-rest-api/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-ryan-miguel-capili-3605822.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-does-it-do-this-keycloak-thing&#34;&gt;What does it do, this Keycloak thing?&lt;/h3&gt;&#xA;&lt;p&gt;Dear seasoned keycloaker, as you probably know, &lt;a href=&#34;https://www.keycloak.org/&#34;&gt;Keycloak&lt;/a&gt; is a stable, scalable, programmable and otherwise killer platform to centralize all your identity, authentication and authorization needs. Keycloak supports &lt;em&gt;fine-grained authorization policies&lt;/em&gt; using Keycloak &lt;a href=&#34;https://www.keycloak.org/docs/latest/authorization_services&#34;&gt;authorization services&lt;/a&gt;. We highly recommend reading our &lt;a href=&#34;https://www.puppeteers.net/blog/keycloak-authorization-services-terminology/&#34;&gt;Keycloak authorization services terminology&lt;/a&gt; article before this article. if you don&amp;rsquo;t understand terms, you will have some hard times ahead. The purpose of &lt;em&gt;this article&lt;/em&gt; is to give you an example of how to work with the Keycloak authorization services REST API.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Debugging Terraform AWS UnauthorizedOperation errors</title>
				<link>https://www.puppeteers.net/blog/debugging-terraform-aws-unauthorizedoperation-errors/</link>
				<pubDate>Wed, 11 Jan 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/debugging-terraform-aws-unauthorizedoperation-errors/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-jake-young-732894.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;causes-for-the-terraform-aws-unauthorizedoperation-errors&#34;&gt;Causes for the Terraform AWS UnauthorizedOperation errors&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.puppeteers.net/learn/what-is-terraform-and-how-does-it-work/&#34;&gt;Terraform&lt;/a&gt; is an &lt;a href=&#34;https://www.puppeteers.net/learn/understanding-infrastructure-as-code-iac/&#34;&gt;infrastructure as code&lt;/a&gt; tool you can use to configure Cloud resources in AWS. When using &lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/aws/latest/docs&#34;&gt;Terraform AWS provider&lt;/a&gt; you frequently run into various UnauthorizedOperation errors when creating, modifying or deleting resources. That happens unless you do what you should &lt;em&gt;not&lt;/em&gt; do and let Terraform use an AWS API key tied to an IAM user with full admin privileges. In almost all cases Terraform UnauthorizedOperation errors are caused by missing IAM permissions. It can sometimes be a bit tedious to get to the root cause, because Terraform may not show it in its normal output.&lt;/p&gt;</description>
			</item>
			<item>
				<title>How to disable S3 bucket ACLs</title>
				<link>https://www.puppeteers.net/blog/how-to-disable-s3-bucket-acls/</link>
				<pubDate>Tue, 10 Jan 2023 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/how-to-disable-s3-bucket-acls/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-david-riano-cortes-975771.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;AWS recommends that you disable S3 bucket ACLs for all new buckets. To understand why some background information is needed.&lt;/p&gt;&#xA;&lt;p&gt;AWS S3 providers two ways to manage access to S3 buckets and objects:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Access policies:&lt;/strong&gt; these are standard IAM policies that you attach to users (&amp;ldquo;user policies&amp;rdquo;) or resources (&amp;ldquo;resource-based policies&amp;rdquo;). IAM policies are the recommended method for managing access to Amazon S3 nowadays.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Access Control Lists (ACLs)&lt;/strong&gt;: ACLs are an older access control method for AWS S3. ACL &lt;a href=&#34;https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html&#34;&gt;map to IAM permissions&lt;/a&gt;. ACLs works on the bucket and object (file) file.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Azure Private DNS and VPN Gateway</title>
				<link>https://www.puppeteers.net/blog/azure-private-dns-and-vpn-gateway/</link>
				<pubDate>Tue, 13 Dec 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/azure-private-dns-and-vpn-gateway/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-mo-eid-8347501.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-azure-private-dns&#34;&gt;What is Azure Private DNS?&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://learn.microsoft.com/en-us/azure/dns/private-dns-overview&#34;&gt;Azure Private DNS&lt;/a&gt; is a DNS service for Azure virtual networks. You can register a &lt;a href=&#34;https://learn.microsoft.com/en-us/azure/dns/private-dns-privatednszone&#34;&gt;private DNS zone&lt;/a&gt; to Azure Private DNS and then link that zone with one or more virtual networks. If you enable DNS auto-registration for a virtual network, a new resource (e.g. virtual machines and VPN Gateways) will automatically add its IP address to Azure Private DNS. Resources in the linked virtual networks can use entries in Azure Private DNS to locate each other, instead of relying on IP addresses or the default Azure DNS domain. You can make Azure Private DNS and Azure VPN Gateway work together in several ways, some of which this article will describe.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Cloud automation and infrastructure standardization at Red Hat Open Tour 2022</title>
				<link>https://www.puppeteers.net/blog/cloud-automation-and-infrastructure-standardization-at-red-hat-open-tour-2022/</link>
				<pubDate>Sat, 01 Oct 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/cloud-automation-and-infrastructure-standardization-at-red-hat-open-tour-2022/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/Red-Hat-Open-Tour-2022-Tallinn-badge-part.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;We participated in &lt;a href=&#34;https://www.redhat.com/en/events/open-tour-tallinn-2022&#34;&gt;Red Hat Open Tour 2022 Tallinn&lt;/a&gt; a while back. Johan Wennerberg, who is a Solution Architect for Red Hat Nordics in Stockholm, gave a presentation titled &amp;ldquo;Gain robust repeatability as self.service, by automating your automation&amp;rdquo;. Among other things he discussed the importance and use-cases of Cloud infrastructure standardization and automation. Here I willsummarize his views on standardization and automation and explain how they tie in with our focus on &lt;em&gt;quality&lt;/em&gt; in the Cloud infrastructure and elsewhere.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Enabling Azure Backup on Linux VMs with Terraform</title>
				<link>https://www.puppeteers.net/blog/enabling-azure-backup-on-linux-vms-with-terraform/</link>
				<pubDate>Mon, 05 Sep 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/enabling-azure-backup-on-linux-vms-with-terraform/</guid>
				<description>&lt;p&gt;This article shows you how to enable Azure Backup on Linux VMs. It is recommended to read the &lt;a href=&#34;https://www.puppeteers.net/blog/understanding-azure-backup-for-linux-vms/&#34;&gt;Understanding Azure Backup for Linux VMs&lt;/a&gt; article first before trying to enable backups with Terraform. Terraform AzureRM provider has three relevant resources:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_virtual_machine&#34;&gt;azurerm_linux_virtual_machine&lt;/a&gt;: parameters &lt;em&gt;provision_vm_agent&lt;/em&gt; and &lt;em&gt;allow_extension_operations&lt;/em&gt; should be &lt;em&gt;true&lt;/em&gt; or enabling backups will fail (with or without Terraform)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine_extension&#34;&gt;azurerm_virtual_machine_extension&lt;/a&gt;: this can be used to run/enable a VM extension on a VM&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_protected_vm&#34;&gt;azurerm_backup_protected_vm&lt;/a&gt;: this resource enables backups on a VM&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/recovery_services_vault&#34;&gt;azurerm_recovery_services_vault&lt;/a&gt;: the recovery services vault where backups will be stored&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/backup_policy_vm&#34;&gt;azurerm_backup_policy_vm&lt;/a&gt;: backup schedule and retainment rules&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll go through the basic process first, which may work for some people. I&amp;rsquo;ll then take a deep dive into the timeout issues you &lt;em&gt;may&lt;/em&gt; or &lt;em&gt;may not&lt;/em&gt; encounter in your environment.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Understanding Azure Backup for Linux VMs</title>
				<link>https://www.puppeteers.net/blog/understanding-azure-backup-for-linux-vms/</link>
				<pubDate>Mon, 29 Aug 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/understanding-azure-backup-for-linux-vms/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://docs.microsoft.com/en-us/azure/backup/backup-overview&#34;&gt;Azure Backup&lt;/a&gt; is an Azure service that allows, among other things, backing up Windows and Linux VMs in Azure. The backups are essentially virtual machine snapshots, but backing up and/or restoring individual files is also possible. This article tries to explain how Azure Backup and Linux VMs interact and what is required for them to work. If you&amp;rsquo;re interested in using Terraform to configure Azure Backup, please have a look at the &lt;a href=&#34;https://www.puppeteers.net/blog/enabling-azure-backup-on-linux-vms-with-terraform/&#34;&gt;Enabling Azure Backup on Linux VMs with Terraform&lt;/a&gt; article.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Terraform: converting an  aws_instance network interface into an explicitly managed interface</title>
				<link>https://www.puppeteers.net/blog/terraform-converting-an-aws_instance-network-interface-into-an-explicitly-managed-interface/</link>
				<pubDate>Tue, 23 Aug 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/terraform-converting-an-aws_instance-network-interface-into-an-explicitly-managed-interface/</guid>
				<description>&lt;p&gt;The &lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance&#34;&gt;aws_instance resource&lt;/a&gt; in Terraform can automatically create the default network interface for you. There are cases, however, when you notice that the default network interface is not enough anymore, and modifying it via the limited aws_instance parameters is not sufficient. In these cases you &lt;em&gt;can&lt;/em&gt; convert the interface into an &lt;a href=&#34;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_interface&#34;&gt;aws_network_interface resource&lt;/a&gt;, but the process is far from straightforward.&lt;/p&gt;&#xA;&lt;p&gt;The first step is to create a Terraform resource for the network interface:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Managing custom realm keys in Keycloak programmatically</title>
				<link>https://www.puppeteers.net/blog/managing-custom-realm-keys-in-keycloak-programmatically/</link>
				<pubDate>Fri, 19 Aug 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/managing-custom-realm-keys-in-keycloak-programmatically/</guid>
				<description>&lt;h2 id=&#34;what-are-keycloak-realm-keys&#34;&gt;What are Keycloak realm keys?&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.keycloak.org/&#34;&gt;Keycloak&lt;/a&gt;&amp;rsquo;s authentication protocols make use of private and public keys for signing and encrypting, as described in the &lt;a href=&#34;https://www.keycloak.org/docs/latest/server_admin/index.html#realm_keys&#34;&gt;official documentation&lt;/a&gt;. These keys are realm-specific, and by default managed internally in Keycloak. So, when you create a realm using the Keycloak Admin API, kcadm.sh or manually using the Web UI, new keypair(s) get generated automatically. These are called &amp;ldquo;Managed keys&amp;rdquo;. However, you can also use custom realm keys in Keycloak, which is what this article is about. Using custom realm keys allow you, for example, to use a single keypair in multiple realms. When you import a custom private key, Keycloak uses it to automatically create a certificate. If you want, you can pass both a private key and a certificate signed with that private key instead. That way you can bypass Keycloak&amp;rsquo;s automatic certificate generation, should you need to.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Modern cronjob part 1: Azure Automation with Terraform</title>
				<link>https://www.puppeteers.net/blog/modern-cronjob-part-1-azure-automation-with-terraform/</link>
				<pubDate>Thu, 11 Aug 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/modern-cronjob-part-1-azure-automation-with-terraform/</guid>
				<description>&lt;p&gt;Microsoft Azure has a nice service for scheduling tasks called &lt;a href=&#34;https://duckduckgo.com/?q=azure&amp;#43;automation&amp;amp;t=newext&amp;amp;atb=v310-1&amp;amp;ia=web&#34;&gt;Azure Automation&lt;/a&gt;. While Azure Automation is able to other things as well, such as being able to act as a Powershell DSC pull server, we&amp;rsquo;ll focus on the runbooks and scheduling. Runbooks are scripts that do things, e.g. run maintenance and reporting tasks. Runbooks often, but not necessarily manipulate objects in Azure. Runbooks are serverless like Azure Functions and the pricing is therefore similar - you pay for the amount of computing resources you use and don&amp;rsquo;t have to pay for a server that&amp;rsquo;s mostly idle.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Multi-part cloud-init provisioning with Terraform</title>
				<link>https://www.puppeteers.net/blog/multi-part-cloud-init-provisioning-with-terraform/</link>
				<pubDate>Thu, 28 Apr 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/multi-part-cloud-init-provisioning-with-terraform/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://cloud-init.io/&#34;&gt;Cloud-Init&lt;/a&gt; is &amp;ldquo;a standard for customizing&amp;rdquo; cloud instances, typically on their first boot. It is allows mixing state-based configuration management with imperative provisioning commands (details in &lt;a href=&#34;https://www.puppeteers.net/learn/understanding-infrastructure-as-code-iac/&#34;&gt;our IaC article&lt;/a&gt;). By using cloud-init most of the annoyances of SSH-based provisioning can be avoided:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Having to use (possibly shared) SSH keys for provisioning&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Having to have direct network access to the VM being provisioned (may require a VPN connection)&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;That said, neither cloud-init itself, nor its use within Terraform is particularly well documented. Therefore it can be an effort to create cloud-init-based provisioning that works &lt;em&gt;and&lt;/em&gt; adapts easily to different use-cases. This article attempts to fill that gap to some extent.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Data-driven Terraform: Kubernetes cluster in Hetzner Cloud</title>
				<link>https://www.puppeteers.net/blog/data-driven-terraform-kubernetes-cluster-in-hetzner-cloud/</link>
				<pubDate>Fri, 15 Apr 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/data-driven-terraform-kubernetes-cluster-in-hetzner-cloud/</guid>
				<description>&lt;p&gt;Terraform does not have a particularly strong decoupling between &lt;em&gt;data&lt;/em&gt; and &lt;em&gt;code&lt;/em&gt;, at least not from a best practices perspective. It is possible and useful, however, to use data to define Terraform resources - if not for any other reason but to reduce code repetition for common resources that require defining lots of parameters. Here&amp;rsquo;s an example of setting up a Kubernetes cluster in Hetzner Cloud using Terraform with a &amp;ldquo;data-driven&amp;rdquo; approach:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Debugging Puppet Bolt inventory plugins</title>
				<link>https://www.puppeteers.net/blog/debugging-puppet-bolt-inventory-plugins/</link>
				<pubDate>Mon, 14 Mar 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/debugging-puppet-bolt-inventory-plugins/</guid>
				<description>&lt;p&gt;Puppet Bolt handles &lt;a href=&#34;https://puppet.com/docs/bolt/latest/inventory_files.html&#34;&gt;inventories&lt;/a&gt; in a very flexible and powerful manner: you can combine static target definitions and different targets into a single inventory. For example, you can have an inventory which defines some static node names combined with the &lt;a href=&#34;https://forge.puppet.com/modules/puppetlabs/aws_inventory&#34;&gt;AWS inventory&lt;/a&gt;, or one that combines static nodes with the &lt;a href=&#34;https://forge.puppet.com/modules/dylanratcliffe/bolt_vagrant/readme&#34;&gt;Vagrant inventory&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Puppet Bolt inventory plugins do their magic and then output what is essentially a static inventory generated dynamically. When dynamic inventory plugins do not work (as &lt;a href=&#34;https://github.com/dylanratcliffe/bolt_vagrant/pull/5&#34;&gt;in my case&lt;/a&gt;) it can be challenging to figure out what is wrong, let alone how to fix it. However, there&amp;rsquo;s is a very handy way to print out a static version of the entire inventory, including the dynamically created content:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Are Corporate Vision awards fake?</title>
				<link>https://www.puppeteers.net/blog/is-small-business-awards-a-scam/</link>
				<pubDate>Thu, 10 Feb 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/is-small-business-awards-a-scam/</guid>
				<description>&lt;p&gt;This was a burning question in my head in September 2021 but didn&amp;rsquo;t have much luck googling it. Here&amp;rsquo;s our experience and analysis of Small Business Awards by Corporate Vision. Read on to find out whether the awards handed out by Corporate Vision awards truly are a legit or not.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-did-we-hear-about-corporate-vision&#34;&gt;How did we hear about Corporate Vision?&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.corporatevision-news.com&#34;&gt;Corporate Vision&lt;/a&gt; contacted us in September 2021 announcing us that we were nominated as candidate for being the best company in the &amp;lsquo;IT Infrastructure Management Specialists - Finland&amp;rsquo; category for &lt;a href=&#34;https://www.corporatevision-news.com/awards/small-business-awards/&#34;&gt;Small Business Awards&lt;/a&gt;. At that time (before this blog post) there was very little information online about Small Business Awards or the company behind them. What I learned at that time was that they seemed to be a so-called &amp;lsquo;vanity award&amp;rsquo;, where winners have been preselected and everything else was just for show. We could not be absolutely sure about that then, and we thought that &amp;ldquo;winning&amp;rdquo; might have some marketing value, so we decided to play along and see where it leads us. I will first go through the process, then I&amp;rsquo;ll try to give an answer the question in the title.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Mautic spam prevention</title>
				<link>https://www.puppeteers.net/blog/mautic-spam-prevention/</link>
				<pubDate>Mon, 07 Feb 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/mautic-spam-prevention/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://www.mautic.org/&#34;&gt;Mautic&lt;/a&gt; is a widely used open source email marketing automation application written in PHP. Email marketing is typically used in conjunction with &lt;a href=&#34;https://www.hubspot.com/inbound-marketing&#34;&gt;inbound marketing&lt;/a&gt; done by asking people to give their email address in exchange for something, like a free ebook or a newsletter with good content. As you&amp;rsquo;re asking for the email address on a publicly facing webpage, spambots will find your form, and start misusing it to send your &amp;ldquo;Welcome&amp;rdquo; emails all over the place. This in turn may result in lots of bounces and/or complaints, which may get you locked out from your email service provider unless you pay attention. So, you need a way to block or fool those spam bots to prevent such issues, and to keep the Mautic database clean.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Conditional provisioner blocks in Terraform</title>
				<link>https://www.puppeteers.net/blog/conditional-provisioner-blocks-in-terraform/</link>
				<pubDate>Wed, 05 Jan 2022 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/conditional-provisioner-blocks-in-terraform/</guid>
				<description>&lt;p&gt;I&amp;rsquo;ll start with a spoiler: what the title suggests is not possible. It is, however, possible to accomplish this with cloud-init and Terraform templates as described in the &lt;a href=&#34;https://www.puppeteers.net/blog/multi-part-cloud-init-provisioning-with-terraform/&#34;&gt;Multi-part cloud-init provisioning with Terraform&lt;/a&gt; blog post.&lt;/p&gt;&#xA;&lt;p&gt;If you need to use SSH/WinRM provisioning, then there are various workarounds you can apply, and this article explains some of them and goes into depth into one in particular.&lt;/p&gt;&#xA;&lt;p&gt;The first workaround is relatively clean, but is not usable in all cases, especially when working with complex modules. The idea is to have two resources, here of type &lt;em&gt;aws_instance&lt;/em&gt;. Those resources are identical except for the provisioner blocks:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Dealing with multiple AWS accounts with one Keycloak client for Single-Sign On</title>
				<link>https://www.puppeteers.net/blog/dealing-with-multiple-aws-accounts-with-one-keycloak-client-for-single-sign-on/</link>
				<pubDate>Thu, 18 Nov 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/dealing-with-multiple-aws-accounts-with-one-keycloak-client-for-single-sign-on/</guid>
				<description>&lt;p&gt;This article assumes that the user backend for Keycloak is &lt;a href=&#34;https://www.freeipa.org/page/Main_Page&#34;&gt;FreeIPA&lt;/a&gt;. Regardless of that the instructions will apply to any other setup with minor modifications. Here we use two different AWS accounts renamed to 123412341234 and 567856785678 to protect the personal information of the innocent. The Keycloak staging cluster on which this integration was done is called &lt;em&gt;id-staging.example.org&lt;/em&gt; and the production cluster is called &lt;em&gt;id.example.org&lt;/em&gt;. The Keycloak realm is EXAMPLE.ORG. Replace those with the values correct for your environment.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Allowing external email forwarding in Office 365</title>
				<link>https://www.puppeteers.net/blog/allowing-external-email-forwarding-in-office-365/</link>
				<pubDate>Tue, 16 Nov 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/allowing-external-email-forwarding-in-office-365/</guid>
				<description>&lt;p&gt;We use Zimbra as our main email server. We also have Office 365 subscription to make working with our clients a bit easier. The challenge is that when customers send us, say, Teams meeting invites, they typically use autofill and the email gets sent to our Office 365 mailboxes which nobody really looks at.&lt;/p&gt;&#xA;&lt;p&gt;It is possible to fix this by configuring email forwarding. That is theoretically possible out of the box on a per-user basis in &lt;a href=&#34;https://outlook.office.com/mail/options/mail/forwarding&#34;&gt;https://outlook.office.com/mail/options/mail/forwarding&lt;/a&gt;. However, when you actually try it out you will get an error message in your Office 365 inbox because forwarding is disabled on the organizational level by default:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Enabling AWS EC2 instance automatic recovery with Terraform</title>
				<link>https://www.puppeteers.net/blog/enabling-aws-ec2-instance-automatic-recovery-with-terraform/</link>
				<pubDate>Thu, 28 Oct 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/enabling-aws-ec2-instance-automatic-recovery-with-terraform/</guid>
				<description>&lt;p&gt;AWS EC2 instances are subject to two types of status checks (&lt;a href=&#34;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-system-instance-status-check.html&#34;&gt;AWS docs&lt;/a&gt;):&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;System status check (issues with the underlying hardware/networking: &amp;ldquo;the AWS side&amp;rdquo;)&lt;/li&gt;&#xA;&lt;li&gt;Instance status check (issues with the OS, e.g. OOM, file system corruption, broken networking, etc: &amp;ldquo;our side&amp;rdquo;)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://aws.amazon.com/premiumsupport/knowledge-center/automatic-recovery-ec2-cloudwatch/&#34;&gt;official AWS EC2 instance recovery documentation&lt;/a&gt; claims that automatically recovering from an EC2 instance failure is only possible for system status checks, but the AWS documentation &lt;a href=&#34;https://www.percona.com/blog/2021/04/29/improving-percona-monitoring-and-management-ec2-instance-resilience-using-cloudwatch-alarm-actions/&#34;&gt;&lt;/a&gt;is outdated: Cloudwatch metrics are available for both types of check failures and people have set up &lt;a href=&#34;https://www.percona.com/blog/2021/04/29/improving-percona-monitoring-and-management-ec2-instance-resilience-using-cloudwatch-alarm-actions/&#34;&gt;&lt;/a&gt;recovery for both types of failures &lt;a href=&#34;https://www.percona.com/blog/2021/04/29/improving-percona-monitoring-and-management-ec2-instance-resilience-using-cloudwatch-alarm-actions/&#34;&gt;using AWS CLI&lt;/a&gt;.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Extending snmpd with custom scripts</title>
				<link>https://www.puppeteers.net/blog/extending-snmpd-with-custom-scripts/</link>
				<pubDate>Fri, 16 Jul 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/extending-snmpd-with-custom-scripts/</guid>
				<description>&lt;p&gt;Traditional network monitoring systems tend to get their monitoring data via SNMP. In case of Linux snmpd is usually the system application that&amp;rsquo;s responsible for providing that data. The data consists mostly, but not entirely, of metrics. For example, the data contains strings such as operating system version, administrative contacts and network interface names.&lt;/p&gt;&#xA;&lt;p&gt;It is possible to make snmpd run custom scripts and programs to gather more data from the system. The options are described in &lt;a href=&#34;http://www.net-snmp.org/docs/man/snmpd.conf.html&#34;&gt;snmpd.conf man page&lt;/a&gt;, but here are the most important ones for this use-case:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Packer QEMU: Building Ubuntu 20.04/22.04/24.04 VM images</title>
				<link>https://www.puppeteers.net/blog/building-ubuntu-20-04-qemu-images-with-packer/</link>
				<pubDate>Mon, 05 Jul 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/building-ubuntu-20-04-qemu-images-with-packer/</guid>
				<description>&lt;p&gt;&lt;img src=&#34;https://puppeteers-public.hel1.your-objectstorage.com/pexels-karolina-grabowska-44981361-683x1024.jpg&#34; alt=&#34;A person closing a large cardboard box with tape.&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://developer.hashicorp.com/packer/integrations/hashicorp/qemu/latest/components/builder/qemu&#34;&gt;Packer QEMU builder&lt;/a&gt; allows you to build virtual machine images from scratch. You need a &lt;em&gt;Packerfile&lt;/em&gt;, an &lt;em&gt;automatic installation configuration file&lt;/em&gt; (autoinstall, kickstart or preseed) and the &lt;em&gt;operating system installer&lt;/em&gt; (e.g. ISO). The benefit of Packer QEMU in particular are that you can have fine-grained control over the virtual machine image content such as disk partitioning. Moreover you don&amp;rsquo;t need to rely on official base images produced by other people, such as the official &lt;a href=&#34;https://cloud-images.ubuntu.com/&#34;&gt;Ubuntu Cloud images&lt;/a&gt;.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Making wpcal.io work with Zimbra calendars</title>
				<link>https://www.puppeteers.net/blog/making-wpcal-io-work-with-zimbra-calendars/</link>
				<pubDate>Thu, 01 Jul 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/making-wpcal-io-work-with-zimbra-calendars/</guid>
				<description>&lt;p&gt;Scheduling meetings with email is annoying. When everyone is on the same timezone that kind of works, but tends to be slow. When you factor in timezone differences the process becomes really error-prone and slows down even more, often to several days. For this reason we wanted to provide people - including our customers - a way to easily schedule meetings with us.&lt;/p&gt;&#xA;&lt;p&gt;We&amp;rsquo;re special in the sense that we self-host almost everything we use. For email and calendars we use &lt;a href=&#34;https://www.zimbra.com/&#34;&gt;Zimbra&lt;/a&gt; and for our website we use &lt;a href=&#34;https://wordpress.com/&#34;&gt;Wordpress&lt;/a&gt;. Most people seem to use &lt;a href=&#34;https://calendly.com/&#34;&gt;Calendly&lt;/a&gt; as a meeting scheduler, but we ended up choosing &lt;a href=&#34;https://wpcal.io/&#34;&gt;wpcal.io&lt;/a&gt; which is a native Wordpress plugin and seems to work quite nicely.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Testing Puppet feature environments with Puppet Bolt</title>
				<link>https://www.puppeteers.net/blog/testing-puppet-feature-environments-with-puppet-bolt/</link>
				<pubDate>Fri, 18 Jun 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/testing-puppet-feature-environments-with-puppet-bolt/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://www.puppeteers.net/blog/fattening-the-workflow-part-2-r10k/&#34;&gt;Puppet feature environments&lt;/a&gt; are an excellent way to test code before deploying it, typically to production. They allow testing Puppet runs on no-operation mode across the whole node population managed by Puppet. There are sometimes cases where your code changes potentially impact many nodes and you&amp;rsquo;re not exactly sure of their scope or effect. In that case it helps to test your code on all Puppet-managed nodes. The challenge is that Puppet open source does not have any built-in mechanism to do that. This is where we can make good use of Puppet Bolt.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Puppet types and providers development part 5: self.instances</title>
				<link>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-5-self-instances/</link>
				<pubDate>Sun, 30 May 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-5-self-instances/</guid>
				<description>&lt;p&gt;This blog post is a part of this blog post series:&lt;/p&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://www.rubydoc.info/gems/puppet/Puppet%2FProvider.instances&#34;&gt;self.instances&lt;/a&gt; is a provider class method that is used to produce an array containing all resources found from the system. For example, a yum package provider might run &amp;ldquo;rpm -qa&amp;rdquo; in self.instances to get a list of packages installed on the system. This serves two main purposes:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Allows using of &amp;ldquo;puppet resource type&amp;rdquo; to produce Puppet code for all resources of type found on the system.&lt;/li&gt;&#xA;&lt;li&gt;Data created by self.instances can be passed to &lt;a href=&#34;https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-6-mysteries-of-self-prefetch/&#34;&gt;self.prefetch&lt;/a&gt; to cache resource properties. The cached properties are then reused for every resource of that provider type. For example, a yum package provider might create a list of packages installed on a system when Puppet encounters the first &amp;ldquo;yum&amp;rdquo; package resource of &amp;ldquo;yum&amp;rdquo; type. That cache would then be reused, thus removing the need to individually check each package&amp;rsquo;s state.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;As discussed in &lt;a href=&#34;https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-4-caching-resource-properties-to-improve-performance/&#34;&gt;Puppet types and providers development part 4: caching resource properties to improve performance&lt;/a&gt; self.instances or self.prefetch are not really suitable for scenarios where you need to manage (multiple) remote systems using the same provider, because things like connection would be given in the Puppet resource definition are at the provider instance level, to which provider class level methods like self.instance and self.prefetch do not have access to.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Puppet types and providers development part 6: mysteries of self.prefetch</title>
				<link>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-6-mysteries-of-self-prefetch/</link>
				<pubDate>Sun, 30 May 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-6-mysteries-of-self-prefetch/</guid>
				<description>&lt;p&gt;This blog post is a part of this blog post series:&lt;/p&gt;&#xA;&lt;p&gt;I will open this blog post with a quote from the famous Gary Larizza:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;After wading the waters of &lt;code&gt;self.prefetch&lt;/code&gt;, I’m PRETTY SURE its implementation might have come to uncle Luke after a long night in Reed’s chem lab where he might have accidently synthesized mescaline.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;http://garylarizza.com/blog/2013/12/15/seriously-what-is-this-provider-doing/&#34;&gt;http://garylarizza.com/blog/2013/12/15/seriously-what-is-this-provider-doing/&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;After reading Gary&amp;rsquo;s rather elaborate explanation about self.prefetch I still did not fully get what self.prefetch &lt;em&gt;actually&lt;/em&gt; does and the official documentation surely does not help:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Limiting concurrent builds in Buildbot</title>
				<link>https://www.puppeteers.net/blog/limiting-concurrent-builds-in-buildbot/</link>
				<pubDate>Fri, 21 May 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/limiting-concurrent-builds-in-buildbot/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;http://buildbot.net/&#34;&gt;Buildbot&lt;/a&gt; is a continuous integration &lt;em&gt;framework&lt;/em&gt; which many open source projects seem to be using. Unlike continuous integration &lt;em&gt;applications&lt;/em&gt; or &lt;em&gt;automation servers&lt;/em&gt; like &lt;a href=&#34;https://www.jenkins.io/&#34;&gt;Jenkins&lt;/a&gt; Buildbot does not make many assumptions about your use-case. In fact, when you build your CI or CD pipeline you&amp;rsquo;re actually writing Python code and hence have all the flexibility of Python directly at your disposal. In other words, you&amp;rsquo;re not being blocked or obstructed by assumptions hidden in the tool itself, like often tends to happen with Jenkins.&lt;/p&gt;</description>
			</item>
			<item>
				<title>How to Setup a Staging Wordpress Server</title>
				<link>https://www.puppeteers.net/blog/how-to-staging-wordpress/</link>
				<pubDate>Tue, 18 May 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/how-to-staging-wordpress/</guid>
				<description>&lt;p&gt;Having a staging server for Wordpress is quite useful for testing new features without the worry of breaking something in production. It is also helpful when you have a multi user environment and need to test something that could impact others. In this article it is assumed that your Wordpress instance has SELinux enabled as is the case on RHEL/CentOS for example. On other distros like Ubuntu or Debian you can omit the steps specific to SELinux.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Dynamic partitioning in Foreman kickstart templates</title>
				<link>https://www.puppeteers.net/blog/dynamic-partitioning-in-foreman-kickstart-templates/</link>
				<pubDate>Wed, 12 May 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/dynamic-partitioning-in-foreman-kickstart-templates/</guid>
				<description>&lt;p&gt;Foreman&amp;rsquo;s &lt;a href=&#34;https://docs.theforeman.org/nightly/Provisioning_Guide/index-foreman-deb.html&#34;&gt;provisioning system&lt;/a&gt; allows creating provisioning templates with highly dynamic content. This article describes how to create dynamic content in your Foreman provisioning templates. While the example is related to dynamic partitioning in kickstart, the basic mechanisms for setting this up applies to any kind of template.&lt;/p&gt;&#xA;&lt;p&gt;Foreman &lt;a href=&#34;https://docs.theforeman.org/nightly/Provisioning_Guide/index-foreman-deb.html#provisioning-templates_provisioning&#34;&gt;provisioning templates&lt;/a&gt; are written in &lt;a href=&#34;https://www.stuartellis.name/articles/erb/&#34;&gt;ERB format&lt;/a&gt;. This allows having logic in the template itself based on user-defined host parameters. For example the &lt;a href=&#34;https://github.com/theforeman/foreman/blob/develop/app/views/unattended/provisioning_templates/provision/kickstart_default.erb&#34;&gt;Kickstart default template&lt;/a&gt; consumes a bunch of &lt;a href=&#34;https://docs.theforeman.org/nightly/Managing_Hosts/index-foreman-el.html&#34;&gt;host parameters&lt;/a&gt; that allow you to define what kind of kickstart file you want Foreman to spit out for each host or host group. To give a simple example there&amp;rsquo;s the &amp;ldquo;lang&amp;rdquo; parameter which sets the value for &amp;ldquo;lang&amp;rdquo; kickstart option:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Fixing foreman-installer &#34;Forward DNS points to x&#34; errors</title>
				<link>https://www.puppeteers.net/blog/fixing-foreman-installer-forward-dns-points-to-errors/</link>
				<pubDate>Wed, 03 Mar 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/fixing-foreman-installer-forward-dns-points-to-errors/</guid>
				<description>&lt;p&gt;This posting comes strictly from the land of esoteria. We have a &lt;a href=&#34;https://www.vagrantup.com/&#34;&gt;Vagrant&lt;/a&gt; + &lt;a href=&#34;https://www.virtualbox.org/&#34;&gt;Virtualbox&lt;/a&gt; environment that sets up &lt;a href=&#34;https://theforeman.org/&#34;&gt;Foreman&lt;/a&gt; used for &lt;a href=&#34;https://www.howtogeek.com/57601/what-is-network-booting-pxe-and-how-can-you-use-it/&#34;&gt;PXE booting&lt;/a&gt; baremetal servers. The environment work fine on Linux and MacOS. But we needed to make this environment work also on Windows. Easy, right? Vagrant and Virtualbox are supposed to abstract all those pesky operating system settings away, correct? After resolving a &lt;a href=&#34;https://www.puppeteers.net/blog/fixing-vagrant-vbguest-for-the-centos-7-base-box/&#34;&gt;non-Windows related challenge&lt;/a&gt; provisioning of Foreman on Windows almost worked. Except that it failed when foreman-installer attempted to start[*]. The error message was this:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Solving an Apache Mellon redirect loop mystery</title>
				<link>https://www.puppeteers.net/blog/solving-an-apache-mellon-redirect-loop-mystery/</link>
				<pubDate>Sat, 27 Feb 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/solving-an-apache-mellon-redirect-loop-mystery/</guid>
				<description>&lt;p&gt;If you’re at all like me, you every now and then find yourself thrown out of your comfort zone, when you should actually be in it.&lt;/p&gt;&#xA;&lt;p&gt;The pattern usually goes something like this:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;It’s something simple. I’ll fix it in a couple of minutes and document it for others. I know my stuff. &lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Hmm, this seems to be a bit stubborn. I need to take a closer look.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Still doesn’t work. I need to run this in a debugging set up and break it into pieces, to see where the problem is. &lt;/p&gt;</description>
			</item>
			<item>
				<title>Authenticate and authorize Grafana users from FreeIPA groups via Keycloak</title>
				<link>https://www.puppeteers.net/blog/authenticating-and-authorizing-users-from-freeipa-groups-via-keycloak/</link>
				<pubDate>Thu, 28 Jan 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/authenticating-and-authorizing-users-from-freeipa-groups-via-keycloak/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://grafana.com&#34;&gt;Grafana&lt;/a&gt; is a common tool to visualize data from multiple datasources. Perhaps the most common datasource is &lt;a href=&#34;https://prometheus.io/docs/introduction/overview/&#34;&gt;Prometheus&lt;/a&gt;. If an organization has a Single-Sign On solution, it makes sense to authenticate users centrally with that solution That will make authentication easier and friendlier for end users (authenticate once and then access multiple services), and also enable stronger authentication by adding &lt;a href=&#34;https://en.wikipedia.org/wiki/Multi-factor_authentication&#34;&gt;multifactor authentication&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In addition to authenticating user, it is also possible to authorize Grafana users based on their group membership. &lt;/p&gt;</description>
			</item>
			<item>
				<title>Making sense of JBOSS/Wildfly interfaces in domain mode</title>
				<link>https://www.puppeteers.net/blog/making-sense-of-jboss-wildfly-interfaces-in-domain-mode/</link>
				<pubDate>Thu, 28 Jan 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/making-sense-of-jboss-wildfly-interfaces-in-domain-mode/</guid>
				<description>&lt;p&gt;In this blog we consider &lt;a href=&#34;https://www.jboss.org/&#34;&gt;JBoss/Wildfly&lt;/a&gt; domain mode in the context of the wonderful &lt;a href=&#34;https://www.keycloak.org/&#34;&gt;Keycloak&lt;/a&gt; software. It is not necessarily trivial to understand how the interfaces  should be configured, especially if you want to do something other than the defaults, for example to secure your Wildfly/JBOSS configuration, or if you are dealing with a more complex nodes with multiple network interfaces. &lt;/p&gt;&#xA;&lt;p&gt;Assumptions:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We want to use Keycloak in domain mode. In this operating mode Keycloak application is clustered and also the caches, like user sessions are replicated in the cluster. &lt;/p&gt;</description>
			</item>
			<item>
				<title>High-level and low-level tasks in Kanban</title>
				<link>https://www.puppeteers.net/blog/high-level-and-low-level-tasks-in-kanban/</link>
				<pubDate>Sun, 17 Jan 2021 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/high-level-and-low-level-tasks-in-kanban/</guid>
				<description>&lt;p&gt;We use Kanban to coordinate our projects and tasks. Kanban is focused on visualizing and improving throughput, that is, making projects (high-level) and tasks (low-level) go through the system as fast as by limiting work in progress, which in turn minimizes waste (time and money).&lt;/p&gt;&#xA;&lt;p&gt;Our field of work is IT operations and we&amp;rsquo;re generally quite busy with fulfilling requests from our internal and external stakeholders. Most of our tasks are quite small, about 1-4 hours each, and produce value immediately. We can generally get these done (&amp;ldquo;through the system&amp;rdquo;) quickly without having to stop in the middle and can then forget about them. However, we also have bigger tasks that tend to take a lot longer, maybe 8-24 hours of focused work and often involve multiple persons.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Keycloak, Wildfly and Infinispan caches</title>
				<link>https://www.puppeteers.net/blog/keycloak-wildfly-and-infinispan-caches/</link>
				<pubDate>Wed, 16 Dec 2020 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/keycloak-wildfly-and-infinispan-caches/</guid>
				<description>&lt;p&gt;We recently hit an interesting issue with an &amp;ldquo;almost in production&amp;rdquo; Keycloak high-availability &lt;a href=&#34;https://www.keycloak.org/docs/latest/server_installation/index.html#_domain-mode&#34;&gt;clustered domain mode setup&lt;/a&gt; that was behind an Amazon EC2 load balancer with sticky sessions enabled. The symptom was that changes from the domain controller did not propagate to the slave. This included:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Changes made to realms and clients using the &lt;a href=&#34;https://www.keycloak.org/docs-api/11.0/rest-api/index.html&#34;&gt;Admin REST API&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;User sessions&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This lead us into a quest to truly understand how &lt;a href=&#34;https://infinispan.org/&#34;&gt;Infinispan&lt;/a&gt; caches in the &lt;a href=&#34;https://www.wildfly.org/&#34;&gt;Wildfly application server&lt;/a&gt; and consequently in &lt;a href=&#34;https://www.keycloak.org/&#34;&gt;Keycloak&lt;/a&gt; work. Before you read this article you should probably read all of these:&lt;/p&gt;</description>
			</item>
			<item>
				<title>Managing Keycloak configuration programmatically</title>
				<link>https://www.puppeteers.net/blog/managing-keycloak-configuration-programmatically/</link>
				<pubDate>Fri, 11 Dec 2020 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/managing-keycloak-configuration-programmatically/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://www.keycloak.org/&#34;&gt;Keycloak&lt;/a&gt; is an excellent Open Source Identity and Access Management solution that builds on top of the &lt;a href=&#34;https://www.wildfly.org/&#34;&gt;Wildfly application server&lt;/a&gt;. We manage several Keycloak installations for providing SSO with FreeIPA credentials for self-hosted and SaaS services via SAML and OIDC.&lt;/p&gt;&#xA;&lt;p&gt;To keep our Keycloak configurations healthy and in a known-good state we manage their configurations programmatically. As we use Puppet for our configuration management needs we&amp;rsquo;ve contributed a lot to the &lt;a href=&#34;https://github.com/treydock/puppet-module-keycloak/&#34;&gt;treydock/puppet-module-keycloak&lt;/a&gt; project. There is also a &lt;a href=&#34;https://github.com/mrparkers/terraform-provider-keycloak&#34;&gt;Terraform Keycloak provider&lt;/a&gt; that covers the Keycloak API very well, but it won&amp;rsquo;t help you one bit with setting up Keycloak initially. This can be problematic if you&amp;rsquo;re setting up something more complex like clustered domain mode with TLS reverse proxies.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Puppet types and providers development part 3: on resource uniqueness</title>
				<link>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-3-on-resource-uniqueness/</link>
				<pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-3-on-resource-uniqueness/</guid>
				<description>&lt;p&gt;This blog post is a part of this blog post series:&lt;/p&gt;&#xA;&lt;p&gt;In the previous blog post &lt;a href=&#34;https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-2-creating-a-resource/&#34;&gt;we talked about how to create a resource, a LibreNMS service, in the provider implementation&lt;/a&gt;. This blog post will talk about &lt;em&gt;identifying&lt;/em&gt; a resource that is being managed. This is a requirement for &lt;em&gt;modifying&lt;/em&gt; existing resources.&lt;/p&gt;&#xA;&lt;p&gt;Modifying existing resources can actually be more tricky than it seems, because you first need to figure out &lt;em&gt;if&lt;/em&gt; the resource Puppet is managing already exists on the target system. In many cases the resource type you&amp;rsquo;re managing has an attribute - for example &amp;ldquo;name&amp;rdquo;, &amp;ldquo;hostname&amp;rdquo;, &amp;ldquo;fqdn&amp;rdquo;, &amp;ldquo;ip&amp;rdquo; - that is guaranteed to be unique at the target system and works well as the identifier at the Puppet end. This is the case, for example with files (fully-qualified path), packages (name of the package) and in our particular case, LibreNMS devices (&lt;a href=&#34;https://github.com/Puppet-Finland/puppet-librenms/blob/master/lib/puppet/provider/librenms_device/api.rb&#34;&gt;hostname&lt;/a&gt;).&lt;/p&gt;</description>
			</item>
			<item>
				<title>Puppet types and providers development part 4: caching resource properties to improve performance</title>
				<link>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-4-caching-resource-properties-to-improve-performance/</link>
				<pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-4-caching-resource-properties-to-improve-performance/</guid>
				<description>&lt;p&gt;This blog post is a part of this blog post series:&lt;/p&gt;&#xA;&lt;p&gt;In the previous blog post we talked about &lt;a href=&#34;https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-3-on-resource-uniqueness/&#34;&gt;how to identify the resources that are being managed&lt;/a&gt;. This post will talk about the various ways of fetching the current state of the resources you wish to manage.&lt;/p&gt;&#xA;&lt;p&gt;Puppet manages a resource&amp;rsquo;s properties by checking their current state and if the current state differs from the state defined in the Puppet manifest (&amp;ldquo;desired state&amp;rdquo;) then Puppet will execute the commands necessary to fix the situation. So, when writing a Puppet provider you need to figure out a way to get the current state of all the resources of the &lt;em&gt;type&lt;/em&gt; (e.g. file, package, LibreNMS service) you&amp;rsquo;re managing as efficiently as possible.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Integrating Puppet Bolt with PuppetDB</title>
				<link>https://www.puppeteers.net/blog/integrating-puppet-bolt-with-puppetdb/</link>
				<pubDate>Fri, 24 Apr 2020 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/integrating-puppet-bolt-with-puppetdb/</guid>
				<description>&lt;p&gt;In the &lt;a href=&#34;https://www.puppeteers.net/blog/integrating-puppet-bolt-with-puppetdb/&#34;&gt;Puppet Bolt with a Puppet control repository&lt;/a&gt; blog post we showed how to integrate Puppet Bolt with an existing control repository. We used a static inventory file, which is ok for testing or when you have a few target nodes. However, if you have a Puppetserver running and are not using Bolt to manage the &lt;em&gt;configurations&lt;/em&gt; of your nodes, then the chances are that you have a fairly large node population and maintaining a static inventory would be both tedious and error-prone. One option &lt;a href=&#34;https://puppet.com/docs/bolt/latest/using_plugins.html&#34;&gt;among many&lt;/a&gt; is to use the PuppetDB plugin to generate a dynamic inventory and that is what we describe here.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Puppet types and providers development part 2: creating a resource</title>
				<link>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-2-creating-a-resource/</link>
				<pubDate>Sat, 07 Mar 2020 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-2-creating-a-resource/</guid>
				<description>&lt;p&gt;This blog post is a part of this blog post series:&lt;/p&gt;&#xA;&lt;p&gt;In the &lt;a href=&#34;https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-1-creating-the-type/&#34;&gt;previous blog post&lt;/a&gt; we created the Puppet type &lt;em&gt;librenms_service&lt;/em&gt; and created a dummy skeleton for the provider implementation. We were able to use the type, but it did not yet do anything. In this blog post we move to implementing the &lt;em&gt;create&lt;/em&gt; method, which in this case was the low-hanging fruit. At this point we do not need to worry about any existence checks (the &lt;em&gt;exists?&lt;/em&gt; method) or trying to minimizing the number of API calls with self.prefetch or something similar.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Puppet types and providers development part 1: creating the type</title>
				<link>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-1-creating-the-type/</link>
				<pubDate>Tue, 03 Mar 2020 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/puppet-types-and-providers-development-part-1-creating-the-type/</guid>
				<description>&lt;p&gt;This article is a part of this blog post series:&lt;/p&gt;&#xA;&lt;p&gt;Writing Puppet types and providers looks like black magic even to those who have lots of experience in the Puppet language itself. While the official &lt;a href=&#34;https://puppet.com/docs/puppet/latest/custom_types.html&#34;&gt;types development documentation&lt;/a&gt; is quite ok, &lt;a href=&#34;https://puppet.com/docs/puppet/latest/provider_development.html&#34;&gt;provider documentation&lt;/a&gt; is definitely lacking. Not only are there no practical examples from real life, the important features such as prefetching, resource methods and flushing are described only on a very high level. The usual answer to lack of examples is &amp;ldquo;have a look at the built-in resources&amp;rdquo;. But when you look at any built-in resource, you realize that the code is very complex because&lt;/p&gt;</description>
			</item>
			<item>
				<title>Pidgin IRC with ZNC and Freenode SASL external auth</title>
				<link>https://www.puppeteers.net/blog/pidgin-irc-with-znc-and-freenode-sasl-external-auth/</link>
				<pubDate>Thu, 12 Dec 2019 00:00:00 +0000</pubDate>
				<guid>https://www.puppeteers.net/blog/pidgin-irc-with-znc-and-freenode-sasl-external-auth/</guid>
				<description>&lt;p&gt;I use &lt;a href=&#34;https://pidgin.im/&#34;&gt;Pidgin&lt;/a&gt; as my instant messaging client because it is open source and because it supports almost all IM protocols directly or through plugins. In my case I need support for IRC, XMPP, Facebook, Slack and SIPE (Office 365). &lt;a href=&#34;https://github.com/hoehermann/libpurple-signald&#34;&gt;Apparently&lt;/a&gt; it would be possible to use Pidgin for Signal as well, but as official Signal client is open source and works quite well I&amp;rsquo;m fine with running it standalone. As I use Linux, I can rarely hope for a native client for the proprietary IM services. Plus even if there was one, I would not want to run 4-5 messaging applications when I can have one (or two). Or to have the same amount of IM web applications open just to get messages.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
