<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<title>Austin&#x27;s Thought Basin</title>
	<subtitle>The personal blog of Austin Dworaczyk Wiltshire.</subtitle>
	<link href="https://austindw.com/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="https://austindw.com"/>
	<generator uri="https://www.getzola.org/">Zola</generator>
	<updated>2022-05-30T00:00:00+00:00</updated>
	<id>https://austindw.com/atom.xml</id>
	<entry xml:lang="en">
		<title>Converting a website to an ebook</title>
		<published>2022-05-30T00:00:00+00:00</published>
		<updated>2022-05-30T00:00:00+00:00</updated>
		<link href="https://austindw.com/website-to-ebook/" type="text/html"/>
		<id>https://austindw.com/website-to-ebook/</id>
		<content type="html">&lt;p&gt;I recently ran through the ups and downs of taking a very well written blog and converting it to an EPUB ebook in order
to read it on my Kindle.&lt;&#x2F;p&gt;
&lt;p&gt;Using a few command line applications I was able to produce a rather well formatted EPUB file that I could send to my
Kindle using Amazon&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;gp&#x2F;help&#x2F;customer&#x2F;display.html?nodeId=G7NECT4B4ZWHQ8WV&quot;&gt;Email to Kindle&lt;&#x2F;a&gt;
service.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;The general principal can be applied to almost any website that renders using HTML on the server side (&lt;em&gt;throws shade at SPAs&lt;&#x2F;em&gt;), so blogs
are often perfect for this, or Wikipedia articles, whatever suits your fancy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-1-collect-your-urls&quot;&gt;Step 1 - Collect your URLs&lt;a class=&quot;zola-anchor&quot; href=&quot;#step-1-collect-your-urls&quot; aria-label=&quot;Anchor link for: step-1-collect-your-urls&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Start by collecting all of the URLs that you want into a single file, with each URL separated by a newline. I called my
file &lt;code&gt;urls&lt;&#x2F;code&gt; (original I know).&lt;&#x2F;p&gt;
&lt;p&gt;Example of &lt;code&gt;urls&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;https:&#x2F;&#x2F;austindw.com&#x2F;harden-openwrt&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;https:&#x2F;&#x2F;austindw.com&#x2F;precompressed-assets-caddy&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;step-2-create-the-book&quot;&gt;Step 2 - Create the book&lt;a class=&quot;zola-anchor&quot; href=&quot;#step-2-create-the-book&quot; aria-label=&quot;Anchor link for: step-2-create-the-book&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Wow, two steps and we&#x27;re done? Kinda.&lt;&#x2F;p&gt;
&lt;p&gt;I wrote up a script to do the rest of the steps in one fell swoop.&lt;&#x2F;p&gt;
&lt;p&gt;It requires a few tools be installed, specifically:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;readability-cli&lt;&#x2F;code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;readability-cli&quot;&gt;Homepage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;For Arch Linux users, this package is provided in the AUR, so a simple &lt;code&gt;yay -Sa readability-cli&lt;&#x2F;code&gt; should be all you
need.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pandoc&lt;&#x2F;code&gt;
&lt;ul&gt;
&lt;li&gt;The macdaddy of document processors as far as I can tell. It&#x27;s available on most Linux distro&#x27;s in the package
manager.&lt;&#x2F;li&gt;
&lt;li&gt;For Arch Linux users, a simple &lt;code&gt;pacman -S pandoc&lt;&#x2F;code&gt; will do the trick.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Now that we have the required dependencies, let&#x27;s take a look at the script:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;#!&#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;set &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;-eu
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Point this at whatever file your URLs are stored in.
&lt;&#x2F;span&gt;&lt;span&gt;urls&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;urls&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Make the directory where we&amp;#39;ll store the clean HTML for each post.
&lt;&#x2F;span&gt;&lt;span&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span&gt; posts
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Iterate over the URLs, download them and clean them up with the readability-cli
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# We use a count here to ensure that we organize the output posts in the same order that they are specified
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# in the input file. This is helpful as you can lay out the full order of your book by just editing the URLs file.
&lt;&#x2F;span&gt;&lt;span&gt;count&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;cat &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;$urls&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt; url
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;do
&lt;&#x2F;span&gt;&lt;span&gt;    output&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;printf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;posts&#x2F;%03d.html&amp;quot; $count)
&lt;&#x2F;span&gt;&lt;span&gt;    readable&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -q --low-confidence&lt;&#x2F;span&gt;&lt;span&gt; force &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;$url&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -o &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;$output&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;dev&#x2F;null
&lt;&#x2F;span&gt;&lt;span&gt;    count&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;$((count&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;done
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Take all of the posts and put them into a book.
&lt;&#x2F;span&gt;&lt;span&gt;pandoc&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span&gt; TheBook.epub posts&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Save, make executable (&lt;code&gt;chmod +x script.sh&lt;&#x2F;code&gt;), and run the script and you&#x27;ll have a fresh new EPUB named &lt;code&gt;TheBook.epub&lt;&#x2F;code&gt;
at the end of it.&lt;&#x2F;p&gt;
&lt;p&gt;Open that up in your preferred ebook reader and you&#x27;ll see a nicely formatted output like the following:&lt;&#x2F;p&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;406f088b66b593c700.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;406f088b66b593c700.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;Screenshot of the zathura application rendering an ebook of blog posts derived from austindw.com&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;406f088b66b593c700.png&quot; width=&quot;780&quot; height=&quot;880&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;p&gt;Obviously, you should edit the script to your needs. This post just acts as a guide, demonstrating the power of the
&lt;code&gt;readability-cli&lt;&#x2F;code&gt; and &lt;code&gt;pandoc&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; I used the &lt;code&gt;--low-confidence force&lt;&#x2F;code&gt; option when executing the &lt;code&gt;readable&lt;&#x2F;code&gt; command as I noticed a few posts that
failed to extract with the default &lt;code&gt;keep&lt;&#x2F;code&gt; setting. Using &lt;code&gt;force&lt;&#x2F;code&gt; here worked just fine for my use case. Obviously, this
may or may not work for your use case, so experiment.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Encoding Snippets</title>
		<published>2022-03-12T00:00:00+00:00</published>
		<updated>2022-03-12T00:00:00+00:00</updated>
		<link href="https://austindw.com/encoding-snippets/" type="text/html"/>
		<id>https://austindw.com/encoding-snippets/</id>
		<content type="html">&lt;p&gt;I do a lot of encoding work, but I seem to lose track of useful encoding snippets from time to time.&lt;&#x2F;p&gt;
&lt;p&gt;This post will act as a central repository for me to organize my snippets.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;ffmpeg&quot;&gt;FFMPEG&lt;a class=&quot;zola-anchor&quot; href=&quot;#ffmpeg&quot; aria-label=&quot;Anchor link for: ffmpeg&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;downscale-video-using-spline36&quot;&gt;Downscale video using spline36&lt;a class=&quot;zola-anchor&quot; href=&quot;#downscale-video-using-spline36&quot; aria-label=&quot;Anchor link for: downscale-video-using-spline36&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; input.mp4&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -vf&lt;&#x2F;span&gt;&lt;span&gt; zscale=w=1920:h=-1:filter=spline36 out.mp4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;denoise-using-hqdn3d-or-fftdnoiz&quot;&gt;Denoise using hqdn3d or fftdnoiz&lt;a class=&quot;zola-anchor&quot; href=&quot;#denoise-using-hqdn3d-or-fftdnoiz&quot; aria-label=&quot;Anchor link for: denoise-using-hqdn3d-or-fftdnoiz&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;hqdn3d, with a luma_spatial of 6 (default is 4).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; input.mp4&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -vf&lt;&#x2F;span&gt;&lt;span&gt; hqdn3d=luma_spatial=6 out.mp4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;fftdnoiz, sigma 4, using 1 previous and 1 future frame for temporal filtering&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; input.mp4&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -vf&lt;&#x2F;span&gt;&lt;span&gt; fftdnoiz=sigma=4:prev=1:next=1 out.mp4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;downscale-and-denoise&quot;&gt;Downscale and denoise&lt;a class=&quot;zola-anchor&quot; href=&quot;#downscale-and-denoise&quot; aria-label=&quot;Anchor link for: downscale-and-denoise&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; input.mp4&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -vf&lt;&#x2F;span&gt;&lt;span&gt; zscale=w=1920:h=-1:filter=spline36,hqdn3d=luma_spatial=6 out.mp4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;output-using-x264-copying-audio&quot;&gt;Output using x264, copying audio&lt;a class=&quot;zola-anchor&quot; href=&quot;#output-using-x264-copying-audio&quot; aria-label=&quot;Anchor link for: output-using-x264-copying-audio&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; input.mp4&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt;:a copy&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt;:v libx264&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -preset&lt;&#x2F;span&gt;&lt;span&gt; slower&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -tune&lt;&#x2F;span&gt;&lt;span&gt; film&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -crf&lt;&#x2F;span&gt;&lt;span&gt; 21 out.mp4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;enable-video-fast-start-by-adding-movflags-to-mp4-file&quot;&gt;Enable video fast start by adding movflags to MP4 file&lt;a class=&quot;zola-anchor&quot; href=&quot;#enable-video-fast-start-by-adding-movflags-to-mp4-file&quot; aria-label=&quot;Anchor link for: enable-video-fast-start-by-adding-movflags-to-mp4-file&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; input.mp4&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -movflags&lt;&#x2F;span&gt;&lt;span&gt; +faststart out.mp4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This enables videos to start playing as soon as the first few bytes are sent to the client, instead of requiring the
client to download the full video.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;process-video-with-vapoursynth-encode-video-and-copy-audio-using-ffmpeg&quot;&gt;Process video with Vapoursynth, encode video and copy audio using FFMPEG&lt;a class=&quot;zola-anchor&quot; href=&quot;#process-video-with-vapoursynth-encode-video-and-copy-audio-using-ffmpeg&quot; aria-label=&quot;Anchor link for: process-video-with-vapoursynth-encode-video-and-copy-audio-using-ffmpeg&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;This is useful to handle video processing with Vapoursynth (denoise, deinterlacing, sharpening, etc etc) while still
maintaining the audio from the original source.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;vspipe&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --arg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;source=.&#x2F;input.mp4&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt; y4m script.py - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; input.mp4&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -map&lt;&#x2F;span&gt;&lt;span&gt; 0:v&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -map&lt;&#x2F;span&gt;&lt;span&gt; 1:a&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt;:a copy&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt;:v libx264&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -preset&lt;&#x2F;span&gt;&lt;span&gt; fast&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -tune&lt;&#x2F;span&gt;&lt;span&gt; film&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -crf&lt;&#x2F;span&gt;&lt;span&gt; 20 out.mp4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The magic is in the &lt;code&gt;-map 0:v -map 1:a -c:a copy&lt;&#x2F;code&gt; line. &lt;code&gt;map&lt;&#x2F;code&gt; is used to select from multiple sources,
so in the case we&#x27;re saying &amp;quot;select video from the first input (raw pipe from Vapoursynth), select audio from the second input (the same file
we fed to Vapoursynth), and copy the audio&amp;quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vspipe&quot;&gt;VSPIPE&lt;a class=&quot;zola-anchor&quot; href=&quot;#vspipe&quot; aria-label=&quot;Anchor link for: vspipe&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;vspipe&lt;&#x2F;code&gt;, used for reading Vapoursynth (Python) files and feeding them to other programs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;feed-vspipe-output-to-mpv-in-a-paused-state&quot;&gt;Feed vspipe output to MPV in a paused state&lt;a class=&quot;zola-anchor&quot; href=&quot;#feed-vspipe-output-to-mpv-in-a-paused-state&quot; aria-label=&quot;Anchor link for: feed-vspipe-output-to-mpv-in-a-paused-state&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;vspipe&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt; y4m script.vpy - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;mpv&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --pause --demuxer-rawvideo-codec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;y4m -
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;feed-vspipe-to-x265&quot;&gt;Feed vspipe to x265&lt;a class=&quot;zola-anchor&quot; href=&quot;#feed-vspipe-to-x265&quot; aria-label=&quot;Anchor link for: feed-vspipe-to-x265&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;vspipe&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt; y4m script.vpy - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;x265&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --y4m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span&gt; out.h265
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;feed-vspipe-to-x265-with-10-bit-video&quot;&gt;Feed vspipe to x265 with 10-bit video&lt;a class=&quot;zola-anchor&quot; href=&quot;#feed-vspipe-to-x265-with-10-bit-video&quot; aria-label=&quot;Anchor link for: feed-vspipe-to-x265-with-10-bit-video&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;vspipe&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt; y4m script.vpy - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;x265&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --y4m --input-depth&lt;&#x2F;span&gt;&lt;span&gt; 10 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span&gt; out.h265
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;feed-vspipe-to-ffmpeg&quot;&gt;Feed vspipe to ffmpeg&lt;a class=&quot;zola-anchor&quot; href=&quot;#feed-vspipe-to-ffmpeg&quot; aria-label=&quot;Anchor link for: feed-vspipe-to-ffmpeg&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;vspipe&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt; y4m script.vpy - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;ffmpeg&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt; out.mp4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;pass-arg-to-vapoursynth-script-from-vspipe&quot;&gt;Pass arg to Vapoursynth script from vspipe&lt;a class=&quot;zola-anchor&quot; href=&quot;#pass-arg-to-vapoursynth-script-from-vspipe&quot; aria-label=&quot;Anchor link for: pass-arg-to-vapoursynth-script-from-vspipe&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;vspipe&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --arg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;source=.&#x2F;input.mp4&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --info&lt;&#x2F;span&gt;&lt;span&gt; script.vpy -
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The arg takes the place of a python variable, so it works with something like the following script:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;vapoursynth &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;vs
&lt;&#x2F;span&gt;&lt;span&gt;core &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;vs.core
&lt;&#x2F;span&gt;&lt;span&gt;clip &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;core.lsmas.LWLibavSource(source) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Note that &amp;#39;source&amp;#39; is read from the --arg param
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# ... do processing here
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;clip.set_output()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note: The &lt;code&gt;--info&lt;&#x2F;code&gt; just quickly validates that the passed arg is legit, and prints out the video statistics. You&#x27;ll
remove it when actually feeding to something like ffmpeg.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Hardening OpenWrt</title>
		<published>2021-09-26T00:00:00+00:00</published>
		<updated>2021-09-26T00:00:00+00:00</updated>
		<link href="https://austindw.com/harden-openwrt/" type="text/html"/>
		<id>https://austindw.com/harden-openwrt/</id>
		<content type="html">&lt;p&gt;For a few reasons I&#x27;ve fallen down the OpenWrt hole again of late.&lt;&#x2F;p&gt;
