<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Aaron Berry</title>
    <description>The latest articles on Forem by Aaron Berry (@aaronktberry).</description>
    <link>https://forem.com/aaronktberry</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F102603%2Fbaf31831-5aa5-45c0-af57-8c9dbde62da1.jpg</url>
      <title>Forem: Aaron Berry</title>
      <link>https://forem.com/aaronktberry</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/aaronktberry"/>
    <language>en</language>
    <item>
      <title>Generating Encrypted Key Pairs In Python</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Sun, 25 Jul 2021 02:54:35 +0000</pubDate>
      <link>https://forem.com/aaronktberry/generating-encrypted-key-pairs-in-python-69b</link>
      <guid>https://forem.com/aaronktberry/generating-encrypted-key-pairs-in-python-69b</guid>
      <description>&lt;p&gt;I recently had a requirement to produce some code that can generate encrypted PEM encoded RSA key pairs that can be used for snowflake key pair authentication for service accounts. I didn't find a lot of clear documentation on what the best practice was to do this in a python environment, so ill share what I came up with that allows you to produce an RSA key pair with the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is a PEM encoded format for both public and private keys&lt;/li&gt;
&lt;li&gt;PEM encoded Private key is encrypted with a password for further security and to align with snowflakes recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To achieve this, I used the &lt;a href="https://cryptography.io/en/latest/" rel="noopener noreferrer"&gt;python cryptography package&lt;/a&gt;. It has all the necessary backends we need for PEM encoded keys and for applying our encrypted password. I found that some other common crypt packages did not expose configuration in their python classes that are available in the underlying OpenSSL binary. Our intended outputs from this process will be a password for our private key, an encrypted PEM encoded RSA key, and a PEM encoded public key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Aaron-K-T-Berry/python-encrypted-rsa-keys-demo" rel="noopener noreferrer"&gt;You can use the repo I have created if you wish to follow along with the example.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an Encrypted PEM Encoded RSA Key Pair
&lt;/h2&gt;

&lt;p&gt;The first thing we will want to do is generate an RSA key pair with the python cryptography library. You are strongly recommended to use the defaults for this module for the security implications, but you may configure as you need and know the impact of those changes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.hazmat.primitives.asymmetric&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rsa&lt;/span&gt;

&lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rsa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_private_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;public_exponent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;65537&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;key_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With your key pair object, you will then be able to encode it in your desired format. We will use the PEM encoding for our key pair and produce the required bytes for our PEM encoded public and private keys. Take note of us passing the bytes for our private key password when calling &lt;code&gt;private_key.private_bytes&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.hazmat.primitives&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serialization&lt;/span&gt;

&lt;span class="n"&gt;private_key_pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;encrypted_pem_private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;private_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PEM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivateFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PKCS8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;encryption_algorithm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BestAvailableEncryption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;private_key_pass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted_pem_private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# b'-----BEGIN ENCRYPTED PRIVATE KEY-----'
&lt;/span&gt;
&lt;span class="n"&gt;pem_public_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;public_key&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;public_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PEM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubjectPublicKeyInfo&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pem_public_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# b'-----BEGIN PUBLIC KEY-----'
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you do not require an encrypted private key file, you can always pass no encryption for the key like so.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.hazmat.primitives&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serialization&lt;/span&gt;

&lt;span class="n"&gt;unencrypted_pem_private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;private_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PEM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivateFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TraditionalOpenSSL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;encryption_algorithm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NoEncryption&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unencrypted_pem_private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# b'-----BEGIN RSA PRIVATE KEY-----'
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With our PEM encoded public and private key bytes, we can generate them into strings if you wish to write to file or save them in another service.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;private_key_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example-rsa.pem&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;private_key_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted_pem_private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;private_key_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;public_key_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example-rsa.pub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;public_key_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pem_public_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;public_key_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When we put all these pieces together, we get the following completed code example.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.hazmat.primitives.asymmetric&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rsa&lt;/span&gt;&lt;br&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.hazmat.primitives&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serialization&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rsa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_private_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;public_exponent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;65537&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;key_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="n"&gt;private_key_pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="n"&gt;encrypted_pem_private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;private_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PEM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivateFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PKCS8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;encryption_algorithm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BestAvailableEncryption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;private_key_pass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="n"&gt;pem_public_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;public_key&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;public_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;br&gt;
  &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PEM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
  &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;serialization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubjectPublicKeyInfo&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="n"&gt;private_key_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example-rsa.pem&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br&gt;
&lt;span class="n"&gt;private_key_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted_pem_private_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br&gt;
&lt;span class="n"&gt;private_key_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="n"&gt;public_key_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example-rsa.pub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br&gt;
&lt;span class="n"&gt;public_key_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pem_public_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br&gt;
&lt;span class="n"&gt;public_key_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Further Reading&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cryptography.io/en/latest/" rel="noopener noreferrer"&gt;You can find the documentation for the python cryptography library here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The documentation can answer most of your questions once you work out what objects must be passed at each stage of the key generation process. By intention, the library is very flexible with many modules to change things out for your use cases requirements from crypto backends to serialization formats.&lt;/p&gt;

