<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Christopher&#39;s Blog</title>
    <link>https://www.nadeau.tv/</link>
    <description>Recent content on Christopher&#39;s Blog</description>
    <generator>Hugo</generator>
    <language>en-gb</language>
    <lastBuildDate>Tue, 23 Mar 2021 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.nadeau.tv/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Fast Integration Tests with MySQL</title>
      <link>https://www.nadeau.tv/post/fast-integration-tests-with-mysql/</link>
      <pubDate>Tue, 23 Mar 2021 00:00:00 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/fast-integration-tests-with-mysql/</guid>
      <description>&lt;p&gt;We have a collection of nearly 700 integration tests (and growing!) in over 130 suites that we run against a live MySQL database. These tests are mostly performing GraphQL mutations, and the tests basically just assert that the mutation does what it&amp;rsquo;s meant to do.&lt;/p&gt;&#xA;&lt;p&gt;As time goes on and we add more and more tests, the test suite was becoming slower and slower&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;resetting-the-db-between-tests&#34;&gt;Resetting the DB between tests&lt;/h2&gt;&#xA;&lt;p&gt;To ensure tests aren&amp;rsquo;t too fragile, early on we added a &lt;a href=&#34;https://jestjs.io/docs/setup-teardown&#34;&gt;&lt;code&gt;beforeAll&lt;/code&gt;&lt;/a&gt; routine that reset the database between each suite.&lt;/p&gt;</description>
    </item>
    <item>
      <title>About</title>
      <link>https://www.nadeau.tv/about/</link>
      <pubDate>Sat, 08 Aug 2020 00:00:00 +0000</pubDate>
      <guid>https://www.nadeau.tv/about/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://twitter.com/chroder&#34; style=&#34;display: inline-block; border-radius: 8px; overflow: hidden; padding:0; margin: 0;&#34;&gt;&lt;img src=&#34;https://pbs.twimg.com/profile_images/1018606396676493313/u5Z1o9en_400x400.jpg&#34; width=&#34;125&#34; height=&#34;125&#34; style=&#34;margin:0;padding:0;&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;I’m Christopher Nadeau. I’m the CTO over at &lt;a href=&#34;https://www.deskpro.com/&#34;&gt;Deskpro&lt;/a&gt;. I like writing and shipping software, and building businesses.&lt;/p&gt;&#xA;&lt;h3 id=&#34;connect&#34;&gt;Connect&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;GitHub: &lt;a href=&#34;https://github.com/chroder&#34;&gt;@chroder&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Twitter: &lt;a href=&#34;https://twitter.com/chroder&#34;&gt;@chroder&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Email: &lt;a href=&#34;mailto:&amp;#099;&amp;#104;&amp;#114;&amp;#105;&amp;#115;&amp;#064;&amp;#110;&amp;#097;&amp;#100;&amp;#101;&amp;#097;&amp;#117;&amp;#046;&amp;#116;&amp;#118;&#34;&gt;chris at nadeau dot tv&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Secure home server with Unraid and Cloudflare</title>
      <link>https://www.nadeau.tv/post/unraid-home-server-with-cloudflare/</link>
      <pubDate>Sat, 08 Aug 2020 00:00:00 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/unraid-home-server-with-cloudflare/</guid>
      <description>&lt;p&gt;I built a home server earlier this year to serve as a NAS and home media center. I&amp;rsquo;m trying to make a more concerted effort to take control over my own data and rely less on cloud services.&lt;/p&gt;&#xA;&lt;p&gt;I chose &lt;a href=&#34;https://unraid.net/&#34;&gt;Unraid&lt;/a&gt; as the underlying operating system. If you&amp;rsquo;re building a home server, I really recommend checking it out. Out of the options I tried, Unraid was by far the easiest to get up and running with.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Quickie: Color console output with parallel command</title>
      <link>https://www.nadeau.tv/post/color-console-output-parallel-command/</link>
      <pubDate>Thu, 18 Jul 2019 16:20:00 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/color-console-output-parallel-command/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve got a Lerna monorepos with a few microservices. I needed to run the dev version a few of these microservices so I decided to use parallel to run them all at the same time in my terminal:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;parallel --tagstring &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;{/}&amp;#39;&lt;/span&gt; --linebuffer &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;cd {} &amp;amp;&amp;amp; npm run dev&amp;#39;&lt;/span&gt; ::: packages/service-a packages/service-b packages/service-c&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This worked, but I noticed that the color output was stripped when doing this. This is really annoying. The color really helps during development to spot errors.&lt;/p&gt;</description>
    </item>
    <item>
      <title>SPF, DKIM, DMARC: What they do and what they don&#39;t</title>
      <link>https://www.nadeau.tv/post/spf-dkim-dmarc-what-they-do-and-what-they-dont/</link>
      <pubDate>Fri, 14 Jun 2019 15:54:31 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/spf-dkim-dmarc-what-they-do-and-what-they-dont/</guid>
      <description>&lt;p&gt;Email is such a mess of technologies and standards, it&amp;rsquo;s hard to understand how everything works together. When it comes to SPF, DKIM, DMARC, there are some misconceptions.&lt;/p&gt;&#xA;&lt;p&gt;The major misconception is around what SPF and DKIM actually do. Many people think that SPF and DKIM are somehow related to controlling who can send messages &lt;em&gt;From&lt;/em&gt; your domain, but that&amp;rsquo;s not totally true.&lt;/p&gt;&#xA;&lt;p&gt;The first thing to understand is that there are &lt;em&gt;two&lt;/em&gt; email addresses in an email:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Configure a Hyper Key on OSX</title>
      <link>https://www.nadeau.tv/post/configure-hyper-key-osx/</link>
      <pubDate>Tue, 28 Aug 2018 12:00:00 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/configure-hyper-key-osx/</guid>
      <description>&lt;p&gt;If you&amp;rsquo;re anything like me, you like keyboard shortcuts. I like to set up custom shortcuts and macros to automate everything I can. The problem is that the most convenient keyboard combinations are already in use by the OS or by user applications.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s where the Hyper Key (also sometimes called a &lt;em&gt;Super Key&lt;/em&gt;) comes in. Basically: Get rid of the useless caps-lock key and turn it into a new modifier key that isn&amp;rsquo;t used by anything else. For example, maybe you want &lt;code&gt;HYPER+V&lt;/code&gt; to mean &amp;ldquo;Paste without formatting&amp;rdquo;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Nginx proxy_pass DNS Cache</title>
      <link>https://www.nadeau.tv/post/nginx-proxy_pass-dns-cache/</link>
      <pubDate>Fri, 31 Mar 2017 10:00:12 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/nginx-proxy_pass-dns-cache/</guid>
      <description>&lt;p&gt;We use nginx to proxy to an Amazon S3 bucket to serve static content to customers. Yesterday, I noticed a high failure rate through the proxy but I couldn&amp;rsquo;t figure out why.&lt;/p&gt;&#xA;&lt;p&gt;After some debugging, I finally discovered that the IP address nginx was hitting was different from the one that DNS was returning. It turns out that nginx resolves hostnames only once on load, meaning whatever IP address it got on load would stick around until reload.&lt;/p&gt;</description>
    </item>
    <item>
      <title>pt-online-schema-change error &#34;Error creating new table ... duplicate key&#34;</title>
      <link>https://www.nadeau.tv/post/pt-online-schema-change-error-error-creating-new-table-duplicate-key/</link>
      <pubDate>Thu, 16 Jun 2016 16:11:04 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/pt-online-schema-change-error-error-creating-new-table-duplicate-key/</guid>
      <description>&lt;p&gt;&lt;code&gt;pt-online-schema-change&lt;/code&gt; is a tool in the &lt;a href=&#34;https://www.percona.com/doc/percona-toolkit/2.2/index.html&#34;&gt;Percona Toolkit&lt;/a&gt; which allows you to make large table alters without locking the database.&lt;/p&gt;&#xA;&lt;p&gt;Newer versions of MySQL have &lt;a href=&#34;https://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html&#34;&gt;Online DDL&lt;/a&gt; which reduce the need for this tool. But if you&amp;rsquo;re like us, &lt;code&gt;pt-online-schema-change&lt;/code&gt; is still very valuable because we use Galera. Running a DDL query on a Galera cluster blocks the entire cluster (even other databases in the same cluster).&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve successfully used &lt;code&gt;pt-online-schema-change&lt;/code&gt; in the past with great success. This week I tried to use it again to perform some expensive queries and I ran into an error message like this:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Quickie: Prevent Mac apps from quitting when last window is closed</title>
      <link>https://www.nadeau.tv/post/quickie-prevent-osx-from-closing-when-last-window-is-closed/</link>
      <pubDate>Thu, 03 Mar 2016 10:29:18 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/quickie-prevent-osx-from-closing-when-last-window-is-closed/</guid>
      <description>&lt;p&gt;There are a few apps on OSX that quit/terminate once their window is closed. This is typical on Windows of course, but it&amp;rsquo;s a bit random on OSX. Some (most?) apps stay open, and some close. I find it really bloody annoying. I&amp;rsquo;ll quit my apps when I&amp;rsquo;m ready to quit them, thank you very much.&lt;/p&gt;&#xA;&lt;p&gt;The biggest sore spot with me is &lt;a href=&#34;https://agilebits.com/onepassword&#34;&gt;1password&lt;/a&gt; which I use dozens of times a day, and every time I &lt;code&gt;CMD+W&lt;/code&gt; to close the window (muscle memory!), it quits the app. Re-opening it takes about 2 seconds. It doesn&amp;rsquo;t seem like much, but it&amp;rsquo;s annoying when I use it so often.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Quickie: Quickly rename MySQL database</title>
      <link>https://www.nadeau.tv/post/quickie-quickly-rename-mysql-database/</link>
      <pubDate>Wed, 02 Mar 2016 17:42:43 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/quickie-quickly-rename-mysql-database/</guid>
      <description>&lt;p&gt;There&amp;rsquo;s no way to rename a MySQL database. Typical advice is to dump/restore the database, but this is obviously very slow if you have a huge database.&lt;/p&gt;&#xA;&lt;p&gt;I found a solution today. Create your database, then execute this one-line:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;mysql -uUSER -pPASS OLD_DB -sNe &amp;#39;SHOW TABLES&amp;#39; | while read t; do mysql -u username -ppassword -sNe &amp;#34;rename table OLD_DB.$t to NEW_DB.$t&amp;#34;; done&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;Obviously replace the params as necessary.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Or here&amp;rsquo;s the same as a slightly easier to read bash script:&lt;/p&gt;</description>
    </item>
    <item>
      <title>SSH with a Bastion Host</title>
      <link>https://www.nadeau.tv/post/ssh-with-a-bastion-host/</link>
      <pubDate>Sat, 27 Feb 2016 13:33:16 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/ssh-with-a-bastion-host/</guid>
      <description>&lt;p&gt;A bastion host is a server that sits on a public network whose sole purpose is to provide access to an inner private network.&lt;/p&gt;&#xA;&lt;p&gt;For example, if you use AWS and have instances on a private VPC subnet, then the only way you can gain SSH access to them is to use a bastion host as a kind of proxy.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;You &amp;gt; Bastion &amp;gt; Server&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;For the best security, you typically have SSH configured for key-only authentication. This presents a problem: Your bastion server needs the keys to any internal server. Having a single bastion server with the keys to the castle is a pretty big risk.&lt;/p&gt;</description>
    </item>
    <item>
      <title>AWS VPC Network Structure</title>
      <link>https://www.nadeau.tv/post/aws-vpc-network-structure/</link>
      <pubDate>Sat, 27 Feb 2016 13:32:41 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/aws-vpc-network-structure/</guid>
      <description>&lt;p&gt;I recently started playing around with AWS. One of the really cool things about AWS is the Virtual Private Cloud  (VPC) features. By creating a VPC, you create a private network for yourself complete with NAT gateways, custom route tables, firewalls and more.&lt;/p&gt;&#xA;&lt;h2 id=&#34;vpc-components&#34;&gt;VPC Components&lt;/h2&gt;&#xA;&lt;p&gt;A VPC is made up of several main components:&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;CIDR Block&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;When you create your VPC, you are asked to define a CIDR block, which is the range of IP addresses you want your VPC to use. For example, &lt;code&gt;10.0.0.0/16&lt;/code&gt; means you can use &lt;code&gt;10.0.0.0 - 10.0.255.255&lt;/code&gt; (65,534 addresses).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Setting up a new MySQL slave database via steaming xtrabackup</title>
      <link>https://www.nadeau.tv/post/setting-up-a-new-mysql-slave-database-via-streaming-xtrabackup/</link>
      <pubDate>Wed, 27 Jan 2016 18:16:45 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/setting-up-a-new-mysql-slave-database-via-streaming-xtrabackup/</guid>
      <description>&lt;p&gt;The goal today is to build a new MySQL slave database off an existing database. We&amp;rsquo;ll use Percona&amp;rsquo;s &lt;a href=&#34;https://www.percona.com/doc/percona-xtrabackup&#34;&gt;xtrabackup&lt;/a&gt; to &lt;em&gt;stream&lt;/em&gt; a hot backup over the wire to a new machine, while keeping the existing server online.&lt;/p&gt;&#xA;&lt;h2 id=&#34;prep&#34;&gt;Prep&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Install MySQL on New Server&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Install MySQL in the way you normally would (e.g., &lt;code&gt;apt-get&lt;/code&gt; etc).&lt;/p&gt;&#xA;&lt;p&gt;The only very important thing you need to do is edit &lt;code&gt;my.cnf&lt;/code&gt; and set a &lt;a href=&#34;http://dev.mysql.com/doc/refman/5.7/en/replication-options.html#option_mysqld_server-id&#34;&gt;&lt;code&gt;server-id&lt;/code&gt;&lt;/a&gt; for the server. This can be any integer. I tend to use the current date and time just because it&amp;rsquo;s generally pretty unique (like &lt;code&gt;201601271730&lt;/code&gt;).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Using NgModelController with Custom Directives</title>
      <link>https://www.nadeau.tv/post/using-ngmodelcontroller-with-custom-directives/</link>
      <pubDate>Sat, 01 Feb 2014 15:38:00 +0000</pubDate>
      <guid>https://www.nadeau.tv/post/using-ngmodelcontroller-with-custom-directives/</guid>
      <description>&lt;p&gt;Creating directives with AngularJS is &lt;a href=&#34;http://docs.angularjs.org/guide/directive&#34;&gt;fairly straightforward&lt;/a&gt;. But most directives also need to interact with a model which represents their state. You could bake in your own custom model handling, but you can also plug right in to AngularJS&amp;rsquo;s own &lt;a href=&#34;http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController&#34;&gt;NgModelController&lt;/a&gt; &amp;ndash; the same &lt;code&gt;ng-model&lt;/code&gt; that is used for things like input boxes and select menus.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;example-directive-time-duration-&#34;&gt;Example directive: &lt;code&gt;&amp;lt;time-duration /&amp;gt;&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;As a simple example, let&amp;rsquo;s build a directive where the user can input a duration using one of many possible units of time.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