&lt;p&gt;While working on some custom builds, I noticed some areas where I could improve the security
of my devices significantly. To be honest, I&#x27;m a little surprised that OpenWrt doesn&#x27;t do some
of them by default.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll walk through various methods that most people can use to harden their OpenWrt install.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;This guide assumes you know how to either SSH into your router or access the Luci web interface, as well as install
packages using &lt;code&gt;opkg&lt;&#x2F;code&gt; or the &lt;code&gt;System -&amp;gt; Software&lt;&#x2F;code&gt; menu. If you don&#x27;t know how to do these things, simply read the
&lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-quick-start&#x2F;start&quot;&gt;OpenWrt quick start&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When installing Luci applications (any package with a name starting with &lt;code&gt;luci-app-&lt;&#x2F;code&gt;), you may need to logout and log
back in if the expected menu entries don&#x27;t show up at first.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;restrict-ssh-access-to-the-local-network-lan&quot;&gt;Restrict SSH access to the local network (LAN)&lt;a class=&quot;zola-anchor&quot; href=&quot;#restrict-ssh-access-to-the-local-network-lan&quot; aria-label=&quot;Anchor link for: restrict-ssh-access-to-the-local-network-lan&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;First things first, let&#x27;s lockdown the SSH server (OpenWrt uses &amp;quot;dropbear&amp;quot; by default) so that it only listens
on local network. By default, it listens on all interfaces, which &lt;em&gt;includes&lt;&#x2F;em&gt; the WAN&#x2F;internet interface. This means
that anyone on the web could potentially log into your router if they knew your IP address. They&#x27;d likely have to brute
force your admin password (you &lt;em&gt;did&lt;&#x2F;em&gt; set one right?), unless you locked down the SSH server to use public key
authentication.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, I don&#x27;t want to given the public internet the option of logging into my device. I have no personal need to
access my router when I&#x27;m away from home, so let&#x27;s shut it down entirely.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note: The OpenWrt firewall does not open the SSH ports in the WAN zone by default, so the risk is low here. But this
extra layer of security never hurts.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;method-1-uci&quot;&gt;Method 1 (uci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-1-uci&quot; aria-label=&quot;Anchor link for: method-1-uci&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;SSH into your router (likely something like &lt;code&gt;ssh root@192.168.1.1&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Type the following to configure dropbear to only listen on the local lan:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;uci set dropbear.@dropbear&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.Interface=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;lan&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;uci commit dropbear
&lt;&#x2F;span&gt;&lt;span&gt;service dropbear restart 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;method-2-luci&quot;&gt;Method 2 (Luci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-2-luci&quot; aria-label=&quot;Anchor link for: method-2-luci&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Login to Luci (open your browser and go to &lt;code&gt;http:&#x2F;&#x2F;192.168.1.1&lt;&#x2F;code&gt;, enter your password)&lt;&#x2F;li&gt;
&lt;li&gt;Navigate to &lt;code&gt;System -&amp;gt; Administration -&amp;gt; SSH Access&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Select &lt;code&gt;LAN&lt;&#x2F;code&gt; from the &lt;code&gt;Interface&lt;&#x2F;code&gt; menu.&lt;&#x2F;li&gt;
&lt;li&gt;Click &lt;code&gt;Save and Apply&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Go to &lt;code&gt;System -&amp;gt; Startup&lt;&#x2F;code&gt; and click the &lt;code&gt;Restart&lt;&#x2F;code&gt; button next to dropbear.&lt;&#x2F;li&gt;
&lt;li&gt;Note: Luci may actually restart dropbear for us, so this last step might be unnecessary.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;67b139f9c04b6dbd00.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;67b139f9c04b6dbd00.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;Screenshot showing SSH Access tab with lan set in Interface option.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;67b139f9c04b6dbd00.png&quot; width=&quot;780&quot; height=&quot;464&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h2 id=&quot;restrict-luci-uhttpd-access-to-the-local-network-access-over-https&quot;&gt;Restrict Luci&#x2F;uhttpd access to the local network, access over HTTPS.&lt;a class=&quot;zola-anchor&quot; href=&quot;#restrict-luci-uhttpd-access-to-the-local-network-access-over-https&quot; aria-label=&quot;Anchor link for: restrict-luci-uhttpd-access-to-the-local-network-access-over-https&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Just like SSH&#x2F;dropbear, the Luci web interface (uhttpd server) exposes itself to the public web by default.&lt;&#x2F;p&gt;
&lt;p&gt;Assuming you have no need to login to your router when away from home, let&#x27;s lock it down to only
be accessible on the local network.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note: The OpenWrt firewall does not open the HTTP&#x2F;HTTPS ports in the WAN zone by default, so the risk is low here. But this
extra layer of security never hurts.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-user&#x2F;services&#x2F;webserver&#x2F;uhttpd#securing_uhttpd&quot;&gt;OpenWrt Wiki reference for &#x27;Securing uHTTPd&#x27;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;method-1-uci-1&quot;&gt;Method 1 (uci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-1-uci-1&quot; aria-label=&quot;Anchor link for: method-1-uci-1&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Listen to local LAN IPs and enable HTTP to HTTPS redirects.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;lib&#x2F;functions&#x2F;network.sh
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Load the list of ipv4&#x2F;ipv6 addresses into local variables for easily handling.
&lt;&#x2F;span&gt;&lt;span&gt;network_get_ipaddrs ip4addrs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;lan&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;network_get_ipaddrs6 ip6addrs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;lan&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;uci delete uhttpd.main.listen_http
&lt;&#x2F;span&gt;&lt;span&gt;uci delete uhttpd.main.listen_https
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; ip4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;$ip4addrs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;; do
&lt;&#x2F;span&gt;&lt;span&gt;    uci add_list uhttpd.main.listen_http=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;$ip4:80&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    uci add_list uhttpd.main.listen_https=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;$ip4:443&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;done
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; ip6 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;$ip6addrs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;; do
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Only add the link local&#x2F;ULA IPV6 address, which starts with an &amp;#39;f&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;[ &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;-n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;$ip6&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;grep &amp;#39;^f&amp;#39;)&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;$ip6 starts with f&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        uci add_list uhttpd.main.listen_http=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;[$ip6]:80&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        uci add_list uhttpd.main.listen_https=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;[$ip6]:443&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;done
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# (Optional) Ensure that we use&#x2F;redirect to HTTPS always
&lt;&#x2F;span&gt;&lt;span&gt;uci set uhttpd.main.redirect_https=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;1&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;uci commit uhttpd
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;service uhttpd restart
&lt;&#x2F;span&gt;&lt;span&gt;service uhttpd enable
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note: This sets up the uhttpd to listen on the link-local&#x2F;ULA IPV6 address as well. The OpenWrt documentation (linked
above) suggests disabling the IPV6 address completely.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Do whatever suits your preferences. Listening to the local IPV6 address doesn&#x27;t seem like a risk to me. Listening to the
&lt;strong&gt;global&lt;&#x2F;strong&gt; IPV6 address would be more of a concern but we&#x27;re not doing that here.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;method-2-luci-1&quot;&gt;Method 2 (Luci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-2-luci-1&quot; aria-label=&quot;Anchor link for: method-2-luci-1&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Install the &lt;code&gt;luci-app-uhttpd&lt;&#x2F;code&gt; package.&lt;&#x2F;li&gt;
&lt;li&gt;Go to &lt;code&gt;Services -&amp;gt; uHTTPd&lt;&#x2F;code&gt; page.&lt;&#x2F;li&gt;
&lt;li&gt;Fill in the HTTP and HTTPS listener sections with IPv4 and IPv6 addresses.
&lt;ol&gt;
&lt;li&gt;You can set the IPv4 address to just &lt;code&gt;192.168.1.1&lt;&#x2F;code&gt; or whatever you&#x27;ve configured your router&#x27;s LAN IP to be.&lt;&#x2F;li&gt;
&lt;li&gt;Make sure to use brackets to surround the IPv6 addresses and add the port number at the end, like
&lt;code&gt;[fd88:38bc:dd39::1]:443&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) Click the &lt;code&gt;Redirect all HTTP to HTTPS&lt;&#x2F;code&gt; checkbox if you want to use HTTPS with a self-signed certificate.&lt;&#x2F;li&gt;
&lt;li&gt;Click &lt;code&gt;Save and Apply&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;98c2ea51562e534c00.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;98c2ea51562e534c00.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;Menu showing the addresses uhttpd is listening on.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;98c2ea51562e534c00.png&quot; width=&quot;780&quot; height=&quot;317&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h2 id=&quot;bcp38&quot;&gt;BCP38&lt;a class=&quot;zola-anchor&quot; href=&quot;#bcp38&quot; aria-label=&quot;Anchor link for: bcp38&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This is less about protecting your router and more about preventing your network&#x27;s contribution to some types of DoS&#x2F;DDoS attack.&lt;&#x2F;p&gt;
&lt;p&gt;For more info I highly recommend the &lt;a href=&quot;http:&#x2F;&#x2F;www.bcp38.info&#x2F;index.php&#x2F;Main_Page&quot;&gt;BCP38 info website&lt;&#x2F;a&gt; which explains the
root problem quite well.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;method-1-uci-2&quot;&gt;Method 1 (uci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-1-uci-2&quot; aria-label=&quot;Anchor link for: method-1-uci-2&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Install the &lt;code&gt;bcp38&lt;&#x2F;code&gt; package.&lt;&#x2F;li&gt;
&lt;li&gt;Run the following &lt;code&gt;uci&lt;&#x2F;code&gt; commands&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;uci set bcp38.@bcp38&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.enabled=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;1&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci set bcp38.@bcp38&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.interface=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;wan&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;#Adjust to match your WAN port - may be something like eth0.2 for example.
&lt;&#x2F;span&gt;&lt;span&gt;uci commit bcp38 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;service bcp38 restart
&lt;&#x2F;span&gt;&lt;span&gt;service bcp38 enable
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;method-2-luci-2&quot;&gt;Method 2 (Luci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-2-luci-2&quot; aria-label=&quot;Anchor link for: method-2-luci-2&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Install the &lt;code&gt;luci-app-bcp38&lt;&#x2F;code&gt; package.&lt;&#x2F;li&gt;
&lt;li&gt;Navigate to &lt;code&gt;Network -&amp;gt; Firewall -&amp;gt; BCP38&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Click the checkbox to enable.&lt;&#x2F;li&gt;
&lt;li&gt;Select the interfaces that pertains to your WAN (likely labeled &lt;code&gt;wan,wan6&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Click &lt;code&gt;Save and Apply&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;f4dfdfc1eacc665d00.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;f4dfdfc1eacc665d00.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;Image of BCP38 firewall settings with Enabled checked and the interface set to wan&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;f4dfdfc1eacc665d00.png&quot; width=&quot;780&quot; height=&quot;330&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h2 id=&quot;banip&quot;&gt;banIP&lt;a class=&quot;zola-anchor&quot; href=&quot;#banip&quot; aria-label=&quot;Anchor link for: banip&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s highly recommended to install and configure banIP using Luci as the core configuration is a little verbose when
done from the commandline. I say that, but I&#x27;ve been configuring it from the commandline for a while now, so feel free
to copy-paste my configuration below - it should work well.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note: This package recommends that your router has at least 128MB of RAM.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openwrt&#x2F;packages&#x2F;blob&#x2F;master&#x2F;net&#x2F;banip&#x2F;files&#x2F;README.md&quot;&gt;banIP project page&#x2F;documentation&lt;&#x2F;a&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;forum.openwrt.org&#x2F;t&#x2F;banip-support-thread&#x2F;16985&quot;&gt;banIP Support Thread&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;method-1-uci-3&quot;&gt;Method 1 (uci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-1-uci-3&quot; aria-label=&quot;Anchor link for: method-1-uci-3&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Install the &lt;code&gt;banip&lt;&#x2F;code&gt; package.&lt;&#x2F;li&gt;
&lt;li&gt;Enable, and configure a core set of blocklists:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;uci set banip.global.ban_enabled=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;1&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci set banip.global.ban_trigger=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;wan&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;#Configure to your proper WAN interface, eg. &amp;#39;eth0.2&amp;#39; or &amp;#39;wan&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci delete banip.global.ban_sources
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;darklist&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;debl&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;drop&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;feodo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;firehol1&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;greensnow&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;iblockads&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;iblockspy&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;myip&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;nixspam&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;proxy&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;sslbl&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;talos&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;threat&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;tor&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;uceprotect1&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;uci add_list banip.global.ban_sources=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;yoyo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Allowlist a few sites that I&amp;#39;ve seen some blocklists break before.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;enro.com&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;etc&#x2F;banip&#x2F;banip.whitelist
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;www.reddit.com&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;etc&#x2F;banip&#x2F;banip.whitelist
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;yelp.com&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;etc&#x2F;banip&#x2F;banip.whitelist
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;uci commit banip
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;service banip restart
&lt;&#x2F;span&gt;&lt;span&gt;service banip enable
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This enables banIP with a set of blocklists that I recommend. The &lt;code&gt;iblockads&lt;&#x2F;code&gt; and &lt;code&gt;yoyo&lt;&#x2F;code&gt; lists specifically target ads,
and may be redundant depending on your networking setup (like if you&#x27;re running PiHole or AdguardHome), but they can
help regardless. I &lt;em&gt;have&lt;&#x2F;em&gt; seen some false positives come out of &lt;code&gt;iblockads&lt;&#x2F;code&gt; so be sure to use the whitelist
functionality if you notice any breakages, or just disable its use completely.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;bonus-setup-cronjob-to-refresh-blocklists&quot;&gt;Bonus - setup cronjob to refresh blocklists&lt;a class=&quot;zola-anchor&quot; href=&quot;#bonus-setup-cronjob-to-refresh-blocklists&quot; aria-label=&quot;Anchor link for: bonus-setup-cronjob-to-refresh-blocklists&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;I recommend refreshing the blocklists every 24 hours. Here&#x27;s an example of how to configure a cronjob to run once a day:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;crontab - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;&amp;lt;EOF
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;15 07 * * * &#x2F;etc&#x2F;init.d&#x2F;banip reload
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;NOTE: This OVERWRITES your existing crontab. If you already have other cronjobs, either edit the crontab manually or
add them to this command as appropriate.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;method-2-luci-3&quot;&gt;Method 2 (Luci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-2-luci-3&quot; aria-label=&quot;Anchor link for: method-2-luci-3&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;luci-app-banip&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Navigate to &lt;code&gt;Services -&amp;gt; banIP&lt;&#x2F;code&gt;. &lt;&#x2F;li&gt;
&lt;li&gt;You can leave most settings at default (banIP autodetection is pretty good), but you&#x27;ll need to both enable banIP and
configure blocklists directly.&lt;&#x2F;li&gt;
&lt;li&gt;Enable banIP - just check the &lt;code&gt;Enabled&lt;&#x2F;code&gt; box on the &lt;code&gt;General Settings&lt;&#x2F;code&gt; tab.&lt;&#x2F;li&gt;
&lt;li&gt;Configure blocklists - go to the &lt;code&gt;Blocklist Sources&lt;&#x2F;code&gt; tab and use the &lt;code&gt;Sources&lt;&#x2F;code&gt; tab to select your desired lists. You
can see an example of the lists I personally use in the command used in &lt;strong&gt;Method 1&lt;&#x2F;strong&gt; above.&lt;&#x2F;li&gt;
&lt;li&gt;Click &lt;code&gt;Save and Apply&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Enabling banIP:&lt;&#x2F;p&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;fd0934531540e4c800.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;fd0934531540e4c800.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;BanIP plugin page with the Enabled box checked.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;fd0934531540e4c800.png&quot; width=&quot;780&quot; height=&quot;251&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;p&gt;Configuring blocklists:&lt;&#x2F;p&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;96e0d481f20392e100.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;96e0d481f20392e100.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;BanIP plugin page displaying blocklist settings.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;96e0d481f20392e100.png&quot; width=&quot;780&quot; height=&quot;290&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h4 id=&quot;bonus-setup-cronjob-to-refresh-blocklists-1&quot;&gt;Bonus - setup cronjob to refresh blocklists&lt;a class=&quot;zola-anchor&quot; href=&quot;#bonus-setup-cronjob-to-refresh-blocklists-1&quot; aria-label=&quot;Anchor link for: bonus-setup-cronjob-to-refresh-blocklists-1&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Just like &lt;strong&gt;Method 1&lt;&#x2F;strong&gt;, its possible to setup a cronjob to refresh the blocklists.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;code&gt;Refresh Timer&lt;&#x2F;code&gt; button on the main status page.&lt;&#x2F;li&gt;
&lt;li&gt;Set the action to &lt;code&gt;reload&lt;&#x2F;code&gt; (not &amp;quot;refresh&amp;quot;, confusing I know...)&lt;&#x2F;li&gt;
&lt;li&gt;Pick an hour in the 0-23 time range that works for you.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Here&#x27;s an example of my own configuration:&lt;&#x2F;p&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;8ab35026d9bbfd9f00.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;8ab35026d9bbfd9f00.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;Menu dialog showing refresh timer configuration.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;8ab35026d9bbfd9f00.png&quot; width=&quot;780&quot; height=&quot;835&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h2 id=&quot;disable-or-remove-upnp&quot;&gt;Disable or remove UPNP&lt;a class=&quot;zola-anchor&quot; href=&quot;#disable-or-remove-upnp&quot; aria-label=&quot;Anchor link for: disable-or-remove-upnp&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;If you aren&#x27;t using UPNP (a service to automatically punch holes in your firewall...), you should disable it completely,
and&#x2F;or remove the package completely.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;Services -&amp;gt; UPnP&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Uncheck the &lt;code&gt;Start UPnP and NAT-PMP service&lt;&#x2F;code&gt; checkbox.&lt;&#x2F;li&gt;
&lt;li&gt;Save and Apply.&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) Navigate to &lt;code&gt;System -&amp;gt; Startup&lt;&#x2F;code&gt; and stop + disable the &lt;code&gt;upnp&lt;&#x2F;code&gt; (or &lt;code&gt;miniupnp&lt;&#x2F;code&gt;) service.&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) Remove the package completely using the &lt;code&gt;System -&amp;gt; Software&lt;&#x2F;code&gt; menu or &lt;code&gt;opkg --autoremove remove luci-app-upnp&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;firewall-drop-external-connections&quot;&gt;Firewall DROP external connections&lt;a class=&quot;zola-anchor&quot; href=&quot;#firewall-drop-external-connections&quot; aria-label=&quot;Anchor link for: firewall-drop-external-connections&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;By default the OpenWrt firewall configuration is kinda &amp;quot;noisy&amp;quot; in how it rejects traffic from the global internet.&lt;&#x2F;p&gt;
&lt;p&gt;You can see this in action by using Steve Gibson&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.grc.com&#x2F;shieldsup&quot;&gt;ShieldsUP tool&lt;&#x2F;a&gt;. Click on the
&lt;code&gt;Proceed&lt;&#x2F;code&gt; buton and then use the &lt;code&gt;Common Ports&lt;&#x2F;code&gt; or &lt;code&gt;All Service Ports&lt;&#x2F;code&gt; buttons to scan your whole router. The buttons
are kind of hard to see, I admit, but they should be there.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s configure the firewall to silently drop all external connections instead of gracefully telling them &amp;quot;no thank
you&amp;quot;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;method-1-uci-4&quot;&gt;Method 1 (uci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-1-uci-4&quot; aria-label=&quot;Anchor link for: method-1-uci-4&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# Note: I&amp;#39;M ASSUMING THAT THE LAST ZONE IS THE WAN ZONE. THIS BREAKS IF THE WAN ZONE IS ON A DIFFERENT ZONE NUMBER.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;# A little safety check - only try and set the input DROP on WAN. Skip&#x2F;bail if the last interface isn&amp;#39;t the WAN.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;[ &lt;&#x2F;span&gt;&lt;span&gt;$(uci get firewall.@zone&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;-1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.name) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;wan&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;Locking down firewall&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    uci set firewall.@zone&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;-1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.input=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;DROP&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    uci set firewall.@zone&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;-1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.forward=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;DROP&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    uci commit firewall
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    service firewall restart
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;method-2-luci-4&quot;&gt;Method 2 (Luci)&lt;a class=&quot;zola-anchor&quot; href=&quot;#method-2-luci-4&quot; aria-label=&quot;Anchor link for: method-2-luci-4&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;Network -&amp;gt; Firewall&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Under &lt;code&gt;Zones&lt;&#x2F;code&gt;, set the &lt;code&gt;wan =&amp;gt; REJECT&lt;&#x2F;code&gt; zone to &lt;code&gt;drop&lt;&#x2F;code&gt; (instead of the default &lt;code&gt;reject&lt;&#x2F;code&gt;) on both &lt;code&gt;Input&lt;&#x2F;code&gt; and &lt;code&gt;Forward&lt;&#x2F;code&gt;
using the associated dropdowns.&lt;&#x2F;li&gt;
&lt;li&gt;Click &lt;code&gt;Save and Apply&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;7992970695e6853000.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;7992970695e6853000.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;Screenshot showing the firewall zone settings, with input and forward set to drop.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;7992970695e6853000.png&quot; width=&quot;780&quot; height=&quot;149&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Hopefully this helps secure your home router just a little bit more. OpenWrt is already significantly more secure than
the standard firmware that ships from the factory for most routers, but these tweaks should lock it down to the utmost
degree.&lt;&#x2F;p&gt;
&lt;p&gt;A few other references that may be helpful:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-user&#x2F;luci&#x2F;luci.secure&quot;&gt;Accessing LuCI web interface securely - OpenWrt wiki&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-user&#x2F;security&#x2F;secure.access&quot;&gt;Secure your routers access - OpenWrt wiki&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Precompressed Assets with Caddy</title>
		<published>2021-05-15T00:00:00+00:00</published>
		<updated>2021-05-15T00:00:00+00:00</updated>
		<link href="https://austindw.com/precompressed-assets-caddy/" type="text/html"/>
		<id>https://austindw.com/precompressed-assets-caddy/</id>
		<content type="html">&lt;p&gt;Serving precompressed assets with &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt; has historically required
some configuration gymnastics.&lt;&#x2F;p&gt;
&lt;p&gt;A good example can be found in a &lt;a href=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;faster-website&#x2F;#updating-caddy-to-serve-pre-compressed-assets&quot;&gt;previous post&lt;&#x2F;a&gt;
of mine.&lt;&#x2F;p&gt;
&lt;p&gt;That all changes in &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;caddyserver&#x2F;caddy&#x2F;releases&#x2F;tag&#x2F;v2.4.0&quot;&gt;Caddy 2.4.0&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;native-precompressed-asset-serving&quot;&gt;Native Precompressed Asset Serving&lt;a class=&quot;zola-anchor&quot; href=&quot;#native-precompressed-asset-serving&quot; aria-label=&quot;Anchor link for: native-precompressed-asset-serving&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;As seen in the above-linked 2.4.0 release notes, Caddy added support for serving &amp;quot;precompressed sidecar files&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, they fail to point to a more useful section of their documentation that actually describes how to 
configure Caddy to serve said assets.&lt;&#x2F;p&gt;
&lt;p&gt;The real documentation lies under their &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;caddyfile&#x2F;directives&#x2F;file_server&quot;&gt;&lt;code&gt;file_server&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
directive.&lt;&#x2F;p&gt;
&lt;p&gt;If you want the TL;DR version, here you go:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;file_server {
&lt;&#x2F;span&gt;&lt;span&gt;    precompressed br zstd gzip
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above will handle an incoming request for an asset by analyzing the &lt;code&gt;Accept-Encoding&lt;&#x2F;code&gt; header provided by
the client (browser) and searching for files ending in &lt;code&gt;.br&lt;&#x2F;code&gt;, &lt;code&gt;.zst&lt;&#x2F;code&gt;, and &lt;code&gt;.gz&lt;&#x2F;code&gt;, respectively.&lt;&#x2F;p&gt;
&lt;p&gt;And yes, the order that you specify in the &lt;code&gt;precompressed&lt;&#x2F;code&gt; field &lt;strong&gt;does&lt;&#x2F;strong&gt; matter, so pick wisely. If you aren&#x27;t sure,
just use what I have above. Once Zstandard has widespread browser adoption (it doesn&#x27;t yet), and established
dictionaries for compressing HTML&#x2F;CSS&#x2F;JS, then it will make more sense to prioritize &lt;code&gt;zstd&lt;&#x2F;code&gt; before &lt;code&gt;br&lt;&#x2F;code&gt; (Brotli
compression). But we&#x27;re unfortunately a few years out from then.&lt;&#x2F;p&gt;
&lt;p&gt;Note that this feature works wonderfully with &lt;code&gt;file_server&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;index&lt;&#x2F;code&gt; attribute. This means that if you use
&amp;quot;clean urls&amp;quot; (without an ending &lt;code&gt;index.html&lt;&#x2F;code&gt; for example, like &lt;code&gt;https:&#x2F;&#x2F;austindw.com&#x2F;precompressed-assets-caddy&#x2F;&lt;&#x2F;code&gt;),
precompressing your &lt;code&gt;index.html&lt;&#x2F;code&gt; files and serving them with this option will work correctly. This required extra
configuration to get right using the old way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;before-and-after&quot;&gt;Before and After&lt;a class=&quot;zola-anchor&quot; href=&quot;#before-and-after&quot; aria-label=&quot;Anchor link for: before-and-after&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Just to provide some context on why this is such a nice improvement let&#x27;s look at the old configuration compared to the new
configuration.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;before&quot;&gt;Before&lt;a class=&quot;zola-anchor&quot; href=&quot;#before&quot; aria-label=&quot;Anchor link for: before&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;example.com {
&lt;&#x2F;span&gt;&lt;span&gt;    root * &#x2F;path&#x2F;to&#x2F;dir
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    file_server
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    ### Precompression support
&lt;&#x2F;span&gt;&lt;span&gt;	@brotli {
&lt;&#x2F;span&gt;&lt;span&gt;	header Accept-Encoding *br*
&lt;&#x2F;span&gt;&lt;span&gt;	  file {
&lt;&#x2F;span&gt;&lt;span&gt;	    try_files {path}.br {path}&#x2F;index.html.br {path}.html.br
&lt;&#x2F;span&gt;&lt;span&gt;	  }
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	handle @brotli {
&lt;&#x2F;span&gt;&lt;span&gt;	  header {
&lt;&#x2F;span&gt;&lt;span&gt;	    Content-Encoding br
&lt;&#x2F;span&gt;&lt;span&gt;	    Content-Type text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;	  }
&lt;&#x2F;span&gt;&lt;span&gt;	  rewrite {http.matchers.file.relative}
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@gzip {
&lt;&#x2F;span&gt;&lt;span&gt;	  header Accept-Encoding *gzip*
&lt;&#x2F;span&gt;&lt;span&gt;	  file {
&lt;&#x2F;span&gt;&lt;span&gt;	    try_files {path}.gz {path}&#x2F;index.html.gz {path}.html.gz
&lt;&#x2F;span&gt;&lt;span&gt;	  }
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	handle @gzip {
&lt;&#x2F;span&gt;&lt;span&gt;	  header {
&lt;&#x2F;span&gt;&lt;span&gt;	    Content-Encoding gzip
&lt;&#x2F;span&gt;&lt;span&gt;	    Content-Type text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;	  }
&lt;&#x2F;span&gt;&lt;span&gt;	  rewrite {http.matchers.file.relative}
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@html {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.html *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @html {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@css {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.css
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @css {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type text&#x2F;css
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@js {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.js
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @js {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type text&#x2F;javascript
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@svg {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.svg
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @svg {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type image&#x2F;svg+xml
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@xml {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.xml
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @xml {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type application&#x2F;xml
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@json {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.json
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @json {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type application&#x2F;json
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;after&quot;&gt;After&lt;a class=&quot;zola-anchor&quot; href=&quot;#after&quot; aria-label=&quot;Anchor link for: after&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;example.com {
&lt;&#x2F;span&gt;&lt;span&gt;    root * &#x2F;path&#x2F;to&#x2F;dir
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    file_server {
&lt;&#x2F;span&gt;&lt;span&gt;        precompressed br zstd gzip
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pretty dope improvement, no?&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s all for today - go forth and precompress.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Load Testing for Fun and Profit</title>
		<published>2021-04-04T00:00:00+00:00</published>
		<updated>2021-04-04T00:00:00+00:00</updated>
		<link href="https://austindw.com/load-testing-fun-profit/" type="text/html"/>
		<id>https://austindw.com/load-testing-fun-profit/</id>
		<content type="html">&lt;p&gt;I&#x27;ve been doing a lot of load testing at work recently, using an internal load generation and measurement tool.&lt;&#x2F;p&gt;
&lt;p&gt;Since I seem to be so obsessed with making this &lt;a href=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;faster-website&#x2F;&quot;&gt;website faster&lt;&#x2F;a&gt;, I decided to run some
numbers to get an idea of its true performance.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;a-little-context&quot;&gt;A little context&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-little-context&quot; aria-label=&quot;Anchor link for: a-little-context&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Let me start by saying that load testing is an imperfect science. The tests that I&#x27;m going to detail today
don&#x27;t properly represent the real-world user experience of someone actually navigating around this website. There are
lots of other factors that impact said user&#x27;s percieved performance on this site, including their browser, my
Cache-Control headers, their proximity in the world relative to my server location, the list goes on.&lt;&#x2F;p&gt;
&lt;p&gt;But these tests &lt;em&gt;do&lt;&#x2F;em&gt; provide a general idea of this website&#x27;s max requests (or transactions) per second (TPS), or
roughly how many people can access the home page at a time.&lt;&#x2F;p&gt;
&lt;p&gt;This not only measures the relative speed at which a user loads my website, but also provides a
realistic expectation of how my site will perform if it ever blows up on Hacker News, for example.&lt;&#x2F;p&gt;
&lt;p&gt;It should be noted that a better measurement of the perceived user experience speed can be found with a tool like
&lt;a href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;speed&#x2F;pagespeed&#x2F;insights&#x2F;&quot;&gt;PageSpeed&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tool&quot;&gt;The tool&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-tool&quot; aria-label=&quot;Anchor link for: the-tool&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Since I&#x27;m not at work, I decided to use a more rudimentary (but still quite good) load testing tool called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wg&#x2F;wrk&quot;&gt;wrk&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s right, I&#x27;m not at work, so I do wrk... eghm.&lt;&#x2F;p&gt;
&lt;p&gt;Wrk let&#x27;s me configure the number of threads, connections, duration, and headers with which to hit my server, &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&quot;&gt;Caddy&lt;&#x2F;a&gt;.
Since I can specify different headers, I can use the &lt;code&gt;Accept-Encoding&lt;&#x2F;code&gt; header to tune which version of my home page I
want Caddy to serve, meaning the raw HTML, a gzip compressed version, or a Brotli compressed version.&lt;&#x2F;p&gt;
&lt;p&gt;As explained in this &lt;a href=&quot;https:&#x2F;&#x2F;engineering.appfolio.com&#x2F;appfolio-engineering&#x2F;2019&#x2F;4&#x2F;21&#x2F;wrk-it-my-experiences-load-testing-with-an-interesting-new-tool&quot;&gt;delightful post&lt;&#x2F;a&gt;,
wrk&#x27;s use of threads + connections means that the total number of connections as specified on the commandline are split
up evenly across the total number of threads specified on the commandline.&lt;&#x2F;p&gt;
&lt;p&gt;For example, if I used 75 connections with 25 threads, this means that each thread would handle responses for 3
connections. &lt;&#x2F;p&gt;
&lt;p&gt;In my case, with a little trial and error, I tweaked my connections and threads until I had a stable benchmark that
saturated my 100 megabit home internet connection.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tests&quot;&gt;The tests&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-tests&quot; aria-label=&quot;Anchor link for: the-tests&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Like I mentioned above, I ran three test runs for each &amp;quot;version&amp;quot; of my home page. One test for the uncompressed
HTML, and then two more tests for the gzip and Brotli compressed assets, respectively. I say &amp;quot;version&amp;quot;, because I
tweaked my static site generator to also produce a minified version of my home page, and then ran three more tests
against that.&lt;&#x2F;p&gt;
&lt;p&gt;I wish I could leave HTML minification on full time, but alas, a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&#x2F;issues&#x2F;1300&quot;&gt;bug in Zola&#x27;s minification dependency&lt;&#x2F;a&gt; causes
my &lt;code&gt;&amp;lt;code&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;lt;pre&amp;gt;&lt;&#x2F;code&gt; blocks to collapse to a single line.&lt;&#x2F;p&gt;
&lt;p&gt;Once a new version of Zola is out with the fixed dependency, I&#x27;ll definitely be upgrading and activing HTML minification.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-results&quot;&gt;The results&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-results&quot; aria-label=&quot;Anchor link for: the-results&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Okay, enough talking, let&#x27;s get to the data.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;test-setup&quot;&gt;Test Setup&lt;a class=&quot;zola-anchor&quot; href=&quot;#test-setup&quot; aria-label=&quot;Anchor link for: test-setup&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Download speed of home connection, measured using &lt;code&gt;speedtest&lt;&#x2F;code&gt; CLI: &lt;code&gt;12.57 MB&#x2F;s&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Latency, as measured in same speed test: &lt;code&gt;15.78 ms&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;CPU (load test host): &lt;code&gt;Ryzen ThreadRipper 3960x (24c&#x2F;48t), performance governor activated&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Mem (load test host): &lt;code&gt;64GB 3600Mhz DDR4&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;CPU (web server): &lt;code&gt;Intel(R) Xeon(R) Gold 6140 CPU @ 2.30GHz&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Mem (web server): &lt;code&gt;989MB&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;All compressed &#x2F; minified assets are compressed or minified offline, meaning that the server is doing no extra work.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The web server is hosted on a cheap $5.00&#x2F;month, 1GB&#x2F;1CPU, 25GB SSD, 1000GB transfer droplet at DigitalOcean.&lt;&#x2F;p&gt;
&lt;p&gt;Tests were run for 5 minutes each, late at night on a quiet connection.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;commands&quot;&gt;Commands&lt;a class=&quot;zola-anchor&quot; href=&quot;#commands&quot; aria-label=&quot;Anchor link for: commands&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;wrk&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -t&lt;&#x2F;span&gt;&lt;span&gt; 25&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt; 75&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;  -d&lt;&#x2F;span&gt;&lt;span&gt; 300s&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --latency&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;austindw.com
&lt;&#x2F;span&gt;&lt;span&gt;wrk&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -t&lt;&#x2F;span&gt;&lt;span&gt; 25&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt; 125&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -d&lt;&#x2F;span&gt;&lt;span&gt; 300s&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --latency -H &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;Accept-Encoding: gzip&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;austindw.com
&lt;&#x2F;span&gt;&lt;span&gt;wrk&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -t&lt;&#x2F;span&gt;&lt;span&gt; 25&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span&gt; 125&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; -d&lt;&#x2F;span&gt;&lt;span&gt; 300s&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt; --latency -H &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;Accept-Encoding: br&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;austindw.com
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;data&quot;&gt;Data&lt;a class=&quot;zola-anchor&quot; href=&quot;#data&quot; aria-label=&quot;Anchor link for: data&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Metric&lt;&#x2F;th&gt;&lt;th&gt;raw HTML&lt;&#x2F;th&gt;&lt;th&gt;GZIP compressed&lt;&#x2F;th&gt;&lt;th&gt;Brotli compressed&lt;&#x2F;th&gt;&lt;th&gt;minified HTML&lt;&#x2F;th&gt;&lt;th&gt;minified + GZIP&lt;&#x2F;th&gt;&lt;th&gt;minified + Brotli&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Size (bytes)&lt;&#x2F;td&gt;&lt;td&gt;16781&lt;&#x2F;td&gt;&lt;td&gt;3712&lt;&#x2F;td&gt;&lt;td&gt;3002&lt;&#x2F;td&gt;&lt;td&gt;11108&lt;&#x2F;td&gt;&lt;td&gt;3374&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;2765&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Threads&lt;&#x2F;td&gt;&lt;td&gt;25&lt;&#x2F;td&gt;&lt;td&gt;25&lt;&#x2F;td&gt;&lt;td&gt;25&lt;&#x2F;td&gt;&lt;td&gt;25&lt;&#x2F;td&gt;&lt;td&gt;25&lt;&#x2F;td&gt;&lt;td&gt;25&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Connections&lt;&#x2F;td&gt;&lt;td&gt;75&lt;&#x2F;td&gt;&lt;td&gt;125&lt;&#x2F;td&gt;&lt;td&gt;125&lt;&#x2F;td&gt;&lt;td&gt;125&lt;&#x2F;td&gt;&lt;td&gt;125&lt;&#x2F;td&gt;&lt;td&gt;125&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Requests per sec&lt;&#x2F;td&gt;&lt;td&gt;752.82&lt;&#x2F;td&gt;&lt;td&gt;2963.38&lt;&#x2F;td&gt;&lt;td&gt;3193.88&lt;&#x2F;td&gt;&lt;td&gt;1130.91&lt;&#x2F;td&gt;&lt;td&gt;3070.17&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;3246.17&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Transfer per sec (MB)&lt;&#x2F;td&gt;&lt;td&gt;12.22&lt;&#x2F;td&gt;&lt;td&gt;11.27&lt;&#x2F;td&gt;&lt;td&gt;9.98 MB&lt;&#x2F;td&gt;&lt;td&gt;12.23&lt;&#x2F;td&gt;&lt;td&gt;10.69&lt;&#x2F;td&gt;&lt;td&gt;9.41&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;P50 (ms)&lt;&#x2F;td&gt;&lt;td&gt;98.34&lt;&#x2F;td&gt;&lt;td&gt;40.93&lt;&#x2F;td&gt;&lt;td&gt;37.61&lt;&#x2F;td&gt;&lt;td&gt;67.70&lt;&#x2F;td&gt;&lt;td&gt;38.90&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;37.39&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;P90 (ms)&lt;&#x2F;td&gt;&lt;td&gt;114.28&lt;&#x2F;td&gt;&lt;td&gt;52.35&lt;&#x2F;td&gt;&lt;td&gt;50.94&lt;&#x2F;td&gt;&lt;td&gt;74.82&lt;&#x2F;td&gt;&lt;td&gt;52.63&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;50.10&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;P99 (ms)&lt;&#x2F;td&gt;&lt;td&gt;151.74&lt;&#x2F;td&gt;&lt;td&gt;79.53&lt;&#x2F;td&gt;&lt;td&gt;75.61&lt;&#x2F;td&gt;&lt;td&gt;79.71&lt;&#x2F;td&gt;&lt;td&gt;83.91&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;70.37&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Web server CPU 5min load&lt;&#x2F;td&gt;&lt;td&gt;0.41&lt;&#x2F;td&gt;&lt;td&gt;0.74&lt;&#x2F;td&gt;&lt;td&gt;0.87&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;takeways&quot;&gt;Takeways&lt;a class=&quot;zola-anchor&quot; href=&quot;#takeways&quot; aria-label=&quot;Anchor link for: takeways&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;It should have been pretty obvious, but of course minifying and compressing HTML with Brotli results in the smallest
file sizes, and thus the fastest response times.&lt;&#x2F;p&gt;
&lt;p&gt;Being able to handle ~3200 users requesting my home page in a single second at $5&#x2F;month ain&#x27;t nothin&#x27; to sneeze at,
that&#x27;s for sure (and another reason why static site generators are just the best).&lt;&#x2F;p&gt;
&lt;p&gt;What &lt;em&gt;is&lt;&#x2F;em&gt; interesting is that the difference between GZIP and Brotli wasn&#x27;t as significant as I would have expected, but
looking at the 5min CPU load and how the &amp;quot;Transfer per sec&amp;quot; &lt;em&gt;dropped&lt;&#x2F;em&gt; as response sizes got smaller hints at why - my
server was starting to bottleneck on its single CPU core.&lt;&#x2F;p&gt;
&lt;p&gt;To confirm this, I ran another test with a raw text file containing the word &amp;quot;hello&amp;quot;, which measured at a total of 6
bytes. &lt;&#x2F;p&gt;
&lt;p&gt;The result? &lt;code&gt;4077.37&lt;&#x2F;code&gt; requests&#x2F;sec. &lt;&#x2F;p&gt;
&lt;p&gt;At first glance, this might seem like a big difference when compared against minified Brotli&#x27;s &lt;code&gt;3246&lt;&#x2F;code&gt; request&#x2F;sec. But
considering that the minified + Brotli compressed asset is 2765 bytes, or &lt;strong&gt;460x larger&lt;&#x2F;strong&gt; than the 6 byte text file, and
both results are within ~800 TPS of each other, it would appear that the CPU on my droplet (which was pegged at 100%
pretty much the whole time for both tests) is much more the culprit than the response size or my network speeds.&lt;&#x2F;p&gt;
&lt;p&gt;This means that I&#x27;d expect even better performance out of the minified + Brotli compressed assets with a beefier
CPU&#x2F;multi-core setup even if all other specs remained the same (network, memory, etc).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In summary, this website really &lt;em&gt;is&lt;&#x2F;em&gt; fast. Because science says so.&lt;&#x2F;p&gt;
&lt;p&gt;One thing I&#x27;ve learned after my 9+ years working in software, it&#x27;s always important to measure and thus validate your
assumptions. Before this, my website always &lt;em&gt;seemed&lt;&#x2F;em&gt; fast, but now I know I can easily handle over 3000 visitors &lt;em&gt;in a
single second&lt;&#x2F;em&gt;. This means I&#x27;ve got a lot of headroom on this blog before I&#x27;d need to worry about upgrading to a bigger
droplet.&lt;&#x2F;p&gt;
&lt;p&gt;Was this testing methodolgy perfect? No. Will this web server actually be able to handle 3000 visitors in one second?
Maybe. There&#x27;s a lot that can effect that answer, but these results are very much &amp;quot;good enough&amp;quot;, at least for now.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>This website is (slightly) faster</title>
		<published>2021-02-07T00:00:00+00:00</published>
		<updated>2021-05-15T00:00:00+00:00</updated>
		<link href="https://austindw.com/faster-website/" type="text/html"/>
		<id>https://austindw.com/faster-website/</id>
		<content type="html">&lt;p&gt;As many of you may be aware, the public internet is a bloated, Javascript-riddled mess.&lt;&#x2F;p&gt;
&lt;p&gt;If you don&#x27;t believe me, I&#x27;m not the &lt;a href=&quot;https:&#x2F;&#x2F;idlewords.com&#x2F;talks&#x2F;website_obesity.htm&quot;&gt;first one&lt;&#x2F;a&gt; to &lt;a href=&quot;https:&#x2F;&#x2F;danluu.com&#x2F;web-bloat&#x2F;&quot;&gt;talk about
this&lt;&#x2F;a&gt;. And I certainly won&#x27;t be the last...&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;d think with how much internet speeds have increased in the past 20 years, particularly
when compared to the dialup internet that many of us may have grown up with, we&#x27;d be loading
every website with blinding speeds. But that&#x27;s just not the case, now is it?&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a multitude of reasons for this, including things like advertising, JavaScript, tracking pixels, the list goes
on...&lt;&#x2F;p&gt;
&lt;p&gt;Today, I&#x27;m going to talk about a much smaller piece of this pie - the actual size of the HTML document you&#x27;re reading,
and how it gets delivered to your browser.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;background&quot;&gt;Background.&lt;a class=&quot;zola-anchor&quot; href=&quot;#background&quot; aria-label=&quot;Anchor link for: background&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s get some quick background.&lt;&#x2F;p&gt;
&lt;p&gt;When you point your browser at my website, you kick off a 3 step proccess. I&#x27;m hand waving some things here (like TCP
connections and TLS handshakes), so just roll with it if you&#x27;re more technically inclined.&lt;&#x2F;p&gt;
&lt;p&gt;Steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Browser makes a request to the server, while also specifying what types of content encoding it can accept.&lt;&#x2F;li&gt;
&lt;li&gt;The server receives the request, analyzes that list of allowed content encodings, and then finds the requested asset
(think an HTML web page or CSS stylesheet).&lt;&#x2F;li&gt;
&lt;li&gt;Having found the asset, the server makes sure it can &amp;quot;fit&amp;quot; into the desired content encoding specified by the
browser, and may take steps to optimize the target asset for a particular content encoding.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Now, when I say &amp;quot;content encoding&amp;quot; here, I&#x27;m really meaning &amp;quot;compression&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Specifically, many web servers support serving content using &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Gzip&quot;&gt;gzip&lt;&#x2F;a&gt; compression.
This is an old standard, works pretty well for text data, is relatively fast for a web server to do on the fly, and
&amp;quot;just works&amp;quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, it&#x27;s not guaranteed that you receive a gzip-compressed blob of HTMl for every website your visit. It depends on
your browser and the web server configuration.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;so-why-is-this-website-faster&quot;&gt;So why is this website &amp;quot;faster&amp;quot;?&lt;a class=&quot;zola-anchor&quot; href=&quot;#so-why-is-this-website-faster&quot; aria-label=&quot;Anchor link for: so-why-is-this-website-faster&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Because I made my compression &amp;quot;more better&amp;quot;. Yeah, I said it.&lt;&#x2F;p&gt;
&lt;p&gt;More &lt;del&gt;better&lt;&#x2F;del&gt; specifically, I optimized 3 key aspects of how my website assets are compressed:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Utilized a better gzip compressor known as &lt;a href=&quot;https:&#x2F;&#x2F;blog.codinghorror.com&#x2F;zopfli-optimization-literally-free-bandwidth&#x2F;&quot;&gt;Zopfli&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Added &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Brotli&quot;&gt;Brotli&lt;&#x2F;a&gt;, an even more efficient compression algorithm than gzip.&lt;&#x2F;li&gt;
&lt;li&gt;Compressed all assets &lt;strong&gt;before&lt;&#x2F;strong&gt; the web server ever sees them, meaning less work for it to do.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;To be clear, I was already using compression via Caddy&#x27;s &lt;code&gt;encode gzip zstd&lt;&#x2F;code&gt; option, but that requires all compression to
be done on the fly (and thus repeated for every duplicate request), doesn&#x27;t support Brotli, and uses a sub-par gzip
compression algorithm (when compared to Zopfli).&lt;&#x2F;p&gt;
&lt;p&gt;In summary, I&#x27;m increasing existing compression, utilizing more advanced compression, and pre-compressing all of my
pertinent text-related assets of this website (things like HTML, CSS, and even SVG images, if I had any...).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;great-so-how-did-you-do-this&quot;&gt;Great, so how did you do this?&lt;a class=&quot;zola-anchor&quot; href=&quot;#great-so-how-did-you-do-this&quot; aria-label=&quot;Anchor link for: great-so-how-did-you-do-this&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;It all kind of started when I got a little frustrated with my web server, &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;Now to be clear, Caddy is an excellent web server. I just wanted to replicate an existing setup I had on my old nginx
server where I pre-compressed a number of assets before uploading them.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d looked at doing this a few times over the past year, but ran into a few roadblocks along the way, including:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Older versions of Caddy (v1) made this easy, but this feature was removed in a large rewrite for v2, which is what I
use.&lt;&#x2F;li&gt;
&lt;li&gt;It was theoretically possible using their new configuration syntax, but no one had fully put the puzzel pieces
together yet.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Luckily, if you wait long enough, someone else figures out how to get something done on the internet. Actually, several someones.&lt;&#x2F;p&gt;
&lt;p&gt;After doing another web search on handling pre-compressed assets with Caddy, I noticed some forum posts from the past
year, and eventually stumbled on this &lt;a href=&quot;https:&#x2F;&#x2F;mdleom.com&#x2F;blog&#x2F;2020&#x2F;11&#x2F;12&#x2F;caddy2-pre-compressed&#x2F;&quot;&gt;excellent blog post&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;See the bottom of that blog post for links to the pertinent forum posts.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;By solving the &amp;quot;serving pre-compressed assets&amp;quot; problem, getting better gzip compression with Zopfli and adding Brotli to
the mix was the easy part.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;updating-caddy-to-serve-pre-compressed-assets&quot;&gt;Updating Caddy to serve pre-compressed assets.&lt;a class=&quot;zola-anchor&quot; href=&quot;#updating-caddy-to-serve-pre-compressed-assets&quot; aria-label=&quot;Anchor link for: updating-caddy-to-serve-pre-compressed-assets&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Update 2021-05-15: Serving precompressed assets got a LOT easier in Caddy 2.4.0. Read more
&lt;a href=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;precompressed-assets-caddy&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is copied pretty much verbatim from the above blog post, but here is the configuration I added in order to get
Caddy to correctly serve pre-compressed Brotli and gzip compressed assets whenever possible.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;example.com {
&lt;&#x2F;span&gt;&lt;span&gt;    root * &#x2F;path&#x2F;to&#x2F;dir
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    #I specifically removed the following &amp;#39;encode&amp;#39; option, since I&amp;#39;m doing compression
&lt;&#x2F;span&gt;&lt;span&gt;    #myself and Caddy was gzip-ing my PNG and JPEG images with it on (which is wasted CPU effort).
&lt;&#x2F;span&gt;&lt;span&gt;    #encode gzip zstd
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    ### Precompression support
&lt;&#x2F;span&gt;&lt;span&gt;	@brotli {
&lt;&#x2F;span&gt;&lt;span&gt;	header Accept-Encoding *br*
&lt;&#x2F;span&gt;&lt;span&gt;	  file {
&lt;&#x2F;span&gt;&lt;span&gt;	    try_files {path}.br {path}&#x2F;index.html.br {path}.html.br
&lt;&#x2F;span&gt;&lt;span&gt;	  }
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	handle @brotli {
&lt;&#x2F;span&gt;&lt;span&gt;	  header {
&lt;&#x2F;span&gt;&lt;span&gt;	    Content-Encoding br
&lt;&#x2F;span&gt;&lt;span&gt;	    Content-Type text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;	  }
&lt;&#x2F;span&gt;&lt;span&gt;	  rewrite {http.matchers.file.relative}
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@gzip {
&lt;&#x2F;span&gt;&lt;span&gt;	  header Accept-Encoding *gzip*
&lt;&#x2F;span&gt;&lt;span&gt;	  file {
&lt;&#x2F;span&gt;&lt;span&gt;	    try_files {path}.gz {path}&#x2F;index.html.gz {path}.html.gz
&lt;&#x2F;span&gt;&lt;span&gt;	  }
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	handle @gzip {
&lt;&#x2F;span&gt;&lt;span&gt;	  header {
&lt;&#x2F;span&gt;&lt;span&gt;	    Content-Encoding gzip
&lt;&#x2F;span&gt;&lt;span&gt;	    Content-Type text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;	  }
&lt;&#x2F;span&gt;&lt;span&gt;	  rewrite {http.matchers.file.relative}
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@html {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.html *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @html {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type text&#x2F;html
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@css {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.css
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @css {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type text&#x2F;css
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@js {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.js
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @js {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type text&#x2F;javascript
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@svg {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.svg
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @svg {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type image&#x2F;svg+xml
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@xml {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.xml
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @xml {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type application&#x2F;xml
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	@json {
&lt;&#x2F;span&gt;&lt;span&gt;	  file
&lt;&#x2F;span&gt;&lt;span&gt;	  path *.json
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	header @json {
&lt;&#x2F;span&gt;&lt;span&gt;	  Content-Type application&#x2F;json
&lt;&#x2F;span&gt;&lt;span&gt;	  defer
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While long, it&#x27;s actually not a scary config. It basically tells Caddy to serve pre-compressed assets if they exist,
while also fixing the &lt;code&gt;Content-Type&lt;&#x2F;code&gt; header so that we correctly identify &lt;code&gt;*.html&lt;&#x2F;code&gt; files as &lt;code&gt;text&#x2F;html&lt;&#x2F;code&gt; instead of
compressed binary data. &lt;&#x2F;p&gt;
&lt;h3 id=&quot;compressing-assets-using-zopfli&quot;&gt;Compressing assets using Zopfli&lt;a class=&quot;zola-anchor&quot; href=&quot;#compressing-assets-using-zopfli&quot; aria-label=&quot;Anchor link for: compressing-assets-using-zopfli&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Now that the web server can correctly serve my assets, I tested a few iterations of the Zopfli before adding it to my
web publishing workflow. I already optimize my website&#x27;s images using &lt;code&gt;advpng&lt;&#x2F;code&gt; and &lt;code&gt;jpegtran&lt;&#x2F;code&gt;, so I just added to my
existing pattern.&lt;&#x2F;p&gt;
&lt;p&gt;Also, for those who may be confused - Zopfli is basically a &amp;quot;better gzip compressor&amp;quot;. It produces files that any
standard gzip utility can decompress, but it does so using more advanced algorithms than the standard &lt;code&gt;gzip&lt;&#x2F;code&gt; utility.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to get started, here&#x27;s some useful commands for testing zopfli.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;zopfli -c index.html &amp;gt; index.html.gz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll note that I&#x27;m using a redirect here (&lt;code&gt;&amp;gt;&lt;&#x2F;code&gt;) to produce a new file. By default, zopfli overwrites the existing file,
which I want to preserve as a fallback option on my web server in case the user&#x27;s browser doesn&#x27;t support
compression. So instead, I force zopfli to output to stdout by using the &lt;code&gt;-c&lt;&#x2F;code&gt; flag, and then use shell redirection to
create a new file.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;do-it-in-parallel&quot;&gt;Do it in parallel&lt;a class=&quot;zola-anchor&quot; href=&quot;#do-it-in-parallel&quot; aria-label=&quot;Anchor link for: do-it-in-parallel&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Here&#x27;s the fancy &lt;code&gt;fd&lt;&#x2F;code&gt; command that I came up with that will automatically find all of my text assets in my website
publishing directory (&lt;code&gt;public&#x2F;&lt;&#x2F;code&gt;) and compress them using zopfli:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;fd -e html -e xml -e css -e js -e svg -e txt -e json --exec sh -c &amp;#39;zopfli -c {} &amp;gt; {}.gz&amp;#39; \; . public&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By default, &lt;code&gt;fd&lt;&#x2F;code&gt; will utilize all of your CPU cores to run whatever command you specify in bulk. This allows me to &lt;em&gt;very
quickly&lt;&#x2F;em&gt; compress my entire website.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;compressing-assets-with-brotli&quot;&gt;Compressing assets with Brotli&lt;a class=&quot;zola-anchor&quot; href=&quot;#compressing-assets-with-brotli&quot; aria-label=&quot;Anchor link for: compressing-assets-with-brotli&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Brotli produces even smaller files than Zopfli, and has been accepted as an &lt;a href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;draft-alakuijala-brotli-07&quot;&gt;IETF standard&lt;&#x2F;a&gt;,
meaning that most web browsers support it by default now. &lt;&#x2F;p&gt;
&lt;p&gt;In order to create Brotli files for my assets like I did with Zopfli above, I came up with the following:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;brotli -Z -f index.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unlike zopfli, brotli doesn&#x27;t overwrite its input file, so the above command will produce an &lt;code&gt;index.html.br&lt;&#x2F;code&gt; file by
default.  For good measure I added &lt;code&gt;-Z&lt;&#x2F;code&gt; to always use max compression, and &lt;code&gt;-f&lt;&#x2F;code&gt; to force overwriting of any existing
files. This is useful because I statically generate this site from a set of Markdown files, and I&#x27;d rather not have to
delete the existing output directory every time just to keep Brotli happy.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;do-it-in-parallel-again&quot;&gt;Do it in parallel, again&lt;a class=&quot;zola-anchor&quot; href=&quot;#do-it-in-parallel-again&quot; aria-label=&quot;Anchor link for: do-it-in-parallel-again&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;fd -e html -e xml -e css -e js -e svg -e txt -e json --exec brotli -Z -f {} \; . public&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Same style of &lt;code&gt;fd&lt;&#x2F;code&gt; command as above...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results&quot; aria-label=&quot;Anchor link for: results&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;For just a quick comparison, I compressed the home page of this blog with Zopfli and Brotli.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the number of bytes in four forms: uncompressed, compressed with Brotli, and compressed with Zopfli, and
compressed with standard gzip using &lt;code&gt;gzip -9&lt;&#x2F;code&gt; for maximum compression:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;17,817 index.html
&lt;&#x2F;span&gt;&lt;span&gt;2,607  index.html.br (85.37% improvement over uncompressed)
&lt;&#x2F;span&gt;&lt;span&gt;3,308  index.html.gz (81.43% improvement over uncompressed) (zopfli)
&lt;&#x2F;span&gt;&lt;span&gt;3,404  index.html.gzip (80.89% improvement over uncompressed) (gzip -9)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, compression in general results in significant savings. Brotli unsurprisingly takes the cake, followed by
Zopfli and standard gzip as dead last.&lt;&#x2F;p&gt;
&lt;p&gt;That said, the improvement of Zopfli over standard gzip is marginal in this case, but when applied to all text assets
across the entire website, you can shave a few percentage points off your web traffic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;So yeah, you&#x27;re likely reading this via a Brotli-compressed HTML page, or maybe even a Zopfli-compressed HTML page.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to the total lack of Javascript, trackers, and any other 3rd party requests, you can enjoy a lighting fast
&amp;quot;plain text&amp;quot; experience on this website.&lt;&#x2F;p&gt;
&lt;p&gt;Cheers!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>NetworkManager is bloat</title>
		<published>2021-01-31T00:00:00+00:00</published>
		<updated>2021-01-31T00:00:00+00:00</updated>
		<link href="https://austindw.com/networkmanager-is-bloat/" type="text/html"/>
		<id>https://austindw.com/networkmanager-is-bloat/</id>
		<content type="html">&lt;p&gt;Or how I came to love &lt;code&gt;dhcpcd&lt;&#x2F;code&gt; and &lt;code&gt;iwd&lt;&#x2F;code&gt; for all of my networking needs...&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;background&quot;&gt;Background&lt;a class=&quot;zola-anchor&quot; href=&quot;#background&quot; aria-label=&quot;Anchor link for: background&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;I have a weird fascination with running as &lt;em&gt;little&lt;&#x2F;em&gt; software as possible on my machines.&lt;&#x2F;p&gt;
&lt;p&gt;For whatever reason, minimizing RAM usage scratches some weird itch of mine. And no, it&#x27;s not infected. At least, I hope
not...&lt;&#x2F;p&gt;
&lt;p&gt;Anyways, after watching a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=bOzLwODMqIo&quot;&gt;video on installing Arch Linux&lt;&#x2F;a&gt; for fun (don&#x27;t judge me),
the presenter Ermanno (who&#x27;s videos I &lt;strong&gt;VERY HIGHLY RECOMMEND&lt;&#x2F;strong&gt;) covered a change to the install process that Arch Linux
made recently.&lt;&#x2F;p&gt;
&lt;p&gt;Or I suppose a more accurate description is a change that Arch Linux made to how to connect to a wireless network when
you&#x27;re installing. Keep in mind that the standard Arch Linux install process doesn&#x27;t have a GUI or any desktop
environment with a graphical installer. There&#x27;s no comfy icon to click on to configure networking, nothing.&lt;&#x2F;p&gt;
&lt;p&gt;Out of curiousity, I started looking into this new replacement sofware - &lt;code&gt;iwd&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Once I started falling down that rabbit hole, I discovered just how unnecessary &lt;code&gt;NetworkManager&lt;&#x2F;code&gt; is in my setup.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-works-for-me&quot;&gt;Why this works for me&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-this-works-for-me&quot; aria-label=&quot;Anchor link for: why-this-works-for-me&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Like I said, I run a minimal setup. This means I don&#x27;t need nor want big fancy GUI&#x27;s for my tools.&lt;&#x2F;p&gt;
&lt;p&gt;To give an example, I run:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A tiling window manager (i3, bspwm, sway, river are all on regular rotation...)&lt;&#x2F;li&gt;
&lt;li&gt;A CLI or ncurses-UI for connecting to wifi (this was &lt;code&gt;nmtui&lt;&#x2F;code&gt; when I was using &lt;code&gt;NetworkManager&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;A CLI VPN with no visual feedback or need to graphically configure said VPN.&lt;&#x2F;li&gt;
&lt;li&gt;I don&#x27;t connect to esoteric modems like PPPOE, etc from my laptop or desktop.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With all this in mind, all of the &amp;quot;extra&amp;quot; features (read: bloat) of &lt;code&gt;NetworkManager&lt;&#x2F;code&gt; mean that I&#x27;m paying a pretty steep
cost in terms of dependencies and memory usage for things I simply don&#x27;t need.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that there are some GUI tools for &lt;code&gt;dhcpcd&lt;&#x2F;code&gt; and &lt;code&gt;iwd&lt;&#x2F;code&gt; at this point, so check those out on the Arch Wiki if you&#x27;re
really curious.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Iwd&quot;&gt;Arch Linux Wiki entry on iwd&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Dhcpcd&quot;&gt;Arch Linux Wiki entry on dhcpcd&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;how-to-make-the-change&quot;&gt;How to make the change&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-to-make-the-change&quot; aria-label=&quot;Anchor link for: how-to-make-the-change&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to make the change yourself, it&#x27;s actually pretty easy. I recommend doing things in this order, because if
you can&#x27;t get iwd&#x2F;dhcpcd to work to your liking, it&#x27;s trivial to go back to &lt;code&gt;NetworkManager&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;install-iwd-and-dhcpcd-and-openresolv&quot;&gt;Install iwd and dhcpcd (and openresolv)&lt;a class=&quot;zola-anchor&quot; href=&quot;#install-iwd-and-dhcpcd-and-openresolv&quot; aria-label=&quot;Anchor link for: install-iwd-and-dhcpcd-and-openresolv&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;We need all three applications. In short, &lt;code&gt;dhcpcd&lt;&#x2F;code&gt; handles the DHCP handshake (and thus giving you an IP address) when a
connection is established, like plugging in an ethernet cable or connecting to a wifi network with &lt;code&gt;iwd&lt;&#x2F;code&gt;. As stated 
&lt;code&gt;iwd&lt;&#x2F;code&gt; handles wireless connections, that&#x27;s it.&lt;&#x2F;p&gt;
&lt;p&gt;Lastly, &lt;code&gt;openresolv&lt;&#x2F;code&gt; (a &lt;code&gt;resolvconf&lt;&#x2F;code&gt; implementation) handles the DNS configuration (mostly the maintenance of your
&lt;code&gt;&#x2F;etc&#x2F;hosts&lt;&#x2F;code&gt; file). &lt;code&gt;dhcpcd&lt;&#x2F;code&gt; works with &lt;code&gt;openresolv&lt;&#x2F;code&gt; automatically, you can read its
&lt;a href=&quot;https:&#x2F;&#x2F;man.archlinux.org&#x2F;man&#x2F;core&#x2F;dhcpcd&#x2F;dhcpcd.8.en&quot;&gt;documentation&lt;&#x2F;a&gt; for more details.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I did mess around with using &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Systemd-resolved&quot;&gt;systemd-resolvd&lt;&#x2F;a&gt; to have one less
dependency, but ran into several issues with DNS configuration reliability. Just use &lt;code&gt;openresolv&lt;&#x2F;code&gt; and you&#x27;ll be much
happier.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;On Arch, I installed all necessary software with pacman like so:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# pacman -S iwd dhcpcd openresolv
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;disable-networkmanager-and-wpa-supplicant&quot;&gt;Disable NetworkManager and wpa_supplicant&lt;a class=&quot;zola-anchor&quot; href=&quot;#disable-networkmanager-and-wpa-supplicant&quot; aria-label=&quot;Anchor link for: disable-networkmanager-and-wpa-supplicant&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Now that you&#x27;ve downloaded the necessary software, you&#x27;ve got to shutdown &lt;code&gt;NetworkManager&lt;&#x2F;code&gt; and &lt;code&gt;wpa_supplicant&lt;&#x2F;code&gt; to prevent
conflicts between the two sets of software.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# systemctl stop NetworkManager wpa_supplicant
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note: Obviously, you&#x27;ll lose internet at this point.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;start-iwd-and-dhcpcd&quot;&gt;Start iwd and dhcpcd&lt;a class=&quot;zola-anchor&quot; href=&quot;#start-iwd-and-dhcpcd&quot; aria-label=&quot;Anchor link for: start-iwd-and-dhcpcd&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;With &lt;code&gt;NetworkManager&lt;&#x2F;code&gt; and its wireless sidekick taken care of, spin up iwd and dhcpcd.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# systemctl start iwd dhcpcd
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;wifi-setup&quot;&gt;Wifi setup&lt;a class=&quot;zola-anchor&quot; href=&quot;#wifi-setup&quot; aria-label=&quot;Anchor link for: wifi-setup&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;dhcpcd&lt;&#x2F;code&gt; handles all wired connections automatically, so if you&#x27;re already connected with an ethernet cable you&#x27;re done.&lt;&#x2F;p&gt;
&lt;p&gt;But, if you need to connect to a wireless network (as I&#x27;d wager 99.99% of people reading this do...), you&#x27;ll need to
configured &lt;code&gt;iwd&lt;&#x2F;code&gt; to know about your wireless network.&lt;&#x2F;p&gt;
&lt;p&gt;To do so you can use the delightful companion for iwd - &lt;code&gt;iwctl&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can run &lt;code&gt;iwctl&lt;&#x2F;code&gt; directly, type &lt;code&gt;help&lt;&#x2F;code&gt;, and then follow the corresponding documentation. Alternatively, you can
pass all of your commands directly to &lt;code&gt;iwctl&lt;&#x2F;code&gt;, as I demonstrate at the end of this section.&lt;&#x2F;p&gt;
&lt;p&gt;In my case, I simply needed to type the following:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ iwctl
&lt;&#x2F;span&gt;&lt;span&gt;[iwd]# device list
&lt;&#x2F;span&gt;&lt;span&gt;wlan0 ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I simply wanted to ensure that a wireless device was recognized, and it was. This isn&#x27;t actually required to connect to
an access point.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;[iwd]# station wlan0 scan
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wait a few seconds as iwd looks up all the networks in your area...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;[iwd]# station wlan0 connect &amp;quot;MyNetworkName&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Enter password when prompted and wait ~10 seconds to ensure you don&#x27;t get an error back. If you do, you likely mistyped
your password or your wifi is on the fritz.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that you can press &lt;code&gt;Tab&lt;&#x2F;code&gt; to autocomplete pretty much all commands, including the wireless name above.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;[iwd]# quit
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Exit out of the application.&lt;&#x2F;p&gt;
&lt;p&gt;Note that instead of using the &lt;code&gt;iwctl&lt;&#x2F;code&gt; REPL, you can just feed the associated commands directly to &lt;code&gt;iwctl&lt;&#x2F;code&gt;, like so:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ iwctl station wlan0 connect &amp;quot;MyNetworkName&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I do like the REPL, as it holds your hand (if necessary), supports tab completion and just feels polished. Use whatever method you prefer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ensure-you-ve-got-an-ip-address&quot;&gt;Ensure you&#x27;ve got an IP address&lt;a class=&quot;zola-anchor&quot; href=&quot;#ensure-you-ve-got-an-ip-address&quot; aria-label=&quot;Anchor link for: ensure-you-ve-got-an-ip-address&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;You may need to wait a few seconds as &lt;code&gt;iwd&lt;&#x2F;code&gt; and &lt;code&gt;dhcpcd&lt;&#x2F;code&gt; do their corresonding thaaangs, but you should receive an IP
address that looks somewhat familiar. You can check this with the &lt;code&gt;ip&lt;&#x2F;code&gt; command.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ ip addr
&lt;&#x2F;span&gt;&lt;span&gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
&lt;&#x2F;span&gt;&lt;span&gt;    inet 127.0.0.1&#x2F;8 scope host lo
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 ::1&#x2F;128 scope host
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;3: wlan0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether 60:e1:86:87:bc:89 brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.217&#x2F;24 brd 192.168.1.255 scope global dynamic noprefixroute wlan0
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft 33914sec preferred_lft 28514sec
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fd22:f6c3:4e66::a7e&#x2F;128 scope global dynamic noprefixroute
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft 35181sec preferred_lft 35181sec
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 2600:6c52:7b00:55aa::a7e&#x2F;128 scope global dynamic noprefixroute
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft 35181sec preferred_lft 35181sec
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fd22:f6c3:4e66:0:dcb8:7af:18a1:8bd9&#x2F;64 scope global mngtmpaddr noprefixroute
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 2600:6c52:7b00:55aa:9af:4ba4:ee9b:d32d&#x2F;64 scope global dynamic mngtmpaddr noprefixroute
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft 573699sec preferred_lft 573699sec
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::1f0:1103:da4d:ee9b&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While that might seem like a wall of text, the &lt;code&gt;192.168.1.217&lt;&#x2F;code&gt; under &lt;code&gt;wlan0&lt;&#x2F;code&gt; is what I&#x27;m looking for and tells me that I&#x27;m
properly connected to my home network.&lt;&#x2F;p&gt;
&lt;p&gt;You can confirm network + DNS connectivity with a simple:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ ping austindw.com
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Or use google.com, whatever you want...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If everything looks good, you can make the switch permanent:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# systemctl enable dhcpcd iwd
&lt;&#x2F;span&gt;&lt;span&gt;# systemctl disable NetworkManager wpa_supplicant
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Reboot, and you should come up with a perfectly working internet connection.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-to-revert&quot;&gt;How to revert&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-to-revert&quot; aria-label=&quot;Anchor link for: how-to-revert&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;If you run into issues and you want to switch back, simply do:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# systemctl disable --now dhcpcd iwd
&lt;&#x2F;span&gt;&lt;span&gt;# systemctl enable --now NetworkManager wpa_supplicant
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will immediately stop &lt;code&gt;dhcpcd&lt;&#x2F;code&gt; and &lt;code&gt;iwd&lt;&#x2F;code&gt;, then start &lt;code&gt;NetworkManager&lt;&#x2F;code&gt; and &lt;code&gt;wpa_supplicant&lt;&#x2F;code&gt;. With these commands, you&#x27;ll
even be safe to reboot and still use &lt;code&gt;NetworkManager&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results&quot; aria-label=&quot;Anchor link for: results&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;But Austin, I just replaced two networking programs with two more networking programs, how is this an improvement?&amp;quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Good question - if you measure the RAM usage before and after the switch, you should notice around a ~20MB reduction
with the &lt;em&gt;exact same end result&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, my wireless connections were &lt;em&gt;much&lt;&#x2F;em&gt; more stable with &lt;code&gt;iwd&lt;&#x2F;code&gt; than with &lt;code&gt;NetworkManager&lt;&#x2F;code&gt;. I used to have
frequent disconnect&#x2F;reconnect storms when I placed a decent amount of load on my wifi connection. I never quite tracked
down the root cause, but the broader stroke of just replacing &lt;code&gt;NetworkManager&lt;&#x2F;code&gt; completely has yielded a much improved
networking experience.&lt;&#x2F;p&gt;
&lt;p&gt;So I have less resource usage, and an extremely stable wireless network connection.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m never going back to &lt;code&gt;NetworkManager&lt;&#x2F;code&gt; if I can help it.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully this has helped convert you. Give it a try, and you just might be sold on the &lt;code&gt;iwd&lt;&#x2F;code&gt; + &lt;code&gt;dhcpcd&lt;&#x2F;code&gt; power couple
for life.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>OpenWRT Router Setup</title>
		<published>2020-12-06T00:00:00+00:00</published>
		<updated>2020-12-06T00:00:00+00:00</updated>
		<link href="https://austindw.com/openwrt-router-setup/" type="text/html"/>
		<id>https://austindw.com/openwrt-router-setup/</id>
		<content type="html">&lt;p&gt;Since it&#x27;s 2020, I have an abundance of free time on weekends, and a buddy of mine
kept (rightfully) bugging me to write up a post on my router setup, I finally got around to doing so.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s dive in on my home router setup, including firmware, QoS, and the beginnings of ad blocking.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;prelaunch&quot;&gt;Prelaunch&lt;a class=&quot;zola-anchor&quot; href=&quot;#prelaunch&quot; aria-label=&quot;Anchor link for: prelaunch&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Before I get started, perhaps I should explain why I run a custom router firmware, and why you may want to as well.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;The upside to running a firmware like OpenWRT is that I get much more up-to-date code than what ships with the
router. Router manufacturers rarely support their router firmware longer than a year or so, so by using something
like OpenWRT I recieve regular updates, which is paramount for network security. Also, by flashing my own firmware,
I know exactly what&#x27;s running on the device, instead of potential malware.&lt;&#x2F;li&gt;
&lt;li&gt;If you don&#x27;t believe me, here&#x27;s just one example of modern routers being sold on Walmart and Amazon that contain
backdoors: &lt;a href=&quot;https:&#x2F;&#x2F;cybernews.com&#x2F;security&#x2F;walmart-exclusive-routers-others-made-in-china-contain-backdoors-to-control-devices&#x2F;&quot;&gt;Cybernews.com&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;&#x2F;strong&gt; 
&lt;ul&gt;
&lt;li&gt;OpenWRT was one of the first operating systems to support &lt;a href=&quot;https:&#x2F;&#x2F;www.bufferbloat.net&#x2F;projects&#x2F;&quot;&gt;bufferbloat mitigation technologies&lt;&#x2F;a&gt;
like fq_codel, &amp;quot;cake&amp;quot;, etc. It&#x27;s a long story, but the creators of this cutting edge QoS technology created a custom
fork of OpenWRT (&lt;a href=&quot;https:&#x2F;&#x2F;www.bufferbloat.net&#x2F;projects&#x2F;cerowrt&#x2F;wiki&#x2F;&quot;&gt;CeroWrt&lt;&#x2F;a&gt;) for research purposes. As their
research bore fruit, they published their work upstream into the core OpenWRT project. This technology is truly
amazing in its ability to reduce or eliminate severe latency on a loaded network connection, and could stand on
its own as the sole reason to run OpenWRT.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ad Blocking&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;While Pihole is all the rage (I prefer, and have contributed to, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AdguardTeam&#x2F;AdGuardHome&quot;&gt;Adguard Home&lt;&#x2F;a&gt; instead),
you can get pretty dang before when it comes to blocking ads across your entire network with some of the facilities
available in OpenWRT.  Off the cuff, I know of three different methods of blocking ads network wide with OpenWRT,
and we&#x27;ll cover one today.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Because it&#x27;s fun!&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;Let&#x27;s face it, if you&#x27;re reading this blog, you&#x27;re likely a fellow nerd (said with affection). Hacking away on
your own device gives a strong sense of accomplishment and a feeling like you really own something.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;launch&quot;&gt;Launch&lt;a class=&quot;zola-anchor&quot; href=&quot;#launch&quot; aria-label=&quot;Anchor link for: launch&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Okay, first things first - you&#x27;ll want to install OpenWRT on your device.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a few methods for doing this, and I&#x27;m just going to refer you to the OpenWRT website, which has a &lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-quick-start&#x2F;factory_installation&quot;&gt;Quick
Start&lt;&#x2F;a&gt; guide for taking an existing router with stock
firmware and installing OpenWRT.&lt;&#x2F;p&gt;
&lt;p&gt;The TL;DR version:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Make sure your device is &lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;toh&#x2F;start&quot;&gt;supported by OpenWRT&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Boot your router, login to the admin page (generally found at &lt;code&gt;http:&#x2F;&#x2F;192.168.0.1&lt;&#x2F;code&gt; or &lt;code&gt;http:&#x2F;&#x2F;192.168.1.1&lt;&#x2F;code&gt;).
&lt;ul&gt;
&lt;li&gt;If you don&#x27;t know the username&#x2F;password (if it prompts you), do an internet search for the brand, as they often
use standard credentials like &lt;code&gt;admin&#x2F;admin&lt;&#x2F;code&gt; or &lt;code&gt;root&#x2F;admin&lt;&#x2F;code&gt; for the username and password combo. You may be able to
find it written on your router near the serial number as well.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Find the firmware upgrade button, and select the &lt;code&gt;*-factory.bin&lt;&#x2F;code&gt; firmware image you presumably downloaded.
&lt;ul&gt;
&lt;li&gt;I have a few routers (don&#x27;t judge), so using the &lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;toh&#x2F;tp-link&#x2F;archer-c7-1750&quot;&gt;TP-Link Archer C7 v2&lt;&#x2F;a&gt; as an example, I&#x27;d upload
the &lt;a href=&quot;http:&#x2F;&#x2F;downloads.openwrt.org&#x2F;releases&#x2F;19.07.4&#x2F;targets&#x2F;ath79&#x2F;generic&#x2F;openwrt-19.07.4-ath79-generic-tplink_archer-c7-v2-squashfs-factory.bin&quot;&gt;openwrt-19.07.4-ath79-generic-tplink_archer-c7-v2-squashfs-factory.bin&lt;&#x2F;a&gt; as an example.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; One particular quirk I ran into with this router (funny story actually...) is that the company made a
few regionalized models, separate from their global models. These are region locked, and require uploading the
correct &lt;a href=&quot;https:&#x2F;&#x2F;downloads.openwrt.org&#x2F;releases&#x2F;19.07.4&#x2F;targets&#x2F;ath79&#x2F;generic&#x2F;openwrt-19.07.4-ath79-generic-tplink_archer-c7-v2-squashfs-factory-us.bin&quot;&gt;US&lt;&#x2F;a&gt;&#x2F;&lt;a href=&quot;https:&#x2F;&#x2F;downloads.openwrt.org&#x2F;releases&#x2F;19.07.4&#x2F;targets&#x2F;ath79&#x2F;generic&#x2F;openwrt-19.07.4-ath79-generic-tplink_archer-c7-v2-squashfs-factory-eu.bin&quot;&gt;EU&lt;&#x2F;a&gt; version when doing the initial flash. &lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Wait for the router to reboot (this &lt;em&gt;can&lt;&#x2F;em&gt; take a while, so be sure to give it 5-10 minutes before you assume you&#x27;ve
failed).&lt;&#x2F;li&gt;
&lt;li&gt;Reset your network (unplug&#x2F;replug your wired cable, assuming you used one).&lt;&#x2F;li&gt;
&lt;li&gt;Login to the admin page at &lt;code&gt;192.168.1.1&lt;&#x2F;code&gt;. Just type that into your browser and go. 
&lt;ul&gt;
&lt;li&gt;If your browser tries to get smart with you and perform a web search with that address instead, look for the little
prompt that says &amp;quot;did you actually mean to go to 192.168.1.1?&amp;quot;. &lt;em&gt;Yes I did, you cheaky bastard of a browser...&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;There&#x27;s loads of tutorials, Youtube videos, etc about doing this particular song and dance. I recommend you start
searching if you want more information or better tutorials.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;a class=&quot;zola-anchor&quot; href=&quot;#configuration&quot; aria-label=&quot;Anchor link for: configuration&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Okay, now that you&#x27;ve got the guts installed, let&#x27;s get configuring the cool stuff.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;root-password&quot;&gt;Root password&lt;a class=&quot;zola-anchor&quot; href=&quot;#root-password&quot; aria-label=&quot;Anchor link for: root-password&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;When you initially login, you&#x27;ll see a prompt with the username &lt;code&gt;root&lt;&#x2F;code&gt; and an empty password box. Simply click &lt;code&gt;Login&lt;&#x2F;code&gt;
the first time, since an administrative password hasn&#x27;t been set. You&#x27;ll want to set one, for obvious security reasons.&lt;&#x2F;p&gt;
&lt;p&gt;You can change it under &lt;code&gt;System&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Administration&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Router Password&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;792e803a4c02377b00.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;792e803a4c02377b00.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;OpenWRT router password page under system, administration.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;792e803a4c02377b00.png&quot; width=&quot;780&quot; height=&quot;264&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h3 id=&quot;wireless&quot;&gt;Wireless&lt;a class=&quot;zola-anchor&quot; href=&quot;#wireless&quot; aria-label=&quot;Anchor link for: wireless&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Not all routers actually have wireless radios, but assuming yours does (and you want to use it), you can get started
creating your wireless network by navigating to &lt;code&gt;Network&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Wireless&lt;&#x2F;code&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re running a modern router, you likely have two radios (one for 802.11n and one for 802.11ac).&lt;&#x2F;p&gt;
&lt;p&gt;Simply click the &lt;code&gt;Edit&lt;&#x2F;code&gt; button for each and fill in details like the (E)SSID (your wireless network name), set the
Wireless Security Encryption to &lt;code&gt;WPA2-PSK&lt;&#x2F;code&gt; (strong security), and pick a decent password for the &lt;code&gt;Key&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;bd722b45d93d672400.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;bd722b45d93d672400.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;OpenWRT network wireless tab with Wireless Security sub-tab selected.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;bd722b45d93d672400.png&quot; width=&quot;780&quot; height=&quot;668&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;p&gt;You may want to experiment with the &lt;code&gt;Channel&lt;&#x2F;code&gt; and &lt;code&gt;Width&lt;&#x2F;code&gt; options over time as well. Generally, the greater the &lt;code&gt;Width&lt;&#x2F;code&gt;,
the better your speeds will be, but this depends on the router and what the devices on your network support. Generally
you&#x27;ll have better compatibility with a smaller &lt;code&gt;Width&lt;&#x2F;code&gt; (like 20-40 MHz), but you may be sacrificing some speed. TBH, you
probably won&#x27;t even notice...&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;Channel&lt;&#x2F;code&gt; option is a little more tricky. When in doubt, leave it at default. Maybe try &lt;code&gt;auto&lt;&#x2F;code&gt; (although I&#x27;ve had
some routers just straight fail to spin up the radio on &lt;code&gt;auto&lt;&#x2F;code&gt;...). The best approach is to use an app like &lt;a href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=com.farproc.wifi.analyzer&amp;amp;hl=en&amp;amp;gl=us&quot;&gt;Wifi
Analyzer&lt;&#x2F;a&gt; (Android) to map out the
channels being used by your neighbors. You&#x27;ll want to aim for a less congested channel.&lt;&#x2F;p&gt;
&lt;p&gt;Also, channels can overlap a bit (you&#x27;ll see that in the graphs generated by Wifi Analyzer), so it&#x27;s recommended to pick
something that&#x27;s ~3 (or more) channels away from another channel, if you can. In general aim for the largest gap in
channels, and hope for the best.&lt;&#x2F;p&gt;
&lt;p&gt;This is more of a problem on 2.4Ghz networks, since 5Ghz networks have access to a lot more channels. &lt;&#x2F;p&gt;
&lt;p&gt;Again, if you&#x27;re unsure about any of this, simply stick with the defaults for now. You can always change it later.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;firewall&quot;&gt;Firewall&lt;a class=&quot;zola-anchor&quot; href=&quot;#firewall&quot; aria-label=&quot;Anchor link for: firewall&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;For a little extra security, you can use this trick to &amp;quot;hide&amp;quot; your router from the public internet. To be fair, it&#x27;s not
really hiding, but simply acts as a deterent to anyone running port scans on the open internet.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Run a &amp;quot;ShieldsUP&amp;quot; check against your current router configuration, courtesy of Steve Gibson
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.grc.com&#x2F;shieldsup&quot;&gt;ShieldsUP&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Navigate to &lt;code&gt;Network&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Firewall&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;General Settings&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Under the &lt;code&gt;Zones&lt;&#x2F;code&gt; section, change the &lt;code&gt;reject&lt;&#x2F;code&gt; value to &lt;code&gt;drop&lt;&#x2F;code&gt; for the &lt;code&gt;Input&lt;&#x2F;code&gt; and &lt;code&gt;Forward&lt;&#x2F;code&gt; columns of the &lt;code&gt;wan =&amp;gt; REJECT&lt;&#x2F;code&gt; row. See the screenshot below for reference.&lt;&#x2F;li&gt;
&lt;li&gt;Run the &amp;quot;ShieldsUP&amp;quot; scan again, which should show that your &amp;quot;equipment actively rejected our UPnP probes!&amp;quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Rejoice.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;7812ff04008b479300.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;7812ff04008b479300.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;OpenWRT firewall zone settings.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;7812ff04008b479300.png&quot; width=&quot;780&quot; height=&quot;443&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h3 id=&quot;sqm-aka-the-bufferbloat-killer&quot;&gt;SQM (aka the bufferbloat killer...)&lt;a class=&quot;zola-anchor&quot; href=&quot;#sqm-aka-the-bufferbloat-killer&quot; aria-label=&quot;Anchor link for: sqm-aka-the-bufferbloat-killer&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;For this next part, you&#x27;ll want to install the SQM package. You can either do so from the Web UI, or if you want to go
commando-line (heh), then you can SSH to your router via &lt;code&gt;ssh root@192.168.1.1&lt;&#x2F;code&gt;. The password is whatever you set on the
&lt;code&gt;Router Password&lt;&#x2F;code&gt; page beforehand.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;command-line-install-of-sqm&quot;&gt;Command line install of SQM&lt;a class=&quot;zola-anchor&quot; href=&quot;#command-line-install-of-sqm&quot; aria-label=&quot;Anchor link for: command-line-install-of-sqm&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Nice and easy:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# opkg update
&lt;&#x2F;span&gt;&lt;span&gt;# opkg install luci-app-sqm
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that I&#x27;m installing &lt;code&gt;luci-app-sqm&lt;&#x2F;code&gt;, as that brings in the core SQM dependencies &lt;em&gt;AND&lt;&#x2F;em&gt; a useful widget in the Web
UI. If you&#x27;re hardcore and don&#x27;t want to use the Web UI at all, then just install the &lt;code&gt;sqm-scripts&lt;&#x2F;code&gt; package.&lt;&#x2F;p&gt;
&lt;p&gt;But if you&#x27;re that hardcore, you probably already knew to do that... why are you reading this blog??&lt;&#x2F;p&gt;
&lt;h4 id=&quot;web-ui-install-of-sqm&quot;&gt;Web UI install of SQM&lt;a class=&quot;zola-anchor&quot; href=&quot;#web-ui-install-of-sqm&quot; aria-label=&quot;Anchor link for: web-ui-install-of-sqm&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;System&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Software&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Using the &lt;code&gt;Filter&lt;&#x2F;code&gt; field, type &lt;code&gt;luci-app-sqm&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;It should show up as the top result, so click the &lt;code&gt;Install&lt;&#x2F;code&gt; button and wait.&lt;&#x2F;li&gt;
&lt;li&gt;It can take a minute, but if the screen seems to have frozen while waiting for the install, chances are you&#x27;re fine
and the install finished, so simply reload the page.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;setting-up-sqm&quot;&gt;Setting up SQM&lt;a class=&quot;zola-anchor&quot; href=&quot;#setting-up-sqm&quot; aria-label=&quot;Anchor link for: setting-up-sqm&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;Note: I have a DOCSIS (cable) modem to connect to my ISP (Charter). Depending on your connection, you may want to
change a few of these settings. I recommend reading the linked references.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After installing the &lt;code&gt;luci-app-sqm&lt;&#x2F;code&gt; package, and &lt;strong&gt;rebooting&lt;&#x2F;strong&gt;, log back in and go to &lt;code&gt;Network&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;SQM QoS&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Check the box to enable this SQM instance.&lt;&#x2F;li&gt;
&lt;li&gt;From the dropdown, select your &lt;strong&gt;WAN&lt;&#x2F;strong&gt; interface (aka, the interface that connects to the public internet, NOT your
local LAN). If you open the list, chances are you&#x27;ll see an interface with &lt;code&gt;(wan,wan6)&lt;&#x2F;code&gt; tacked on the end. This is
what you want.&lt;&#x2F;li&gt;
&lt;li&gt;Set the download speed&#x2F;upload speed accordingly.
&lt;ol&gt;
&lt;li&gt;This will require trial and error, I recommend testing using a good speed test tool (make sure you convert the
value to kilobits&#x2F;s, which is what this tool takes).&lt;&#x2F;li&gt;
&lt;li&gt;If you&#x27;re on Arch Linux&#x2F;Manjaro&#x2F;etc, I recommend installing &lt;code&gt;ookla-speedtest-bin&lt;&#x2F;code&gt; from the AUR, and running your
speedtest like so: &lt;code&gt;speedtest -u kbps&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;You&#x27;ll want to set these values to someting like 90% of the tested rate to start, but then after doing the later
tweaks, you can run tests to bring these closer to 95% or even 99% of rated speeds.&lt;&#x2F;li&gt;
&lt;li&gt;For my 100 megabit connection from Charter, I use: &lt;code&gt;111000&lt;&#x2F;code&gt; for download and &lt;code&gt;11100&lt;&#x2F;code&gt; for upload on my WRT3200ACM, but I
have to tune those down to &lt;code&gt;110000&lt;&#x2F;code&gt; and &lt;code&gt;10000&lt;&#x2F;code&gt; respectively on my Archer C7, since it&#x27;s not powerful enough to
handle the higher bandwidth settings without spiking the latency by 200ms in the first few packets.&lt;&#x2F;li&gt;
&lt;li&gt;You can test your optimal settings by running a ping (&lt;code&gt;ping 1.1.1.1&lt;&#x2F;code&gt;) in one terminal and then a speedtest (&lt;code&gt;speedtest -u kbps&lt;&#x2F;code&gt;) in another.&lt;&#x2F;li&gt;
&lt;li&gt;If the ping spikes significantly while running your speedtest (really noticeable when doing uploads), then you&#x27;ll
need to adjust your settings to more conservative values. If you want an idea of what&#x27;s bad, simply run this test
with SQM off - you&#x27;ll likely see your ping times pike into the 100&#x27;s of milliseconds (which is insane).&lt;&#x2F;li&gt;
&lt;li&gt;Reference - short version: &lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-user&#x2F;network&#x2F;traffic-shaping&#x2F;sqm&quot;&gt;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-user&#x2F;network&#x2F;traffic-shaping&#x2F;sqm&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Reference - long (and very interesting) version: &lt;a href=&quot;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-user&#x2F;network&#x2F;traffic-shaping&#x2F;sqm-details&quot;&gt;https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-user&#x2F;network&#x2F;traffic-shaping&#x2F;sqm-details&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Set the Queue discipline to &lt;code&gt;cake&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Set the Queue setup script to &lt;code&gt;piece_of_cake&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Check the &lt;code&gt;Show and use dangerous configuration&lt;&#x2F;code&gt; checkbox.&lt;&#x2F;li&gt;
&lt;li&gt;Set the &lt;code&gt;Explicit congestion control&lt;&#x2F;code&gt; to &lt;code&gt;ECN&lt;&#x2F;code&gt; for &lt;code&gt;ingress&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Set the &lt;code&gt;Explicit congestion control&lt;&#x2F;code&gt; to &lt;code&gt;NOECN&lt;&#x2F;code&gt; for &lt;code&gt;egress&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Under the &lt;code&gt;Advanced option...for ingress queueing&lt;&#x2F;code&gt; option, set &lt;code&gt;docsis nat ingress&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Under the &lt;code&gt;Advanced option...for egress queueing&lt;&#x2F;code&gt; option, set &lt;code&gt;docsis nat&lt;&#x2F;code&gt;
&lt;ol&gt;
&lt;li&gt;If your up&#x2F;down bandwidth is greater than or equal to 1x15, you can experiment with adding &lt;code&gt;ack-filter&lt;&#x2F;code&gt; to your egress
options.&lt;&#x2F;li&gt;
&lt;li&gt;Reference: &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;HomeNetworking&#x2F;comments&#x2F;fvhr4w&#x2F;psa_sqm_cake_nat_and_bufferbloat_tuning&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;HomeNetworking&#x2F;comments&#x2F;fvhr4w&#x2F;psa_sqm_cake_nat_and_bufferbloat_tuning&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;You can read more about these advanced options at the following man page: &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man8&#x2F;tc-cake.8.html&quot;&gt;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man8&#x2F;tc-cake.8.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Both of these are assuming you&#x27;re using a cable (DOCSIS) modem.&lt;&#x2F;li&gt;
&lt;li&gt;IF you aren&#x27;t using the &lt;code&gt;docsis&lt;&#x2F;code&gt; queue option above THEN do the following, otherwise set the link layer adaptation to &lt;code&gt;none&lt;&#x2F;code&gt;
(because you&#x27;re already adapting for it):&lt;&#x2F;li&gt;
&lt;li&gt;Under Link Layer Adaptation, set the Link Layer to &lt;code&gt;Ethernet with overhead&lt;&#x2F;code&gt; if using a cable modem (which I am).&lt;&#x2F;li&gt;
&lt;li&gt;Much more information can be found here: https:&#x2F;&#x2F;openwrt.org&#x2F;docs&#x2F;guide-user&#x2F;network&#x2F;traffic-shaping&#x2F;sqm-details#making_cake_sing_and_dance_on_a_tight_rope_without_a_safety_net_aka_advanced_features&lt;&#x2F;li&gt;
&lt;li&gt;Set the Per Packet Overhead to 18 (or 22, seems to be some discrepancy in recommendations).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;






&lt;picture&gt;
  
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;7b9d8bdd54f2773200.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;source srcset=&quot;https:&#x2F;&#x2F;austindw.com&#x2F;processed_images&#x2F;7b9d8bdd54f2773200.webp&quot; type=&quot;image&#x2F;webp&quot; &#x2F;&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;OpenWRT SQM or Smart Queue Management configuration page with the queue discipline sub-tab selected.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;7b9d8bdd54f2773200.png&quot; width=&quot;780&quot; height=&quot;1085&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h3 id=&quot;encrypted-dns-with-optional-ad-blocking&quot;&gt;Encrypted DNS (with optional ad blocking)&lt;a class=&quot;zola-anchor&quot; href=&quot;#encrypted-dns-with-optional-ad-blocking&quot; aria-label=&quot;Anchor link for: encrypted-dns-with-optional-ad-blocking&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m a big fan of privacy. I&#x27;m also a big fan of ad blocking, which generally improves privacy, security, AND
performance. One hell of a trifecta.&lt;&#x2F;p&gt;
&lt;p&gt;With that in mind, I wanted to give my brother all of these benefits, without the hastle of dealing with adblock lists,
special admin pages on the router, etc.&lt;&#x2F;p&gt;
&lt;p&gt;To be fair, &lt;strong&gt;I&lt;&#x2F;strong&gt; do this (via an instance of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AdguardTeam&#x2F;AdGuardHome&quot;&gt;Adguard Home&lt;&#x2F;a&gt;, installed on my router), as I like
to have complete control and reap the performance benefits of having an adblocker running directly on my local router.
I&#x27;ll write a proper blog post about that setup another time...&lt;&#x2F;p&gt;
&lt;p&gt;But, this just didn&#x27;t make sense for my brother&#x27;s use case. So in order to give my brother the benefits of encrypted DNS
while also allowing myself to remotely turn on ad blocking if he desires, I set him up with the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A profile on my &lt;a href=&quot;https:&#x2F;&#x2F;nextdns.io&#x2F;&quot;&gt;NextDNS&lt;&#x2F;a&gt; account.
&lt;ol&gt;
&lt;li&gt;Even if you aren&#x27;t using their ad blocking functionality, I think that NextDNS is a fanastic service. They
provide high speed DNS servers, encrypted traffic support, optional (!!) metrics&#x2F;logs, and of course - incredibly
comprehensive filtering capabilities, with blocking for everything from ads to malware to social media.&lt;&#x2F;li&gt;
&lt;li&gt;Plus, their &lt;a href=&quot;https:&#x2F;&#x2F;nextdns.io&#x2F;privacy&quot;&gt;privacy policy&lt;&#x2F;a&gt; is just incredible and I think sets the standard that
other companies should be held against.&lt;&#x2F;li&gt;
&lt;li&gt;They&#x27;re primary service is free for 300,000 queries&#x2F;month. Because I love their service, I go ahead and throw $2
their way a month. Since I pay for their &amp;quot;Pro&amp;quot; plan, if I spill over 300,000 DNS queries a month, then I don&#x27;t
lose ad blocking support for the remainder of the month.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;An instance of &lt;code&gt;dnscrypt-proxy&lt;&#x2F;code&gt; (2), running on the router.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This combination allows for strong DNS traffic encryption, blocking via NextDNS, and local device resolution via the
onboard &lt;code&gt;dnsmasq&lt;&#x2F;code&gt; instance that comes with OpenWRT.&lt;&#x2F;p&gt;
&lt;p&gt;So, without further ado, let&#x27;s get started.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;installing-dnscrypt-proxy-2&quot;&gt;Installing dnscrypt-proxy 2&lt;a class=&quot;zola-anchor&quot; href=&quot;#installing-dnscrypt-proxy-2&quot; aria-label=&quot;Anchor link for: installing-dnscrypt-proxy-2&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Luckily, this is quite easy these days, ever since they added an official package to the OpenWRT repos.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;DNSCrypt&#x2F;dnscrypt-proxy&#x2F;wiki&#x2F;Installation-on-OpenWrt#using-the-luci-web-interface&quot;&gt;dnscrypt-proxy wiki&lt;&#x2F;a&gt; has detailed instructions.&lt;&#x2F;p&gt;
&lt;p&gt;In short:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Update your software lists from either the UI (&lt;code&gt;System&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Software&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Update lists...&lt;&#x2F;code&gt;) or an SSH instance (&lt;code&gt;opkg update&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Install &lt;code&gt;dnscrypt-proxy2&lt;&#x2F;code&gt;, just like you did with &lt;code&gt;luci-app-sqm&lt;&#x2F;code&gt; above.&lt;&#x2F;li&gt;
&lt;li&gt;Go to &lt;code&gt;Network&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;DHCP and DNS&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;General Settings&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;DNS forwardings&lt;&#x2F;code&gt;, and add &lt;code&gt;127.0.0.53&lt;&#x2F;code&gt;.
&lt;ol&gt;
&lt;li&gt;This tells the running &lt;code&gt;dnsmasq&lt;&#x2F;code&gt; instance to point to the &lt;code&gt;dnscrypt-proxy&lt;&#x2F;code&gt; instance for DNS resolution, instead
of using your ISP&#x27;s servers.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Save &amp;amp; Apply.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;configuring-dnscrypt-proxy-2&quot;&gt;Configuring dnscrypt-proxy 2&lt;a class=&quot;zola-anchor&quot; href=&quot;#configuring-dnscrypt-proxy-2&quot; aria-label=&quot;Anchor link for: configuring-dnscrypt-proxy-2&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Now, before we restart dnsmasq to get the changes to take effect, let&#x27;s update &lt;code&gt;dnscrypt-proxy&lt;&#x2F;code&gt; to point to our NextDNS
instances.&lt;&#x2F;p&gt;
&lt;p&gt;You need to SSH into your router to do so. If you know what SSH is, you probably know how to do it (&lt;code&gt;ssh root@192.168.1.1&lt;&#x2F;code&gt;...)&lt;&#x2F;p&gt;
&lt;p&gt;Once you&#x27;ve logged in, you&#x27;ll want to edit the &lt;code&gt;&#x2F;etc&#x2F;dnscrypt-proxy2&#x2F;dnscrypt-proxy.toml&lt;&#x2F;code&gt; file. Chances are your OpenWRT
install has either &lt;code&gt;nano&lt;&#x2F;code&gt; or a stripped down verison of &lt;code&gt;vim&lt;&#x2F;code&gt; installed. Pick your favorite editor.&lt;&#x2F;p&gt;
&lt;p&gt;In this case, I used &lt;code&gt;vim&lt;&#x2F;code&gt;: &lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span&gt;vim &#x2F;etc&#x2F;dnscrypt-proxy2&#x2F;dnscrypt-proxy.toml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h5 id=&quot;point-to-nextdns&quot;&gt;Point to NextDNS&lt;a class=&quot;zola-anchor&quot; href=&quot;#point-to-nextdns&quot; aria-label=&quot;Anchor link for: point-to-nextdns&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h5&gt;
&lt;p&gt;Scroll to the very bottom, you&#x27;ll see a section for &lt;code&gt;Static entries&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re using NextDNS, login to your account, select the profile you want to use, and then scroll down in the
installation instructions, and you&#x27;ll see an generated config for DNSCrypt support.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example of my own after I updated it to point to my NextDNS profile:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;########################################
&lt;&#x2F;span&gt;&lt;span&gt;#            Static entries            #
&lt;&#x2F;span&gt;&lt;span&gt;########################################
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;## Optional, local, static list of additional servers
&lt;&#x2F;span&gt;&lt;span&gt;## Mostly useful for testing your own servers.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;[static]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  [static.&amp;#39;NextDNS-BroRouter&amp;#39;]
&lt;&#x2F;span&gt;&lt;span&gt;  stamp = &amp;#39;sdns:&#x2F;&#x2F;AgEAAAAAAAAACImaBunchOgiBberish...&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Scroll back up to the top of the file, and uncomment and update the &lt;code&gt;server_names&lt;&#x2F;code&gt; entry to point to your new NextDNS
record.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;server_names = [&amp;#39;NextDNS-BroRouter&amp;#39;]
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You could stop right there. I updated a bit more of the config, out of some old lesson&#x27;s I&#x27;d learned over the years.&lt;&#x2F;p&gt;
&lt;h5 id=&quot;ipv6&quot;&gt;IPv6&lt;a class=&quot;zola-anchor&quot; href=&quot;#ipv6&quot; aria-label=&quot;Anchor link for: ipv6&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h5&gt;
&lt;p&gt;First, if you have an IPv6 connection, you&#x27;ll want to able the &lt;code&gt;ipv6_servers&lt;&#x2F;code&gt; option. You can tell if you have IPv6 in
OpenWRT by viewing your WAN6 interface - if it&#x27;s up and sending&#x2F;recieving packets, you have IPv6 configured on the modem
and the router.&lt;&#x2F;p&gt;
&lt;p&gt;So, find the &lt;code&gt;ipv6_servers&lt;&#x2F;code&gt; option, and set it to &lt;code&gt;true&lt;&#x2F;code&gt; (it&#x27;s likely &lt;code&gt;false&lt;&#x2F;code&gt; by default).&lt;&#x2F;p&gt;
&lt;h5 id=&quot;blacklist&quot;&gt;Blacklist&lt;a class=&quot;zola-anchor&quot; href=&quot;#blacklist&quot; aria-label=&quot;Anchor link for: blacklist&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h5&gt;
&lt;p&gt;Lastly, if you&#x27;re going to be using NextDNS for ad blocking&#x2F;domain filtering, I recommend disabling the default
blacklist file that &lt;code&gt;dnscrypt-proxy&lt;&#x2F;code&gt; comes with.&lt;&#x2F;p&gt;
&lt;p&gt;To do that, find the &lt;code&gt;[blacklist]&lt;&#x2F;code&gt; section.&lt;&#x2F;p&gt;
&lt;p&gt;Under that, you should see an entry for &lt;code&gt;blacklist_file&lt;&#x2F;code&gt;. Simply comment it out, like so:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;[blacklist]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  ## Path to the file of blocking rules (absolute, or relative to the same directory as the...
&lt;&#x2F;span&gt;&lt;span&gt;#blacklist_file = &amp;#39;blacklist.txt&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will prevent &lt;code&gt;dnscrypt-proxy&lt;&#x2F;code&gt; from doing any of its own filtering on box. While this might sound advantageous at
first, if you&#x27;re using NextDNS to configure your filters, you don&#x27;t want an extra set of filtering rules running on your
router that might conflict with your downstream settings. Trust me, this is confusing as hell when you run into it, took
me a little while to figure out why certain websites were&#x27;t working that should have been.&lt;&#x2F;p&gt;
&lt;h5 id=&quot;caching&quot;&gt;Caching&lt;a class=&quot;zola-anchor&quot; href=&quot;#caching&quot; aria-label=&quot;Anchor link for: caching&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h5&gt;
&lt;p&gt;You don&#x27;t have to do anything! &lt;&#x2F;p&gt;
&lt;p&gt;Older versions of &lt;code&gt;dnscrypt-proxy&lt;&#x2F;code&gt; ran with less-than-optimal caching settings, but the author conducted some
&lt;a href=&quot;https:&#x2F;&#x2F;00f.net&#x2F;2019&#x2F;11&#x2F;03&#x2F;stop-using-low-dns-ttls&#x2F;&quot;&gt;interesting research&lt;&#x2F;a&gt;, found pretty optimal settings, and set
those as the defaults in &lt;code&gt;dnscrypt-proxy.toml&lt;&#x2F;code&gt;. You can scroll down to the caching section to get an idea of what they
are, if you&#x27;re curious.&lt;&#x2F;p&gt;
&lt;p&gt;See also: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;DNSCrypt&#x2F;dnscrypt-proxy&#x2F;wiki&#x2F;Caching&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;DNSCrypt&#x2F;dnscrypt-proxy&#x2F;wiki&#x2F;Caching&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Otherwise, just rest easy and enjoy blazing fast caching.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;restart-dnsmasq&quot;&gt;Restart dnsmasq&lt;a class=&quot;zola-anchor&quot; href=&quot;#restart-dnsmasq&quot; aria-label=&quot;Anchor link for: restart-dnsmasq&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Restart &lt;code&gt;dnsmasq&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;System&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Startup&lt;&#x2F;code&gt;...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Whoo! This was a long post. I hope this helped you in some way, as it&#x27;s been a collection of techniques that I&#x27;ve used
on my own routers in one way shape or form, and I don&#x27;t think there&#x27;s any other place on the internet that has all of
this in one place.&lt;&#x2F;p&gt;
&lt;p&gt;Go forth, have awesome internet, and prosper!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Troublesome iPod</title>
		<published>2020-08-16T00:00:00+00:00</published>
		<updated>2020-08-16T00:00:00+00:00</updated>
		<link href="https://austindw.com/troublesome-ipod/" type="text/html"/>
		<id>https://austindw.com/troublesome-ipod/</id>
		<content type="html">&lt;p&gt;In an effort to get away from the shitstorm that is 2020 (COVID-19, major upsets in my personal life, etc),
I decided to visit my mom, back in my hometown.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h3 id=&quot;dem-boonies&quot;&gt;Dem boonies&lt;a class=&quot;zola-anchor&quot; href=&quot;#dem-boonies&quot; aria-label=&quot;Anchor link for: dem-boonies&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;To frame things a bit, my mom lives a fair ways out from &amp;quot;town&amp;quot;. This means that certain amenities that I&#x27;ve come to
take for granted aren&#x27;t available. Things like a truly high speed internet connection (I&#x27;m sorry, but DSL does &lt;em&gt;not&lt;&#x2F;em&gt;
count any more), cellular reception, a coffee shop filled with cute baristas and college students...&lt;&#x2F;p&gt;
&lt;p&gt;I digress.&lt;&#x2F;p&gt;
&lt;p&gt;One key point is that the online world is not easily accessible when you take a few steps out of the cityverse. This
also means that things like Spotify aren&#x27;t really usable, especially for my mother, who&#x27;s as far removed from a &amp;quot;tech
wiz&amp;quot; as anyone I know.&lt;&#x2F;p&gt;
&lt;p&gt;But she does love her music.&lt;&#x2F;p&gt;
&lt;p&gt;And she has loved her iPods. A tiny device with one of the greatest navigation interfaces of all time (seriously, can we
bring back the click wheel?), loads of storage space, loads of battery life, and loads of not needing an internet
connection.&lt;&#x2F;p&gt;
&lt;p&gt;Like too many things in tech, they don&#x27;t always age well. The iPod Classic my mom had been using for the past few years
can barely hold a charge longer than 2-3 hours of playback time. Additionally, the data&#x2F;charge port on the device&lt;sup&gt;1&lt;&#x2F;sup&gt; can
only do the latter. Plugging it into a laptop yielded zero device recognition, on either Windows or Linux.&lt;&#x2F;p&gt;
&lt;p&gt;So, the old device was kaput. No way to add music, no way to migrate said music to another device, nothing.&lt;&#x2F;p&gt;
&lt;p&gt;But, this didn&#x27;t stop my mom from ordering a &amp;quot;new&amp;quot; iPod. Apparently, you can &lt;strong&gt;still&lt;&#x2F;strong&gt; get these things on
Amazon&lt;sup&gt;2&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So, there we were with a new iPod to load up with music and a laptop that (very luckily) had pretty much every song my
mom had on her old iPod. +1 for coincidental backups.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;so-you-want-to-transfer-some-files&quot;&gt;So you want to transfer some files?&lt;a class=&quot;zola-anchor&quot; href=&quot;#so-you-want-to-transfer-some-files&quot; aria-label=&quot;Anchor link for: so-you-want-to-transfer-some-files&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;It being 2020, and iPod Classics having ended their official manufacturing run 10 years ago, I thought - &amp;quot;it &lt;em&gt;has&lt;&#x2F;em&gt; to be
possible to upload music to these things without iTunes, right?&amp;quot; I mean, we had a Linux laptop that I brought and her
Windows laptop for optimal spread of operating system support. Surely there must be some free software that&#x27;s been
written that easily imports music from a folder into the iPod Classic!&lt;&#x2F;p&gt;
&lt;p&gt;Boy, was I wrong.&lt;&#x2F;p&gt;
&lt;p&gt;I tried:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.atunes.org&#x2F;&quot;&gt;aTunes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.yamipod.com&#x2F;main&#x2F;modules&#x2F;home&#x2F;&quot;&gt;YamiPod&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Manual workarounds like revealing hidden folders in Windows, navigating into the iPod&#x27;s hidden Music folder, and
drag&#x2F;dropping some files in.&lt;&#x2F;li&gt;
&lt;li&gt;A fleet of other software all based around shared libraries used by YamiPod.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;But nooooooo. Apple builds such brilliant hardware that something that should be as simple as copying a bunch of MP3
files into a folder isn&#x27;t even possible. In fact, it&#x27;s &lt;em&gt;actively disallowed&lt;&#x2F;em&gt;. &lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t really news to anyone. Apple created the greatest MP3 player in the world (and possibly ever),
but everyone who got one hated one thing about it - having to use iTunes to manage all of their music. It was slow, it
locked down a device to a particular computer, music couldn&#x27;t be easily shared with friends, etc.&lt;&#x2F;p&gt;
&lt;p&gt;All around iTunes was a total regression in user experience, which juxtaposed so very shockingly with the &lt;strong&gt;excellent&lt;&#x2F;strong&gt;
UX that the iPod Classic offered (I mean that &lt;em&gt;click wheel&lt;&#x2F;em&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;And here we are 10 years later, and we&#x27;re still back at square one - use iTunes.&lt;&#x2F;p&gt;
&lt;p&gt;To be fair, there &lt;em&gt;are&lt;&#x2F;em&gt; a stupidly large number of paid &lt;del&gt;spyware&lt;&#x2F;del&gt; apps that claim to handle iPod Classics with zero
problem. And I believe them - we as a society have had a very very long time to nail down a 10 year old piece of
hardware. But we seem to have given up.&lt;&#x2F;p&gt;
&lt;p&gt;Or at least I&#x27;ve given up. &lt;&#x2F;p&gt;
&lt;p&gt;We downloaded iTunes, installed it, and I drag&#x2F;dropped 110GB+ of music onto the device and
away we went.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;learnings&quot;&gt;Learnings...&lt;a class=&quot;zola-anchor&quot; href=&quot;#learnings&quot; aria-label=&quot;Anchor link for: learnings&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;But I learned something. I learned something about myself and Apple. I learned that Apple will actively create consumer
unfriendly software. And I learned that I don&#x27;t want to deal with its bullshit any more. Just give me an MP3 player with
an SD card slot and I&#x27;m good.&lt;&#x2F;p&gt;
&lt;p&gt;Oh look - &lt;a href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;FiiO-M5-Bluetooth-Supports-Recordings&#x2F;dp&#x2F;B07VS42KZZ&quot;&gt;they do exist&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And of course, it looks like an Apple Watch...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;a class=&quot;zola-anchor&quot; href=&quot;#footnotes&quot; aria-label=&quot;Anchor link for: footnotes&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Those old wide + flat connectors from back in the day before Apple made 2-3 more connectors and now everything
requires a damn dongle.&lt;&#x2F;li&gt;
&lt;li&gt;Although they aren&#x27;t nearly as &lt;a href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;ipod-classic&#x2F;s?k=ipod+classic&quot;&gt;cheap as they should be&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>(Re)New Beginnings...</title>
		<published>2020-07-12T00:00:00+00:00</published>
		<updated>2020-07-12T00:00:00+00:00</updated>
		<link href="https://austindw.com/re-new-beginnings/" type="text/html"/>
		<id>https://austindw.com/re-new-beginnings/</id>
		<content type="html">&lt;p&gt;Jeebus.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s been quite a long time since I last picked up the pen... as it were.&lt;&#x2F;p&gt;
&lt;p&gt;This blog has sat in the metaphorical trunk, strapped with a belt, wrapped in a blanket, tucked under the creaky stairs
of your old aunt&#x2F;grandma&#x2F;weird neighbor&#x27;s house for a very very long time.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Much has changed since I&#x27;ve been away...&lt;&#x2F;p&gt;
&lt;p&gt;For one, I&#x27;m writing this in the time of Coronavirus (COVID-19), the longest running catastrophe that my fickle mind can
remember at my age, and I remember when the Twin Towers fell and the 2008-09 stock market crashed (I was pretty
sheltered from that one, still trudging through university at the time, like you do).&lt;&#x2F;p&gt;
&lt;p&gt;Coronavirus seems to be the impetus from which so many find new inspiration. I find this stems from a boredom grown from
the mind numbing steps one takes, marching through life strapped onto the back of a routine - wakeup, work, workout, eat, sleep, repeat. I
could blame this new found desire to write on Coronavirus, and I&#x27;d probably be right. But also a little wrong.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Aside: Now, I talk of the gift that is boredom from the comfort of my own home. It doesn&#x27;t take much to recognize my privilege
here. Many are struggling to survive, either to provide food for the table, or a place to sleep for the night.
A member of my own family survives due to the very helpful program that is unemployment. It&#x27;s not perfect, but dammit is it a
lifeline in this torrential downpour.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For another, I&#x27;ve spent over 9 years in the tech industry, working my way through the ranks at Amazon. Far and away a
different person than I was in my college days, or just there after.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d like to think myself more interesting, but I guess you&#x27;ll be the judge of that.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;but-i-digress&quot;&gt;But I digress&lt;a class=&quot;zola-anchor&quot; href=&quot;#but-i-digress&quot; aria-label=&quot;Anchor link for: but-i-digress&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Back to our regularly scheduled programming.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;m restarting this blog.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe it&#x27;s because people in the software industry still seem to have blogs, which convey some startlingly useful
information, or solutions to problems that I encounter on the daily, and I&#x27;d like to pass it on (my home-room middle school
teacher would be so proud).&lt;&#x2F;p&gt;
&lt;p&gt;Or maybe it&#x27;s because social media has molded the web into its own image, where everyone has a site, a profile, a
&amp;quot;feed&amp;quot;, while possessing none of them. They no longer own the data that they produce. Leave that to Facebook, to Google, Twitter,
Snapchat, the list goes on.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly, &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=bdKZVIGRAKQ&quot;&gt;Luke Smith&lt;&#x2F;a&gt; had a point when he argues for setting up your own
website. It&#x27;s a site&#x2F;profile&#x2F;feed that &lt;em&gt;you&lt;&#x2F;em&gt; own, you control. It&#x27;s my own personal space to put whatever I want, and
know that I&#x27;m not paying for the privilege with anything other than my own cash.&lt;&#x2F;p&gt;
&lt;p&gt;Having your own website is the OG social media profile. Most of the world seems to have forgotten that.&lt;&#x2F;p&gt;
&lt;p&gt;While preparing this post, I&#x27;ve actually been able to download my LinkedIn data, and I&#x27;m working deleting my account as
these days pass by. To be honest, it literally never did me any good. I had a job right out of college that I&#x27;ve never
left. I haven&#x27;t had a need to &lt;em&gt;network&lt;&#x2F;em&gt;, to connect myself with as many other like minds, all in the hopes of
establishing a game of career hoops and ladders. I&#x27;ve been perfectly fine. &lt;&#x2F;p&gt;
&lt;p&gt;When there does come a time when I want a new job, I&#x27;ll simply start asking. I&#x27;ll be the ones to reach out to
recruiters, demonstrating my skill set. It will be the inverse of what happens today, where multiple times a week I get
emails from FAANG recruiters, which I&#x27;ve ignored for... literally years.&lt;&#x2F;p&gt;
&lt;p&gt;Who knows... maybe I&#x27;ll go freelance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;looking-forward&quot;&gt;Looking forward&lt;a class=&quot;zola-anchor&quot; href=&quot;#looking-forward&quot; aria-label=&quot;Anchor link for: looking-forward&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;I look forward to more. &lt;&#x2F;p&gt;
&lt;p&gt;More sharing of technological breakthroughs, those oh-so-critical &amp;quot;ah hah&amp;quot; moments.&lt;&#x2F;p&gt;
&lt;p&gt;Sharing insight on the tech industry, ridiculously good recipes, or other inventive ways to inflate one&#x27;s ego.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s hope I stick with it this time... I feel like it has been a long time coming.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Headphone Review: PSB M4U 1 vs B&amp;W P7</title>
		<published>2014-06-21T00:00:00+00:00</published>
		<updated>2014-06-21T00:00:00+00:00</updated>
		<link href="https://austindw.com/headphones-psb-vs-bw/" type="text/html"/>
		<id>https://austindw.com/headphones-psb-vs-bw/</id>
		<content type="html">&lt;p&gt;After graduating college, I started working fulltime at Amazon. I went from sprinting from class to class
to staying indoors (professionally) for 8+ hours a day. I was forced to spend most of my day in front of a computer,
sitting (or standing, thanks to my stand up desk) while I worked.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Okay, okay, I&#x27;m sure you&#x27;re wondering why I bring up my change in daily life. I&#x27;ll cut to the chase. My extended periods
indoors in front of a computer practically forced me to develop my taste in music, and eventually good sound.&lt;&#x2F;p&gt;
&lt;p&gt;With this migration into the arena of &amp;quot;good sound&amp;quot;, I began my journey down the corridors of the audiophiling cabinet (see what I did there?).
I bought my first pair of speakers ever, the &lt;a href=&quot;http:&#x2F;&#x2F;www.nhthifi.com&#x2F;Absolute-Tower-Speaker?sc=12&amp;amp;category=3773&quot;&gt;NHT Absolute Tower speakers&lt;&#x2F;a&gt;
. A few months later, I started thinking about where I was listening to music most, as my NHT&#x27;s are great, but I can&#x27;t exactly set them up at work.&lt;&#x2F;p&gt;
&lt;p&gt;With this came my foray into headphones, and after a few hours of reasearch, I bought the &lt;a href=&quot;http:&#x2F;&#x2F;www.amazon.com&#x2F;PSB-Over-Ear-Audiophile-Headphones-Remote&#x2F;dp&#x2F;B00AFUE7S6&#x2F;ref=sr_1_1?ie=UTF8&amp;amp;qid=1404078801&amp;amp;sr=8-1&amp;amp;keywords=psb+m4u+1&quot;&gt;PSB M4U 1&#x27;s&lt;&#x2F;a&gt;, primarily due to &lt;a href=&quot;http:&#x2F;&#x2F;thewirecutter.com&#x2F;reviews&#x2F;best-300ish-headphone&#x2F;&quot;&gt;this excellent Wirecutter article&lt;&#x2F;a&gt;. Now, these headphones (at least at the time of this writing) are $300, so not cheap by any measure. However, after about a week of constant use, I noticed a few... particulars that I will detail in a minute.&lt;&#x2F;p&gt;
&lt;p&gt;Because of these particulars, I started looking at alternative headphones. I eventually worked my way to the &lt;a href=&quot;http:&#x2F;&#x2F;www.amazon.com&#x2F;Bowers-Wilkins-P7-Mobile-Headphones&#x2F;dp&#x2F;B00F6PRSMW&quot;&gt;B&amp;amp;W P7s&lt;&#x2F;a&gt;. Now at $400, these are hardly the cheaper option, but they were especially usefull as my local Apple store had a pair on display, so I was able to do a quick comparison before purchasing a pair for futher testing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-review&quot;&gt;The Review&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-review&quot; aria-label=&quot;Anchor link for: the-review&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Okay, let&#x27;s get to the meat of the review. I&#x27;m going to go over the differeneces in comfort, build quality, sound quality, and ammenities, and how they applied to me.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;comfort&quot;&gt;Comfort&lt;a class=&quot;zola-anchor&quot; href=&quot;#comfort&quot; aria-label=&quot;Anchor link for: comfort&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Right off the bat, I&#x27;m going to dive into comfort. Comfort is a big subject for me, as my primary listening environment is 4+ hour sessions at work, so I can&#x27;t be pulling the headphones off and massaging my ears every 20 minutes.&lt;&#x2F;p&gt;






&lt;picture&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;PSB M4U 1 black headphones.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;5b480710a69ee6ce00.jpg&quot; width=&quot;780&quot; height=&quot;780&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;p&gt;First off, the PSBs:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;pros&quot;&gt;Pros&lt;a class=&quot;zola-anchor&quot; href=&quot;#pros&quot; aria-label=&quot;Anchor link for: pros&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Memory foam ear pads.&lt;&#x2F;li&gt;
&lt;li&gt;Excellent head band cushion.&lt;&#x2F;li&gt;
&lt;li&gt;Great ear seal.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;cons&quot;&gt;Cons&lt;a class=&quot;zola-anchor&quot; href=&quot;#cons&quot; aria-label=&quot;Anchor link for: cons&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Shallow ear pads.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I know it&#x27;s not the largest breadth of points, but I want to make one call out about the shallow ear pads. As a blonde elf look-alike, I have nicely pronounced ears (at least I think they are nice...) but nonetheless I have &amp;quot;large&amp;quot; ears. The PSBs are able to completely surround my ears without any problems, and the seal is fantastic, but the shallowness of their ear pads (the distance from the edge of ear pad to the driver on the headband) is problematic for my ears. This shallowness forces my ears to rub, and thus curl, just the slighted bit at the tips, which is irritating over extended listening sessions.&lt;&#x2F;p&gt;
&lt;p&gt;This shallowness is the primary reason why I began my search for alternative headphones, and thus the B&amp;amp;Ws:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;pros-1&quot;&gt;Pros&lt;a class=&quot;zola-anchor&quot; href=&quot;#pros-1&quot; aria-label=&quot;Anchor link for: pros-1&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Much larger earpad volume&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;cons-1&quot;&gt;Cons&lt;a class=&quot;zola-anchor&quot; href=&quot;#cons-1&quot; aria-label=&quot;Anchor link for: cons-1&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Non-memory phone ear pads&lt;&#x2F;li&gt;
&lt;li&gt;Stiffer headband cushion&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The larger earpad volume is the main reason why I prefer the B&amp;amp;Ws, as I no longer feel like I&#x27;m pressing the tips of my ears against a wall every time I put them on. The PSBs have a better headband pad, and cushier ear pads, but if you have larger (or in my case, pointier) ears, you may want to look elsewhere.&lt;&#x2F;p&gt;
&lt;p&gt;In summary, the PSBs have a better headband pad, and cushier ear pads, but if you have larger (or in my case, pointier) ears, you may want to look elsewhere. The B&amp;amp;Ws are firmer overall with their cushions, but I think that is simply the nature of using memory foam vs not using memory foam. Still, the B&amp;amp;Ws just fit my pointy-ass ears better.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;build-quality&quot;&gt;Build Quality&lt;a class=&quot;zola-anchor&quot; href=&quot;#build-quality&quot; aria-label=&quot;Anchor link for: build-quality&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;I have to admit build quality turned out to be more of a care-point for me than I would have thought, so let&#x27;s break down some differences.&lt;&#x2F;p&gt;
&lt;p&gt;Again, we&#x27;ll start with the PSBs:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;pros-2&quot;&gt;Pros&lt;a class=&quot;zola-anchor&quot; href=&quot;#pros-2&quot; aria-label=&quot;Anchor link for: pros-2&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Prime use of leather and metal&lt;&#x2F;li&gt;
&lt;li&gt;Two axis earcup pivot&lt;&#x2F;li&gt;
&lt;li&gt;Nice case material, kind of a mix of hardshell with soft rubber.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;cons-2&quot;&gt;Cons&lt;a class=&quot;zola-anchor&quot; href=&quot;#cons-2&quot; aria-label=&quot;Anchor link for: cons-2&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Plaassticc, specifically the headband cover and overall exterior.&lt;&#x2F;li&gt;
&lt;li&gt;Gut wrenching snap when folding the headphones up, makes me think I&#x27;m doing something wrong everytime I fold them up.&lt;&#x2F;li&gt;
&lt;li&gt;Cheap zipper on case. Not a huge problem, but you have to align the case just right in order to zip it up smoothly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All in all, I was actually marginally disappointed with the PSB build quality, but really only because of the plastic exterior. Sure, they look similar to Beats, but the plastic just seems a touch brittle to me, and makes me worry about snapping in extreme cases. Granted, the likelyhood of snapping is pretty much zero, so it&#x27;s more of a subjective opinion, and by no means hard fact.
The interior of the headband is solid, excellent metal connections and hinges, and I like the fact that I can easily yank out the headphone cord for easier folding and storage.&lt;&#x2F;p&gt;
&lt;p&gt;On to the B&amp;amp;W&#x27;s:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;pros-3&quot;&gt;Pros&lt;a class=&quot;zola-anchor&quot; href=&quot;#pros-3&quot; aria-label=&quot;Anchor link for: pros-3&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Solid metal and leather, I don&#x27;t think there is an ounce of plastic on the headphone at all.&lt;&#x2F;li&gt;
&lt;li&gt;Large headband cushion, it&#x27;s much more encompasing of the head than the PSB, but that isn&#x27;t as large a point as it sounds, as the PSB really only touches the head in one spot, and it&#x27;s a bitching cushion.&lt;&#x2F;li&gt;
&lt;li&gt;Magnetic cushion holders are a nice touch, and hold extremely well. You&#x27;ve gotta give &#x27;em a solid yank to get the ears off.&lt;&#x2F;li&gt;
&lt;li&gt;Leather carry case.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;cons-3&quot;&gt;Cons&lt;a class=&quot;zola-anchor&quot; href=&quot;#cons-3&quot; aria-label=&quot;Anchor link for: cons-3&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;The metal arms seem marginally thin on the B&amp;amp;W&#x27;s, which makes one worry about permanent bending or damage.&lt;&#x2F;li&gt;
&lt;li&gt;Leather carry case. I know that I listed the case twice in pros&#x2F;cons, but while the case is well built, I don&#x27;t believe it actually protects the headphones much, especially in cramped luggage or some other rock&#x2F;hard place.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The B&amp;amp;W&#x27;s have some solid build quality, with excellent drivers and top quality leather. The clamping force is certainly strong, which indicated strong metal retention. The carry case definitely leaves something to be desired, at least when compared to the soft-shell of the PSB. The foam ear pads are okay, but I like the memory foam of the PSB&#x27;s (as mentioned previously). Still, I think it&#x27;s a part of the stiffer foam on the B&amp;amp;W&#x27;s that actually allow for a better fit with my extended ears, because if they compressed more I might run the risk of having my ear tips touch the drivers.&lt;&#x2F;p&gt;






&lt;picture&gt;
  
  &lt;img loading=&quot;lazy&quot; alt=&quot;Bowers and Wilkins P7 headphones&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;austindw.com&amp;#x2F;processed_images&amp;#x2F;280688a22be376bc00.jpg&quot; width=&quot;780&quot; height=&quot;520&quot; style=&quot;height:auto&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;h3 id=&quot;sound-quality&quot;&gt;Sound Quality&lt;a class=&quot;zola-anchor&quot; href=&quot;#sound-quality&quot; aria-label=&quot;Anchor link for: sound-quality&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Both headphones offer excellent sound quality, so you really can&#x27;t go wrong with either headphone. Still there is a $100 price difference, so let&#x27;s breakdown the differences that I noticed.&lt;&#x2F;p&gt;
&lt;p&gt;The PSB&#x27;s had excellent clarity, with defined treble, solid midrange, and articulate bass. These headphones lend themselves particularly well to singing&#x2F;guitar-focused music, such as Johnny Cash&#x27;s rendition of &amp;quot;Hurt&amp;quot;. You can practically see his fingers on the strings in your mind, and his voice comes to life throughout your entire listening session. That being said, I listen to a wide variety of music, and I felt that these phones didn&#x27;t tune perfectly (but still damn close) to my listening tastes for genres such as trap and dubstep, along with a few hip-hop songs. This is mostly attributed to the more neutral bass response, which some people may like, but I did not.&lt;&#x2F;p&gt;
&lt;p&gt;This leads me to the B&amp;amp;W&#x27;s. The B&amp;amp;W&#x27;s have a much more... dynamic sound, I feel. I noticed a clear seperation in the &lt;em&gt;instruments&lt;&#x2F;em&gt; in the music I listened too. I could easily focus on the bass track and then switch to the vocals in my mind, hearing each with precision without one over powering the other. I have to say, if you like bass, get the B&amp;amp;W&#x27;s. They kick the ear drums off your head when compared to the PSB&#x27;s, which is something I was actually looking for without realizing it. That is, until I found it in the B&amp;amp;W&#x27;s. I very much enjoyed listening to the clear highs of &lt;em&gt;The Weeknd&lt;&#x2F;em&gt; while also bumping those sick trap beatzzz of Diplo&#x27;s &amp;quot;Revolution&amp;quot;. As soon as I heard the latter track on the B&amp;amp;W&#x27;s, I just started smiling in the middle of the Apple store.&lt;&#x2F;p&gt;
&lt;p&gt;All said and done, the B&amp;amp;W&#x27;s fit &lt;strong&gt;my&lt;&#x2F;strong&gt; listening tastes better. The PSB&#x27;s are great, and will probably be preferred by some users, as they are more neutral in their presentation. I just preferred the B&amp;amp;W&#x27;s dynamic sound and sweet bass response. Is it worth the $100 difference? Maybe, as it certainly was for me. Still, you can&#x27;t go wrong with the PSB&#x27;s, and they are pretty much the best you can get in the $300 price range.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;amenities&quot;&gt;Amenities&lt;a class=&quot;zola-anchor&quot; href=&quot;#amenities&quot; aria-label=&quot;Anchor link for: amenities&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Without a doubt, PSB takes the cake on this one. The inclusion of spare ear pads, cleaning cloth, airplane dual-prong adapter, 1&#x2F;4&amp;quot; adapter, and secondary output through the alternate audio port makes for a sick package at $300. I do want to take the time to call out the secondary output feature I mentioned. This means that you can listen to your main audio source on your PSB&#x27;s through the input on one side of the headphone, but then you can also attach a secondary set of headphones to the port on the otherside of the PSB&#x27;s, allowing another person to easily listen with you. This is great for car&#x2F;train&#x2F;airplane trips with my girlfriend, as we can watch a movie in peace, or jam to the same tunes without effecting other people. This is something that should be present on more headphones, and something I was sad to see missing on the B&amp;amp;W&#x27;s.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t get me wrong, the B&amp;amp;W&#x27;s have a carrying case, two cords (one for iPod control, one for &amp;quot;normal&amp;quot; use), 1&#x2F;4&amp;quot; plug, and the option to plug your cord into either side of the headphone. However, the PSB&#x27;s have all of this, and more. Plus, the B&amp;amp;W&#x27;s require the use of a proprietary, angled connector, which means you have to pay B&amp;amp;W everytime you want a new cord. The PSB&#x27;s have no such limitation&lt;&#x2F;p&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;So, after this (rather verbose) review, I ended up going with the B&amp;amp;W&#x27;s, but that is mostly because my ears couldn&#x27;t handle the PSB&#x27;s form factor and I liked the bass response on the B&amp;amp;W&#x27;s more. The PSB&#x27;s have better amentiies, a better price, and better foam materials, but they just didn&#x27;t fit me properly. If they fit you, great, buy them and enjoy them.&lt;&#x2F;p&gt;
&lt;p&gt;If you like &lt;em&gt;possibly&lt;&#x2F;em&gt; better audio quality, especially with respect to bass, and have large, protruding ears, I have to recommend the B&amp;amp;W&#x27;s instead.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for listening!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Getting mac ready to compile Vapoursynth</title>
		<published>2014-05-11T00:00:00+00:00</published>
		<updated>2014-05-11T00:00:00+00:00</updated>
		<link href="https://austindw.com/compile-vapoursynth-mac/" type="text/html"/>
		<id>https://austindw.com/compile-vapoursynth-mac/</id>
		<content type="html">&lt;p&gt;brew install gcc48
brew install python3&lt;&#x2F;p&gt;
&lt;p&gt;CC=&#x2F;usr&#x2F;local&#x2F;bin&#x2F;gcc-4.8 CXX=&#x2F;usr&#x2F;local&#x2F;bin&#x2F;g++-4.8 PYTHON=python3 .&#x2F;waf configure build&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Running IntelliJ with JDK 1.7 and Scala 2.10 on Mac OS X 10.9 Mavericks</title>
		<published>2014-01-02T00:00:00+00:00</published>
		<updated>2014-01-02T00:00:00+00:00</updated>
		<link href="https://austindw.com/running-intellij-jdk-1-7-scala-2-10-mac-os-x-10-9-mavericks/" type="text/html"/>
		<id>https://austindw.com/running-intellij-jdk-1-7-scala-2-10-mac-os-x-10-9-mavericks/</id>
		<content type="html">&lt;p&gt;Since the combination of OS X, Scala, and IntelliJ appear to be a moving
target in the development world, I figured I&#x27;d go ahead and jot down how
I got them up and running on my MacBook Pro. First things first, I used
IntelliJ 13 (Community Edition), with Scala 2.10.3, which I installed
using Homebrew (I will detail it below). In addition, I&#x27;m using the
latest Java 7 JDK for Mac OS X from Oracle.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;installing-scala&quot;&gt;Installing Scala&lt;a class=&quot;zola-anchor&quot; href=&quot;#installing-scala&quot; aria-label=&quot;Anchor link for: installing-scala&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;First things first, use Homebrew to install Scala, including the
documentation, like I have detailed below.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ brew install scala --with-docs
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You will likely see a line about where to point IntelliJ in the post
install message, similar to this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;==&amp;gt; Caveats
&lt;&#x2F;span&gt;&lt;span&gt;To use with IntelliJ, set the Scala home to:
&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;usr&#x2F;local&#x2F;opt&#x2F;scala&#x2F;idea
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And that&#x27;s exactly what we are going to do...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installing-java&quot;&gt;Installing Java&lt;a class=&quot;zola-anchor&quot; href=&quot;#installing-java&quot; aria-label=&quot;Anchor link for: installing-java&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Make sure that you have the latest version of the Java JDK installed, I
just downloaded the appropriate JDK from Oracle&#x27;s &lt;a href=&quot;http:&#x2F;&#x2F;www.oracle.com&#x2F;technetwork&#x2F;java&#x2F;javase&#x2F;downloads&#x2F;jdk7-downloads-1880260.html&quot; title=&quot;Java 7 JDK&quot;&gt;site&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;preparing-and-installing-intellij&quot;&gt;Preparing and Installing IntelliJ&lt;a class=&quot;zola-anchor&quot; href=&quot;#preparing-and-installing-intellij&quot; aria-label=&quot;Anchor link for: preparing-and-installing-intellij&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In order to get IntelliJ to work properly with the latest version of the
Java 7 JDK, you need to edit the .app according to the instructions
provided by the IntelliJ authors &lt;a href=&quot;http:&#x2F;&#x2F;blog.jetbrains.com&#x2F;idea&#x2F;2013&#x2F;09&#x2F;jdk7_compatibility&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;. Almost there!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;starting-a-scala-program&quot;&gt;Starting a Scala Program&lt;a class=&quot;zola-anchor&quot; href=&quot;#starting-a-scala-program&quot; aria-label=&quot;Anchor link for: starting-a-scala-program&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Now, that you have all of the tools installed, you need to start a Scala
module in IntelliJ. Start by opening IntelliJ and starting a new Scala
Module. Set the *Project SDK *path to the location of where you
installed Java 7. Mine was:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;&#x2F;Library&#x2F;Java&#x2F;JavaVirtualMachines&#x2F;jdk1.7.0_45.jdk&#x2F;Contents&#x2F;Home
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, select &lt;em&gt;Set Scala Home&lt;&#x2F;em&gt;, and point it to the location of your
Scala install, which was pointed out to us by Homebrew during our
earlier install.  In my case it was:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;&#x2F;usr&#x2F;local&#x2F;opt&#x2F;scala&#x2F;idea
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;IntelliJ should autodetect the necessary libraries and documentation
path. Fill out the remainder of your projects information (name, etc),
and then click &lt;em&gt;Finish&lt;&#x2F;em&gt; to get started.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Installing XBMC 12.2 on an ASRock ION 330HT</title>
		<published>2013-06-28T00:00:00+00:00</published>
		<updated>2013-06-28T00:00:00+00:00</updated>
		<link href="https://austindw.com/installing-xbmc-on-an-asrock-ion-330ht/" type="text/html"/>
		<id>https://austindw.com/installing-xbmc-on-an-asrock-ion-330ht/</id>
		<content type="html">&lt;p&gt;Here are some notes for an XBMC 12.2 (Frodo) install job that I did for
a buddy of mine on his ASRock ION 330HT. We were both a little nervous
about performing a full upgrade, but due to smart partitioning,
everything upgraded perfectly.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s what I did...&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;backup-prior-install&quot;&gt;Backup Prior Install&lt;a class=&quot;zola-anchor&quot; href=&quot;#backup-prior-install&quot; aria-label=&quot;Anchor link for: backup-prior-install&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Using &lt;a href=&quot;http:&#x2F;&#x2F;clonezilla.org&#x2F;&quot; title=&quot;Clonezilla&quot;&gt;Clonezilla&lt;&#x2F;a&gt;, I made an image of his current install, which was
an Ubuntu 10.04 install with XBMC on top of it. I just went ahead and
backed up the first 10G partition on his internal hard drive. Everything
went smoothly. A small trick for booting something like Clonezilla from
a flash drive with the ION 330HT is to have a keyboard plugged in and
then mash the F11 key on bootup. You should see a small boot menu appear
and then you can select to boot from the corresponding USB stick.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;download-and-install-xbmcbuntu&quot;&gt;Download and Install XBMCbuntu&lt;a class=&quot;zola-anchor&quot; href=&quot;#download-and-install-xbmcbuntu&quot; aria-label=&quot;Anchor link for: download-and-install-xbmcbuntu&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Since he only uses his ION 330HT as a media box, he didn&#x27;t need a full
fledged Ubuntu install. So, we decided to go with &lt;a href=&quot;http:&#x2F;&#x2F;wiki.xbmc.org&#x2F;index.php?title=XBMCbuntu&quot; title=&quot;XBMCbuntu&quot;&gt;XBMCbuntu&lt;&#x2F;a&gt;, which
is available for download on the main XBMC page. We installed that ISO
onto a USB drive using UNetbootin (for Mac! Didn&#x27;t know they had this
now...).&lt;&#x2F;p&gt;
&lt;p&gt;Next we booted the ION 330, mashed the F11 key, and started up the live
USB. It&#x27;s important to select the &lt;strong&gt;Fixed DPI (120x120)&lt;&#x2F;strong&gt; option if you
are installing with an HD TV attached, as otherwise the installer text
is way to freakin&#x27; small. With the fixed DPI it&#x27;s totally manageable.&lt;&#x2F;p&gt;
&lt;p&gt;We quickly selected our keyboard and timezone options, and reformated
the 10G partition he had from his previous install on the internal
harddrive. Then, we made sure that the installer pulled down the latest
packages and set his user to automatically login on bootup.&lt;&#x2F;p&gt;
&lt;p&gt;Then we hit GO!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rejoice&quot;&gt;Rejoice!&lt;a class=&quot;zola-anchor&quot; href=&quot;#rejoice&quot; aria-label=&quot;Anchor link for: rejoice&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;After the install finished, we rebooted into our wonderful new XBMC
machine. And frankly, it pretty much worked just fine after that with
two small caveats:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;automount-drives&quot;&gt;Automount Drives&lt;a class=&quot;zola-anchor&quot; href=&quot;#automount-drives&quot; aria-label=&quot;Anchor link for: automount-drives&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;We wanted his drives to automatically mount on bootup, so we can always
have his media at the ready. We did this by finding each drive&#x27;s
attached UUID using&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ sudo blkid
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After we found the partition&#x27;s UUIDs, we created mount points
under &lt;em&gt;&#x2F;media&lt;&#x2F;em&gt;. For example&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ sudo mkdir -p &#x2F;media&#x2F;Media
&lt;&#x2F;span&gt;&lt;span&gt;$ sudo mkdir -p &#x2F;media&#x2F;Media_640G
&lt;&#x2F;span&gt;&lt;span&gt;$ sudo mkdir -p &#x2F;media&#x2F;FusionHD
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first two are for his internal drives, and the last one is for an
external he has hooked up over eSATA. Then, I edited the &lt;em&gt;&#x2F;etc&#x2F;fstab&lt;&#x2F;em&gt;
file to include lines like the following for each drive:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;UUID=&amp;lt;the_uuid&amp;gt;    &#x2F;media&#x2F;FusionHD     ext4 (or ntfs-3g)  rw,user,auto,nosuid,nodev     0    0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After that, upon reboot, all necessary drives in the fstab file will
automount and appear as media locations in XBMC.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fix-hdmi-audio-output&quot;&gt;Fix HDMI Audio Output&lt;a class=&quot;zola-anchor&quot; href=&quot;#fix-hdmi-audio-output&quot; aria-label=&quot;Anchor link for: fix-hdmi-audio-output&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;While almost everything worked out of the box on the ION 330HT,
including the remote and display, the audio was a little wonky. My buddy
has his ION feed out to a Sony receiver over HDMI, and the audio
channels were a little screwed up for his 5.1 setup.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily for us, this is a solved issue. All that is necessary is to boot
into the XBMCbuntu desktop (which you can do by exiting XBMC (not
shutdown!), and then selecting &amp;quot;XBMCbuntu&amp;quot; from the login manager&#x27;s
dropdown menu). Once you are in the desktop, open up the asoundrc file
located in your home directory:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ vim ~&#x2F;.asoundrc
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Simply follow the instructions located in the XBMC wiki &lt;a href=&quot;http:&#x2F;&#x2F;wiki.xbmc.org&#x2F;index.php?title=HOW-TO:Remap_HDMI_audio_on_Gen_1_ION_-_Linux#For_5.1_with_desktop_application_support_on_XBMCbuntu_Frodo&quot;&gt;here&lt;&#x2F;a&gt;. I
backed up the asoundrc file and then copy and pasted the settings right
into the file. I completely blew away all of the previous contents.&lt;&#x2F;p&gt;
&lt;p&gt;Then reboot. Once you login to XBMC again via that login manager from
earlier, you should be able to playback your media over a standard
receiver with no issues, as long as you make sure to set your &lt;strong&gt;Audio
Output Device&lt;&#x2F;strong&gt; to *hdmi_direct (which we get from that wiki
link). ***
**&lt;&#x2F;p&gt;
&lt;p&gt;You should be good to go!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-few-notes&quot;&gt;A few notes...&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-few-notes&quot; aria-label=&quot;Anchor link for: a-few-notes&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;First of all, make sure that you go into the ION 330HT&#x27;s BIOS and give
the shared video memory a full 512MB of RAM. This ensures smooth video
performance.&lt;&#x2F;p&gt;
&lt;p&gt;Also, if you have DPI issues with XBMCbuntu AFTER you have installed it,
simply add a line to your *&#x2F;etc&#x2F;X11&#x2F;xorg.conf *file under the &amp;quot;Monitor&amp;quot;
section. There should be a few other entries and another &lt;em&gt;Option&lt;&#x2F;em&gt; entry,
so just add this to the end of the &lt;em&gt;Monitor&lt;&#x2F;em&gt; section:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Option   &amp;quot;DPI&amp;quot; &amp;quot;120 x 120&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then logout and log back in. You should now be able to actually read the
OS desktop text on a Full HD television.&lt;&#x2F;p&gt;
&lt;p&gt;After all of this was said and done, I booted up Clonezilla once more
over a USB and made a backup image of the known working configuration.
That way he can fallback on it if anything ever screws up.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Pick Your CUDA Device at Program Runtime</title>
		<published>2013-05-05T00:00:00+00:00</published>
		<updated>2013-05-05T00:00:00+00:00</updated>
		<link href="https://austindw.com/choosing-cuda-device-at-program-runtime/" type="text/html"/>
		<id>https://austindw.com/choosing-cuda-device-at-program-runtime/</id>
		<content type="html">&lt;h2 id=&quot;select-your-cuda-device&quot;&gt;Select your CUDA Device&lt;a class=&quot;zola-anchor&quot; href=&quot;#select-your-cuda-device&quot; aria-label=&quot;Anchor link for: select-your-cuda-device&quot;&gt;§&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;While conducting research on my thesis, there were several times where I
wanted to test the efforts of my work on different CUDA cards. Luckily,
I had access to a machine that contains 4 different CUDA cards, ranging
from a GTX 480, to a Tesla C2050, to a Kepler K20Xm (there are two of
these). This is all according to &lt;strong&gt;nvidia-smi&lt;&#x2F;strong&gt; of course.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Now, all of the kernels that I have been writing recently have been only
designed to run on a single device (this could very likely change in the
future, but not now). Normally, when you want to run a CUDA kernel on a
different device, you select the device number programmatically using
the cudaSetDevice() API call.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, you might be thingking : &amp;quot;But I have a lot of code! I don&#x27;t
want to make a branch in my git repo, edit all of my source files,
recompile, and then run from there!&amp;quot; At least, you should be thinking
that...&lt;&#x2F;p&gt;
&lt;p&gt;Luckily, there is a solution, and it is one that let&#x27;s you select the
devices you want your CUDA kernels to run on whenever you &lt;em&gt;execute&lt;&#x2F;em&gt; your
program. Deep in the CUDA Best Practices guide is a little section on
the &lt;strong&gt;CUDA_VISIBLE_DEVICES&lt;&#x2F;strong&gt; environment variable.&lt;&#x2F;p&gt;
&lt;p&gt;By simply setting the &lt;strong&gt;CUDA_VISIBLE_DEVICES&lt;&#x2F;strong&gt; variable to your
desired device identifier(s), you can change which device your program
runs on. This is great for testing kernels across a number of devices
rather quickly, without having to recompile every time.&lt;&#x2F;p&gt;
&lt;p&gt;Here is an example:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ CUDA_VISIBLE_DEVICES=1 .&#x2F;myCUDAProgram
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If your kernels DO support multiple devices, you can provide a list like
so:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ CUDA_VISIBLE_DEVICES=1,3 .&#x2F;myCUDAProgram
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Not too shabby, eh? Now use this in your CUDA testing! You can thank me
later...&lt;&#x2F;p&gt;
&lt;p&gt;Source: &lt;a href=&quot;http:&#x2F;&#x2F;docs.nvidia.com&#x2F;cuda&#x2F;cuda-c-best-practices-guide&#x2F;index.html#cuda-visible-devices&quot; title=&quot;CUDA Best Practices Guide&quot;&gt;CUDA Best Practices Guide&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Profiling CUDA through Python with NVVP</title>
		<published>2013-02-09T00:00:00+00:00</published>
		<updated>2013-02-09T00:00:00+00:00</updated>
		<link href="https://austindw.com/profiling-cuda-through-python-with-nvvp/" type="text/html"/>
		<id>https://austindw.com/profiling-cuda-through-python-with-nvvp/</id>
		<content type="html">&lt;p&gt;For those of you who don&#x27;t know, I&#x27;m currently pursuing my Masters in
Computer Science. Part of this undertaking requires me to complete a
thesis.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;For the purposes of my thesis, I decided to implement a framework into
the &lt;a href=&quot;http:&#x2F;&#x2F;www.vapoursynth.com&#x2F;&quot;&gt;Vapoursynth&lt;&#x2F;a&gt; video filtering project that will allow it to run as
many video operations as possible on a CUDA-enabled GPU.&lt;&#x2F;p&gt;
&lt;p&gt;In so doing, I&#x27;ve been doing a lot of CUDA kernel writing and profiling
recently. The problem, of course, is that Vapoursynth works through a
Python script wrapper around a C&#x2F;C++ core. So, whenever I want to
profile my filters, I have to insert their associated calls into a
python script, and obtain their timings through it&#x27;s execution.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, this is a less than ideal solution. What I&#x27;ve (finally) been
able to do is profile my CUDA filters through their python script files
using NVidia&#x27;s NVVP (NVidia Visual Profiler) program. It took a few
tricks to get it working correctly, especially considering that these
scripts output &lt;em&gt;video data&lt;&#x2F;em&gt; directly to standard out (stdout) (which
NVVP attempts to display, poorly, on the Console tab of the profiler).&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s get to the tricks:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Make sure that a hash-bang is at the top of your script. Ex:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python3
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Make sure that instead of sending out video output to stdout, we
send it to &#x2F;dev&#x2F;null on Linux, or NUL on Windows. This prevents NVVP
from exploding on the massive amount of video data. Ex:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(os.devnull, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;#39;w&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;f:
&lt;&#x2F;span&gt;&lt;span&gt;    clip.output(f, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;y4m&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Be sure to make the script executable, otherwise NVVP won&#x27;t be able
to, well, execute it.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;example@example-desktop:~&#x2F;src&#x2F;testing $ chmod +x test.py
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Start a new profiling session in NVVP, and load your target Python
script under the &lt;strong&gt;File&lt;&#x2F;strong&gt; path, optionally setting the
&lt;strong&gt;Working Directory&lt;&#x2F;strong&gt; to the same directory as your script, in case
you need to load any external files. After that, you&#x27;re done! Go
ahead and profile your application like you would any other CUDA
executable. It may not be able to run all ~28 profiling passes, but
it will run most, and give you nice execution time line to boot.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So, to sum up, simply make your target Python script executable, being
sure to redirect any output to &#x2F;dev&#x2F;null instead of stdout if there is a
large amount of data, and then run NVVP like you would a normal CUDA
program and enjoy the wealth of analysis tools it has to offer.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>W3 Total Cache and DONOTMINIFY</title>
		<published>2013-02-07T00:00:00+00:00</published>
		<updated>2013-02-07T00:00:00+00:00</updated>
		<link href="https://austindw.com/w3-total-cache-and-donotminify/" type="text/html"/>
		<id>https://austindw.com/w3-total-cache-and-donotminify/</id>
		<content type="html">&lt;p&gt;I use W3 Total Cache for all my of my website caching needs and usually
it works great. There have been a few problems with the latest release,
but that is for another post.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;One issue that I just experienced recently with one of my sites is that
even though minification (or minifying) was turned on, none of my CSS or
Javascript files were actually being minified. When I would &amp;quot;View
Source&amp;quot;, all of my files where in their original, un-minified form.&lt;&#x2F;p&gt;
&lt;p&gt;If I scrolled down to the bottom of the source, where W3 Total Cache
inserts its cache statistics, I saw something like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Minified using disk: basic (DONOTMINIFY constant is defined)
&lt;&#x2F;span&gt;&lt;span&gt;Page Caching using disk: enhanced (Cookie is rejected)
&lt;&#x2F;span&gt;&lt;span&gt;Database Caching using apc (Cookie is rejected)
&lt;&#x2F;span&gt;&lt;span&gt;Object Caching 1293&#x2F;1305 objects using apc
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The DONOTMINIFY statement jumped out at me. After doing some quick
research, I discovered &lt;a href=&quot;http:&#x2F;&#x2F;wordpress.org&#x2F;support&#x2F;topic&#x2F;plugin-w3-total-cache-donotminify-constant-is-defined&quot;&gt;this forum topic&lt;&#x2F;a&gt;, which detailed that the
problem is actually in my Wordpress SEO plugin, made by Yoast. More
specifically, the &amp;quot;&lt;label for=&quot;yoast_tracking&quot;&gt;Allow tracking of this
WordPress installs anonymous data&amp;quot; option that is available under the
plugin&#x27;s Dashboard, under Tracking, was enabled. By &lt;em&gt;disabling&lt;&#x2F;em&gt;** **this
option, minification works like a charm again.&lt;&#x2F;label&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So, in summary, if you see the DONOTMINIFY notification in your source
code, and you have the Wordpress SEO plugin from Yoast, make sure that
the anonymous tracking option is turned off.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Reading Unicode from raw_input in Python</title>
		<published>2012-10-10T00:00:00+00:00</published>
		<updated>2012-10-10T00:00:00+00:00</updated>
		<link href="https://austindw.com/reading-unicode-from-raw-input-in-python/" type="text/html"/>
		<id>https://austindw.com/reading-unicode-from-raw-input-in-python/</id>
		<content type="html">&lt;p&gt;This took me too damn long to figure out in Python, so a quick note.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;To obtain a unicode string in from the raw_input() function in Python,
simply use a line like the following:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;unicode_string = raw_input(&amp;quot;Enter your input&amp;quot;).decode(&amp;#39;utf8&amp;#39;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>About the only good thing in iOS 6</title>
		<published>2012-10-07T00:00:00+00:00</published>
		<updated>2012-10-07T00:00:00+00:00</updated>
		<link href="https://austindw.com/about-the-only-good-thing-in-ios-6/" type="text/html"/>
		<id>https://austindw.com/about-the-only-good-thing-in-ios-6/</id>
		<content type="html">&lt;p&gt;iOS 6 has been all over the news recently with botched promises and new
features (culminating in the new Maps application and the removal of a
native YouTube app).&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Granted, the YouTube-written app is LOADS better, but nonetheless, iOS 6
has been... underwhelming. Or lackluster, whatever you want to call it.
Still, there is one thing that I like about iOS 6:&lt;strong&gt;not having to enter
my password to update my apps&lt;&#x2F;strong&gt;. It might seem like a small thing, but
it&#x27;s the small things that really count.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, I&#x27;m not convinced that not having to enter my password makes
up for the debacle of Apple&#x27;s new Maps app.... ah, whatever.&lt;&#x2F;p&gt;
&lt;p&gt;Just some random thoughts, go back about your browsing...&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Stopping BOINC from running on boot up in Ubuntu</title>
		<published>2012-10-07T00:00:00+00:00</published>
		<updated>2012-10-07T00:00:00+00:00</updated>
		<link href="https://austindw.com/stopping-boinc-from-running-on-boot-up-in-ubuntu/" type="text/html"/>
		<id>https://austindw.com/stopping-boinc-from-running-on-boot-up-in-ubuntu/</id>
		<content type="html">&lt;p&gt;Thank you
AskUbuntu:&lt;a href=&quot;http:&#x2F;&#x2F;askubuntu.com&#x2F;questions&#x2F;96787&#x2F;stop-boinc-from-auto-start-on-system-boot&quot;&gt;http:&#x2F;&#x2F;askubuntu.com&#x2F;questions&#x2F;96787&#x2F;stop-boinc-from-auto-start-on-system-boot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I like to control when BOINC runs, and there is no easy to access
preference in the options dialog, so this little gem is nice to know.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Quick Solutions to iOS 6 Issues</title>
		<published>2012-09-21T00:00:00+00:00</published>
		<updated>2012-09-21T00:00:00+00:00</updated>
		<link href="https://austindw.com/quick-solutions-ios-6-issues/" type="text/html"/>
		<id>https://austindw.com/quick-solutions-ios-6-issues/</id>
		<content type="html">&lt;p&gt;With the release of iOS 6, a number of my friends and colleagues are
jumping on the update bandwagon. I went ahead and did the same thing,
but I heard some horror stories about people losing access to their
email (those who had Gmail anyways) and the Youtube app disappearing (a
&amp;quot;feature&amp;quot; touted in the iOS 6 release party).&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Luckily, there is a quick solution, and one that should have been used
by anybody who has a Gmail account and was&#x2F;is using the native Mail app
for iPhone. The solution? Get the Gmail app. It has much better
integration with the full feature set of Gmail. You can pick it up on
the &lt;a href=&quot;http:&#x2F;&#x2F;itunes.apple.com&#x2F;us&#x2F;app&#x2F;gmail&#x2F;id422689480?mt=8&quot; title=&quot;Gmail App&quot;&gt;App Store&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, with the removal of the native Youtube app, a lot of people may be
angry, scared, or what have you. I beg to differ, as this is actually a
good thing. Now Youtube has the ability to update and fix its own app
instead of being at the mercy of Apple every time it wants to release a
new feature. Again, you can find the Youtube app on the &lt;a href=&quot;http:&#x2F;&#x2F;itunes.apple.com&#x2F;us&#x2F;app&#x2F;youtube&#x2F;id544007664?mt=8&quot; title=&quot;Youtube App&quot;&gt;App Store&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Two quick solutions to Apple&#x27;s crippling of Google related features in
iOS 6.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Beginnings...</title>
		<published>2012-09-19T00:00:00+00:00</published>
		<updated>2012-09-19T00:00:00+00:00</updated>
		<link href="https://austindw.com/beginnings/" type="text/html"/>
		<id>https://austindw.com/beginnings/</id>
		<content type="html">&lt;p&gt;I started this blog because I knew that I already had the resources
available (considering that my other site is fully up and running,
&lt;a href=&quot;http:&#x2F;&#x2F;adubvideo.net&quot;&gt;adubvideo.net&lt;&#x2F;a&gt;) and sometimes I need a place to put my random
thoughts and a few of the things that I learn while adventuring through
the precarious world of technology.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;For those of you who don&#x27;t know, I&#x27;m a Graduate Student at California
Polytechnic State University. I&#x27;ve been there five, going on six years,
first pursuing my B.S. in Computer Engineering, and now getting my M.S.
in Computer Science.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout my time there, I&#x27;ve learned a lot and experimented more. One
thing is for sure, my experiments lead to more issues and discoveries
than any class could ever offer, which is why I plan on posting my
results and discoveries to this blog whenever I stumble across them.&lt;&#x2F;p&gt;
&lt;p&gt;Until then, good day!&lt;&#x2F;p&gt;
</content>
	</entry>
</feed>