&lt;p&gt;With your generated private and public key bytes, you can create your keys in any encoding format you need for your consuming client. In the projects I have worked on, we have found that it is most helpful for us to store these keys in a standard format in a secret storage service like SSM as base64 encoded strings to preserve the formatting of the keys. This shifts the responsibility of formatting the key to the necessary format to the consumers of the key pair by them either writing the key to file or store it in other formats depending on their use case with a simple decode of the base 64 string from SSM. The flow for this process would look something like in the diagram below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5b9aj7mnj6ee3wgd942.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5b9aj7mnj6ee3wgd942.png" alt="Key generation client to consumer workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the use cases for this process, some services require keys in this format. A notable example and what triggered me to look into this was snowflake's requirement for keys formatted in this way for key-pair authentication for snowflake service accounts in an automated key rotation process. However, snowflake does allow you to use non-encrypted key pairs with most of their SDK's now as well as supporting unencrypted keys too, although snowflake does still recommend using encrypted keys as best practice for their service. I do generally agree with them if you're looking for the most secure setup for your key pairs as it allows for another layer of protection for private keys saved on disk or fetched with the need for a password rather than just relying on file-based access control or your secret provider's security only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make sure to follow on &lt;a href="https://aaron-kt-berry.medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, &lt;a href="https://twitter.com/Aaron_KT_Berry" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://aaron-kt-berry.medium.com/subscribe" rel="noopener noreferrer"&gt;Email&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;If you are thinking of subscribing on Medium, you can use my &lt;a href="https://aaron-kt-berry.medium.com/membership" rel="noopener noreferrer"&gt;referral link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Connect with me on &lt;a href="https://www.linkedin.com/in/aaron-kt-berry/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; if you want to chat&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>todayilearned</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Articles around the web (03-05-2020)</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Sun, 03 May 2020 13:46:40 +0000</pubDate>
      <link>https://forem.com/aaronktberry/articles-around-the-web-03-05-2020-4ag9</link>
      <guid>https://forem.com/aaronktberry/articles-around-the-web-03-05-2020-4ag9</guid>
      <description>&lt;p&gt;Here's a collection of some interesting articles from around the web this week revolving around all things technology and programming. This is part of the &lt;a href="https://codepunnet.com"&gt;CodePunnet&lt;/a&gt; blog weekly newsletter. If you would like to get this update in your inbox make sure to subscribe to the &lt;a href="https://codepunnet.com/subscribe"&gt;newsletter&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://slack.engineering/development-environments-at-slack-f3c1339c2445"&gt;→ Development Environments at Slack&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The engineers at slack once again provide a glance on how they manage some of their technical processes. In this article they cover how they manage Dev environments and show how with effective management and tooling of these environments can be "critical to the success of any technology company".&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/bytebodger/is-typescript-really-a-language-ep1"&gt;→ Is TypeScript Really... A Language??&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Check out this interesting discussion into is typescript really a language? This in depth article covers all aspects of the topic from the definitions of programming languages and whether it all even actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://css-tricks.com/advice-for-writing-a-technical-resume/"&gt;→ Advice for Writing a Technical Resume&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you find yourself with a lot of free time during this pandemic consider taking some of that time and giving your resume a cleanup. This article provides some great points on how you can update your technical resume and hopefully score some interviews or offers when restrictions begin to be lifted.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://css-tricks.com/using-formik-to-handle-forms-in-react/"&gt;→ Using Formik to Handle Forms in React&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;On almost any site you will find some kind of form. This article shows how easy it is to manage forms in react using the npm package Formik with a dive into the multiple possible implementations and common validation and error handling scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://netflixtechblog.com/how-netflix-brings-safer-and-faster-streaming-experience-to-the-living-room-on-crowded-networks-78b8de7f758c"&gt;→ How Netflix brings safer and faster streaming experiences to the living room on crowded networks using TLS 1.3&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The engineers at Netflix provide some insight into their results from a security analysis into the usage of TLS 1.3 vs TLS 1.2 and the increased performance of the newer version for streaming performance, especially when the world is seeing more streaming than ever.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/sanderdebr/deep-equality-checking-of-objects-in-vanilla-javascript-5592"&gt;→ Deep Equality checking of Objects in Vanilla JavaScript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you've ever wanted to know how deep equality checking works and how you could implement it this article looks at how you can create your own deep equality checking just with vanilla javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://stackoverflow.blog/2020/04/20/pandemic-changed-traffic-trends-stack-exchange-sites/"&gt;→ How the pandemic changed traffic trends from 400M visitors across 172 Stack Exchange sites&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Stack overflow shares some insights into how they are seeing changing traffic trends due to the global pandemic. This article shares some uplifting news on how these traffic patterns are showing people increased interest to learn and to see traffic surges in important communities like academia and questions on how to move to remote working situations.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/david_j_eddy/how-to-aws-service-endpoints-via-terraform-for-fun-and-profit-ba1"&gt;→ How to: AWS Service Endpoints via Terraform for fun and profit&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This in-depth endpoint shows how you can use Terraform and AWS service endpoints to easily connect public AWS resources to your private VPC subnets.&lt;/p&gt;




&lt;p&gt;That's all the links for this week, stay safe and look after each other (But not too close). 🤚&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read more articles over on the &lt;a href="https://codepunnet.com"&gt;Code Punnet&lt;/a&gt; blog.&lt;/li&gt;
&lt;li&gt;Consider subscribing to the blogs &lt;a href="https://codepunnet.com/subscribe"&gt;weekly newsletter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Follow for more on &lt;a href="https://twitter.com/CodePunnet"&gt;twitter&lt;/a&gt; or the blogs &lt;a href="https://codepunnet.com/rss"&gt;RSS feed&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Articles around the web (26-04-2020)</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Sun, 26 Apr 2020 08:12:58 +0000</pubDate>
      <link>https://forem.com/aaronktberry/articles-around-the-web-26-04-2020-4g20</link>
      <guid>https://forem.com/aaronktberry/articles-around-the-web-26-04-2020-4g20</guid>
      <description>&lt;p&gt;Here's a collection of some interesting articles from around the web this week revolving around all things technology and programming. This is part of the &lt;a href="https://codepunnet.com"&gt;CodePunnet&lt;/a&gt; blog weekly newsletter. If you would like to get this update in your inbox make sure to subscribe to the &lt;a href="https://codepunnet.com/subscribe"&gt;newsletter&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://martinfowler.com/articles/branching-patterns.html"&gt;→ Patterns for Managing Source Code Branches&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Martin Fowler is starting a new article series on common patterns on how you can effectively manage source code branches with the first article covering source branching. You can never learn enough about git and branching so every developer can gain something from this series.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/pluralsight/top-kubernetes-courses-you-can-take-for-free-338j"&gt;→ Top Kubernetes Courses You Can Take For Free&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you've found yourself spending a lot more time at home consider checking out some of these free course to get you up-skilled on Kubernetes all the way from the fundamentals of installation and configuration to more advanced topics like controllers, deployments and managing storage and scheduling.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://stackoverflow.blog/2020/04/20/brush-up-your-cobol-why-is-a-60-year-old-language-suddenly-in-demand/"&gt;→ Brush up your COBOL: Why is a 60-year-old language suddenly in demand?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Due to the current demands on some of our ageing systems there has been a bit of an uptick in the need for COBOL programmers. This article from stack overflow has a look into the history of COBOL as a language and should help guide you through some nice COBOL examples you should be able to run yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.hanselman.com/blog/QuarantineWorkIsNotRemoteWork.aspx"&gt;→ Quarantine work is not Remote work&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Scott Hanselman has been providing developers with some great resources on working remotely but with the current pandemic pushing more people into a remote work like scenario he shares his thoughts on how taxing this period can be as well as some resources to make this period of time a bit easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/otomer/google-chrome-s-new-update-finally-allows-you-to-organize-tabs-easily-this-is-how-you-can-use-it-3f99"&gt;→ Google Chrome’s new update finally allows you to organize and group tabs!&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You can now get tab groups in your chrome browser with this sneaky new addition. Just like when dark mode first found its way to chrome you can follow this quick guide to enable the experimental feature in your chrome browser today.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dlford.io//aws-lambda-handling-form-submissions/"&gt;→ How to Set Up Serverless Form Submissions with AWS Lambda&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Creating Serverless functions can be a great way to achieve the functionality you need without having the extra bloat of a full backend stack f you don't need it. In this great article, it runs you through how you can easily set up a lambda function on AWS to handle form submission using the Serverless framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.ansible.com/blog/ops-by-pull-request-an-ansible-gitops-story"&gt;→ Ops By Pull Request: An Ansible Gitops Story&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;GitOps is becoming a more popular concept within organisations as a way to try and streamline the development and release process. The people at Red Hat discuss the basic concepts of GitOps and how this can be achieved with Ansible in an agentless, flexible and repeatable way.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.blog/2020-04-09-from-48k-lines-of-code-to-10-the-story-of-githubs-javascript-sdk/"&gt;→ From 48k lines of code to 10—the story of GitHub’s JavaScript SDK&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;An interesting look at some of the thought processes to developing and maintaining an open-source library. In this article, the Gregor Martynus discuss where his GitHub JavaScript SDK came from and the steps to get to where it is now with the much smaller (and more maintainable) codebase it is in now.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://medium.com/@NetflixTechBlog/how-netflix-uses-druid-for-real-time-insights-to-ensure-a-high-quality-experience-19e1e8568d06"&gt;→ How Netflix uses Druid for Real-time Insights to Ensure a High-Quality Experience&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://druid.apache.org/"&gt;Apache Druid&lt;/a&gt; is a high-performance real-time analytics database and the engineers at Netflix go over how it powers real-time analytics insights at Netflix. This article covers the whole pipeline from ingestion, data management and querying giving some great insights at how this is done at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/renanbr/controlling-service-readiness-in-docker-compose-4dfm"&gt;→ Controlling Service Readiness in Docker Compose&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A quick article showing you how you can make sure that your applications are actually ready to receive traffic after they are done starting up if your applications are declared in docker-compose with just the use of one small container dokku/wait to check if your applications are actually ready and started.&lt;/p&gt;




