<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.6">Jekyll</generator><link href="https://qubitrenegade.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://qubitrenegade.com/" rel="alternate" type="text/html" /><updated>2019-09-18T21:09:59+00:00</updated><id>https://qubitrenegade.com/feed.xml</id><title type="html">Qubit Renegade</title><subtitle>Current status - breaking things.</subtitle><entry><title type="html">Migrating to GitLab</title><link href="https://qubitrenegade.com/2019/09/08/Migrating-to-gitlab.html" rel="alternate" type="text/html" title="Migrating to GitLab" /><published>2019-09-08T07:00:29+00:00</published><updated>2019-09-08T07:00:29+00:00</updated><id>https://qubitrenegade.com/2019/09/08/Migrating-to-gitlab</id><content type="html" xml:base="https://qubitrenegade.com/2019/09/08/Migrating-to-gitlab.html">&lt;p&gt;After a bit of debate, I’ve moved the blog to &lt;a href=&quot;https://about.gitlab.com/product/pages/&quot;&gt;GitLab Pages&lt;/a&gt;.  This has nothing to do with the change in ownership at GitHub and everything to do with wanting more control over the build process.  Unfortunately, GH Pages only supports &lt;a href=&quot;https://pages.github.com/versions/&quot;&gt;a specific list&lt;/a&gt; of Jekyll plugins.&lt;/p&gt;

&lt;p&gt;The blog may end up back on GitHub as the idea is “as little work as possible”… but for now we’re trying the GitLab experiment.&lt;/p&gt;

&lt;p&gt;I’ll probably have more to say on this topic at a later point.  This mostly serves to validate that our CDN is working.&lt;/p&gt;

&lt;h2 id=&quot;initial-impressions-12-hours-after-initial-post&quot;&gt;Initial impressions (12 hours after initial post)&lt;/h2&gt;

&lt;p&gt;Well, out of the gate it was easy to implement automated spellcheck, however, redirecting the default &lt;code class=&quot;highlighter-rouge&quot;&gt;gitlab.io&lt;/code&gt; domain to &lt;a href=&quot;https://qubitrenegade.com&quot;&gt;qubitrenegade.com&lt;/a&gt; was a bit tricky…  It &lt;a href=&quot;https://gitlab.com/gitlab-org/gitlab-ce/issues/42949#note_206473489&quot;&gt;looks like&lt;/a&gt; this may be a feature coming soon, which is so far the only thing missing for feature parity with GitHub Pages.&lt;/p&gt;</content><author><name></name></author><summary type="html">After a bit of debate, I’ve moved the blog to GitLab Pages. This has nothing to do with the change in ownership at GitHub and everything to do with wanting more control over the build process. Unfortunately, GH Pages only supports a specific list of Jekyll plugins.</summary></entry><entry><title type="html">Configuring Matrix and Riot for private Chat</title><link href="https://qubitrenegade.com/matrix/synapse/riot/privacy/chat/2019/08/01/Matrix-and-Riot-for-privacy-chat.html" rel="alternate" type="text/html" title="Configuring Matrix and Riot for private Chat" /><published>2019-08-01T02:38:21+00:00</published><updated>2019-08-01T02:38:21+00:00</updated><id>https://qubitrenegade.com/matrix/synapse/riot/privacy/chat/2019/08/01/Matrix-and-Riot-for-privacy-chat</id><content type="html" xml:base="https://qubitrenegade.com/matrix/synapse/riot/privacy/chat/2019/08/01/Matrix-and-Riot-for-privacy-chat.html">&lt;h1 id=&quot;configuring-matrix-and-riot-for-private-chat&quot;&gt;Configuring Matrix and Riot for Private Chat&lt;/h1&gt;

&lt;p&gt;It’s time to replace Slack and Discord.  While they provided chat to make the transition to a “Virtual Workplace” easier, they are the very antithesis of the decentralized web.  IRC was, &lt;a href=&quot;https://m.xkcd.com/1782/&quot;&gt;and still is&lt;/a&gt;, an amazing technology.  However, running an IRC server, while not hard, isn’t exactly easy, IRC suffers from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Network_effect&quot;&gt;Network Effect&lt;/a&gt; making stand alone servers a bit pointless, and it’s not encrypted (yes you can do encryption over the wire, but the data is unencrypted at rest).  Not to mention, you’re reliant on external tools for keeping history.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href=&quot;https://matrix.org/&quot;&gt;Matrix&lt;/a&gt;.  Matrix is “An open network for secure, decentralized communication”.  Practically what this means, is Matrix attempts to solve the centralization problem by making federation easy, it solves the security problem by implementing an easy to use end-to-end encryption system, and attempts to solve the “Network Effect problem” by providing easy to use &lt;a href=&quot;https://matrix.org/bridges/&quot;&gt;bridging&lt;/a&gt; with existing chat platforms (including but not limited to Slack, Discord, and IRC).  It’s a complete, secure, chat, VoIP, and Video calling platform.&lt;/p&gt;

&lt;p&gt;Mattermost is another “Slack alternative” that deserves a special mention and received serious consideration before Matrix was ultimately chosen.  &lt;a href=&quot;https://www.slant.co/versus/12763/12764/~mattermost_vs_matrix&quot;&gt;Mattermost vs Matrix&lt;/a&gt; is really out of the scope of this conversation.  (Though I will say you absolutely &lt;em&gt;can&lt;/em&gt; edit posts with Matrix)&lt;/p&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Matrix is a protocol. Which is defined by the &lt;a href=&quot;https://matrix.org/docs/spec/&quot;&gt;Matrix Specification&lt;/a&gt;.  Matrix defines client-to-server, server-to-server, and client-to-client interactions.  What this means to the administrator/user is there is [potentially] a variety of server and client software to chose from.  The &lt;a href=&quot;https://en.wikipedia.org/wiki/Reference_implementation&quot;&gt;reference implementation&lt;/a&gt; known as &lt;a href=&quot;https://github.com/matrix-org/synapse&quot;&gt;Synapse&lt;/a&gt; and &lt;a href=&quot;https://about.riot.im/&quot;&gt;Riot.im&lt;/a&gt; appear to be the de facto standard server at client, at the time of this writing.&lt;/p&gt;

&lt;p&gt;Synapse has some &lt;a href=&quot;https://github.com/matrix-org/synapse/blob/master/README.rst&quot;&gt;great docs&lt;/a&gt; which cover nearly every scenario.  There’s also some &lt;a href=&quot;https://gist.github.com/attacus/cb5c8a53380ca755b10a5b37a636a0b9&quot;&gt;great guides&lt;/a&gt; to help get started.&lt;/p&gt;

&lt;p&gt;In short we need to install and configure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/matrix-org/synapse&quot;&gt;Synapse&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/vector-im/riot-web&quot;&gt;Riot Web&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nginx.org/en/&quot;&gt;NGINX&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.postgresql.org/&quot;&gt;PostgreSQL&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://certbot.eff.org/&quot;&gt;CertBot&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT&quot;&gt;TURN&lt;/a&gt; Server (we’ll use &lt;a href=&quot;https://github.com/coturn/coturn&quot;&gt;coturn&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is an attempt to collate all the information into a single procedure based on the information learned before it is forgotten.&lt;/p&gt;

&lt;p&gt;This guide is written as if all applications are running on the same server, however, each service can be run in its own VM/container/etc.&lt;/p&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Minimum Virtual Machine
    &lt;ul&gt;
      &lt;li&gt;1 CPU&lt;/li&gt;
      &lt;li&gt;1 GB Ram&lt;/li&gt;
      &lt;li&gt;25 GB root &lt;code class=&quot;highlighter-rouge&quot;&gt;/&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;10 GB &lt;code class=&quot;highlighter-rouge&quot;&gt;/var/lib/postgresql&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;chown postgres:postgres /var/lib/postgresql&lt;/code&gt; XFS, mounted &lt;code class=&quot;highlighter-rouge&quot;&gt;noatime&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Free CloudFlare account
    &lt;ul&gt;
      &lt;li&gt;DNS Subdomain Entries, recommend both A and AAAA entries if IPv6 is supported:
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;chat&lt;/code&gt; - Riot Web address&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;matrix&lt;/code&gt; - Matrix Server Address&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;turn&lt;/code&gt; - TURN Server address&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make it easier on ourselves since we’re using CloudFlare, we’ll leverage the &lt;a href=&quot;https://certbot-dns-cloudflare.readthedocs.io/en/stable/&quot;&gt;certbot-dns-cloudflare&lt;/a&gt; CertBot plugin for CertBot authentication.&lt;/p&gt;

&lt;h2 id=&quot;install-packages&quot;&gt;Install Packages&lt;/h2&gt;

&lt;h3 id=&quot;add-matrixorg-repo&quot;&gt;Add Matrix.org Repo&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'echo &quot;deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main&quot; |  sudo tee /etc/apt/sources.list.d/matrix-org.list'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;add-certbot-repo&quot;&gt;Add CertBot Repo&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;add-apt-repository ppa:certbot/certbot
add-apt-repository universe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;add-postgresql-repo&quot;&gt;Add PostgreSQL Repo&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget &lt;span class=&quot;nt&quot;&gt;--quiet&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; - https://www.postgresql.org/media/keys/ACCC4CF8.asc | &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-key add -
sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'echo &quot;deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main&quot; &amp;gt;&amp;gt; /etc/apt/sources.list.d/pgdg.list'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;package-list&quot;&gt;Package List&lt;/h3&gt;

&lt;h4 id=&quot;synapse&quot;&gt;Synapse&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;matrix-synapse-py3 nginx certbot python-certbot-nginx python3-certbot-dns-cloudflare
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;postgresql&quot;&gt;PostgreSQL&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/37128058/difference-between-postgresql-common-and-postgresql-contrib&quot;&gt;Common and/or Contrib&lt;/a&gt; you be the judge.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;postgresql postgresql-contrib postgresql-common
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;riot-web&quot;&gt;Riot Web&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;nginx certbot python-certbot-nginx python3-certbot-dns-cloudflare
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;turn-server&quot;&gt;TURN Server&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;coturn certbot python3-certbot-dns-cloudflare
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;all-in-one&quot;&gt;All in one&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;matrix-synapse-py3 coturn &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    postgresql postgresql-contrib postgresql-common &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    nginx certbot python-certbot-nginx python3-certbot-dns-cloudflare &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    libjemalloc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://jemalloc.net/&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;libjemalloc&lt;/code&gt;&lt;/a&gt; is optional, results are unclear if it actually helps memory usage in Python3.&lt;/p&gt;

&lt;h2 id=&quot;setup-certbot&quot;&gt;Setup CertBot&lt;/h2&gt;

&lt;h3 id=&quot;cloudflare-credentials&quot;&gt;CloudFlare Credentials&lt;/h3&gt;

&lt;p&gt;Create an &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/certbot-cloudflare.ini&lt;/code&gt;.  N.b.: you currently must use the “&lt;a href=&quot;https://support.cloudflare.com/hc/en-us/articles/200167836-Where-do-I-find-my-Cloudflare-API-key-&quot;&gt;CloudFlare Global API Key&lt;/a&gt;” for &lt;code class=&quot;highlighter-rouge&quot;&gt;certbot&lt;/code&gt; to be able to authenticate.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dns_cloudflare_email &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;your-cloudflare-email@protonmail.com&quot;&lt;/span&gt;
dns_cloudflare_api_key &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;GLOBAL API KEY&amp;gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;run-certbot&quot;&gt;Run CertBot&lt;/h3&gt;

&lt;p&gt;CertBot will use the first domain listed when generating the certificate path.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;certbot certonly &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; dns-cloudflare &lt;span class=&quot;nt&quot;&gt;--dns-cloudflare-credentials&lt;/span&gt; /etc/certbot-cloudflare.ini &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--expand&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; example.com,www.example.com,matrix.example.com,chat.example.com,turn.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will create a timer which can be validated with &lt;code class=&quot;highlighter-rouge&quot;&gt;systemctl list-timers&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# systemctl list-timers -all | grep certbot
Thu 2019-08-01 04:41:16 UTC  14min left    Wed 2019-07-31 21:19:33 UTC  7h ago      certbot.timer                certbot.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;configure-postgresql&quot;&gt;Configure PostgreSQL&lt;/h2&gt;

&lt;p&gt;See &lt;a href=&quot;https://github.com/matrix-org/synapse/blob/master/docs/postgres.rst#tuning-postgres&quot;&gt;Tuning&lt;/a&gt; for info on tuning PgSQL.&lt;/p&gt;

