<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Vectops</title>
        <link>https://vectops.com/</link>
        <description>Recent content on Vectops</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Sat, 08 Mar 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://vectops.com/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Mikrotik: Save your config via FTP</title>
        <link>https://vectops.com/post/2025/mikrotik-backup-your-cfg/</link>
        <pubDate>Sat, 08 Mar 2025 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2025/mikrotik-backup-your-cfg/</guid>
        <description>&lt;img src="https://vectops.com/post/2025/mikrotik-backup-your-cfg/image.jpg" alt="Featured image of post Mikrotik: Save your config via FTP" /&gt;&lt;p&gt;Do you have a MikroTik? Have you ever made changes to the configuration and then, after a while, when you reset the configuration, it didn&amp;rsquo;t work as you expected?&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t worry, if you have an FTP server at home, we can solve this quickly and easily.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to tell you a very simple way (really, a very simple way) to make FTP backups of your MikroTik and keep your configurations safe.&lt;/p&gt;
&lt;p&gt;Download the script from our repository: &lt;a class=&#34;link&#34; href=&#34;https://raw.githubusercontent.com/vectops/scripts/refs/heads/master/mikrotik/ftp/ftp.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ftp_backup&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;configure-the-script&#34;&gt;Configure the script&lt;/h2&gt;
&lt;p&gt;Create the script in &lt;code&gt;System -&amp;gt; Scripts&lt;/code&gt; menu, click on &lt;code&gt;Add new&lt;/code&gt;, and fill in the form fields as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- Name: ftp_backup
- Policy: read, write, test
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the script, variables are defined through the &lt;code&gt;:local&lt;/code&gt; refs where you need to put the information:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;:local FTPserver &amp;#34;x.x.x.x&amp;#34;
:local FTPuser &amp;#34;username&amp;#34;
:local FTPpassword &amp;#34;password&amp;#34;
:local FTPdestFile &amp;#34;remote_directory&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Just fill the spaces between double commas for each variable with the values you got in the previous step.&lt;/p&gt;
&lt;p&gt;Now, you can test the script by applying and clicking on &lt;code&gt;Run Script&lt;/code&gt;, or via cli:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/system scripts run ftp_backup
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;scheduling-the-script&#34;&gt;Scheduling the script&lt;/h2&gt;
&lt;p&gt;Now here&amp;rsquo;s the thing. We got everything set up, verified that runs as intended, and everything is ready. But at this point, if you don&amp;rsquo;t click on the &amp;ldquo;Run script&amp;rdquo; button, the script won&amp;rsquo;t trigger itself. Hopefully that is quite simple to fix: just configure a &lt;code&gt;Scheduler&lt;/code&gt; to run this script on a given time basis (say 1d).&lt;/p&gt;
&lt;p&gt;To achive this, from your Mikrotik&amp;rsquo;s web UI, go to &lt;code&gt;System -&amp;gt; Scheduler&lt;/code&gt; menu, and click on &lt;code&gt;Add new&lt;/code&gt;, then just fill each field with the next details:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- Name: ftp_backup
- Interval: 1d
- Start time: 23:00:00
- Policy: read, write, test
- On event: /system script run ftp_backup
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you prefer setting this up through the cli, this is done just by running the following command:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/system scheduler
add interval=1d name=ftp_backup on-event=&amp;#34;/system script run ftp_backup&amp;#34; policy=read,write,test start-time=23:00:00
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Remember that you can change the &lt;code&gt;interval&lt;/code&gt; accordingly to fit your own needs.&lt;/p&gt;
&lt;p&gt;With that, we  can say we&amp;rsquo;re done! You have configured the FTP backup on your Mikrotik, and now you can break anything in your config, you have a backup!&lt;/p&gt;
&lt;p&gt;See you next time, don&amp;rsquo;t forget to &lt;strong&gt;share&lt;/strong&gt; &amp;amp; leave a comment!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Flysky (iBUS) interfacing to an arduino</title>
        <link>https://vectops.com/post/2025/flysky-arduino-interfacing/</link>
        <pubDate>Thu, 27 Feb 2025 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2025/flysky-arduino-interfacing/</guid>
        <description>&lt;img src="https://vectops.com/post/2025/flysky-arduino-interfacing/image.jpg" alt="Featured image of post Flysky (iBUS) interfacing to an arduino" /&gt;&lt;p&gt;Recently I had a need to control an arduino with an RC Controller, this was a proof of concept project that took 2 or maybe 3 tries to get working but from what I&amp;rsquo;ve seen online there&amp;rsquo;s not that much documentation for projects like this.&lt;/p&gt;
&lt;p&gt;This is a very sparse and simple explanation for the process but hey, it should work.&lt;/p&gt;
&lt;p&gt;This project, as well as other electronics projects I do use PlatformIO on VSCode because the Arduino IDE and I don&amp;rsquo;t get along. Even the newer 2.0 one.&lt;/p&gt;
&lt;h3 id=&#34;required-parts&#34;&gt;Required parts&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Flysky FS-A8S:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://s.click.aliexpress.com/e/_onz1w2M&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Flysky FS-A8S - Aliexpress Affiliate Link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://amzn.to/43dgvjo&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Flysky FS-A8S - Amazon Affiliate Link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Breadboard:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://s.click.aliexpress.com/e/_omzwaog&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Breadboard - Aliexpress Affiliate Link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://amzn.to/4hXcvIp&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Breadboard - Amazon Affiliate Link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Flysky FS-i6 RC Controller:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://s.click.aliexpress.com/e/_oFAkTle&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Flysky FS-i6 RC Controller - Aliexpress Affiliate Link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://amzn.to/43e7s1C&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Flysky FS-i6 RC Controller - Amazon Affiliate Link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Arduino PRO Micro:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://s.click.aliexpress.com/e/_okOy92u&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Arduino PRO Micro - Aliexpress Affiliate Link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://amzn.to/4km3KJJ&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Arduino PRO Micro - Amazon Affiliate Link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;wiring&#34;&gt;Wiring&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s only 3 wires to take into account here:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Arduino Pro Micro PIN&lt;/th&gt;
&lt;th&gt;FS-A8S PIN&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RX1(D0)&lt;/td&gt;
&lt;td&gt;IBus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ground&lt;/td&gt;
&lt;td&gt;Ground&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5v(VCC)&lt;/td&gt;
&lt;td&gt;Vin&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;setting-up-the-arduino-pro-micro&#34;&gt;Setting up the Arduino Pro Micro&lt;/h2&gt;
&lt;p&gt;The Pro Micro&amp;rsquo;s setup is pretty straight forward, since we&amp;rsquo;re using a FlySky RC Controller for this setup why not use it&amp;rsquo;s iBUS protocol wich is widely documented and easy to implement on the arduino since it already has a library. You can find the library &lt;a class=&#34;link&#34; href=&#34;https://registry.platformio.org/libraries/bmellink/IBusBM&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt; along with it&amp;rsquo;s documentation.&lt;/p&gt;
&lt;p&gt;Platformio need to have a &lt;code&gt;platformio.ini&lt;/code&gt; file, this is created automagically when you create the project using platformio&amp;rsquo;s interface -&amp;gt; next, next, next, confirm, wait, profit.&lt;/p&gt;
&lt;p&gt;Once it&amp;rsquo;s created you can set up libraries and other stuff on it, since this is a basic proof of concept we&amp;rsquo;re only importing the iBusBM library:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[env:sparkfun_promicro16]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;platform&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;atmelavr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;board&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;sparkfun_promicro16&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;framework&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;arduino&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;lib_deps&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;bmellink/IBusBM @ ~1.1.4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As for the &lt;code&gt;main.cpp&lt;/code&gt; arduino code (it&amp;rsquo;s heavily commented for your pleasure):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Include iBusBM Library
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;IBusBM.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Create iBus Object
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;IBusBM ibus;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Read the number of a given channel and convert to the range provided.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// If the channel is off, return the default value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;readChannel&lt;/span&gt;(byte channelInput, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; minLimit, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; maxLimit, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; defaultValue) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; ch &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ibus.&lt;span style=&#34;color:#a6e22e&#34;&gt;readChannel&lt;/span&gt;(channelInput);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (ch &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; defaultValue;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;map&lt;/span&gt;(ch, &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2000&lt;/span&gt;, minLimit, maxLimit);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Read the channel and return a boolean value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;readSwitch&lt;/span&gt;(byte channelInput, &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; defaultValue) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; intDefaultValue &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (defaultValue) &lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; ch &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;readChannel&lt;/span&gt;(channelInput, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, intDefaultValue);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; (ch &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;50&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setup&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Start serial monitor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;begin&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;115200&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Attach iBus object to serial port
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  ibus.&lt;span style=&#34;color:#a6e22e&#34;&gt;begin&lt;/span&gt;(Serial1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;loop&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Cycle through first 5 channels and determine values
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Print values to serial monitor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Note IBusBM library labels channels starting with &amp;#34;0&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (byte i &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;; i&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;readChannel&lt;/span&gt;(i, &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Ch&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(i &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;: &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(value);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; | &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Print channel 6 (switch) boolean value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Ch6: &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;readSwitch&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;, false));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Serial.&lt;span style=&#34;color:#a6e22e&#34;&gt;println&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;delay&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then just build it and upload it onto the Pro Micro&lt;/p&gt;
&lt;h2 id=&#34;setting-up-the-rc-controller&#34;&gt;Setting up the RC Controller&lt;/h2&gt;
&lt;p&gt;Just bind it, same procedure as 10 years ago.&lt;/p&gt;
&lt;h2 id=&#34;additional-considerations&#34;&gt;Additional Considerations&lt;/h2&gt;
&lt;p&gt;This &amp;ldquo;sketch&amp;rdquo; outputs the values incomming from 6 channels, if you have another RC Controller that has more channels just change the loop that goes through every channel.&lt;/p&gt;
&lt;p&gt;Once you have those values you can parse them into variables of your own definition. Take this as a starting point. Baby steps!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>2025 blog update: Late new year&#39;s resolution</title>
        <link>https://vectops.com/post/2025/2025-blog-update-new-years-resolution/</link>
        <pubDate>Wed, 26 Feb 2025 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2025/2025-blog-update-new-years-resolution/</guid>
        <description>&lt;img src="https://vectops.com/post/2025/2025-blog-update-new-years-resolution/image.jpg" alt="Featured image of post 2025 blog update: Late new year&#39;s resolution" /&gt;&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve been busy with real work, family, family work, working families, robotics? family robots! and so on but we haven&amp;rsquo;t forgotten about this blog/site.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve decided to take a quick turn so the site gets atleast some updates. (Beleive it or not, there&amp;rsquo;s people that actually follow this besides the 3 of us&amp;hellip;.. I know right?)&lt;/p&gt;
&lt;p&gt;Since this site was originally meant for &lt;em&gt;very&lt;/em&gt; specific problems that arose whenever we had an issue at work or testing something out on our homelab setups, it hinders what we can post without &amp;ldquo;contaminating&amp;rdquo; everything else that has been posted but&amp;hellip; as you can probably tell, we don&amp;rsquo;t maintain this site for profit, just for shits and/or giggles. No responsibilities to any higher power other than the people who read this, the half a dozen of you who do.&lt;/p&gt;
&lt;p&gt;This means that we can basically do whatever the hell we want with it, not that anyone&amp;rsquo;s complaining (try it, I double dare you).&lt;/p&gt;
&lt;p&gt;So, from my part, I have several ongoing projects that involve electronics, &lt;em&gt;robotics&lt;/em&gt;, and several other weird things that interest a lot of people online (atleast 2). I&amp;rsquo;ll try to provide updates on them, start to&amp;hellip;. maybe finish.&lt;/p&gt;
&lt;p&gt;From my counterparts on Vectops, I&amp;rsquo;m pretty sure that if I start posting regularly they will be inspired to do so too(hopefully).&lt;/p&gt;
&lt;p&gt;I guess i&amp;rsquo;ll see you around. I just have to get started, how hard can it be? baby steps!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>2024 blog update: farewell WordPress, hello Hugo</title>
        <link>https://vectops.com/post/2023/2024-blog-update-farewell-wordpress-hello-hugo/</link>
        <pubDate>Sun, 24 Dec 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/2024-blog-update-farewell-wordpress-hello-hugo/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/2024-blog-update-farewell-wordpress-hello-hugo/image.png" alt="Featured image of post 2024 blog update: farewell WordPress, hello Hugo" /&gt;&lt;p&gt;Hello there!&lt;/p&gt;
&lt;p&gt;Just a heads up from Vectops. It&amp;rsquo;s been a while since our last post here, but we&amp;rsquo;re far from done with the blog! What a busy year has 2023 been for everybody, huh?&lt;/p&gt;
&lt;p&gt;Anyway, we&amp;rsquo;re pleased to announce that our scope for the project towards the upcoming year is to continue bringing interesting and helpful approaches to common issues that anyone in the IT world can face.&lt;/p&gt;
&lt;p&gt;For now, the big news is that we have recently switched from the good ol&amp;rsquo; WordPress engine to Hugo so the whole site is now managed as code, something we as authors are already thankful for. Hopefully this change will bring more stability, better performance and even help reducing the attack surface of our platform, something essential for us as webmasters. All without sacrificing useful features for you as readers, such as the &amp;ldquo;search&amp;rdquo; bar or the archive.&lt;/p&gt;
&lt;p&gt;The only thing we still have to re-think is the comment system, since it is the main way you as user got to interact with us and our content. It&amp;rsquo;s a pity that all the old comments had to be left inside WordPress, since there was some valuable insights from you as well over there, but don&amp;rsquo;t worry, we&amp;rsquo;ll eventually come up with a solution for this.&lt;/p&gt;
&lt;p&gt;Wish you all the best, and let&amp;rsquo;s keep rolling in this next year.&lt;/p&gt;
&lt;p&gt;The Vectops team&lt;/p&gt;
</description>
        </item>
        <item>
        <title>DevSecOps: Integrating Security in DevOps - A Comprehensive Guide</title>
        <link>https://vectops.com/post/2023/devsecops-integrating-security-in-devops-a-comprehensive-guide/</link>
        <pubDate>Mon, 08 May 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/devsecops-integrating-security-in-devops-a-comprehensive-guide/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/devsecops-integrating-security-in-devops-a-comprehensive-guide/image.png" alt="Featured image of post DevSecOps: Integrating Security in DevOps - A Comprehensive Guide" /&gt;&lt;p&gt;In the modern software development landscape, security is more important than ever. DevSecOps, the practice of integrating security into the DevOps process, aims to ensure that applications are developed and deployed with security in mind from the very beginning.&lt;/p&gt;
&lt;p&gt;In this comprehensive guide, we&amp;rsquo;ll explore the fundamentals of DevSecOps, explain how to integrate security into your DevOps workflow, and provide examples to help you get started.&lt;/p&gt;
&lt;h2 id=&#34;outline&#34;&gt;Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Understanding DevSecOps
  a. What is DevSecOps?
  b. DevSecOps principles
  c. Benefits of DevSecOps

Integrating Security in the DevOps Pipeline
  a. Shift-Left Security
  b. Continuous Security Testing
  c. Security as Code
  d. Automated Security Monitoring

DevSecOps Tools and Practices
  a. Static Application Security Testing (SAST)
  b. Dynamic Application Security Testing (DAST)
  c. Container Security
  d. Infrastructure as Code (IaC) Security
  e. Secrets Management

Building a DevSecOps Culture
  a. Collaboration and Communication
  b. Security Awareness and Training
  c. Continuous Improvement

DevSecOps Examples
  a. Integrating SAST into the CI/CD pipeline
  b. Implementing container security scanning
  c. Secure IaC practices
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;understanding-devsecops&#34;&gt;Understanding DevSecOps&lt;/h2&gt;
&lt;h3 id=&#34;what-is-devsecops&#34;&gt;What is DevSecOps?&lt;/h3&gt;
&lt;p&gt;DevSecOps is the practice of integrating security into the DevOps process. It aims to address security concerns throughout the entire software development lifecycle, from planning to deployment. DevSecOps promotes a proactive approach to security, ensuring that security is built into applications from the very beginning, rather than being added as an afterthought.&lt;/p&gt;
&lt;h4 id=&#34;devsecops-principles&#34;&gt;DevSecOps Principles&lt;/h4&gt;
&lt;p&gt;The core principles of DevSecOps include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Collaboration:&lt;/strong&gt; Encourage communication and collaboration between development, security, and operations teams.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Automate security processes and tools within the DevOps pipeline to improve efficiency and reduce human error.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shift-Left Security:&lt;/strong&gt; Integrate security early in the development process to identify and address vulnerabilities sooner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Continuous Improvement:&lt;/strong&gt; Continuously evaluate and improve security practices and tools based on feedback and lessons learned.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;benefits-of-devsecops&#34;&gt;Benefits of DevSecOps&lt;/h4&gt;
&lt;p&gt;Implementing DevSecOps offers several advantages, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Faster remediation:&lt;/strong&gt; By addressing security issues early in the development process, vulnerabilities can be fixed more quickly and efficiently.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced risk:&lt;/strong&gt; Integrating security into the DevOps pipeline reduces the risk of security breaches and data loss.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved collaboration:&lt;/strong&gt; DevSecOps fosters better communication and collaboration between development, security, and operations teams, leading to more secure and reliable applications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost savings:&lt;/strong&gt; By detecting and fixing security issues early, organizations can avoid the high costs associated with security breaches and remediation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;integrating-security-in-the-devops-pipeline&#34;&gt;Integrating Security in the DevOps Pipeline&lt;/h3&gt;
&lt;p&gt;To integrate security into your DevOps pipeline, consider adopting the following practices:&lt;/p&gt;
&lt;h4 id=&#34;shift-left-security&#34;&gt;Shift-Left Security&lt;/h4&gt;
&lt;p&gt;&amp;ldquo;Shift-Left&amp;rdquo; security means incorporating security practices early in the development process. This can include activities such as threat modeling, secure coding practices, and code reviews focused on security.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: During the design phase, conduct threat modeling sessions with your team to identify potential risks and vulnerabilities in your application. Address these risks by implementing secure coding practices and validating the security of your code through regular code reviews.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;continuous-security-testing&#34;&gt;Continuous Security Testing&lt;/h4&gt;
&lt;p&gt;Continuously test your application for security vulnerabilities throughout the development process. This can involve static application security testing (SAST), dynamic application security testing (DAST), and interactive application security testing (IAST).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: Integrate a SAST tool, such as SonarQube or Checkmarx, into your CI/CD pipeline to automatically analyze your code for security vulnerabilities during the build process.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;security-as-code&#34;&gt;Security as Code&lt;/h4&gt;
&lt;p&gt;Define and manage security policies, configurations, and controls as code. This approach allows you to version control security settings, automate security policy enforcement, and improve the auditability of security configurations.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: Use a tool like HashiCorp Sentinel or Open Policy Agent to enforce security policies programmatically across your infrastructure.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;automated-security-monitoring&#34;&gt;Automated Security Monitoring&lt;/h4&gt;
&lt;p&gt;Automate the monitoring and analysis of your application and infrastructure for security events and anomalies. This can include tools for log analysis, intrusion detection, and security information and event management (SIEM).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: Configure a SIEM tool, such as Splunk or Elasticsearch, to collect and analyze security-related logs from your application and infrastructure. Set up alerts to notify your team of potential security incidents.
DevSecOps Tools and Practices&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;static-application-security-testing-sast&#34;&gt;Static Application Security Testing (SAST)&lt;/h4&gt;
&lt;p&gt;SAST tools analyze your source code for potential security vulnerabilities without executing the code. Popular SAST tools include SonarQube, Checkmarx, and Fortify.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: Integrate SonarQube into your CI/CD pipeline to automatically analyze your code for security vulnerabilities during the build process.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;dynamic-application-security-testing-dast&#34;&gt;Dynamic Application Security Testing (DAST)&lt;/h4&gt;
&lt;p&gt;DAST tools analyze your running application for security vulnerabilities by simulating attacks and identifying potential issues. Popular DAST tools include OWASP ZAP, Burp Suite, and Acunetix.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: Integrate OWASP ZAP into your CI/CD pipeline to automatically perform dynamic security testing on your application during the staging or pre-production phase.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;interactive-application-security-testing-iast&#34;&gt;Interactive Application Security Testing (IAST)&lt;/h4&gt;
&lt;p&gt;IAST tools combine elements of SAST and DAST by analyzing application behavior during runtime to identify security vulnerabilities. Popular IAST tools include Contrast Security, HCL AppScan, and Micro Focus Fortify.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: Incorporate Contrast Security into your application to continuously monitor its behavior during development and testing, identifying and alerting on potential security issues in real-time.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;container-security&#34;&gt;Container Security&lt;/h4&gt;
&lt;p&gt;As containerization becomes more prevalent, it&amp;rsquo;s essential to ensure the security of your containers and container orchestration platforms. Container security tools help you scan container images for vulnerabilities, enforce security policies, and monitor runtime behavior. Popular container security tools include Aqua Security, Sysdig Secure, and Anchore.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: Integrate Aqua Security into your CI/CD pipeline to scan container images for vulnerabilities, enforce security policies, and monitor container runtime behavior.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;infrastructure-as-code-iac-security&#34;&gt;Infrastructure as Code (IaC) Security&lt;/h4&gt;
&lt;p&gt;With the increasing adoption of IaC, it&amp;rsquo;s crucial to ensure the security of your infrastructure code. IaC security tools help you analyze your infrastructure code for misconfigurations, compliance violations, and potential security risks. Popular IaC security tools include Checkov, Terrascan, and Bridgecrew.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example: Integrate Checkov into your CI/CD pipeline to scan your Terraform or CloudFormation code for security vulnerabilities and compliance issues before deploying infrastructure changes.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By adopting DevSecOps practices and integrating security into your DevOps pipeline, you can create a more secure, efficient, and collaborative development environment. This proactive approach to security will help you reduce risk, improve application reliability, and ultimately protect your organization from potential security breaches.&lt;/p&gt;
&lt;h4 id=&#34;building-a-devsecops-culture&#34;&gt;Building a DevSecOps Culture&lt;/h4&gt;
&lt;p&gt;To successfully implement DevSecOps, it&amp;rsquo;s essential to foster a culture of shared responsibility for security across your organization. Here are some tips for building a DevSecOps culture:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Encourage collaboration: Break down silos between development, operations, and security teams by encouraging open communication, collaboration, and shared goals. Regularly hold cross-functional meetings, workshops, and training sessions to enhance understanding and cooperation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Provide training and resources:&lt;/strong&gt; Equip your team members with the necessary knowledge and skills to handle security concerns effectively. Offer training, resources, and tools that help them understand security best practices, threat modeling, and secure coding techniques.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;**Shift security left:**Integrate security early in the development process by incorporating security requirements into the planning and design phases. This proactive approach will help you identify and address security issues before they become more challenging and costly to fix later in the development lifecycle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Automate security testing:&lt;/strong&gt; Use automated security testing tools to streamline the security validation process and ensure that security checks are consistently applied throughout the development pipeline.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Measure and improve:&lt;/strong&gt; Continuously monitor and measure your DevSecOps efforts by tracking key performance indicators (KPIs), such as vulnerability detection rates, mean time to remediation, and deployment frequency. Use these metrics to identify areas for improvement and refine your DevSecOps practices over time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By promoting a DevSecOps culture within your organization, you&amp;rsquo;ll create an environment where security becomes an integral part of the development process, and everyone shares the responsibility for protecting your applications and infrastructure.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;DevSecOps represents a significant shift in how organizations approach application and infrastructure security, emphasizing the need to integrate security throughout the entire development lifecycle. By adopting DevSecOps principles and practices, you can enhance collaboration, streamline security validation, and ultimately build more secure, resilient applications that protect your organization from potential security threats.&lt;/p&gt;
&lt;p&gt;As you continue to explore DevSecOps, remember to foster a culture of shared responsibility for security, invest in training and resources, and leverage automation to improve the efficiency and effectiveness of your security efforts. With a solid foundation in DevSecOps, your organization will be well-positioned to tackle the ever-evolving security challenges of the modern software development landscape.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Mastering Git: Branching, Merging &amp; Conflicts - A Comprehensive Guide</title>
        <link>https://vectops.com/post/2023/mastering-git-branching-merging-conflicts-a-comprehensive-guide/</link>
        <pubDate>Wed, 03 May 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/mastering-git-branching-merging-conflicts-a-comprehensive-guide/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/mastering-git-branching-merging-conflicts-a-comprehensive-guide/image.png" alt="Featured image of post Mastering Git: Branching, Merging &amp; Conflicts - A Comprehensive Guide" /&gt;&lt;p&gt;Welcome to our in-depth guide on mastering Git, focusing on branching, merging, and handling conflicts. Git is a powerful version control system widely used by developers and teams to manage their codebases efficiently.&lt;/p&gt;
&lt;p&gt;Understanding how to work with branches, merge changes, and resolve conflicts is essential for seamless collaboration and effective software development.&lt;/p&gt;
&lt;h2 id=&#34;outline&#34;&gt;Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;1. Introduction to Git Branching
2. Creating and Switching Branches
3. Merging Branches
4. Handling Merge Conflicts
5. Advanced Branching Techniques
6. Git Best Practices
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;1-introduction-to-git-branching&#34;&gt;1. Introduction to Git Branching&lt;/h2&gt;
&lt;p&gt;Branching in Git allows you to create parallel lines of development, isolating features, bug fixes, or experiments from the main codebase. The default branch in a Git repository is called the &amp;ldquo;master&amp;rdquo; branch or, more recently, the &amp;ldquo;main&amp;rdquo; branch.&lt;/p&gt;
&lt;h4 id=&#34;benefits-of-git-branching&#34;&gt;Benefits of Git Branching:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Isolation of work:&lt;/strong&gt; Developers can work independently on different features or fixes without affecting the main codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easier collaboration:&lt;/strong&gt; Team members can share branches to collaborate on specific tasks or review code before merging it into the main branch.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible release management:&lt;/strong&gt; Teams can maintain separate branches for different release versions, making it easier to manage releases and apply hotfixes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;2-creating-and-switching-branches&#34;&gt;2. Creating and Switching Branches&lt;/h2&gt;
&lt;h2 id=&#34;creating-a-new-branch&#34;&gt;Creating a new branch:&lt;/h2&gt;
&lt;p&gt;To create a new branch and switch to it, use the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout -b feature-xyz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command creates a new branch called feature-xyz and switches to it.&lt;/p&gt;
&lt;h2 id=&#34;switching-between-branches&#34;&gt;Switching between branches:&lt;/h2&gt;
&lt;p&gt;To switch to an existing branch:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout branch-name
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Replace branch-name with the name of the branch you want to switch to.&lt;/p&gt;
&lt;h2 id=&#34;3-merging-branches&#34;&gt;3. Merging Branches&lt;/h2&gt;
&lt;p&gt;To merge changes from one branch into another, follow these steps:&lt;/p&gt;
&lt;p&gt;a. Switch to the target branch (usually the main branch):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;b. Merge the source branch into the target branch:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git merge feature-xyz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command merges the feature-xyz branch into the main branch.&lt;/p&gt;
&lt;h2 id=&#34;4-handling-merge-conflicts&#34;&gt;4. Handling Merge Conflicts&lt;/h2&gt;
&lt;p&gt;Merge conflicts occur when changes in different branches conflict with each other. Git will automatically merge changes whenever possible, but sometimes manual intervention is required.&lt;/p&gt;
&lt;h4 id=&#34;resolving-merge-conflicts&#34;&gt;Resolving merge conflicts:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Identify conflicting files by looking for the CONFLICT message in the Git output.&lt;/li&gt;
&lt;li&gt;Open the conflicting files and look for conflict markers (&amp;laquo;&amp;laquo;&amp;laquo;&amp;lt;, =======, and &amp;raquo;&amp;raquo;&amp;raquo;&amp;gt;), which indicate the conflicting changes.&lt;/li&gt;
&lt;li&gt;Review the changes and decide which version to keep, or modify the file as needed to resolve the conflict.&lt;/li&gt;
&lt;li&gt;Stage the resolved files using git add file-name.&lt;/li&gt;
&lt;li&gt;Commit the changes using git commit.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;5-advanced-branching-techniques&#34;&gt;5. Advanced Branching Techniques&lt;/h2&gt;
&lt;h4 id=&#34;rebasing&#34;&gt;Rebasing:&lt;/h4&gt;
&lt;p&gt;Rebasing is an alternative to merging that keeps a linear commit history. To rebase a branch onto another branch, use the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git rebase target-branch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;cherry-picking&#34;&gt;Cherry-picking:&lt;/h4&gt;
&lt;p&gt;Cherry-picking allows you to selectively apply commits from one branch to another. To cherry-pick a commit, use the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git cherry-pick commit-hash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Replace commit-hash with the hash of the commit you want to cherry-pick.&lt;/p&gt;
&lt;h2 id=&#34;6-git-best-practices&#34;&gt;6. Git Best Practices&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Use descriptive branch names related to the task or feature.&lt;/li&gt;
&lt;li&gt;Keep branches short-lived and focused on a specific task.&lt;/li&gt;
&lt;li&gt;Regularly pull changes fromthe main branch to keep your feature branches up-to-date.&lt;/li&gt;
&lt;li&gt;Perform small, frequent commits with clear and informative commit messages.&lt;/li&gt;
&lt;li&gt;Use pull requests and code reviews to ensure high-quality code before merging into the main branch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By mastering Git branching, merging, and conflict resolution, you&amp;rsquo;ll be well-prepared to handle complex projects and collaborate effectively with your team. Implementing Git best practices will further improve your software development process and enhance the overall quality of your codebase. As you continue to hone your Git skills, you&amp;rsquo;ll find it to be an indispensable tool in managing your projects and streamlining your workflow.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Docker Essentials: Images, Containers &amp; More</title>
        <link>https://vectops.com/post/2023/docker-essentials-images-containers-more/</link>
        <pubDate>Sun, 30 Apr 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/docker-essentials-images-containers-more/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/docker-essentials-images-containers-more/image.png" alt="Featured image of post Docker Essentials: Images, Containers &amp; More" /&gt;&lt;p&gt;In this tutorial, we&amp;rsquo;ll cover the essentials of Docker, focusing on key concepts like images, containers, and Dockerfiles. By the end of this guide, you&amp;rsquo;ll have a solid understanding of Docker fundamentals and be prepared to create, manage, and deploy containerized applications with ease.&lt;/p&gt;
&lt;h2 id=&#34;article-outline&#34;&gt;Article Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Introduction to Docker
Key Docker Concepts
  a. Docker Images
  b. Docker Containers
  c. Dockerfiles
  d. Docker Registries
Installing Docker
Creating Your First Docker Image and Container
  a. Writing a Dockerfile
  b. Building the Docker Image
  c. Running a Docker Container
Basic Docker Commands
  a. Listing Images and Containers
  b. Starting, Stopping, and Restarting Containers
  c. Removing Images and Containers
Conclusion
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;part-1-introduction-to-docker&#34;&gt;Part 1: Introduction to Docker&lt;/h2&gt;
&lt;p&gt;Docker is an open-source platform that automates the deployment, scaling, and management of containerized applications. Docker allows you to package an application and its dependencies into a lightweight, portable container that can run consistently across different environments. This consistency simplifies application development, testing, and deployment, making Docker a popular choice among developers and sysadmins.&lt;/p&gt;
&lt;h2 id=&#34;part-2-key-docker-concepts&#34;&gt;Part 2: Key Docker Concepts&lt;/h2&gt;
&lt;p&gt;To get started with Docker, it&amp;rsquo;s important to understand its key concepts:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Docker Images:&lt;/strong&gt; An image is a lightweight, portable, and executable snapshot of a containerized application and its dependencies. Images are built from a Dockerfile and can be stored in a registry for sharing and deployment.&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Docker Containers:&lt;/strong&gt; Containers are instances of Docker images that run the packaged application in an isolated environment. Containers provide consistency and portability across various platforms and environments.&lt;/p&gt;
&lt;p&gt;c. &lt;strong&gt;Dockerfiles:&lt;/strong&gt; A Dockerfile is a script that contains instructions for building a Docker image. It defines the base image, application code, dependencies, and configuration required to create a containerized application.&lt;/p&gt;
&lt;p&gt;d. &lt;strong&gt;Docker Registries:&lt;/strong&gt; A Docker registry is a centralized repository for storing and sharing Docker images. Docker Hub is the default public registry, but you can also use private registries or create your own.&lt;/p&gt;
&lt;h2 id=&#34;part-3-installing-docker&#34;&gt;Part 3: Installing Docker&lt;/h2&gt;
&lt;p&gt;To start using Docker, download and install the appropriate version for your operating system from the official Docker website. Docker Desktop is available for Windows and macOS, while Docker Engine is available for Linux distributions.&lt;/p&gt;
&lt;h2 id=&#34;part-4-creating-your-first-docker-image-and-container&#34;&gt;Part 4: Creating Your First Docker Image and Container&lt;/h2&gt;
&lt;p&gt;Once Docker is installed, you can create your first Docker image and container by following these steps:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Writing a Dockerfile:&lt;/strong&gt; Create a new text file named &amp;ldquo;Dockerfile&amp;rdquo; (without any file extension) in your project directory. Write the necessary instructions to define your containerized application, such as specifying the base image, copying application files, installing dependencies, and setting up the runtime environment.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For example: (Note that the html code has been embedded within the Dockerfile for simplicity&amp;rsquo;s sake)&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Use the official NGINX image as the base image&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; nginx:latest&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Set the working directory&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; /usr/share/nginx/html&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Create a simple &amp;#34;Hello, World!&amp;#34; HTML file&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Hello, World!&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Hello, World!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;#39;&lt;/span&gt; &amp;gt; index.html&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Expose the default NGINX port (80)&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; 80&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Start the NGINX server&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-g&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;daemon off;&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;b. &lt;strong&gt;Building the Docker Image:&lt;/strong&gt; In your project directory, run the docker build command followed by the -t flag (to tag the image with a name) and a period (to indicate the current directory). This command builds a Docker image from your Dockerfile.&lt;/p&gt;
&lt;p&gt;For the above example, this would be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker build -t hello-world-nginx .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;c.** Running a Docker Container:** Use the docker run command followed by the image name to create and start a new container from your Docker image. Optionally, you can specify flags to customize the container&amp;rsquo;s behavior, such as -p to map container ports to host ports, or &amp;ndash;name to assign a custom name to the container.&lt;/p&gt;
&lt;p&gt;From the previous step, you would use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d -p 8080:80 --name hello-world-nginx-container hello-world-nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally open your browser to the URL: http://localhost:8080 and see the Hello World.&lt;/p&gt;
&lt;h2 id=&#34;part-5-basic-docker-commands&#34;&gt;Part 5: Basic Docker Commands&lt;/h2&gt;
&lt;p&gt;Here are some basic Docker commands to help you manage images and containers:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Listing Images and Containers:&lt;/strong&gt; Use docker images to list all available images on your system, and docker ps (or &lt;code&gt;docker container ls&lt;/code&gt;) to list all running containers. To view all containers, including stopped ones, add the &lt;code&gt;-a&lt;/code&gt; flag to the docker &lt;code&gt;ps&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Starting, Stopping, and Restarting Containers:&lt;/strong&gt; To start, stop, or restart a container, use the docker start, docker stop, or docker restart commands, followed by the container ID or name.&lt;/p&gt;
&lt;p&gt;c. &lt;strong&gt;Removing Images and Containers:&lt;/strong&gt; Use docker rmi followed by the image ID or name to remove a Docker image. To remove a container, use docker rm followed by the container ID or name. Remember that you&amp;rsquo;ll need to stop a container before you can remove it.&lt;/p&gt;
&lt;h2 id=&#34;part-6-conclusion&#34;&gt;Part 6: Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations! You&amp;rsquo;ve now learned the essentials of Docker, including its key concepts, how to create images and containers, and basic Docker commands. With a solid foundation in Docker, you&amp;rsquo;ll be well-equipped to manage and deploy containerized applications effectively, and take your DevOps and sysadmin career to new heights.&lt;/p&gt;
&lt;p&gt;As you become more comfortable with Docker, consider exploring additional features like Docker Compose, Docker Swarm, and Docker networking to further enhance your container management skills. Keep learning and experimenting with new Docker features and best practices to stay ahead in the rapidly evolving world of containerization.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Kubernetes Basics: Cluster Setup &amp; Deployment</title>
        <link>https://vectops.com/post/2023/kubernetes-basics-cluster-setup-deployment/</link>
        <pubDate>Sun, 23 Apr 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/kubernetes-basics-cluster-setup-deployment/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/kubernetes-basics-cluster-setup-deployment/image.png" alt="Featured image of post Kubernetes Basics: Cluster Setup &amp; Deployment" /&gt;&lt;p&gt;In this tutorial, we&amp;rsquo;ll walk you through the basics of Kubernetes, focusing on setting up a Kubernetes cluster and deploying a containerized application. By the end of this guide, you&amp;rsquo;ll have a solid understanding of Kubernetes fundamentals and be ready to manage containerized applications with ease.&lt;/p&gt;
&lt;h2 id=&#34;article-outline&#34;&gt;Article Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Introduction to Kubernetes
Kubernetes Components
  a. Nodes
  b. Pods
  c. Services
  d. Deployments
Setting Up a Kubernetes Cluster
  a. Using a managed Kubernetes service
  b. Setting up a cluster manually
Deploying a Containerized Application
  a. Creating a deployment
  b. Exposing the application using a service
  c. Scaling the application
  d. Updating the application