&lt;p&gt;That's all the links for this week, stay safe and look after each other (But not too close). 🤚&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read more articles over on the &lt;a href="https://codepunnet.com"&gt;Code Punnet&lt;/a&gt; blog.&lt;/li&gt;
&lt;li&gt;Consider subscribing to the blogs &lt;a href="https://codepunnet.com/subscribe"&gt;weekly newsletter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Follow for more on &lt;a href="https://twitter.com/CodePunnet"&gt;twitter&lt;/a&gt; or the blogs &lt;a href="https://codepunnet.com/rss"&gt;RSS feed&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Articles around the web (05-04-2020)</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Sun, 05 Apr 2020 06:50:36 +0000</pubDate>
      <link>https://forem.com/aaronktberry/articles-around-the-web-05-04-2020-3oaa</link>
      <guid>https://forem.com/aaronktberry/articles-around-the-web-05-04-2020-3oaa</guid>
      <description>&lt;p&gt;Here's a collection of some interesting articles from around the web this week revolving around all things technology and programming. This is part of the &lt;a href="https://codepunnet.com"&gt;CodePunnet&lt;/a&gt; blog weekly newsletter. If you would like to get this update in your inbox make sure to subscribe to the &lt;a href="https://codepunnet.com/subscribe"&gt;newsletter&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://slack.engineering/deploys-at-slack-cd0d28c61701"&gt;→ Deploys at Slack&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The engineers at slack once again go over some of their internal findings from their internal processes. This time they cover what it is like to deploy code at slack hoping to share how you can make deploying code easier and safer for everyone in your organisation.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/shaijut/pluralsight-all-7-000-courses-are-free-for-april-no-credit-card-required-450f"&gt;→ Pluralsight - All 7,000+ Programming courses are free for April!&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Pluralsight is technology skills platform, companies can up-skill teams and increase engineering impact and for the month of April, they are releasing all of their paid programming course for free with no credit card required. Since a lot of us are already in lockdown or entering it this is a great time to make the most of it and learn a new skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://nystudio107.com/blog/an-annotated-docker-config-for-frontend-web-development"&gt;→ An Annotated Docker Config for Frontend Web Development&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This article provides an in-depth guide to the advantages of using Docker to set up your front-end web development project. By the end of it, you should have all of your project defined in a docker file that you are easily able to run on your machine or anyone else's with one easy command.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://css-tricks.com/react-suspense-in-practice/"&gt;→ React Suspense in Practice&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This in-depth look at React suspense goes over how it can be used to create better user experiences with a multi-data source web application. With react suspense were able to communicate to the user the state of loading the multiple data sources whilst keeping as much of the UI as interactive as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://slack.engineering/how-big-technical-changes-happen-at-slack-f1569d25ee7b"&gt;→ How Big Technical Changes Happen at Slack&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The engineers over at slack share some thoughts about how they approach performing big changes at their organisation. In this article, they go over the adoption curve while sharing their learnings and strategies to navigate this curve coming from slacks own internal technology change initiatives as case studies.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/pluralsight/how-i-got-my-website-to-load-in-1-second-27lo"&gt;→ How I Got My Website to Load in 1 Second&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A great look at some of the tools and processes you can use to optimise your sites for faster loading and better user experiences. There should be some learnings in this article that should be usable for almost any website.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://laurakalbag.com/how-to-read-rss-in-2020/"&gt;→ Laura Kalbag – How to read RSS in 2020&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you've wanted to regain control back over your media consumption check out this comprehensive guide on how you can achieve this with RSS in 2020. In this article, the basics of RSS is covered as well as many recommendations for RSS readers to ingest these feeds for anyone's use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/monicafidalgo/how-to-host-a-website-on-google-drive-for-free-1ejk"&gt;→ How to Host A Website On Google Drive for Free&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you got a site that you need to host for the minimum amount of effort check out this article that shows how you can host your site just on your google drive.&lt;/p&gt;