&lt;h3 id=&quot;create-database-user&quot;&gt;Create Database User&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; postgres createuser &lt;span class=&quot;nt&quot;&gt;--pwprompt&lt;/span&gt; synapse_user
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-database&quot;&gt;Create Database&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&quot;language-SQL&quot;&gt;sudo -u postrees psql -c '
  CREATE DATABASE synapse
    ENCODING 'UTF8'
    LC_COLLATE='C'
    LC_CTYPE='C'
    template=template0
    OWNER synapse_user;'
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;configure-coturn&quot;&gt;Configure Coturn&lt;/h2&gt;

&lt;h3 id=&quot;coturn-config&quot;&gt;Coturn Config&lt;/h3&gt;

&lt;p&gt;Create a &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/turnserver.conf&lt;/code&gt;.  This is the minimal options required.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/a16780803bb9662c7825ce9e5becd8fa.js?file=turnserver.conf&quot;&gt; &lt;/script&gt;

&lt;h3 id=&quot;enable-coturn&quot;&gt;Enable Coturn&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sh -c 'echo TURNSERVER_ENABLED=1 &amp;gt;&amp;gt; /etc/default/coturn'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;start-coturn&quot;&gt;Start Coturn&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl enable coturn # this might actually not be required because it still uses sysv init...
systemctl start coturn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;install-riot-web&quot;&gt;Install Riot Web&lt;/h2&gt;

&lt;h3 id=&quot;download-latest-release&quot;&gt;Download latest Release&lt;/h3&gt;

&lt;p&gt;The latest release can be found &lt;a href=&quot;https://github.com/vector-im/riot-web/releases&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget -O- https://github.com/vector-im/riot-web/releases/download/v1.3.0/riot-v1.3.0.tar.gz | tar vzxf - -C /var/www/html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;link-to-riot-root-dir&quot;&gt;Link to Riot root dir&lt;/h3&gt;

&lt;p&gt;We’ll use &lt;code class=&quot;highlighter-rouge&quot;&gt;/var/www/html/riot&lt;/code&gt; as the DocumentRoot of our &lt;code class=&quot;highlighter-rouge&quot;&gt;chat.example.com&lt;/code&gt; domain.  This makes upgrading (or downgrading) in the future easier.  e.g.: we can upgrade without restarting NGINX.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ln -s /var/www/html/riot-v1.3.0 /var/www/html/riot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;configure-synapse&quot;&gt;Configure Synapse&lt;/h2&gt;

&lt;h3 id=&quot;server-name-config&quot;&gt;Server Name Config&lt;/h3&gt;

&lt;p&gt;We don’t want our name to show up as &lt;code class=&quot;highlighter-rouge&quot;&gt;@foo:matrix.example.com&lt;/code&gt;, so we’ll update &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/matrix-synapse/conf.d/server_name.yaml&lt;/code&gt; to point our server name to &lt;code class=&quot;highlighter-rouge&quot;&gt;example.com&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;server_name: example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;homeserver-config-file&quot;&gt;Homeserver Config File&lt;/h3&gt;

&lt;p&gt;This is an opinionated &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/matrix-synapse/homeserver.yaml&lt;/code&gt; file and by no means covers every config option.  (We’ll look at how we can break this into multiple smaller files in a future post)&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/a16780803bb9662c7825ce9e5becd8fa.js?file=homeserver.yaml&quot;&gt; &lt;/script&gt;

&lt;h3 id=&quot;optional-tuning&quot;&gt;Optional Tuning&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;jemalloc&lt;/code&gt; purportedly reduced memory usage in Python2 up to 40% in some cases.  However, it is unclear how &lt;code class=&quot;highlighter-rouge&quot;&gt;jemalloc&lt;/code&gt; affects Python3 memory usage.  If any instability is encountered, this would be the first thing to undo.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sh -c 'echo &quot;LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1&quot; | tee -a /etc/default/matrix-synapse'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;start-synapse&quot;&gt;Start Synapse&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl start matrix-synapse
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;verify-our-setup-by-registering-a-new-user&quot;&gt;Verify our Setup by registering a new user&lt;/h3&gt;

&lt;p&gt;Execute the &lt;code class=&quot;highlighter-rouge&quot;&gt;register_new_matrix_user&lt;/code&gt; script to register a new user and validate our Synapse configuration is operational.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://localhost:8008
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;/h3&gt;

&lt;p&gt;If any errors are encountered with the registration of a new user, refer to &lt;code class=&quot;highlighter-rouge&quot;&gt;/var/log/matrix-synapse/homeserver.log&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;systemctl status matrix-synapse&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;journalctl -u matrix-synapse&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;configure-nginx&quot;&gt;Configure NGINX&lt;/h2&gt;

&lt;p&gt;We need to configure three sites, the “default” page, or the &lt;code class=&quot;highlighter-rouge&quot;&gt;example.com&lt;/code&gt; main site, &lt;code class=&quot;highlighter-rouge&quot;&gt;chat.example.com&lt;/code&gt; where we’ll host the Riot Web app, and &lt;code class=&quot;highlighter-rouge&quot;&gt;matrix.example.com&lt;/code&gt; which is where Synapse is running.&lt;/p&gt;

&lt;p&gt;We’ll mimic the Apache method of creating our site configs in &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/nginx/sites-available&lt;/code&gt; and linking them to &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/nginx/sites-enabled/&lt;/code&gt;.  This makes enabling/disabling sites easy for purposes of scaling.&lt;/p&gt;

&lt;h3 id=&quot;setup-sites&quot;&gt;Setup Sites&lt;/h3&gt;

&lt;h4 id=&quot;default---examplecom&quot;&gt;Default - &lt;code class=&quot;highlighter-rouge&quot;&gt;example.com&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;In many cases, this will already be configured and running a site.  We need to be able to serve two files from &lt;code class=&quot;highlighter-rouge&quot;&gt;example.com/.well-known/matrix&lt;/code&gt;, the below config identifies a SIMPLE configuration.  The most important part for the operation of Synapse/Riot is the location&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/a16780803bb9662c7825ce9e5becd8fa.js?file=nginx-default&quot;&gt; &lt;/script&gt;

&lt;h4 id=&quot;riot-web---chatexamplecom&quot;&gt;Riot Web - &lt;code class=&quot;highlighter-rouge&quot;&gt;chat.example.com&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Nothing too fancy here, we’re just serving the static files, all the magic happens in the client.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/a16780803bb9662c7825ce9e5becd8fa.js?file=nginx-chat&quot;&gt; &lt;/script&gt;

&lt;h4 id=&quot;synapse---matrixexamplecom&quot;&gt;Synapse - &lt;code class=&quot;highlighter-rouge&quot;&gt;matrix.example.com&lt;/code&gt;&lt;/h4&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/a16780803bb9662c7825ce9e5becd8fa.js?file=nginx-gist&quot;&gt; &lt;/script&gt;

&lt;h3 id=&quot;create-well-known-files&quot;&gt;Create “well known” files&lt;/h3&gt;