Conclusion
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;part-1-introduction-to-kubernetes&#34;&gt;Part 1: Introduction to Kubernetes&lt;/h2&gt;
&lt;p&gt;Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. Developed by Google and now maintained by the Cloud Native Computing Foundation (CNCF), Kubernetes has become the industry standard for container orchestration, supporting a wide range of container runtimes, including Docker and containerd.&lt;/p&gt;
&lt;h2 id=&#34;part-2-kubernetes-components&#34;&gt;Part 2: Kubernetes Components&lt;/h2&gt;
&lt;p&gt;Kubernetes uses various components to manage containerized applications:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Nodes:&lt;/strong&gt; These are the worker machines that run containers. Nodes can be virtual or physical machines, and a Kubernetes cluster can consist of one or more nodes.&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Pods:&lt;/strong&gt; The smallest and simplest unit in Kubernetes, pods are used to deploy containers. A pod can contain one or more containers that share the same network namespace and storage volumes.&lt;/p&gt;
&lt;p&gt;c. &lt;strong&gt;Services:&lt;/strong&gt; A Kubernetes service is an abstraction that defines a logical set of pods and a policy to access them. Services are used to expose applications running in pods to the network, either within the cluster or externally.&lt;/p&gt;
&lt;p&gt;d. &lt;strong&gt;Deployments:&lt;/strong&gt; Deployments are used to declaratively manage the desired state of your containerized application. They can automatically manage and update pods based on the specified configuration.&lt;/p&gt;
&lt;h2 id=&#34;part-3-setting-up-a-kubernetes-cluster&#34;&gt;Part 3: Setting Up a Kubernetes Cluster&lt;/h2&gt;
&lt;p&gt;To set up a Kubernetes cluster, you have two options:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Using a managed Kubernetes service:&lt;/strong&gt; Many cloud providers offer managed Kubernetes services, such as Google Kubernetes Engine (GKE), Amazon Elastic Kubernetes Service (EKS), and Azure Kubernetes Service (AKS). These services simplify cluster setup and management by automating tasks like node provisioning and updates.&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Setting up a cluster manually:&lt;/strong&gt; For more control over your cluster, you can set it up manually using tools like kubeadm, Minikube, or Kops. This approach requires more hands-on management but offers greater customization.&lt;/p&gt;
&lt;h2 id=&#34;part-4-deploying-a-containerized-application&#34;&gt;Part 4: Deploying a Containerized Application&lt;/h2&gt;
&lt;p&gt;Once your Kubernetes cluster is set up, follow these steps to deploy a containerized application:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Creating a deployment:&lt;/strong&gt; Write a YAML manifest file to define your application&amp;rsquo;s deployment, specifying the container image, desired replicas, and other configuration details. Use the kubectl apply command to create the deployment.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;apps/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myapp-deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;replicas&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;selector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;matchLabels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myapp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;template&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myapp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;containers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myapp-container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myapp-image:v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;containerPort&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;b. &lt;strong&gt;Exposing the application using a service:&lt;/strong&gt; To make your application accessible, create a Kubernetes service by defining a YAML manifest file and applying it with kubectl apply. The service will expose the application on a specific port or load balancer, depending on the chosen service type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myapp-service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;selector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myapp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;protocol&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;TCP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;targetPort&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;LoadBalancer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;c. &lt;strong&gt;Scaling the application:&lt;/strong&gt; To scale your application, update the replicas field in your deployment manifest, and reapply the configuration using kubectl apply. Kubernetes will automatically create or remove pods to match the desired replica count.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Update the replicas field in your deployment manifest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# For example, change the replicas from 3 to 5, then run:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f myapp-deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;d. &lt;strong&gt;Updating the application:&lt;/strong&gt; To update your application, modify the container image or other configuration details in your deployment manifest, and reapply the updated manifest using kubectl apply. Kubernetes will perform a rolling update, replacing old pods with new ones while maintaining the desired replica count and minimizing downtime.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Update the container image or other configuration details in your deployment manifest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# For example, change the image from myapp-image:v1 to myapp-image:v2, then run:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f myapp-deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;part-5-conclusion&#34;&gt;Part 5: Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations! You&amp;rsquo;ve now learned the basics of Kubernetes, including its key components, setting up a cluster, and deploying a containerized application. As you become more comfortable with Kubernetes, you can explore additional features like persistent storage, ingress controllers, and custom resource definitions to further enhance your container orchestration skills.&lt;/p&gt;
&lt;p&gt;For more basic Kubernetes information I highly recommend you read: &lt;a class=&#34;link&#34; href=&#34;https://www.cncf.io/phippy/phippy-goes-to-the-zoo-book/&#34;  title=&#34;Phippy goes to the zoo&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Phippy goes to the zoo&lt;/a&gt; by the Cloud Native Computing Foundation. Yes, it looks like a kid&amp;rsquo;s book but it clears out a lot of decent information.&lt;/p&gt;
&lt;p&gt;By mastering Kubernetes basics, you&amp;rsquo;ll be well-equipped to manage and scale containerized applications efficiently, and take your DevOps and sysadmin career to new heights. Don&amp;rsquo;t forget to keep learning and experimenting with new Kubernetes features and best practices to stay ahead in the rapidly evolving world of container orchestration. update, replacing old pods with new ones&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 5: Advanced IaC Techniques and Future Trends</title>
        <link>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-5/</link>
        <pubDate>Tue, 18 Apr 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-5/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-5/image.png" alt="Featured image of post Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 5: Advanced IaC Techniques and Future Trends" /&gt;&lt;p&gt;In the final part of our beginner&amp;rsquo;s guide to Infrastructure as Code, we&amp;rsquo;ll explore advanced IaC techniques and examine future trends in the IaC landscape. By mastering these advanced concepts, you&amp;rsquo;ll be well-equipped to stay ahead in the rapidly evolving world of Infrastructure as Code.&lt;/p&gt;
&lt;h2 id=&#34;article-outline&#34;&gt;Article Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Advanced IaC techniques
  a. Policy as Code
  b. Immutable infrastructure
  c. Infrastructure monitoring and observability
  d. IaC refactoring
Future trends in Infrastructure as Code
  a. AI and Machine Learning in IaC
  b. Edge computing and IaC
  c. Serverless infrastructure management
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;part-5-advanced-iac-techniques-and-future-trends&#34;&gt;Part 5: Advanced IaC Techniques and Future Trends&lt;/h1&gt;
&lt;h2 id=&#34;advanced-iac-techniques&#34;&gt;Advanced IaC techniques&lt;/h2&gt;
&lt;p&gt;To further enhance your IaC skills, consider exploring these advanced techniques:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Policy as Code:&lt;/strong&gt; Extend IaC principles to security, compliance, and governance by defining policies as code. Tools like HashiCorp Sentinel, Open Policy Agent, and Azure Policy allow you to enforce policies programmatically across your infrastructure.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example, using OPA(Open Policy Agent), with a Rego policy file &lt;code&gt;example_policy.rego&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-rego&#34; data-lang=&#34;rego&#34;&gt;package main