&lt;p&gt;Hopefully, you can all find a way to stay busy and make the most out of isolation/lockdowns but make sure you remember to stay safe and stay healthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read more articles over on the &lt;a href="https://codepunnet.com"&gt;Code Punnet&lt;/a&gt; blog.&lt;/li&gt;
&lt;li&gt;Consider subscribing to the blogs &lt;a href="https://codepunnet.com/subscribe"&gt;weekly newsletter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Follow for more on &lt;a href="https://twitter.com/CodePunnet"&gt;twitter&lt;/a&gt; or the blogs &lt;a href="https://codepunnet.com/rss"&gt;RSS feed&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Articles around the web (29-03-2020)</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Sun, 29 Mar 2020 10:55:27 +0000</pubDate>
      <link>https://forem.com/aaronktberry/articles-around-the-web-29-03-2020-4j9h</link>
      <guid>https://forem.com/aaronktberry/articles-around-the-web-29-03-2020-4j9h</guid>
      <description>&lt;p&gt;Here's a collection of some interesting articles from around the web this week revolving around all things technology and programming. This is part of the &lt;a href="https://codepunnet.com"&gt;CodePunnet&lt;/a&gt; blog weekly newsletter. If you would like to get this update in your inbox make sure to subscribe to the &lt;a href="https://codepunnet.com/subscribe"&gt;newsletter&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://www.jeffgeerling.com/blog/2020/ansible-101-jeff-geerling-new-series-on-youtube"&gt;→ Ansible 101 by Jeff Geerling - new series on YouTube&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Jeff Gerrling has started a new series called Ansible 101. If you've ever wanted to get started using ansible or wanted to go over the basics again you should follow along with the series following along with his book &lt;a href="https://www.ansiblefordevops.com/"&gt;ansible for DevOps&lt;/a&gt;. If you've ever checked out anything todo with ansible you've probably seen his name pop up in the community so he's got a lot of knowledge to share when it comes to Ansible and how it can help you manage your configurations.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.hanselman.com/blog/TakeRemoteWorkerEducatorWebcamVideoCallsToTheNextLevelWithOBSNDIToolsAndElgatoStreamDeck.aspx"&gt;→ Take Remote Worker/Educator webcam video calls to the next level with OBS, NDI Tools, and Elgato Stream Deck&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Scott Henselman goes over some great software you can use to make your video streaming setup even better hopefully making it easier to share information with your students or workmates so that you can get your work done easier and quicker.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/helenanders26/sql-and-database-wrap-up-march-2020-3nge"&gt;→ SQL and Database Wrap Up - March 2020&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With March coming to an end the monthly database wrap up from &lt;a href="https://dev.to/helenanders26"&gt;Helen Anderson&lt;/a&gt; is in again. If you have to work with databases you should be able to find something interesting or relevant to your work in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://medium.com/@tjblogumas/scaling-devops-with-ansible-ff6e79c43a5f"&gt;→ Scaling DevOps with Ansible&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This multi-part series covers designing and using Ansible roles within an organization in such a way that developers regardless of the business can contribute and build out a catalogue of DevOps services. If you work in a medium-to-large enterprise software shop, this is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://facinating.tech/2020/02/22/in-depth-guide-to-running-elasticsearch-in-production/"&gt;→ In depth guide to running Elasticsearch in production&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This guide is a fantastic resource for everything to do with getting elastic search production-ready for your needs. It covers everything from the basics of how elastic search is designed and functions all the way to some of the intricacies of running it in a production environment and all of the requirements that are involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.blog/2020-03-26-february-service-disruptions-post-incident-analysis/"&gt;→ February service disruptions post-incident analysis&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Github may have experienced another service interruption in February but it is another great opportunity to learn from what happened. With this post-incident analysis, we find out the timeline of what happened as well as what was learned by Github from the incident as well as the most important step of what is done to remediate this incident from happening again.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.blog/2020-03-25-six-years-of-the-github-security-bug-bounty-program/"&gt;→ Six years of the GitHub Security Bug Bounty program&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As the Github bounty program enters its 6th year the organisation takes a look at some of the highlights for 2019 and 2020 so far for the program such as some of the cool bugs that have been discovered and remediated.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/cloudbees/canary-deployment-what-it-is-and-how-to-use-it-3gfg"&gt;→ Canary Deployment: What It Is and How To Use It&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this article, you should get all the information you need to understand canary development and hopefully answer some of the questions that cause so much confusion around it such as, "Does the Release Need It?", "What Infrastructure Do I Need?" and others.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.ansible.com/blog/hands-on-with-ansible-collections"&gt;→ Hands On With Ansible collections&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you work with ansible there's some interesting changes coming down the pipeline around how modules are now being handled as collections. This article should give you all the information you need to get started with these collections and migrate your code to using them.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://heronebag.com/blog/unexpected-benefits-of-asynchronous-remote-work/"&gt;→ Unexpected benefits of asynchronous remote work&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With all the work from home changes happening for most people, this article covers some of the unexpected changes that have been positive when carrying out work asynchronous when teams are working remotely from each other.&lt;/p&gt;




&lt;p&gt;Another week wrapped up with lots of news outside of the tech and programming sphere as well as inside it. Remember to keep safe and keep healthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read more articles over on the &lt;a href="https://codepunnet.com"&gt;Code Punnet&lt;/a&gt; blog.&lt;/li&gt;
&lt;li&gt;Consider subscribing to the blogs &lt;a href="https://codepunnet.com/subscribe"&gt;weekly newsletter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Follow for more on &lt;a href="https://twitter.com/CodePunnet"&gt;twitter&lt;/a&gt; or the blogs &lt;a href="https://codepunnet.com/rss"&gt;RSS feed&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Articles around the web (22-03-2020)</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Sun, 22 Mar 2020 08:02:40 +0000</pubDate>
      <link>https://forem.com/aaronktberry/articles-around-the-web-22-03-2020-4geb</link>
      <guid>https://forem.com/aaronktberry/articles-around-the-web-22-03-2020-4geb</guid>
      <description>&lt;p&gt;Here's a collection of some interesting articles from around the web this week revolving around all things technology and programming. This is part of the &lt;a href="https://codepunnet.com"&gt;CodePunnet&lt;/a&gt; blog weekly newsletter. If you would like to get this update in your inbox make sure to subscribe to the &lt;a href="https://codepunnet.com/subscribe"&gt;newsletter&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.blog/2020-03-16-npm-is-joining-github/"&gt;→ NPM is joining GitHub&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With this acquisition, Github has said their main focus for NPM is to help NPM invest in the registry infrastructure and platform, Improve the core experience and engage with the community further. With this acquisition, Microsoft is further solidifying its stance as an open-source player in the market.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://engineering.fb.com/production-engineering/ntp-service/"&gt;→ Building a more accurate time service at Facebook scale&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Working with time can always pose some challenges but at the scale of an organisation like Facebook, these can get quite complex and require a high degree of accuracy and reliability not usually designed for. In this article, the engineers at Facebook assess some of the time synchronisation options out there with a very deep look at the analytical advantages and disadvantages of each.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://stackoverflow.blog/2020/03/13/scaling-your-vpn-overnight/"&gt;→ Scaling your VPN overnight&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With COVID-19 forcing a lot more people to begin working from home quickly means that a lot of organisations have also had to scale their remote work infrastructure as well. The stack overflow team shares its findings from this experience and some of the best practices they have developed.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://pod.link/thecsspodcast"&gt;→ The CSS Podcast&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you're a developer who enjoys CSS this new podcast is for you. Adam and Una from google get together to discuss all things in the world of CSS with their first two episodes covering "The box model" and "Selectors"&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://stackoverflow.blog/2020/03/18/how-to-develop-a-defensive-plan-for-your-open-source-software-project/"&gt;→ How to develop a defensive plan for your open-source software project&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this article, you'll find some of the core principles you should consider for planning your open source project defensively to make it as secure as the most rigorously developed proprietary code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://stackoverflow.blog/2020/03/16/how-event-driven-architecture-solves-modern-web-app-problems/"&gt;→ How event-driven architecture solves modern web app problems&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A great discussion on some of the key problems in modern web development and how designing applications with an event-driven architecture can solve some of these problems in a more novel way.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.hanselman.com/blog/CSITheCaseOfTheMissingWAVAudioFilesOnTheFAT32SDCard.aspx"&gt;→ CSI: The case of the missing WAV audio files on the FAT32 SD Card&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;An in-depth investigation into an interesting hardware storage issue with certain file types on SD cards. If you enjoy working with hardware or learning about the interaction between hardware and software you'll find something interesting in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://stackoverflow.blog/2020/03/12/working-from-home-tips-from-our-experienced-remote-employees/"&gt;→ Working from home tips from our experienced remote employees&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Again with more people working from home for extended periods of time some of the experienced remote employees at stack overflow share some of their personal tips for making this time as easy and productive as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/molly_struve/how-to-give-engineers-filtered-database-access-8b6"&gt;→ How To Give Engineers Filtered Database Access&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Data access for developers is always a challenge trying to balance making it as easy as possible whilst also making it as secure as possible. This article covers a strategy on how you can do this as effectively as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/swyx/observability-for-frontend-developers-5bb7"&gt;→ Observability for Frontend Developers&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This article provides you with a great explanation of what observability is and how frontend developers can use it to make their work more productive and easier when addressing issues with their code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dev.to/pluralsight/donate-your-unused-cpu-cycles-to-fight-the-coronavirus-45d7"&gt;→ Donate Your Unused CPU Cycles to Fight the Coronavirus&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you have a spare computer at home you can help the fight against COVID-19 by helping solve protein folding problems using your CPUs idle cycles. This article should get you started installing and using "Folding At Home" to try and help in any way possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://css-tricks.com/a-few-background-patterns-sites/"&gt;→ A Few Background Patterns Sites&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A collection of some sites where you can get some quick background patterns for your applications or sites in a pinch for anything you may be developing.&lt;/p&gt;