&lt;h4 id=&quot;varwwwhtmlwell-knownmatrixclient&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/var/www/html/.well-known/matrix/client&lt;/code&gt;&lt;/h4&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
    &quot;m.homeserver&quot;: {
        &quot;base_url&quot;: &quot;https://matrix.example.com&quot;
    },
    &quot;m.identity_server&quot;: {
        &quot;base_url&quot;: &quot;https://vector.im&quot;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;varwwwhtmlwell-knownmatrixserver&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/var/www/html/.well-known/matrix/server&lt;/code&gt;&lt;/h4&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{ &quot;m.server&quot;: &quot;matrix.example.com:443&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;restart-nginx&quot;&gt;Restart Nginx&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctrl restart nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;firewall-rules&quot;&gt;Firewall Rules&lt;/h2&gt;

&lt;h3 id=&quot;ufw-setup&quot;&gt;UFW Setup&lt;/h3&gt;

&lt;p&gt;Update &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/services&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# grep turn /etc/services
stun-turn       3478/tcp                        # Coturn
stun-turn       3478/udp                        # Coturn
stun-turn-tls   5349/tcp                        # Coturn
stun-turn-tls   5349/udp                        # Coturn
turnserver-cli  5766/tcp                        # Coturn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Enable UFW&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ufw allow ssh
ufw allow http
ufw allow https
ufw allow stun-turn
ufw allow stun-turn-tls
ufw enable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;digital-ocean-rules&quot;&gt;Digital Ocean Rules&lt;/h3&gt;

&lt;p&gt;This terraform sets up firewall rules to block all communication to the server on 80 and 443 except for traffic from CloudFlare servers.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/a16780803bb9662c7825ce9e5becd8fa.js?file=tf-digital-ocean-rules.tf&quot;&gt; &lt;/script&gt;

&lt;p&gt;N.b. CloudFlare doesn’t proxy TURN traffic, so we recommend running your TURN server on a separate host.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;At this point you should have a running and functional&lt;/p&gt;

&lt;p&gt;Next up, we’ll look at how to automate deploying Synapse, Riot, and Coturn.&lt;/p&gt;</content><author><name></name></author><summary type="html">Configuring Matrix and Riot for Private Chat</summary></entry><entry><title type="html">Configuring GPU Passthrough with VFIO on Fedora 30 notes</title><link href="https://qubitrenegade.com/virtualization/kvm/vfio/2019/07/17/VFIO-Fedora-Notes.html" rel="alternate" type="text/html" title="Configuring GPU Passthrough with VFIO on Fedora 30 notes" /><published>2019-07-17T02:38:21+00:00</published><updated>2019-07-17T02:38:21+00:00</updated><id>https://qubitrenegade.com/virtualization/kvm/vfio/2019/07/17/VFIO-Fedora-Notes</id><content type="html" xml:base="https://qubitrenegade.com/virtualization/kvm/vfio/2019/07/17/VFIO-Fedora-Notes.html">&lt;p&gt;GPU Passthrough is all the rage.  The ArchLinux Wiki does an amazing job explaining all the different ways to setup VFIO/GPU passthrough.  These are my notes for setting up GPU Passthrough in Fedora 30 with two identical cards.  This does not aim to be a comprehensive guide.&lt;/p&gt;

&lt;p&gt;I believe, while untested, this method can be used for setups with a different cards as well.&lt;/p&gt;

&lt;h2 id=&quot;setup-kvm&quot;&gt;Setup KVM&lt;/h2&gt;

&lt;p&gt;Install KVM&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;bridge-utils libvirt virt-install qemu-kvm virt-top libguestfs-tools virt-manager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Configure bridge networking using NetworkManager (this is largely due to laziness when setting the OS up, NM is the default, so I kinda just deal with it…)&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# make up a bridge name, I like br0&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;br0
&lt;span class=&quot;c&quot;&gt;# this will vary depending on the mobo/eth card.  see `ip addr` to find device name&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_INTERFACE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;enp5s0

&lt;span class=&quot;c&quot;&gt;# Get our device UUID&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;BR_INT_OG_UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;nmcli &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; GENERAL.CON-UUID device show &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_INTERFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Create bridge&lt;/span&gt;
nmcli connection add &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;bridge autoconnect &lt;span class=&quot;nb&quot;&gt;yes &lt;/span&gt;con-name &lt;span class=&quot;s2&quot;&gt;&quot;{BR_NAME}&quot;&lt;/span&gt; ifname &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_NAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Disable STP&lt;/span&gt;
nmcli connection modify &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_NAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; bridge.stp no

&lt;span class=&quot;c&quot;&gt;# Add our interface to our bridge&lt;/span&gt;
nmcli connection add &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;bridge-slave autoconnect &lt;span class=&quot;nb&quot;&gt;yes &lt;/span&gt;con-name &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_INTERFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; ifname &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_INTERFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; master &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_NAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Turn off our old interface&lt;/span&gt;
nmcli con down &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_INTERFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Turn on our new bridge&lt;/span&gt;
nmcli con up &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_NAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# delete our old interface config&lt;/span&gt;
nmcli con delete &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BR_INT_OG_UUID&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;update-kernel-cli-parameters&quot;&gt;Update Kernel CLI parameters&lt;/h2&gt;

&lt;p&gt;Append to &lt;code class=&quot;highlighter-rouge&quot;&gt;GRUB_CMDLINE_LINUX&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/default/grub&lt;/code&gt; to enable iommu and load our &lt;code class=&quot;highlighter-rouge&quot;&gt;vfio-pci&lt;/code&gt; driver.  We do this early to ensure &lt;code class=&quot;highlighter-rouge&quot;&gt;vfio&lt;/code&gt; is able to claim the devices before the kernel does.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;GRUB_CMDLINE_LINUX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;amd_iommu=on iommu=pt rd.driver.pre=vfio-pci&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;modprobe-config&quot;&gt;Modprobe Config&lt;/h2&gt;

&lt;p&gt;Create &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/modprobe.d/vfio.conf&lt;/code&gt; to tell modprobe how to load &lt;code class=&quot;highlighter-rouge&quot;&gt;vfio-pci&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;install vfio-pci /sbin/vfio-pci-override.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dracut-config&quot;&gt;Dracut Config&lt;/h2&gt;

&lt;p&gt;Create &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/dracut.conf.d/vfio.conf&lt;/code&gt; to load our drivers and setup script into our initramfs.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;add_drivers+=&quot;vfio vfio_iommu_type1 vfio_pci vfio_virqfd&quot;
install_items+=&quot;/sbin/vfio-pci-override.sh /usr/bin/dirname&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;vga-passthrough-script&quot;&gt;VGA Passthrough Script&lt;/h2&gt;

&lt;p&gt;Create &lt;code class=&quot;highlighter-rouge&quot;&gt;/sbin/vfio-pci-override.sh&lt;/code&gt;, this will passthrough all non-boot VGA devices, including audio and USB controllers if they exist.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/2ff70cc63346a09c2374262e1075564c.js?file=vfio-pci-override.sh&quot;&gt; &lt;/script&gt;

&lt;h2 id=&quot;update-our-boot-system&quot;&gt;Update our boot system&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# update initramfs&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or dracut -f --regenerate-all&lt;/span&gt;
dracut &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--kver&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# update grub&lt;/span&gt;
grub2-mkconfig &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/grub2-efi.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;post-setup-check&quot;&gt;Post setup Check&lt;/h2&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/2ff70cc63346a09c2374262e1075564c.js?file=vfio-setup-check.sh&quot;&gt; &lt;/script&gt;

&lt;p&gt;(this could be improved)&lt;/p&gt;

&lt;h2 id=&quot;failed-to-setup-container-for-group-xx-failed-to-set-iommu-for-container-operation-not-permitted&quot;&gt;“failed to setup container for group XX: failed to set iommu for container: Operation not permitted”&lt;/h2&gt;

&lt;p&gt;Shoutout to &lt;a href=&quot;https://www.reddit.com/r/VFIO/comments/70qneu/threadripper_failed_to_set_iommu_for_container/dn62wyj/?context=2&quot;&gt;/u/degerdem and /u/WiFivomFranman&lt;/a&gt; for identifying that you need to go into the BIOS&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Advanced -&amp;gt; AMD PBS
** Enumerate all IOMMU in IVRS = Enabled&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;nvidia-geforce-card-reports-error-43-in-guest-os&quot;&gt;Nvidia GeForce Card reports Error 43 in Guest OS&lt;/h2&gt;

&lt;p&gt;In the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;features&amp;gt;&amp;lt;/features&amp;gt;&lt;/code&gt; stanza,  add `  &lt;vendor_id state=&quot;on&quot; value=&quot;10DE&quot;&gt;&lt;/vendor_id&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt; to the &lt;/code&gt;hyperv&lt;code class=&quot;highlighter-rouge&quot;&gt; block and &lt;/code&gt;hidden state=on`.&lt;/p&gt;

&lt;p&gt;Before:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &amp;lt;features&amp;gt;
    &amp;lt;acpi/&amp;gt;
    &amp;lt;apic/&amp;gt;
    &amp;lt;hyperv&amp;gt;
      &amp;lt;relaxed state='on'/&amp;gt;
      &amp;lt;vapic state='on'/&amp;gt;
      &amp;lt;spinlocks state='on' retries='8191'/&amp;gt;
    &amp;lt;/hyperv&amp;gt;
    &amp;lt;vmport state='off'/&amp;gt;
  &amp;lt;/features&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &amp;lt;features&amp;gt;
    &amp;lt;acpi/&amp;gt;
    &amp;lt;apic/&amp;gt;
    &amp;lt;hyperv&amp;gt;
      &amp;lt;relaxed state='on'/&amp;gt;
      &amp;lt;vapic state='on'/&amp;gt;
      &amp;lt;spinlocks state='on' retries='8191'/&amp;gt;
      &amp;lt;vendor_id state='on' value='10DE'/&amp;gt;
    &amp;lt;/hyperv&amp;gt;
    &amp;lt;kvm&amp;gt;
      &amp;lt;hidden state='on'/&amp;gt;
    &amp;lt;/kvm&amp;gt;
    &amp;lt;vmport state='off'/&amp;gt;
  &amp;lt;/features&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;links&quot;&gt;Links&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cyberciti.biz/faq/how-to-add-network-bridge-with-nmcli-networkmanager-on-linux/&quot;&gt;Cybercity &lt;code class=&quot;highlighter-rouge&quot;&gt;nmcli&lt;/code&gt; guide&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF&quot;&gt;Arch Linux VFIO Wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://vfio.blogspot.com/2015/05/vfio-gpu-how-to-series-part-3-host.html&quot;&gt;VFIO Blogspot&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://forum.level1techs.com/t/play-games-in-windows-on-linux-pci-passthrough-quick-guide/108981&quot;&gt;Level1Techs “Play games in Windows on Linux!”&lt;/a&gt;, however, they are mistaken you need different GPUs.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/qubitrenegade/2ff70cc63346a09c2374262e1075564c&quot;&gt;script gist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">GPU Passthrough is all the rage. The ArchLinux Wiki does an amazing job explaining all the different ways to setup VFIO/GPU passthrough. These are my notes for setting up GPU Passthrough in Fedora 30 with two identical cards. This does not aim to be a comprehensive guide.</summary></entry><entry><title type="html">HabiChef: Pt2 Applying Change</title><link href="https://qubitrenegade.com/habitat/chef/habichef/2019/04/28/Habichef-Pt2-Applying-Change.html" rel="alternate" type="text/html" title="HabiChef: Pt2 Applying Change" /><published>2019-04-28T22:29:47+00:00</published><updated>2019-04-28T22:29:47+00:00</updated><id>https://qubitrenegade.com/habitat/chef/habichef/2019/04/28/Habichef-Pt2-Applying-Change</id><content type="html" xml:base="https://qubitrenegade.com/habitat/chef/habichef/2019/04/28/Habichef-Pt2-Applying-Change.html">&lt;p&gt;In our &lt;a href=&quot;https://qubitrenegade.com/habitat/chef/habichef/2019/04/28/Habichef-Packaging-Chef-for-easy-consumption.html&quot;&gt;last post&lt;/a&gt; we discussed how to package our Chef Cookbooks in a Habitat package using Policyfiles.  We showed that we could package all of our cookbooks into a single, easily distributable, package.&lt;/p&gt;

&lt;p&gt;We were even able to set node attributes via the Policyfile enabling us to create Policyfile specific settings.  However, we don’t want to manage a dozen different versions of the resolver package since the only thing that changes is node attributes.&lt;/p&gt;

&lt;p&gt;For instance, all of our servers use the same DNS server but will have a different domain based on the data center they live in.  We’ll use &lt;code class=&quot;highlighter-rouge&quot;&gt;qubitrenegade.com&lt;/code&gt;, so suppose we have &lt;code class=&quot;highlighter-rouge&quot;&gt;us-east-1.qubitrenegade.com&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;us-west-1.qubitreengade.com&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;First, let’s update our base policy file.  Let’s add a &lt;code class=&quot;highlighter-rouge&quot;&gt;domain&lt;/code&gt; attribute to our &lt;code class=&quot;highlighter-rouge&quot;&gt;default&lt;/code&gt; settings.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/policyfiles/base.rb
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/policyfiles/base.rb
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -4,7 +4,10 @@&lt;/span&gt; name 'base'
 default_source :supermarket

 # Environment Attributes
&lt;span class=&quot;gd&quot;&gt;-default['resolver']['nameservers'] = ['1.1.1.1']
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+default['resolver'] = {
+  'domain' = 'qubitrenegade.com',
+  'nameservers' = ['1.1.1.1'],
+}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;multiple-policyfiles&quot;&gt;Multiple Policyfiles&lt;/h2&gt;

&lt;p&gt;Since policy files include other policy files, we could create a new policy for each environment.&lt;/p&gt;

&lt;p&gt;First, let’s update our Habitat &lt;code class=&quot;highlighter-rouge&quot;&gt;plan.sh&lt;/code&gt; to include the policy name in the name of our package.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/habitat/plan.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/habitat/plan.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -1,6 +1,11 @@&lt;/span&gt;
 # habichef_demo/habitat/plan.sh
&lt;span class=&quot;gd&quot;&gt;-scaffold_policy_name=&quot;base&quot;
-pkg_name=&quot;habichef_demo&quot;
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+if [ -z ${CHEF_POLICYFILE+x} ]; then
+  policy_name=&quot;base&quot;
+else
+  policy_name=&quot;${CHEF_POLICYFILE}&quot;
+fi
+
+pkg_name=&quot;habichef_demo-${policy_name}&quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, let’s create a Policyfile for &lt;code class=&quot;highlighter-rouge&quot;&gt;us-east-1&lt;/code&gt; that includes our base Policyfile.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# habichef_demo/policyfiles/us-east-1.rb
name 'us-east-1'

include_policy 'base'

default['resolver']['domain'] = 'us-east-1.qubitrenegade.com'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then we can build our project, using the same process as before.  (If you’re receiving errors, you can check out the &lt;code class=&quot;highlighter-rouge&quot;&gt;2019-04-28-pt1-multiple-policy-files&lt;/code&gt; branch of the &lt;a href=&quot;https://github.com/qubitrenegade/habichef_demo/tree/2019-04-28-pt1-multiple-policy-files&quot;&gt;HabiChef Demo repo&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;hab studio enter

... snip ...

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1][default:/src:0]# build
... snip ...

  habichef_demo-base: Installed Path: /hab/pkgs/qbrd/habichef_demo-base/0.1.0/20190428185221
   habichef_demo-base: Artifact: /src/results/qbrd-habichef_demo-base-0.1.0-20190428185221-x86_64-linux.hart
   habichef_demo-base: Build Report: /src/results/last_build.env
   habichef_demo-base: SHA256 Checksum: 4a126ec5c47dba1643ef767c7ccc02acd36ea780d2f88110db9c964c4598c2b9
   habichef_demo-base: Blake2b Checksum: 7fc45fcf07bebe57f90301c0c83df6700f772fc8925ec0162b1efbfa85b89b6a
   habichef_demo-base:
   habichef_demo-base: I love it when a plan.sh comes together.
   habichef_demo-base:
   habichef_demo-base: Build &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;: 0m5s
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2][default:/src:0]#
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, note that the name of our package is &lt;code class=&quot;highlighter-rouge&quot;&gt;habichef_demo-base&lt;/code&gt;.  We need to set `
CHEF_POLICYFILE` environment variable to build the correct package.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[2][default:/src:0]# CHEF_POLICYFILE=us-east-1 build
... snip ...
Building policy us-east-1
Error: Failed to generate Policyfile.lock
Reason: (ChefDK::LocalPolicyfileLockNotFound) The provided path ./base.lock.json does not exist.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Well, it seems that something is blowing away the &lt;code class=&quot;highlighter-rouge&quot;&gt;base.lock.json&lt;/code&gt; file…  This probably needs follow up with the Habitat team.&lt;/p&gt;

&lt;p&gt;UPDATE: &lt;a href=&quot;https://github.com/habitat-sh/core-plans/issues/2536&quot;&gt;#2536&lt;/a&gt; indicates I may have misunderstood the usage pattern.&lt;/p&gt;

&lt;p&gt;Regardless, this example starts to break down as you start to deploy to more environments as you have effectively the same package being generated with minor changes.&lt;/p&gt;

&lt;h2 id=&quot;usertoml-config-changes&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;user.toml&lt;/code&gt; Config Changes&lt;/h2&gt;

&lt;p&gt;Let’s continue working with &lt;code class=&quot;highlighter-rouge&quot;&gt;habichef_demo&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;If you’ve been following along, we’ll want to explicitly set our &lt;code class=&quot;highlighter-rouge&quot;&gt;scaffold_policy_name=&quot;base&quot;&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/habitat/plan.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/habitat/plan.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -5,8 +5,8 @@&lt;/span&gt; else
   policy_name=&quot;${CHEF_POLICYFILE}&quot;
 fi