deny[msg] {
    input.resource.kind == &amp;#34;Pod&amp;#34;
    image := input.resource.spec.containers[_].image
    not startswith(image, &amp;#34;example.com/&amp;#34;)
    msg := sprintf(&amp;#34;Invalid image registry: %v&amp;#34;, [image])
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;b. &lt;strong&gt;Immutable infrastructure:&lt;/strong&gt; Adopt an immutable infrastructure approach, where infrastructure components are replaced rather than updated. By using IaC tools to create and manage immutable infrastructure, you can improve consistency, reduce configuration drift, and simplify rollback processes.&lt;/p&gt;
&lt;p&gt;Using Terraform, you could add the following to your &lt;code&gt;main.tf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;resource&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;aws_instance&amp;#34; &amp;#34;web&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ami           &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ami-0c55b159cbfafe1f0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  instance_type &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;t2.micro&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  tags &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;web-${timestamp()}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;c. &lt;strong&gt;Infrastructure monitoring and observability:&lt;/strong&gt; Incorporate monitoring and observability tools into your IaC workflows to gain deeper insights into the performance and health of your infrastructure. Tools like Prometheus, Grafana, and ELK Stack can help you collect, analyze, and visualize infrastructure metrics.&lt;/p&gt;
&lt;p&gt;Example Ansible playbook for deploying Prometheus and Grafana:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Deploy Prometheus and Grafana&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;hosts&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;monitoring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;become&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;tasks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Install Docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ansible.builtin.package&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;state&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Install docker-compose&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ansible.builtin.package&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;docker-compose&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;state&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Deploy Prometheus and Grafana with docker-compose&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ansible.builtin.docker_compose&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;project_src&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/path/to/prometheus-grafana-docker-compose&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;state&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;This Ansible playbook deploys Prometheus and Grafana using Docker and docker-compose on a target host labeled monitoring. 
Make sure to replace /path/to/prometheus-grafana-docker-compose with the path to the directory containing the docker-compose.yml file for your Prometheus and Grafana setup.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;d. &lt;strong&gt;IaC refactoring:&lt;/strong&gt; Periodically review and refactor your IaC code to improve maintainability, readability, and efficiency. Techniques like modularization, code reuse, and removing duplication can help you keep your IaC codebase clean and up-to-date.&lt;/p&gt;
&lt;h2 id=&#34;future-trends-in-infrastructure-as-code&#34;&gt;Future trends in Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;Stay ahead of the curve by keeping an eye on these emerging trends in the IaC landscape:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;AI and Machine Learning in IaC:&lt;/strong&gt; As AI and Machine Learning continue to advance, expect to see more intelligent IaC tools that can optimize infrastructure management, detect anomalies, and even suggest code improvements. Read: ChatGPT&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Edge computing and IaC:&lt;/strong&gt; With the rise of edge computing, IaC tools will need to adapt to manage the distributed nature of edge infrastructure, enabling efficient deployment and management of edge devices and services.&lt;/p&gt;
&lt;p&gt;c. &lt;strong&gt;Serverless infrastructure management:&lt;/strong&gt; The increasing adoption of serverless computing will lead to the development of IaC tools and techniques tailored to manage serverless infrastructure, such as AWS Lambda functions and Azure Functions.&lt;/p&gt;
&lt;p&gt;By mastering advanced IaC techniques and staying informed about future trends, you&amp;rsquo;ll be well-prepared to tackle the challenges of modern infrastructure management. With a solid foundation in Infrastructure as Code, you&amp;rsquo;ll continue to excel in your DevOps and sysadmin career, and lead your organization towards more efficient and automated infrastructure management.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 4: Integrating IaC with CI/CD Pipelines</title>
        <link>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-4/</link>
        <pubDate>Mon, 17 Apr 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-4/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-4/image.png" alt="Featured image of post Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 4: Integrating IaC with CI/CD Pipelines" /&gt;&lt;p&gt;In Part 4 of our beginner&amp;rsquo;s guide to Infrastructure as Code, we&amp;rsquo;ll focus on the integration of IaC into Continuous Integration and Continuous Delivery (CI/CD) pipelines.&lt;/p&gt;
&lt;p&gt;You can check the previous part &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-3&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt; or if you want to start from the beginning, go &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-1&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Integrating IaC into your CI/CD pipeline is crucial for efficient infrastructure management and automation. By using more transition words, we&amp;rsquo;ll make this part even more readable and engaging.&lt;/p&gt;
&lt;h2 id=&#34;article-outline&#34;&gt;Article Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Understanding CI/CD pipelines
Benefits of integrating IaC with CI/CD pipelines
Steps to integrate IaC into your CI/CD pipeline
  a. Choose a CI/CD platform
  b. Create the pipeline configuration
  c. Add IaC stages to the pipeline
  d. Automate testing and validation
  e. Monitor and optimize the pipeline
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;part-4-integrating-iac-with-cicd-pipelines&#34;&gt;Part 4: Integrating IaC with CI/CD Pipelines&lt;/h1&gt;
&lt;h2 id=&#34;understanding-cicd-pipelines&#34;&gt;Understanding CI/CD pipelines&lt;/h2&gt;
&lt;p&gt;Continuous Integration (CI) and Continuous Delivery (CD) are practices that enable the automation of building, testing, and deploying code and infrastructure changes. CI involves merging code changes into a shared repository, where automated builds and tests are run. CD, on the other hand, automates the deployment of these changes to various environments, such as staging or production.&lt;/p&gt;
&lt;h2 id=&#34;benefits-of-integrating-iac-with-cicd-pipelines&#34;&gt;Benefits of integrating IaC with CI/CD pipelines&lt;/h2&gt;
&lt;p&gt;Integrating IaC with your CI/CD pipeline offers several advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Improved collaboration:&lt;/strong&gt; IaC and CI/CD together promote collaboration among team members by encouraging code reviews and shared ownership of the codebase and infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Faster deployments:&lt;/strong&gt; Automated infrastructure provisioning and deployment through CI/CD pipelines enable faster, more efficient deployments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced errors:&lt;/strong&gt; Automation reduces the likelihood of human errors, resulting in more reliable and stable infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easier rollback:&lt;/strong&gt; If issues arise, you can quickly revert to previous infrastructure versions using version-controlled IaC code and CI/CD rollback mechanisms.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;steps-to-integrate-iac-into-your-cicd-pipeline&#34;&gt;Steps to integrate IaC into your CI/CD pipeline&lt;/h2&gt;
&lt;p&gt;To integrate IaC into your CI/CD pipeline, follow these steps:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Choose a CI/CD platform&lt;/strong&gt;: Select a CI/CD platform that fits your organization&amp;rsquo;s needs and is compatible with your chosen IaC tool. Examples of CI/CD platforms include Jenkins, GitLab CI/CD, and AWS CodePipeline.&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Create the pipeline configuration:&lt;/strong&gt; Define the pipeline structure and stages using your CI/CD platform&amp;rsquo;s configuration language, such as Jenkinsfile for Jenkins or .gitlab-ci.yml for GitLab.&lt;/p&gt;
&lt;p&gt;For example, using Jenkins with Terraform:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipeline &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    agent any
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stages &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stage&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Initialize Terraform&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            steps &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;terraform init&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stage&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Validate Terraform&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            steps &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;terraform validate&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stage&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Plan Terraform&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            steps &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;terraform plan&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stage&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Apply Terraform&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            steps &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;terraform apply -auto-approve&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another example, using Gitlab CI/CD with Ansible:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;stages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;prepare&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;validate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;prepare&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;prepare&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;ansible-galaxy install -r requirements.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;validate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;validate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;ansible-playbook --syntax-check site.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;deploy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;ansible-playbook -i inventory.ini site.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;c. &lt;strong&gt;Add IaC stages to the pipeline:&lt;/strong&gt; Incorporate IaC-specific stages into your pipeline, such as infrastructure provisioning, configuration management, and deployment. Ensure these stages align with your infrastructure management workflows.&lt;/p&gt;
&lt;p&gt;An example using AWS CodePipeline with AWS CloudFormation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- In your AWS CodePipeline, click &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Edit&amp;#34;&lt;/span&gt; to modify your pipeline.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- Add a new stage by clicking the &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt; icon.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- Name the stage, &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; example, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Deploy CloudFormation&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- Click &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Add action group&amp;#34;&lt;/span&gt; in the new stage.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   * Choose &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS CloudFormation&amp;#34;&lt;/span&gt; as the action provider.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   * Select an action mode, such as &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Create or update stack&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   * Provide the necessary inputs, such as Stack name, Template file, and any required Parameters.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- Click &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Done&amp;#34;&lt;/span&gt; to add the action to the stage.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This setup creates a new stage in your AWS CodePipeline that deploys or updates a CloudFormation stack as part of the pipeline.&lt;/p&gt;
&lt;p&gt;d. &lt;strong&gt;Automate testing and validation:&lt;/strong&gt; Implement automated testing and validation for your IaC code within the pipeline. This process can include static analysis, unit testing, and integration testing to ensure that your code is functional and adheres to best practices.&lt;/p&gt;
&lt;p&gt;An example on how to automate testing with Terraform:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pipeline&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;agent&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;stages&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;//&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;stage&lt;/span&gt;(&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Validate&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Terraform&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;steps&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;sh&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;terraform&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;validate&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;stage&lt;/span&gt;(&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Terraform&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Security&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Check&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;steps&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;sh&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;tfsec&lt;/span&gt; .&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;stage&lt;/span&gt;(&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Terraform&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Compliance&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;steps&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;sh&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;terraform&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;compliance&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;f&lt;/span&gt; . &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;plan&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;//&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;e. &lt;strong&gt;Monitor and optimize the pipeline:&lt;/strong&gt; Continuously monitor your CI/CD pipeline&amp;rsquo;s performance and optimize it based on your organization&amp;rsquo;s needs. Consider factors like deployment frequency, success rate, and the duration of each pipeline stage.&lt;/p&gt;
&lt;p&gt;By integrating Infrastructure as Code into your CI/CD pipeline, you&amp;rsquo;ll streamline your infrastructure management process and improve the overall efficiency of your DevOps and sysadmin workflows. In the next and final part of our beginner&amp;rsquo;s guide, we&amp;rsquo;ll explore advanced IaC techniques and future trends to help you stay ahead in the rapidly evolving world of IaC.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 3: Implementing IaC Best Practices and Real-World Examples</title>
        <link>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-3/</link>
        <pubDate>Sun, 16 Apr 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-3/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-3/image.png" alt="Featured image of post Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 3: Implementing IaC Best Practices and Real-World Examples" /&gt;&lt;p&gt;In this third installment of our beginner&amp;rsquo;s guide to Infrastructure as Code, we&amp;rsquo;ll explore the best practices for implementing IaC in your organization.&lt;/p&gt;
&lt;p&gt;You can check the previous part &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-2&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt; or if you want to start from the beginning, go &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-1&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Additionally, we&amp;rsquo;ll provide real-world examples that demonstrate the power and versatility of IaC. With a focus on readability and SEO, let&amp;rsquo;s dive into the world of IaC best practices and examples.&lt;/p&gt;
&lt;h2 id=&#34;article-outline&#34;&gt;Article Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;IaC best practices
  a. Maintain consistency
  b. Use version control
  c. Modularize your code
  d. Validate and test your infrastructure code
  e. Keep secrets secure
  f. Document your code
Real-world IaC examples
  a. Deploying a web application
  b. Managing a multi-cloud environment
  c. Scaling infrastructure on demand
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;part-3-implementing-iac-best-practices-and-real-world-examples&#34;&gt;Part 3: Implementing IaC Best Practices and Real-World Examples&lt;/h1&gt;
&lt;h2 id=&#34;iac-best-practices&#34;&gt;IaC best practices&lt;/h2&gt;
&lt;p&gt;To ensure your Infrastructure as Code implementation is effective and efficient, consider following these best practices:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Maintain consistency&lt;/strong&gt;: Consistently apply naming conventions, directory structures, and coding styles across your IaC codebase. This consistency makes it easier for team members to collaborate and understand the code.&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Use version control&lt;/strong&gt;: Employ a version control system, such as Git, to track changes in your IaC code. This practice allows you to roll back to previous versions if needed and simplifies collaboration among team members.&lt;/p&gt;
&lt;p&gt;c. &lt;strong&gt;Modularize your code&lt;/strong&gt;: Break your IaC code into reusable modules, which can be shared across projects. Modularization helps reduce code duplication and makes maintenance more manageable.&lt;/p&gt;
&lt;p&gt;d. &lt;strong&gt;Validate and test your infrastructure code&lt;/strong&gt;: Regularly test your IaC code using techniques such as static analysis, unit testing, and integration testing. Testing ensures that your code is functional and adheres to best practices.&lt;/p&gt;
&lt;p&gt;e. &lt;strong&gt;Keep secrets secure:&lt;/strong&gt; Store sensitive information, such as API keys and passwords, securely using tools like HashiCorp Vault or AWS Secrets Manager. Avoid including secrets directly in your IaC code.&lt;/p&gt;
&lt;p&gt;f. &lt;strong&gt;Document your code:&lt;/strong&gt; Provide clear and concise documentation for your IaC code, outlining the purpose of each module, variables, and dependencies. Good documentation makes it easier for other team members to understand and maintain the code.&lt;/p&gt;
&lt;h2 id=&#34;real-world-iac-examples&#34;&gt;Real-world IaC examples&lt;/h2&gt;
&lt;p&gt;Now, let&amp;rsquo;s look at some real-world examples of IaC in action:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Deploying a web application:&lt;/strong&gt; By using IaC tools like Terraform or AWS CloudFormation, you can automate the provisioning and management of web servers, load balancers, databases, and other necessary infrastructure components. This automation simplifies deployment and ensures a consistent setup across different environments (e.g., development, staging, and production).&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Managing a multi-cloud environment:&lt;/strong&gt; With IaC tools that support multiple cloud providers, such as Terraform, you can manage infrastructure across different clouds (e.g., AWS, Azure, and Google Cloud) using a single codebase. This approach streamlines multi-cloud management and ensures consistency across your infrastructure.&lt;/p&gt;
&lt;p&gt;c. &lt;strong&gt;Scaling infrastructure on demand:&lt;/strong&gt; By leveraging IaC and cloud-native services, you can automatically scale your infrastructure based on demand, such as increasing the number of web servers during peak traffic periods. This dynamic scaling ensures optimal resource utilization and improves overall application performance.&lt;/p&gt;
&lt;p&gt;By implementing Infrastructure as Code best practices and exploring real-world examples, you can unlock the full potential of IaC in your organization. As you continue to refine your IaC skills, you&amp;rsquo;ll discover new ways to improve the efficiency and automation of your DevOps and sysadmin workflows.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 2: Popular IaC Tools and Getting Started</title>
        <link>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-2/</link>
        <pubDate>Sat, 15 Apr 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-2/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-2/image.png" alt="Featured image of post Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 2: Popular IaC Tools and Getting Started" /&gt;&lt;p&gt;In the first part of our beginner&amp;rsquo;s guide to Infrastructure as Code, which you can find &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-1&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt; we introduced the concept of IaC and its importance in the modern DevOps and sysadmin landscape.&lt;/p&gt;
&lt;p&gt;In this second part, we&amp;rsquo;ll explore popular IaC tools and platforms and provide a hands-on guide for getting started with IaC in your organization.&lt;/p&gt;
&lt;h2 id=&#34;article-outline&#34;&gt;Article Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Popular IaC tools and platforms
  a. Terraform
  b. Ansible
  c. Chef
  d. Puppet
  e. AWS CloudFormation
Getting started with IaC
  a. Choose the right IaC tool
  b. Learn the tool-specific language
  c. Create your first infrastructure code
  d. Test and validate your code
  e. Integrate IaC into your CI/CD pipeline
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;part-2-popular-iac-tools-and-getting-started&#34;&gt;Part 2: Popular IaC Tools and Getting Started&lt;/h2&gt;
&lt;h3 id=&#34;popular-iac-tools-and-platforms&#34;&gt;Popular IaC tools and platforms&lt;/h3&gt;
&lt;p&gt;There are several IaC tools and platforms available, each with its own strengths and weaknesses. Here are some popular options:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Terraform&lt;/strong&gt;: An open-source IaC tool developed by HashiCorp that allows you to define and manage infrastructure across multiple cloud providers using a declarative language called HCL (HashiCorp Configuration Language).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;provider&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;aws&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  region &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;us-west-2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;resource&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;aws_instance&amp;#34; &amp;#34;example&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ami           &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ami-0c55b159cbfafe1f0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  instance_type &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;t2.micro&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  tags &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;example-instance&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;b. &lt;strong&gt;Ansible&lt;/strong&gt;: An open-source configuration management and automation tool that uses a simple, human-readable language called YAML. Ansible is agentless, relying on SSH for remote execution, and is often used for managing server configurations.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Install and start Nginx on Ubuntu&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;hosts&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;become&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;tasks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Install Nginx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;apt&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nginx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;state&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Start Nginx service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;service&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nginx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;state&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;started&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;c. &lt;strong&gt;Chef&lt;/strong&gt;: An open-source configuration management tool that uses a Ruby-based domain-specific language (DSL) to define infrastructure as code. Chef uses a client-server architecture and requires the installation of a Chef agent on managed nodes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# cookbooks/my_web_server/recipes/default.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;package &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;httpd&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;service &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;httpd&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;:enable&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;:start&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/var/www/html/index.html&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  content &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mode &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0644&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  owner &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  group &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;d. &lt;strong&gt;Puppet&lt;/strong&gt;: Another open-source configuration management tool that uses its own declarative DSL called Puppet DSL. Puppet can manage infrastructure in a client-server setup or in a standalone mode using Puppet Bolt.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-DSL&#34; data-lang=&#34;DSL&#34;&gt;class nginx {
  package { &amp;#39;nginx&amp;#39;:
    ensure =&amp;gt; present,
  }

  service { &amp;#39;nginx&amp;#39;:
    ensure     =&amp;gt; running,
    enable     =&amp;gt; true,
    require    =&amp;gt; Package[&amp;#39;nginx&amp;#39;],
    subscribe  =&amp;gt; File[&amp;#39;/etc/nginx/nginx.conf&amp;#39;],
  }

  file { &amp;#39;/etc/nginx/nginx.conf&amp;#39;:
    ensure  =&amp;gt; file,
    owner   =&amp;gt; &amp;#39;root&amp;#39;,
    group   =&amp;gt; &amp;#39;root&amp;#39;,
    mode    =&amp;gt; &amp;#39;0644&amp;#39;,
    source  =&amp;gt; &amp;#39;puppet:///modules/nginx/nginx.conf&amp;#39;,
  }
}

include nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;e. &lt;strong&gt;AWS CloudFormation&lt;/strong&gt;: A cloud-native IaC service provided by Amazon Web Services (AWS) that allows you to define and manage AWS resources using JSON or YAML templates.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Resources&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;MyS3Bucket&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;Type&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AWS&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;S3&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;Properties&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;BucketName&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;my&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;example&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;getting-started-with-iac&#34;&gt;Getting started with IaC&lt;/h2&gt;
&lt;p&gt;To get started with IaC, follow these steps:&lt;/p&gt;
&lt;p&gt;a. &lt;strong&gt;Choose the right IaC tool:&lt;/strong&gt; Based on your organization&amp;rsquo;s infrastructure needs, cloud provider(s), and existing skillset, select the most suitable IaC tool.&lt;/p&gt;
&lt;p&gt;b. &lt;strong&gt;Learn the tool-specific language&lt;/strong&gt;: Familiarize yourself with the syntax, structure, and best practices of the IaC tool&amp;rsquo;s language (e.g., HCL for Terraform, YAML for Ansible, or JSON for AWS CloudFormation).&lt;/p&gt;
&lt;p&gt;c. &lt;strong&gt;Create your first infrastructure code:&lt;/strong&gt; Start by defining a simple infrastructure component, such as a virtual machine or a network configuration, in your chosen IaC tool. Use the tool&amp;rsquo;s documentation and examples as a reference.&lt;/p&gt;
&lt;p&gt;d. &lt;strong&gt;Test and validate your code:&lt;/strong&gt; Ensure your IaC code is functional and adheres to best practices by using testing and validation techniques, such as static analysis, unit testing, and integration testing.&lt;/p&gt;
&lt;p&gt;e. &lt;strong&gt;Integrate IaC into your CI/CD pipeline:&lt;/strong&gt; Once you&amp;rsquo;re comfortable with your IaC tool and have successfully defined and tested infrastructure code, incorporate it into your CI/CD pipeline to automate the provisioning and management of infrastructure.&lt;/p&gt;
&lt;p&gt;By following these steps, you&amp;rsquo;ll be on your way to successfully implementing Infrastructure as Code in your organization. As you gain experience and confidence with IaC, you&amp;rsquo;ll be able to further optimize your infrastructure management processes, reduce manual intervention, and increase the overall efficiency of your DevOps and sysadmin workflows.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 1: Introduction and Key Concepts</title>
        <link>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-1/</link>
        <pubDate>Fri, 14 Apr 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-1/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/beginners-guide-to-infrastructure-as-code/part-1/image.png" alt="Featured image of post Beginner&#39;s Guide to Infrastructure as Code (IaC) - Part 1: Introduction and Key Concepts" /&gt;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Welcome to the first part of our beginner&amp;rsquo;s guide to Infrastructure as Code (IaC). In this series, we&amp;rsquo;ll be exploring the foundations of IaC, its benefits, and how to get started with implementing it in your DevOps and sysadmin workflows. By breaking down this topic into easily digestible sections, we aim to provide a comprehensive understanding that will help you leverage IaC for maximum efficiency.&lt;/p&gt;
&lt;h2 id=&#34;article-outline&#34;&gt;Article Outline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;What is Infrastructure as Code (IaC)?
Why is IaC important for DevOps and sysadmins?
Key concepts in IaC
Popular IaC tools and platforms
Getting started with IaC
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;part-1-introduction-and-key-concepts&#34;&gt;Part 1: Introduction and Key Concepts&lt;/h2&gt;
&lt;h3 id=&#34;what-is-infrastructure-as-code-iac&#34;&gt;What is Infrastructure as Code (IaC)?&lt;/h3&gt;
&lt;p&gt;Infrastructure as Code (IaC) is the practice of managing and provisioning infrastructure components, such as virtual machines, networks, and storage, using machine-readable definition files rather than manual processes.&lt;/p&gt;
&lt;p&gt;These definition files, or &amp;ldquo;code,&amp;rdquo; can be versioned, tested, and maintained just like any other software codebase. This approach allows for a more consistent, automated, and scalable infrastructure management process.&lt;/p&gt;
&lt;h3 id=&#34;why-is-iac-important-for-devops-and-sysadmins&#34;&gt;Why is IaC important for DevOps and sysadmins?&lt;/h3&gt;
&lt;p&gt;IaC has become a critical component of modern DevOps practices and sysadmin workflows for several reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automation: IaC enables the automation of infrastructure provisioning and management, reducing manual intervention and human errors.&lt;/li&gt;
&lt;li&gt;Version control: With IaC, infrastructure configurations can be versioned and tracked, making it easier to maintain and update.&lt;/li&gt;
&lt;li&gt;Collaboration: IaC promotes collaboration between teams, as infrastructure changes can be reviewed and approved by multiple stakeholders.&lt;/li&gt;
&lt;li&gt;Scalability: IaC allows for infrastructure to be quickly and easily scaled to meet the demands of a growing application.&lt;/li&gt;
&lt;li&gt;Cost savings: By automating and optimizing infrastructure management, IaC can lead to cost savings in the long run.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;key-concepts-in-iac&#34;&gt;Key concepts in IaC&lt;/h3&gt;
&lt;p&gt;In order to understand and effectively work with IaC, it&amp;rsquo;s essential to be familiar with a few key concepts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configuration Management: The practice of maintaining and updating the state of your infrastructure over time.&lt;/li&gt;
&lt;li&gt;Immutable Infrastructure: An infrastructure model where components are replaced with new instances rather than being updated in place.&lt;/li&gt;
&lt;li&gt;Declarative vs. Imperative IaC: Declarative IaC focuses on defining the desired end state of the infrastructure, while imperative IaC outlines the steps to achieve that state.&lt;/li&gt;
&lt;li&gt;Continuous Integration and Continuous Delivery (CI/CD): CI/CD practices enable the automation of building, testing, and deploying code and infrastructure changes.&lt;/li&gt;
&lt;li&gt;Infrastructure as Code Testing: Techniques for validating and verifying IaC code to ensure the desired infrastructure state is achieved and maintained.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the next part of our beginner&amp;rsquo;s guide to Infrastructure as Code, we&amp;rsquo;ll delve deeper into popular IaC tools and platforms, as well as provide a hands-on guide for getting started with IaC in your organization.&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Configure Mikrotik with Cloudflare DDNS</title>
        <link>https://vectops.com/post/2023/configure-mikrotik-with-cloudflare-ddns/</link>
        <pubDate>Tue, 14 Feb 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/configure-mikrotik-with-cloudflare-ddns/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/configure-mikrotik-with-cloudflare-ddns/image.png" alt="Featured image of post Configure Mikrotik with Cloudflare DDNS" /&gt;&lt;p&gt;On last year I published a guide to configure our Mikrotik with the &lt;a class=&#34;link&#34; href=&#34;https://docs.ovh.com/gb/en/domains/hosting_dynhost/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OVH DDNS Service&lt;/a&gt; you can read the post in the next link: &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2022/configure-mikrotik-with-ovh-dyndns/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Configure Mikrotik with OVH DynDNS&lt;/a&gt;. A few days ago I migrated my DNS Zone from OVH to Cloudflare, and as you guessed I needed to change the DDNS from OVH to Cloudflare inside the Mikrotik script.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t know what DDNS is, it is a basic service where you have a local script or program to check when your public IP address changes and update the DNS record associated to it. This service is used by lots of people who have a homelab and are not given a static IP  address from their ISP provider.&lt;/p&gt;
&lt;h2 id=&#34;what-i-need&#34;&gt;What I need&lt;/h2&gt;
&lt;p&gt;First of all, we need some information to use this script in your Mikrotik from Cloudflare:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DNS Zone in Cloudflare&lt;/li&gt;
&lt;li&gt;Subdomain what we use to set the IP&lt;/li&gt;
&lt;li&gt;API Token to configure the script&lt;/li&gt;
&lt;li&gt;Script ddns_cloudflare for your mikrotik&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;After you create the DNS zone in Cloudflare and point the NS of your domain to it, create your custom sub-domain in your zone, like &amp;ldquo;private.mydomain.com&amp;rdquo; or something like that&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To create your API token, refer to &lt;a class=&#34;link&#34; href=&#34;https://developers.cloudflare.com/fundamentals/api/get-started/create-token/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this article from Cloudflare&lt;/a&gt; from the Cloudflare docs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download the &lt;a class=&#34;link&#34; href=&#34;https://github.com/vectops/scripts/blob/master/mikrotik/ddns/ddns_cloudflare.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ddns_cloudflare script&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;gathering-details-for-the-script&#34;&gt;Gathering details for the script&lt;/h2&gt;
&lt;p&gt;The script needs some local variables to work properly. You need to get the &lt;code&gt;zoneID&lt;/code&gt;, &lt;code&gt;dnsRecordID&lt;/code&gt;, &lt;code&gt;apiToken&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;subdomain&lt;/code&gt; from the DNS record and also the &lt;code&gt;interface&lt;/code&gt; from Mikrotik where your public IP address is assigned to.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For the &lt;code&gt;ZoneID&lt;/code&gt; you can find it on the Cloudflare dashboard. &lt;a class=&#34;link&#34; href=&#34;https://developers.cloudflare.com/fundamentals/get-started/basic-tasks/find-account-and-zone-ids/&#34;  title=&#34;Check how to&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;This is how to do it&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;With your &lt;code&gt;ZoneID&lt;/code&gt;, you can query your &lt;code&gt;dnsRecordID&lt;/code&gt; via &lt;code&gt;curl&lt;/code&gt;. &lt;a class=&#34;link&#34; href=&#34;https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-list-dns-records&#34;  title=&#34;API call&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;This is API call&lt;/a&gt;. For example:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records \
    -H &amp;#34;Authorization: Bearer $CLOUDFLARE_API_TOKEN&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On the router, go and check what your WAN interface is. You can see that in the &lt;code&gt;/ip address&lt;/code&gt; section.&lt;/p&gt;
&lt;h2 id=&#34;configure-the-script&#34;&gt;Configure the script&lt;/h2&gt;
&lt;p&gt;In the script, variables are defined through the &lt;code&gt;:local&lt;/code&gt; refs where you need to put the information:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;:local cfzoneid &amp;#34;&amp;#34; // Cloudflare Zone ID
:local cfdnsrecordid &amp;#34;&amp;#34; // Cloudflare DNS Record ID
:local cftoken &amp;#34;&amp;#34; // Cloudflare API Token
:local cfemail &amp;#34;&amp;#34; // Cloudflare email user
:local cfdnshost &amp;#34;&amp;#34; // Cloudflare subdomain

:local publicinterface &amp;#34;&amp;#34; // Mikrotik Public interface
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Just fill the spaces between double commas for each variable with the values you got in the previous step.&lt;/p&gt;
&lt;h2 id=&#34;setting-up-the-dyndns-client-script&#34;&gt;Setting up the DynDNS client script&lt;/h2&gt;
&lt;p&gt;Now go to your Mikrotik&amp;rsquo;s web interface and browse to the &lt;code&gt;System -&amp;gt; Scripts&lt;/code&gt; menu, click on &lt;code&gt;Add new&lt;/code&gt;, and fill in the form fields as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- Name: ddns_cloudflare
- Policy: read, write, test
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can test the script by applying and clicking on &lt;code&gt;Run Script&lt;/code&gt;. If everything is correct, you can see how on your Cloudflare&amp;rsquo;s dashboard the DNS record configured with the public IP address has been automatically updated. You also might like to use cli utilities such as &lt;code&gt;dig&lt;/code&gt; or &lt;code&gt;drill&lt;/code&gt; to check it out. That&amp;rsquo;s up to you :)&lt;/p&gt;
&lt;h2 id=&#34;scheduling-the-ddns-script&#34;&gt;Scheduling the DDNS script&lt;/h2&gt;
&lt;p&gt;Now here&amp;rsquo;s the thing. We got everything set up, verified that runs as intended, and everything is ready. But at this point, if you don&amp;rsquo;t click on the &amp;ldquo;Run script&amp;rdquo; button, the script won&amp;rsquo;t trigger itself. Hopefully that is quite simple to fix: just configure a &lt;code&gt;Scheduler&lt;/code&gt; to run this script on a given time basis (say 10 minutes).&lt;/p&gt;
&lt;p&gt;To achive this, from your Mikrotik&amp;rsquo;s web UI, go to &lt;code&gt;System -&amp;gt; Scheduler&lt;/code&gt; menu, and click on &lt;code&gt;Add new&lt;/code&gt;, then just fill each field with the next details:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- Name: ddns_cloudflare
- Interval: 00:10:00
- Policy: read, write, test
- On event: /system script run ddns_cloudflare
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you prefer setting this up through the cli, this is done just by running the following command:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/system scheduler
add interval=10m name=ddns_cloudflare on-event=&amp;#34;/system script run ddns_cloudflare&amp;#34; policy=read,write,test start-time=startup
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Remember that you can change the &lt;code&gt;interval&lt;/code&gt; accordingly to fit your own needs.&lt;/p&gt;
&lt;p&gt;With that, we  can say we&amp;rsquo;re done! You have configured the Cloudflare DDNS on your Mikrotik, and now you can connect remotely to your home network by pointing your VPN configuration to your very own, automatically updated domain record.&lt;/p&gt;
&lt;p&gt;See you next time, don&amp;rsquo;t forget to &lt;strong&gt;share&lt;/strong&gt; &amp;amp; leave a comment!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Avoid private information leaks in your Docker images metadata</title>
        <link>https://vectops.com/post/2023/avoid-private-information-leaks-in-your-docker-images-metadata/</link>
        <pubDate>Mon, 13 Feb 2023 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2023/avoid-private-information-leaks-in-your-docker-images-metadata/</guid>
        <description>&lt;img src="https://vectops.com/post/2023/avoid-private-information-leaks-in-your-docker-images-metadata/image.png" alt="Featured image of post Avoid private information leaks in your Docker images metadata" /&gt;&lt;p&gt;&lt;em&gt;Please note that in this article we will &lt;strong&gt;not&lt;/strong&gt; cover the deployment nor instructions on the usage of any version control system or container repository software, but are directly implying the use of both components.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you are one of those who run their own servers at home or just away from being exposed to the Internet, but still get some of the work done there made public, you are probably interested in this article.&lt;/p&gt;
&lt;p&gt;Recently I started publishing some of the Docker image builds I run on my own, for whoever might find the changes I introduce in others base images useful. &lt;a class=&#34;link&#34; href=&#34;https://hub.docker.com/r/mtnezm/nextcloud&#34;  title=&#34;Here is an example&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Here is an example&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-issue&#34;&gt;The issue&lt;/h2&gt;
&lt;p&gt;However, all the previous work before the image is pushed to public registries is run in my homelab. And for that reason I am especially interested in keeping all the details related to that part of my infrastructure private, as it is supposed to be.&lt;/p&gt;
&lt;p&gt;This said, if you happen to run your own container registry but also want to make your images available (by uploading them to public container registries such as &lt;a class=&#34;link&#34; href=&#34;https://hub.docker.com/&#34;  title=&#34;Docker Hub&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Docker Hub&lt;/a&gt; or &lt;a class=&#34;link&#34; href=&#34;https://github.com/features/packages&#34;  title=&#34;GitHub Container Registry&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Container Registry&lt;/a&gt;) there are a couple of things to be aware of.&lt;/p&gt;
&lt;p&gt;In particular, I&amp;rsquo;m talking about these annotations: &lt;code&gt;org.opencontainers.image.source&lt;/code&gt; and &lt;code&gt;org.opencontainers.image.url&lt;/code&gt; (more details can be found &lt;a class=&#34;link&#34; href=&#34;https://specs.opencontainers.org/image-spec/annotations/#pre-defined-annotation-keys&#34;  title=&#34;here&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;). When left intact, if you push a Docker image to a registry they will contain direct references to the Git repository where the image is being built from.&lt;/p&gt;
&lt;p&gt;This is normally not a problem when the code is also hosted in public repositories, but this is not our case. Say our private Git server resolves to &lt;code&gt;https://git.home.lab&lt;/code&gt;. Then we can check how it looks by inspecting the image, like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ docker pull ghcr.io/mtnezm/nextcloud:latest
$ docker inspect ghcr.io/mtnezm/nextcloud:latest  |jq &amp;#39;.[] | .ContainerConfig | .Labels&amp;#39;
{
  &amp;#34;maintainer&amp;#34;: &amp;#34;Miguel Martínez &amp;lt;mtnezm@linux.com&amp;gt;&amp;#34;,
  &amp;#34;org.opencontainers.image.created&amp;#34;: &amp;#34;2023-01-29T12:57:51Z&amp;#34;,
  &amp;#34;org.opencontainers.image.description&amp;#34;: &amp;#34;Custom Docker Nextcloud image build&amp;#34;,
  &amp;#34;org.opencontainers.image.revision&amp;#34;: &amp;#34;dab535e710a65affbb517aecaa9fc02fe21df1f6&amp;#34;,
  &amp;#34;org.opencontainers.image.source&amp;#34;: &amp;#34;https://git.home.lab/mtnezm/nextcloud.git&amp;#34;,
  &amp;#34;org.opencontainers.image.url&amp;#34;: &amp;#34;https://git.home.lab/mtnezm/nextcloud.git&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There it is, a link to our private Git repository included in a worldwide accessible Docker image. Something that does not make sense at all.&lt;/p&gt;
&lt;h2 id=&#34;fixing-it&#34;&gt;Fixing it&lt;/h2&gt;
&lt;p&gt;As we said, there is no real value in keeping a URL to a private Git server exposed there, so one thing we can do here is setting a custom value for those labels in our image. In this case, as I am using &lt;a class=&#34;link&#34; href=&#34;https://www.drone.io/&#34;  title=&#34;Drone CI&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Drone CI&lt;/a&gt; to build them, it can be done by adding these lines to the corresponding step in the pipeline:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- name: &amp;#34;Deploy&amp;#34;
  image: plugins/docker
  (...)
  custom_labels:
    - org.opencontainers.image.source=REDACTED FOR PRIVACY
    - org.opencontainers.image.url=REDACTED FOR PRIVACY
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you are working directly with the Dockerfile, you can achieve it by adding these lines:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;LABEL org.opencontainers.image.source=REDACTED FOR PRIVACY
LABEL org.opencontainers.image.url=REDACTED FOR PRIVACY
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After applying that change, if we build, publish, pull and inspect the image again, we can verify how it looks now:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;{
  &amp;#34;maintainer&amp;#34;: &amp;#34;Miguel Martínez &amp;lt;mtnezm@linux.com&amp;gt;&amp;#34;,
  &amp;#34;org.opencontainers.image.created&amp;#34;: &amp;#34;2023-01-29T13:22:49Z&amp;#34;,
  &amp;#34;org.opencontainers.image.description&amp;#34;: &amp;#34;Custom Docker Nextcloud image build&amp;#34;,
  &amp;#34;org.opencontainers.image.revision&amp;#34;: &amp;#34;30f0f6cff0f9a63af0cd990301d1f301b425df85&amp;#34;,
  &amp;#34;org.opencontainers.image.source&amp;#34;: &amp;#34;REDACTED FOR PRIVACY&amp;#34;,
  &amp;#34;org.opencontainers.image.url&amp;#34;: &amp;#34;REDACTED FOR PRIVACY&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This way we can keep references to the work that runs in our homelab out of the public eye. But then again you might wonder &amp;ldquo;how do we know what is the work behind that image in particular, and if we can trust you?&amp;rdquo; which is perfectly reasonable.&lt;/p&gt;
&lt;p&gt;In this case, as we are talking about Docker images there is the Dockerfile for you to go and verify it line by line, but let me answer to that one with a different approach in a future post here &lt;a class=&#34;link&#34; href=&#34;https://vectops.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;at Vectops&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Compile your own binaries for WD MyCloud OS5</title>
        <link>https://vectops.com/post/2022/compile-your-own-binaries-for-wd-mycloud-os5/</link>
        <pubDate>Sat, 19 Feb 2022 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2022/compile-your-own-binaries-for-wd-mycloud-os5/</guid>
        <description>&lt;img src="https://vectops.com/post/2022/compile-your-own-binaries-for-wd-mycloud-os5/image.png" alt="Featured image of post Compile your own binaries for WD MyCloud OS5" /&gt;&lt;p&gt;Recently, I bought a WesternDigital MyCloud PR2100 NAS. It runs a simple Linux OS with some pre-built packages but somehow I feel it&amp;rsquo;s not enough and it could be used for more stuff, so I thought &amp;ldquo;can you imagine running Docker and deploying your own Dockerfiles on this thing?&amp;rdquo;. And well, now I have an answer for that: &amp;ldquo;yes, you can!&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s see how it works. The NAS has a simple hardware setup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intel Pentium N3710 quad-core @ 1.60Ghz x86_64&lt;/li&gt;
&lt;li&gt;4GiB DDR3 1600Mhz 2x2gb dual-channel&lt;/li&gt;
&lt;li&gt;2 ports gigabit ethernet (bonding configurable)&lt;/li&gt;
&lt;li&gt;2x SATA3 6Gbps ports hot-swap&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This setup it&amp;rsquo;s already far from brand-new and has been present for a few years, mainly for non-technical audience. However, those are not bad specs at all. Just remember the latest Raspberry Pi v4 with 8GiB of RAM, for example. It&amp;rsquo;s not that far from it, right?&lt;/p&gt;
&lt;p&gt;Anyway, you&amp;rsquo;re here because you want to install more packages in your WD MyCloud OS5, so let&amp;rsquo;s focus on that.&lt;/p&gt;
&lt;h2 id=&#34;grabbing-the-binaries&#34;&gt;Grabbing the binaries&lt;/h2&gt;
&lt;p&gt;First of all, you need a computer with Docker engine already installed, say a laptop for example, then go ahead and clone &lt;a class=&#34;link&#34; href=&#34;https://github.com/WDCommunity/wdpksrc&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this repository&lt;/a&gt;. It is where the WD Community puts its own source packages to be compiled locally and installed in your NAS:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ git clone https://github.com/WDCommunity/wdpksrc.git
$ cd wdpksrc
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, its time to let Docker work:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker build -t wdpk .
docker run -it -v $(pwd):/wdpksrc wdpk /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If everything went right, you will see some like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;root@021ca29af42e:/wdpksrc# ls
Dockerfile  LICENSE  README.md	build.sh  build_and_install.sh	mksapkg-OS3  mksapkg-OS5  packages  tests  wdpk
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On this environment, we can build any package inside &lt;code&gt;wdpksrc&lt;/code&gt; directory. On this example, we are compiling a Docker package, so just run:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd wdpksrc/docker
./build.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The process will take around 1 minute or so.&lt;/p&gt;
&lt;h2 id=&#34;installing-packages-on-a-wd-nas-running-os5&#34;&gt;Installing packages on a WD NAS running OS5&lt;/h2&gt;
&lt;p&gt;After the process has been completed, you will have available a .tar.gz file containing the binaries on the &lt;code&gt;packages/&lt;/code&gt; directory. Uncompress the .tar.gz and install the package through your WD MyCloud OS5 web UI.&lt;/p&gt;
&lt;p&gt;When you are done installing it, connect via SSH to your NAS. Then you should have available the &lt;code&gt;docker&lt;/code&gt; command. Beside this installation, you will also have a Portainer web UI available on this URL: http://IP_NAS:9000/&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it! Now you can &lt;a class=&#34;link&#34; href=&#34;https://hub.docker.com/search?type=image&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;explore the public&lt;/a&gt; Docker images and run whatever you want in your NAS. If you are thinking of running a PiHole instance, just hold on and read the next post.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Dual booting Arch Linux and Windows</title>
        <link>https://vectops.com/post/2022/dual-booting-arch-linux-and-windows/</link>
        <pubDate>Fri, 18 Feb 2022 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2022/dual-booting-arch-linux-and-windows/</guid>
        <description>&lt;img src="https://vectops.com/post/2022/dual-booting-arch-linux-and-windows/image.png" alt="Featured image of post Dual booting Arch Linux and Windows" /&gt;&lt;h2 id=&#34;assumptions&#34;&gt;Assumptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You are using &lt;a class=&#34;link&#34; href=&#34;https://www.freedesktop.org/software/systemd/man/systemd-boot.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;systemd-boot&lt;/a&gt; as UEFI manager, &lt;strong&gt;NOT&lt;/strong&gt; GRUB&lt;/li&gt;
&lt;li&gt;You run Arch Linux and Windows on the same machine (it doesn&amp;rsquo;t matter if they are installed on different partitions or separate physical disks)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;copy-efi-files&#34;&gt;Copy EFI files&lt;/h2&gt;
&lt;p&gt;First things first! Fire up your Arch, get a root shell and mount the Window&amp;rsquo;s EFI partition:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;mount /dev/sdXN /mnt # replace &amp;#39;sdXN&amp;#39; accordingly to your Windows&amp;#39; disk address
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Copy &lt;code&gt;/mnt/EFI/Microsoft&lt;/code&gt; folder inside the &lt;code&gt;/boot&lt;/code&gt; directory:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cp -r /mnt/EFI/Microsoft/ /boot/EFI/Microsoft/
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;add-windows-entry-to-systemd-boot&#34;&gt;Add Windows entry to systemd-boot&lt;/h2&gt;
&lt;p&gt;Add a new entry for Windows by creating a new &lt;code&gt;/boot/loader/entries/windows.conf&lt;/code&gt; file, containing:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;title   Windows 10
efi     /EFI/Microsoft/Boot/bootmgfw.efi
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Apply changes by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bootctl update
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Check that the new entry is showing correctly with:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bootctl list
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It should output something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Boot Loader Entries:
        title: Arch Linux
           id: arch.conf
       source: /boot/loader/entries/arch.conf
        linux: /vmlinuz-linux
       initrd: /initramfs-linux.img

        title: Windows 10
           id: windows.conf
       source: /boot/loader/entries/windows.conf
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once done, reboot your system and wait for systemd-boot to show up with both Arch and Windows 10 entries.&lt;/p&gt;
&lt;p&gt;Until we meet again!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Configure Mikrotik with OVH DynDNS</title>
        <link>https://vectops.com/post/2022/configure-mikrotik-with-ovh-dyndns/</link>
        <pubDate>Thu, 17 Feb 2022 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2022/configure-mikrotik-with-ovh-dyndns/</guid>
        <description>&lt;img src="https://vectops.com/post/2022/configure-mikrotik-with-ovh-dyndns/image.png" alt="Featured image of post Configure Mikrotik with OVH DynDNS" /&gt;&lt;p&gt;Say you want to connect to your homelab or local network via VPN. This is possible thanks to software like WireGuard or &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ZeroTier&lt;/a&gt; among other older solutions (OpenVPN, PPTP, L2TP)&amp;hellip;&lt;/p&gt;
&lt;p&gt;Right, but you know that, in order to connect through this kind of software you need the public IP address of the VPN server. If you run this software in your home you probably have a dynamic public IP address assigned, as most of the ISP providers offer out there. So there&amp;rsquo;s a problem.&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s pretend you can connect to your home&amp;rsquo;s VPN server no matter what IP address it has assigned, without paying an extra cent for it. Wouldn&amp;rsquo;t you love that? We do so too, and yep, there&amp;rsquo;s always a way.&lt;/p&gt;
&lt;p&gt;The only thing you need to achieve this is your own domain (there are other solutions that don&amp;rsquo;t involve having a custom domain, but as those are non self-hosteable or fully manageable we won&amp;rsquo;t be covering them on this post).&lt;/p&gt;
&lt;p&gt;With the DynDNS service you can update a type A DNS record when the record&amp;rsquo;s value changes, automatically, just by setting up a DynDNS client with a given timeout of your liking, say 5 minutes, 10 minutes, or 2 hours.&lt;/p&gt;
&lt;p&gt;In this post we&amp;rsquo;ll explain how to configure your Mikrotik to use the &lt;a class=&#34;link&#34; href=&#34;https://docs.ovh.com/us/en/domains/hosting_dynhost/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OVH DynDNS&lt;/a&gt; feature. Before starting, please follow the link and configure your domain in OVH panel just as the guide says.&lt;/p&gt;
&lt;h2 id=&#34;pre-checks&#34;&gt;Pre-checks&lt;/h2&gt;
&lt;p&gt;Now, we also said this is for Mikrotik router users, so to configure OVH DynDNS in your Mikrotik, this is all we need:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- OVH DynDNS user
- OVH DynDNS password
- OVH DynDNS host (subdomain)
- Mikrotik Interface where is the public ip
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To check your current&amp;rsquo;s Mikrotik public IP address, you can just issue this command via SSH or terminal web:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/ip address print
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It will list all the address configured on your Mikrotik. Just look for the one marked with the &lt;code&gt;D&lt;/code&gt; flag, that means &lt;code&gt;Dynamic&lt;/code&gt;, and check the name of &lt;code&gt;INTERFACE&lt;/code&gt; column. In case you have multiple dynamic addresses for whatever reason, look for the one matching the WAN interface.&lt;/p&gt;
&lt;h2 id=&#34;setting-up-the-dyndns-client-script&#34;&gt;Setting up the DynDNS client script&lt;/h2&gt;
&lt;p&gt;Now go to your Mikrotik web interface and browse to the &lt;code&gt;System -&amp;gt; Scripts&lt;/code&gt; menu, click on &lt;code&gt;Add new&lt;/code&gt;, and fill in the form fields as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- Name: ovh-ddns
- Policy: read, write, test
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For the &lt;code&gt;source&lt;/code&gt;, you can just copy &lt;a class=&#34;link&#34; href=&#34;https://github.com/vectops/scripts/blob/master/mikrotik/ddns/ddns_ovh.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this script&lt;/a&gt; we already tested and tried.&lt;/p&gt;
&lt;p&gt;After that click on &lt;code&gt;OK&lt;/code&gt;. You need to configure the script, just review the first line and add the configuration we did get before:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;:global ovhddnsuser &amp;#34;&amp;lt;OVH DynDNS USER&amp;gt;&amp;#34;
:global ovhddnspass &amp;#34;&amp;lt;OVH DynDNS PASS&amp;gt;&amp;#34;
:global theinterface &amp;#34;&amp;lt;INTERFACE THAT HAS YOUR PUBLIC IP&amp;gt;&amp;#34;
:global ovhddnshost &amp;#34;&amp;lt;OVHDynDNS HOSTNAME&amp;gt;&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can test the script just by applying and clicking on &lt;code&gt;Run Script&lt;/code&gt;. If everything is correct, you can see how, on your OVH panel, the DNS record configured with the public IP address has been  automatically updated. Maybe you want to use a &lt;code&gt;dig&lt;/code&gt; command to check it out. That&amp;rsquo;s up to you :)&lt;/p&gt;
&lt;h2 id=&#34;scheduling-the-dyndns-script&#34;&gt;Scheduling the DynDNS script&lt;/h2&gt;
&lt;p&gt;Right, but here&amp;rsquo;s the thing. At this point, if you don&amp;rsquo;t click on the &amp;ldquo;Run script&amp;rdquo; button, the script won&amp;rsquo;t trigger itself. Hopefully that is quite simple to fix: just configure a &lt;code&gt;Scheduler&lt;/code&gt; to run this script on a given time basis (say 10 minutes).&lt;/p&gt;
&lt;p&gt;To achive this, from your Mikrotik&amp;rsquo;s web UI, go to &lt;code&gt;System -&amp;gt; Scheduler&lt;/code&gt; menu, and click on &lt;code&gt;Add new&lt;/code&gt;, then just fill each field with the next details:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- Name: ovh-ddns
- Interval: 00:10:00
- Policy: read, write, test
- On event: /system script run ovh-ddns
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If for some reason you prefer setting this up through the cli, just run this command via SSH:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/system scheduler 
add interval=10m name=ovh-ddns on-event=&amp;#34;/system script run ovh-ddns&amp;#34; policy=read,write,test start-time=startup
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Remember that you can change the &lt;code&gt;interval&lt;/code&gt; accordingly to your fit your own needs.&lt;/p&gt;
&lt;p&gt;With that, we  can say we&amp;rsquo;re done! You have configured the OVH DynDNS on your Mikrotik, and now you can connect remotely to your home network by pointing your VPN configuration to your very own, automatically updated domain record.&lt;/p&gt;
&lt;p&gt;See you next time, don&amp;rsquo;t forget to &lt;strong&gt;share&lt;/strong&gt; &amp;amp; leave a comment!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Send multi-line Telegram messages using cURL</title>
        <link>https://vectops.com/post/2022/send-multiline-telegram-messages-using-curl/</link>
        <pubDate>Thu, 17 Feb 2022 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2022/send-multiline-telegram-messages-using-curl/</guid>
        <description>&lt;img src="https://vectops.com/post/2022/send-multiline-telegram-messages-using-curl/image.png" alt="Featured image of post Send multi-line Telegram messages using cURL" /&gt;&lt;p&gt;Not much context behind this one, I have been messing with stuff like this recently while doing some scripting and found it worth enough bringing it here. The solution is fairly simple, declare the needed variables:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;BOT_API_TOKEN=&amp;#39;&amp;lt;your bot token here&amp;gt;&amp;#39;
CHAT_ID=&amp;#39;&amp;lt;your chat ID here&amp;gt;&amp;#39;
MSG=&amp;#39;
This is a simple
multiline message
&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then just build the requests like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;curl --data &amp;#34;chat_id=${CHAT_ID}&amp;#34; --data-urlencode &amp;#34;text=${MSG}&amp;#34; &amp;#39;https://api.telegram.org/bot&amp;#39;${BOT_API_TOKEN}&amp;#39;/sendMessage&amp;#39;
                                 ------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Stay safe!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>3 ways to set up DynDNS with CloudFlare</title>
        <link>https://vectops.com/post/2022/3-ways-to-set-up-dyndns-with-cloudflare/</link>
        <pubDate>Wed, 16 Feb 2022 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2022/3-ways-to-set-up-dyndns-with-cloudflare/</guid>
        <description>&lt;img src="https://vectops.com/post/2022/3-ways-to-set-up-dyndns-with-cloudflare/image.png" alt="Featured image of post 3 ways to set up DynDNS with CloudFlare" /&gt;&lt;p&gt;Shout-out to all the selfhosters around there!&lt;/p&gt;
&lt;p&gt;Ever thought about running your own dynamic DNS system without relying on third-party providers? Well, me too, not going to lie.&lt;/p&gt;
&lt;p&gt;Luckily, if you own a domain and have a CloudFlare account, there&amp;rsquo;s a few things we can do about that. Today, we are bringing a bunch of different approaches to face this scenario, so let&amp;rsquo;s get down to it.&lt;/p&gt;
&lt;h2 id=&#34;general-assumptions&#34;&gt;General assumptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Have your own domain&lt;/li&gt;
&lt;li&gt;Set up your domain&amp;rsquo;s DNS with CloudFlare&lt;/li&gt;
&lt;li&gt;Have a CloudFlare account with DNS management capabilities&lt;/li&gt;
&lt;li&gt;This task works with IPv4 only (for now)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;classic-linux-cronjob-with-a-simple-curl&#34;&gt;Classic Linux cronjob with a simple cURL&lt;/h2&gt;
&lt;h3 id=&#34;specific-assumptions&#34;&gt;Specific assumptions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Have access to a Linux host (no root permissions needed)&lt;/li&gt;
&lt;li&gt;Have the &lt;code&gt;jq&lt;/code&gt; package installed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Being this one the simplest way to achieve our goal, just save the following script to a file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DNS_ZONE=&amp;#39;&amp;lt;your DNS zone ID here&amp;gt;&amp;#39;
DNS_RECORD=&amp;#39;&amp;lt;your DNS record ID here&amp;gt;&amp;#39;
AUTH_KEY=&amp;#39;&amp;lt;your CloudFlare API token here&amp;gt;&amp;#39;
EMAIL_ADDRESS=&amp;#39;&amp;lt;your CloudFlare&amp;#39;s email account here&amp;gt;&amp;#39;
DNS_RECORD_NAME=&amp;#34;\&amp;#34;&amp;lt;your.domain.tld here&amp;gt;\&amp;#34;&amp;#34;
CURRENT_IP_ADDRESS=&amp;#34;\&amp;#34;$(curl -s ip.me)\&amp;#34;&amp;#34;
CURRENT_DNS_VALUE=$(curl -sX GET &amp;#34;https://api.cloudflare.com/client/v4/zones/${DNS_ZONE}/dns_records/${DNS_RECORD}&amp;#34; -H &amp;#34;Content-Type:application/json&amp;#34; -H &amp;#34;X-Auth-Key:${AUTH_KEY}&amp;#34; -H &amp;#34;X-Auth-Email:${EMAIL_ADDRESS}&amp;#34; | jq &amp;#39;.result[&amp;#34;content&amp;#34;]&amp;#39;)

if [ ${CURRENT_DNS_VALUE} != ${CURRENT_IP_ADDRESS} ]; then
	curl -sX PUT &amp;#34;https://api.cloudflare.com/client/v4/zones/${DNS_ZONE}/dns_records/${DNS_RECORD}&amp;#34; -H &amp;#34;X-Auth-Email:${EMAIL_ADDRESS}&amp;#34; -H &amp;#34;X-Auth-Key:${AUTH_KEY}&amp;#34; -H &amp;#34;Content-Type:application/json&amp;#34; --data &amp;#39;{&amp;#34;type&amp;#34;:&amp;#34;A&amp;#34;,&amp;#34;name&amp;#34;:&amp;#39;${DNS_RECORD_NAME}&amp;#39;,&amp;#34;content&amp;#34;:&amp;#39;${CURRENT_IP_ADDRESS}&amp;#39;}&amp;#39; &amp;gt; /dev/null
fi
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s say we name this file as &lt;code&gt;cf-ddns.bash&lt;/code&gt; and save it to &lt;code&gt;/opt&lt;/code&gt;. Then make it executable:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;chmod +x /opt/cf-ddns.bash
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now let&amp;rsquo;s create a cron job that will run it every hour. Open the crontab editor with:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;crontab -e
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then simply add the following line:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;@hourly /bin/bash /opt/cf-ddns.bash
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is worth mentioning that the Linux machine where you are setting up this task must be behind the same NAT or on the same local network from where you want your DNS record to point to its public IP address.&lt;/p&gt;
&lt;h2 id=&#34;kubernetes-cronjob&#34;&gt;Kubernetes cronjob&lt;/h2&gt;
&lt;p&gt;Specific assumptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run a Kubernetes cluster (pretty obvious right?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why not!?&lt;/p&gt;
&lt;p&gt;If you are running a self-hosted Kubernetes cluster you can just go all the way down and make use of the native cronjob feature it provides.&lt;/p&gt;
&lt;p&gt;In this case you would only have to apply the following manifest, which creates a pod that will run the previous script we defined but it will be managed at a cluster level. (don&amp;rsquo;t forget to update the variable values according to yours!) :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cf-dyndns
  namespace: default
spec:
  schedule: &amp;#34;@hourly&amp;#34;
  successfulJobsHistoryLimit: 0
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cf-dyndns
            image: bash:latest
            imagePullPolicy: IfNotPresent
            restartPolicy: OnFailure
            command:
            - /usr/local/bin/bash
            - -c
            - apk add --update curl jq &amp;amp;&amp;gt;/dev/null ; DNS_ZONE=&amp;#39;&amp;lt;your DNS zone ID here&amp;gt;&amp;#39; DNS_RECORD=&amp;#39;&amp;lt;your DNS record ID here&amp;gt;&amp;#39; AUTH_KEY=&amp;#39;&amp;lt;your CloudFlare API token here&amp;gt;&amp;#39; EMAIL_ADDRESS=&amp;#39;&amp;lt;your CloudFlare account&amp;#39;s email here&amp;gt;&amp;#39; DNS_RECORD_NAME=&amp;#34;\&amp;#34;&amp;lt;your.domain.tld here&amp;gt;\&amp;#34;&amp;#34; CURRENT_IP_ADDRESS=&amp;#34;\&amp;#34;$(curl -s ip.me)\&amp;#34;&amp;#34; CURRENT_DNS_VALUE=$(curl -sX GET &amp;#34;https://api.cloudflare.com/client/v4/zones/${DNS_ZONE}/dns_records/${DNS_RECORD}&amp;#34; -H &amp;#34;Content-Type:application/json&amp;#34; -H &amp;#34;X-Auth-Key:${AUTH_KEY}&amp;#34; -H &amp;#34;X-Auth-Email:${EMAIL_ADDRESS}&amp;#34; | jq &amp;#39;.result[&amp;#34;content&amp;#34;]&amp;#39;); if [ ${CURRENT_DNS_VALUE} != ${CURRENT_IP_ADDRESS} ] ; then curl -sX PUT &amp;#34;https://api.cloudflare.com/client/v4/zones/${DNS_ZONE}/dns_records/${DNS_RECORD}&amp;#34; -H &amp;#34;X-Auth-Email:${EMAIL_ADDRESS}&amp;#34; -H &amp;#34;X-Auth-Key:${AUTH_KEY}&amp;#34; -H &amp;#34;Content-Type:application/json&amp;#34; --data &amp;#39;{&amp;#34;type&amp;#34;:&amp;#34;A&amp;#34;,&amp;#34;name&amp;#34;:&amp;#39;${DNS_RECORD_NAME}&amp;#39;,&amp;#34;content&amp;#34;:&amp;#39;${CURRENT_IP_ADDRESS}&amp;#39;}&amp;#39; &amp;gt; /dev/null; fi &amp;amp;&amp;amp; echo OK || echo ERROR
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can always check its status by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;kubectl get cronjob
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;drone-ci-pipeline&#34;&gt;Drone CI pipeline&lt;/h2&gt;
&lt;p&gt;Specific assumptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run a Drone CI instance&lt;/li&gt;
&lt;li&gt;A git repository to interact with through Drone&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another way to automate your DynDNS setup could be defining the task into a CI pipeline, and for that purpose this time we will be using Drone CI to do so.&lt;/p&gt;
&lt;p&gt;Although Drone provides a &lt;a class=&#34;link&#34; href=&#34;http://plugins.drone.io/jetrails/drone-cloudflare-dns/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;specific plugin&lt;/a&gt; to interact with CloudFlare&amp;rsquo;s API with ease, in this case we will be using a basic cURL image so we can get the DynDNS logic working in a pipeline inside our &lt;code&gt;.drone.yml&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;There is a very specific reason for this: as we are dealing with dynamic IP addresses that may change over time, there are &lt;a class=&#34;link&#34; href=&#34;https://discourse.drone.io/t/any-way-to-share-variables-between-steps/571/11&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;some limitations&lt;/a&gt; with Drone when it comes to sharing variable between steps in a pipeline.&lt;/p&gt;
&lt;p&gt;Thus the workaround we are proposing here to bypass that limitation consists of having the ability to assign to the &lt;code&gt;CURRENT_IP_ADDRESS&lt;/code&gt; variable a value at the very time the same pipeline&amp;rsquo;s step is running, not before.&lt;/p&gt;
&lt;p&gt;In other words, not inheriting the contents from a pipeline-level variable but to gather its value from inside the same container that will also handle its content to update our DNS record itself on the next command it runs:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;---
kind: pipeline
type: kubernetes # or &amp;#34;docker&amp;#34; if you don&amp;#39;t have a kubernetes runner configured!
name: cf-ddns

steps:
- name: Update DNS record
  image: curlimages/curl
  environment:
    AUTH_KEY:
      from_secret: cloudflare_token
    EMAIL_ADDRESS:
      from_secret: cloudflare_email
    DNS_ZONE_ID:
      from_secret: cloudflare_zone_id
    DNS_RECORD_ID:
      from_secret: cloudflare_record_id
    DNS_RECORD_NAME: &amp;lt;your.domain.tld here&amp;gt;
  commands:
    - export CURRENT_IP_ADDRESS=&amp;#34;$(curl -s ip.me)&amp;#34;
    - curl -sX PUT &amp;#34;https://api.cloudflare.com/client/v4/zones/$DNS_ZONE_ID/dns_records/$DNS_RECORD_ID&amp;#34; -H &amp;#34;X-Auth-Email:$EMAIL_ADDRESS&amp;#34; -H &amp;#34;X-Auth-Key:$AUTH_KEY&amp;#34; -H &amp;#34;Content-Type:application/json&amp;#34; --data &amp;#34;{\&amp;#34;type\&amp;#34;:\&amp;#34;A\&amp;#34;,\&amp;#34;name\&amp;#34;:\&amp;#34;$DNS_RECORD_NAME\&amp;#34;,\&amp;#34;content\&amp;#34;:\&amp;#34;$CURRENT_IP_ADDRESS\&amp;#34;}

trigger:
  event:
  - cron
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As you can see we are here using secrets to provide the multiple pipeline-level variable contents too, so don&amp;rsquo;t forget to create those secrets manually inside the repository options through the Drone web interface.&lt;/p&gt;
&lt;p&gt;Once that&amp;rsquo;s done, the last thing we need is to create the cron job that will trigger the pipeline. The cron job options are easily found in the web UI as well, but if you&amp;rsquo;d rather using the cli you can always run something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;drone cron add &amp;#34;myuser/myrepo&amp;#34; &amp;#34;cf-ddns&amp;#34; &amp;#39;@hourly&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Worth to point out, this last method gets rid of the original principle: &amp;ldquo;if the IP address has changed, then overwrite the DNS record with the current IP address&amp;rdquo; that was present on the first two examples, and just runs the HTTP request to overwrite the DNS record with whatever IP address it gathers each time, no matter if it is a new one or not.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for now. Wish it was useful!&lt;/p&gt;
&lt;p&gt;Cheers.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to set up a SMTP relay on your Proxmox node</title>
        <link>https://vectops.com/post/2022/how-to-set-up-a-smtp-relay-on-your-proxmox-node/</link>
        <pubDate>Tue, 15 Feb 2022 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2022/how-to-set-up-a-smtp-relay-on-your-proxmox-node/</guid>
        <description>&lt;img src="https://vectops.com/post/2022/how-to-set-up-a-smtp-relay-on-your-proxmox-node/image.png" alt="Featured image of post How to set up a SMTP relay on your Proxmox node" /&gt;&lt;p&gt;5-minute craft, specially useful for those self-hosted Proxmox users who seek sending e-mails to their remote inboxes directly from their nodes:&lt;/p&gt;
&lt;h2 id=&#34;assumptions&#34;&gt;Assumptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Your Proxmox run behind a NAT / is not directly accessible on the Internet so you find trouble sending native system e-mails by default&lt;/li&gt;
&lt;li&gt;You have an already existing e-mail address you would want to make your Proxmox host use to send mails to you&lt;/li&gt;
&lt;li&gt;The connection method to the &amp;ldquo;sender&amp;rdquo; e-mail address will be using password authentication&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;step-by-step-guide&#34;&gt;Step by step guide&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First off, install some dependencies. Run as root:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;apt-get update
apt-get install libsasl2-modules
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit the &lt;code&gt;/etc/postfix/main.cf&lt;/code&gt; file like this (replace relayhost&amp;rsquo;s key value to suit your needs):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# See /usr/share/postfix/main.cf.dist for a commented, more complete version

myhostname=pve.local

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA&amp;#39;s job.
append_dot_mydomain = no

# Uncomment the next line to generate &amp;#34;delayed mail&amp;#34; warnings
#delay_warning_time = 4h

alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
#mydestination = $myhostname, localhost.$mydomain, localhost
mynetworks = 127.0.0.0/8
inet_interfaces = loopback-only
recipient_delimiter = +

sender_canonical_classes = envelope_sender, header_sender
sender_canonical_maps =  regexp:/etc/postfix/sender_canonical_maps
smtp_header_checks = regexp:/etc/postfix/header_check

relayhost = &amp;lt;smtp.mailserver.com&amp;gt;:&amp;lt;smtp_server_port&amp;gt;
smtp_use_tls = yes
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_tls_wrappermode = yes
smtp_tls_security_level = encrypt
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit or create the &lt;code&gt;/etc/postfix/sasl_passwd&lt;/code&gt; file, that will contain the following line (remember to place your own values there):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;smtp.mailserver.com&amp;gt;:&amp;lt;smtp_server_port&amp;gt;    &amp;lt;sender&amp;gt;@&amp;lt;mailserver.com&amp;gt;:&amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change file permissions with:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;chmod 600 /etc/postfix/sasl_passwd
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;postmap /etc/postfix/sasl_passwd
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit or create the file &lt;code&gt;/etc/postfix/sender_canonical_maps&lt;/code&gt; containing:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/.+/    &amp;lt;sender&amp;gt;@&amp;lt;mailserver.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit or create the file &lt;code&gt;/etc/postfix/header_check&lt;/code&gt; with the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/From:.*/ REPLACE From: &amp;lt;sender&amp;gt;@&amp;lt;mailserver.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply changes by restarting Postfix service:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;systemctl restart postfix.service
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that&amp;rsquo;s it. You can always manually test if it works by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;echo &amp;#34;This is a test e-mail&amp;#34; | mail -s &amp;#34;Testing&amp;#34; &amp;lt;receiver&amp;gt;@&amp;lt;mailserver.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See you next time!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Terraform 1 and Proxmox; working as it should</title>
        <link>https://vectops.com/post/2021/terraform-1-and-proxmox-working-as-it-should/</link>
        <pubDate>Sat, 12 Jun 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/terraform-1-and-proxmox-working-as-it-should/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/terraform-1-and-proxmox-working-as-it-should/image.png" alt="Featured image of post Terraform 1 and Proxmox; working as it should" /&gt;&lt;p&gt;And work it should&amp;hellip;&lt;/p&gt;
&lt;p&gt;A while ago we typed up a detailed article about using Terraform to provision VMs on proxmox nodes, you can find it &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2020/provision-proxmox-vms-with-terraform-quick-and-easy/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That article was dependant on some versions that are no longer supported and can and will cause problems eventually.&lt;/p&gt;
&lt;p&gt;So we updated the dependencies, versions and did some definition refactoring in order to allow the process to work with the latest versions at the time of writing this article.&lt;/p&gt;
&lt;p&gt;Current versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Terraform 1.0&lt;/li&gt;
&lt;li&gt;Proxmox 6.4&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;hooray-terraform-registry&#34;&gt;Hooray Terraform Registry!&lt;/h2&gt;
&lt;p&gt;The Terraform Registry finally has Telmate&amp;rsquo;s Proxmox provisioner hosted on its platform so we can define it on the &lt;code&gt;.tf&lt;/code&gt; file and forget about it.&lt;/p&gt;
&lt;p&gt;You can find the module here: &lt;a class=&#34;link&#34; href=&#34;http://https://registry.terraform.io/providers/Telmate/proxmox/latest/docs&#34;  title=&#34;Telmate&amp;#39;s Proxmox Module&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Telmate&amp;rsquo;s Proxmox Module&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This allows us to happily say you no longer need to worry about installing the module manually and working out the kinks on Go&amp;rsquo;s installation methods.&lt;/p&gt;
&lt;h2 id=&#34;terraform-definitions&#34;&gt;Terraform Definitions&lt;/h2&gt;
&lt;p&gt;There are some changes that need to be made to the old &lt;code&gt;main.tf&lt;/code&gt; definition file, the first one is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;terraform&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;required_providers&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxmox &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      source &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Telmate/proxmox&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.7.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Afterwards, we need change some other entries that are no longer supported:&lt;/p&gt;
&lt;h3 id=&#34;disk-definitions&#34;&gt;Disk definitions&lt;/h3&gt;
&lt;p&gt;These definitions no longer apply as they are properly detected by the module:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    id              &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    storage_type    &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;lvm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    iothread        &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;network-definitions&#34;&gt;Network definitions&lt;/h3&gt;
&lt;p&gt;The same happens to some of the network definitions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-hcl&#34; data-lang=&#34;hcl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    id              &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;github-repo&#34;&gt;Github repo&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ve uploaded the updates to Github with the updates you can also check out the commit history to see the changes yourself:&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/galdorork/tf-Proxmox&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/galdorork/tf-Proxmox&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, we&amp;rsquo;ve updated the docker image we&amp;rsquo;ve use to run pipelines that need Terraform and (maybe) Terragrunt (wink, wink):&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/galdorork/terragrunt-proxmox-module&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/galdorork/terragrunt-proxmox-module&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;We&amp;rsquo;ll try to keep updating old posts to work on newer versions, but this one really needed some love.&lt;/p&gt;
&lt;p&gt;BAIIII :)&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to fking use Git; like a pro</title>
        <link>https://vectops.com/post/2021/how-to-fking-use-git-like-a-pro/</link>
        <pubDate>Fri, 11 Jun 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/how-to-fking-use-git-like-a-pro/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/how-to-fking-use-git-like-a-pro/image.png" alt="Featured image of post How to fking use Git; like a pro" /&gt;&lt;p&gt;TLDR; Just read this:&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://git-scm.com/book/en/v2&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://git-scm.com/book/en/v2&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Dear Devs,&lt;/p&gt;
&lt;p&gt;Some tasks are easily performed using a GUI, some are not, some are more convenient. However, not all tooling is available all the time.&lt;/p&gt;
&lt;p&gt;I recently had an issue with a version control interface that was failing, throwing 500 errors everywhere, but guess what? the git services were still working.&lt;/p&gt;
&lt;p&gt;Its not only your responsibility, its your duty as a corporate developer to KNOW how to use git without all the bells and whistles of a graphical interface.&lt;/p&gt;
&lt;p&gt;Using simple commands such as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git branch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git merge
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git commit --amend -m 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Is extremely helpful and extremely important to know when you want to work fast.&lt;/p&gt;
&lt;p&gt;Take this into account on your current/next job offerings.&lt;/p&gt;
&lt;p&gt;PD: yes, this is a rant.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Build your own git server on WD MyCloud EX2</title>
        <link>https://vectops.com/post/2021/build-your-own-git-server-on-wd-mycloud-ex2/</link>
        <pubDate>Sun, 04 Apr 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/build-your-own-git-server-on-wd-mycloud-ex2/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/build-your-own-git-server-on-wd-mycloud-ex2/image.png" alt="Featured image of post Build your own git server on WD MyCloud EX2" /&gt;&lt;p&gt;If you want to build your own server to create and manage a private repositories and if you have a WD MyCloud EX2, this post may be helpful to do it in a painless manner.&lt;/p&gt;
&lt;p&gt;Fist of all, you need to enable the SSH access on your server, and install the &lt;a class=&#34;link&#34; href=&#34;https://github.com/Entware/Entware/wiki&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Entware software&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After you have installed the Entware software, connect via SSH to your NAS and do the magic:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ln -s /opt/bin/opkg /usr/bin/opkg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;opkg install git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes! Now you have installed the git software in your NAS.&lt;/p&gt;
&lt;p&gt;Now we should make some syslinks to do git clone, upload, etc without errors, just execute these commands:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ln -s /opt/bin/git /usr/bin/git
ln -s /opt/bin/git-receive-pack /usr/bin/git-receive-pack
ln -s /opt/bin/git-shell /usr/bin/git-shell
ln -s /opt/bin/git-upload-archive /usr/bin/git-upload-archive
ln -s /opt/bin/git-upload-pack /usr/bin/git-upload-pack
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally, you can use the WD MyCloud as a git server.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>First steps with git server; the right way</title>
        <link>https://vectops.com/post/2021/first-steps-with-git-server-the-right-way/</link>
        <pubDate>Sun, 04 Apr 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/first-steps-with-git-server-the-right-way/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/first-steps-with-git-server-the-right-way/image.png" alt="Featured image of post First steps with git server; the right way" /&gt;&lt;p&gt;Yay! What&amp;rsquo;s up? On this article we will summarize the first steps everyone should follow when it comes to deploying your own Git server. Don&amp;rsquo;t have any yet? Read &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2021/build-your-own-git-server-on-wd-mycloud-ex2/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Keep in mind that any host with the Git software installed and Internet connection can be a Git server, you just need to configure a SSH connection to be able to use it.&lt;/p&gt;
&lt;p&gt;You can install Git on your Raspberry Pi, a virtual machine on your server, on the cloud&amp;hellip; Whatever you want, just install it!&lt;/p&gt;
&lt;h2 id=&#34;remote-server&#34;&gt;Remote server&lt;/h2&gt;
&lt;p&gt;Ok, right. Now you have the Git software installed, but you need to create the repository first. How to do it? Very simple, just go to the directory where you want to set up the repository (remember! It needs to be accessible through SSH):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# change directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd /home/cooluser/repositories/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# make new directory with .git extension&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir coolrepo.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# come inside&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd coolrepo.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# run the init command&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git init --bare
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;local-machine&#34;&gt;Local machine&lt;/h2&gt;
&lt;p&gt;Create the directory where you want to have this repository&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir coolrepo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd coolrepo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, you need to prepare this directory for git:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch README.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git commit -m &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;First commit&amp;#34;&lt;/span&gt; -a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git remote add origin ssh://sshuser@server_ip:/home/cooluser/repositories/coolrepo.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git push origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et voila, you have your own repository with full functionality.&lt;/p&gt;
&lt;p&gt;In the future, you can do a &lt;code&gt;git clone&lt;/code&gt; like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone sshuser@server_ip:/home/cooluser/repositories/coolrepo.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cheers!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Nagios-like monitoring Linux system services within Grafana</title>
        <link>https://vectops.com/post/2021/nagios-like-monitoring-linux-system-services-within-grafana/</link>
        <pubDate>Mon, 29 Mar 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/nagios-like-monitoring-linux-system-services-within-grafana/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/nagios-like-monitoring-linux-system-services-within-grafana/image.png" alt="Featured image of post Nagios-like monitoring Linux system services within Grafana" /&gt;&lt;h2 id=&#34;assumptions&#34;&gt;Assumptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You have a Telegraf service up and running on the same host you want to monitor system services from&lt;/li&gt;
&lt;li&gt;You have a InfluxDB instance up and running, receiving data from the previously mentioned Telegraf service&lt;/li&gt;
&lt;li&gt;You have a Grafana instance up and running, making it possible to visualize data from InfluxDB&lt;/li&gt;
&lt;li&gt;In this example, the Nginx web server will be monitored&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;install-sysdweb&#34;&gt;Install Sysdweb&lt;/h2&gt;
&lt;p&gt;Follow the installation instructions provided in the repository&amp;rsquo;s &lt;a class=&#34;link&#34; href=&#34;https://github.com/ogarcia/sysdweb/blob/master/README.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;README file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then save the &lt;a class=&#34;link&#34; href=&#34;https://raw.githubusercontent.com/ogarcia/sysdweb/master/sysdweb.conf&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;sysdweb.conf&lt;/a&gt; file to &lt;code&gt;/etc/sysdweb/sysdweb.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo mkdir /etc/sysdweb
sudo wget https://raw.githubusercontent.com/ogarcia/sysdweb/master/sysdweb.conf -O /etc/sysdweb/sysdweb.conf
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;create-a-systemd-service-for-sysdweb&#34;&gt;Create a Systemd service for Sysdweb&lt;/h2&gt;
&lt;p&gt;Save the following to &lt;code&gt;/lib/systemd/system/sysdweb.service&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[Unit]
Description=Control systemd services through Web or REST API
Documentation=https://github.com/ogarcia/sysdweb
After=network.target
Requires=dbus.socket

[Service]
ExecStart=/usr/local/bin/sysdweb -c /etc/sysdweb/sysdweb.conf
Restart=on-failure

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Start the new Sysdweb service:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl enable --now sysdweb
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Check if the service is working:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ curl -u &amp;#39;sysdweb:supersecretpassword&amp;#39; 127.0.0.1:10080/api/v1/ngx/status
{&amp;#34;status&amp;#34;: &amp;#34;active&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;create-a-user-for-sysdweb&#34;&gt;Create a user for Sysdweb&lt;/h2&gt;
&lt;p&gt;There are multiple ways of interacting with Sysdweb (just review the config file), but this time I will be using the system user method:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo adduser sysdweb
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;prepare-telegraf&#34;&gt;Prepare Telegraf&lt;/h2&gt;
&lt;p&gt;Add the following block to &lt;code&gt;/etc/telegraf/telegraf.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[[inputs.http_response]]
  urls = [&amp;#34;http://localhost:10080/api/v1/ngx/status&amp;#34;]
  response_timeout = &amp;#34;5s&amp;#34;
  username = &amp;#34;sysdweb&amp;#34;
  password = &amp;#34;supersecretpassword&amp;#34;
  response_string_match = &amp;#34;{\&amp;#34;status\&amp;#34;: \&amp;#34;active\&amp;#34;}&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Apply changes to the Telegraf configuration:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo systemctl restart telegraf
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;let-grafana-do-the-rest&#34;&gt;Let Grafana do the rest&lt;/h2&gt;
&lt;p&gt;After adding a new panel and selecting InfluxDB as data source, with such a simple query you will see a &amp;ldquo;Success&amp;rdquo; string (by picking &lt;code&gt;Stat&lt;/code&gt; as visualization type) in your panel:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;SELECT result_type FROM http_response WHERE server =~ /ngx/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At this point, by adding a &lt;a class=&#34;link&#34; href=&#34;https://grafana.com/docs/grafana/latest/panels/field-options/standard-field-options/#value-mapping&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;value mapping&lt;/a&gt; from the string &amp;ldquo;success&amp;rdquo; to &amp;ldquo;UP&amp;rdquo;, you will then be able to monitor the current status of the Nginx service from your host at a glance.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2021/nagios-like-monitoring-linux-system-services-within-grafana/attachment1.png&#34;
	width=&#34;300&#34;
	height=&#34;213&#34;
	srcset=&#34;https://vectops.com/post/2021/nagios-like-monitoring-linux-system-services-within-grafana/attachment1_huea718dab1993c534b951e7e71e009d09_13883_480x0_resize_box_3.png 480w, https://vectops.com/post/2021/nagios-like-monitoring-linux-system-services-within-grafana/attachment1_huea718dab1993c534b951e7e71e009d09_13883_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;140&#34;
		data-flex-basis=&#34;338px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;In the same way, by adding another value mapping from the string &amp;ldquo;response_string_mismatch&amp;rdquo; to &amp;ldquo;KO&amp;rdquo;, it will become pretty clear that something wrong is taking place when Nginx goes down.&lt;/p&gt;
&lt;h2 id=&#34;final-notes&#34;&gt;Final notes&lt;/h2&gt;
&lt;p&gt;I know there is a Telegraf plugin called &lt;a class=&#34;link&#34; href=&#34;https://github.com/influxdata/telegraf/blob/release-1.18/plugins/inputs/systemd_units/README.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;inputs.systemd_units&lt;/a&gt; that could directly cover the need described in this article, but finding out that Sysdweb could be effectively used for the same purpose was hella fun.&lt;/p&gt;
&lt;p&gt;Finally, shout out to &lt;a class=&#34;link&#34; href=&#34;https://github.com/ogarcia&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Óscar García&lt;/a&gt; for bringing this useful tool to life!&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Install Nextcloud with Apache2 on Debian 10</title>
        <link>https://vectops.com/post/2021/install-nextcloud-with-apache2-on-debian-10/</link>
        <pubDate>Sat, 30 Jan 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/install-nextcloud-with-apache2-on-debian-10/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/install-nextcloud-with-apache2-on-debian-10/image.png" alt="Featured image of post Install Nextcloud with Apache2 on Debian 10" /&gt;&lt;h2 id=&#34;pre-requisites&#34;&gt;Pre-requisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Have your own domain and be able to configure DNS accordingly&lt;/li&gt;
&lt;li&gt;Have access to a Debian host with root privileges&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;installing-dependencies&#34;&gt;Installing dependencies&lt;/h2&gt;
&lt;p&gt;Make sure to not miss this step:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt update
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt install apache2 libapache2-mod-php php php-gd php-curl php-zip php-dom php-xml php-simplexml php-mbstring php-apcu php-mysql php-intl php-bcmath php-gmp php-imagick unzip mariadb-server certbot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;configure-database&#34;&gt;Configure database&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mysql &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;u root &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;p
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;DATABASE&lt;/span&gt; your_database;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;GRANT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ALL&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; your_database.&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TO&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;your_user&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt; IDENTIFIED &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;your_password&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FLUSH &lt;span style=&#34;color:#66d9ef&#34;&gt;PRIVILEGES&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;download-and-set-up-nextcloud&#34;&gt;Download and set up Nextcloud&lt;/h2&gt;
&lt;p&gt;Run the following commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://download.nextcloud.com/server/releases/latest.zip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unzip latest.zip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv nextcloud/* /var/www/html/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv nextcloud/.* /var/www/html/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rmdir nextcloud
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown -R www-data. /var/www/html/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Edit &lt;code&gt;/var/www/html/config/config.php&lt;/code&gt; file and:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Declare your public access domain:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;trusted_domains&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;your.domain.tld&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ),
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Disable new user registration:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;simpleSignUpLink.shown&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Configure APCu as cache memory system:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;memcache.local&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\\OC\\Memcache\\APCu&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;set-up-apache2&#34;&gt;Set up Apache2&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Make it run at startup:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl enable --now apache2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Enable HTTPS traffic:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a2enmod ssl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Issue a new Let&amp;rsquo;s Encrypt SSL certificate:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;certbot certonly -d your.domain.tld
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;Set up Apache virtual host:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a2ensite your.domain.tld
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s a &lt;code&gt;/etc/apache2/sites-available/your.domain.tld.conf&lt;/code&gt; file sample:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;VirtualHost *:80&amp;gt;
  ServerName your.domain.tld
  Redirect permanent &amp;#34;/&amp;#34; &amp;#34;https://your.domain.tld/&amp;#34;
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost *:443&amp;gt;
  ServerName your.domain.tld

  # Example SSL certificate path for Let&amp;#39;s Encrypt
  SSLEngine On
  SSLCertificateFile /etc/letsencrypt/live/your.domain.tld/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/your.domain.tld/privkey.pem

  DocumentRoot /var/www/html

  CustomLog /var/log/apache2/your.domain.tld-access.log combined
  ErrorLog /var/log/apache2/your.domain.tld-error.log
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Apply changes by running:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apachectl configtest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl reload apache2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At this point you should be able to open &lt;code&gt;https://your.domain.tld&lt;/code&gt; at any web browser and follow the web installation wizard.&lt;/p&gt;
&lt;h2 id=&#34;fix-security-warnings-on-a-fresh-installation&#34;&gt;Fix security warnings on a fresh installation&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add HSTS header&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Edit &lt;code&gt;/etc/apache2/sites-available/your_vhost.conf&lt;/code&gt; and within HTTPS VirtualHost block add:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Header always set Strict-Transport-Security: &amp;#34;max-age&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;63072000; includeSubDomains; preload&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;&lt;strong&gt;Increase default PHP memory_limit value&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Edit &lt;code&gt;/etc/php/7.3/apache2/php.ini&lt;/code&gt; and set:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;memory_limit&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;512M # At least&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;&lt;strong&gt;Disable PHP output_buffering&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Edit &lt;code&gt;/etc/php/7.3/apache2/php.ini&lt;/code&gt; and set:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;output_buffering&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;off&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;&lt;strong&gt;Fix missing database indices&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Run these commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod +x /var/www/html/occ
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo -u www-data /usr/bin/php /var/www/html/occ db:add-missing-indices
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;5&#34;&gt;
&lt;li&gt;&lt;strong&gt;Fix webdav URLs&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Edit &lt;code&gt;/etc/apache2/sites-available/your_vhost.conf&lt;/code&gt; and within the HTTPS VirtualHost add:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;RewriteEngine On&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;RewriteRule ^/\.well-known/carddav https://your.domain.tld/remote.php/dav/ [R&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;301,L]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;RewriteRule ^/\.well-known/caldav https://your.domain.tld/remote.php/dav/ [R&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;301,L]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Apply all these last changes by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;systemctl restart apache2
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        <item>
        <title>Monitoring an OpenWRT router with Grafana and InfluxDB</title>
        <link>https://vectops.com/post/2021/monitoring-an-openwrt-router-with-grafana-and-influxdb/</link>
        <pubDate>Sat, 30 Jan 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/monitoring-an-openwrt-router-with-grafana-and-influxdb/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/monitoring-an-openwrt-router-with-grafana-and-influxdb/image.png" alt="Featured image of post Monitoring an OpenWRT router with Grafana and InfluxDB" /&gt;&lt;h2 id=&#34;assumptions&#34;&gt;Assumptions&lt;/h2&gt;
&lt;p&gt;You have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Debian 10 VM running InfluxDB (v1.7.10+) and Grafana (v6.7.2+) services&lt;/li&gt;
&lt;li&gt;Network appliance running OpenWRT (v18.06+)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;install-and-configure-influxdb-inside-a-vm&#34;&gt;Install and configure InfluxDB (inside a VM)&lt;/h2&gt;
&lt;p&gt;Install needed package and dependencies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add -
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;deb https://repos.influxdata.com/debian buster stable&amp;#34;&lt;/span&gt; | sudo tee /etc/apt/sources.list.d/influxdb.list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install -y influxdb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: if you receive the following error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;E: gnupg, gnupg2 and gnupg1 &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; not seem to be installed, but one of them is required &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; this operation
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You need to install &amp;lsquo;gpg&amp;rsquo; package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install gpg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once InfluxDB is installed, edit &lt;code&gt;/etc/influxdb/influxdb.conf&lt;/code&gt; file to enable Collectd plugin (locate and uncomment the following lines):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[[collectd]]
   enabled = true
   bind-address = &amp;#34;:25826&amp;#34;
   database = &amp;#34;${YOUR_DB_NAME}&amp;#34;
   retention-policy = &amp;#34;&amp;#34;
   typesdb = &amp;#34;/usr/local/share/collectd/types.db&amp;#34;
   security-level = &amp;#34;none&amp;#34;
   batch-size = 5000
   batch-pending = 10
   batch-timeout = &amp;#34;10s&amp;#34;
   read-buffer = 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Create &amp;rsquo;types.db&amp;rsquo; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo mkdir -p /usr/local/share/collectd/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo wget -O /usr/local/share/collectd/types.db https://raw.githubusercontent.com/CactusProjects/openwrt_influxdb/master/types.db
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Start and enable the InfluxDB service on startup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl enable --now influxdb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Create Influx database:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;influx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;DATABASE&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;${&lt;/span&gt;YOUR_DB_NAME&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Assign a one-month based retention policy to the database:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;DROP&lt;/span&gt; RETENTION POLICY &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;autogen&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;${YOUR_DB_NAME}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; RETENTION POLICY &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;one_month&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;${YOUR_DB_NAME}&amp;#34;&lt;/span&gt; DURATION &lt;span style=&#34;color:#ae81ff&#34;&gt;730&lt;/span&gt;h0m REPLICATION &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;DEFAULT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;install-and-configure-grafana-inside-a-vm&#34;&gt;Install and configure Grafana (inside a VM)&lt;/h2&gt;
&lt;p&gt;Install needed package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo add-apt-repository &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;deb https://packages.grafana.com/oss/deb stable main&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install grafana
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; if you receive the following error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bash: add-apt-repository: command not found
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You need to install &amp;lsquo;software-properties-common&amp;rsquo; package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt install software-properties-common
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to run Grafana service on port 80, edit the &lt;code&gt;/etc/grafana/grafana.ini&lt;/code&gt; file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;http_port = 80
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After that, you need to run this command to allow running Grafana service as non-root (the default user is &amp;lsquo;grafana&amp;rsquo;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo setcap &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;cap_net_bind_service=+ep&amp;#39;&lt;/span&gt; /usr/sbin/grafana-server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Start and enable the Grafana service on startup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl enable --now grafana-server.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;install-and-configure-collectd-in-openwrt&#34;&gt;Install and configure collectd (in OpenWRT)&lt;/h2&gt;
&lt;p&gt;Install needed packages:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo opkg install collectd collectd-mod-cpu collectd-mod-dns collectd-mod-interface collectd-mod-iwinfo collectd-mod-load collectd-mod-logfile collectd-mod-memory collectd-mod-network collectd-mod-openvpn collectd-mod-ping collectd-mod-rrdtool collectd-mod-thermal collectd-mod-uptime collectd-mod-wireless
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Edit &lt;code&gt;/etc/collectd/collectd.conf&lt;/code&gt; to configure the service:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;BaseDir &amp;#34;/var/run/collectd&amp;#34;
Include &amp;#34;/etc/collectd/conf.d&amp;#34;
PIDFile &amp;#34;/var/run/collectd.pid&amp;#34;
PluginDir &amp;#34;/usr/lib/collectd&amp;#34;
TypesDB &amp;#34;/usr/share/collectd/types.db&amp;#34;
Interval 10
ReadThreads 2
Hostname &amp;#34;${YOUR_OPENWRT_HOSTNAME_HERE}&amp;#34;

LoadPlugin ping
&amp;lt;Plugin ping&amp;gt;
        TTL 127
        Interval 10
        Host &amp;#34;1.1.1.1&amp;#34;
&amp;lt;/Plugin&amp;gt;

LoadPlugin memory
LoadPlugin cpu
LoadPlugin load
LoadPlugin uptime

LoadPlugin interface
&amp;lt;Plugin interface&amp;gt;
        IgnoreSelected false
        Interface &amp;#34;YOUR_INTERFACE_1_NAME_HERE&amp;#34; # i.e. &amp;#34;pppoe-wan&amp;#34;
        Interface &amp;#34;YOUR_INTERFACE_2_NAME_HERE&amp;#34; # i.e. &amp;#34;br-lan&amp;#34;
        Interface &amp;#34;YOUR_INTERFACE_3_NAME_HERE&amp;#34;
&amp;lt;/Plugin&amp;gt;

LoadPlugin dns
&amp;lt;Plugin dns&amp;gt;
        Interface &amp;#34;YOUR_INTERFACE_1_NAME_HERE&amp;#34; # i.e. &amp;#34;pppoe-wan&amp;#34;
        Interface &amp;#34;YOUR_INTERFACE_2_NAME_HERE&amp;#34; # i.e. &amp;#34;br-lan&amp;#34;
        Interface &amp;#34;YOUR_INTERFACE_3_NAME_HERE&amp;#34;
        IgnoreSource &amp;#34;127.0.0.1&amp;#34;
&amp;lt;/Plugin&amp;gt;

LoadPlugin thermal
&amp;lt;Plugin thermal&amp;gt;
        IgnoreSelected false
&amp;lt;/Plugin&amp;gt;

LoadPlugin network
&amp;lt;Plugin network&amp;gt;
        Server &amp;#34;${YOUR_INFLUXDB_SERVER_ADDRESS_HERE}&amp;#34; &amp;#34;25826&amp;#34;
        CacheFlush 86400
        Forward false
&amp;lt;/Plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Start and enable Collectd service on startup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo /etc/init.d/collectd start
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo /etc/init.d/collectd enable
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;testing-it-out&#34;&gt;Testing it out&lt;/h2&gt;
&lt;p&gt;Once OpenWRT is configured, check if it&amp;rsquo;s working. SSH to your Grafana/InfluxDB server and issue:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;influx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;${&lt;/span&gt;YOUR_DB_NAME&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;show&lt;/span&gt; measurements
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; uptime_value
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And verify if every 10 seconds the records are getting updated.&lt;/p&gt;
&lt;h2 id=&#34;grafana-dashboard&#34;&gt;Grafana dashboard&lt;/h2&gt;
&lt;p&gt;Login to your Grafana webUI and follow this steps:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CREATE NEW DATA SOURCE&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to &lt;code&gt;https://${YOUR_GRAFANA_SERVER_ADDRESS}/datasources&lt;/code&gt; and click on &amp;ldquo;Add&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Change &amp;ldquo;Name&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Fill &amp;ldquo;URL&amp;rdquo; field under HTTP settings&lt;/li&gt;
&lt;li&gt;Fill &amp;ldquo;Database&amp;rdquo; field and set &amp;ldquo;HTTP method&amp;rdquo; to GET under &amp;ldquo;InfluxDB Details&amp;rdquo; settings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;IMPORT AN EXISTING DASHBOARD&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Place your mouse over the &lt;code&gt;+&lt;/code&gt; sign at the left side of screen&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;Import&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;Grafana.com Dashboard&lt;/code&gt; field, type &amp;ldquo;&lt;a class=&#34;link&#34; href=&#34;https://grafana.com/grafana/dashboards/11858&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;11858&lt;/a&gt;&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Click on the &lt;code&gt;Load&lt;/code&gt; button&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are things on that dashboard that won&amp;rsquo;t be working by default right after you create it, such as  the Wi-Fi related stuff and maybe other elements depending on your setup.&lt;/p&gt;
&lt;p&gt;At this point, it&amp;rsquo;s time for you to verify the queries definition and modifying it to suit your needs.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Keep your machines updated with GitLab; Ansible inside</title>
        <link>https://vectops.com/post/2021/keep-your-machines-updated-with-gitlab-ansible-inside/</link>
        <pubDate>Mon, 25 Jan 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/keep-your-machines-updated-with-gitlab-ansible-inside/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/keep-your-machines-updated-with-gitlab-ansible-inside/image.png" alt="Featured image of post Keep your machines updated with GitLab; Ansible inside" /&gt;&lt;p&gt;Some of the more mundane tasks involving a server, or a bunch of servers, is to run repeatable tasks on each one of them.&lt;/p&gt;
&lt;p&gt;Most sysadmins nowadays have some sort of automation in place to control this, however not everyone has the time to keep their machines updated, for example.&lt;/p&gt;
&lt;p&gt;So, this article is going to be written as an absolute starting point to what can be achieved using pipeline scheduling and control for system automation.&lt;/p&gt;
&lt;h3 id=&#34;how-does-a-pipeline-work-in-gitlab&#34;&gt;How does a pipeline work in GitLab&lt;/h3&gt;
&lt;p&gt;According to GitLab&amp;rsquo;s documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Pipelines are the top-level component of continuous integration, delivery, and deployment.&lt;/p&gt;
&lt;p&gt;Pipelines comprise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jobs, which define &lt;em&gt;what&lt;/em&gt; to do. For example, jobs that compile or test code.&lt;/li&gt;
&lt;li&gt;Stages, which define &lt;em&gt;when&lt;/em&gt; to run the jobs. For example, stages that run tests after stages that compile the code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jobs are executed by runners. Multiple jobs in the same stage are executed in parallel, if there are enough concurrent runners.&lt;/p&gt;
&lt;p&gt;If &lt;em&gt;all&lt;/em&gt; jobs in a stage succeed, the pipeline moves on to the next stage.&lt;/p&gt;
&lt;p&gt;If &lt;em&gt;any&lt;/em&gt; job in a stage fails, the next stage is not (usually) executed and the pipeline ends early.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So basically all we need to start automating things is a runner.&lt;/p&gt;
&lt;p&gt;Luckily we&amp;rsquo;ve released an article that covers this, for example using the Kubernetes executor &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2021/kubernetes-executor-on-gitlab-not-a-gitlab-managed-cluster/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;getting-started-with-our-repo&#34;&gt;Getting started with our repo&lt;/h3&gt;
&lt;p&gt;Since we&amp;rsquo;re using a pipeline, we&amp;rsquo;re also going to be needing a repository to save and commit our work.&lt;/p&gt;
&lt;p&gt;Go on your GitLab instance and create a new repo. In this case we&amp;rsquo;re going to be calling it: &lt;code&gt;vm-update&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Once the repository has been created we need to create a folder on it, lets call it ansible:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir ansible
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Within that folder, we&amp;rsquo;re going to need a file called &lt;code&gt;hosts&lt;/code&gt; and a folder called &lt;code&gt;debian&lt;/code&gt;. Take into account that you can have several playbooks depending on the distro type, such as CentOS.&lt;/p&gt;
&lt;p&gt;Actually, lets create a &lt;code&gt;centos&lt;/code&gt; folder too. You should end up with the following files on the repo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ansible/debian/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ansible/centos/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ansible-hosts&#34;&gt;Ansible Hosts&lt;/h3&gt;
&lt;p&gt;For ansible to know where to connect to it needs a hosts file, create that file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vi ansible/hosts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And add some machine descriptors to it (update with the IPs for your infra):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;debian]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;120.0.120.200&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# gitlab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;120.0.120.201&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# k3s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;centos]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;120.0.120.202&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# webserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ansible-playbooks&#34;&gt;Ansible Playbooks&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;re going to need some playbooks for this to work.&lt;/p&gt;
&lt;h4 id=&#34;debian&#34;&gt;Debian&lt;/h4&gt;
&lt;p&gt;Lets say you have a Debian type OS (Debian, Ubuntu, etc.) that needs to be updated, then create the following file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vi ansible/debian/playbook.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Within that file place the following contents:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;hosts&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;debian &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;tasks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Update repositories and upgrade packages&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;become&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;apt&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;update_cache&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;upgrade&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;force_apt_get&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;allow_unauthenticated&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;autoremove&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;autoclean&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;install_recommends&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;only_upgrade&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;tags&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;upgrade&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;centos&#34;&gt;CentOS&lt;/h4&gt;
&lt;p&gt;As for the CentOS based machines we can use this (more complete) playbook:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vi ansible/debian/playbook.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the following contents&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;hosts&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;centos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;tasks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;check packages for updates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;shell&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;yum list updates | awk &amp;#39;f;/Updated Packages/{f=1;}&amp;#39; | awk &amp;#39;{ print $1 }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;changed_when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;updates.stdout_lines | length &amp;gt; 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;args&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;warn&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;register&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;updates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;display count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;debug&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;msg&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Found {{ updates.stdout_lines | length }} packages to be updated:\n\n{{ updates.stdout }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;updates.stdout_lines | length &amp;gt; 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;block&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;install updates using yum&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;yum&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;state&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;install yum-utils&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;yum-utils&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;check if reboot is required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;shell&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;needs-restarting -r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;failed_when&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;register&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;reboot_required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;changed_when&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;updates.stdout_lines | length &amp;gt; 0 and reboot_required.rc != 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;block&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;reboot the server if required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;shell&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;sleep 3; reboot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ignore_errors&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;changed_when&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;async&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;poll&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;wait for server to come back after reboot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;wait_for_connection&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;delay&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;register&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;reboot_result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;reboot time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;debug&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;msg&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;The system rebooted in {{ reboot_result.elapsed }} seconds.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you should have the following files on your repo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ansible/debian/playbook.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ansible/centos/playbook.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ansible/hosts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ssh-connections&#34;&gt;SSH Connections&lt;/h3&gt;
&lt;p&gt;For this to work the GitLab runner is going to need a key pair to be able to connect to the servers.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not going to go on much detail about it on this article but you can create a folder on the repo to have those keys:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir ssh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And put both the private and the public key there.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NOTE: I know this can be way more secure, lets save it for another article.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;gitlab-pipeline&#34;&gt;GitLab Pipeline&lt;/h3&gt;
&lt;p&gt;For a GitLab pipeline to work you&amp;rsquo;re going to need a &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vi .gitlab-ci.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And add the following contents:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;mullnerz/ansible-playbook &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;stages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;update_centos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;update_debian&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;update_debian&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;update_debian&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ANSIBLE_HOST_KEY_CHECKING&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ANSIBLE_SSH_PRIVATE_KEY_FILE&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ssh/id_rsa&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;chmod 600 ssh/id_rsa&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;ansible-playbook ansible/debian/playbook.yml -i ansible/hosts --tag upgrade -u vectops --private-key=ssh/id_rsa&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;update_centos&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;update_cento&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ANSIBLE_HOST_KEY_CHECKING&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ANSIBLE_SSH_PRIVATE_KEY_FILE&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ssh/id_rsa&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;chmod 600 ssh/id_rsa&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;ansible-playbook ansible/debian/playbook.yml -i ansible/hosts --tag upgrade -u vectops --private-key=ssh/id_rsa&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On this YML you can see we&amp;rsquo;re running a pre-setup Docker image that has all of the needed ansible tools to be used and the command that connects to the ansible hosts uses the &lt;code&gt;vectops&lt;/code&gt; user.&lt;/p&gt;
&lt;p&gt;Adjust it to your setup.&lt;/p&gt;
&lt;h4 id=&#34;gitlab-scheduling&#34;&gt;GitLab Scheduling&lt;/h4&gt;
&lt;p&gt;The whole idea is for this pipeline to run automatically on a scheduled day.&lt;/p&gt;
&lt;p&gt;For this you can take advantage of GitLab&amp;rsquo;s job scheduler, on your GitLab web interface go on:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;CI/CD &amp;gt; Schedules&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Then click on the &lt;code&gt;New Schedule&lt;/code&gt; and set up the properties and save the schedule.&lt;/p&gt;
&lt;p&gt;Et voilà! You can now let the pipeline do it&amp;rsquo;s job and keep your machines updated.&lt;/p&gt;
&lt;p&gt;Now, I know that some critical infrastructure can&amp;rsquo;t be updated this way because of some package updates can break stuff, however validation steps can be added between stages so the job is still automated but can be checked by a human before the upgrade happens.&lt;/p&gt;
&lt;p&gt;Or maybe modify the pipeline to just update security patches that shouldn&amp;rsquo;t break anything.&lt;/p&gt;
&lt;p&gt;This is just a starting point, it can be scaled or modified to suit your needs.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Kubernetes executor on GitLab (not a GitLab managed cluster)</title>
        <link>https://vectops.com/post/2021/kubernetes-executor-on-gitlab-not-a-gitlab-managed-cluster/</link>
        <pubDate>Mon, 25 Jan 2021 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2021/kubernetes-executor-on-gitlab-not-a-gitlab-managed-cluster/</guid>
        <description>&lt;img src="https://vectops.com/post/2021/kubernetes-executor-on-gitlab-not-a-gitlab-managed-cluster/image.png" alt="Featured image of post Kubernetes executor on GitLab (not a GitLab managed cluster)" /&gt;&lt;p&gt;Some of us that work with Gitlab, regardless on where we work or the role you thrive in (development, sysadmins, etc.), benefit hugely from GitLab&amp;rsquo;s ability to streamline and automate a deployment process.&lt;/p&gt;
&lt;p&gt;Whether it&amp;rsquo;s a process that deploys an application or some tedious time-consuming process that sysadmins have to perform, can be automated.&lt;/p&gt;
&lt;p&gt;Unfortunately not everyone or every company can afford to use the enterprise version of Gitlab. This is especially the case for Gitlab instances that run on homelabs.&lt;/p&gt;
&lt;p&gt;Usually this doesn&amp;rsquo;t affect the functionality of the platform, however Gitlab has a really awesome toolset that allows it to manage a kubernetes&amp;rsquo; deployment that&amp;rsquo;s included with the enterprise version.&lt;/p&gt;
&lt;p&gt;We can work around this with the use of a Gitlab Kubernetes executor.&lt;/p&gt;
&lt;h3 id=&#34;enter-the-kubernetes-executor&#34;&gt;Enter the Kubernetes Executor&lt;/h3&gt;
&lt;p&gt;The Kubernetes executor is basically what it&amp;rsquo;s name states, it&amp;rsquo;s pod that&amp;rsquo;s deployed on a kubernetes namespace that can run processes.&lt;/p&gt;
&lt;p&gt;What kind of processes? Anything that can be done with any other executor can be done by this executor.&lt;/p&gt;
&lt;p&gt;Once deployed it&amp;rsquo;s a pretty hands-off experience. If you need to update it, you can update it with no downtime and the main benefit it has is that, since it&amp;rsquo;s not run on a specific VM or HW you don&amp;rsquo;t have another machine to add to your infrastructure and maintain. This last one can become overwhelming after a while (100 machines is easy to maintain, try 4000).&lt;/p&gt;
&lt;h3 id=&#34;requirements&#34;&gt;Requirements&lt;/h3&gt;
&lt;p&gt;This kind of executor needs some stuff to work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A GitLab Instance&lt;/li&gt;
&lt;li&gt;A Kubernetes instance, doesn&amp;rsquo;t matter which type, it can be a full fledged k8s cluster, OpenShift cluster or even k3s.&lt;/li&gt;
&lt;li&gt;A namespace on the kubernetes cluster.&lt;/li&gt;
&lt;li&gt;Access to create secrets on the namespace.&lt;/li&gt;
&lt;li&gt;kubectl and helm3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s basically all you need to do this.&lt;/p&gt;
&lt;h3 id=&#34;setup&#34;&gt;Setup&lt;/h3&gt;
&lt;h4 id=&#34;kubernetes-side&#34;&gt;Kubernetes&amp;rsquo; side&lt;/h4&gt;
&lt;h5 id=&#34;namespace&#34;&gt;Namespace&lt;/h5&gt;
&lt;p&gt;You&amp;rsquo;re going to need a namespace to install the executor, in this case we&amp;rsquo;re going with &lt;code&gt;gitlab-executor&lt;/code&gt; (make sure you can access the kubernetes instance from your machine):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl create namespace gitlab-executor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h5 id=&#34;gitlab-registration-token&#34;&gt;GitLab registration Token&lt;/h5&gt;
&lt;p&gt;The registration token can be acquired from your GitLab instance, either from a full instance perspective, a GitLab-wide admin.&lt;/p&gt;
&lt;p&gt;Or you can just define it for a project group or a single project.&lt;/p&gt;
&lt;p&gt;The steps are pretty much the same.&lt;/p&gt;
&lt;p&gt;For a project:&lt;/p&gt;
&lt;p&gt;​	&lt;em&gt;Go on the project settings -&amp;gt; CI/CD -&amp;gt; Runners -&amp;gt; Expand&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And you&amp;rsquo;ll see the registration token.&lt;/p&gt;
&lt;h5 id=&#34;helm-chart&#34;&gt;Helm Chart&lt;/h5&gt;
&lt;p&gt;Once the namespace is created you need to set up Helm, start by adding the GitLab repo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;helm repo add gitlab https://charts.gitlab.io
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then update the repo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Afterwards, you need a &lt;code&gt;values.yaml&lt;/code&gt; file, which can be found &lt;!-- raw HTML omitted --&gt;here&lt;!-- raw HTML omitted --&gt;. From that file you&amp;rsquo;re going to need to focus on the following entries (to begin with):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;gitlabUrl&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;https://gitlab.company.com/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;runnerRegistrationToken&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;XXXXXXXXXXXXXXXXX&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;runners&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu:16.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;privileged&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There&amp;rsquo;s a lot more entries on that file, you can decide which ones do you need, right now we&amp;rsquo;re focusing on the &lt;code&gt;gitlabUrl&lt;/code&gt;, the registration token and whether the container is going to run on privileged mode (yes, this can run DockerInDocker).&lt;/p&gt;
&lt;p&gt;Save the &lt;code&gt;values.yaml&lt;/code&gt; on your local machine and then run the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;helm install gitlab-runner -f values.yaml -n gitlab-executor gitlab/gitlab-runner
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure you have the proper permissions to deploy an application on that namespace (although, if you&amp;rsquo;ve already created the namespace you should already have those.)&lt;/p&gt;
&lt;h4 id=&#34;gitlabs-side&#34;&gt;GitLab&amp;rsquo;s side&lt;/h4&gt;
&lt;p&gt;There&amp;rsquo;s not much to do on GitLab&amp;rsquo;s side, just wait until the runner is registered and you can use it.&lt;/p&gt;
&lt;h3 id=&#34;testing-our-shiny-new-runner&#34;&gt;Testing our shiny new runner&lt;/h3&gt;
&lt;p&gt;We&amp;rsquo;re going to perform an easy test,just a hello world to check that the runner runs a task.&lt;/p&gt;
&lt;p&gt;For this you need a repo with the following files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.gitlab-ci.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes, just one.&lt;/p&gt;
&lt;p&gt;Within that &lt;code&gt;gitlab-ci.yml&lt;/code&gt; file you need the following contents (we&amp;rsquo;re borrowing from the official GitLab wiki, the main article is &lt;!-- raw HTML omitted --&gt;here&lt;!-- raw HTML omitted --&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;build-job&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;Hello, $GITLAB_USER_LOGIN!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;test-job1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;This job tests something&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;test-job2&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;This job tests something, but takes more time than test-job1.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;After the echo commands complete, it runs the sleep command for 20 seconds&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;which simulates a test that runs 20 seconds longer than test-job1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;sleep 20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;deploy-prod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;This job deploys something from the $CI_COMMIT_BRANCH branch.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After you commit and push the file to your project repo, the pipeline should run automatically and show the &lt;code&gt;echo&lt;/code&gt; results.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Using Icinga2 and Ansible: one playbook to monitor them all!</title>
        <link>https://vectops.com/post/2020/using-icinga2-and-ansible-one-playbook-to-monitor-them-all/</link>
        <pubDate>Sat, 24 Oct 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/using-icinga2-and-ansible-one-playbook-to-monitor-them-all/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/using-icinga2-and-ansible-one-playbook-to-monitor-them-all/image.png" alt="Featured image of post Using Icinga2 and Ansible: one playbook to monitor them all!" /&gt;&lt;p&gt;Have you ever thought of way to monitor new hosts without having to spend much time adding the NRPE plugins, command check definitions and other custom configurations manually on each of them?&lt;/p&gt;
&lt;p&gt;No problem, I have just faced that very same situation. Also, got tired of it pretty quickly. So how should we solve it?&lt;/p&gt;
&lt;p&gt;The solution we are providing here is pretty simple: apply an Icinga2 monitoring template to a brand new, fresh installed machine thanks to Ansible.&lt;/p&gt;
&lt;p&gt;NOTICE: for the examples provided we will be using Debian-like distros, so if yours is different you may have to adapt those affected parts, such as package manager related commands, specific Ansible plugins and so on.&lt;/p&gt;
&lt;h1 id=&#34;installing-dependencies&#34;&gt;Installing dependencies&lt;/h1&gt;
&lt;p&gt;The only things we need to configure on our machine are the SSH keys (so we can apply our playbooks normally), and to install the &lt;code&gt;sudo&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;For the SSH keys you can copy your public key with the following command:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ssh-copy-id -i path/to/your/key ${YOUR_USERNAME}@${YOUR_NEW_MACHINE}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In case you don&amp;rsquo;t have a key set up, you can create one as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ssh-keygen -t rsa
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then fill in the information the shell is going to prompt for. After that, from inside your new machine, run the following as root (or using sudo):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;apt-get update
apt-get install sudo -y
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When the package is installed, be sure to run &lt;code&gt;visudo&lt;/code&gt; and configure the user you will be using properly, otherwise the Ansible steps may fail. If you are using &lt;code&gt;root&lt;/code&gt; user directly (which I don&amp;rsquo;t recommend, &lt;em&gt;insert security disclaimer here&lt;/em&gt;) these last steps are not needed at all.&lt;/p&gt;
&lt;p&gt;Due to time constraints we&amp;rsquo;re not going to cover the Icinga2 installation on this article.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re going to assume you&amp;rsquo;ve already set it up and it&amp;rsquo;s running properly.&lt;/p&gt;
&lt;h1 id=&#34;setting-up-ansible&#34;&gt;Setting up Ansible&lt;/h1&gt;
&lt;p&gt;From the machine you&amp;rsquo;re going to be using for the Ansible deployments, you will need to have a directory structure such as this one:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;|-- inventories
|   `-- my_machines
|       `-- hosts
|-- playbooks
    |-- icinga_add_host.yml
    |-- install_nrpe_client.yml
    |-- files
        |-- nrpe
            |-- nrpe.cfg.template
            `-- nrpe_local.cfg.template
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this configuration, two playbooks are set up, the first one &lt;code&gt;install_nrpe_client.yml&lt;/code&gt; has the following content:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;---
- hosts: &amp;#34;{{ host }}&amp;#34;

  tasks:

    - name: &amp;#34;Install NRPE client and monitoring plugins&amp;#34;
      apt:
        pkg: [&amp;#34;nagios-nrpe-server&amp;#34;, &amp;#34;monitoring-plugins&amp;#34;, &amp;#34;nagios-plugins-contrib&amp;#34;]
        force_apt_get: yes
        update_cache: yes
        state: present
      tags: install

    - name: Copy NRPE service core files
      copy: src={{ item.src }} dest={{ item.dest }}
      with_items:
        - { src: &amp;#39;nrpe/nrpe_local.cfg.template&amp;#39;, dest: &amp;#39;/etc/nagios/nrpe_local.cfg&amp;#39; }
        - { src: &amp;#39;nrpe/nrpe.cfg.template&amp;#39;, dest: &amp;#39;/etc/nagios/nrpe.cfg&amp;#39; }
      tags: copy

    - name: Restart nagios-nrpe-server service
      service: name=nagios-nrpe-server state=restarted
      tags: restart
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The playbook just goes on the machine and performs the needed package set up to run the monitoring services for that machine.&lt;/p&gt;
&lt;p&gt;The second one, &lt;code&gt;icinga_add_host.yml&lt;/code&gt;, has the following content:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;---
- hosts: ${YOUR_ICINGA2_SERVER}

  tasks:

    - name: &amp;#34;Add host to Icinga&amp;#34;
      copy:
        dest: /etc/icinga2/conf.d/homelab/{{ host }}.conf
        content: |
          object Host &amp;#34;{{ host }}&amp;#34; {
            import &amp;#34;generic-host&amp;#34;
            address = &amp;#34;{{ host }}&amp;#34;
            vars.os = &amp;#34;Linux&amp;#34;
            vars.disks[&amp;#34;disk /&amp;#34;] = {
              disk_partitions = &amp;#34;/&amp;#34;
            }
            vars.notification[&amp;#34;mail&amp;#34;] = {
              groups = [ &amp;#34;icingaadmins&amp;#34; ]
            }
          }
      tags: add-host-template

    - name: &amp;#34;Restart Icinga2 service&amp;#34;
      service: name=icinga2 state=restarted
      tags: restart
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that we&amp;rsquo;re using the default way of adding a host in Icinga2, of course this can be further extended by adding multiple and new commands and services.&lt;/p&gt;
&lt;p&gt;Finally, there is the &lt;code&gt;inventories/my_machines/hosts&lt;/code&gt; file, which should only have one line for now:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;new_machine_hostname
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Keep this in mind for later.&lt;/p&gt;
&lt;h1 id=&#34;setting-up-icinga2&#34;&gt;Setting up Icinga2&lt;/h1&gt;
&lt;p&gt;As you may have already seen, there are two other files in this setup, both templates are for the Icinga2 service configuration itself and command check definitions.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;The file &lt;code&gt;nrpe.cfg.template&lt;/code&gt;, is almost a clone of the default &lt;code&gt;nrpe.cfg&lt;/code&gt;, as the only meaningful change to get things working is the &lt;code&gt;allowed_hosts&lt;/code&gt; variable.&lt;/p&gt;
&lt;p&gt;Where you must declare the address or FQDN of your Icinga2 server, so you can leave it intact except for that one bit (seriously don&amp;rsquo;t forget this).&lt;/p&gt;
&lt;p&gt;The rest is just matter of custom preferences.&lt;/p&gt;
&lt;p&gt;Also, the &lt;code&gt;nrpe_local.cfg.template&lt;/code&gt; is the default file I chose to host all my custom command checks. However you can get things working too just by copy-pasting the ones declared in the default &lt;code&gt;nrpe.cfg&lt;/code&gt; file or directly uncommenting them right there.&lt;/p&gt;
&lt;p&gt;If you choose to copy them, it would end up looking something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;command[check_users]=/usr/lib/nagios/plugins/check_users -w 5 -c 10
command[check_load]=/usr/lib/nagios/plugins/check_load -r -w .15,.10,.05 -c .30,.25,.20
command[check_hda1]=/usr/lib/nagios/plugins/check_disk -w 20% -c 10% -p /dev/hda1
command[check_zombie_procs]=/usr/lib/nagios/plugins/check_procs -w 5 -c 10 -s Z
command[check_total_procs]=/usr/lib/nagios/plugins/check_procs -w 150 -c 200

### MISC SYSTEM METRICS ###
command[check_users]=/usr/lib/nagios/plugins/check_users $ARG1$
command[check_load]=/usr/lib/nagios/plugins/check_load $ARG1$
command[check_disk]=/usr/lib/nagios/plugins/check_disk $ARG1$
command[check_swap]=/usr/lib/nagios/plugins/check_swap $ARG1$
command[check_cpu_stats]=/usr/lib/nagios/plugins/check_cpu_stats.sh $ARG1$
command[check_mem]=/usr/lib/nagios/plugins/custom_check_mem -n $ARG1$

### GENERIC SERVICES ###
command[check_init_service]=sudo /usr/lib/nagios/plugins/check_init_service $ARG1$
command[check_services]=/usr/lib/nagios/plugins/check_services -p $ARG1$

### SYSTEM UPDATES ###
command[check_yum]=/usr/lib/nagios/plugins/check_yum
command[check_apt]=/usr/lib/nagios/plugins/check_apt

### PROCESSES ###
command[check_all_procs]=/usr/lib/nagios/plugins/custom_check_procs
command[check_procs]=/usr/lib/nagios/plugins/check_procs $ARG1$

### OPEN FILES ###
command[check_open_files]=/usr/lib/nagios/plugins/check_open_files.pl $ARG1$

### NETWORK CONNECTIONS ###
command[check_netstat]=/usr/lib/nagios/plugins/check_netstat.pl -p $ARG1$ $ARG2$
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;running-the-playbooks&#34;&gt;Running the playbooks&lt;/h1&gt;
&lt;p&gt;At this point everything should be ready to start monitoring your new machine, so the way you would do this is by running the following commands from your super amazing laptop:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ansible-playbook -i ansible/inventories/my_hosts/hosts ansible/playbooks/nrpe_client.yml --extra-vars &amp;#34;host=${new_machine_hostname}&amp;#34;
ansible-playbook -i ansible/inventories/my_hosts/hosts ansible/playbooks/icinga_add_host.yml --extra-vars &amp;#34;host=${new_machine_hostname}&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;IMPORTANT: The &amp;ldquo;new_machine_hostname&amp;rdquo; value must coincide with the one set in the hosts inventory file (I told you to keep that in mind for a reason!), else it will return an error message.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;As you can see, it can be pretty easy to monitor new hosts with Icinga2 when it comes to get things done by using automation software, and this is just a slight example.&lt;/p&gt;
&lt;p&gt;Hope you find it useful!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Run your own bandwidth speed test server thanks to iPerf</title>
        <link>https://vectops.com/post/2020/run-your-own-bandwidth-speed-test-server-thanks-to-iperf/</link>
        <pubDate>Mon, 19 Oct 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/run-your-own-bandwidth-speed-test-server-thanks-to-iperf/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/run-your-own-bandwidth-speed-test-server-thanks-to-iperf/image.png" alt="Featured image of post Run your own bandwidth speed test server thanks to iPerf" /&gt;&lt;p&gt;When it comes to this kind of analysis, iPerf is one of the first options I think of to perform network tests.&lt;/p&gt;
&lt;h1 id=&#34;installing-iperf&#34;&gt;Installing iPerf&lt;/h1&gt;
&lt;p&gt;So, that said let&amp;rsquo;s just get hands on. This example relies on running a Linux machine wherever you want to host your speed test instance. Thus the only thing you just need is to install the &lt;a class=&#34;link&#34; href=&#34;https://iperf.fr/iperf-download.php&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;iperf3&lt;/a&gt; tool.&lt;/p&gt;
&lt;p&gt;Then the next step would be running the speed test instance, which can be achieved by running this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/usr/bin/iperf3 -s -p 5500
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Where &lt;code&gt;-s&lt;/code&gt; means &amp;ldquo;run in server mode&amp;rdquo; and &lt;code&gt;-p 5500&lt;/code&gt; means &amp;ldquo;in port 5500&amp;rdquo; (this is the one by default, you can change it to whatever you want). If the server is running behind a NAT firewall don&amp;rsquo;t forget to set the proper port-forwarding rules.&lt;/p&gt;
&lt;h1 id=&#34;running-the-server&#34;&gt;Running the server&lt;/h1&gt;
&lt;p&gt;At this point, the only thing you have to do to start measuring your speed connection against this iPerf instance is running this command:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;iperf3 -c ${IPERF\_SERVER\_ADDRESS} -p 5500 -P 8 -t 30
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Where &lt;code&gt;-c&lt;/code&gt; points the server to connect to, &lt;code&gt;-P&lt;/code&gt; the number of parallel client streams to run and &lt;code&gt;-t&lt;/code&gt; the ammount of time (in seconds) we want it to keep running.&lt;/p&gt;
&lt;p&gt;You should get an output similar to this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  32.4 MBytes  27.2 Mbits/sec  444             sender
[  5]   0.00-10.00  sec  29.3 MBytes  24.6 Mbits/sec                  receiver
(...)
[SUM]   0.00-10.00  sec   276 MBytes   232 Mbits/sec  2663             sender
[SUM]   0.00-10.00  sec   259 MBytes   217 Mbits/sec                  receiver
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;set-it-up-as-a-systemd-service&#34;&gt;Set it up as a Systemd service&lt;/h1&gt;
&lt;p&gt;Also, if you are running Systemd you can create a script file to make it run as a service on your system. For this, simply create the file `/etc/systemd/system/speedtest.service` and copy the following content into it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[Unit]
Description=iPerf3 speed test server
After=network.target

[Service]
ExecStart=/usr/bin/iperf3 -s -p 5500

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once created just reload Systemd&amp;rsquo;s configuration and start it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo systemctl daemon-reload sudo systemctl start speedtest.service
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Lastly, if you wish to get your iPerf3 instance running on system startup go enable the new service:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo systemctl enable speedtest.service
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And that&amp;rsquo;s it, now you can start measuring your bandwidth speed test against your own server.&lt;/p&gt;
&lt;p&gt;See you next time!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Install Docker on Debian 10 with no effort</title>
        <link>https://vectops.com/post/2020/install-docker-on-debian-10/</link>
        <pubDate>Sun, 21 Jun 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/install-docker-on-debian-10/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/install-docker-on-debian-10/image.png" alt="Featured image of post Install Docker on Debian 10 with no effort" /&gt;&lt;p&gt;Recently, I have been dealing with the deployment of multiple Debian servers which I had to configure in a pretty tailored way and also running Docker was a must. As I was performing the deployments by hand, after a few times finishing the Docker service installation I reached the conclusion that things needed to speed up.&lt;/p&gt;
&lt;p&gt;That said, the quickest way that I found to do it was as easy as parsing every command pointed in installation process (which you can check in the &lt;!-- raw HTML omitted --&gt;official Docker documentation&lt;!-- raw HTML omitted --&gt;) directly into the machines through a snippet that I posted on Gist to make it available for anyone interested on it.&lt;/p&gt;
&lt;p&gt;So yeah, as you can guess this is another one-liner shot focused to save some time. So if you are thinking of installing Docker in a Debian system, just try:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;curl -s https://code.nullbyte.es/docker-apt | sudo bash
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Of course, I encourage you to check the content of whatever you run before doing so, for many reasons. In this case, note that by default I am installing the latest available version of &lt;code&gt;docker-ce&lt;/code&gt; and also &lt;code&gt;docker-compose&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When the installation of Docker finishes, you can check if it is active on your machine by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo systemctl status docker
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After that, you should see something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2020-06-20 15:42:47 CEST; 33s ago
     Docs: https://docs.docker.com
 Main PID: 3769 (dockerd)
    Tasks: 12
   Memory: 47.9M
   CGroup: /system.slice/docker.service
           └─3769 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that there is also an official script from Docker to provide an automated installation located at &lt;a class=&#34;link&#34; href=&#34;https://github.com/docker/docker-install&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this GitHub repository&lt;/a&gt;, so you just can follow any method you prefer, but keep in mind that, &lt;a class=&#34;link&#34; href=&#34;https://docs.docker.com/engine/install/debian/#installation-methods&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;as the Docker team points&lt;/a&gt;, this method is only recommended in &lt;strong&gt;TESTING AND DEVELOPMENT ENVIRONMENTS&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s all, now you can start containerizing whatever you want! I hope you find this as useful as I have. As always, any feedback is welcome.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Provision Proxmox VMs with Terraform, quick and easy</title>
        <link>https://vectops.com/post/2020/provision-proxmox-vms-with-terraform-quick-and-easy/</link>
        <pubDate>Thu, 07 May 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/provision-proxmox-vms-with-terraform-quick-and-easy/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/provision-proxmox-vms-with-terraform-quick-and-easy/image.png" alt="Featured image of post Provision Proxmox VMs with Terraform, quick and easy" /&gt;&lt;hr&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update: We&amp;rsquo;ve uploaded an update to this article using the Terraform 1.0 release. You can find it here: &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2021/terraform-1-and-proxmox-working-as-it-should/&#34;  title=&#34;Terraform 1 and Proxmox; working as it should&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Terraform 1 and Proxmox; working as it should&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;p&gt;Previously, I wrote an article about how to provision Proxmox VMs using Ansible, you can find it &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2020/provision-proxmox-vms-with-ansible-quick-and-easy/&#34;  title=&#34;here&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That article went into the workings of a functional Ansible script that provisions Proxmox virtual machines in an easy and streamlined way that can be integrated into many other implementations.&lt;/p&gt;
&lt;p&gt;This time, we&amp;rsquo;re going to delve into another way to do so, using Terraform.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Terraform allows us to streamline the process even further by the use of plugins in much the same way as Ansible would.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Both of these methods depend on a template to be created beforehand. You could, of course, just create an empty virtual machine and it would work, but this means you&amp;rsquo;ll have to perform the OS installation manually, where&amp;rsquo;s the fun in that?&lt;/p&gt;
&lt;p&gt;Within Proxmox, the VM creation method (using the GUI) is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Create VM -&amp;gt; Present operating system ISO to VM -&amp;gt; perform installation -&amp;gt; Enjoy&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That process takes too long, it&amp;rsquo;s manual (eww) and honestly, it&amp;rsquo;s just boring. Especially when you have to create multiple VMs.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create a template to be used by Terraform.&lt;/p&gt;
&lt;h2 id=&#34;building-atemplate&#34;&gt;Building a template&lt;/h2&gt;
&lt;p&gt;Within Proxmox, you can choose two ways (usually) to create a VM, from the GUI or from the Terminal console. For this example, you should use a bare minimum machine with the minimal resources allocated to it. This way it can easily be scaled in the future.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re going to need a VM with the following resources:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1 Core
1 GB RAM
10 GB HDD
1 Network Interface
1 Cloud-init drive
1 EFI Disk&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some of the properties noted above will have to be added after the VM creation process.&lt;/p&gt;
&lt;h3 id=&#34;manually-creating-thetemplate&#34;&gt;Manually creating the template&lt;/h3&gt;
&lt;p&gt;The process for creating a VM within the Proxmox GUI has been explained countless times on the internet. For the sake of completeness let&amp;rsquo;s mention the basic process:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Click on create VM&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Input a name for the VM, you can check for it to start at boot, your call. Click next&lt;/li&gt;
&lt;li&gt;Select an ISO for the install and select the type and version of the OS that will be installed. Click next&lt;/li&gt;
&lt;li&gt;Check the &amp;ldquo;Qemu Agent&amp;rdquo; option, you&amp;rsquo;ll use this later on. Click next&lt;/li&gt;
&lt;li&gt;Select the Disk size, in this case 10 GB. You can also change some of the storage emulation options for this drive, we won&amp;rsquo;t go into that on this example. Click next&lt;/li&gt;
&lt;li&gt;Select how many Cores you want to use for the VM, in this case 1 Core. Click next&lt;/li&gt;
&lt;li&gt;Input the amount of memory for the VM, in this case 1024 MB. I advice using the Ballooning device so you can save up memory resources on the node and to be able to oversell the resources, just like a CPU. Note that if the memory is being actually used by the VM, it can&amp;rsquo;t be used by other VMs unless it&amp;rsquo;s the exact same memory block, enter KSM (Kernel Shared Memory) I won&amp;rsquo;t go into detail about KSM just know that it&amp;rsquo;s awesome. Select the Minimum memory for the Ballooning Device, in this case 256 MB. Click next&lt;/li&gt;
&lt;li&gt;If you don&amp;rsquo;t have any custom network configurations on the node you can just Click next here. If you do, make sure that the configuration matches what you need.&lt;/li&gt;
&lt;li&gt;Confirm the VM setup and click on &amp;ldquo;Finish&amp;rdquo;** Don&amp;rsquo;t start the VM yet**&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After the VM is created, you&amp;rsquo;re going to need to change a few things on the VM. As you can see from the above steps, the Cloud-init drive wasn&amp;rsquo;t added. Select the VM on the left and click on Hardware then Add and finally on Cloud-Init Drive and select the storage where it will reside.&lt;/p&gt;
&lt;p&gt;Afterward, edit the BIOS (double click on the BIOS entry on the Hardware tab) and select OVMF (UEFI)&lt;/p&gt;
&lt;p&gt;Finally, the EFI Disk, it&amp;rsquo;s the same process as with the Cloudinit-drive, but now select EFI Disk and select the storage where it will reside. It won&amp;rsquo;t let you create the drive before setting up the BIOS on the second step.&lt;/p&gt;
&lt;p&gt;Inside the VM&amp;rsquo;s terminal, you can go ahead and install the Cloud-Init&amp;rsquo;s packages so the VM is ready for use with:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;apt-get install cloud-init -y&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;using-debians-official-image-for-cloud-init&#34;&gt;Using Debian&amp;rsquo;s official image for Cloud-init.&lt;/h3&gt;
&lt;p&gt;If the manual process above takes too long and you don&amp;rsquo;t want to spend as much time with the OS installation, you can just download a pre-configured image from Debian&amp;rsquo;s official repositories.&lt;/p&gt;
&lt;p&gt;From the proxmox node&amp;rsquo;s terminal run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://cdimage.debian.org/cdimage/openstack/current-10/debian-10-openstack-amd64.qcow2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since we described the process through the GUI on the manual installation, let&amp;rsquo;s go for the CLI way of doing things, the commands are as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm create &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -name debian-10-template -memory &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt; -net0 virtio,bridge&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;vmbr0 -cores &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; -sockets &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; -cpu cputype&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;kvm64 -description &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Debian 10 cloud image&amp;#34;&lt;/span&gt; -kvm &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; -numa &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm importdisk &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; debian-10-openstack-amd64.qcow2 lvm-thin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -scsihw virtio-scsi-pci -virtio0 lvm-thin:vm-9000-disk-1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -serial0 socket
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -boot c -bootdisk virtio0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -agent &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -hotplug disk,network,usb,memory,cpu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -vcpus &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -vga qxl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -name debian-10-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -ide2 lvm-thin:cloudinit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; -sshkey /etc/pve/pub_keys/pub_key.pub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Please, please, please, take into account that the disk needs to be resized to 10 GB, so the VM has space to grow when it runs, you can do this from the hardware tab on the GUI.&lt;/p&gt;
&lt;h3 id=&#34;template-setup&#34;&gt;Template setup&lt;/h3&gt;
&lt;p&gt;Ok, you created the template, now what?&lt;/p&gt;
&lt;p&gt;The template needs to have some packages on it to run smoothly, not all of these packages are strictly necessary but it&amp;rsquo;s what I usually go for:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install bmon screen ntpdate vim locate locales-all iotop atop curl libpam-systemd python-pip python-dev ifenslave vlan mysql-client sysstat snmpd sudo lynx rsync nfs-common tcpdump strace darkstat qemu-guest-agent
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;defining-thetemplate&#34;&gt;Defining the template&lt;/h3&gt;
&lt;p&gt;When the VM has been shut down cleanly, you can proceed and convert it to a template, this can be done on the Proxmox GUI by right-clicking on the VM and clicking on &amp;ldquo;Convert to Template&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;In this case, let&amp;rsquo;s rename the VM template to: &lt;code&gt;debian-cloudinit&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Success, the template has been created.&lt;/p&gt;
&lt;h2 id=&#34;enter-terraform&#34;&gt;Enter Terraform&lt;/h2&gt;
&lt;p&gt;Terraform works in a pretty straightforward way.&lt;/p&gt;
&lt;p&gt;It uses a file with HCL format (kinda like JSON) which is JSON compatible.&lt;/p&gt;
&lt;p&gt;Within that file (or files), you can define an entire infrastructure. How simple or complex it can be is up to you. For this example, it&amp;rsquo;s going to be a pretty simple infrastructure definition, after all, we&amp;rsquo;re just creating one VM (for now).&lt;/p&gt;
&lt;p&gt;The Terraform installation has been explained countless times online, for whichever operating system you might use, so I&amp;rsquo;m going to assume that you know how to install it (or how to google for: terraform install &lt;code&gt;&amp;lt;insert OS here&amp;gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Once it has been installed you need to install a provider so it can talk to the Proxmox API Server. Luckily there&amp;rsquo;s a provider that&amp;rsquo;s actively developed for this use.&lt;/p&gt;
&lt;h3 id=&#34;proxmox-provider&#34;&gt;Proxmox Provider&lt;/h3&gt;
&lt;p&gt;You can find the Proxmox provider for Terraform &lt;a class=&#34;link&#34; href=&#34;https://github.com/Telmate/terraform-provider-proxmox&#34;  title=&#34;here&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The project is in active development and runs without hitches most of the time(99% of the time works all the time).&lt;/p&gt;
&lt;p&gt;To install it just run the following commands to install the dependencies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go get -v github.com/Telmate/terraform-provider-proxmox/cmd/terraform-provider-proxmox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go get -v github.com/Telmate/terraform-provider-proxmox/cmd/terraform-provisioner-proxmox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go install -v github.com/Telmate/terraform-provider-proxmox/cmd/terraform-provider-proxmox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go install -v github.com/Telmate/terraform-provider-proxmox/cmd/terraform-provisioner-proxmox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, copy the executables that the compilation gave us into the path directory, in my case:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo cp $GOPATH/bin/terraform-provider-proxmox /usr/local/bin/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo cp $GOPATH/bin/terraform-provisioner-proxmox /usr/local/bin/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;terraform-project&#34;&gt;Terraform Project&lt;/h3&gt;
&lt;p&gt;Now you can get started with the Terraform project and project definitions.
We&amp;rsquo;re going to use a directory structure like this one:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tfProxmox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|- main.tf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Just a single file. Remember this can be as complex or as simple as you need it to.&lt;/p&gt;
&lt;h3 id=&#34;project-definition&#34;&gt;Project Definition&lt;/h3&gt;
&lt;p&gt;Within that &lt;code&gt;main.tf&lt;/code&gt; file you first need to set up the connection profile for the Proxmox node. In case you have a cluster, any of the nodes will suffice:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;provider &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;proxmox&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pm_api_url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://&lt;/span&gt;$PROXMOXSERVERIP&lt;span style=&#34;color:#e6db74&#34;&gt;:8006/api2/json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pm_user &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;root@pam&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pm_password &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$SUPERSECRETPASSWORD&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pm_tls_insecure &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember to change the $PROXMOXSERVERIP and the $SUPERSECRETPASSWORD variables on the example.&lt;/p&gt;
&lt;h4 id=&#34;ssh-keys&#34;&gt;SSH Keys&lt;/h4&gt;
&lt;p&gt;Since you&amp;rsquo;re using a Cloud-init image (in case you went for Debian&amp;rsquo;s official template image), it&amp;rsquo;s set up for passwordless login so you need to define an SSH key to be installed on the VM:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;variable &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ssh_key&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  default &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;#INSERTSSHHPUBLICKEYHERE&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where &lt;code&gt;$INSERTSSHHPUBLICKEYHERE&lt;/code&gt; is your super-amazing-laptop&amp;rsquo;s SSH public key.&lt;/p&gt;
&lt;p&gt;Now you can define the VM itself.&lt;/p&gt;
&lt;h3 id=&#34;vm-definition&#34;&gt;VM Definition&lt;/h3&gt;
&lt;p&gt;Bellow these definitions we can start defining our VM:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;resource &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;proxmox_vm_qemu&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;proxmox_vm&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  count             &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name              &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tf-vm-&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;count.index&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  target_node       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$NODETOBEDEPLOYED&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clone             &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;debian-cloudinit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os_type           &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cloud-init&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cores             &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sockets           &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cpu               &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;host&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  memory            &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2048&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  scsihw            &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;virtio-scsi-pci&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  bootdisk          &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scsi0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;disk &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    id              &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    size            &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    type            &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scsi&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    storage         &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;data2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    storage_type    &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;lvm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    iothread        &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;network &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    id              &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model           &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;virtio&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bridge          &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vmbr0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lifecycle &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ignore_changes  &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      network,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Cloud Init Settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ipconfig0 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ip=10.10.10.15&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;count.index + 1&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/24,gw=10.10.10.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sshkeys &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;lt;&amp;lt;EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  ${var.ssh_key}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember to change the &lt;code&gt;$NODETOBEDEPLOYED&lt;/code&gt; entry for the node name where the VM will be deployed and the &lt;code&gt;lvm-thin&lt;/code&gt; entry to whatever storage resource you&amp;rsquo;ll be using.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s explain the resource definition. The main entries that you should take into account are:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;count     &amp;lt;- This states the amount of VMs to be created
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;name      &amp;lt;- This states the VM Name, the &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;count.index&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; allows  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             you to create more than one VM and it&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ll just count    
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             from then e.g.: tf-vm-1, tf-vm-2, tf-vm-3, etc.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;cores     &amp;lt;- The amount of cores that the VM will have
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;memory    &amp;lt;- The amount of RAM the VM will have
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;disk      &amp;lt;- The disk definitions for the VM, scale the size here.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;network   &amp;lt;- The network bridge definition to be used.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;ipconfig0 &amp;lt;- The Ip for the VM, the &amp;#34;${count.index}&amp;#34; allows  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             you to create more than one VM and it&amp;#39;&lt;/span&gt;ll just count    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             from &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt; e.g.: 10.10.10.151, 10.10.10.152, etc.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;running-terraform&#34;&gt;Running Terraform&lt;/h2&gt;
&lt;p&gt;Terraform uses 3 main stages to run:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Init - This step allows Terraform to be initialized and downloads the required plugins to run&lt;/li&gt;
&lt;li&gt;Plan - This step performs planning for the deployment, using the tf file that you&amp;rsquo;ve defined. It focuses on the calculation for the deployment and conflict resolution in case such conflict exists, it&amp;rsquo;s going to show you all the changes, additions, and deletions to be performed.&lt;/li&gt;
&lt;li&gt;Apply - After the planning stage, this is the stage that applies the changes to the infrastructure. It&amp;rsquo;s going to give you a summary of the changes, additions and/or deletions to be made and ask for confirmation to commit these changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;init&#34;&gt;Init&lt;/h4&gt;
&lt;p&gt;While on the project folder run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;terraform init
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As stated before, this is going to initialize Terraform and install the needed plugins for the project, the output should be as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;terraform init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Initializing the backend...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Initializing provider plugins...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Terraform has been successfully initialized!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;You may now begin working with Terraform. Try running &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;terraform plan&amp;#34;&lt;/span&gt; to see
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;any changes that are required &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; your infrastructure. All Terraform commands
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;should now work.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;If you ever set or change modules or backend configuration &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Terraform,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rerun this command to reinitialize your working directory. If you forget, other
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;commands will detect it and remind you to &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; so &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; necessary.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;plan&#34;&gt;Plan&lt;/h4&gt;
&lt;p&gt;This step will take care of all of the calculations that need to be run and conflict resolution with the infrastructure that might already be deployed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;victor@AMAZINGLAPTOP:~$ terraform plan
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Refreshing Terraform state in-memory prior to plan...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The refreshed state will be used to calculate this plan, but will not be
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;persisted to local or remote state storage.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;An execution plan has been generated and is shown below.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resource actions are indicated with the following symbols:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  + create
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Terraform will perform the following actions:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# proxmox_vm_qemu.proxmox_vm[0] will be created&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  + resource &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;proxmox_vm_qemu&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;proxmox_vm&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + agent        &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + balloon      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + boot         &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cdn&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + bootdisk     &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scsi0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + clone        &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;debian-cloudinit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + clone_wait   &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + cores        &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + cpu          &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;host&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + force_create &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + full_clone   &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + hotplug      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;network,disk,usb&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + id           &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;known after apply&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + ipconfig0    &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ip=10.10.10.151/24,gw=10.10.10.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + memory       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2028&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + name         &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tf-vm-0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + numa         &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + onboot       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + os_type      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cloud-init&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + preprovision &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + scsihw       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;virtio-scsi-pci&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + sockets      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + ssh_host     &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;known after apply&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + ssh_port     &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;known after apply&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + sshkeys      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &amp;lt;&amp;lt;~EOT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              ssh-rsa ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        EOT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + target_node  &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pmx-01&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + vcpus        &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      + vlan         &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; -1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ disk &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + backup       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + cache        &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + format       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;raw&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + id           &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + iothread     &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + mbps         &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + mbps_rd      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + mbps_rd_max  &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + mbps_wr      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + mbps_wr_max  &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + replicate    &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + size         &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;20&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + storage      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;data2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + storage_type &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;lvm&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + type         &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scsi&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ network &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + bridge    &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vmbr0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + firewall  &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + id        &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + link_down &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + model     &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;virtio&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + queues    &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; -1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + rate      &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; -1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          + tag       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; -1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Plan: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; to add, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; to change, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; to destroy.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;This plan was saved to: planfile
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;To perform exactly these actions, run the following command to apply:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    terraform apply &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;planfile&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The plan states that a new resource will be created on the target node: pmx-01 (which is the node I&amp;rsquo;m using on my lab).&lt;/p&gt;
&lt;p&gt;After you check the planning and everything seems to be alright apply it.&lt;/p&gt;
&lt;h4 id=&#34;apply&#34;&gt;Apply&lt;/h4&gt;
&lt;p&gt;To apply the Terraform plan, just run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;terraform apply
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will give you the summary from the plan and prompt for confirmation, type: yes and it&amp;rsquo;ll do it&amp;rsquo;s bidding.&lt;/p&gt;
&lt;p&gt;When it&amp;rsquo;s done the output should be as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;victor@AMAZINGLAPTOP:~$ terraform apply
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Apply complete! Resources: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; added, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; changed, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; destroyed.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The state of your infrastructure has been saved to the path
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;below. This state is required to modify and destroy your
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;infrastructure, so keep it safe. To inspect the complete state
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use the &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;terraform show&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt; command.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;State path: terraform.tfstate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;This example should work as a starting point for Terraform interacting with Proxmox.&lt;/p&gt;
&lt;p&gt;Take into account that you can destroy the VM by changing the count on the &lt;code&gt;main.tf&lt;/code&gt; file to zero and going through the plan and apply stages.&lt;/p&gt;
&lt;p&gt;Also, you can split the &lt;code&gt;main.tf&lt;/code&gt; file into different files so it&amp;rsquo;s more organized when you decide to extend the infrastructure with different machine role definitions and different configurations for each one of them.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve also uploaded the file on my GitHub &lt;a class=&#34;link&#34; href=&#34;https://medium.com/r/?url=https%3A%2F%2Fgithub.com%2Fgaldorork%2Ftf-medium%2Fblob%2Fmaster%2Fmain.tf&#34;  title=&#34;here&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt; in case you just want the file.&lt;/p&gt;
&lt;p&gt;Thanks for reading.&lt;/p&gt;
&lt;h2 id=&#34;new-additions&#34;&gt;New Additions&lt;/h2&gt;
&lt;p&gt;As some folks have reported there could be some issues getting the proxmox plugin installed on their machines.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve set up a Docker Image all set up and ready for it. The repo is located at:&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/galdorork/terragrunt-proxmox-provisioner&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/galdorork/terragrunt-proxmox-provisioner&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And here&amp;rsquo;s the link to the Image on Docker&amp;rsquo;s public registry:&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://hub.docker.com/r/galdor1/terragrunt-proxmox-provisioner&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://hub.docker.com/r/galdor1/terragrunt-proxmox-provisioner&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Setting up Python virtual environments: The right way</title>
        <link>https://vectops.com/post/2020/python-virtual-environments-the-right-way/</link>
        <pubDate>Thu, 16 Apr 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/python-virtual-environments-the-right-way/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/python-virtual-environments-the-right-way/image.png" alt="Featured image of post Setting up Python virtual environments: The right way" /&gt;&lt;p&gt;Yuuup little hackers, a few days ago I was assigned to a new project.&lt;/p&gt;
&lt;p&gt;The main thing about this project is Python so it has to be set-up on my work laptop and the installation should work with my team&amp;rsquo;s laptops so they can help in writing some dependencies.&lt;/p&gt;
&lt;p&gt;At this point, I have doubts about how my workload can shared with them, and the answer was easy, use &lt;code&gt;virtualenvs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First of all, you should know a little bit about pip.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Pip its a package installer for Python, its like &lt;code&gt;apt, yum, pacman...&lt;/code&gt; but focused only to python dependencies.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You have probably heard about &lt;code&gt;virtualenvs&lt;/code&gt; in Python, it allows you to create a Python environment totally independent of the local system where you can run specific versions of Python and its dependencies.&lt;/p&gt;
&lt;h2 id=&#34;install-pipenv&#34;&gt;Install &lt;em&gt;pipenv&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Plain and simple; open your favorite terminal and issue this command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ pip install pipenv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Your virtualenvs packages will be saved at this location:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$HOME/.local/share/virtualenvs/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;first-environment-with-pipenv&#34;&gt;First environment with &lt;em&gt;pipenv&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Ok, let&amp;rsquo;s go to make our first environment. Just create a folder where you can put code or simply go to your git directory, and follow these steps:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ mkdir myFirstApp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cd myFirstApp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ pipenv shell
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After you execute the last command, you will probably see a little change in your terminal. Yeap, your &lt;code&gt;virtualenv&lt;/code&gt; has been created and you&amp;rsquo;re on it.&lt;/p&gt;
&lt;p&gt;You have a new file called &lt;code&gt;Pipfile&lt;/code&gt;, this file contains all the dependencies that pipenv has installed in your &lt;code&gt;virtualenv&lt;/code&gt; as well as any dependencies that you project might need.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try to install, for example, the aws-cli tool:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;myFirstApp&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; $ pip install aws-cli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the installation has finished, run help with &lt;code&gt;help&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;Now try to run an &lt;code&gt;exit&lt;/code&gt; and test if you can to execute the &lt;code&gt;aws-cli&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;activate-your-virtualenv-again&#34;&gt;Activate your virtualenv again&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ source $HOME/.local/share/virtualenvs/myFirstApp-*/bin/active
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;save-your-packages&#34;&gt;Save your packages&lt;/h2&gt;
&lt;p&gt;This is a golden feature and this is the main thing we want to use.&lt;/p&gt;
&lt;p&gt;I can install a lot of packages on my local machine, but when my teammate tries to deploy the application in his/hers local environment, there might be some dependencies issues. Mainly because they haven&amp;rsquo;t installed any.&lt;/p&gt;
&lt;p&gt;How would this work?&lt;/p&gt;
&lt;p&gt;Easy, just save your local packages on a stupid file called &lt;code&gt;requirements.txt&lt;/code&gt; and push to your repository with the source code of the app.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ pipenv lock -r | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{ if (NR!=1) print $1 }&amp;#39;&lt;/span&gt; &amp;gt; requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that, your teammate be able to install the dependencies with the command described on the next step.&lt;/p&gt;
&lt;h2 id=&#34;install-packages-from-file&#34;&gt;Install packages from file&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ pip install -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aaaaand there go, you know now how to create and work with &lt;code&gt;virtualenv&lt;/code&gt;, and the most important part: to be able to teamwork!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Production-ready Kubernetes PaaS in 10 steps; IaaS included</title>
        <link>https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/</link>
        <pubDate>Tue, 25 Feb 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/image.png" alt="Featured image of post Production-ready Kubernetes PaaS in 10 steps; IaaS included" /&gt;&lt;p&gt;Easy, straightforward and can be performed by anyone with a basic understanding of production systems (read: basic). But, my advice &lt;strong&gt;IF&lt;/strong&gt; (&amp;lt;- big if) you want to use these steps on your infrastructure, adapt them to your needs.&lt;/p&gt;
&lt;p&gt;At the very least you’ll have a place to start without having to spend countless hours, doing research… drinking more than what anyone would consider a healthy amount of coffee. And/or having to work out what articles out there are compatible with what or which aren’t.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Tech writers need to start specifying software versions on their articles to prevent this from happening.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I’ve written other articles about how to streamline the deployment for VMs using virtualization platforms such as &lt;a class=&#34;link&#34; href=&#34;https://www.proxmox.com/en/&#34;  title=&#34;Proxmox&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Proxmox&lt;/a&gt; and automation tools like &lt;a class=&#34;link&#34; href=&#34;https://www.ansible.com/&#34;  title=&#34;Ansible&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Ansible&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This step-by-step can and will deal with some of these technologies without too much customization. You could also adapt it to use some other alternatives to the tools used here.&lt;/p&gt;
&lt;p&gt;Enough preamble, let’s go for it.&lt;/p&gt;
&lt;h2 id=&#34;step-1-get-some-hardware&#34;&gt;Step 1: Get some hardware&lt;/h2&gt;
&lt;p&gt;Take your pick. Whether it’s a very low-cost decommissioned desktop PC from an office or a laptop with a broken screen.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can get a lot of good deals on ebay for decommissioned hardware, either tower PCs or “old” servers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or a US$ 20,000 latest-generation server with the latest and greatest hardware.&lt;/p&gt;
&lt;p&gt;It’s your call. I can’t determine how much load will your platform have but these steps should help you choose. So, please, adapt it to your needs.&lt;/p&gt;
&lt;h2 id=&#34;step-2-lets-set-up-a-cloud-ish-environment&#34;&gt;Step 2: Let’s set up a Cloud-ish environment.&lt;/h2&gt;
&lt;p&gt;Let’s say you don’t have a lot of bare-metal machines or, maybe, you do. In my case I’ve had an issue with the bare-metal servers I have available to me. They’re too big.&lt;/p&gt;
&lt;p&gt;Note: Yes, I know, this example can be set up with &lt;code&gt;virsh&lt;/code&gt;. This is how I decided to do it, there’s a million ways to do it, this one’s easier for me :)&lt;/p&gt;
&lt;p&gt;As in, 512 Gigs of RAM each. Now, Kubernetes’ workloads don’t usually go well with huge servers, there’s a pod limit to each node. Kernel limitations won’t help either. So I’ve decided to go with a Proxmox cluster environment that will host a few VMs with different VM models on it.&lt;/p&gt;
&lt;p&gt;This is how the Proxmox deployment will look like after it’s done:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment1.png&#34;
	width=&#34;254&#34;
	height=&#34;627&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment1_hu5e7dfbdc13cdbeb6fc8e1a138e16b4fa_8197_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment1_hu5e7dfbdc13cdbeb6fc8e1a138e16b4fa_8197_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Proxmox Infrastructure&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;40&#34;
		data-flex-basis=&#34;97px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;This example uses a 3 node Proxmox cluster. The setup for the cluster just needs you to install 3 machines with Proxmox, it can be Proxmox 5 or 6, your call. It makes no difference.&lt;/p&gt;
&lt;p&gt;After you have installed the Proxmox distro on the machines, just create a cluster.&lt;/p&gt;
&lt;h3 id=&#34;create-the-proxmox-cluster&#34;&gt;Create the Proxmox Cluster&lt;/h3&gt;
&lt;p&gt;In this example I’m going to reserve the following IPs for the installation (they’re also stated on the image above):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;192.168.1.2 node1
192.168.1.3 node2
192.168.1.4 node3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The cluster creation is pretty well documented on Proxmox’s documentation &lt;a class=&#34;link&#34; href=&#34;https://pve.proxmox.com/wiki/Cluster_Manager#pvecm_create_cluster&#34;  title=&#34;here&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;. On the newer versions, it can also be done with the GUI. I’m proceeding with the installation on Proxmox 6.1.&lt;/p&gt;
&lt;p&gt;These steps should create a cluster pretty painlessly, let’s name it &lt;em&gt;cloudish&lt;/em&gt;. Just log in via SSH to any of the nodes, in this case node1, and execute the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node1:~# pvecm create cloudish
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then login into the other nodes and run the join command on each one of them:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node2:~# pvecm add 192.168.1.2
node3:~# pvecm add 192.168.1.2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;em&gt;pvecm&lt;/em&gt; command will ask you for the node1 credentials, input them and you’re good to go.&lt;/p&gt;
&lt;h2 id=&#34;step-3-create-a-bare-metal-controller&#34;&gt;Step 3: Create a bare-metal controller&lt;/h2&gt;
&lt;p&gt;To control and deploy the nodes I’m using &lt;a class=&#34;link&#34; href=&#34;https://maas.io/&#34;  title=&#34;MaaS&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;MaaS&lt;/a&gt; (Metal as a Service), a bare metal controller that allows you to present the VMs you are going to create, or even bare metal servers to a cloud orchestrator such as Terraform or JuJu.&lt;/p&gt;
&lt;p&gt;MaaS uses two elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A region Controller that handles: DNS, NTP, Syslog, and Squid Proxy&lt;/li&gt;
&lt;li&gt;A rack Controller that handles: PXE, IPMI, NTP, TFTP, iSCSI, DHCP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both of these elements can be deployed to the same machine.&lt;/p&gt;
&lt;p&gt;In case you want/need high availability these components can be separated and installed in different machines, it’s well documented and straightforward, more info &lt;a class=&#34;link&#34; href=&#34;https://maas.io/docs/high-availability&#34;  title=&#34;here&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In our case, we’re going to use the same machine for both things.&lt;/p&gt;
&lt;p&gt;The deployment will look like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment2.png&#34;
	width=&#34;311&#34;
	height=&#34;269&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment2_hu41a7a691c46adf10a547213d4082d58b_5549_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment2_hu41a7a691c46adf10a547213d4082d58b_5549_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;MaaS Deployment&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;115&#34;
		data-flex-basis=&#34;277px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;Download an Ubuntu Server ISO from the Ubuntu website and install it on a VM created on the Proxmox cluster, in this case, Ubuntu 18.04 LTS.&lt;/p&gt;
&lt;p&gt;The bare minimum MaaS deployment needs one machine with 1 core and 2 Gigs of RAM. This should suffice for a very small deployment with a couple of machines.&lt;/p&gt;
&lt;p&gt;Lets amp that up and go all the way to 4 cores and 8 Gigs of RAM!&lt;/p&gt;
&lt;p&gt;For this example the MaaS machine will have the following IP:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MaaS --- 192.168.1.10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After you’ve installed the OS on the VM, go ahead and install the MaaS Controller, in our case &lt;code&gt;MaaS 2.6.2&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;maas:~# sudo add-apt-repository ppa:maas/2.6
maas:~# sudo apt update
maas:~# sudo apt install maas
maas:~# sudo maas init
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After the initialization is done you’ll see a URL on the terminal. Go ahead and log into it using your favorite browser and finally, proceed with the configuration stage. Read more here.&lt;/p&gt;
&lt;p&gt;Please remember to set up your DHCP service, by going on the MaaS interface and setting up the range you want.&lt;/p&gt;
&lt;p&gt;To use MaaS DHCP you need it to be the only DHCP service on the network. This is very important. Also, reserve the ranges for the IPs you’re going to use elsewhere or the ones you’ve already used.&lt;/p&gt;
&lt;h2 id=&#34;step-4-create-vms&#34;&gt;Step 4: Create VMs.&lt;/h2&gt;
&lt;p&gt;Yes, create Virtual Machines for Proxmox, a lot of them. I advise going with a for loop on the terminal using qm create so the process doesn’t get tedious, remember to check what requirements you need.&lt;/p&gt;
&lt;p&gt;For this project, we’re going to create the bare minimum that Canonical recommends for a charmed Kubernetes deployment with HA, 10 machines.&lt;/p&gt;
&lt;p&gt;Also the 3 VMs for JuJu.&lt;/p&gt;
&lt;p&gt;The setup is as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;VM1    2 CPU Cores | 2 GB RAM | 20 GB HDD   tags=master
VM2    2 CPU Cores | 2 GB RAM | 20 GB HDD   tags=master
VM3    2 CPU Cores | 2 GB RAM | 20 GB HDD   tags=loadbalancer
VM4    2 CPU Cores | 2 GB RAM | 20 GB HDD   tags=easyrsa
VM5    2 CPU Cores | 2 GB RAM | 20 GB HDD   tags=etcd
VM6    2 CPU Cores | 2 GB RAM | 20 GB HDD   tags=etcd
VM7    2 CPU Cores | 2 GB RAM | 20 GB HDD   tags=etcd
VM8    4 CPU Cores | 4 GB RAM | 20 GB HDD   tags=worker
VM9    4 CPU Cores | 4 GB RAM | 20 GB HDD   tags=worker
VM10   4 CPU Cores | 4 GB RAM | 20 GB HDD   tags=worker
VM11   1 CPU Cores | 3 GB RAM | 20 GB HDD   tags=juju-controller
VM12   1 CPU Cores | 3 GB RAM | 20 GB HDD   tags=juju-controller
VM13   1 CPU Cores | 3 GB RAM | 20 GB HDD   tags=juju-controller
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After you create the VMs you need to add them to MaaS, make sure they’re set up for Network boot first and HDD second, like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment3.png&#34;
	width=&#34;301&#34;
	height=&#34;182&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment3_hu39f1430c5236094845764a1fecf90325_4087_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment3_hu39f1430c5236094845764a1fecf90325_4087_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;VM Boot order&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;165&#34;
		data-flex-basis=&#34;396px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;Then boot them up so they go through the process to be added to MaaS.&lt;/p&gt;
&lt;h2 id=&#34;step-5-configure-maas&#34;&gt;Step 5: Configure MaaS&lt;/h2&gt;
&lt;p&gt;For MaaS to be able to control Proxmox VMs like if they were a bare-metal machine it needs a driver.&lt;/p&gt;
&lt;p&gt;Luckily a guy by the name of &lt;a class=&#34;link&#34; href=&#34;https://launchpad.net/~enter2608&#34;  title=&#34;Wojtek Rakoniewski&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Wojtek Rakoniewski&lt;/a&gt; wrote one for all of us to use and posted it on launchpad. It works with what I’ve tested: Proxmox 5.1, 6.1 and everything in between since it uses the Proxmox API.&lt;/p&gt;
&lt;p&gt;I’ve taken the liberty of hosting it on a public Github repo with credits for him all around, just in case the guys from launchpad decide to archive the bug tracker.&lt;/p&gt;
&lt;p&gt;You can download it &lt;a class=&#34;link&#34; href=&#34;https://raw.githubusercontent.com/galdorork/proxmox-maas/master/proxmox.py&#34;  title=&#34;here&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Or using wget:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wget https://raw.githubusercontent.com/galdorork/proxmox-maas/master/proxmox.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After you download it you need to put the file on this route on the MaaS Region controller:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/usr/lib/python3/dist-packages/provisioningserver/drivers/power/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And register the driver on the registry.py located here:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/usr/lib/python3/dist-packages/provisioningserver/drivers/power/registry.py
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You need to edit the entry so it looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## Add this to the import headers
from provisioningserver.drivers.power.proxmox import ProxmoxPowerDriver
## The ProxmoxPowerDriver is the entry to be added
power_drivers = [
     ProxmoxPowerDriver(),
     ...
 ]
 ```
Then install the *proxmoxer* python package so the driver knows what to use when talking to the Proxmox API:
```bash
apt install python3-proxmoxer
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, restart the maas-regiond service to take the changes into account, systemctl restart maas-regiond should work.&lt;/p&gt;
&lt;p&gt;Unfortunately even using this driver MaaS doesn’t know how to auto-detect the hardware controller for the machine, but it’s easily done manually on the VM’s config.&lt;/p&gt;
&lt;p&gt;To do this you need to create a PVE user on the Proxmox GUI that has the VM.Audit and VM.PowerMgmt permissions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment4.png&#34;
	width=&#34;621&#34;
	height=&#34;297&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment4_hu80bb8b4a2d7ccd569d40af691e3a9fee_7097_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment4_hu80bb8b4a2d7ccd569d40af691e3a9fee_7097_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;User Definition&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;209&#34;
		data-flex-basis=&#34;501px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment5.png&#34;
	width=&#34;625&#34;
	height=&#34;23&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment5_hubf2bfa17392ce37bd8d21fdec5a623c0_2515_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment5_hubf2bfa17392ce37bd8d21fdec5a623c0_2515_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Group Definition&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;2717&#34;
		data-flex-basis=&#34;6521px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;Then configure the VM on MaaS so the region controller knows how to use it’s power capabilities.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment6.png&#34;
	width=&#34;694&#34;
	height=&#34;274&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment6_hu036ffcf35a0bf46668f1970ac0fc97be_7580_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment6_hu036ffcf35a0bf46668f1970ac0fc97be_7580_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;MaaS power type configuration&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;253&#34;
		data-flex-basis=&#34;607px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;Input here the PVE user you have created, it’s password, one of the proxmox nodes’ IPs and the VM id.&lt;/p&gt;
&lt;h2 id=&#34;step-6-commission-the-vms&#34;&gt;Step 6: Commission the VMs&lt;/h2&gt;
&lt;p&gt;MaaS uses with this workflow:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The machine is added →Machine needs to be commissioned → Machine is deployed.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The workflow makes sense since no machine can be formatted or deployed accidentally by being present on the same network and being pxe-booted.&lt;/p&gt;
&lt;p&gt;When you boot up your proxmox VMs the first time, they will be added to MaaS as new machines:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment7.png&#34;
	width=&#34;159&#34;
	height=&#34;112&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment7_hud89bd84494f027f07af030f0b424342b_2079_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment7_hud89bd84494f027f07af030f0b424342b_2079_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;New machine added&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;141&#34;
		data-flex-basis=&#34;340px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;Then you need to commission them, this means it gets booted from MaaS (remember to configure the power type) and some tests are run on the machine, as well as defining an inventory for that specific machine, parsing CPU info, RAM info, Storage info, etc.&lt;/p&gt;
&lt;p&gt;After it’s commissioned it’ll be shown as ready:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment8.png&#34;
	width=&#34;1398&#34;
	height=&#34;116&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment8_hu9a9145146f5df8060340aecf8529fd28_7558_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment8_hu9a9145146f5df8060340aecf8529fd28_7558_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;MaaS VM in ready state&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;1205&#34;
		data-flex-basis=&#34;2892px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;This means the VM is ready to be used by either a controller or being manually deployed by either using the MaaS GUI or the MaaS API or, maybe even JuJu.&lt;/p&gt;
&lt;p&gt;Let’s go for JuJu.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;DO NOT FORGET: JuJu needs “tags” to identify MaaS nodes, else it grabs them at random, please set up tags with the VM usage so you can use them as constraints later on:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment9.png&#34;
	width=&#34;698&#34;
	height=&#34;74&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment9_hu0a8573389cbf9c569509c2f3473a27f3_2187_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment9_hu0a8573389cbf9c569509c2f3473a27f3_2187_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;MaaS VM Tag configuration&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;943&#34;
		data-flex-basis=&#34;2263px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;step-7-create-your-juju-controller-vms&#34;&gt;Step 7: Create your JuJu controller VMs.&lt;/h2&gt;
&lt;p&gt;This implementation requires a JuJu controller. For this example, we’re going to use `2.7.1-eoan-amd64.`&lt;/p&gt;
&lt;p&gt;We’re going to use a single machine for it. The VM needs at least 1 core and 3 GB of RAM.&lt;/p&gt;
&lt;p&gt;You don’t need to install it, just set it up to boot from Network and the VM will boot up using iPXE.&lt;/p&gt;
&lt;p&gt;After it boots with the Ubuntu image it will download some of the packages it needs to check the resources the VM has and show it to the MaaS controller.&lt;/p&gt;
&lt;p&gt;Afterward, commission it and you’re all set, you can commission your first machine from JuJu. This will be done from your PC.&lt;/p&gt;
&lt;p&gt;On your PC, execute the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yourawesomelaptop:~$ sudo snap install juju --classic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, add the MaaS cloud to your JuJu environment:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yourawesomelaptop:~$ juju add-cloud --local
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output will be as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Cloud Types
  lxd
  maas
  manual
  openstack
  vsphere
Select cloud type: maas
Enter a name for your maas cloud: my-amazing-bare-metal-cloud
Enter the API endpoint url: http://192.168.1.10:5240/MAAS
Cloud &amp;quot;my-amazing-bare-metal-cloud&amp;quot; successfully added
You will need to add credentials for this cloud (juju add-credential my-amazing-bare-metal-cloud)
before creating a controller (juju bootstrap my-amazing-bare-metal-cloud).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your JuJu installation needs to be able to connect to the API, it has the URL, now it needs the credentials:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yourawesomelaptop:~$ juju add-credential maas-cloud
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’ll ask for the MaaS secret, get it from the MaaS GUI. Click on your username on the top right corner and it’s the first field, copy and paste when it asks for maas-oauth:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Enter credential name: my-amazing-bare-metal-cloud-credentials
Using auth-type &amp;quot;oauth1&amp;quot;.
Enter maas-oauth:
Credentials added for cloud my-amazing-bare-metal-cloud.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can check the added credentials with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yourawesomelaptop:~$ juju credentials --local
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally create the main JuJu controller, using the JuJu tags and constraints:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yourawesomelaptop:~$ juju bootstrap --bootstrap-constraints tags=juju-controller my-amazing-bare-metal-cloud maas-controller
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’re done with JuJu for now.&lt;/p&gt;
&lt;p&gt;If you want High Availability you can scale the controller and let it have more machines, 3 is advised for any production environment (remember to create the VMs first on Proxmox) for this example we’re doing it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yourawesomelaptop:~$ juju enable-ha
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;step-8-juju-the-hell-out-of-that-maas-instance&#34;&gt;Step 8: JuJu the hell out of that MaaS instance&lt;/h2&gt;
&lt;p&gt;Once the empty VMs are ready, the MaaS controllers are ready and the JuJu controller is ready you’re all set.&lt;/p&gt;
&lt;p&gt;You can even do these steps on a nice graphical interface using JuJu Gui. Don’t worry, you can still use the terminal to adjust some of it, or even customize the charm bundle so it adapts to your machines.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment10.png&#34;
	width=&#34;1363&#34;
	height=&#34;783&#34;
	srcset=&#34;https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment10_hude726351306e4566b09287b90aa546c1_45518_480x0_resize_box_3.png 480w, https://vectops.com/post/2020/production-ready-kubernetes-paas-in-10-steps-iaas-included/attachment10_hude726351306e4566b09287b90aa546c1_45518_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Charmed Kubernetes Bundle&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;174&#34;
		data-flex-basis=&#34;417px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;In this case, we’re going to edit some of the constraints, so next to where it says `untitled-model` you can click on export and download the YAML descriptor file. On this file you need to focus on the machine descriptors at the end of the file and add the constraints to each one, depending on their need. E.g:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;machines:
  &#39;0&#39;:
    constraints: tags=easyrsa
  &#39;1&#39;: 
    constraints: tags=etcd
  &#39;2&#39;: 
    constraints: tags=etcd
  &#39;3&#39;: 
    constraints: tags=etcd
  &#39;4&#39;: 
    constraints: tags=loadbalancer
  &#39;5&#39;: 
    constraints: tags=master
  &#39;6&#39;: 
    constraints: tags=master
  &#39;7&#39;: 
    constraints: tags=worker
  &#39;8&#39;: 
    constraints: tags=worker
  &#39;9&#39;: 
    constraints: tags=worker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure the machine IDs match with the descriptions present at the beginning of each service definition. Then import it to your GUI and let it process.&lt;/p&gt;
&lt;p&gt;Then commit the changes. You should add your `ssh` public key on this step. Remember you can always add it later on.&lt;/p&gt;
&lt;p&gt;Then relax, get a cup of coffee, or tea, or a beer, maybe all of them. Depending on the hardware you have available this could take a while, from 15 mins on. In the meantime, you can see the deployment status on the GUI.&lt;/p&gt;
&lt;p&gt;If you decide to use the terminal the bundle can also be deployed like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yourawesomelaptop:~$ juju deploy myawesomekubernetescluster.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;step-9-get-your-kubernetes-config-file&#34;&gt;Step 9: Get your Kubernetes config file&lt;/h2&gt;
&lt;p&gt;After the provisioning is done you just need to get your Kubernetes config file from the juju deployment:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yourawesomelaptop:~$ juju scp kubernetes-master/0:config ~/.kube/config
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And connect to the deployment using kubectl, in case you need to install kubectl on your machine I’ve written an article about it &lt;a class=&#34;link&#34; href=&#34;https://vectops.com/post/2019/set-up-your-machine-to-use-kubectl/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;, it has instructions for the main OSs out there.&lt;/p&gt;
&lt;p&gt;There, you’re all set.&lt;/p&gt;
&lt;p&gt;Optionally you can set up MetalLB as a way to expose the services or even use nfs-client provisioner or whichever persistent storage you might want to use.&lt;/p&gt;
&lt;h2 id=&#34;step-10-scale-it-away&#34;&gt;Step 10: Scale it away&lt;/h2&gt;
&lt;p&gt;Yes, this platform can be scaled vertically, using more VMs present on MaaS for this task.&lt;/p&gt;
&lt;p&gt;From JuJu you can extend each of the cluster roles from your choosing, an example for a Kubernetes worker would be:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;juju add-unit kubernetes-worker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Scale it A LOT? (take caution, this will add 16 worker nodes):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;juju add-unit kubernetes-worker -n 16
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or scale it down (removing the second worker):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;juju remove-unit kubernetes-worker/2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same applies to all of the other cluster roles.&lt;/p&gt;
&lt;p&gt;Et voilá, it’s all set up, now you can focus on developing the next million-dollar idea without having to worry about the platform you have, and without paying premiums on cloud platforms that can be replicated on-site or maybe use hardware you already have laying around.&lt;/p&gt;
&lt;p&gt;If you’re going to use this article as a base to deploy your own PaaS solution, don’t forget that it can be extended a lot, using JuJu for vertical scaling as well as Kubernetes autoscaling for horizontal scaling (pod replica scaling).&lt;/p&gt;
&lt;p&gt;If you need any extra help you can get in touch with me using the comments on this article.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Force Apache to show a 403 error when accessing via IP address</title>
        <link>https://vectops.com/post/2020/forcing-an-apache-webserver-to-show-403-error-when-accessed-through-ip-address/</link>
        <pubDate>Mon, 10 Feb 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/forcing-an-apache-webserver-to-show-403-error-when-accessed-through-ip-address/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/forcing-an-apache-webserver-to-show-403-error-when-accessed-through-ip-address/image.png" alt="Featured image of post Force Apache to show a 403 error when accessing via IP address" /&gt;&lt;p&gt;Let&amp;rsquo;s say we have a few websites hosted in our machine, but we need them to process requests only via a name service; not when accessed via IP address. Very common behavior in shared hosting systems.&lt;/p&gt;
&lt;p&gt;A real time saving tip, and it only needs a couple of lines of code. For this purpose we tested it on an Apache 2.4 server running under a CentOS system.&lt;/p&gt;
&lt;p&gt;To achieve this we only need to make a new file (e. g. &lt;code&gt;default.conf&lt;/code&gt; under the &lt;code&gt;/etc/httpd/conf.d&lt;/code&gt; directory) containing the following lines:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;VirtualHost _default_:80&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ServerName $WEBSERVER_IP_ADDRESS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   UseCanonicalName Off
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Redirect &lt;span style=&#34;color:#ae81ff&#34;&gt;403&lt;/span&gt; /
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/VirtualHost&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course we should run a reload to apply the changes we made on the service:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl reload httpd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s literally all, from here on out when anyone access the webserver through its IP address, the only thing that will show up is a beautiful &lt;strong&gt;403&lt;/strong&gt; error message like this one (which is what we ever intended, right?) as long as you do not tune this up to show anything else or even a custom error message:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Forbidden

You don&amp;#39;t have permission to access / on this server.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cheers!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Provision Proxmox VMs with Ansible, quick and easy</title>
        <link>https://vectops.com/post/2020/provision-proxmox-vms-with-ansible-quick-and-easy/</link>
        <pubDate>Fri, 10 Jan 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/provision-proxmox-vms-with-ansible-quick-and-easy/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/provision-proxmox-vms-with-ansible-quick-and-easy/image.png" alt="Featured image of post Provision Proxmox VMs with Ansible, quick and easy" /&gt;&lt;p&gt;Proxmox is an amazing Virtualization solution for both production, development, testing, etc. basically anything you can think of that requires a virtual machine.&lt;/p&gt;
&lt;p&gt;Whether you rely on an actual kernel (full blown VM) or just the userspace (LXC Containers) it helps a lot to have a free tool that can perform. Not only that but the fact that it can be clustered and have VMs migrated from node to node can help with availability issues that can and will happen when you to perform maintenance on any specific virtualization node.&lt;/p&gt;
&lt;p&gt;However, it can be cumbersome to provision VMs sometimes, the vanilla method is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Create VM -&amp;gt; Present operating system ISO to VM -&amp;gt; perform installation -&amp;gt; Enjoy&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This method can be time consuming depending on how many VMs you need, or what the OS installation process is like.&lt;/p&gt;
&lt;p&gt;I know, I know… There&amp;rsquo;s new fancy tech such as &lt;strong&gt;Kubernetes&lt;/strong&gt; that allows you to easily and swiftly deploy applications on a cloud environment but that kind of infrastructure is not always readily available and it can be hard to migrate some applications to it, depending on what has been developed.&lt;/p&gt;
&lt;h2 id=&#34;enter-templates&#34;&gt;Enter templates&lt;/h2&gt;
&lt;p&gt;The Proxmox system allows you to use and create VM templates, that can be set up with whatever operating system you want.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re going to use a basic Debian 10 template for this example, just go ahead and create a VM, pick low resources for the image so you can expand them later. CPU and memory are easily downsized, storage drives aren&amp;rsquo;t so take this into account.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve created a VM with the following resources:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt; 1 Core
 1 GB RAM
 10 GB HDD
 1 Network Interface
 1 Cloud-init drive
 1 EFI Disk&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some of the properties noted above will have to be added after the VM creation process.&lt;/p&gt;
&lt;h3 id=&#34;creating-the-templatemanually&#34;&gt;Creating the template manually&lt;/h3&gt;
&lt;p&gt;This process is pretty straightforward, here&amp;rsquo;s a step by step:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Click on create VM&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Input a name for the VM, you can check for it to start at boot, your call. Click &lt;strong&gt;next&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select an ISO for the install and select the type and version of the OS that will be installed. Click &lt;strong&gt;next&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Check the &amp;ldquo;Qemu Agent&amp;rdquo; option, you&amp;rsquo;ll use this later on. Click &lt;strong&gt;next&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select the Disk size, in this case 10 GB. You can also change some of the storage emulation options for this drive, we won&amp;rsquo;t go into that on this example. Click &lt;strong&gt;next&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select how many Cores you want to use for the VM, in this case 1 Core. Click &lt;strong&gt;next&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Input the amount of memory for the VM, in this case 1024 MB. I advice using the Ballooning device so you can save up memory resources on the node and to be able to oversell the resources, just like a CPU. Note that if the memory is being actually used by the VM, it can&amp;rsquo;t be used by other VMs unless it&amp;rsquo;s the exact same memory block, enter KSM (Kernel Shared Memory) I won&amp;rsquo;t go into detail about KSM just know that it&amp;rsquo;s awesome. Select the Minimum memory for the Ballooning Device, in this case 256 MB. Click &lt;strong&gt;next&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;If you don&amp;rsquo;t have any custom network configurations on the node you can just Click next here. If you do, make sure that the configuration matches what you need.&lt;/li&gt;
&lt;li&gt;Confirm the VM setup and click on &amp;ldquo;Finish&amp;rdquo; &lt;strong&gt;Don&amp;rsquo;t start the VM yet&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After the VM is created, we need to add a couple of things.&lt;/p&gt;
&lt;h4 id=&#34;after-the-creation&#34;&gt;After the creation&lt;/h4&gt;
&lt;p&gt;First, the Cloud-init drive, select the VM on the left and click on &lt;em&gt;Hardware&lt;/em&gt; then &lt;em&gt;Add&lt;/em&gt; and finally on Cloud Init Drive and select the storage where it will reside.&lt;/p&gt;
&lt;p&gt;Second, edit the BIOS (double click on the BIOS entry on the Hardware tab) and select &lt;em&gt;OVMF (UEFI)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Third, the EFI Disk, same process as the Cloudinit-drive, but now select &lt;em&gt;EFI Disk&lt;/em&gt; and select the storage where it will reside. It won&amp;rsquo;t let you create the drive before setting up the BIOS on the second step.&lt;/p&gt;
&lt;p&gt;Finally, start up the machine.&lt;/p&gt;
&lt;p&gt;Lets get it prepared for Cloud-Init, go on the VM and run this command:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;apt-get install cloud-init -y&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it, it&amp;rsquo;s set up now.&lt;/p&gt;
&lt;h3 id=&#34;using-debians-official-image-for-cloud-init&#34;&gt;Using Debian&amp;rsquo;s official image for Cloud-init.&lt;/h3&gt;
&lt;p&gt;You can also just go for the easy step and more straightforward even that the manual installation, download a ready-to-go image from Debian&amp;rsquo;s repositories. SSH into the node, or open a shell on the node through the GUI and run:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;wget http://cdimage.debian.org/cdimage/openstack/10.2.0/debian-10.2.0-openstack-amd64.qcow2&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Afterwards create a VM either through the GUI or through the command line, if you decide to do it with the graphic interface just do as I wrote earlier, on the CLI the commands are as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm create &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - name debian-10-template - memory &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt; - net0 virtio,bridge&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;vmbr0 - cores &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; - sockets &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; - cpu cputype&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;kvm64 - description &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Debian 10.2 cloud image&amp;#34;&lt;/span&gt; - kvm &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; - numa &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm importdisk &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; debian-10.2.0-openstack-amd64.qcow2 lvm-thin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - scsihw virtio-scsi-pci - virtio0 lvm-thin:vm-9000-disk-1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - serial0 socket
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - boot c - bootdisk virtio0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - agent &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - hotplug disk,network,usb,memory,cpu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - vcpus &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - vga qxl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - name debian-10-template
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - ide2 lvm-thin:cloudinit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm set &lt;span style=&#34;color:#ae81ff&#34;&gt;9000&lt;/span&gt; - sshkey /etc/pve/pub_keys/pub_key.pub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After you execute these commands you need to resize the disk to 10 GB, you can do this on the hardware tab for the VM&lt;/p&gt;
&lt;h3 id=&#34;installation&#34;&gt;Installation&lt;/h3&gt;
&lt;p&gt;Start up the machine and install some basic packages you&amp;rsquo;ll most likely use on all the machines in my case I usually go for these:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo apt install bmon screen ntpdate vim locate locales-all iotop atop curl libpam-systemd python-pip python-dev ifenslave vlan mysql-client sysstat snmpd sudo lynx rsync nfs-common tcpdump strace darkstat qemu-guest-agent&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;After these packages are installed shutdown the VM with:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;shutdown -h now&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;defining-thetemplate&#34;&gt;Defining the template&lt;/h3&gt;
&lt;p&gt;When the VM has been shutdown cleanly, you can proceed and convert it to a template, this can be done on the Proxmox GUI by right clicking on the VM and clicking on &amp;ldquo;Convert to Template&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Success, the template has been created.&lt;/p&gt;
&lt;h3 id=&#34;setting-up-the-proxmox-node-for-ansible-communication&#34;&gt;Setting up the Proxmox node for ansible communication&lt;/h3&gt;
&lt;p&gt;The proxmox node has to be set up with a python tool called &lt;code&gt;proxmoxer&lt;/code&gt;. This tool has the ability to behave like an ansible module, you can either run a playbook for the install or go in manually and proceed with the installation via SSH.&lt;/p&gt;
&lt;p&gt;With a console proceed with these commands and install the necessary packages on the node:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt install -y python-pip python-dev build-essential
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip update pip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install virtualenv
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install proxmoxer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;creating-our-ansible-directory-structure&#34;&gt;Creating our Ansible directory structure&lt;/h3&gt;
&lt;p&gt;We&amp;rsquo;re going to use a simple Ansible setup with the following structure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hosts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;playbooks
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|──proxmox_deploy.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;roles
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|──proxmox_deploy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── defaults
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── main.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── meta
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── main.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── tasks
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── main.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── vars
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── main.yml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| ── travis.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ansible-files&#34;&gt;Ansible files&lt;/h3&gt;
&lt;p&gt;You need to define several things on the ansible files, lets define the hosts file first.&lt;/p&gt;
&lt;p&gt;For the sake of this example we&amp;rsquo;re using two nodes, proxmox1 with the IP: 192.168.1.11 and proxmox2 with the IP: 192.168.1.12&lt;/p&gt;
&lt;p&gt;This definition only needs the proxmox nodes (in case you have more than one) and a group to be called:&lt;/p&gt;
&lt;h5 id=&#34;hosts&#34;&gt;hosts&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ansible&#34; data-lang=&#34;ansible&#34;&gt;[proxmox1]
proxmox1 ansible_ssh_host=192.168.1.11

[proxmox2]
proxmox2 ansible_ssh_host=192.168.1.12

[proxmoxs:children]
proxmox1
proxmox2
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The main playbook is setup as follows (playbooks/proxmox_deploy.yml):&lt;/p&gt;
&lt;h5 id=&#34;playbooksproxmox_deployyml&#34;&gt;playbooks/proxmox_deploy.yml&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ansible&#34; data-lang=&#34;ansible&#34;&gt;- name: &amp;#39;prep proxmox hosts for automation&amp;#39;
  hosts: &amp;#39;proxmox1&amp;#39;
  vars_prompt:
  - name: PV_password
    prompt: &amp;#34;Node Password&amp;#34;
    private: yes
  - name: VM_name
    prompt: &amp;#34;VM name&amp;#34;
    private: no
  - name: VM_network
    prompt: &amp;#34;Network associated to ipconfig0&amp;#34;
    private: no
    default: vlan10
  - name: VM_IP
    prompt: &amp;#34;VM IP&amp;#34;
    private: no
    default: 192.168.1.100
  - name: VM_sockets
    prompt: &amp;#34;VM socket/s&amp;#34;
    private: no
    default: 1
  - name: VM_cores
    prompt: &amp;#34;VM core/s&amp;#34;
    private: no
    default: 1
  - name: VM_memory
    prompt: &amp;#34;VM RAM Memory (MB)&amp;#34;
    private: no
    default: 1024
  - name: VM_INCREASE_DISK
    prompt: &amp;#34;Increase virtio0 disk (20 GB) in&amp;#34;
    private: no
    default: 0
  - name: PV_node
    prompt: &amp;#34;Migrate Virtual Machine to&amp;#34;
    private: no
    default: none
  user: root
  gather_facts: false
  roles:
    - { role: proxmox_deploy, default_proxmox_node: proxmox1 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This playbook defines the inputs that you, as a sysadmin/devops/computer-magician will need to input so the tasks can be completed successfully. &lt;em&gt;Note: It asks for a &amp;ldquo;Node password&amp;rdquo;, this is so the proxmoxer python module can communicate with the node, it uses Linux standard PAM authentication&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;These inputs encompass CPU Sockets, CPU Cores, Memory, IP, Disk size and target node in case you want to migrate the VM to another node after it&amp;rsquo;s finished the creation process.&lt;/p&gt;
&lt;p&gt;Then lets define the roles for this deployment, first with the &lt;code&gt;travis.yml&lt;/code&gt; file within the roles directory (roles/proxmox_deploy/travis.yml):&lt;/p&gt;
&lt;h5 id=&#34;rolesproxmox_deploytravisyml&#34;&gt;roles/proxmox_deploy/travis.yml&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ansible&#34; data-lang=&#34;ansible&#34;&gt;---
language: python
python: &amp;#34;2.7&amp;#34;

# Use the new container infrastructure
sudo: false

# Install ansible
addons:
	 apt:
		 packages:
			 - python-pip

install:
	 # Install ansible
	 - pip install ansible

	# Check ansible version
	 - ansible - version

	# Create ansible.cfg with correct roles_path
	 - printf &amp;#39;[defaults]\nroles_path=../&amp;#39; &amp;gt;ansible.cfg

script:
	 # Basic role syntax check
	 - ansible-playbook tests/test.yml -i tests/inventory - syntax-check

notifications:
	 webhooks: https://galaxy.ansible.com/api/v1/notifications/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Afterwards we set up the main.yml within the defaults directory (roles/proxmox_deploy/defaults/main.yml). Please note that it&amp;rsquo;s very important to adjust this file to concur with the template name you created on the template creation step:&lt;/p&gt;
&lt;h5 id=&#34;rolesproxmox_deploydefaultsmainyml&#34;&gt;roles/proxmox_deploy/defaults/main.yml&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ansible&#34; data-lang=&#34;ansible&#34;&gt;---
# defaults file for proxmox_deploy
VM_template: debian-10-template
default_disk: virtio0
default_interface: ens18
default_volume: /dev/vda
default_partition: 2
template_name: template-debian-deployment
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The handlers main.yml file is basically empty but needs to be defined (roles/proxmox_deploy/handlers/main.yml):&lt;/p&gt;
&lt;h5 id=&#34;rolesproxmox_deployhandlersmainyml&#34;&gt;roles/proxmox_deploy/handlers/main.yml&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ansible&#34; data-lang=&#34;ansible&#34;&gt;---
# handlers file for proxmox_deploy
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then define a very basic default template for the meta&amp;rsquo;s main.yml file, i&amp;rsquo;m just leaving it as a default template (roles/proxmox_deploy/meta/main.yml):&lt;/p&gt;
&lt;h5 id=&#34;rolesproxmox_deploymetamainyml&#34;&gt;roles/proxmox_deploy/meta/main.yml&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ansible&#34; data-lang=&#34;ansible&#34;&gt;galaxy_info:
	author: your name
	description: your description
	company: your company (optional)
	license: license (GPLv2, CC-BY, etc)
	min_ansible_version: 2.4
	galaxy_tags: []
dependencies: []
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The main.yml file for the vars directory is as follows (roles/proxmox_deploy/vars/main.yml), in here, some of the variables that you might need for a VM are set up, in this case i&amp;rsquo;m going to use two VLAN setups as an example. Adjust it to your own infrastructure:&lt;/p&gt;
&lt;h5 id=&#34;rolesproxmox_deployvarsmainyml&#34;&gt;roles/proxmox_deploy/vars/main.yml&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ansible&#34; data-lang=&#34;ansible&#34;&gt;# vars file for proxmox_deploy
vlan10:
	params:
		netmask: 24
		vmbr: 0
		gateway: 192.168.2.1
		dnsservers: &amp;#34;192.168.2.253 192.168.2.254&amp;#34;
		searchdomain: vectops.com
vlan11:
	params:
		netmask: 24
		vmbr: 1
		gateway: 192.168.3.130
		dnsservers: &amp;#34;192.168.3.253 192.168.3.254&amp;#34;
		searchdomain: vectops.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally the main file, the tasks&amp;rsquo; main.yml file (roles/proxmox_deploy/tasks/main.yml). All the actual work goes here, the playbook uses this to complete all of the deployment tasks:&lt;/p&gt;
&lt;h5 id=&#34;rolesproxmox_deploytasksmainyml&#34;&gt;roles/proxmox_deploy/tasks/main.yml&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ansible&#34; data-lang=&#34;ansible&#34;&gt;---
# tasks file for proxmox_deploy
    - name: Cloning virtual machine from &amp;#34;{{ VM_template }}&amp;#34; with name &amp;#34;{{ VM_name }}&amp;#34; 
      proxmox_kvm:
        api_user : root@pam
        api_password: &amp;#34;{{ PV_password }}&amp;#34;
        api_host : &amp;#34;{{ default_proxmox_node }}&amp;#34;
        name : &amp;#34;{{ VM_name }}&amp;#34;
        node : &amp;#34;{{ default_proxmox_node }}&amp;#34;
        clone: &amp;#34;{{ VM_template }}&amp;#34;
        timeout: 300
      tags: provission,test

    - name: Increasing disk if it is necessary
      shell: A=$(qm list |grep &amp;#34;{{ VM_name }}&amp;#34; | awk &amp;#39;{print $1}&amp;#39;); qm resize $A {{ default_disk }} +{{ VM_INCREASE_DISK }}G
      when: &amp;#39;&amp;#34;{{ VM_INCREASE_DISK }}&amp;#34; != &amp;#34;0&amp;#34;&amp;#39;
      tags: provission

    - name: Waiting to apply cloud init changes in disk
      wait_for:
      timeout: 5
      tags: provission

    - name: starting new Virtual Machine to change IPv4 configuration, it is necessary
      proxmox_kvm:
        api_user : root@pam
        api_password: &amp;#34;{{ PV_password }}&amp;#34;
        api_host : &amp;#34;{{ default_proxmox_node }}&amp;#34;
        name : &amp;#34;{{ VM_name }}&amp;#34;
        node : &amp;#34;{{ default_proxmox_node }}&amp;#34;
        state : started
        timeout: 300
      when: &amp;#39;&amp;#34;{{ VM_INCREASE_DISK }}&amp;#34; != &amp;#34;0&amp;#34;&amp;#39;
      register: wait
      tags: provission

    - name: Waiting to start virtual server machine completely
      wait_for:
        timeout: 45
      when: wait.changed == true 
      tags: provission

    - name: Resize disk
      shell: growpart &amp;#34;{{ default_volume }}&amp;#34; &amp;#34;{{ default_partition }}&amp;#34;; pvresize &amp;#34;{{ default_volume }}&amp;#34;&amp;#34;{{ default_partition }}&amp;#34;
      when: &amp;#39;&amp;#34;{{ VM_INCREASE_DISK }}&amp;#34; != &amp;#34;0&amp;#34;&amp;#39;
      delegate_to: &amp;#34;{{ template_name }}&amp;#34;
      tags: provission

    - name: stopping new Virtual Machine to change IPv4 configuration, it is necessary
      proxmox_kvm:
        api_user : root@pam
        api_password: &amp;#34;{{ PV_password }}&amp;#34;
        api_host : &amp;#34;{{ default_proxmox_node }}&amp;#34;
        name : &amp;#34;{{ VM_name }}&amp;#34;
        node : &amp;#34;{{ default_proxmox_node }}&amp;#34;
        state : stopped
        timeout: 300
      when: &amp;#39;&amp;#34;{{ VM_network }}&amp;#34; != &amp;#34;vlan10&amp;#34; or &amp;#34;{{ VM_INCREASE_DISK }}&amp;#34; != &amp;#34;0&amp;#34;&amp;#39;
      tags: provission

    - name: Loading set up for Virtual Machine. Assigning correct bridge in network interface
      shell: A=$(qm list |grep &amp;#34;{{ VM_name }}&amp;#34; | awk &amp;#39;{print $1}&amp;#39;); qm set $A - net0 &amp;#39;virtio,bridge=vmbr{{ item.value.vmbr }}&amp;#39;
      when: &amp;#39;&amp;#34;{{ VM_network }}&amp;#34; != &amp;#34;vlan10&amp;#34;&amp;#39;
      with_dict: &amp;#34;{{ vars[VM_network] }}&amp;#34;
      tags: provission

    - debug: 
        msg: &amp;#34;item.key {{ item.key }} item.value {{ item.value }} item.value.netmask {{ item.value.netmask }} item.value.vmbr {{ item.value.vmbr }}&amp;#34;
      with_dict: &amp;#34;{{ vars[VM_network] }}&amp;#34;
      tags: provission

    - name: Loading set up for Virtual Machine. Assigning IP, sockets, cores and memory for Virtual Machine
      shell: A=$(qm list |grep &amp;#34;{{ VM_name }}&amp;#34; | awk &amp;#39;{print $1}&amp;#39;); qm set $A - ipconfig0 &amp;#39;ip={{ VM_IP }}/{{ item.value.netmask }},gw={{ item.value.gateway }}&amp;#39; - nameserver &amp;#39;{{ item.value.dnsservers }}&amp;#39; - searchdomain &amp;#39;{{ item.value.searchdomain }}&amp;#39; - memory &amp;#39;{{ VM_memory }}&amp;#39; - sockets &amp;#39;{{ VM_sockets }}&amp;#39; - cores &amp;#39;{{ VM_cores }}&amp;#39;
      when: &amp;#39;&amp;#34;{{ VM_IP }}&amp;#34; != &amp;#34;automatic&amp;#34;&amp;#39;
      with_dict: &amp;#34;{{ vars[VM_network] }}&amp;#34;
      tags: provission

    - debug:
        var: current_ip
      tags: provission

    - name: Loading set up for Virtual Machine. Assigning IP automatically, sockets, cores and memory for Virtual Machine
      shell: A=$(qm list |grep &amp;#34;{{ VM_name }}&amp;#34; | awk &amp;#39;{print $1}&amp;#39;); qm set $A - ipconfig0 &amp;#39;ip={{ current_ip.stdout }}/{{ item.value.netmask }},gw={{ item.value.gateway }}&amp;#39; - nameserver &amp;#39;{{ item.value.dnsservers }}&amp;#39; - searchdomain &amp;#39;{{ item.value.searchdomain }}&amp;#39; - memory &amp;#39;{{ VM_memory }}&amp;#39; - sockets &amp;#39;{{ VM_sockets }}&amp;#39; - cores &amp;#39;{{ VM_cores }}&amp;#39;
      when: &amp;#39;&amp;#34;{{ VM_IP }}&amp;#34; == &amp;#34;automatic&amp;#34;&amp;#39;
      with_dict: &amp;#34;{{ vars[VM_network] }}&amp;#34;
      tags: provission

    - debug: 
        var: &amp;#34;{{ PV_node }}&amp;#34;

    - name: Migrating Virtual Machine if it is necessary
      shell: A=$(qm list |grep &amp;#34;{{ VM_name }}&amp;#34; | awk &amp;#39;{print $1}&amp;#39;);qm migrate $A &amp;#34;{{ PV_node }}&amp;#34;
      when: &amp;#39;&amp;#34;{{ PV_node }}&amp;#34; != &amp;#34;none&amp;#34;&amp;#39;
      tags: provission

    - name: starting new Virtual Machine in current proxmox node
      proxmox_kvm:
        api_user : root@pam
        api_password: &amp;#34;{{ PV_password }}&amp;#34;
        api_host : &amp;#34;{{ default_proxmox_node }}&amp;#34;
        name : &amp;#34;{{ VM_name }}&amp;#34;
        node : &amp;#34;{{ default_proxmox_node }}&amp;#34;
        state : started
        timeout: 300
      when: &amp;#39;&amp;#34;{{ PV_node }}&amp;#34; == &amp;#34;none&amp;#34;&amp;#39;
      tags: provission

    - name: starting new Virtual Machine in correct proxmox node
      proxmox_kvm:
        api_user : root@pam
        api_password: &amp;#34;{{ PV_password }}&amp;#34;
        api_host : &amp;#34;{{ PV_node }}&amp;#34; 
        name : &amp;#34;{{ VM_name }}&amp;#34;
        node : &amp;#34;{{ PV_node }}&amp;#34;
        state : started
        timeout: 300
      delegate_to: &amp;#34;{{ PV_node }}&amp;#34;
      when: &amp;#39;&amp;#34;{{ PV_node }}&amp;#34; != &amp;#34;none&amp;#34;&amp;#39;
      tags: provission
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This tasks file is pretty straightforward, it uses several steps, they&amp;rsquo;re defined as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Clones the template into a new VM&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;If you choose to increase the disk size, it does so on the hardware side.&lt;/li&gt;
&lt;li&gt;Applies Cloudinit configurations&lt;/li&gt;
&lt;li&gt;Starts the VM and waits for it to start&lt;/li&gt;
&lt;li&gt;Resizes the partition so it fits the new disk size (in case you did change it)&lt;/li&gt;
&lt;li&gt;Stops the VM so it can apply the IP configuration&lt;/li&gt;
&lt;li&gt;Assigns the correct network hardware properties, in case they need to be changed.&lt;/li&gt;
&lt;li&gt;Configures the necessary hardware properties for the VM (cpu, memory, etc.)&lt;/li&gt;
&lt;li&gt;If you chose to migrate it on the prompt, it will perform a migration of the VM to a target node&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;thats-it&#34;&gt;That&amp;rsquo;s it&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s it, with this playbook you can easily deploy VMs on proxmox, fully configured to your needs with a simple ansible command:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ansible-playbook playbooks/proxmox_deploy.yml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I hope this helps you out as much as it has helped me to simplify and speed up the process of creating new classic virtual instances on Proxmox.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Backup your Docker containers, the lazy way</title>
        <link>https://vectops.com/post/2020/backup-your-docker-containers-the-lazy-way/</link>
        <pubDate>Wed, 08 Jan 2020 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2020/backup-your-docker-containers-the-lazy-way/</guid>
        <description>&lt;img src="https://vectops.com/post/2020/backup-your-docker-containers-the-lazy-way/image.png" alt="Featured image of post Backup your Docker containers, the lazy way" /&gt;&lt;blockquote&gt;
&lt;p&gt;Disclaimer:&lt;/p&gt;
&lt;p&gt;This method is valid for when you don&amp;rsquo;t have access to persist data from within the container to the host where it is running.
To persist data on Docker containers it is recommended to rely on &lt;a class=&#34;link&#34; href=&#34;https://docs.docker.com/storage/volumes/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Docker volumes&lt;/a&gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ever wanted to save a snapshot of all your Docker containers but never had the time or even the energy to write a script that can do that for you? Don&amp;rsquo;t worry, we are here for that reason.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s just say you save these snapshots under the /backup directory of your system. Then you just will run this magic one-liner:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;for CONTAINER in $(docker ps -a --format &amp;#39;{{.Names}}&amp;#39;); do
	docker export $(docker ps -a |grep $CONTAINER \
	|awk &amp;#39;{print $1}&amp;#39;) &amp;gt; /backup/backup_${CONTAINER}_$(date +%d-%m-%Y).tar
done
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will save the container&amp;rsquo;s current filesystem as a tarball.&lt;/p&gt;
&lt;p&gt;However, remember that the &lt;code&gt;docker export&lt;/code&gt; command &lt;strong&gt;DOES NOT&lt;/strong&gt; include a copy of the contents of the volumes associated to the containers, as you can read in the &lt;a class=&#34;link&#34; href=&#34;https://docs.docker.com/engine/reference/commandline/export/&#34;  title=&#34;official Docker documentation&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;official Docker documentation&lt;/a&gt;. For that purpose you will have to mess around with another kind of solutions such as file synchronization directly over the directories linked to the volumes or so.&lt;/p&gt;
&lt;p&gt;Also, because of how it works, the &lt;code&gt;docker export&lt;/code&gt; command  will remove the entrypoint and the container&amp;rsquo;s history, making it useful only if you want to access the container&amp;rsquo;s information, but not if you look for running the image as a container again. The way you would access to it is first creating a new image from the tarball:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker import /backup/backup_${CONTAINER}_$(date +%d-%m-%Y).tar ${IMAGE_NAME}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then running a container based on the new image, like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker run -ti ${IMAGE_ID} /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you are seeking to save a copy of a existing container keeping its information as it is, you would have to use the &lt;code&gt;commit&lt;/code&gt; function in order to generate a new image based on the current container, like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker commit ${CONTAINER} ${IMAGE_NAME}_$(date +%d-%m-%Y)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then you can export it to a new tarball:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker save &amp;gt; /backup/${IMAGE_NAME}_$(date +%d-%m-%Y).tar
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, if this is what you are looking to do with all your containers, you can run:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;for CONTAINER in $(docker ps -a --format &amp;#39;{{.Names}}&amp;#39;); do
	docker commit $(docker ps -a |grep $CONTAINER \
	|awk &amp;#39;{print $1}&amp;#39;) ${CONTAINER}_$(date +%d-%m-%Y)
	docker save &amp;gt; ${CONTAINER}_$(date +%d-%m-%Y)
done
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And finally if you want to import your images from the tar files you can run:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker load  &amp;lt; /backup/${IMAGE_NAME}_$(date +%d-%m-%Y).tar
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See you next time!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How jq can save your job in simple ways</title>
        <link>https://vectops.com/post/2019/how-jq-can-save-your-job-in-simple-ways/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/how-jq-can-save-your-job-in-simple-ways/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/how-jq-can-save-your-job-in-simple-ways/image.png" alt="Featured image of post How jq can save your job in simple ways" /&gt;&lt;p&gt;While checking the ticketing system for my company I noticed there was a new reply for a ticket that had been in hiatus for quite a while (hiatus as in it was opened and no one checked it for whatever reason, maybe someone was too busy and no it wasn&amp;rsquo;t on the backlog queue). The new message said something like: &amp;lsquo;Hey guys? is this happening? ever?&amp;rsquo;&lt;/p&gt;
&lt;p&gt;So, I had some free time and decided to act on it. An API needed to be monitored. The API had several endpoints defined, all of which gave crucial information about the application instance that was deployed on the server. The information is presented on a JSON format and has the &lt;code&gt;value&lt;/code&gt; entry defined with the values that needed monitoring.&lt;/p&gt;
&lt;p&gt;Now, I&amp;rsquo;m not an expert on JSON, however the format isn&amp;rsquo;t too hard to understand and after checking some documentation and a couple of google searches it&amp;rsquo;s easily manageable. With a general understanding about the works on Bash, and a general understanding that&amp;rsquo;s basically summarized in two words -&amp;gt; google-fu (as 99% of sysadmins I know are too afraid to admit this publicly, I will).&lt;/p&gt;
&lt;h2 id=&#34;analizing&#34;&gt;Analizing&lt;/h2&gt;
&lt;p&gt;After checking the API&amp;rsquo;s URL with &lt;code&gt;curl&lt;/code&gt; I could tell there were some endpoints presented. All of the endpoints the developers needed to be monitored in fact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: If you don&amp;rsquo;t want an explanation for this and just wanna see the script, it&amp;rsquo;s posted at the end of this article&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To do this all you need to use is a one-liner on the terminal such as this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s http://amazingapi.local/api
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Note: you could use curl with any URL, be it with a domain name or an IP without DNS, if you need to get some more instructions about it feel free to consult the man pages for the command using &lt;code&gt;man curl&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;working-with-json&#34;&gt;Working with JSON&lt;/h2&gt;
&lt;p&gt;After checking the output from the curl command we get something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s http://amazingapi.local/api
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;names&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.memory.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jdbc.connections.active&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.files.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.memory.promoted&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.cache.hit&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;system.load.average.1m&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.cache.access&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.memory.used&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.max.data.size&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jdbc.connections.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jdbc.connections.min&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.pause&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.memory.committed&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http.server.requests&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;system.cpu.count&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.sent&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.buffer.memory.used&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.created&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.threads.daemon&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;system.cpu.usage&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.memory.allocated&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.request.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.idle&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.pending&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.request&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.expired&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.threads.live&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.threads.peak&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.received&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.active&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.creation&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.uptime&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.rejected&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.cpu.usage&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.threads.config.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.classes.loaded&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.min&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.classes.unloaded&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.error&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.active.current&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.alive.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.live.data.size&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.servlet.request.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.usage&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.threads.current&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.servlet.request&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.timeout&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.files.open&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.buffer.count&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.buffer.total.capacity&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.active.max&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.acquire&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.threads.busy&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.start.time&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.servlet.error&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not many people will read the entire output, first of all because even though it&amp;rsquo;s on a JSON format, it&amp;rsquo;s minimized so it&amp;rsquo;s not as easy to follow, however this is where our new best friend when it comes to JSON comes in: &lt;em&gt;jq&lt;/em&gt;. If you pipe the output from the curl command into &lt;em&gt;jq&lt;/em&gt; we can see something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s http://amazingapi.local/api | jq
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;names&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.memory.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http.server.requests&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jdbc.connections.active&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.files.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.memory.promoted&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.cache.hit&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;system.load.average.1m&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.cache.access&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.memory.used&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.max.data.size&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jdbc.connections.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jdbc.connections.min&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.pause&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.memory.committed&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;system.cpu.count&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.sent&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.buffer.memory.used&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.created&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.threads.daemon&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;system.cpu.usage&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.memory.allocated&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.request.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.idle&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.pending&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.request&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.expired&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.threads.live&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.threads.peak&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.received&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.active&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.creation&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.uptime&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.rejected&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.cpu.usage&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.threads.config.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.classes.loaded&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.min&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.classes.unloaded&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.global.error&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.active.current&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.alive.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.gc.live.data.size&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.servlet.request.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.usage&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.threads.current&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.servlet.request&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.timeout&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.files.open&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.buffer.count&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.buffer.total.capacity&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.sessions.active.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hikaricp.connections.acquire&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.threads.busy&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;process.start.time&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tomcat.servlet.error&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you need to install &lt;em&gt;jq&lt;/em&gt;, it&amp;rsquo;s as simple as: &lt;code&gt;apt install jq -y&lt;/code&gt; on Debian based distros or &lt;code&gt;yum install jq -y&lt;/code&gt; on RHEL based distros.&lt;/p&gt;
&lt;p&gt;This is A LOT easier to understand, and we start finding a small issue, there&amp;rsquo;s a lot of endpoints. There&amp;rsquo;s a few ways to create a script to monitor an API, most of them involve creating a single script for a single API, however there&amp;rsquo;s many APIs to be monitored in both this company&amp;rsquo;s infrastructure or whichever we want to explore.&lt;/p&gt;
&lt;h2 id=&#34;reasoning&#34;&gt;Reasoning&lt;/h2&gt;
&lt;p&gt;In this specific case a few developers told me that not all of the APIs had the same endpoints but most of them didn&amp;rsquo;t need credentials since they were filtered by IPs, so it made the task a lot easier. I won&amp;rsquo;t go on details on how to do this against an authenticated API, maybe on another article; but implementing a token based authentication or a credentials based authentication on the script shouldn&amp;rsquo;t take more than a couple of lines.&lt;/p&gt;
&lt;p&gt;Back to the API. As you and I can see, there&amp;rsquo;s a lot of endpoints and we don&amp;rsquo;t know if those are going to change any day, some deleted, some added. We need to make a script that can adapt and be set up within our monitorization tool to take into account the new changes. Also, this API is served from a Tomcat application, this doesn&amp;rsquo;t need to be the case always.&lt;/p&gt;
&lt;p&gt;Since we can get the Endpoint list from the &lt;code&gt;curl&lt;/code&gt; command we executed earlier, we can also check for a specific endpoint. In the case of the first entry: &lt;em&gt;jvm.memory.max&lt;/em&gt; we can do this:&lt;/p&gt;
&lt;h2 id=&#34;selecting-values&#34;&gt;Selecting values&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s http://amazingapi.local/api/jvm.memory.max | jq
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;jvm.memory.max&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;The maximum amount of memory in bytes that can be used for memory management&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;baseUnit&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;measurements&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;statistic&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;VALUE&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;33096204287&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;availableTags&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tag&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;area&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;values&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;heap&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nonheap&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tag&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;values&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Compressed Class Space&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PS Survivor Space&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PS Old Gen&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Metaspace&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PS Eden Space&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Code Cache&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Awesome, we see the value that the API provides as well as a few extra data that doesn&amp;rsquo;t serve much purpose for our needs right now and we won&amp;rsquo;t dwelve on it too much. The main attribute we want from the JSON output is the &lt;em&gt;VALUE&lt;/em&gt; entry, which belongs on the measurements array:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;measurements&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;statistic&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;VALUE&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;33096204287&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;options-for-jq&#34;&gt;Options for jq&lt;/h2&gt;
&lt;p&gt;With &lt;em&gt;jq&lt;/em&gt; we can get an array from within an object with single quotes and the brackets to denote an array, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s http://amazingapi.local/api/jvm.memory.max | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.measurements[]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;statistic&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;VALUE&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;33096204287&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In case we want to get a specific entry from the array we can go further in and get the specific value we need:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s http://amazingapi.local/api/jvm.memory.max | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.measurements[]&amp;#39;&lt;/span&gt; | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;33096204287&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That number that outputs from the command is &amp;ldquo;The maximum amount of memory in bytes that can be used for memory management&amp;rdquo; as stated by the previous query we did against the API. This number can be converted a bunch of different ways from the script, however we won&amp;rsquo;t because we need the script to be as frugal as possible so it can be used with many APIs and many endpoints.&lt;/p&gt;
&lt;p&gt;Now, we know how to get a specific value from an endpoint using &lt;em&gt;curl&lt;/em&gt;, we just need to script it into something that can be used by monitoring software. Since most monitoring software allows bash scripts or sh or ksh or whichever shell is installed on the monitoring software&amp;rsquo;s host machine we&amp;rsquo;ll just use Bash.&lt;/p&gt;
&lt;h2 id=&#34;scripting&#34;&gt;Scripting&lt;/h2&gt;
&lt;p&gt;Please note that this script relies on some text manipulation that can be understood using the man pages on your linux console. This script might look kinda hard to read at first (sorry, not sorry) but it&amp;rsquo;s pretty simple once you actually go line through line.&lt;/p&gt;
&lt;p&gt;Lets start with the first segment:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; -z $1 &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt; ; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;This script has to be used with two parameters&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Usage:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;check_api.sh &amp;lt;api_url&amp;gt; &amp;lt;endpoint&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;e.g.:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  check_api.sh http://exampleurl.com/api cpu.sys.util&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We just initialize the script and put in a description, if the script doesn&amp;rsquo;t receive the parameters it expects on startup its going to show some help message and an example.&lt;/p&gt;
&lt;p&gt;Afterwards we define a couple of variables to be used:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;url&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;probe&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;endpoints&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;curl -s $1 | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.names[]&amp;#39;&lt;/span&gt;| awk -F&lt;span style=&#34;color:#ae81ff&#34;&gt;\&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;|cut -c 1-&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These variables do simple jobs. The first two are set up to receive the parameters from the script execution, the third one is the command that gets the enpoint list from the API server (like we discovered earlier).&lt;/p&gt;
&lt;p&gt;Then we input the endpoint list onto an array defined as: endpointsarray:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;endpointsarray&lt;span style=&#34;color:#f92672&#34;&gt;=(&lt;/span&gt; $endpoints &lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally the actual magic:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i in &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;endpointsarray[@]&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        specs&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;curl -s $1$i | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.measurements[]&amp;#39;&lt;/span&gt; | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        echo $i $specs |grep $probe | cut -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; -f2-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This for loop just goes through the array and gets the value from the endpoint. It has some text manipulation due to the fact that the script is going to throw out some information that&amp;rsquo;s not needed, in case you wanna see some of it you&amp;rsquo;re free to experiment with the script, try seeing what the &lt;em&gt;cut&lt;/em&gt; command does on it.&lt;/p&gt;
&lt;p&gt;Hopefully this has thrown some light onto some things that may need some light. Full script as follows.&lt;/p&gt;
&lt;h3 id=&#34;final-script&#34;&gt;Final Script&lt;/h3&gt;
&lt;p&gt;TL;DR: Script that gets all endpoints from an API and gets the values from a single endpoint:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; -z $1 &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt; ; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;This script has to be used with two parameters&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Usage:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;check_api.sh &amp;lt;api_url&amp;gt; &amp;lt;endpoint&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;e.g.:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  check_api.sh http://exampleurl.com/api cpu.sys.util&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;url&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;probe&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;endpoints&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;curl -s $1 | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.names[]&amp;#39;&lt;/span&gt;| awk -F&lt;span style=&#34;color:#ae81ff&#34;&gt;\&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;|cut -c 1-&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;endpointsarray&lt;span style=&#34;color:#f92672&#34;&gt;=(&lt;/span&gt; $endpoints &lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i in &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;endpointsarray[@]&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        specs&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;curl -s $1$i | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.measurements[]&amp;#39;&lt;/span&gt; | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        echo $i $specs |grep $probe | cut -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; -f2-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        </item>
        <item>
        <title>Installing Arch Linux base (with UEFI inside!)</title>
        <link>https://vectops.com/post/2019/installing-arch-linux-base-with-uefi-inside/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/installing-arch-linux-base-with-uefi-inside/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/installing-arch-linux-base-with-uefi-inside/image.png" alt="Featured image of post Installing Arch Linux base (with UEFI inside!)" /&gt;&lt;p&gt;We&amp;rsquo;ve all strugled with installing Linux systems from scratch such as Arch or Gentoo, specially the first time we do so.&lt;/p&gt;
&lt;p&gt;Up next is the most basic Arch Linux install you can achieve on a system without things breaking. While using an UEFI partition of course.&lt;/p&gt;
&lt;h2 id=&#34;requirements&#34;&gt;Requirements&lt;/h2&gt;
&lt;p&gt;Before anything starts you need to have an USB Drive with the &lt;a class=&#34;link&#34; href=&#34;https://www.archlinux.org/download/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Arch ISO&lt;/a&gt; on it. You can use whatever tool you want for this, including but not exclusively: &lt;a class=&#34;link&#34; href=&#34;https://www.balena.io/etcher/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Etcher&lt;/a&gt;, &lt;a class=&#34;link&#34; href=&#34;https://unetbootin.github.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;UNetbootin&lt;/a&gt; or even &lt;a class=&#34;link&#34; href=&#34;https://www.linuxliveusb.com/en/download&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;LiLi&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In case you&amp;rsquo;re doing this on a virtual machine, just have the ISO on hand as the virtualizer will need it.&lt;/p&gt;
&lt;h2 id=&#34;formatting&#34;&gt;Formatting&lt;/h2&gt;
&lt;p&gt;First off, boot the machine with the ISO or the USB drive.&lt;/p&gt;
&lt;p&gt;You should take into account that this is going to format the drive on the machine you&amp;rsquo;re booting. I&amp;rsquo;ll say it again:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Caution, the following commands will erase the drive you&amp;rsquo;re using for the install, any data inside of them might be unrecoverable.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;efi-partition&#34;&gt;EFI Partition&lt;/h3&gt;
&lt;p&gt;After the machine has been booted we&amp;rsquo;ll be presented with a prompt, from there we can use &lt;code&gt;gdisk&lt;/code&gt; to do the disk formatting. In this case you&amp;rsquo;re presented with the drive &lt;code&gt;/dev/sda&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gdisk /dev/sda
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From gdisk delete any content that might be on the drive:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;o
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Create a new partition, in this case the EFI partition which will allow you to boot the machine with UEFI:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Press &lt;em&gt;enter&lt;/em&gt; until you&amp;rsquo;re prompted with the size of the &amp;ldquo;Last Sector&amp;rdquo; and input the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+512M
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then select the type of filesystem that will be on the partition, since this is an EFI partition the code is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;EF00
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;boot-partition&#34;&gt;Boot Partition&lt;/h3&gt;
&lt;p&gt;Afterwards we just create the main root partition for the system install:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To write these changes just press:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;w
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These steps will create two partitions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/dev/sda1 -&amp;gt; EFI Partition&lt;/li&gt;
&lt;li&gt;/dev/sda2 -&amp;gt; Root Partition&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;filesystem&#34;&gt;Filesystem&lt;/h2&gt;
&lt;p&gt;After the partition table has been created you can define the filesystems for the installation, for the EFI partition you need a vFAT filesystem, you can define it as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkfs.vfat /dev/sda1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As for the root partition, lets run things a little classic with ext4:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkfs.ext4 /dev/sda2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then mount them for the OS install, the /boot directory is created so the EFI has a place to be mounted on:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mount /dev/sda2 /mnt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir /mnt/boot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mount /dev/sda1 /mnt/boot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;actual-installation&#34;&gt;Actual Installation&lt;/h2&gt;
&lt;p&gt;The fun part, you first need to select a mirror, the pacman repos have a lot of mirror worldwide, you can select the one that suits you the most, I won&amp;rsquo;t go into detail on how to decide since it depends on a lot of factors. Usually the one within your own country or the one closest to you should work best. You can find the repo list and edit it with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vi /etc/pacman.d/mirrorlist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Strap it!, you can install the actual OS with the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pacstrap /mnt base base-devel
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This step will take a bit, depending on the type of drive you&amp;rsquo;re installing to, the speed of the machine and the speed of the USB drive, go and grab a cup of cofee on the meantime.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;ll be done soon enough, you still need to install the bootloader for the machine to be able to boot into your new and shiny Arch installation.&lt;/p&gt;
&lt;h2 id=&#34;installing-the-bootloader&#34;&gt;Installing the bootloader&lt;/h2&gt;
&lt;p&gt;Installing the bootloader is pretty straightforward, in the case of Arch it&amp;rsquo;s kind of more hands-on than the other more user-friendly Linux distros such as ubuntu or other Arch derivatives such as Mandriva but it&amp;rsquo;s not as hard the old days&amp;hellip; anyhow:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arch-chroot /mnt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bootctl install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And edit the bootloader&amp;rsquo;s configuration file with: &lt;code&gt;vi /boot/loader/loader.conf&lt;/code&gt; and just leave the following entries (delete everything else):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;default arch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;timeout &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the final bootloader configuration we need to get the PARTUUID for the partition, do this with &lt;code&gt;blkid&lt;/code&gt; and set it up on the entry for the Arch boot:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vi /boot/loader/entries/arch.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;title Arch Linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;linux /vmlinuz-linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;initrd /initramfs-linux.img
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;options root&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;PARTUUID&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;YOUR_/dev/sda2_PARTUUID&amp;#34;&lt;/span&gt; rw
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, &lt;strong&gt;YOUR_/dev/sda2_PARTUUID = The PARTUUID you got from the command: blkid&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;finishing-up&#34;&gt;Finishing up&lt;/h2&gt;
&lt;p&gt;For the final step, and as a recommendation to avoid future lack of basic software components, just install some basic dependencies for the machine:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pacman -S linux linux-headers linux-firmware netctl dhcpcd mkinitcpio wpa_supplicant
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also, don&amp;rsquo;t forget to change the password, unless you want to watch how it boots up and you&amp;rsquo;re not even able to log in:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;passwd
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;aaaaaaaand reboot:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;reboot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There you go. You just installed a base Arch system, now go ahead and hack it up so it resembles whatever you want and whatever you want to use it for.&lt;/p&gt;
&lt;p&gt;Good luck!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Kernel mishaps on the network stack</title>
        <link>https://vectops.com/post/2019/kernel-mishaps-on-the-network-stack/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/kernel-mishaps-on-the-network-stack/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/kernel-mishaps-on-the-network-stack/image.png" alt="Featured image of post Kernel mishaps on the network stack" /&gt;&lt;p&gt;For a couple of months we&amp;rsquo;ve had some issues with the one of our servers, the issue was summarized as follows:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dev: I can&amp;rsquo;t connect to the server right now&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ops: What do you mean?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dev: Connections time out&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ops: I can connect, we can connect, everyone can connect. Stop messing with your OS settings.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dev: &amp;hellip;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Half an hour passes&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ops: Oh shit I can&amp;rsquo;t connect now.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dev: :)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now this incident happened a few times over the course of a few months, but since this was only happening from our offices and the server was located at the colocation site we thought it was something between the office and the datacenter. We could, however, connect to the server by jumping from any other server at the datacenter. This, of course, was not optimal but we managed to push the issue onto backlog since we had several other critical incidents to take into account.&lt;/p&gt;
&lt;p&gt;After checking everything on the network we noticed something was off about the server. We couldn&amp;rsquo;t reproduce the issue on any server, including this one, totally intermitent and it didn&amp;rsquo;t point towards anything else other than the server.&lt;/p&gt;
&lt;h2 id=&#34;getting-down-to-it&#34;&gt;Getting down to it&lt;/h2&gt;
&lt;p&gt;One day, I had some time to kill so I decided to take a kick at it. Note that this isn&amp;rsquo;t the best way to &amp;ldquo;kill time&amp;rdquo;, you&amp;rsquo;ll end up trying to kill the guys next to you after a few hours of nothing making sense.&lt;/p&gt;
&lt;p&gt;So, I connected to the server via SSH, via mysql remote connection (port 3306), http, https, and a few others and couldn&amp;rsquo;t reproduce the issue. Checked it on a few other pc&amp;rsquo;s, Windows, Linux, Mac, a Solaris VM I carry around, nothing under the sun or above it could not connect. Wait it is.&lt;/p&gt;
&lt;p&gt;After a few hours one of the computers failed to be able to connect, mine (praise the luck gods). So I started checking for eberything within that machine, connected via another machine on the Datacenter&amp;rsquo;s network.&lt;/p&gt;
&lt;p&gt;Now, this machine had a few kernel parameters set up since it needed to use a few thousand connections every few hours due to some hadoop processes that were supposed to run on it, for more information check this article we wrote about it: &lt;a class=&#34;link&#34; href=&#34;https://gryffinroot.com/articles/reusing-tcp-ports-for-fun-profit-and-lack-of-headaches&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;searching-searching-searching&#34;&gt;Searching, searching, searching&amp;hellip;&lt;/h2&gt;
&lt;p&gt;Then our almighty friend Google came in, then it&amp;rsquo;s less mighty friend Bing, then DuckDuckGo, then I was there looking at my screen with a few dozen tabs open with nothing to show for it and a light headache.&lt;/p&gt;
&lt;p&gt;So I started looking at the networking stack within Linux and checking the network statistics recorded by the kernel itself. You can check these with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;netstat -s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output for the &lt;code&gt;netstat -s&lt;/code&gt; command left me with more questions than answers but something stood out of the terminal staring straight to my face:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;35544811584&lt;/span&gt; SYNS to LISTEN sockets dropped
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This can happen since the Linux network stack is designed to avoid SYN floods by default and this counter is almost never zero because of false positives, however this doesn&amp;rsquo;t hinder the performance or the usability of the system. In case you want to learn more about SYN Flood attacks &lt;a class=&#34;link&#34; href=&#34;https://www.cloudflare.com/learning/ddos/syn-flood-ddos-attack/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;read here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-culprit&#34;&gt;The culprit&lt;/h2&gt;
&lt;p&gt;Other than the &lt;em&gt;SYNS to LISTEN sockets dropped&lt;/em&gt; I noticed another couple entries:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;7008728&lt;/span&gt; invalid SYN cookies received
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10703&lt;/span&gt; packets collapsed in receive queue due to low socket buffer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These entries looked strange to me, I know this is a server but those numbers looked way too high for a server that wasn&amp;rsquo;t exposed to external networks.&lt;/p&gt;
&lt;p&gt;After checking a lot more documentation than I should have about those entries which, by the way, is like reading a legal book with it&amp;rsquo;s own technical language that no one but kernel developers seem to understand. I decided to go back to the kernel config at:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/etc/sysctl.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And noticed this (this was copied verbatim straight from the server):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vm.overcommit_memory &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_fin_timeout&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vm.swappiness&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#net.core.somaxconn = 1024&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#fs.file-max = 1311072&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_max_syn_backlog &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;16192&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.core.somaxconn &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vm.nr_hugepages&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;512&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_tw_recycle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_tw_reuse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.netfilter.nf_conntrack_tcp_timeout_established&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The entry for &lt;code&gt;net.ipv4.tcp_tw_reuse = 1&lt;/code&gt; was added by us on the article about &lt;a class=&#34;link&#34; href=&#34;https://gryffinroot.com/articles/reusing-tcp-ports-for-fun-profit-and-lack-of-headaches&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;reusing TCP ports&lt;/a&gt; but these other entries don&amp;rsquo;t match what I was expecting for this server to have configured. However, these sounded familiar and I decided to up the scale on some of them, including the &lt;code&gt;tcp_max_syn_backlog&lt;/code&gt; and the &lt;code&gt;somaxconn&lt;/code&gt;, adapting them to the memory quantities this server has, not outdated numbers for 4GB systems (this node has 512GB of RAM and averages 200GB free RAM, it can afford to give a few megs to the kernel)&lt;/p&gt;
&lt;p&gt;But one other entry popped right at my eyes, after hours and hours of searching and watching for logs, and command outputs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_tw_recycle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;fixing-the-issue&#34;&gt;Fixing the issue&lt;/h2&gt;
&lt;p&gt;Let me explain. tcp_tw_reuse and tcp_tw_recycle should be used when server and client timestamps are enabled, by default they are. tcp_tw_reuse only works for the client, tcp_tw_recycle works for both the client and the server, it reclaims the socket after 3.5*RTO (RTO=Retransmission timeout, if you want to read more about RTO, &lt;a class=&#34;link&#34; href=&#34;https://tools.ietf.org/html/rfc6298&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;check this out&lt;/a&gt;) after opening the connection. In the case of LANs the retransmission is really fast since there&amp;rsquo;s basically no delay on the network so the server tries to recycle connections faster than they can be used, hence the no connection after a while.&lt;/p&gt;
&lt;p&gt;Basically the server says &amp;ldquo;Nope, you already connected, I&amp;rsquo;m recycling your connection for something else&amp;rdquo;. But what else? &amp;hellip;&lt;/p&gt;
&lt;p&gt;The solution, after months, turns out to be disabling the entry. Just comment it out altogether from the &lt;code&gt;sysctl.conf&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_tw_recycle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And reload it with a:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysctl -p
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yeap, a few hours wasted, buuuuuuuuut. Now I know how the Linux network stack works, I&amp;rsquo;ll have a future article about it soon.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Recover an overwritten script from memory</title>
        <link>https://vectops.com/post/2019/recovering-an-overwritten-script-from-memory/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/recovering-an-overwritten-script-from-memory/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/recovering-an-overwritten-script-from-memory/image.png" alt="Featured image of post Recover an overwritten script from memory" /&gt;&lt;p&gt;Recently I had a co-worker do an &lt;em&gt;oopsie&lt;/em&gt; on a server he was running a script on. He, actually wisely, executed a script on a screen within his terminal while connected to a production server. Now, this is all standard, what isn&amp;rsquo;t standard is that he somehow managed to overwrite the script (&lt;strong&gt;while in execution&lt;/strong&gt;) on another terminal with a one-liner.&lt;/p&gt;
&lt;p&gt;This script took a while to run so it was still running after he reported the issue to me. This is atleast 2 days of work from him, a guy that actually knows what he&amp;rsquo;s doing (unlike me :D ).&lt;/p&gt;
&lt;p&gt;So I remembered from my old days that you could output a script from memory using GDB as debugger, so after a few &lt;code&gt;man&lt;/code&gt; searches and a few hairs pulled out of my head (maybe a few from his head) and found a very useful command from within GDB to help us with this.&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t give you the actual script recovery, however I can replicate it.&lt;/p&gt;
&lt;h2 id=&#34;testing-script&#34;&gt;Testing script&lt;/h2&gt;
&lt;p&gt;Assuming you have GDB we can replicate this procedure, if you don&amp;rsquo;t, you&amp;rsquo;re dead on the water. Just kidding, you can install it on whatever distro with the package &lt;code&gt;gdb&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with a &lt;strong&gt;very&lt;/strong&gt; simple script within a &lt;em&gt;screen&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; true; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sleep 1; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Running...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the meantime we can leave the screen with &lt;code&gt;Ctrl+A+D&lt;/code&gt; and then proceed to do some process debugging.&lt;/p&gt;
&lt;h2 id=&#34;pids-everywhere&#34;&gt;PIDs everywhere&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start with getting the PID for the process:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ps -ef | grep bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this case we find the following output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root       &lt;span style=&#34;color:#ae81ff&#34;&gt;436&lt;/span&gt;   &lt;span style=&#34;color:#ae81ff&#34;&gt;410&lt;/span&gt;  &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; 19:14 pts/0    00:00:00 /bin/bash ./while.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;debugging-our-way-into-the-script&#34;&gt;Debugging our way into the script&lt;/h2&gt;
&lt;p&gt;We want the PID number which is &lt;em&gt;436&lt;/em&gt;, so we attach ourselves to the process with our favorite open source debugger:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gdb -p &lt;span style=&#34;color:#ae81ff&#34;&gt;436&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now what we&amp;rsquo;re attached we enter the gdb prompt that will &lt;strong&gt;pause&lt;/strong&gt; the process excecution while we&amp;rsquo;re attached, take this into account as it prevents a lot of stress thinking the process is going to end and lose everything we&amp;rsquo;re trying to rescue. Also, generate a core file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; generate-core-file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which will generate, you guessed it, a &lt;em&gt;core file&lt;/em&gt;, with the output: &lt;code&gt;Saved corefile core.436&lt;/code&gt;. This core file has everything in-memory regarding the process in execution, including our bash script. However we don&amp;rsquo;t want to suddenly stop the execution of the process so we &lt;em&gt;detach&lt;/em&gt; from it using the command (insert obviousness here):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; detach
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we exit the debugger:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; quit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;analizing&#34;&gt;Analizing&lt;/h2&gt;
&lt;p&gt;This output is a binary file that isn&amp;rsquo;t stored as clear text, if we try to use cat to outpit it&amp;rsquo;s contents the system will say something like &lt;code&gt;cat: write error: Input/output error&lt;/code&gt; so we use &lt;em&gt;strings&lt;/em&gt; to make it usable as clear text (don&amp;rsquo;t have it? install it):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;strings core.436 &amp;gt; rescuescript.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And within the dump we can find our script in clear text, however don&amp;rsquo;t be so hopeful and happy yet, core files can have a &lt;strong&gt;lot&lt;/strong&gt; of data that isn&amp;rsquo;t useful for us, so be patient!. Anyway here&amp;rsquo;s the script we found on the core file (on line 10509, hence the need for patience):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; true; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sleep 1; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Running...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et voilà!&lt;/p&gt;
&lt;p&gt;Hope you don&amp;rsquo;t &lt;em&gt;ever&lt;/em&gt; need to use this. Good luck if you do!&lt;/p&gt;</description>
        </item>
        <item>
        <title>Retiring a Proxmox cluster node the right way</title>
        <link>https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/image.png" alt="Featured image of post Retiring a Proxmox cluster node the right way" /&gt;&lt;p&gt;&lt;em&gt;Disclaimer: Following the Official Proxmox documentation of course :p&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When retiring a Proxmox cluster node from a cluster you need to take into account several things.&lt;/p&gt;
&lt;p&gt;Not very often you find yourself with the opportunity to retire a server and install a new one. Especially a new, shiny one with all the best bells and whistles a provider can give. Or you can find yourself finding that a node has broken down and it&amp;rsquo;s not worth it to fix it, might as well replace it.&lt;/p&gt;
&lt;p&gt;In case one of these machines belongs on a Proxmox Cluster you need to retire it. Leaving it presented on the cluster might cause a ton of issues we won&amp;rsquo;t go into on this article, trust me, Murphy&amp;rsquo;s law applies.&lt;/p&gt;
&lt;h2 id=&#34;is-the-proxmox-node-on&#34;&gt;Is the proxmox node on?&lt;/h2&gt;
&lt;p&gt;If the Proxmox Node is online you need to migrate all the Virtual Machines (VMs) to another Node. Since Proxmox 5 migrating VMs has never been easier. You can just right click and click on Migrate, wether it has local or shared storage is transparent for the operator/sysadmin/you.&lt;/p&gt;
&lt;p&gt;After the migration finishes (in the case that you don&amp;rsquo;t use shared storage and you use local storage this might take a while) you can proceed to shutoff the node.&lt;/p&gt;
&lt;p&gt;Non-recoverable hardware failures on nodes don&amp;rsquo;t need to go through this step. There are ways to recover the VMs if the storage was locally based but, due to time constrains I won&amp;rsquo;t cover it here.&lt;/p&gt;
&lt;h2 id=&#34;make-sure-the-node-is-no-longer-on&#34;&gt;Make sure the node is no longer on&lt;/h2&gt;
&lt;p&gt;When the node has been shutdown &lt;strong&gt;DO NOT START IT UP AGAIN&lt;/strong&gt;. This will cause problems with the corosync services. Preferably unplug the network connection, either physically or through the OS configuration.&lt;/p&gt;
&lt;h2 id=&#34;verify-it&#34;&gt;Verify it!&lt;/h2&gt;
&lt;p&gt;In the case described on this post we&amp;rsquo;re using a 9 node cluster, something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/attachment1.png&#34;
	width=&#34;814&#34;
	height=&#34;404&#34;
	srcset=&#34;https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/attachment1_hu03399279965ef0db9423ad2f05f3582f_6036_480x0_resize_box_3.png 480w, https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/attachment1_hu03399279965ef0db9423ad2f05f3582f_6036_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Proxmox Cluster&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;201&#34;
		data-flex-basis=&#34;483px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;You need to check the Node name from the Proxmox Custer Manager CLI, this is as easy as opening an SSH console or going through the Proxmox GUI -&amp;gt; Shell and issuing the command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pvecm nodes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It should give you an output like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Membership information
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;----------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nodeid      Votes Name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox9
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox1 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;local&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;          &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; proxmox2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;get-down-to-it-and-get-the-node-down-too&#34;&gt;Get down to it, and get the node down too&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s say we want to remove the node with id 2 (proxmox2). &lt;em&gt;Ensure you&amp;rsquo;ve shut it off&lt;/em&gt; and issue the command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pvecm delnode proxmox2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There won&amp;rsquo;t be any output to this command unless something goes wrong. What this command does is remove all of the configuration files from the &lt;code&gt;pve&lt;/code&gt; file system that control the cluster. It does NOT, however, completely clean all of the corosync entries, hence the &amp;ldquo;If it&amp;rsquo;s out, it stays out&amp;rdquo;, the cluster will basically look like this afterwards:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/attachment2.png&#34;
	width=&#34;814&#34;
	height=&#34;404&#34;
	srcset=&#34;https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/attachment2_hub365ea7087b923efeb01063ddceddc18_6576_480x0_resize_box_3.png 480w, https://vectops.com/post/2019/retiring-a-proxmox-cluster-node-the-right-way/attachment2_hub365ea7087b923efeb01063ddceddc18_6576_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Proxmox cluster without node&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;201&#34;
		data-flex-basis=&#34;483px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;Et voilá!&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve succesfully removed a Proxmox Node from a running cluster and with zero (hopefully) downtime on the VMs themselves.&lt;/p&gt;
&lt;p&gt;Now go and add a brand new shiny machine to the Cluster. Maybe a few more than one!&lt;/p&gt;
&lt;p&gt;If you want to check out how to create a Production-Ready Proxmox Cluster or maybe adapt your current deployment to the different approaches we&amp;rsquo;ve explored deploying Production Proxmox clusters between all of us here at Vectops you might want to check the upcoming series about it.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Reusing TCP ports for fun, profit and lack of headaches</title>
        <link>https://vectops.com/post/2019/reusing-tcp-ports-for-fun-profit-and-lack-of-headaches/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/reusing-tcp-ports-for-fun-profit-and-lack-of-headaches/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/reusing-tcp-ports-for-fun-profit-and-lack-of-headaches/image.png" alt="Featured image of post Reusing TCP ports for fun, profit and lack of headaches" /&gt;&lt;p&gt;Last week I was checking out some issues on the ticketting system that hadn&amp;rsquo;t been solved way before my time. While browsing them I noticed an unsolved ticket that had a lot of updates from both the sysadmins that came before me and the developers from an application that ran a few times per day but always had issues running.&lt;/p&gt;
&lt;p&gt;The errors that were thrown by the application (which was programmed in Java of all things) were like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;java&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;net&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;NoRouteToHostException&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; Can&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;t assign requested &lt;span style=&#34;color:#a6e22e&#34;&gt;address&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;Address not available&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;possible-causes&#34;&gt;Possible causes&lt;/h2&gt;
&lt;p&gt;All of the updates regarding this issue &amp;ldquo;pointed&amp;rdquo; towards the database cluster that was being called in order for the application to store it&amp;rsquo;s output (the quotes serve a purpose by the way, just wait and read). Now, I could see a year&amp;rsquo;s worth of interactions from both teams discussing the error and possible solutions but somehow they all managed to &amp;ldquo;point&amp;rdquo; the error towards the database cluster.&lt;/p&gt;
&lt;p&gt;Please take into account that this is a Percona cluster that could handle tens of thousands of connections, not counting the concurrency. Real beefy stuff. That had been configured by a co-worker which I &lt;strong&gt;know&lt;/strong&gt; can do his job competently, but since the ticket had my attention I decided to take a crack at it.&lt;/p&gt;
&lt;h2 id=&#34;troubleshooting&#34;&gt;TroubleShooting&lt;/h2&gt;
&lt;p&gt;The first few steps of the troubleshooting I had to do were to eliminate all obvious conclusions (year&amp;rsquo;s worth of work, remember?) my co-workers came to; which pointed me towards the Percona cluster. Since this is a production system I wasn&amp;rsquo;t able to really stress it since I knew my testing would get unwanted attention from developers and managers that start yelling wolf as soon as they see something that&amp;rsquo;s not expected on their metrics. So I just threw arround 30k concurrent sessions to the cluster and it didn&amp;rsquo;t break a sweat.&lt;/p&gt;
&lt;p&gt;So, next steps it is. After checking out the whole error log from Java I noticed the error and decided to SSH into the application server from where the app was being deployed and as soon as I connected to it I received a Slack message asking me not to play with since it was on production!!!&lt;/p&gt;
&lt;p&gt;Naturally I did what every sysadmin does atleast once (a day), ignore the developer and started checking out every log I could get my hands on and noticed something specific to those machines, they weren&amp;rsquo;t reusing TCP connections. As you can see it didn&amp;rsquo;t &amp;ldquo;point&amp;rdquo; to a database issue. These kinds of database clusters are designed to run with HUGE workloads.&lt;/p&gt;
&lt;h2 id=&#34;possible-solutions&#34;&gt;Possible solutions&lt;/h2&gt;
&lt;p&gt;At this point it was painfully obvious that the machine was running out of internal ports for the application that was deployed on it, in order to check this I just reviewed the kernel parameters in execution with the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysctl -a | grep range
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the reusability of the ports:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysctl -a | grep reuse
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;definite-solution&#34;&gt;Definite solution&lt;/h2&gt;
&lt;p&gt;Both of those commands gave me what I needed, the port range was ok:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.ip_local_port_range &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;15000&lt;/span&gt;    &lt;span style=&#34;color:#ae81ff&#34;&gt;65000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which is expected since it&amp;rsquo;s a default behaviour, but the reuse flag wasn&amp;rsquo;t enabled, so we just changed it on the kernel config on the file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/etc/sysctl.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And added the  entry:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_tw_reuse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Applied it live:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysctl -p
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, done.&lt;/p&gt;
&lt;p&gt;Et voilà!&lt;/p&gt;
&lt;h2 id=&#34;final-thoughts&#34;&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;As soon as I had finished the changes, I went to the developers desk and described my solution and the horror face he made when I told him I needed to change a kernel parameter was priceless. He kept rambling about how it needed to be scheduled since it needed a reboot and this is a production system that had to approved by the higher-ups and bla bla bla bla bla (Good thing those types of changes don&amp;rsquo;t require a reboot). I just told him it was done and added a simple &amp;ldquo;Please run the application again, it won&amp;rsquo;t fail now&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Hope it doesn&amp;rsquo;t :p&lt;/p&gt;
</description>
        </item>
        <item>
        <title>S(z)etting up your private networks with ZeroTier</title>
        <link>https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/image.png" alt="Featured image of post S(z)etting up your private networks with ZeroTier" /&gt;&lt;p&gt;At Vectops we use a combination of different technologies for different purposes. Ranging from homelabs, to full-blown multinational production systems that our staff works on during office hours (sometimes beyond office hours). We&amp;rsquo;ve tested and use daily different ways to connect to private infrastructures, ussually through a VPN connection.&lt;/p&gt;
&lt;p&gt;This is where ZeroTier comes in, being a SD-WAN (Software Defined Wide Area Network) it doesn&amp;rsquo;t depend on new hardware, it can just be set up using whatever you already have, as long as you have more than one machine. Take into account that your phone counts :). This is basically a P2P network that only your devices can access.&lt;/p&gt;
&lt;p&gt;ZeroTier&amp;rsquo;s virtual networks are defined by it&amp;rsquo;s creators as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ZeroTier virtual networks are like chat rooms for machines. Just create virtual networks, join them from your devices and systems, approve authorization for the things you’ve added, and you’re done! Advanced features like our network rules engine help you manage your networks like a pro, and automatic end-to-end encryption keeps everything private and secure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;registering&#34;&gt;Registering&lt;/h2&gt;
&lt;p&gt;To be able to use ZeroTier you need to register on their website, this is so you can control the P2P network: &lt;a class=&#34;link&#34; href=&#34;https://zerotier.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ZeroTier&lt;/a&gt;. Click on Login and then Register:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment1.png&#34;
	width=&#34;839&#34;
	height=&#34;759&#34;
	srcset=&#34;https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment1_hu05f98eec5a98d748105d7317a4dfad2e_10115_480x0_resize_box_3.png 480w, https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment1_hu05f98eec5a98d748105d7317a4dfad2e_10115_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Register&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;110&#34;
		data-flex-basis=&#34;265px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;After you register and confirm your email, you could purchase a subscription since the service doesn&amp;rsquo;t allow more than 100 devices on the free plan, also there&amp;rsquo;s no support if you&amp;rsquo;re not paying. That&amp;rsquo;s just how the world works, even though the service is free, people need to be paid for their work.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get started.&lt;/p&gt;
&lt;h2 id=&#34;creating-networks&#34;&gt;Creating Networks&lt;/h2&gt;
&lt;p&gt;You need to create a network for your machines (and phone) to connect, click on &lt;code&gt;Networks&lt;/code&gt; and then on &lt;code&gt;Create a Network&lt;/code&gt;. Take into account that even using the &lt;em&gt;free plan&lt;/em&gt; you still get to be able to create unlimited networks here.&lt;/p&gt;
&lt;p&gt;The network creation is immediate, it comes with a Network ID and a random name:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment2.png&#34;
	width=&#34;1220&#34;
	height=&#34;709&#34;
	srcset=&#34;https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment2_hu91f5eb6f1e71046604f0c02225beb6f7_19809_480x0_resize_box_3.png 480w, https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment2_hu91f5eb6f1e71046604f0c02225beb6f7_19809_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Empty Network&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;172&#34;
		data-flex-basis=&#34;412px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;This network can be &lt;em&gt;Private&lt;/em&gt; or &lt;em&gt;Public&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Private networks are the safest way to go around, but also mean you have to make a couple of clicks per machine you add to the network.&lt;/p&gt;
&lt;p&gt;Public networks allow anyone with the network ID to connect to it and be authorized.&lt;/p&gt;
&lt;p&gt;Afterwards, you can set up the actual network.&lt;/p&gt;
&lt;h2 id=&#34;setting-up-the-network&#34;&gt;Setting up the network&lt;/h2&gt;
&lt;p&gt;IPv4 ranges can be selected from the network control panel, it comes with the &lt;em&gt;Auto-Assign from range&lt;/em&gt; option pre-selected and a random range selected too. Note that all of these ranges are private IPs, you can&amp;rsquo;t see them outside of your ZeroTier network. Since you&amp;rsquo;re using the free plan there&amp;rsquo;s no actual reason to use anything more than a /24 range, select one, in this case: 192.168.195.x:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment3.png&#34;
	width=&#34;1271&#34;
	height=&#34;786&#34;
	srcset=&#34;https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment3_hu5404bd3f62a3d7c4be54ffc6da25317c_18407_480x0_resize_box_3.png 480w, https://vectops.com/post/2019/szetting-up-your-private-networks-with-zerotier/attachment3_hu5404bd3f62a3d7c4be54ffc6da25317c_18407_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Network Ranges&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;161&#34;
		data-flex-basis=&#34;388px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;These ranges also come with an established route, if you would like to change them you could do so as well.&lt;/p&gt;
&lt;p&gt;In the case of IPv6 you can also Auto-Assign the IPs, depending on what you need you could use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ZeroTier RFC4193 (/128 for each device)&lt;/li&gt;
&lt;li&gt;ZeroTier 6PLANE (/80 routable for each device)&lt;/li&gt;
&lt;li&gt;Auto-Assign from Range&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now to the machines:&lt;/p&gt;
&lt;h2 id=&#34;setting-up-our-peers&#34;&gt;Setting up our peers&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;re going to use a couple of examples here so you can see how to set up different machines on different OS&amp;rsquo;s, although ZeroTier&amp;rsquo;s documentation is pretty complete about it:&lt;/p&gt;
&lt;h3 id=&#34;linux-machine&#34;&gt;Linux machine&lt;/h3&gt;
&lt;p&gt;Make sure you have curl and gpg installed. Most modern distros come with gpg, but not always curl. Depending on your linux distro just use your package manager to install these. Once installed run this command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://raw.githubusercontent.com/zerotier/ZeroTierOne/master/doc/contact%40zerotier.com.gpg&amp;#39;&lt;/span&gt; | gpg --import &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; z&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;curl -s &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://install.zerotier.com/&amp;#39;&lt;/span&gt; | gpg&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$z&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; | sudo bash; &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There&amp;rsquo;s another method to install the client, daemon services, and repository but it doesn&amp;rsquo;t check for cryptographic signatures and relies fully on SSL, just a simple script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s https://install.zerotier.com | sudo bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the script is done just join the node with the &lt;code&gt;zerotier-cli&lt;/code&gt; using your network ID:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zerotier-cli join d3ecf5726d62e220
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, authorize it from your control panel by checking on the checkbox that appears on your panel with the node ID (This node ID is shown on the terminal when the installation process finishes)&lt;/p&gt;
&lt;h3 id=&#34;android-phone&#34;&gt;Android phone&lt;/h3&gt;
&lt;p&gt;Yes, we&amp;rsquo;re including this because not everyone has more than one machine and not everyone wants to create VMs and some people need a connection straight to their laptops or desktop machines from their phones:&lt;/p&gt;
&lt;p&gt;Go on the Play Store and search for ZeroTier, install it and join a network, pretty easy, pretty straightforward.&lt;/p&gt;
&lt;p&gt;Oh and don&amp;rsquo;t forget to authorize the phone.&lt;/p&gt;
&lt;h2 id=&#34;final-set-up&#34;&gt;Final set up&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s no final set up, just go ahead and connect to your devices, doesn&amp;rsquo;t matter if you&amp;rsquo;re on the same Wifi or on a different country, as long as the machine as an internet connection you should be able to get to it.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t forget to fill the names and/or description fields on the control panel for the machines, else you&amp;rsquo;re gonna have a bad time after it gets to more than a couple machines.&lt;/p&gt;
&lt;p&gt;Good Luck!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Set up your machine to use kubectl</title>
        <link>https://vectops.com/post/2019/set-up-your-machine-to-use-kubectl/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/set-up-your-machine-to-use-kubectl/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/set-up-your-machine-to-use-kubectl/image.png" alt="Featured image of post Set up your machine to use kubectl" /&gt;&lt;p&gt;At Vectops we like to dwell on new techologies, which includes Kubernetes (K8s from now on). Most of the infrastructure we use on a daily basis is currently tied to K8s in one way or another. As a result this means that our machines have to be set up for K8s in one way or another to be able to perform different tasks on it. If you decide to run, test or become proficient on K8s you need to have &lt;code&gt;kubectl&lt;/code&gt; set up on your environment.&lt;/p&gt;
&lt;p&gt;K8s allows you to have different permissions and roles depending on your role regarding the cluster, whichever it may be: admin, mantainer, operator, developer, tester, etc.&lt;/p&gt;
&lt;p&gt;This article won&amp;rsquo;t go into detail on RBAC (Role-Based Access Control), if you want to learn more about it go &lt;a class=&#34;link&#34; href=&#34;https://kubernetes.io/docs/reference/access-authn-authz/rbac/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For whatever task you need to perform on the cluster you do need some sort of way to interact with the cluster.&lt;/p&gt;
&lt;h2 id=&#34;enter-kubectl&#34;&gt;Enter kubectl&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt; is a CLI tool that allows you to run commands that interact with K8s clusters. Wether it may be getting information from a specific pod, deployment, service, etc. to editing a definition for an instance.&lt;/p&gt;
&lt;p&gt;It can be installed in different ways, lets focus on the ones that can be maintained easily, for instance from the OS&amp;rsquo;s package manager.&lt;/p&gt;
&lt;p&gt;After you install &lt;code&gt;kubectl&lt;/code&gt; you need to configure it. Just scroll down, you&amp;rsquo;ll get there. Above all, take into account the freedom of choice.&lt;/p&gt;
&lt;h2 id=&#34;linux&#34;&gt;Linux&lt;/h2&gt;
&lt;p&gt;The easiest to install, just copy and paste these commands on the terminal for each of the distros.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please take into account that you should check the contents of the repo file as well as the URLs, just to be safe&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re going to use package management, snaps and straight binary download for the sake of completeness (&lt;em&gt;JUST USE ONE OF THESE&lt;/em&gt;)&lt;/p&gt;
&lt;h3 id=&#34;debianubuntuother-derivatives-that-use-deb&#34;&gt;Debian/Ubuntu/other derivatives that use .deb&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt-get update &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt-get install -y apt-transport-https
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;deb https://apt.kubernetes.io/ kubernetes-xenial main&amp;#34;&lt;/span&gt; | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt-get install -y kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;centosrhelfedoraother-derivatives-that-use-rpm&#34;&gt;CentOS/RHEL/Fedora/other derivatives that use .rpm&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;lt;&amp;lt;EOF &amp;gt; /etc/yum.repos.d/kubernetes.repo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;[kubernetes]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;name=Kubernetes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;enabled=1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;gpgcheck=1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;repo_gpgcheck=1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum install -y kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;snap&#34;&gt;Snap&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo snap install kubectl --classic
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;straight-binary&#34;&gt;Straight binary&lt;/h3&gt;
&lt;p&gt;Download the latest release from google:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -LO https://storage.googleapis.com/kubernetes-release/release/&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;/bin/linux/amd64/kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Give it executable permissions&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod +x ./kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And move it to your binary path&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo mv ./kubectl /usr/local/bin/kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure it works!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;windows&#34;&gt;Windows&lt;/h2&gt;
&lt;p&gt;In the case of Windows you can decide to use a few tools including but not limited to WSL (Windows subsystem for linux), PowerShell, Chocolatey, etc.&lt;/p&gt;
&lt;h3 id=&#34;wsl&#34;&gt;WSL&lt;/h3&gt;
&lt;p&gt;Just use the same procedures for linux on your WSL console&lt;/p&gt;
&lt;h3 id=&#34;powershell&#34;&gt;PowerShell&lt;/h3&gt;
&lt;h4 id=&#34;psgallery&#34;&gt;PSGallery&lt;/h4&gt;
&lt;p&gt;You can use PSGallery:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Install-Script -Name install-kubectl -Scope CurrentUser -Force
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;install-kubectl.ps1 [-DownloadLocation $PATH]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You should change: $PATH for whichever path you want to choose for the download&lt;/p&gt;
&lt;h4 id=&#34;curl&#34;&gt;Curl&lt;/h4&gt;
&lt;p&gt;Pure PowerShell allows you to run &lt;code&gt;kubectl&lt;/code&gt; as well:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -LO https&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt;//storage.googleapis.com/kubernetes-release/release/v1.17.&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;/bin/windows/amd64/kubectl.exe
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Don&amp;rsquo;t forget to add the &lt;code&gt;.exe&lt;/code&gt; to your path, else you&amp;rsquo;ll have to navigate to the download path all the time or use an absolute route for the binary.&lt;/p&gt;
&lt;h4 id=&#34;chocolatey&#34;&gt;Chocolatey&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;choco install kubernetes-cli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;mac&#34;&gt;Mac&lt;/h2&gt;
&lt;p&gt;The number of systems and devops engineers that use Mac either grows or diminishes every year (depends on who you ask, to each their own. I don&amp;rsquo;t judge). However there&amp;rsquo;s a lot our there that use it daily. In the same way that Linux and Windows users have a few ways to install it.&lt;/p&gt;
&lt;h3 id=&#34;homebrew&#34;&gt;Homebrew&lt;/h3&gt;
&lt;p&gt;For Homebrew it&amp;rsquo;s a simple one-liner:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install kubectl 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;macports&#34;&gt;Macports&lt;/h3&gt;
&lt;p&gt;Same with Macports&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo port selfupdate; sudo port install kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;straight-binary-on-mac&#34;&gt;Straight binary on MAC&lt;/h3&gt;
&lt;p&gt;The binary method for MAC is basically the same as for linux but with a different binary package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -LO &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://storage.googleapis.com/kubernetes-release/release/&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/bin/darwin/amd64/kubectl&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Give it executable permissions&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod +x ./kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And move it to your binary path&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo mv ./kubectl /usr/local/bin/kubectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure it works!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;After the installation is done you need to add the config file for kubernetes on your &lt;code&gt;$PATH&lt;/code&gt; for &lt;code&gt;kubectl&lt;/code&gt; to be able to work against your cluster.&lt;/p&gt;
&lt;p&gt;On Linux, MAC and WSL this can be done by copying your config file on the following route:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the case of Windows the file should be copied on the following route:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;%&lt;/span&gt;USERPROFILE%/.kube/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;checking-that-everything-works&#34;&gt;Checking that everything works&lt;/h2&gt;
&lt;p&gt;You can test that &lt;code&gt;kubectl&lt;/code&gt; has access to the cluster by issuing the command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the connection works you&amp;rsquo;ll see an output like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Client Version: version.Info&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;Major:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, Minor:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;17&amp;#34;&lt;/span&gt;, GitVersion:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;v1.17.0&amp;#34;&lt;/span&gt;, GitCommit:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;70132b0f130acc0bed193d9ba59dd186f0e634cf&amp;#34;&lt;/span&gt;, GitTreeState:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;, BuildDate:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2019-12-10T03:03:57Z&amp;#34;&lt;/span&gt;, GoVersion:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;go1.13.5&amp;#34;&lt;/span&gt;, Compiler:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;, Platform:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server Version: version.Info&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;Major:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, Minor:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;16&amp;#34;&lt;/span&gt;, GitVersion:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;v1.16.3&amp;#34;&lt;/span&gt;, GitCommit:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;b3cbbae08ec52a7fc73d334838e18d17e8512749&amp;#34;&lt;/span&gt;, GitTreeState:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;clean&amp;#34;&lt;/span&gt;, BuildDate:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2019-11-13T11:13:49Z&amp;#34;&lt;/span&gt;, GoVersion:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;go1.12.12&amp;#34;&lt;/span&gt;, Compiler:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gc&amp;#34;&lt;/span&gt;, Platform:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where the &lt;code&gt;Client Version&lt;/code&gt; is the kubectl binary version and the &lt;code&gt;Server Version&lt;/code&gt; is the Cluster version.&lt;/p&gt;
&lt;h2 id=&#34;final-words&#34;&gt;Final words&lt;/h2&gt;
&lt;p&gt;This tutorial should help you configure kubectl for your machine, it can also be used to set up a control server (just a simple virtual machine that has access to the same network as the K8s cluster)&lt;/p&gt;
&lt;p&gt;In case you need any help you can type in a comment, we try to answer them ASAP.&lt;/p&gt;
&lt;p&gt;Good Luck!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Updating a Proxmox Cluster from 4.4 to 5.4 the safe way</title>
        <link>https://vectops.com/post/2019/updating-a-proxmox-cluster-from-4-4-to-5-4-the-safe-way/</link>
        <pubDate>Wed, 04 Dec 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/post/2019/updating-a-proxmox-cluster-from-4-4-to-5-4-the-safe-way/</guid>
        <description>&lt;img src="https://vectops.com/post/2019/updating-a-proxmox-cluster-from-4-4-to-5-4-the-safe-way/image.png" alt="Featured image of post Updating a Proxmox Cluster from 4.4 to 5.4 the safe way" /&gt;&lt;p&gt;Most of us have had instances where a production virtualization cluster can&amp;rsquo;t be updated for whatever reasons: stability, fear of screwing up, orders from above, or scared co-workers that might think that once it&amp;rsquo;s in production you shouldn&amp;rsquo;t (just don&amp;rsquo;t) touch anything that might hinder the intended behaviour of a system.&lt;/p&gt;
&lt;p&gt;However, there are some things that do need to be upgraded, especially in cases where a bug that has been pestering you has been fixed on a newer version or a new functionality has been added. Now, I&amp;rsquo;m not one of those guys that likes to have absolute bleeding-edge software on production servers (obvious reasons might include: it just hasn&amp;rsquo;t been tested long enough), but having software on production that might soon reach End Of Life or that isn&amp;rsquo;t behaving up to current standards, that, I have a problem with.&lt;/p&gt;
&lt;p&gt;I started to work on a new company not long ago and I came to work on the first day to see a few Proxmox clusters running on 4.4, which isn&amp;rsquo;t that bad (don&amp;rsquo;t touch production servers remember?), so I tested the functionality and I came to see bugs I hadn&amp;rsquo;t seen in years (including issues with the no-vnc conections to the VMs) and decided to do something about it. So I convinced my manager to upgrade the clusters.&lt;/p&gt;
&lt;p&gt;At the time of writing this article the current version of Proxmox is 6.0. I&amp;rsquo;ve had bad experiences upgrading to the first major version of Proxmox before so I decided to upgrade to 5.4 atleast until a more polished version of Proxmox comes arround.&lt;/p&gt;
&lt;p&gt;The procedure is pretty simple, if you have classical shared storage (NFS, iSCSI disks, etc.).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Beware CEPH Users&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This article doesn&amp;rsquo;t cover the steps for a CEPH upgrade, so please be careful&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, we start with a cluster. We need to balance our the whole cluster so we can get an empty node. That means migrating all the VMs to other nodes, all while making sure the target nodes don&amp;rsquo;t run out of RAM and in my case making sure the CPU load wasn&amp;rsquo;t topping out (production servers remember?).&lt;/p&gt;
&lt;p&gt;The migration procedure is pretty straightforward:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Right click on a VM -&amp;gt; Migrate -&amp;gt; Select the target node -&amp;gt; Get a cup of coffee&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After you finish this process you can go ahead and upgrade the node.&lt;/p&gt;
&lt;p&gt;First off, start with a check from the terminal so we can make sure there&amp;rsquo;s no VMs running on the node:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qm list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we make sure there are no running VMs and we&amp;rsquo;re sure the node is empty (go ahead, check again.) we can proceed.&lt;/p&gt;
&lt;p&gt;First step is to do an update on the repos with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt update
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we can upgrade and reboot the current system with the newest kernel for 4.4:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt upgrade -y; reboot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the node comes back up we need to add-in the new repos for the upgrade, as well as the GPG signatures for the repos:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sed -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;s/jessie/stretch/g&amp;#39;&lt;/span&gt; /etc/apt/sources.list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sed -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;s/jessie/stretch/g&amp;#39;&lt;/span&gt; /etc/apt/sources.list.d/pve-enterprise.list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget http://download.proxmox.com/debian/proxmox-ve-release-5.x.gpg -O /etc/apt/trusted.gpg.d/proxmox-ve-release-5.x.gpg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we proceed with updating the repos on APT:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt update
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, this is &lt;strong&gt;very&lt;/strong&gt; important, we need to remote sysv-rc, openrc, etc from the system so we&amp;rsquo;re able to get the latest systemd graceness on the system &lt;strong&gt;DO NOT REBOOT THE SYSTEM&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt purge insserv sysv-rc initscripts openrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;DO NOT REBOOT THE SYSTEM&lt;/strong&gt; Seriously, unless you wanna spend hours fixing the system or just formatting it and adding it as a new node. (which in hindsight isn&amp;rsquo;t such a bad idea)&lt;/p&gt;
&lt;p&gt;After the removal is done we can finally upgrade the node to the 5.4 version of Proxmox:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get dist-upgrade
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This step can take a while, and it&amp;rsquo;s going to prompt you for answers a couple of times regarding configuration files, you can leave them as-is or you can upgrade them, up to you. I leave them as-is in case I need to recover anything.&lt;/p&gt;
&lt;p&gt;Finally, you can reboot the system:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;reboot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et voilà!&lt;/p&gt;
&lt;p&gt;Now you can migrate the VMs back to the node and start all over again with another node. This process can take a while and you might be able to automate it, however I&amp;rsquo;ve heard some stories both from RL and online from people that have had some bad luck with automating it and end up screwing up the cluster in some way or another.&lt;/p&gt;
&lt;p&gt;Good Luck!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Archives</title>
        <link>https://vectops.com/page/archives/</link>
        <pubDate>Tue, 28 May 2019 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/page/archives/</guid>
        <description></description>
        </item>
        <item>
        <title>About us</title>
        <link>https://vectops.com/page/about/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/page/about/</guid>
        <description>&lt;p&gt;We are just three Sysadmins that have had to work on different areas of IT, whether it would be infrastructure, networking, development, testing, etc. You know, pure Sysadmin stuff. After a few years of this, we have noticed that on-point documentation and easy to read use cases are more often than not just not there.&lt;/p&gt;
&lt;p&gt;Thus, we have decided to start posting some of those use cases and articles, digested and easy to read so you don’t have to spend countless hours googling for stuff.&lt;/p&gt;
&lt;p&gt;As we have.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Search</title>
        <link>https://vectops.com/page/search/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://vectops.com/page/search/</guid>
        <description></description>
        </item>
        
    </channel>
</rss>