&lt;p&gt;That's all the links for this week, stay safe and look after each other (But not too close). 🤚&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read more articles over on the &lt;a href="https://codepunnet.com"&gt;Code Punnet&lt;/a&gt; blog.&lt;/li&gt;
&lt;li&gt;Consider subscribing to the blogs &lt;a href="https://codepunnet.com/subscribe"&gt;weekly newsletter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Follow for more on &lt;a href="https://twitter.com/CodePunnet"&gt;twitter&lt;/a&gt; or the blogs &lt;a href="https://codepunnet.com/rss"&gt;RSS feed&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Creating proxmox templates with packer</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Sun, 01 Mar 2020 13:18:22 +0000</pubDate>
      <link>https://forem.com/aaronktberry/creating-proxmox-templates-with-packer-1b35</link>
      <guid>https://forem.com/aaronktberry/creating-proxmox-templates-with-packer-1b35</guid>
      <description>&lt;p&gt;I've been using proxmox for a while now in my homelab as an open-source alternative to something like ESXi for a virtualization platform. With proxmox when can create templates for our VMS so we can have a standard starting point to install our applications on top of, these templates can be useful too so that you can pre-install packages for authentication, security, logging and etc without anyone else needing to think about it.&lt;/p&gt;

&lt;p&gt;However, creating and managing these templates can become a challenge with how time-consuming and manual it can be. I want to show you how you can make this process more standardized and automated with the use of &lt;a href="https://packer.io/" rel="noopener noreferrer"&gt;packer&lt;/a&gt; to allow you to declare your proxmox templates as code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is packer
&lt;/h2&gt;

&lt;p&gt;Packer is a utility that allows you to build virtual machine images so that you can define a golden image as code. Packer can be used to create images for almost all of the big cloud providers such as AWS, GCE, Azure and Digital Ocean, or can be used with locally installed hypervisors such as VMWare, Proxmox and a few others.&lt;/p&gt;

&lt;p&gt;To build an image with packer we need to define our image through a template file. The file uses the JSON format and comprises of 3 main sections that are used to define and prepare your image.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://packer.io/docs/basics/terminology.html#builders" rel="noopener noreferrer"&gt;Builders&lt;/a&gt;: Components of Packer that are able to create a machine image for a single platform. A builder is invoked as part of a build in order to create the actual resulting images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://packer.io/docs/basics/terminology.html#provisioners" rel="noopener noreferrer"&gt;Provisioners&lt;/a&gt;: Install and configure software within a running machine prior to that machine being turned into a static image. Example provisioners include shell scripts, Chef, Puppet, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://packer.io/docs/basics/terminology.html#post-processors" rel="noopener noreferrer"&gt;Post Processors&lt;/a&gt;: Take the result of a builder or another post-processor and process that to create a new artifact. Examples of post-processors are compress and upload to compress and upload artifacts respectively, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using packer we can define our golden VM image as code so that we can easily build identically configured images on demand so that all your machines are running the same image and can also be easily updated to a new image when needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing your packer template
&lt;/h2&gt;

&lt;p&gt;For the following examples ill be referencing files from &lt;a href="https://github.com/Aaron-K-T-Berry/packer-ubuntu-proxmox-template" rel="noopener noreferrer"&gt;this example repo&lt;/a&gt; you can follow along with and should be a solid template to start off from for your own custom proxmox templates.&lt;/p&gt;