-scaffold_policy_name=&quot;${policy_name}&quot;
&lt;span class=&quot;gd&quot;&gt;-pkg_name=&quot;habichef_demo-${policy_name}&quot;
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+scaffold_policy_name=&quot;base&quot;
+pkg_name=&quot;habichef_demo&quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(You can also remove the conditional statement, or just check out the &lt;code class=&quot;highlighter-rouge&quot;&gt;2019-04-28-pt2-user.toml&lt;/code&gt; branch)&lt;/p&gt;

&lt;p&gt;Next, let’s create our &lt;code class=&quot;highlighter-rouge&quot;&gt;user.toml&lt;/code&gt; file.  Habitat will load user config settings from &lt;code class=&quot;highlighter-rouge&quot;&gt;/hab/user/&amp;lt;service name&amp;gt;/config/user.toml&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[15][default:/src:130]# mkdir -p /hab/user/habichef_demo/config/
[16][default:/src:0]# printf '[attributes]\n  [attributes.resolver]\n    domain = &quot;us-east-1.qubitrenegade.com&quot;\n' | tee /hab/user/habichef_demo/config/user.toml
[attributes]
  [attributes.resolver]
    domain = &quot;us-east-1.qubitrenegade.com&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then we’ll build and run the package.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ hab studio enter
... snip ...
[1][default:/src:0]# build
... snip ...
   habichef_demo: Installed Path: /hab/pkgs/qbrd/habichef_demo/0.1.0/20190428192425
   habichef_demo: Artifact: /src/results/qbrd-habichef_demo-0.1.0-20190428192425-x86_64-linux.hart
   habichef_demo: Build Report: /src/results/last_build.env
   habichef_demo: SHA256 Checksum: b0016e36ae76f77e876e27681219eae415eb84ef5801813d83fbd56c46163099
   habichef_demo: Blake2b Checksum: 1be21e1176536917f28b50f3b2856acdc7ad51116009c8aee23ef7bb48708880
   habichef_demo:
   habichef_demo: I love it when a plan.sh comes together.
   habichef_demo:
   habichef_demo: Build time: 0m7s
[2][default:/src:0]# source results/last_build.env
[3][default:/src:0]# hab svc load $pkg_ident
[4][default:/src:0]# sup-log
... snip ...
habichef_demo.default(O):     +# This file is generated by Chef
habichef_demo.default(O):     +# Do not edit, changes will be overwritten
habichef_demo.default(O):     +#
habichef_demo.default(O):     +domain us-east-1.qubitrenegade.com
habichef_demo.default(O):     +nameserver 1.1.1.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, you can set per-instance settings via &lt;code class=&quot;highlighter-rouge&quot;&gt;user.toml&lt;/code&gt;.  Typically this is populated by a third-party tool such as Chef (though in the case of HabiChef, is it the chicken or the egg?), or Terraform.  Terraform is particularly useful when coupled with the Habitat provisioner.&lt;/p&gt;

&lt;h2 id=&quot;running-config-changes&quot;&gt;Running config changes&lt;/h2&gt;

&lt;p&gt;We’ve been running HabiChef for a few weeks now and have several nodes deployed (possibly even with a bastion ring, but that is a topic for another day). A mandate comes down from management that we need to change all of the domains.  Sure, we could log into every node and update the &lt;code class=&quot;highlighter-rouge&quot;&gt;user.toml&lt;/code&gt; file… but that seems like a lot of work and rather error prone.&lt;/p&gt;

&lt;p&gt;Fortunately, Habitat provides a method for applying config changes to a running cluster.&lt;/p&gt;

&lt;p&gt;First, let’s create a temporary &lt;code class=&quot;highlighter-rouge&quot;&gt;.toml&lt;/code&gt; file.  (There is an example file in the &lt;code class=&quot;highlighter-rouge&quot;&gt;habichef_demo/habitat&lt;/code&gt; directory)&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /tmp/config-demo.toml
[attributes]
  [attributes.resolver]
    domain = &quot;example.local&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then we can apply it with:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hab config apply &amp;lt;SERVICE_GROUP&amp;gt; &amp;lt;VERSION_NUMBER&amp;gt; &amp;lt;FILE&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ll use a timestamp generated with &lt;code class=&quot;highlighter-rouge&quot;&gt;$(date +%s)&lt;/code&gt; as the version number.  This way when we apply the update again we don’t have to modify the command.&lt;/p&gt;

&lt;p&gt;Our command should look something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hab config apply habichef_demo.default $(date +%s) habitat/config-apply-demo.toml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And we should see something to the effect of:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[2][default:/src:0]# hab config apply habichef_demo.default $(date +%s) habitat/config-apply-demo.toml &amp;amp;&amp;amp; sup-log

... snip ...

hab-sup(CMD): Setting new configuration version 1556489698 for habichef_demo.default
habichef_demo.default(CF): Modified configuration file /hab/svc/habichef_demo/config/attributes.json

... snip ...

habichef_demo.default(O):   * template[/etc/resolv.conf] action create
habichef_demo.default(O):     - update content in file /etc/resolv.conf from 217c99 to 19c14a
habichef_demo.default(O):     --- /etc/resolv.conf      2019-04-28 19:44:54.719939924 +0000
habichef_demo.default(O):     +++ /etc/.chef-resolv20190428-32280-15wxpjo.conf  2019-04-28 22:15:11.311781489 +0000
habichef_demo.default(O):     @@ -2,7 +2,7 @@
habichef_demo.default(O):      # This file is generated by Chef
habichef_demo.default(O):      # Do not edit, changes will be overwritten
habichef_demo.default(O):      #
habichef_demo.default(O):     -domain asdf.com
habichef_demo.default(O):     +domain example.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Success!  Typically these changes would be applied to a cluster, and the update propagated through the cluster via Habitat’s inbuilt gossip layer.  So if you’re thinking this is a lot of work to change the domain in the &lt;code class=&quot;highlighter-rouge&quot;&gt;resolv.conf&lt;/code&gt; file, you’re not wrong.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Today we’ve seen three different ways (well, two and a half) to apply changes to HabiChef cookbooks.  Big picture, you’d probably want to manage these via some form of CI pipeline, and discourage users from manually &lt;code class=&quot;highlighter-rouge&quot;&gt;hab config apply&lt;/code&gt;ing changes.  Hopefully the gravity of being able to apply config changes to a cluster will become more apparent in the “Habitat: PtX Running at Scale”.&lt;/p&gt;

&lt;p&gt;Tune in next time when we discuss the internals of &lt;code class=&quot;highlighter-rouge&quot;&gt;scaffolding-chef&lt;/code&gt; and how to include local cookbooks.&lt;/p&gt;</content><author><name></name></author><summary type="html">In our last post we discussed how to package our Chef Cookbooks in a Habitat package using Policyfiles. We showed that we could package all of our cookbooks into a single, easily distributable, package.</summary></entry><entry><title type="html">HabiChef: Packaging Chef for easy consumption</title><link href="https://qubitrenegade.com/habitat/chef/habichef/2019/04/28/Habichef-Packaging-Chef-for-easy-consumption.html" rel="alternate" type="text/html" title="HabiChef: Packaging Chef for easy consumption" /><published>2019-04-28T04:29:47+00:00</published><updated>2019-04-28T04:29:47+00:00</updated><id>https://qubitrenegade.com/habitat/chef/habichef/2019/04/28/Habichef-Packaging-Chef-for-easy-consumption</id><content type="html" xml:base="https://qubitrenegade.com/habitat/chef/habichef/2019/04/28/Habichef-Packaging-Chef-for-easy-consumption.html">&lt;p&gt;Dependencies are hard.  There are many different strategies to attempt to solve this problem.&lt;/p&gt;

&lt;h2 id=&quot;policyfiles&quot;&gt;Policyfiles&lt;/h2&gt;

&lt;p&gt;Chef Environments have issues.  They’re unversioned meaning they require an external process of managing version.  Once your environments get to a certain size, it can be a daunting task to update them.  Unless you are explicitly pinning the cookbook versions of every cookbook in your environment, you also expose yourself to risk when pushing changes to cookbooks.  In an environment where there may exist multiple Chef Servers that aren’t all managed by the same team/process, communicating the updated version pinnings can also be a pain point.&lt;/p&gt;

&lt;p&gt;Policy files are effectively an attempt to version environments and cookbook version pinnings while providing a simplified user interface.  This promotes safer workflows as new cookbooks published to the Chef Server won’t be immediately consumed by all nodes, similar to managing version pinnings via environment.&lt;/p&gt;

&lt;h2 id=&quot;habitat&quot;&gt;Habitat&lt;/h2&gt;

&lt;p&gt;Habitat automates applications by bundling the application–typically compiling from source, configuration, and logic to manage the configuration–including configuration updates–together.  However, not all applications lend themselves to being neatly packaged.  We all have those monolithic, CotS, prepackaged from the vendor, applications.&lt;/p&gt;

&lt;p&gt;For those cases where our application can’t be built from source, or doesn’t lend itself to easily being packaged up: enter HabiChef.  With HabiChef we’re bundling our standard set of Chef tools, which is the desired state of the system, in an easily distributable and manageable artifact.&lt;/p&gt;

&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;

&lt;p&gt;Let’s try an example.&lt;/p&gt;

&lt;p&gt;Currently, there isn’t a generator, so we’re going to go at it by hand.  There’s a skeleton project linked later on that you’ll be able to clone and use.&lt;/p&gt;

&lt;h3 id=&quot;skeleton-file-structure&quot;&gt;Skeleton File Structure&lt;/h3&gt;

&lt;p&gt;First we’ll create our skeleton file structure.  Minimally we’ll need a directory for our: project, policy files, and habitat plan.  In this example we’ll also write our own cookbook, but the cookbook directory is optional.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; habichef_demo/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;cookbooks,habitat,policyfiles&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'results\n.kitchen\n'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;habitat-plan&quot;&gt;Habitat Plan&lt;/h3&gt;

&lt;p&gt;Next we’ll create the Habitat &lt;code class=&quot;highlighter-rouge&quot;&gt;plan.sh&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;default.toml&lt;/code&gt; files.  We’re going to assume we’re not reporting to Automate for the purposes of this demo, refer to the project linked at the end for those configuration options.&lt;/p&gt;

&lt;h4 id=&quot;plansh&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;plan.sh&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;plan.sh&lt;/code&gt; is the brains of the operation.  This describes how to package and run our application.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# habichef_demo/habitat/plan.sh&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scaffold_policy_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;base&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;habichef_demo&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_origin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;qbrd&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0.1.0&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_maintainer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;QubitRenegade&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;The Chef &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$scaffold_policy_name&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; Policy&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_upstream_url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://chef.io&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_scaffolding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;core/scaffolding-chef&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_svc_user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkg_svc_group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ve discussed Habitat plans in the past so we won’t delve too much into detail here.  What’s interesting to note is that we’ve eschewed any of our standard hooks for leveraging this &lt;code class=&quot;highlighter-rouge&quot;&gt;core/scaffolding-chef&lt;/code&gt; scaffolding.  This manages the &lt;code class=&quot;highlighter-rouge&quot;&gt;chef-client&lt;/code&gt; in the same way as any other Habitat managed service (hooks etc.).&lt;/p&gt;

&lt;h4 id=&quot;defauttoml&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;defaut.toml&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;default.toml&lt;/code&gt; sets up default options for our Chef Client as a Service.  We need to set a few options here otherwise our scaffolding will fail with some less than obvious errors.&lt;/p&gt;

&lt;div class=&quot;language-toml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# habichef_demo/habitat/default.toml&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;log_level&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;warn&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# All times are in seconds&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1800&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;splay&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;300&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;splay_first_run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;run_lock_timeout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;30&quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[data_collector]&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These are fairly standard chef-client options.  Refer to the &lt;a href=&quot;https://docs.chef.io/ctl_chef_client.html&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;chef-client&lt;/code&gt;&lt;/a&gt; documentation for full explanation of the remaining options.&lt;/p&gt;

&lt;h3 id=&quot;policyfile&quot;&gt;Policyfile&lt;/h3&gt;

&lt;p&gt;Next we’ll create a basic policy file.  We’ll modify this later, but for now, we want to include a cookbook from the Supermarket.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# policyfiles/base.rb&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'base'&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Where to find external cookbooks:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;default_source&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:supermarket&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Environment Attributes&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'resolver'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'nameservers'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'1.1.1.1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Your Run List&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;run_list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'resolver::default'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;building-our-package&quot;&gt;Building Our Package&lt;/h2&gt;