&lt;p&gt;To create the template we will use the &lt;a href="https://packer.io/docs/builders/proxmox.html" rel="noopener noreferrer"&gt;&lt;code&gt;proxmox builder&lt;/code&gt;&lt;/a&gt; which connects through the proxmox web API to provision and configure the VM for us and then turn it into a template. To configure our template we will use a &lt;a href="https://github.com/Aaron-K-T-Berry/packer-ubuntu-proxmox-template/blob/master/example-vars.json" rel="noopener noreferrer"&gt;variables file&lt;/a&gt;, to import this variables file we will use the &lt;code&gt;-var-file&lt;/code&gt; flag to pass in our variables to packer. These variables will be used in our template file with the following syntax within a string like so &lt;code&gt;"passwd/username={{ user 'ssh_username'}}"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now the builder block below will outline the basic properties of our desired proxmox template such as its name, the allocated resources and the devices attached to the VM. To achieve this the &lt;a href="https://packer.io/docs/builders/qemu.html#boot-configuration" rel="noopener noreferrer"&gt;&lt;code&gt;boot_command&lt;/code&gt;&lt;/a&gt; option will be used to boot the OS and tell it to look for the preseed file to automate the OS installation process. Packer has an inbuilt HTTP server to serve this &lt;a href="https://github.com/Aaron-K-T-Berry/packer-ubuntu-proxmox-template/blob/master/http/preseed.cfg" rel="noopener noreferrer"&gt;&lt;code&gt;preseed.cfg&lt;/code&gt;&lt;/a&gt; file to the VM as its installing by using the &lt;a href="https://packer.io/docs/builders/qemu.html#http_directory" rel="noopener noreferrer"&gt;&lt;code&gt;http_directory&lt;/code&gt;&lt;/a&gt; option in the &lt;code&gt;builder&lt;/code&gt; to specify the public files of the HTTP server. &lt;a href="https://help.ubuntu.com/lts/installation-guide/s390x/apbs02.html" rel="noopener noreferrer"&gt;Check out the ubuntu preseed documentation&lt;/a&gt; for info on modifying the automatic installation process of the OS via a pre seed file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;builders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proxmox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proxmox_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://{{user `proxmox_host`}}:8006/api2/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;insecure_skip_tls_verify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{user `proxmox_api_user`}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{user `proxmox_api_password`}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vm_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `vmid` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vm_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{user `template_name`}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;template_description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `template_description` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{user `proxmox_node`}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cores&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `cores` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sockets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `sockets` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;memory&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `memory` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;os&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l26&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;network_adapters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;virtio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bridge&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vmbr0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scsi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disk_size&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `disk_size`}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;storage_pool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{user `datastore`}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;storage_pool_type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{user `datastore_type`}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;format&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;raw&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cache_mode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;writeback&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh_timeout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;90m&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh_password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `ssh_password` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh_username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `ssh_username` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qemu_agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unmount_iso&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;iso_file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{user `iso`}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http_directory&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;boot_wait&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;boot_command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ user `boot_command_prefix` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/install/vmlinuz &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;console-setup/ask_detect=false &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;debconf/frontend=noninteractive &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;debian-installer={{ user `locale` }} &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hostname={{ user `hostname` }} &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fb=false &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grub-installer/bootdev=/dev/sda&amp;lt;wait&amp;gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;initrd=/install/initrd.gz &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kbd-chooser/method=us &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keyboard-configuration/modelcode=SKIP &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;locale={{ user `locale` }} &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noapic &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;passwd/username={{ user `ssh_username` }} &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;passwd/user-fullname={{ user `ssh_fullname` }} &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;passwd/user-password={{ user `ssh_password` }} &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;passwd/user-password-again={{ user `ssh_password` }} &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/{{ user `preseed.cfg` }} &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-- &amp;lt;enter&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this template, we will also be using the &lt;a href="https://packer.io/docs/provisioners/shell.html" rel="noopener noreferrer"&gt;&lt;code&gt;shell&lt;/code&gt;&lt;/a&gt; provisioner to configure our VM os once it has been installed onto the virtual machine and is available via SSH. This can be helpful for installing the minimum required packages on your VM's such as the &lt;a href="https://pve.proxmox.com/wiki/Qemu-guest-agent" rel="noopener noreferrer"&gt;QEMU quest agent&lt;/a&gt; and &lt;a href="https://pve.proxmox.com/wiki/Cloud-Init_Support" rel="noopener noreferrer"&gt;cloud init&lt;/a&gt; or any other software required. You can also switch this provisioner auto for any of the other provisioners such as ansible, chef or puppet for example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;provisioners&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pause_before&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;20s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;environment_vars&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DEBIAN_FRONTEND=noninteractive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;date &amp;gt; provision.txt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sudo apt-get update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sudo apt-get -y upgrade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sudo apt-get -y dist-upgrade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sudo apt-get -y install linux-generic linux-headers-generic linux-image-generic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sudo apt-get -y install qemu-guest-agent cloud-init&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sudo apt-get -y install wget curl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exit 0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, we will use the post processors to run some commands locally. This will make an SSH connection to the PVE host and run some commands manually to set up the virtual devices necessary for &lt;a href="https://pve.proxmox.com/wiki/Cloud-Init_Support#_preparing_cloud_init_templates" rel="noopener noreferrer"&gt;cloud init&lt;/a&gt;. This post-processor is using the &lt;a href="https://packer.io/docs/provisioners/shell-local.html" rel="noopener noreferrer"&gt;&lt;code&gt;shell-local&lt;/code&gt;&lt;/a&gt; post processor to run the commands on the local machine running packer but you could always move this configuration to something like an ansible playbook to make the configuration more readable and portable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post-processors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shell-local&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh root@{{user `proxmox_host`}} qm set {{user `vmid`}} --scsihw virtio-scsi-pci&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh root@{{user `proxmox_host`}} qm set {{user `vmid`}} --ide2 {{user `datastore`}}:cloudinit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh root@{{user `proxmox_host`}} qm set {{user `vmid`}} --boot c --bootdisk scsi0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh root@{{user `proxmox_host`}} qm set {{user `vmid`}} --ciuser {{ user `ssh_username` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh root@{{user `proxmox_host`}} qm set {{user `vmid`}} --cipassword {{ user `ssh_password` }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh root@{{user `proxmox_host`}} qm set {{user `vmid`}} --vga std&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now with your configuration complete, you will be ready to build your proxmox template with packer. Run the command &lt;code&gt;packer build -var-file="./config.json" ./ubuntu-18.04.json&lt;/code&gt; You should see some output for each of the &lt;code&gt;builders&lt;/code&gt;, &lt;code&gt;provisioners&lt;/code&gt; and &lt;code&gt;post-processors&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;packer build &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./config.json"&lt;/span&gt; ./ubuntu-18.04.json
proxmox: output will be &lt;span class="k"&gt;in &lt;/span&gt;this color.

&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; proxmox: Creating VM
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; proxmox: Starting VM
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; proxmox: Starting HTTP server on port 8771

...

Build &lt;span class="s1"&gt;'proxmox'&lt;/span&gt; finished.

&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt; Builds finished. The artifacts of successful builds are:
&lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; proxmox: A template was created: 4444
&lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; proxmox:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the process is complete you should see your template ready in the proxmox interface and ready to be cloned into virtual machines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh508fin6qk40qh6g57gp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh508fin6qk40qh6g57gp.png" alt="Completed proxmox template" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading on packer
&lt;/h2&gt;

&lt;p&gt;You should now have a good starting point for building proxmox templates with packer. If your looking to extend its usefulness a little further check out these useful articles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://packer.io/intro/getting-started/install.html" rel="noopener noreferrer"&gt;Getting started with packer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/16.04/installation-guide/i386/apbs04.html" rel="noopener noreferrer"&gt;Ubuntu docs for the pre-seed file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/solutions/automated-build-images-with-jenkins-kubernetes" rel="noopener noreferrer"&gt;Automated image builds with Jenkins, Packer, and Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://semaphoreci.com/community/tutorials/continuous-deployment-of-golden-images-with-packer-and-semaphore" rel="noopener noreferrer"&gt;Continuous Deployment of Golden Images with Packer and Semaphore&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make sure to follow on &lt;a href="https://aaron-kt-berry.medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, &lt;a href="https://twitter.com/Aaron_KT_Berry" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://aaron-kt-berry.medium.com/subscribe" rel="noopener noreferrer"&gt;Email&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;If you are thinking of subscribing on Medium, you can use my &lt;a href="https://aaron-kt-berry.medium.com/membership" rel="noopener noreferrer"&gt;referral link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Connect with me on &lt;a href="https://www.linkedin.com/in/aaron-kt-berry/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; if you want to chat&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@chuttersnap?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;chuttersnap&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/warehouse?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>packer</category>
      <category>proxmox</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Getting your first software dev internship</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Mon, 10 Feb 2020 11:25:24 +0000</pubDate>
      <link>https://forem.com/aaronktberry/getting-your-first-software-dev-internship-3nh6</link>
      <guid>https://forem.com/aaronktberry/getting-your-first-software-dev-internship-3nh6</guid>
      <description>&lt;p&gt;Getting a software dev internship can be a daunting process but there are a few things that you could be doing to make the process a little easier. I had to complete a year's worth of internships to complete the professional engineering portion of my software engineering degree. I initially found this process to be a challenge but with a few tweaks and learnings along the way, I think I made the process a little easier for myself. I want to share some of those tips with you to make the process easier and hopefully get you the internship you want as well.&lt;/p&gt;

&lt;p&gt;For all the information I provide in this post It will be in the context of finding and applying for an internship in Sydney Australia as a software engineering student. However, most of this information should translate to other regions as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing your CV
&lt;/h2&gt;

&lt;p&gt;For your CV you want to aim for a length of about 1 - 2 pages, anything more than your going to be hiding information in pages that most likely won't be read. Your CV should have your current work experience, your current academic attainments and your technical expertise in things like languages and frameworks you're comfortable with. You should be aiming to try and match the qualities on your CV with the qualities that the employer is looking for in an ideal candidate. I want to also stress that you don't need to include everything in your work or education history if it is not relevant to the role, For example, if your halfway through your university degree you don't need to include your high school on your CV anymore and you should be using that space for something more relevant for the position your applying for.&lt;/p&gt;

&lt;p&gt;On your CV you want to also make sure you have your current contact details present including your full name, email and phone number. You may also want to consider having the details of some of your other social accounts if they are related to the role such as Github, Dev or CodePen so that the employer can see some of your actual projects or writing.&lt;/p&gt;

&lt;p&gt;Finally with your CV, save yourself some embarrassment only realising you missed something after you sent off your application and get someone (or more if you can) to read over your CV to make sure you don't have any silly typos, spelling or weird grammar you missed after reading your CV for the 100th time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching for internships
&lt;/h2&gt;

&lt;p&gt;Now that your CV is all polished and ready to go we need to find some jobs to actually apply for. The job posting sites can be pretty region specific so use what's available in your area but ill just list all the ones I used in my internship search and note if the site is available somewhere else. I would recommend that where applicable you set up alerts for these sites so that you can stay up to date with new postings so you can use your time more efficiently when applying for roles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/"&gt;LinkedIn&lt;/a&gt; (Global)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.jora.com/"&gt;Jora&lt;/a&gt; (Global)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.indeed.com/"&gt;Indeed&lt;/a&gt; (Australia and U.S.)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.seek.com.au/"&gt;Seek&lt;/a&gt; (Australia)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your currently studying in university make sure to reach out to the careers department of your institution. They usually have some great resources when it comes to finding jobs such as a list of which companies have internships or they might even host their own job boards just for students like my university did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing your cover letter
&lt;/h2&gt;

&lt;p&gt;This step isn't always required but is definitely recommended if you have the time. A cover letter is basically just a short (usually 1 page) description of yourself and an example of how you're interested in the internship and how you would be suitable as a potential candidate for that role. Employers are likely to read your CV and cover letter at the same time so make sure your grammar and spelling are on point and that the information between your CV and cover letter match.&lt;/p&gt;

&lt;p&gt;It can seem like a lot of work to have to write a cover letter for each application you make so I recommend you write up a template for your cover letter early. This is going to save you a lot of time with you just needing to change names and a few sentences here and there to tailor your cover letter for the company your applying for. At the peak of me trying to apply for internships using templates, I could have a custom CV and cover letter tailored for the requirements of the roles ideal candidate done in just 30 minutes on average.&lt;/p&gt;

&lt;p&gt;Check out these articles for getting started with writing your cover letter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.seek.com.au/career-advice/article/cover-letters-the-good-and-the-bad"&gt;Cover letters, The good and the bad - Seek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.glassdoor.com/blog/guide/how-to-write-a-cover-letter/"&gt;How to Write A Cover Letter - Glassdoor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.hays.com.au/career-advice/cover-letter-764"&gt;How to write a cover letter - Hays&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Interview prep
&lt;/h2&gt;

&lt;p&gt;WOOO! You got yourself an interview and now you just need to get through this step and you're probably home free. For your interview, you're going to want to prepare both your soft skills and your technical skills.&lt;/p&gt;

&lt;p&gt;For your soft skills, these are things like your ability to communicate, provided feedback and work in a team. Soft skills are something you develop over time but if you're wanting to practice them or get warmed up with these skills I would recommend you try and find a friend or mentor who can practice asking interview questions with you.&lt;/p&gt;

&lt;p&gt;For your technical skills, these can also be hard to prepare actively for your interview but I would recommend going over some basics courses for the languages you would need to work with if you got the role. I would also recommend you try and complete and explain your solution for some common technical interview questions. Additionally, look through some of the projects you've worked on and try and link those to what the company is looking for in the advertised role so when asked how you demonstrated a skill you can show off a project you've already completed nicely linking what you've already done with what they are looking for.&lt;/p&gt;

&lt;p&gt;If your looking for some more info on preparing your soft skills to check out the links below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://business.linkedin.com/talent-solutions/blog/interview-questions/2016/the-most-popular-interview-questions-to-reveal-key-soft-skills"&gt;The Most Popular Interview Questions to Reveal Key Soft Skills - Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goskills.com/Soft-Skills/Articles/Soft-skills-interview-questions-answers"&gt;6 Most Helpful Soft Skills Interview Questions and Answers - Goskills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.forbes.com/sites/ashiraprossack1/2019/03/28/soft-skills-in-interview/#90a009b1108f"&gt;How To Highlight Soft Skills In A Job Interview - Forbes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if you need help with your technical skills these articles below could be helpful to you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.glassdoor.com/blog/technical-interview-tips/"&gt;What You Need to Know to Ace Your Technical Interview - Glassdoor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learntocodewith.me/posts/technical-interview/"&gt;The Ultimate Guide To Acing Your Technical Interview - Learn to code with me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.techrepublic.com/article/10-questions-software-developers-should-expect-in-a-job-interview/"&gt;10 questions software developers should expect in a job interview - TechRepublic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My personal tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Save yourself some embarrassing mistakes easily and get the &lt;a href="https://grammarly.com"&gt;grammarly extension&lt;/a&gt;, you just need the free version and use it to check your CV and cover letter before you send it to anyone.&lt;/li&gt;
&lt;li&gt;Try and be personable but professional, being too formal makes you sound like a robot and unfortunately quite forgettable so remember to be friendly and yourself.&lt;/li&gt;
&lt;li&gt;Take the effort to personalize at least some portion of your internship submission for every company be that your CV or cover letter.&lt;/li&gt;
&lt;li&gt;If you don't like the company, people or terms of the contract don't be afraid to say no, being unhappy or working under an illegal contract is never worth the work experience you may get.&lt;/li&gt;
&lt;li&gt;Rejection is part of the game but not the end, Don't be afraid to ask for feedback on why you didn't get the role and take that on board to make each application better.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully, these tips are able to help you out in your journey to getting your internship. It's a hard process and can feel very defeating at times, but people have done it before and as long as your learning throughout the process you'll get the internship in the end.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make sure to follow on &lt;a href="https://aaron-kt-berry.medium.com/"&gt;Medium&lt;/a&gt;, &lt;a href="https://twitter.com/Aaron_KT_Berry"&gt;Twitter&lt;/a&gt; or &lt;a href="https://aaron-kt-berry.medium.com/subscribe"&gt;Email&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;If you are thinking of subscribing on Medium, you can use my &lt;a href="https://aaron-kt-berry.medium.com/membership"&gt;referral link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Connect with me on &lt;a href="https://www.linkedin.com/in/aaron-kt-berry/"&gt;LinkedIn&lt;/a&gt; if you want to chat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@sunday_digital?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Nastuh Abootalebi&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A11y testing web apps with axe-core</title>
      <dc:creator>Aaron Berry</dc:creator>
      <pubDate>Thu, 09 Jan 2020 05:38:12 +0000</pubDate>
      <link>https://forem.com/aaronktberry/a11y-testing-web-apps-with-axe-core-150d</link>
      <guid>https://forem.com/aaronktberry/a11y-testing-web-apps-with-axe-core-150d</guid>
      <description>&lt;p&gt;When we build applications we like to make sure that they work. To assure this we would write our normal unit, stub and integration tests. However, one thing that isn't usually being tested in these suits is the accessibility of our web applications.&lt;/p&gt;