&lt;p&gt;Now it’s time to build our project!&lt;/p&gt;

&lt;p&gt;If you haven’t already, change into your habichef_demo directory. i.e.: assuming it’s in your home dir:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/habichef_demo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you’re building from a CI tool, you likely want to build your package directly with &lt;code class=&quot;highlighter-rouge&quot;&gt;hab pkg build .&lt;/code&gt; or similar.&lt;/p&gt;

&lt;h3 id=&quot;habitat-studio&quot;&gt;Habitat Studio&lt;/h3&gt;

&lt;p&gt;However, Habitat comes with a handy chroot environment.  We can enter this cleanroom build environment, then build and test the package there.&lt;/p&gt;

&lt;p&gt;Let’s enter the studio with &lt;code class=&quot;highlighter-rouge&quot;&gt;hab studio enter&lt;/code&gt;, you’ll see a lot of output, and it should drop you into a shell.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ hab studio enter
[sudo hab-studio] password for qubitrenegade:
   hab-studio: Creating Studio at /hab/studios/home--qubitrenegade--habichef_demo (default)

... snip ...

   hab-studio: Entering Studio at /hab/studios/home--qubitrenegade--habichef_demo (default)
   hab-studio: Exported: HAB_ORIGIN=qbrd

--&amp;gt; Launching the Habitat Supervisor in the background...
    Running: hab sup run
    * Use 'hab svc start' &amp;amp; 'hab svc stop' to start and stop services
    * Use 'sup-log' to tail the Supervisor's output (Ctrl+c to stop)
    * Use 'sup-term' to terminate the Supervisor
    * To pass custom arguments to run the Supervisor, export
      'HAB_STUDIO_SUP' with the arguments before running
      'hab studio enter'.

--&amp;gt; To prevent a Supervisor from running automatically in your
    Studio, export 'HAB_STUDIO_SUP=false' before running
    'hab studio enter'.

[1][default:/src:0]#
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;build-our-package&quot;&gt;Build our Package&lt;/h3&gt;

&lt;p&gt;As we said above, from outside of the studio we can execute &lt;code class=&quot;highlighter-rouge&quot;&gt;hab pkg build .&lt;/code&gt; to build our package.  Without any flags this will destroy any existing studios, spawn a new one, and build our package in the new studio.  However, since we are now in the Habitat Studio and therefore in a &lt;code class=&quot;highlighter-rouge&quot;&gt;chroot&lt;/code&gt; environment, we can’t run &lt;code class=&quot;highlighter-rouge&quot;&gt;hab pkg build .&lt;/code&gt; as this will attempt to spawn a &lt;code class=&quot;highlighter-rouge&quot;&gt;chroot&lt;/code&gt; jail inside a &lt;code class=&quot;highlighter-rouge&quot;&gt;chroot&lt;/code&gt; jail.&lt;/p&gt;

&lt;p&gt;From within our studio we need to issue the &lt;code class=&quot;highlighter-rouge&quot;&gt;build&lt;/code&gt; command.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[1][default:/src:0]# build
   : Loading /src/habitat/plan.sh
   habichef_demo: Plan loaded
   habichef_demo: Validating plan metadata
   habichef_demo: Using HAB_BIN=/hab/pkgs/core/hab/0.79.1/20190410220617/bin/hab for installs, signing, and hashing
   habichef_demo: hab-plan-build setup
   habichef_demo: Writing pre_build file
   habichef_demo: Resolving scaffolding dependencies
» Installing core/scaffolding-chef

... snip ...

   habichef_demo: Installing /src/habitat/../policyfiles/base.rb
Building policy base
Expanded run list: recipe[resolver::default]
Caching Cookbooks...
Installing resolver 2.1.0

Lockfile written to /src/policyfiles/base.lock.json
Policy revision id: eb77ea2f4542b34427531c139129bd1bc026c57b12733c53442e2af1f5340293

... snip ...

   habichef_demo: hab-plan-build cleanup
   habichef_demo:
   habichef_demo: Source Path: /src
   habichef_demo: Installed Path: /hab/pkgs/qbrd/habichef_demo/0.1.0/20190428033409
   habichef_demo: Artifact: /src/results/qbrd-habichef_demo-0.1.0-20190428033409-x86_64-linux.hart
   habichef_demo: Build Report: /src/results/last_build.env
   habichef_demo: SHA256 Checksum: 1cacfcb1f90f9a162331fb85376a16e578bc9a6740e1eecbd3d2e78639fea111
   habichef_demo: Blake2b Checksum: 5e35d5950dc75e35ea7eb43f3a4e8745c6ac3c4cf350e51221bdbc0b546632b8
   habichef_demo:
   habichef_demo: I love it when a plan.sh comes together.
   habichef_demo:
   habichef_demo: Build time: 0m51s
[2][default:/src:0]#
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Congrats!  You now have your first Habitat bundled Chef cookbook!&lt;/p&gt;

&lt;p&gt;If we &lt;code class=&quot;highlighter-rouge&quot;&gt;ls&lt;/code&gt; the &lt;code class=&quot;highlighter-rouge&quot;&gt;results/&lt;/code&gt; directory, you should see a &lt;code class=&quot;highlighter-rouge&quot;&gt;.hart&lt;/code&gt; artifact and a &lt;code class=&quot;highlighter-rouge&quot;&gt;last_build.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;last_build.env&lt;/code&gt; file contains information about the last build.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pkg_origin=qbrd
pkg_name=habichef_demo
pkg_version=0.1.0
pkg_release=20190428033409
pkg_target=x86_64-linux
pkg_ident=qbrd/habichef_demo/0.1.0/20190428033409
pkg_artifact=qbrd-habichef_demo-0.1.0-20190428033409-x86_64-linux.hart
pkg_sha256sum=1cacfcb1f90f9a162331fb85376a16e578bc9a6740e1eecbd3d2e78639fea111
pkg_blake2bsum=5e35d5950dc75e35ea7eb43f3a4e8745c6ac3c4cf350e51221bdbc0b546632b8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This means that we can source the file to export these variables to our environment.&lt;/p&gt;

&lt;p&gt;Next, let’s run it!&lt;/p&gt;

&lt;h3 id=&quot;running-our-package-in-habitat-studio&quot;&gt;Running our package in Habitat Studio&lt;/h3&gt;

&lt;p&gt;To make things easier, first, let’s source our &lt;code class=&quot;highlighter-rouge&quot;&gt;last_build.env&lt;/code&gt; file.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[4][default:/src:0]# source results/last_build.env
[5][default:/src:0]# echo $pkg_ident
qbrd/habichef_demo/0.1.0/20190428031740
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now that we have our environment variables loaded, we can run our package.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[6][default:/src:0]# hab svc load $pkg_ident
The qbrd/habichef_demo/0.1.0/20190428033409 service was successfully loaded
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then we’ll start our package:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[7][default:/src:0]# hab svc start $pkg_ident
Supervisor starting qbrd/habichef_demo/0.1.0/20190428033409. See the Supervisor output for more details.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can see our service is running with &lt;code class=&quot;highlighter-rouge&quot;&gt;hab svc status&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hab&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;package&lt;/span&gt;                                  &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;desired&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;elapsed&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;pid&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;qbrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;habichef_demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0.1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;20190428033409&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;standalone&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;up&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;up&lt;/span&gt;     &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;            &lt;span class=&quot;m&quot;&gt;1918&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;habichef_demo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we view our log, with either &lt;code class=&quot;highlighter-rouge&quot;&gt;sup-log&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;less -R /hab/sup/default/sup.log&lt;/code&gt;, we should see the update to the &lt;code class=&quot;highlighter-rouge&quot;&gt;resolv.conf&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[9][default:/src:0]# sup-log
--&amp;gt; Tailing the Habitat Supervisor's output (use 'Ctrl+c' to stop)
habichef_demo.default(SR): Initializing
habichef_demo.default(SV): Starting service as user=root, group=root
habichef_demo.default(O): Starting Chef Client, version 14.12.9
habichef_demo.default(O): Using policy 'base' at revision 'eb77ea2f4542b34427531c139129bd1bc026c57b12733c53442e2af1f5340293'
habichef_demo.default(O): resolving cookbooks for run list: [&quot;resolver::default@2.1.0 (6bbbd0f)&quot;]
habichef_demo.default(O): Synchronizing Cookbooks:
habichef_demo.default(O):   - resolver (2.1.0)
habichef_demo.default(O): Installing Cookbook Gems:
habichef_demo.default(O): Compiling Cookbooks...
habichef_demo.default(O): Converging 1 resources
habichef_demo.default(O): Recipe: resolver::default
habichef_demo.default(O):   * template[/etc/resolv.conf] action create
habichef_demo.default(O):     - update content in file /etc/resolv.conf from 14236b to 82a27b
habichef_demo.default(O):     --- /etc/resolv.conf      2019-04-28 03:41:22.037991908 +0000
habichef_demo.default(O):     +++ /etc/.chef-resolv20190428-1929-1o2aqzr.conf   2019-04-28 03:41:27.218028370 +0000
habichef_demo.default(O):     @@ -1,5 +1,7 @@
habichef_demo.default(O):     -# Generated by NetworkManager
habichef_demo.default(O):     -nameserver 1.0.0.1
habichef_demo.default(O):     -nameserver 8.8.8.8
habichef_demo.default(O):     +#
habichef_demo.default(O):     +# This file is generated by Chef
habichef_demo.default(O):     +# Do not edit, changes will be overwritten
habichef_demo.default(O):     +#
habichef_demo.default(O):     +search
habichef_demo.default(O):     +nameserver 1.1.1.1
habichef_demo.default(O):
habichef_demo.default(O): Running handlers:
habichef_demo.default(O): Running handlers complete
habichef_demo.default(O): Chef Client finished, 1/1 resources updated in 01 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Today we’ve seen how we can bundle our Chef cookbooks using policy files to set the environment and run list.  The &lt;a href=&quot;https://github.com/qubitrenegade/habichef-skeleton&quot;&gt;habichef-skeleton&lt;/a&gt; repo contains the basic skeleton we’ve outlined here.  The &lt;a href=&quot;https://github.com/qubitrenegade/habichef_demo&quot;&gt;habichef_demo&lt;/a&gt; contains the project we’ve built here, there is a 2019-04-27 branch and tag.  You can also download and run the &lt;a href=&quot;https://bldr.habitat.sh/#/pkgs/qbrd/habichef_demo/latest&quot;&gt;Habitat package&lt;/a&gt; with a &lt;code class=&quot;highlighter-rouge&quot;&gt;hab pkg install qbrd/habichef_demo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tune in next time when we demonstrate adding local cookbooks and applying changes to running environments.&lt;/p&gt;</content><author><name></name></author><summary type="html">Dependencies are hard. There are many different strategies to attempt to solve this problem.</summary></entry><entry><title type="html">Habitat and Consul: Client Mode and Registering Services</title><link href="https://qubitrenegade.com/habitat/consul/docker/2018/06/06/Habitat-and-Consul-client-mode.html" rel="alternate" type="text/html" title="Habitat and Consul: Client Mode and Registering Services" /><published>2018-06-06T06:29:47+00:00</published><updated>2018-06-06T06:29:47+00:00</updated><id>https://qubitrenegade.com/habitat/consul/docker/2018/06/06/Habitat-and-Consul-client-mode</id><content type="html" xml:base="https://qubitrenegade.com/habitat/consul/docker/2018/06/06/Habitat-and-Consul-client-mode.html">&lt;h2 id=&quot;previously-on-as-the-qubitrenegade-turns&quot;&gt;Previously on “As the QubitRenegade turns…”&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.consul.io&quot;&gt;Consul&lt;/a&gt; an OpenSource(ish, there’s an enterprise version that has some awesome features) Distributed, Highly Available, Service Discovery, Health Checking, KV Store, that provides federated Multi Datacenter support.  (disclaimer: I am in absolutely no way, shape, or form associated with HashiCorp.  All opinions are my own and not influenced by schwag.  I just happen to think they make a pretty swell product… even if it is written in go ;) )&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.habitat.sh/learn/&quot;&gt;Habitat&lt;/a&gt; an OpenSource, Artifact Builder, Artifact and Service Manager, Docker/Kubernetes/Serverless Enabler, sane Docker container builder system, with Distributed Service Discovery and “build once run anywhere (no really)” mentality.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; is how most people do containers. Just… I’ll post the opinion piece soon.  Docker is fine.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.habitat.sh/docs/install-habitat/&quot;&gt;Habitat&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/install/&quot;&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;high-level-overview&quot;&gt;High level Overview&lt;/h2&gt;

&lt;p&gt;In the last installment, we exported a Core habitat package to a Docker container, then started several instances to build a cluster leveraging Habitat’s service discovery.  To follow along you don’t necessarily need all five servers, a single node running in dev mode would be sufficient.  We’ll proceed as though you have a full cluster to work with.&lt;/p&gt;

&lt;p&gt;Today we’ll explore running Consul in “client” mode.&lt;/p&gt;

&lt;h2 id=&quot;justification&quot;&gt;Justification&lt;/h2&gt;

&lt;p&gt;Initially, I wanted to have the ability to run &lt;code class=&quot;highlighter-rouge&quot;&gt;core/consul&lt;/code&gt; in either “Client” or “Server” mode.  The primary difference is that Consul “Servers” participate in gossip and present a Web UI.  Technically the client could present a Web UI.  When running other services (Vault, Nomad, etc. which we’ll touch on in a later post), HashiCorp recommends running Consul in client mode locally and not allowing the tools to communicate directly with the consul server.&lt;/p&gt;

&lt;p&gt;When discussing Consul, we speak about “Server” and “Client” mode; even though it’s the same binary run with different CLI parameters, “client” and “server” makes a natural demarcation which lends itself to the segregation of packages.&lt;/p&gt;

&lt;h2 id=&quot;security&quot;&gt;Security&lt;/h2&gt;

&lt;p&gt;It’s worth noting that Habitat and Consul both have methods of encrypting communication.  For the time being this guide is putting that aside, with a note that we will cover it eventually.&lt;/p&gt;

&lt;h2 id=&quot;building-consul-client&quot;&gt;Building Consul Client&lt;/h2&gt;

&lt;p&gt;The Habitat plan source can be found &lt;a href=&quot;https://github.com/qubitrenegade/habitat-consul-client&quot;&gt;on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to just run it, skip to Exporting Consul Client below.&lt;/p&gt;

&lt;h3 id=&quot;service-config-files&quot;&gt;Service Config Files&lt;/h3&gt;

&lt;p&gt;To enable what is essentially “arbitrary” configuration files, we can use the &lt;code class=&quot;highlighter-rouge&quot;&gt;toJson&lt;/code&gt; helper method to turn the &lt;code class=&quot;highlighter-rouge&quot;&gt;default.toml&lt;/code&gt;/&lt;code class=&quot;highlighter-rouge&quot;&gt;user.toml&lt;/code&gt; config into JSON structures.  As Handlebars is fairly limited, there is no “else if” clause, we generate correct JSON and allow Consul to complain about the configuration file.&lt;/p&gt;

&lt;div class=&quot;language-handlebars highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &lt;span class=&quot;k&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cfg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;}}&lt;/span&gt;
    &quot;service&quot;: &lt;span class=&quot;k&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;toJson&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cfg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}}{{#if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cfg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}}&lt;/span&gt;,&lt;span class=&quot;k&quot;&gt;{{/if}}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;}}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cfg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}}&lt;/span&gt;
    &quot;services&quot;: &lt;span class=&quot;k&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;toJson&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cfg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;}}&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will allow a minimal configuration such as:&lt;/p&gt;

&lt;div class=&quot;language-haml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[service]
name = &quot;foo&quot;
[service.checks]
interval = &quot;1s&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which will generate the JSON:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;service&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;checks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;interval&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1s&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(just not pretty formatted)&lt;/p&gt;

&lt;h2 id=&quot;exporting-consul-client&quot;&gt;Exporting Consul Client&lt;/h2&gt;

&lt;p&gt;The Consul Client package is really designed as a building block for other packages that need to leverage a Consul Client.  For demonstrative purposes, we’re just going to run Consul by itself.&lt;/p&gt;

&lt;h4 id=&quot;enter-studio&quot;&gt;Enter Studio&lt;/h4&gt;

&lt;p&gt;If you’re not in a Linux environment, you’ll need to enter the habitat studio:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ hab studio enter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;export-qubitrenegadeconsul-client&quot;&gt;Export &lt;code class=&quot;highlighter-rouge&quot;&gt;qubitrenegade/consul-client&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Run the &lt;code class=&quot;highlighter-rouge&quot;&gt;hab pkg&lt;/code&gt; command to export &lt;code class=&quot;highlighter-rouge&quot;&gt;qubitrenegade/consul-client&lt;/code&gt; to a docker container.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ hab pkg export docker qubitrenegade/consul-client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will create a directory &lt;code class=&quot;highlighter-rouge&quot;&gt;$(pwd)/results&lt;/code&gt; and a file &lt;code class=&quot;highlighter-rouge&quot;&gt;$(pwd)/results/last_docker_export.env&lt;/code&gt; which exports a number of environment variables if sourced.  This enables such idioms as &lt;code class=&quot;highlighter-rouge&quot;&gt;docker run -it $name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will specify the origin and package name in examples below.&lt;/p&gt;

&lt;h4 id=&quot;run-your-docker-containers&quot;&gt;Run your docker containers:&lt;/h4&gt;

&lt;p&gt;You will either need to open multiple terminal windows, or replace the &lt;code class=&quot;highlighter-rouge&quot;&gt;-e&lt;/code&gt; with &lt;code class=&quot;highlighter-rouge&quot;&gt;-de&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This also assumes you have no more than one (1) running container before starting this process.  If you have more than one (1) running container, adjust your IPs accordingly.&lt;/p&gt;