&lt;p&gt;In comes &lt;a href="https://github.com/dequelabs/axe-core" rel="noopener noreferrer"&gt;axe-core&lt;/a&gt; which as been developed by &lt;a href="https://www.deque.com/" rel="noopener noreferrer"&gt;deque systems&lt;/a&gt;. I'll briefly outline how we can easily configure and use axe for our needs and how it can be integrated into your current tooling so we can start finding (and fixing!) accessibility defects in our web applications TODAY 😃.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is axe
&lt;/h2&gt;

&lt;p&gt;From the &lt;a href="https://github.com/dequelabs/axe-core" rel="noopener noreferrer"&gt;axe-core&lt;/a&gt; repo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Axe is an accessibility testing engine for websites and other HTML-based user interfaces. It's fast, secure, lightweight, and was built to seamlessly integrate with any existing test environment so you can automate accessibility testing alongside your regular functional testing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What this means is that we can use axe to analyse our web applications DOM structure for accessibility issues. This is done via a rule-based system allowing you to configure axe for your needs and requirements, you can find all the axe rules &lt;a href="https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;. These rules test against common accessibility guidelines and standards such as WCAG, Section 508 and axe's own ruleset.&lt;/p&gt;

&lt;p&gt;An example simple axe configuration below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// axe-config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;landmark-one-main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration can become much more complex with the &lt;a href="https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axeconfigure" rel="noopener noreferrer"&gt;extended attributes&lt;/a&gt; you can use such as CSS selectors, tags or excluding hidden elements making axe-core highly configurable for your testing requirements.&lt;/p&gt;

&lt;p&gt;This same configuration should be importable into any of the projects that utilise the &lt;a href="https://github.com/dequelabs/axe-core" rel="noopener noreferrer"&gt;axe-core&lt;/a&gt; engine allowing you to standardize and share your configurations across tooling and applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can I use axe to test accessibility
&lt;/h2&gt;

&lt;p&gt;Now that we know axe can allow for us to test accessibility in our web applications how do I actually implement it? Below ill go over a couple of common ways you can easily implement axe into your testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployed sites (&lt;a href="https://github.com/dequelabs/axe-cli" rel="noopener noreferrer"&gt;axe-cli&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;If your application is already deployed and accessible via HTTP/S it's as simple as running the axe CLI against your applications URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; axe-cli
axe http://your-site.com/page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solution works best for simple HTML pages without authentication or that can easily be navigated to via URL paths. If you require any kind of user actions to get to the desired pages to test have a look at the sections on either Puppeteer or Selenium implementations of axe.&lt;/p&gt;

&lt;h3&gt;
  
  
  React (&lt;a href="https://github.com/dequelabs/react-axe" rel="noopener noreferrer"&gt;react-axe&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;This is a great tool that can be incorporated into almost any react application quite easily with the following snippet being all that's needed, just make sure to load it before you load your main react application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;axe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-axe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;axe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React axe is now able to show you the a11y errors and even give you some nice DOM highlighting of where the issue is happening when applicable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frm3g33bhze0hvr51bcqo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frm3g33bhze0hvr51bcqo.jpg" alt="react axe dom highlighting"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh326k80b4ql0eah1v2xk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh326k80b4ql0eah1v2xk.jpg" alt="react axe console output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React axe is also smart enough to reload and re-analyse when components in the DOM are re-rendered making the developer experience great when using it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Jest (&lt;a href="https://github.com/nickcolley/jest-axe" rel="noopener noreferrer"&gt;jest-axe&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;Now if your team is using something like jest integrating axe into your testing suite is as simple as the snippet below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;axe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toHaveNoViolations&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-axe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toHaveNoViolations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should demonstrate this matcher`s usage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;img src="#"/&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="c1"&gt;// pass anything that outputs html to axe&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;axe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveNoViolations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some nice helper methods provided by this implementation such as the  &lt;code&gt;toHaveNoViolations&lt;/code&gt; function. Once you run your tests you'll be provided with nicely formated errors as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6tn50aqhqz8lxxj0yvrz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6tn50aqhqz8lxxj0yvrz.jpg" alt="react axe console output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Puppeteer (&lt;a href="https://github.com/dequelabs/axe-puppeteer" rel="noopener noreferrer"&gt;axe-puppeteer&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;With the use of axe-puppeteer it's again easy to implement axe into your existing tests with axe being injected automatically for you and just need to call the &lt;code&gt;analyze&lt;/code&gt; function when the DOM is in the desired state to be tested.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AxePuppeteer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axe-puppeteer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;puppeteer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBypassCSP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://dequeuniversity.com/demo/mars/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AxePuppeteer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One note with this implementation is that you will have to fail your tests by evaluating the results object to your testing requirements as an easy function is not provided like the jest-axe implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Selenium (&lt;a href="https://github.com/dequelabs/axe-webdriverjs" rel="noopener noreferrer"&gt;axe-webdriverjs&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;Finally, if your using something like selenium axe-core can still be integrated into your current tests with axe-webdriverjs. This solution simply hooks into the web driver object and runs analysis on the rendered DOM when the &lt;code&gt;analyze&lt;/code&gt; function is called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;AxeBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axe-webdriverjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;WebDriver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;selenium-webdriver&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebDriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forBrowser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firefox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;driver&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://dequeuniversity.com/demo/mars/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;AxeBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// Handle error somehow&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to the puppeteer implementation you'll have to evaluate the results object for more fine-grained control over the failure criteria for the axe analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;By utilizing axe for testing accessibility in your web application you can make sure that your applications at the minimum cover some of the best standards when it comes to web accessibility. Also moving as much of the simple accessibility testing covered by axe into code should allow you to catch the simple errors faster saving time and money for the user testing later on.&lt;/p&gt;

&lt;p&gt;If your tool or framework wasn't covered make sure check out the full list of projects that use the axe engine &lt;a href="https://github.com/dequelabs/axe-core/blob/develop/doc/projects.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connect further
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make sure to follow on &lt;a href="https://aaron-kt-berry.medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;, &lt;a href="https://twitter.com/Aaron_KT_Berry" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://aaron-kt-berry.medium.com/subscribe" rel="noopener noreferrer"&gt;Email&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;If you are thinking of subscribing on Medium, you can use my &lt;a href="https://aaron-kt-berry.medium.com/membership" rel="noopener noreferrer"&gt;referral link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Connect with me on &lt;a href="https://www.linkedin.com/in/aaron-kt-berry/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; if you want to chat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@dannyg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;DANNY G&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