&lt;p&gt;Create a service config file and save it as &lt;code class=&quot;highlighter-rouge&quot;&gt;services.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &quot;client&quot;: {
    &quot;enable_script_checks&quot;: true
  },
  &quot;service&quot;: {
    &quot;name&quot;: &quot;simple-service&quot;,
    &quot;checks&quot;: [
      {
        &quot;name&quot;: &quot;is_alive&quot;,
        &quot;args&quot;: [&quot;/bin/bash&quot;, &quot;:(){ echo &quot;I'm alive!&quot;; return 200; }; :&quot;],
        &quot;interval&quot;: &quot;1s&quot;
      }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then start your docker container while importing your settings (adjust peer IPs as necessary):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -e &quot;HAB_CONSUL_CLIENT=$(&amp;lt; services.json)&quot; qubitrenegade/consul-client --peer 172.17.0.4 --bind consul-server:consul.default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now when visit &lt;a href=&quot;http://localhost:8500&quot;&gt;http://localhost:8500&lt;/a&gt; You should see your service registered!&lt;/p&gt;

&lt;h4 id=&quot;examples&quot;&gt;Examples&lt;/h4&gt;

&lt;p&gt;A number of service examples are provided in the &lt;a href=&quot;https://github.com/qubitrenegade/habitat-consul-client/tree/master/example&quot;&gt;example&lt;/a&gt; directory.&lt;/p&gt;

&lt;p&gt;To use any of the examples, you can import the config values as environment variables:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -e &quot;HAB_CONSUL_CLIENT=$(curl https://raw.githubusercontent.com/qubitrenegade/habitat-consul-client/master/example/service-with-no-checks.json)&quot; qubitrenegade/consul-client --peer 172.17.0.4 --bind consul-server:consul.default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><summary type="html">Previously on “As the QubitRenegade turns…”</summary></entry><entry><title type="html">Habitat &amp;amp; Consul: Gossip: You won’t believe the dirt!</title><link href="https://qubitrenegade.com/habitat/consul/docker/2018/06/04/Habitat-and-Consul-gossip-you-wont-belive-dirt.html" rel="alternate" type="text/html" title="Habitat &amp; Consul: Gossip: You won't believe the dirt!" /><published>2018-06-04T18:29:47+00:00</published><updated>2018-06-04T18:29:47+00:00</updated><id>https://qubitrenegade.com/habitat/consul/docker/2018/06/04/Habitat-and-Consul-gossip-you-wont-belive-dirt</id><content type="html" xml:base="https://qubitrenegade.com/habitat/consul/docker/2018/06/04/Habitat-and-Consul-gossip-you-wont-belive-dirt.html">&lt;h2 id=&quot;previously-on-as-the-qubitrenegade-turns&quot;&gt;Previously on “As the QubitRenegade turns…”&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.consul.io&quot;&gt;Consul&lt;/a&gt; an OpenSource(ish, there’s an enterprise version that has some awesome features) Distributed, Highly Available, Service Discovery, Health Checking, KV Store, that provides federated Multi Datacenter support.  (disclaimer: I am in absolutely no way, shape, or form associated with HashiCorp.  All opinions are my own and not influenced by schwag.  I just happen to think they make a pretty swell product… even if it is written in go ;) )&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.habitat.sh/learn/&quot;&gt;Habitat&lt;/a&gt; an OpenSource, Artifact Builder, Artifact and Service Manager, Docker/Kubernetes/Serverless Enabler, sane Docker container builder system, with Distributed Service Discovery and “build once run anywhere (no really)” mentality.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; is how most people do containers. Just… I’ll post the opinion piece soon.  Docker is fine.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.habitat.sh/docs/install-habitat/&quot;&gt;Habitat&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/install/&quot;&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll need to install them both.  Basically we’re going to run a bunch of containers instead of a bunch of servers.  If we were going to push this into production, it doesn’t really make sense to run three-five instances of a service on on VM… if that VM dies, then there goes your cluster.  But with Habitat we can basically run the service in any format we want, containers the same way we’d run them if they were individual VMs or being published to a Kubernetes cluster.  Kubernetes expects you to show up to the party with containers ready to go, Habitat is the one who comes up with the kegs in the trunk.&lt;/p&gt;

&lt;h2 id=&quot;high-level-overview&quot;&gt;High level Overview&lt;/h2&gt;

&lt;p&gt;Habitat needs at least three nodes to form consensus and elect a “leader”.  This prevents “split brain” where two nodes both think they are the leader.  Clusters then scale to uneven numbers… 3, 5, 7, etc.
Consul needs at least three nodes to form consensus and elect a leader… (sound familiar)…&lt;/p&gt;

&lt;p&gt;It’s definitely easier to bootstrap a Habitat cluster than a Consul cluster.  By leveraging Habitat we can bootstrap a consul cluster more easily…  This is for sure not a “Habitat vs Consul” this is 100% a “Habitat + Consul”, I think they are the perfect compliment for each other.&lt;/p&gt;

&lt;h2 id=&quot;building-consul&quot;&gt;Building Consul&lt;/h2&gt;

&lt;p&gt;You have multiple choices actually.  That’s the whole point!&lt;/p&gt;

&lt;p&gt;If you have three (or five!) VMs to run on, you can just install hab on each VM then run:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hab sup run core/consul --peer &amp;lt;node X-1&amp;gt; --peer &amp;lt;node X+1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You probably don’t want to do this for production, but you get the idea, you can run the packages natively in Linux or in a container on any other platform.&lt;/p&gt;

&lt;p&gt;On to the task at hand:&lt;/p&gt;

&lt;h4 id=&quot;enter-studio&quot;&gt;Enter Studio&lt;/h4&gt;

&lt;p&gt;If you’re not in a Linux environment, you’ll need to enter the habitat studio:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ hab studio enter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;export-coreconsul&quot;&gt;Export &lt;code class=&quot;highlighter-rouge&quot;&gt;core/consul&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Run the &lt;code class=&quot;highlighter-rouge&quot;&gt;hab pkg&lt;/code&gt; command to export &lt;code class=&quot;highlighter-rouge&quot;&gt;core/consul&lt;/code&gt; to a docker container.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ hab pkg export docker core/consul
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will create a directory &lt;code class=&quot;highlighter-rouge&quot;&gt;$(pwd)/results&lt;/code&gt; and a file &lt;code class=&quot;highlighter-rouge&quot;&gt;$(pwd)/results/last_docker_export.env&lt;/code&gt; which exports a number of environment variables if sourced.  This enables such idioms as &lt;code class=&quot;highlighter-rouge&quot;&gt;docker run -it $name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will specify the origin and package name in examples below.&lt;/p&gt;

&lt;h4 id=&quot;run-your-docker-containers&quot;&gt;Run your docker containers:&lt;/h4&gt;

&lt;p&gt;You either need to open three or five terminal windows, or replace the &lt;code class=&quot;highlighter-rouge&quot;&gt;-e&lt;/code&gt; with &lt;code class=&quot;highlighter-rouge&quot;&gt;-de&lt;/code&gt; in the examples below.&lt;/p&gt;

&lt;p&gt;This also assumes you have no more than one (1) running container before starting this process.  If you have more than one (1) running container, adjust your IPs accordingly.&lt;/p&gt;

&lt;p&gt;Run once:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -e HAB_CONSUL='{ &quot;server&quot;: { &quot;beta_ui&quot;: true, &quot;bind&quot;: &quot;0.0.0.0&quot; }, &quot;client&quot;:{&quot;bind&quot;: &quot;0.0.0.0&quot;}}' -p 8500:8500 -p 8600:8600/udp core/consul --peer 172.17.0.3 --topology leader --peer 172.17.0.4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run thrice (well, 2 or 4 times but actually not specifically not 3 times)&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -e HAB_CONSUL='{ &quot;server&quot;: { &quot;beta_ui&quot;: true, &quot;bind&quot;: &quot;0.0.0.0&quot; }, &quot;client&quot;:{&quot;bind&quot;: &quot;0.0.0.0&quot;}}' core/consul --peer 172.17.0.3 --topology leader --peer 172.17.0.4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now visit &lt;a href=&quot;http://localhost:9500&quot;&gt;http://localhost:9500&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;you should see 5 nodes!&lt;/p&gt;</content><author><name></name></author><summary type="html">Previously on “As the QubitRenegade turns…”</summary></entry><entry><title type="html">Habitwhat? Habitat!</title><link href="https://qubitrenegade.com/habitat/2018/05/28/Habiwhat-Habitat.html" rel="alternate" type="text/html" title="Habitwhat?  Habitat!" /><published>2018-05-28T22:51:27+00:00</published><updated>2018-05-28T22:51:27+00:00</updated><id>https://qubitrenegade.com/habitat/2018/05/28/Habiwhat-Habitat</id><content type="html" xml:base="https://qubitrenegade.com/habitat/2018/05/28/Habiwhat-Habitat.html">&lt;p&gt;Habitat is an artifact builder.  Habitat is a package/dependency manager.  Habitat is a service manager.  Habitat is a cluster coordinator.&lt;/p&gt;

&lt;p&gt;Habitat is pretty slick!&lt;/p&gt;

&lt;p&gt;I promise to expand this post… but I really want to talk about Habitat and Consul…  so &lt;a href=&quot;https://www.habitat.sh/learn/&quot;&gt;go check out Habitat for yourself!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To be continued…&lt;/em&gt;&lt;/p&gt;</content><author><name></name></author><summary type="html">Habitat is an artifact builder. Habitat is a package/dependency manager. Habitat is a service manager. Habitat is a cluster coordinator.</summary></entry><entry><title type="html">ChefDK: Rakefile for common tasks</title><link href="https://qubitrenegade.com/chef/chefdk/2018/02/07/ChefDK-Rakefile.html" rel="alternate" type="text/html" title="ChefDK: Rakefile for common tasks" /><published>2018-02-07T19:08:21+00:00</published><updated>2018-02-07T19:08:21+00:00</updated><id>https://qubitrenegade.com/chef/chefdk/2018/02/07/ChefDK-Rakefile</id><content type="html" xml:base="https://qubitrenegade.com/chef/chefdk/2018/02/07/ChefDK-Rakefile.html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Good practice is to run rubocop, foodcritic, and ChefSpec (rspec) tests, and test kitchen before pushing your changes, as we’ve &lt;a href=&quot;&quot;&gt;talked about before&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And it’s really not THAT much to type every time to go:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rubocop
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rubocop &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rubocop &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;foodcritic
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;foodcritic &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# I always forget the dot...&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rspec &lt;span class=&quot;nt&quot;&gt;--color&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; d
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kitchen &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;But wouldn’t it be nice to automate this, so we just have one command to type?&lt;/p&gt;

&lt;p&gt;Actually, you can now do that with &lt;code class=&quot;highlighter-rouge&quot;&gt;delivery&lt;/code&gt; locally.  But that comes with some other considerations which deserves its own post.&lt;/p&gt;

&lt;p&gt;So for now, enter, Ruby’s Make! aka &lt;a href=&quot;https://github.com/ruby/rake&quot;&gt;rake&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;rakefile&quot;&gt;Rakefile&lt;/h2&gt;

&lt;p&gt;Rake really is a very powerful tool.  I recommend reading over the documentation linked as well as &lt;a href=&quot;https://edelpero.svbtle.com/everything-you-always-wanted-to-know-about-writing-good-rake-tasks-but-were-afraid-to-ask&quot;&gt;this article&lt;/a&gt;.  We’ll focus on just enough rake to automate our tests.&lt;/p&gt;

&lt;h3 id=&quot;basic-rakefile&quot;&gt;Basic Rakefile&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;default: :reticulate_splines&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Reticulate splines'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:reticulate_splines&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Reticulating Splines...'&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# doing something useful like reticulating splines...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then we can run it.  Also we can run rake with the &lt;code class=&quot;highlighter-rouge&quot;&gt;-T&lt;/code&gt; flag to see all tasks available.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt;
rake reticulate_splines  &lt;span class=&quot;c&quot;&gt;# Reticulate splines&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rake
Reticulating Splines...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This isn’t very useful, but is a good structure to show the basics of a Rakefile.&lt;/p&gt;

&lt;h3 id=&quot;rakefile-explanation&quot;&gt;Rakefile explanation&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;default: :reticulate_splines&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The first line describes the default task.  This is the task that will be run when &lt;code class=&quot;highlighter-rouge&quot;&gt;rake&lt;/code&gt; is called without any arguments.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Reticulate splines'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The next line is the description of the task.  The &lt;code class=&quot;highlighter-rouge&quot;&gt;desc&lt;/code&gt; function call must precede a &lt;code class=&quot;highlighter-rouge&quot;&gt;task&lt;/code&gt; block.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:reticulate_splines&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Reticulating Splines...'&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# doing something useful like reticulating splines...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally, the task block.  The task is named as a symbol, then within the block a function is performed.  In this case we’re only printing a message, but it’s just Ruby, so we can do any useful functions.&lt;/p&gt;

&lt;h2 id=&quot;chef-rakefile&quot;&gt;Chef Rakefile&lt;/h2&gt;

&lt;p&gt;What are the things we always do?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/bbatsov/rubocop&quot;&gt;RuboCop&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/chefspec/chefspec&quot;&gt;ChefSpec&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Foodcritic/foodcritic&quot;&gt;FoodCritic&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/test-kitchen/test-kitchen&quot;&gt;Test Kitchen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To that end, let’s get started!&lt;/p&gt;

&lt;h3 id=&quot;rake-rubocop&quot;&gt;Rake Rubocop&lt;/h3&gt;

&lt;p&gt;The first thing to do, include RuboCop!  Since version 0.10 RuboCop comes with a rake task.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'rubocop/rake_task'&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;RuboCop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RakeTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rubocop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;rubocop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'--display-cop-names'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First we require the library with the rake task.&lt;/p&gt;

&lt;p&gt;Then we initialize the task, by calling RuboCop::RakeTask.new.&lt;/p&gt;

&lt;p&gt;Personally, I like to have the cop names displayed when I run rubocop, so we take the opportunity to add that option when we run rubocop.  You can pass any flags here you would pass on the command line.&lt;/p&gt;

&lt;p&gt;Then when we run &lt;code class=&quot;highlighter-rouge&quot;&gt;rake -T&lt;/code&gt; we get:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt;
rake rubocop               &lt;span class=&quot;c&quot;&gt;# Run RuboCop&lt;/span&gt;
rake rubocop:auto_correct  &lt;span class=&quot;c&quot;&gt;# Auto-correct RuboCop offenses&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we can have &lt;code class=&quot;highlighter-rouge&quot;&gt;rake&lt;/code&gt; run &lt;code class=&quot;highlighter-rouge&quot;&gt;rubocop&lt;/code&gt; for us!&lt;/p&gt;

&lt;h3 id=&quot;rake-foodcritic&quot;&gt;Rake Foodcritic&lt;/h3&gt;

&lt;p&gt;Similar to RuboCop, FoodCritic has built in rake tasks.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'foodcritic'&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;FoodCritic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;LintTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foodcritic&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;foodcritic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:fail_tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(any)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First we again require the library.  Then we initialize the FoodCritic tasks.  Additional options can be set as keys:value pairs to #options.&lt;/p&gt;

&lt;p&gt;Now we should have:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt;
rake foodcritic            &lt;span class=&quot;c&quot;&gt;# Lint Chef cookbooks&lt;/span&gt;
rake rubocop               &lt;span class=&quot;c&quot;&gt;# Run RuboCop&lt;/span&gt;
rake rubocop:auto_correct  &lt;span class=&quot;c&quot;&gt;# Auto-correct RuboCop offenses&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;rake-rspec&quot;&gt;Rake RSpec&lt;/h3&gt;

&lt;p&gt;Finally, RSpec tests.  This also has a rake task.  So following the same pattern…&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'rspec/core/rake_task'&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;RSpec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Core&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RakeTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rspec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;rspec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rspec_opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--color --format documentation&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now we should have one more rake task:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt;
rake foodcritic            &lt;span class=&quot;c&quot;&gt;# Lint Chef cookbooks&lt;/span&gt;
rake rubocop               &lt;span class=&quot;c&quot;&gt;# Run RuboCop&lt;/span&gt;
rake rubocop:auto_correct  &lt;span class=&quot;c&quot;&gt;# Auto-correct RuboCop offenses&lt;/span&gt;
rake spec                  &lt;span class=&quot;c&quot;&gt;# Run RSpec code examples&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;rake-test-kitchen&quot;&gt;Rake Test Kitchen&lt;/h3&gt;

&lt;p&gt;Finally Test Kitchen.  And we follow the same pattern.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'kitchen/rake_tasks'&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Kitchen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RakeTasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We don’t really have any options to change, so we just call “new”.  Now we have something along the lines of:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt;
rake foodcritic                   &lt;span class=&quot;c&quot;&gt;# Lint Chef cookbooks&lt;/span&gt;
rake kitchen:all                  &lt;span class=&quot;c&quot;&gt;# Run all test instances&lt;/span&gt;
rake kitchen:default-centos-7     &lt;span class=&quot;c&quot;&gt;# Run default-centos-7 test instance&lt;/span&gt;
rake kitchen:default-ubuntu-1604  &lt;span class=&quot;c&quot;&gt;# Run default-ubuntu-1604 test instance&lt;/span&gt;
rake rubocop                      &lt;span class=&quot;c&quot;&gt;# Run RuboCop&lt;/span&gt;
rake rubocop:auto_correct         &lt;span class=&quot;c&quot;&gt;# Auto-correct RuboCop offenses&lt;/span&gt;
rake spec                         &lt;span class=&quot;c&quot;&gt;# Run RSpec code examples&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;pulling-it-all-together&quot;&gt;Pulling it all together&lt;/h3&gt;

&lt;p&gt;Remember I said I was lazy?  Probably too lazy to say it.  It’s great that we have one command to run everything, but I still have to remember and give rake a subcommand…  if only there was a way that we could have one rake task call another…?  Also note, we haven’t declared a default task yet.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;default: :all&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Run all tests'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;all: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:kitchen:all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Run Rubocop and Foodcritic style checks'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;style: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:rubocop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foodcritic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Run all style checks and unit tests'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;test: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This gives us a few new commands that will call the various linters and test tools for us directly.  You should have something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rake &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt;
rake all                          &lt;span class=&quot;c&quot;&gt;# Run all tests&lt;/span&gt;
rake foodcritic                   &lt;span class=&quot;c&quot;&gt;# Lint Chef cookbooks&lt;/span&gt;
rake kitchen:all                  &lt;span class=&quot;c&quot;&gt;# Run all test instances&lt;/span&gt;
rake kitchen:default-centos-7     &lt;span class=&quot;c&quot;&gt;# Run default-centos-7 test instance&lt;/span&gt;
rake kitchen:default-ubuntu-1604  &lt;span class=&quot;c&quot;&gt;# Run default-ubuntu-1604 test instance&lt;/span&gt;
rake rubocop                      &lt;span class=&quot;c&quot;&gt;# Run RuboCop&lt;/span&gt;
rake rubocop:auto_correct         &lt;span class=&quot;c&quot;&gt;# Auto-correct RuboCop offenses&lt;/span&gt;
rake spec                         &lt;span class=&quot;c&quot;&gt;# Run RSpec code examples&lt;/span&gt;
rake style                        &lt;span class=&quot;c&quot;&gt;# Run Rubocop and Foodcritic style checks&lt;/span&gt;
rake &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;                         &lt;span class=&quot;c&quot;&gt;# Run all style checks and unit tests&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;final-form&quot;&gt;Final Form&lt;/h2&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/39f1b2e6e2f24181e307841ba180ef41.js&quot;&gt; &lt;/script&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Hopefully this will encourage you to run your tests before you push your code!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Q&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">Introduction</summary></entry><entry><title type="html">Chef: Getting Started</title><link href="https://qubitrenegade.com/chef/intro/2018/02/01/Chef-Getting-Started.html" rel="alternate" type="text/html" title="Chef: Getting Started" /><published>2018-02-01T19:13:57+00:00</published><updated>2018-02-01T19:13:57+00:00</updated><id>https://qubitrenegade.com/chef/intro/2018/02/01/Chef-Getting-Started</id><content type="html" xml:base="https://qubitrenegade.com/chef/intro/2018/02/01/Chef-Getting-Started.html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;This does not intend to be a replacement for the tutorials on the &lt;a href=&quot;https://learn.chef.io/&quot;&gt;Chef Website&lt;/a&gt;.  In fact, I highly recommend reading and working through those tutorials as this blog intends to build on ideas and concepts presented there.  In fact, most of this guide is based on the &lt;a href=&quot;https://learn.chef.io/modules/manage-a-node-chef-server/ubuntu/bring-your-own-system/set-up-your-workstation#/&quot;&gt;Chef Tutorial&lt;/a&gt; and &lt;a href=&quot;https://docs.chef.io/workstation.html&quot;&gt;Documentation&lt;/a&gt; on the same subject.&lt;/p&gt;

&lt;p&gt;This page exists to document my workflows.  So without further ado.&lt;/p&gt;

&lt;h2 id=&quot;chef-account-setup-hosted-chef&quot;&gt;Chef Account Setup (Hosted Chef)&lt;/h2&gt;

&lt;p&gt;Head on over to the &lt;a href=&quot;https://manage.chef.io/signup&quot;&gt;Sign Up Page&lt;/a&gt; to get signed up with a Hosted Chef.  You can run Chef.io Hosted Chef for free up to 5 nodes.  If you need more than that then you’re looking at paying for nodes, or hosting your own Chef Server.&lt;/p&gt;

&lt;h3 id=&quot;knife-setup&quot;&gt;Knife Setup&lt;/h3&gt;

&lt;p&gt;Head over to &lt;a href=&quot;https://manage.chef.io/organizations/&quot;&gt;The Organizations page&lt;/a&gt; in your manage interface (Administration -&amp;gt; Organizations).  Find your organization, and select “Generate Knife Config”.  You should download a &lt;code class=&quot;highlighter-rouge&quot;&gt;knife.rb&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Then head over to Users (Administration -&amp;gt; Users) and find your user, then select “Reset Key”.  You should download a ` &lt;username&gt;.pem ` file.&lt;/username&gt;&lt;/p&gt;

&lt;p&gt;Create a ` ~/.chef ` directory, and move your newly downloaded files into the ` ~/.chef ` directory.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; ~/.chef
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mv&lt;/span&gt; ~/Downloads/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;knife.rb,qubitrenegade.pem&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; ~/.chef&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;kniferb-file&quot;&gt;Knife.rb file&lt;/h3&gt;

&lt;p&gt;Your &lt;code class=&quot;highlighter-rouge&quot;&gt;knife.rb&lt;/code&gt; will look like&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# See http://docs.chef.io/config_rb_knife.html for more information on knife configuration options&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;current_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;__FILE__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log_level&lt;/span&gt;                &lt;span class=&quot;ss&quot;&gt;:info&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log_location&lt;/span&gt;             &lt;span class=&quot;no&quot;&gt;STDOUT&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;node_name&lt;/span&gt;                &lt;span class=&quot;s2&quot;&gt;&quot;qubitrenegade&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client_key&lt;/span&gt;               &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_dir&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/qubitrenegade.pem&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chef_server_url&lt;/span&gt;          &lt;span class=&quot;s2&quot;&gt;&quot;https://api.chef.io/organizations/qubitrenegade&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cookbook_path&lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_dir&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/../cookbooks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;chefdk-install&quot;&gt;ChefDK Install&lt;/h2&gt;

&lt;p&gt;This guide assumes you’re not doing other Ruby development.  If you use bundler and things get weird (Chef can’t find gems that are installed when you &lt;code class=&quot;highlighter-rouge&quot;&gt;gem list&lt;/code&gt;), you can remove the &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.chefdk/gems&lt;/code&gt;  directory.&lt;/p&gt;

&lt;h3 id=&quot;download-chefdk&quot;&gt;Download ChefDK&lt;/h3&gt;

&lt;p&gt;Head over to the [ChefDK Downloads page}(https://downloads.chef.io/chefdk) and select the appropriate package.  For me, I selected the Red Hat 7 rpm.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; /tmp https://packages.chef.io/files/stable/chefdk/2.4.17/el/7/chefdk-2.4.17-1.el7.x86_64.rpm
2018-02-04 17:34:40 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3.33 MB/s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; - ‘/tmp/chefdk-2.4.17-1.el7.x86_64.rpm’ saved &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;106718859/106718859]

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sha256sum&lt;/span&gt; /tmp/chefdk-2.4.17-1.el7.x86_64.rpm 
ab2d62b1eeb5248949f044f4c4bf489babe652fc649dc93cc2dac30607eb207e  /tmp/chefdk-2.4.17-1.el7.x86_64.rpm

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; /tmp/chefdk-2.4.17-1.el7.x86_64.rpm
Running transaction
  Preparing        :                                                                                                                                                                                           1/1 
  Installing       : chefdk-2.4.17-1.el7.x86_64                                                                                                                                                                1/1 
  Running scriptlet: chefdk-2.4.17-1.el7.x86_64                                                                                                                                                                1/1 
Thank you &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;installing Chef Development Kit!
  Verifying        : chefdk-2.4.17-1.el7.x86_64                                                                                                                                                                1/1 

Installed:
  chefdk.x86_64 2.4.17-1.el7                                                                                                                                                                                       

Complete!&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;configure-chefdk&quot;&gt;Configure ChefDK&lt;/h3&gt;

&lt;p&gt;Once our ChefDK package is installed, we need to set up our shell. (Windows users, head over to &lt;a href=&quot;https://docs.chef.io/dk_windows.html#configure-environment&quot;&gt;ChefDK on Windows&lt;/a&gt;)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'eval &quot;$(chef shell-init bash)&quot;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then we can either log in a new shell, or just source our file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you’re using rbenv to manage Ruby, you’re own your own for now…&lt;/p&gt;

&lt;h2 id=&quot;verify&quot;&gt;Verify&lt;/h2&gt;

&lt;p&gt;At this point you should have the ChefDK installed and should be able to communicate with your Hosted Chef account.  We can verify by running a few commands:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;chef &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
Chef Development Kit Version: 2.4.17
chef-client version: 13.6.4
delivery version: master &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;73ebb72a6c42b3d2ff5370c476be800fee7e5427&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
berks version: 6.3.1
kitchen version: 1.19.2
inspec version: 1.45.13

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;knife client list
&amp;lt;your orgname&amp;gt;-validator
node1
node2
node3&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(note: I already have nodes registered, you likely will not.  So you’ll likely only see the validator key)&lt;/p&gt;

&lt;h2 id=&quot;ssl-errors&quot;&gt;SSL Errors&lt;/h2&gt;

&lt;p&gt;If you’re working with self signed certs or are behind some corporate proxies, Ruby will have a bad time validating SSL certs.  While the &lt;em&gt;best&lt;/em&gt; answer is always “fix your SSL”, but that is, unfortunately, not always a possible solution.  These can be worked around with the below solutions.&lt;/p&gt;

&lt;h3 id=&quot;chef-ssl-errors&quot;&gt;Chef SSL Errors&lt;/h3&gt;

&lt;h4 id=&quot;download-ssl-certs&quot;&gt;Download SSL Certs&lt;/h4&gt;

&lt;p&gt;The first thing we can try is to download the SSL certs from the server.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;knife ssl fetch
WARNING: Certificates from api.chef.io will be fetched and placed &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;your trusted_cert
directory &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;/home/qubitrenegade/.chef/trusted_certs&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

Knife has no means to verify these are the correct certificates. You should
verify the authenticity of these certificates after downloading.

Adding certificate &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;wildcard_opscode_com &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; /home/qubitrenegade/.chef/trusted_certs/wildcard_opscode_com.crt
Adding certificate &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;DigiCert_SHA2_Secure_Server_CA &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; /home/qubitrenegade/.chef/trusted_certs/DigiCert_SHA2_Secure_Server_CA.crt&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;disable-ssl-checking&quot;&gt;Disable SSL Checking&lt;/h4&gt;

&lt;p&gt;If you’re dealing with a proxy, the above may not work still.  You can disable ssl checking with knife entirely, though this is not recommended, disabling SSL for Knife is documented below.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ssl_verify_mode :verify_none'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/.chef/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;knife&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rb&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Again, this disables all SSL checking and is not recommended!!!&lt;/p&gt;

&lt;h3 id=&quot;berkshelf-ssl-errors&quot;&gt;Berkshelf SSL Errors&lt;/h3&gt;

&lt;p&gt;Disable ssl checking for berkshelf:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; ~/.berkshelf
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{&quot;ssl&quot;:{&quot;verify&quot;: false }}'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/.berkshelf/config.json&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;docker&quot;&gt;Docker&lt;/h2&gt;

&lt;p&gt;This should not be seen as condoning the use of docker in production!  However, for the purposes of the next few posts, it will serve our needs.  Again, this post mostly just follows the instructions found in the &lt;a href=&quot;https://docs.docker.com/install/linux/docker-ce/fedora/&quot;&gt;official documentation&lt;/a&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Remove old versions of Docker&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; remove docker docker-common docker-selinux docker-engine-selinux docker-engine

&lt;span class=&quot;c&quot;&gt;# install dnf plugins&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;dnf-plugins-core

&lt;span class=&quot;c&quot;&gt;# add docker-ce repo&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf config-manager &lt;span class=&quot;nt&quot;&gt;--add-repo&lt;/span&gt; https://download.docker.com/linux/fedora/docker-ce.repo

&lt;span class=&quot;c&quot;&gt;# install docker-ce&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;docker-ce 

&lt;span class=&quot;c&quot;&gt;# start docker&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl start docker

&lt;span class=&quot;c&quot;&gt;# optionally enable docker to start at boot&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;docker

&lt;span class=&quot;c&quot;&gt;# and validate we can run a container&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker run hello-world

&lt;span class=&quot;c&quot;&gt;# if you get an error like the following, your daemon probably isn't started.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker run hello-world
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
See &lt;span class=&quot;s1&quot;&gt;'docker run --help'&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Add your user to the docker group.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# This doesn't seem to work on F27?  Further investigation to follow&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Maybe try logging out then logging back in.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;usermod &lt;span class=&quot;nt&quot;&gt;-aG&lt;/span&gt; docker &lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;first-cookbook&quot;&gt;First cookbook&lt;/h2&gt;

&lt;p&gt;I like to do my work in my &lt;code class=&quot;highlighter-rouge&quot;&gt;~/chef-dev&lt;/code&gt; directory.  So let’s create this first.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; ~/chef-dev
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/chef-dev&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then we’ll create our first cookbook, this can be found on &lt;a href=&quot;https://github.com/qubitrenegade/my_test&quot;&gt;github&lt;/a&gt;, but it’s not much more than a base &lt;code class=&quot;highlighter-rouge&quot;&gt;chef generate cookbook &amp;lt;cookbook name&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;chef generate cookbook my_test
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;my_test&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;running-test-kitchen&quot;&gt;Running Test Kitchen&lt;/h3&gt;

&lt;p&gt;At this point, we should be in our new cookbook directory, and be able to run &lt;code class=&quot;highlighter-rouge&quot;&gt;kitchen test&lt;/code&gt;, but I’m having trouble and didn’t want to reboot at the moment…&lt;/p&gt;

&lt;p&gt;So more on this later,&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;At this point, we should have:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;installed the ChefDK,&lt;/li&gt;
  &lt;li&gt;installed Docker,&lt;/li&gt;
  &lt;li&gt;Configured our &lt;code class=&quot;highlighter-rouge&quot;&gt;knife.rb&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;created our first cookbook using the ChefDK generator&lt;/li&gt;
  &lt;li&gt;Run Test Kitchen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re now ready to rock!  Tune in next time when we discuss the cookbook development process.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Q&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">Introduction</summary></entry></feed>