<![CDATA[alecgerona.io RSS Feed]]>https://alecgerona.ioGatsbyJSWed, 01 Apr 2026 05:31:19 GMT<![CDATA[PyConPH 2024 Speaker Slides]]>https://alecgerona.io/pyconph-2024/https://alecgerona.io/pyconph-2024/Sun, 25 Feb 2024 00:00:00 GMT<p>I’m proud to announce that I delivered a talk for PyConPH 2024! I talked about Developer Experience and how we approach it in my company, BillEase.</p> <p>If you want to see the slides I used, please <a href="https://docs.google.com/presentation/d/1AlGdPh1FkxbLE0VAf8xv8S3BvQLS36wc/edit?usp=sharing&#x26;ouid=101615132313690550120&#x26;rtpof=true&#x26;sd=true" target="_blank" rel="nofollow noopener noreferrer">click here</a>.</p><![CDATA[Setting up media automation on my NAS]]>https://alecgerona.io/media-automation/https://alecgerona.io/media-automation/Sat, 12 Mar 2022 00:00:00 GMT<h2 id="so-what-exactly-do-i-mean-by-media-automation" style="position:relative;"><a href="#so-what-exactly-do-i-mean-by-media-automation" aria-label="so what exactly do i mean by media automation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>So what exactly do I mean by media automation?</h2> <p>So the plan is simple: have my NAS serve all my media. But where will the media come from? How will they be managed internally in its folders? Drives? What can I use to manage this and most importantly automate it?</p> <h2 id="what-to-do" style="position:relative;"><a href="#what-to-do" aria-label="what to do permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>What to do</h2> <p>So if you haven’t seen my <a href="https://alecgerona.io/building-my-nas" target="_blank" rel="nofollow noopener noreferrer">previous post</a>, I’m using Unraid as my NAS OS. Just a way to keep management overhead to a minimum. This also means that it’ll also manage my Docker installation for me which I intend to use to run all the parts that constitutes my media automation strategy.</p> <p>So without further ado, let’s go step by step.</p> <h3 id="0-prerequisites" style="position:relative;"><a href="#0-prerequisites" aria-label="0 prerequisites permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>0. Prerequisites</h3> <p>Before proceeding with this guide be aware that you should have a working knowledge of Linux filesystems, Docker, media servers, torrents, and usenet to maximize the features. If you’re at all confused by any of this (as was I when I started) feel free to leave a comment and I’ll help out when I can.</p> <h3 id="1-qbittorrent" style="position:relative;"><a href="#1-qbittorrent" aria-label="1 qbittorrent permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>1. qBittorrent</h3> <p>Of course the start is qBittorrent ( ͡° ͜ʖ ͡°). I chose to go with <a href="https://hotio.dev/containers/qbittorrent/" target="_blank" rel="nofollow noopener noreferrer">hotio’s qBittorrent image</a> since it has more features (such as having Vuetorrent pre-installed) than say, Linuxserver.io’s which I have used in the past. Unraid allows this via a simple install command in the apps tab assuming you’ve installed Unraid’s Community Applications OS plugin.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 401px; " > <a class="gatsby-resp-image-link" href="/static/8228a7ce78bc6c4ec94ad494986f646a/9144d/qbittorrent.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 70.94594594594594%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB60lEQVR42p2Uy2sTURTG80+JgkvBTReWWlEUKaXQXRaSRXEXcCdZmUVcCF0UbDbdFLrPok1BwZKQycMkM5M0mbwfk/ckc+frnDM3WFprggc+7mMuv3O+ey7jE0KABDjwwsFy7yHZNp0X0HWBt68dvNhw8PSxg1dbNnySgnPNwtdzEz/1qcT+O7gGN7JZ4P074Mkj4Pkz4QGThoX94wY+nhj4cKSiUPegYgVV2H+gb7aBl5sSeJY0sftNxefTMva+JHCR6coqVtUJ1743Kilgb0cCexOBg+86Nj79wsFhFnOBtWzftX9dlnfYrNdwcfkDZ7ErlMvXyP/OodPxqnSc9bB0zLYlsFhUkUwkUNKK0DQNmUwGg8FAWrK5s+uAFwsJnE6nGI3HqNXq6Pf7DPmf4Aoty0I4HEYoFEI+n0e1WkWlUsFwOORKI5EIf4/FYg9eATHa7TY78Y1GIwSDQVaj0UCpVIKiKDBNE/F4HIFAAH6/H9Fo9B5wOR+77gqFAq99nvcF5vM5JpMJZrMZZ6REtKZvJNqnPUpEI8t1cTsBWyZQOp12G1PkLLlcDqqqsn0lleJR13UYhoFms8lXQk5oTloCaWQg+Sb/pFarxRV0u130ej336XTQcveHsuNrNWX5JFaJDv9Nt38a5PYG+vgeZERP9SgAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="qbittorrent" title="" src="/static/8228a7ce78bc6c4ec94ad494986f646a/9144d/qbittorrent.png" srcset="/static/8228a7ce78bc6c4ec94ad494986f646a/12f09/qbittorrent.png 148w, /static/8228a7ce78bc6c4ec94ad494986f646a/e4a3f/qbittorrent.png 295w, /static/8228a7ce78bc6c4ec94ad494986f646a/9144d/qbittorrent.png 401w" sizes="(max-width: 401px) 100vw, 401px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Remember to toggle autostart to start the containers on reboot.</p> <p>And here are the settings that I used. The <code class="language-text">/data/torrents</code> in the container path is where we will have qBittorrent direct its downloads.</p> <p>Also, <strong>very important</strong>, make sure to use a custom docker network for this one (and all the succeeding containers following except otherwise noted). This serves a lot of purposes but the most important part is that our containers will be limited to their own network and that they can connect to each other using their own names instead of IP. This is critical for when you’re moving servers, restoring a backup, or changing your server’s static IP.</p> <p>In case you forgot how to create a custom docker network it’s as simple as going into the terminal of your Unraid server and:</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token function">docker</span> network create <span class="token operator">&lt;</span>your-network-name<span class="token operator">></span></code></pre></div> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/d803076bfbf63a65b79cdc3bb655091a/5c744/qbittorrent-container-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 47.2972972972973%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABI0lEQVR42o2SzVLDMAyE8/6PCENJmvhftmM75bqsnR5goNDDXmTN511JUwgBpRTUWv+V8wLrBEESfIhwlMSMmHYItZMzKaXQoa21P2H93RqLy/uM5boSHghLSJmgvQ51Y5MxBh3qvX8M7AkIFBFo3Q14AjIBO3JOw1B/671TB1lrEWN8DGwH2ojsGTUgSkRKidD9mwZQaw1DlXvhh1hvekM7bjBGQ7xjb6az7i6PmO1L/9SdOeeQ+WP9bY7HgapWtHVBcAp6eYVaZ8aU4XIslAlOtRPY7T7eNOu3D7T5DTK/QG8XODWP2fWtFgmoTqPaK2owmOpTJ1OG08Akalu57Q17ltNI4uzFEUZFT+AT93eeDZciBZvN0I53F8v99uo5qrs+AeeOqt1ibt2iAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="qbittorrent-container-settings" title="" src="/static/d803076bfbf63a65b79cdc3bb655091a/fcda8/qbittorrent-container-settings.png" srcset="/static/d803076bfbf63a65b79cdc3bb655091a/12f09/qbittorrent-container-settings.png 148w, /static/d803076bfbf63a65b79cdc3bb655091a/e4a3f/qbittorrent-container-settings.png 295w, /static/d803076bfbf63a65b79cdc3bb655091a/fcda8/qbittorrent-container-settings.png 590w, /static/d803076bfbf63a65b79cdc3bb655091a/efc66/qbittorrent-container-settings.png 885w, /static/d803076bfbf63a65b79cdc3bb655091a/c83ae/qbittorrent-container-settings.png 1180w, /static/d803076bfbf63a65b79cdc3bb655091a/5c744/qbittorrent-container-settings.png 1206w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Then once in the web UI, we have qBittorrent use the path we’ve specified in the step above.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 436px; " > <a class="gatsby-resp-image-link" href="/static/baf128d409030018cbae11b6bb579956/8574c/qbittorrent-ui-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 26.351351351351354%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAuUlEQVR42l2Qya6FMAxD+//fhtgDG8SGeZ4R4KsTqRLvRXKTpq5T1/V9r6IoVJal6rq2vK6riPd95eO6Lp3nqW3bFIahgiCwHEWR9eZ51jiOcizLsgjhaZo0DIMBUc4gf+O+b6VpqjiOlSSJ1VmWGdq2leMy6rySRlVVyvPcagYcx/FH8HkecwKPDM/v4ZsgL8Rq13UmjCAkLHqrCH/3/+HPnbeFALabpjF8xZnOQGr4+77bnS/4Ivo/odl9E71zqi4AAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="qbittorrent-ui-settings" title="" src="/static/baf128d409030018cbae11b6bb579956/8574c/qbittorrent-ui-settings.png" srcset="/static/baf128d409030018cbae11b6bb579956/12f09/qbittorrent-ui-settings.png 148w, /static/baf128d409030018cbae11b6bb579956/e4a3f/qbittorrent-ui-settings.png 295w, /static/baf128d409030018cbae11b6bb579956/8574c/qbittorrent-ui-settings.png 436w" sizes="(max-width: 436px) 100vw, 436px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Then we change our default admin password and enable VueTorrent web UI.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 477px; " > <a class="gatsby-resp-image-link" href="/static/c4da11030cb1b8f0446e1dda8e5593b3/d743b/qbittorrent-ui-settings-2.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 77.02702702702703%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB7UlEQVR42o1U2W7bMBD01xf9gvY3iv5AH4oWRQGjjtHARWIrju6LkqzLknxMdxaRoR5JTGCwIKkdLmeHmgVBgDAMYVkWNpuNxjRNkSTJH8iy7CrMfN9HWVVKUpYl1us1PNfFse/RP2G/3+N0OuGaMWOFRWYQxzGKosD93R0ebBtVP6CWg+qm0fXD4XBJOp/Piv8S2m6A79sBYRQhMylMWSG/vUH19RPyuoFJEyXM81xxPB5frtD1fLhJDVuqch0HThTD/fYZ5t1bxKmB/fio1XN/u92qNMYYPeSZK/sSTioo9TTSgLztUPz6idK1YSSRJCSI5BZsEJvIyDXqPgwDuq5TnVVDjrZtsdvtUNc1WtGtIWSNc4LzMU7BPJKxcZTjQthPusoPOvlAo2C6N+5fvnvCP4Qs++/EKQETWM1+ctAU3COH+pAix6JP6HtIpAGx6MOD2AxqxUitxqRXfUhLqbfoMSn7LFVxUFM2xBWjz+dznbMAHsDrjX6cYuaLbZqmQhl6qG4XOMy/4OHmBxxZ51VGD47Gfs7QlwrjwMN90mD78QOy92/Ui2t503yC4zunXUh81VtOIh9WcoQVtciKDG4QKpHneYqpZajha9CmFJn8UWKaNYUjFS4WC6xWKyyXS62OZJW8a16X5n0JvwFzKnuAJNSEPQAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="qbittorrent-ui-settings-2" title="" src="/static/c4da11030cb1b8f0446e1dda8e5593b3/d743b/qbittorrent-ui-settings-2.png" srcset="/static/c4da11030cb1b8f0446e1dda8e5593b3/12f09/qbittorrent-ui-settings-2.png 148w, /static/c4da11030cb1b8f0446e1dda8e5593b3/e4a3f/qbittorrent-ui-settings-2.png 295w, /static/c4da11030cb1b8f0446e1dda8e5593b3/d743b/qbittorrent-ui-settings-2.png 477w" sizes="(max-width: 477px) 100vw, 477px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Now before we hit save, restart the UI, and see that sexy VueTorrent skin, a quick reminder to disable these two settings right here. This will be a needed way down the line. Of course this is optional as is the later step but if you’re not planning to open up your NAS to the internet then this really isn’t a security issue.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 354px; " > <a class="gatsby-resp-image-link" href="/static/240606247016def487ffa76fbf70686e/8f50f/qbittorrent-clickjacking.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 31.08108108108108%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA60lEQVR42n1RB26EMBDk/w9ElKOIIopxANNBMMdscpdEimJptMXr2dm1ta4r2rZFGAY3QuR5jnmeMQwDxnEU+/KNMei67l9Yfd+j71nYCzGTfMw8CaZpepMtywKe67r+xHmesIbBoK41qkohiiJBkiTwfV8UB0GAOI4lrqoK+77jOA5wMmLbNmlECCE7a91CKY00TYWsLEsZnX6WZULIuCgKeJ4ndWzweDx+1bHRF2GHpvmQJMm01qKmrus734glGXOve6WU+FT488gOuXRjhvthc48cw3Gc97i0jKnKdV3Yti0+d0sxn3/wjSfQY8R3w9WCTgAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="qbittorrent-clickjacking.png" title="" src="/static/240606247016def487ffa76fbf70686e/8f50f/qbittorrent-clickjacking.png" srcset="/static/240606247016def487ffa76fbf70686e/12f09/qbittorrent-clickjacking.png 148w, /static/240606247016def487ffa76fbf70686e/e4a3f/qbittorrent-clickjacking.png 295w, /static/240606247016def487ffa76fbf70686e/8f50f/qbittorrent-clickjacking.png 354w" sizes="(max-width: 354px) 100vw, 354px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>That should be it for our downloader.</p> <h3 id="2-sonarr" style="position:relative;"><a href="#2-sonarr" aria-label="2 sonarr permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>2. Sonarr</h3> <p>Next up is Sonarr or the TV show downloader. I’m also using Hotio’s just by virtue of already using the previous one with it.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; " > <a class="gatsby-resp-image-link" href="/static/1b68a014284ca1df5b3b670b581c5eae/e17e5/sonarr.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 70.94594594594594%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAABk0lEQVR42q1Sy2rCUBAV+k39MjfuXFiKYummOzeu2oVddNdFoasWhAql0KiJ7ycaq+Ij0US9Oc2ZNFIKhaINnDu5M5mTOTMT8TwP//lEeKxdF6+ajtWHibeiActeHU4oFaodLrM5nF7kcJa5gdq4hxMqFUi+ur7DSSyL8+ytf1PwjpHsuhs8PL2gWdZx//iMpWUf18PRyERRe0elUsFisQgiBw5LCE3ThKZpqNfrmEwmUEp9cXrY7XaCv26DDGW9XvsyLfT7fQwGA7kfLHm73SKdTiMajaJUKmE8HgvxfD5HuVxGPB5HLBZDPp+XhLD67w8VMIfFCWEmk0EqlRLncDiUXk6nU7HJZBKJRAKFQuFXQnI0Go2AkAc/Ilx/wZfLpYCyCcaZYNv23u84zj7u/GhPhOVWq1WRxwqrflW1Wk1An6Hr0H3LCgjDMGR4jLfbbbEcZLgdQthqtQSdTkeS+AMm9brdwPZ6aDabEtP9H9DP6mazmVTN9tDuCclOBy2lcSBEKDOMWf4m8J2S2YoQ4YqxbZ8cQCt5OJLzhAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="sonarr" title="" src="/static/1b68a014284ca1df5b3b670b581c5eae/e17e5/sonarr.png" srcset="/static/1b68a014284ca1df5b3b670b581c5eae/12f09/sonarr.png 148w, /static/1b68a014284ca1df5b3b670b581c5eae/e4a3f/sonarr.png 295w, /static/1b68a014284ca1df5b3b670b581c5eae/e17e5/sonarr.png 400w" sizes="(max-width: 400px) 100vw, 400px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>We pretty much set up the same settings on its mapping. <strong>Except</strong> that instead of mapping the container path to a specific host directory or share, we’re giving it access to the entire Unraid <code class="language-text">/data</code> share. This is so that Sonarr has access to all the subdirectories within that share and can move files between torrents/usenets to media and other subdirectories we may have via hardlinking or instant-move.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/dcb90798c83d66ddb8e8b9a45f0feff3/7a4b2/sonarr-container-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 61.48648648648649%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABQUlEQVR42o2S226DMBBE+f8vbBVVIoDB92vfp7MOiZqo0DyMsND6eGZ3B6UUtNZwziGEcCrvPWKMLwpP50FgtVa01k5VSoE2Hs4nGBdhbOznEAtcyPChwPPcgSmlfknARxLgNM0YxyuMsd2R3HvUFKmpGJZ5ZuHUI/8HlMe3bevxc85d0gbn7A5vGKy1EMmLh8B7ZG1Ylx5A+XfXvXZY15URzDGMxS0n5FqwrQtS9N2NSKCv9YNEFYdZLB/0sU0jKmF6+YIaP2GNRtyh/U7X9y3yadQ9btflA+t4gdkmurytSmL8ui3URF1Rc8RwCvvdQ8pwKHqTrcjcCjoX9wS3RFMpsLa8CdynPCsL7QpCqty7AOvYT5k0z4U1Mqy3gOIk5YpF0Z1ZEIwiJHKp89OU5ftmZEoGwF619YrGfvXIfwzxBzS7j3c19TlxAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="sonarr-container-settings" title="" src="/static/dcb90798c83d66ddb8e8b9a45f0feff3/fcda8/sonarr-container-settings.png" srcset="/static/dcb90798c83d66ddb8e8b9a45f0feff3/12f09/sonarr-container-settings.png 148w, /static/dcb90798c83d66ddb8e8b9a45f0feff3/e4a3f/sonarr-container-settings.png 295w, /static/dcb90798c83d66ddb8e8b9a45f0feff3/fcda8/sonarr-container-settings.png 590w, /static/dcb90798c83d66ddb8e8b9a45f0feff3/efc66/sonarr-container-settings.png 885w, /static/dcb90798c83d66ddb8e8b9a45f0feff3/c83ae/sonarr-container-settings.png 1180w, /static/dcb90798c83d66ddb8e8b9a45f0feff3/7a4b2/sonarr-container-settings.png 1240w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Now in Sonarr’s web UI, go to Settings > Media Management and map our <code class="language-text">/data/media/tv</code> as a root folder.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 295px; " > <a class="gatsby-resp-image-link" href="/static/66724be3c92f5e6521d2dcb1977808ed/e4a3f/sonarr-ui-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 83.1081081081081%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAACGklEQVR42p1UTW/TQBD1r0QcEHdEJQ5ADyAkDly5tdAKcQKBVKBIwAVCkiI+hEhKKSlVpXw4TRqnwbGdNrZ312v7MbtORVWaYDg8vZnV7tuZt2MbXesnEgAiSiaIIWRyDCmYiBGwKBcMa99Bo9WFuWuh1x/C7FhomF202j3N6kLHGyPkMp9gf+Cg9qOO0rvPKJY/YWu7gerXLRRKH/G68B5vih9Qb3Z05X7AEYRiJgxVQUw9h6SuwIQEpxY1k4iCutmnzXlg7JGg8olHmWfZYQKjDROhvP7plpVv44Ch0dwl37r/LDBFkGOzto31jZqO/aMqw/8QzFpOEMkYksxkXGhwkXHIVMX5QRXaCHiCzbaPdTPAjsVQ6zJstEN87zD0PSUc6apzVmgjFAn6LseeIzAYCViuQM/htCbgjdU4/Lbgb1bosUnTFGkcAalEmhCIMWGVJzHxMUg5fciNwcDG2g7HwtsRlsoHuFs6xGKRmGLFCstrh7hTOtBYoPzVN588Pt0GwxnauF0Y48ySjSsrHuYeubjxfIRrzwirHuafuLi84uI6xTdfjHB22abYhYxOb90Y2jYWyz7O3bPpoIeLDx3MP/Vw6bGrL7hKghceOBQr0RHO3x/i1ksP0TRBi16540pUWgGqrRBVM8SXCVeIK82QXj+Lj9br+4x+FjMeJU5S3UIsM8NPsjyRi0jOHmz1HY8D8cdozMI0wV8j9P+4EWjSkwAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="sonarr-ui-settings.png" title="" src="/static/66724be3c92f5e6521d2dcb1977808ed/e4a3f/sonarr-ui-settings.png" srcset="/static/66724be3c92f5e6521d2dcb1977808ed/12f09/sonarr-ui-settings.png 148w, /static/66724be3c92f5e6521d2dcb1977808ed/e4a3f/sonarr-ui-settings.png 295w" sizes="(max-width: 295px) 100vw, 295px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Some things to note here is that the disk space that Sonarr shows might be incorrect since it may be showing the <a href="https://wiki.servarr.com/sonarr/system#disk-space" target="_blank" rel="nofollow noopener noreferrer">container’s disk space instead</a>. So don’t worry about it. Also, you might notice that there are a few issues listed in the Systems tab. This is normal. This is just telling us that we need to do to make Sonarr fully operational.</p> <h3 id="3-jackett" style="position:relative;"><a href="#3-jackett" aria-label="3 jackett permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>3. Jackett</h3> <p>Which brings us to our next requirement, Jackett. Now, Jackett is what is called an indexer or basically the tool that searches in behalf Sonarr and the other Arrs on where they might find their files to download. No need to change anything in the mapping so this is a straight install.</p> <p>Now onto the web UI, click Add indexers and add the indexers that you might want to use. For security’s sake, I won’t put up a screenshot here. You should know it when you see it.</p> <p>Back to Sonarr, go to Settings > Indexers and add a Torznab feed. Here you just add the name of the indexer itself, the Torznab feed URL and the API key from Jackett.</p> <p>I also added a few more settings to my preferences in the categories.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/e5963ede9278e49bb84d6ffb10a19a06/01dae/indexer.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 151.35135135135135%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAACXBIWXMAAAsTAAALEwEAmpwYAAADXElEQVR42o1Wy44cRRDc3+eAhLiBJYR8ggtwxBxXIJCQhZAQ64PRend2ZufR7/ejqoKI6q71jLfH45ZS1Y+qyMjKyKy+atsWm80Gq9UKSZJg8/iIKIpgjME4jjCyYfDPHzNrLe7u7nHlnDt5GUa91xXGj11hzna3w9W5SV3XoWwauDyBufkblu8sFy6ZsdaveXh4OAWUJ5kYtgSr6hpl2WGM9nBwT98/NDsDrtfrZYZ93yOKY4KVuE8MBuM+KeRngEVRIssy5Hnuraoq3McjyqpFzy1o2847UyJ13/KdtqZhNIuAmlgzTE2QaXLRWqRZjiRNvAqSNPPv+05Oen+vdYuAYuUX0VIu9CGTYUGGHQEaz6ydQEaDjmx7SupsyAM/KqS+H6YQyTKrBFj78GUl7wtuy3B/izqnU0ZUnwv5+FLmqrrxTgLrw+GAPUW/f9xg/PMaxe1bbJm87Xbr5aMCOQvo6hhoYh9WzdAhiVD0zhp6M16XXjazPi8yhB0A06NkNuNuQM01BVmXVmJ+rtuLgB03v+E8+98N3IvPMH77Bcbvvob55Ue4Vz/AXv8M29QTQzK/CFjXTEDTwkU74NdXwE8v4V5+CXz/FfDN5zBykCU+dHMJUInQRpdFgZyS+e2fW/zxZoXfb+5wzfvXb9dP+xaay0WGQVsSuGSSpykiZlkWHyJkfC7kkJby+9ksq1JiSkESkbAlndd//YvdPj5xZOdkyAb2TF2LgFqgxqqwNbnhXt6+W9FJ6gVcSuB0WtBZM5dccHLSvhSaGMlCTWtcpyN6ltlIB76G+6l+g03NovMY+/1+ApSHYt4LFb+6jhqC2OwKg6pRHTdzl2k90yaMc98MveA05JEhFCugfOT4wPYTT431wlEQvqn1fdCxeZZI9XMFTElig1B/nDOqezF3c/ufRrsEODNoU3Jfk+GGaAd26/eH1vE58sSa1vsEuoWQvR7MVMeOIz3Xc0arkF2yLOdnN9MIh9SzkN+DUldtxsOlen4oHXWZi3t40mmqvQc9PkNCx26a9iTLocGeBzy6FN6BpZao9KLYL/JanB0FPU6A+RlA9kGfGDZZu3AOnyiNSRN7vZUCrhYPb2V15OFjxsU/hWH+1wklKsZSwnKWP+FShgUSSlX3tf/LKPE/ur8jOV4vPiAAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="indexer.png" title="" src="/static/e5963ede9278e49bb84d6ffb10a19a06/fcda8/indexer.png" srcset="/static/e5963ede9278e49bb84d6ffb10a19a06/12f09/indexer.png 148w, /static/e5963ede9278e49bb84d6ffb10a19a06/e4a3f/indexer.png 295w, /static/e5963ede9278e49bb84d6ffb10a19a06/fcda8/indexer.png 590w, /static/e5963ede9278e49bb84d6ffb10a19a06/01dae/indexer.png 721w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>You need to repeat this for each indexer you’ve added in Jackett.</p> <p>Next is to add qBittorrent to Sonarr. Go to Settings > Download Clients. There should be a qBittorrent preset. Note here that the host is now the qBittorrent container’s name instead of its ip/port! This is because they’re all in the same Docker network.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/16535403f8d286fecb81712ae9e3936c/a242d/sonarr-add-client.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 145.94594594594594%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAAAsTAAALEwEAmpwYAAACu0lEQVR42r2W2XLbMAxF/f9v+blmktbjNE28at9lSkJxSDGWU0nJUz0DQ5RJLPcCoDc/nn7K69ubbHcvsvv9avXr+15+7XayfXmRIIolK0pJi8LqOcnLSsI4kXMQyuZwOMowDGKuVzHGWN11nVxHzW/f/TRNI5sgCOzi80EMFhpVp07O57NkWSZd38+KwbGeiaJoxaAawmBRGwl1Y1VX9tCc9OPZOI6XDVZVJVmayPZspDXrafuzSZIsG+w1lbIsLY6RElMq8OyZE/a6CL8wSMqkfgLDPLepzUk3GkzWUvYRwlwYhrf0Rpk+D9/BsK5rx7Iabtt2lKvTWgGNaiqhVYes2WcxvCwYLJWUvHC4pWkql8tF2Bto8cL68XiUWA3gmCzAepUUuRYaZjzLJsoS8un9asrDtRFpC1s+RJJluRSKKZroeW/XSlau0HB+NeUplni2eGpatKfVXnRNJazWYd8Pwns2ADyt51OcMuvf9aNeTJnnXFMhKqJItY+J4us6TP6TQY8HKYAXOEPCHWkz7C+k7FDqex1J6hkWaT32BaGrQTqHUYXgLNE65TwjbrlsxjUGISUMIzlrcWOMNaVEQRO5Md3HDL03iNTJTZp0NrW5lPmJEpoYHL8q7Y4q0t6LbKfQpxXtNfYzutbImqYdI6ztIOH4J4PzKUcK9B+9xOjd/X6v+iT7w8GJrsEVDP0dNEuKMW6q2C7QjUTkJ42dMB/Tp52kPCxHSMnAIJp0kzSzmzHaTMaXhwBibADzEd5/GLJcARS6m5Hlx3BgjUNw9H1+M9h1dwOBGeivAA71Mw6n4wtiFlOu68YWKRcT3jEOo6U+M7KqaYSVi7LrfYTKnjw9iXl8ZMz8E4XD7kaGL2aMOYMOP/8vY/P+/CzZw4NEKjWRwOq42Y/3Kas4oGfB1Laedg/QnE4n+1fkL+h22XUWtaJkAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="sonarr-add-client.png" title="" src="/static/16535403f8d286fecb81712ae9e3936c/fcda8/sonarr-add-client.png" srcset="/static/16535403f8d286fecb81712ae9e3936c/12f09/sonarr-add-client.png 148w, /static/16535403f8d286fecb81712ae9e3936c/e4a3f/sonarr-add-client.png 295w, /static/16535403f8d286fecb81712ae9e3936c/fcda8/sonarr-add-client.png 590w, /static/16535403f8d286fecb81712ae9e3936c/a242d/sonarr-add-client.png 724w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Then make sure the prefilled category, <code class="language-text">tv-sonarr</code>, is in qBittorrent itself.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/8e3d1301fe1a55155d99b7ff9ae4c3e0/43fbc/add-category.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 68.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAABs0lEQVR42s2SzUtUYRTG71/UBzRJYh+aoVZQKWRhI9FohJs2QtKuVdCuxeyCaNuiL82PZuZONd4UbTUEDmgMiAqOTDM6t7kzc+97f533OlqKRM6q530fnvc853A4vByjOzJM39BD2q/fI9QZJtQV5qSw6WK/xLd231r3x1pPiKf9UEdfoEZrzyCXwvc5fSXCsfYbnOse5NTl2xw938uZqxHx73D8wk2auvpp7bm727hZao609XL22gAtUtMmOa3GmwmT1+8TvJ1MMhm3iCdn+GB+YTyWYjwxHXAs9pnRqU+8m/pIUC8ck/yEaWFOz5NIzZG0vmJa8xjgo5QS8bFRlPCEior4f8L3FZ7rivoBD4T4hlL1ArnPs3M8yZg8zsQx1xcDr+Z66Jpy2SGfz6M8j6pws+qwJSzXqrgS27aNl8vpCf8dqj6ZmVvk6VKK6HeLV6vp+nDbuUM13EHJrbBRKbFRtSnWyntyDTX8Gxpq6O/j/zfh70m3j14X9OoJjZ29aoQHfUHDf6ix5myy4ORxVpYhncbPZjGKxSKH5Y9CAWfL5mVmlkffYiy8eMbPByMUolF+AZUf6Jv3z60sAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="add-category.png" title="" src="/static/8e3d1301fe1a55155d99b7ff9ae4c3e0/fcda8/add-category.png" srcset="/static/8e3d1301fe1a55155d99b7ff9ae4c3e0/12f09/add-category.png 148w, /static/8e3d1301fe1a55155d99b7ff9ae4c3e0/e4a3f/add-category.png 295w, /static/8e3d1301fe1a55155d99b7ff9ae4c3e0/fcda8/add-category.png 590w, /static/8e3d1301fe1a55155d99b7ff9ae4c3e0/43fbc/add-category.png 797w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="progress-check" style="position:relative;"><a href="#progress-check" aria-label="progress check permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Progress Check</h3> <p>Okay, okay. I know that was long. But those were mostly images. So not really. Just a quick recap, but at this point we’ve actually automated everything from looking up a series to having it downloaded to our array. Really. In Sonarr, try going to Series > Add New, look up any series you want, and hit Add. If you tick the <code class="language-text">Start search for missing episodes</code> box, it’ll actually search and then download the episodes for you. Yes. Every episode of every season.</p> <p>And we’re just getting started.</p> <h3 id="4-tv-show-download-preferences" style="position:relative;"><a href="#4-tv-show-download-preferences" aria-label="4 tv show download preferences permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>4. TV Show Download Preferences</h3> <p>Now this part is mostly for my benefit (as this guide really is), but feel free to copy them.</p> <h3 id="41-set-seeding-limit-time" style="position:relative;"><a href="#41-set-seeding-limit-time" aria-label="41 set seeding limit time permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>4.1. Set seeding limit time</h3> <p>First, head to qBittorrent to set the seeding limit time to 120 minutes. This will remove the torrent from qBittorrent after the specified time.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/8d2ce93b92384284e782238235adc706/e1031/seeding-limit.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 69.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAACNElEQVR42q2SS2tTQRTH7wdSBKEopvWJaJU+RCmiNdpUl+rGTTfu/QKCO21sF20jYkxbkCK6cSEuUgoVxcoNJikmTe57Hndu/p4Zbtqkgrpw4Mc5c16cOWesK9MPcPPeQ4xk72NwdMowNDaF4+PTe/fxHN1zGEztQ2O5XbRNy8zILZy+fAdWhhKGr9/FiUu3cfDUhClw5EIWB05O4BgFaQ6duYrDZ68hM5rb1QfOTZr4oxezGDg/SXGUN3wD1uzCK+QXXxtmF4qYf7GKucIynhl9xejPl5ZRKK3h5epbLBbfIL9UMuiYucIK+Usmb75QgsWFwP86YRjCchwXjuui7ThotduGnZamhUazCc8PIOMYQkgIKfdkD7oppRL4QQDLpwTOOQWKVErEsTJFNFr/F6SM4XoeLM/zEQShwSfCiPWjbYz/bt9HEEZwXV2QOowYS+FgXKSQLhV44yfYdg0sTsD6/P3o3OZOi55M79aBeha6bTOjLvQU4XsQ37+QX/X7eqGCkvz1el3P0IdDC9FFdcGYSJKE6CChQSe0vaTyDYpFIFPq60cpZbbcpCWagnrdURQZKXq/UadjRPzDBt8sg5POOTNb1UQ0llCPhmYoaIb1ag3W1y0bLfom3U492pRL3yiO006piKD79kYZbsjM4rrIiENFEgGNxlEdVGr05Dht90+nQ50mabe953PQwEevCrGxDrx7D7+8Dsu2bfyNSsp++9NPa3j0oYjNJ49RnZnBVj6PX5Lz2XEXi6vaAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="seeding-limit.png" title="" src="/static/8d2ce93b92384284e782238235adc706/fcda8/seeding-limit.png" srcset="/static/8d2ce93b92384284e782238235adc706/12f09/seeding-limit.png 148w, /static/8d2ce93b92384284e782238235adc706/e4a3f/seeding-limit.png 295w, /static/8d2ce93b92384284e782238235adc706/fcda8/seeding-limit.png 590w, /static/8d2ce93b92384284e782238235adc706/e1031/seeding-limit.png 803w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="42-create-a-sonarr-hd-quality-profile" style="position:relative;"><a href="#42-create-a-sonarr-hd-quality-profile" aria-label="42 create a sonarr hd quality profile permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>4.2. Create a Sonarr HD+ Quality Profile</h3> <p>Sonarr by default comes with a lot of Quality profiles. These work well the default qualities you would find out there such as 720p, 1080p, 4k, and so on. This profile is just a quick QoL way to tell Sonarr to prefer the latest and greatest quality (4k with niceties such as Dolby or Remux) all the way down to 1080p. Sonarr will then flag an error if it can’t find beyond that.</p> <p>You should then select a profile per series accordingly.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/578150fff5d97672a48276d34d13df3f/0d98f/sonarr-quality.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 76.35135135135135%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYElEQVR42p1T23KDIBTM//9Sf6IPfWtaNZqLUZGbigrZcqhkJu1MG90ZxBFc9ixnd+M4QikFYwwIt9vt13gW1lrs6MU5ByLuug7DMIAo3A/Cya8LpZGXAmUjgwghJLgQ4Z+IHZFJqQLZNE1+0QRyGvM8L6rDE42a8fKm8Jp2cHYOimhP3BcIY5l/Ia5qY1GcK4i2gdIaLRdgrA1qHwj/QzyPdzPSYwUpOMqywvs+wf4j84R6JeEy917hpWJoGQuWOGe9TSO01tsUCq8wKa7gLUNVM6RpgSwrtpcslpKVFGiaFp9JjiTNNyhc5s6XfLzUnuC7ZbLDCYf86LtEblMo+xn5ufEltyEI5J8xQ2i5VYQRZrSoGb8niy6Gmnp1yRHON7IOZIPvP+49PAQP5cOlUD1P5pUSQd71fR/SVdUNrlW9/pbvCn1MKZ5ETO+UsPjtTmizDDZJHt1fCfKSPKWDvgBn8ppLTcW+ewAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="sonarr.png" title="" src="/static/578150fff5d97672a48276d34d13df3f/fcda8/sonarr-quality.png" srcset="/static/578150fff5d97672a48276d34d13df3f/12f09/sonarr-quality.png 148w, /static/578150fff5d97672a48276d34d13df3f/e4a3f/sonarr-quality.png 295w, /static/578150fff5d97672a48276d34d13df3f/fcda8/sonarr-quality.png 590w, /static/578150fff5d97672a48276d34d13df3f/efc66/sonarr-quality.png 885w, /static/578150fff5d97672a48276d34d13df3f/c83ae/sonarr-quality.png 1180w, /static/578150fff5d97672a48276d34d13df3f/0d98f/sonarr-quality.png 1276w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="5-radarr" style="position:relative;"><a href="#5-radarr" aria-label="5 radarr permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>5. Radarr</h3> <p>The next Arr for movies.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 404px; " > <a class="gatsby-resp-image-link" href="/static/244b657a9db4c09e05f47f08bab2b6c9/494f9/radarr.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 69.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAABkElEQVR42qWTS0sCURTH/cauXPkF3I0RtAijoECUXCVtQiKQHlao+ZiZfFCzMB11dHw7o/6b/62xFITSC4e5c865v3te1zObzbBYLDCdTsE1n8+FUPdfIctDyEe9joPDYyRuUkvwNouBCODdYwbXlyd4TuzjLBxBs9kUDrx1K+Dtwwtur/YAXUI0GoGsqEuHrYBv7xou4nGchmO4Tz3tnrJpmoiex5BOp2Hb1u7AVquJTCaDSqWCTre7TNXtnDsJfwLScTweYzgcou50W9d1TCaT7SPk7UehEPx+P3K5nBNtS0B7vR6q1SokSUIgEEA2m93YKDJ4TsyhZVkIBoPw+XwCUKvVxOFGo4FCPi/0Xq8XyWRyI5AZvarqF9B9GfwhnEYKy8Ahd23cj0Yj8aWde5aJtpWUCZFlGYqiiAhLpZLYFwoFUYJyubwi9FGdaOhTLBahaRr6/T4Gg8FPDbtOZ9vttqgda+H+U/hqDMMQYjr6Tqcj9Bw149tHd8rDmrPBHtu2lyOyLuvP77du3Y+LrE81+C1KIic0vAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="radarr.png" title="" src="/static/244b657a9db4c09e05f47f08bab2b6c9/494f9/radarr.png" srcset="/static/244b657a9db4c09e05f47f08bab2b6c9/12f09/radarr.png 148w, /static/244b657a9db4c09e05f47f08bab2b6c9/e4a3f/radarr.png 295w, /static/244b657a9db4c09e05f47f08bab2b6c9/494f9/radarr.png 404w" sizes="(max-width: 404px) 100vw, 404px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>We know the drill by now, so I’ll just post screenshots for posterity.</p> <p>Set the root folder.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 234px; " > <a class="gatsby-resp-image-link" href="/static/7f1b92a55ad3570780a3e7269c909775/7235c/radarr-ui-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 93.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAACjUlEQVR42p1US08TURTuH3SjS0OCEZC1GzfuNUZXKjHxBbpCSNyoQIiVoFX6sJWntVARioidmU5npjNz59H5POfe1tYHJWHx5dzzzb3fnO/cM5OqayaCqE2IEcUqiiCGH0QQYdzhE4QM2uf64UCkzKaD6u4BXs4voVDaRHH1MwrFDSxnCljb3MZi+j3mF98iT1xprQzHDQYLGqaFwyMdmZUSFl9nkC2skVAFm+WqFE4vreDF3BvJ5z6uo2l78ER0vGBda0jLbCeKEgRk0xcdu4SQLMdtZZfRcsVApOq6Sf2KYVNiOR7sli9tKQjJK05InNjDriBfQjtJ5AWcdGig4E+yTE6wVd6mfi0jly+i5QWnF1Q9THCkGVhd38KXSvW3YOtUgmxZ8OyFSNgyleuLkBD8CV9B0Nqj6Hr/R4oHW4RtaJZA9chDTffxvSFwYATY1wTlgvIAh4QfBM4bDose20P1pfDG5bKLlR0Pn/Y8lL55+EBrzlcp36gpPlNxsVsX0kVr0C1z33gTv5mhbNO6D12ODzpeD62/K+SBRTskRP8iOYbr47svkYKNhomaEWEmb2M272Am58g4TfFZVkW57sN0VsXZAu2nvTVDyEttUbUpx2riXUXgzO06hh7qGH6k4/x9HZeeGBidMjBGcYTihccGLk4SKI4/Vc+GHujyXJb63I4jaV8KZnYEzt6t4+pzEzfmLFyZMTGRdnBzwcL1VxbupG3cWrDpeRPXKL+35Eju8nQD5yY05L72CdqWSYTAMFU3TtUwRidVBVwlV8VV8npkUidex9hUj+NzRZqIOOoIanTLjh/L+eO52+vMHq+7c7ivK36/u9Z7+xi225tLOTb8q+IvIKDGngb9c/gLLTKDHKABXkAAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="radarr-ui-settings.png" title="" src="/static/7f1b92a55ad3570780a3e7269c909775/7235c/radarr-ui-settings.png" srcset="/static/7f1b92a55ad3570780a3e7269c909775/12f09/radarr-ui-settings.png 148w, /static/7f1b92a55ad3570780a3e7269c909775/7235c/radarr-ui-settings.png 234w" sizes="(max-width: 234px) 100vw, 234px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Set the indexers.</p> <p>Add your qBittorrent download client.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/7e77a80870f4efdec212e4738325d2ea/01dae/radarr-add-client.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 146.6216216216216%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAChUlEQVR42qWWi46jMAxF+/PzA/N5I412pD6mhfIqJbzj8QmB7SIo3d1IVniEG1/72mEXx7GcTidnh8NBjsejhGEo+/1ejvqsLEvp+166rls13ldVJbfbTXZcWGvdw7nxHHt1GGNkV9f14ks2yvO7NPoe79PsJj0bL1inmzOSJFkHbOpGiqKQzLRyU+C6qQVfl6z3LNI0XQfE/SxL5VfYSd09p21fASSGeNg0jQSapDzPJ2/WKL8EWCtgFEXO460YbgICgmwI9iLVv6FsTCH3+90Bs2Y0sr80s+4pYKHeGSdq6xYi9vB6dfSTOJHz5aJSyqTyGyHwp4BSZSJlLHaWzUku/vplyratRNpS7prdq3qVqTe5hiDT8iIUMBjvMbsF+FgxgJEc67M6zmOJbmaZD64aL4odQK7XJDMCbwICVhRGmrZ1163O/6xDAKHpKkWBiFHzP4CMWKWRJOlUKWuilu3mMAijV11Z3Rm6QRC6TGOxVs01iiXSxkxzRpvoEcyXsgz1i4oYsEsQOABmvC81YYQFUS/3w15flKm3xInbLrSpOeXxOYr4E9B2A1ChFVJo3EziyoomYUypWqzcR5QkM/fOQ58UPN2kTJw4uKjd7/PZ0Wd2999nF1PCQt9cBLS297ubqcOgx3mHKSvmeqKMuNt2EXDoLnhGhoejIHM6rB5BvUEfQ/gvUab1x14ixGuIp5mASm848huQLPnAMlgwll6ri/Dk2flsfbWw1h308/TjCZoa21SaZhM9Nil9ppn5njUOUGnvak6zz0/pv74GT2eDRXg8xmwEcJTNsAHz+Kexiz4+JHx7k/D9XXJNxl29I26j4e2jAU47I3GBVgwyImn8XcDoB4TF3vQJtN2dAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="radarr-add-client.png" title="" src="/static/7e77a80870f4efdec212e4738325d2ea/fcda8/radarr-add-client.png" srcset="/static/7e77a80870f4efdec212e4738325d2ea/12f09/radarr-add-client.png 148w, /static/7e77a80870f4efdec212e4738325d2ea/e4a3f/radarr-add-client.png 295w, /static/7e77a80870f4efdec212e4738325d2ea/fcda8/radarr-add-client.png 590w, /static/7e77a80870f4efdec212e4738325d2ea/01dae/radarr-add-client.png 721w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Make sure qBittorrent has the required category.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/dfc6489203120f841c5f2f597c4e8065/2ad15/qbittorrent-radarr-category.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 68.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAByElEQVR42s2ST2sTURTF5+voxlBc9K+bGivWqlBQEyFtFVxY3NaNO0G/RLBKW6WaKaZpKiYpou6MG8FSaV1oWhQTmHQySWwy8+bnnZekWFBIxYUXDve+98493Hc5xsXrM8Ru3uZ0dJq+sxMMjE3SNxqjv10HOTh36iB3av3Wvhs8N6VhHB+5QvjSDUYi0/ScihIKRxg4f5Xe0QlCw5elaZKhC9cInYzQPzZFTziq0XsmpjmDwj02HOHI0DhHT4xjxBeWmH38jEdLqySSWUxBKv0ScznHgrnKYvIFT5azzD1dYT6xwsPFpJwzpLKvSWVekc69wUzn9PtcIo3hui6+rwQ+eyiqAgdP1wfDRykPX8m9cP8URqPRFGqLYO68597HNe5urPH820agget5KBGoVBxsu6J5rqdoyCABmvLelFy1bVSx2Jqwm6jX6xSl4Xd8JVPXHAdKpe4FdWP7q/lygfuf3/LgS55scbO1kGAVMu2hBDub266XyVsF3pW32aqWDu7wMILdxF8JBo5Qv+AfTujvO0RbSfB/fLkT3xsOmz8s9r7uwPo6FAoYlmWJaStiWrtr7ApqYnRzK8+dDxk+zc9Sm7nFbjzOT9Af5PRHPBSpAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="qbittorent-radarr-category.png" title="" src="/static/dfc6489203120f841c5f2f597c4e8065/fcda8/qbittorrent-radarr-category.png" srcset="/static/dfc6489203120f841c5f2f597c4e8065/12f09/qbittorrent-radarr-category.png 148w, /static/dfc6489203120f841c5f2f597c4e8065/e4a3f/qbittorrent-radarr-category.png 295w, /static/dfc6489203120f841c5f2f597c4e8065/fcda8/qbittorrent-radarr-category.png 590w, /static/dfc6489203120f841c5f2f597c4e8065/2ad15/qbittorrent-radarr-category.png 801w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="51-optional-radarr-profiles-and-custom-formats" style="position:relative;"><a href="#51-optional-radarr-profiles-and-custom-formats" aria-label="51 optional radarr profiles and custom formats permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>5.1. (Optional) Radarr Profiles and Custom Formats</h3> <p>Now we’re gonna pull off a pro-gamer move and make Radarr picky. Now as you may know, there’s a <em>lot</em> possible group/encoding/quality for releases. Some are better than others. Some should never be downloaded at all. Now here’s my preferences. I mostly prefer 4k releases packaged by Tigole/QxR with x265 or HEVC encoding and AAC audio. This ensures a very reasonable file size with great picture and audio quality. Perfect type to hoard.</p> <p>Of course not every release will be like this, so we need to tell Radarr to “score” releases according to our specifications and just grab whichever scores the highest (the one that fits our criteria the most).</p> <p>First, go to Profiles and again create an HD+ profile.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/76b2aa38083fefb6ec2acc653e780860/21b4d/radarr-profile.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 85.13513513513513%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAABr0lEQVR42qVT7XKCQAz0/V+oL9E/fYBWHXTagsB9gnAHaTZyoNWOts3M6s1dstl8sLLWUlEUpLWmvu+pD4G6rrsC3kLoaYiBIvuEM+ANPt57WhHbOI5y2bQtGU5wy/DufEOV9qStp6ZphMAxQAbD3WoYBlJKkTFmztL1J1UxRjollF/6UD09vWh6fnOc4ORzPB4l2UxoraM8z0W6ODBadoJa/ON+TCpDpFpZ8hyYyEDinFsIUS6UpMeOsw18N06Q80TYdpE+i4r7rWZlLSdGVTMhDkmd5UxQfJyUISCVvSjU5NkPg1yv17TZbKRdF4TIAoDQGMs91VTXSoBykkLTRHrNCqqrkoNbecOWXClMhkwABoVyU58WhUEUggR+dV1TVVWXPTwnPBwOAqgFEXYTKpFAAriH73nFZFqIdrsd7fd7SXCT8J5BodJGFAFJ4Y8l3zMMyHKpCMTuQmGWZddDedQweZQHdehv2oR/KTSTwrIsZW2ANBT0/tcKEYyBIdjJmpmZEMP7U8lQmHYXZ2AhxJc/jr8qGT1LhDinHgrhwHsUt9uHCOXb5qDvSHuLCr4A56wyi9W73zsAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="radarr-profile.png" title="" src="/static/76b2aa38083fefb6ec2acc653e780860/fcda8/radarr-profile.png" srcset="/static/76b2aa38083fefb6ec2acc653e780860/12f09/radarr-profile.png 148w, /static/76b2aa38083fefb6ec2acc653e780860/e4a3f/radarr-profile.png 295w, /static/76b2aa38083fefb6ec2acc653e780860/fcda8/radarr-profile.png 590w, /static/76b2aa38083fefb6ec2acc653e780860/efc66/radarr-profile.png 885w, /static/76b2aa38083fefb6ec2acc653e780860/c83ae/radarr-profile.png 1180w, /static/76b2aa38083fefb6ec2acc653e780860/21b4d/radarr-profile.png 1280w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>As you can see, there’s a section below called Custom Formats along with the criteria I listed above. Next to the labels are the points assigned to them. Let’s create them now.</p> <p>Go to Settings > Custom Formats > Add Custom Format and hit Import.</p> <p>Paste the following.</p> <div class="gatsby-highlight" data-language="json"><pre class="language-json"><code class="language-json"><span class="token punctuation">{</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"x265"</span><span class="token punctuation">,</span> <span class="token property">"includeCustomFormatWhenRenaming"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token property">"specifications"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"x265"</span><span class="token punctuation">,</span> <span class="token property">"implementation"</span><span class="token operator">:</span> <span class="token string">"ReleaseTitleSpecification"</span><span class="token punctuation">,</span> <span class="token property">"negate"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token property">"required"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token property">"fields"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"[xh][ .]?265|\\bHEVC(\\b|\\d)"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Remux"</span><span class="token punctuation">,</span> <span class="token property">"implementation"</span><span class="token operator">:</span> <span class="token string">"QualityModifierSpecification"</span><span class="token punctuation">,</span> <span class="token property">"negate"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token property">"required"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token property">"fields"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"value"</span><span class="token operator">:</span> <span class="token number">5</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span></code></pre></div> <p>Hit save and add one more.</p> <div class="gatsby-highlight" data-language="json"><pre class="language-json"><code class="language-json"><span class="token punctuation">{</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Preferred Groups"</span><span class="token punctuation">,</span> <span class="token property">"includeCustomFormatWhenRenaming"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token property">"specifications"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Preferred Groups"</span><span class="token punctuation">,</span> <span class="token property">"implementation"</span><span class="token operator">:</span> <span class="token string">"ReleaseTitleSpecification"</span><span class="token punctuation">,</span> <span class="token property">"negate"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token property">"required"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token property">"fields"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"\\b(Tigole|qxr|QxR|tigole)\\b"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span></code></pre></div> <p>Now these may look complicated but they’re simply just JSON text that has a regex as their value to provide the rules to Radarr.</p> <p>That’s it, actually. Now when we try to add a movie and hit search files manually, we can see the scores that Radarr has given to each release and prioritized them accordingly.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 327px; " > <a class="gatsby-resp-image-link" href="/static/6bea3b352eca3892635d6e6eb4c9a0cb/00e65/radarr-search-score.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 102.7027027027027%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAAAsTAAALEwEAmpwYAAACo0lEQVR42p1USVMTQRid/3/3YnnQg6XlQS2qQEALEVAg4hCSgGyBLCzJZJLZepuN5/fNBAJaBYmHV93pdH/9vvfetCV1gv+BUDGUSTHyI3iBQCQNQqFhCZoo2sDQtEHSRl57Crd774PXLb5hr36I3b19bFZ+oXvlQOgMgYgRyqSA+ItZkgGVHZvONJAD6F72sLC4DJPksKQykCKECH0E3gixVrjJEuSEmzGUIQZ6AmUSDIYeIqGQpBldYu7+swxdZ7dj7LRi7HUTbDUNNk80fpxqbBzrYu7LFFmWIabDyRhSabTaHbjuEEEYoVZvIMtvYLGwSw2FhZrEPOG9LfDBlgSBjzTO7Uo4ATHOqWBSFkuzHJ4f4PDoGL2+Q0wl9g9+F+tWaUaJNOFWU+RpWo5jGJPcGXcfRfs8siGqNNfySPyXGxGerYQ4d0xxmI2I1ATiQWTKuFz1Bqj8tHHSbKHnuJj/tDQ2hTZ4UYxhaAoH74v/GHScFhLoOClMSvO8NCUgNp/3Sb+qxLVHDGOOxuOhZob9wRC1xgFanUuaj7CyukbFM1jc3nZTYf1IwfHjQsunCjL8kAj0XbijAEGkKIvXxUWWIJpXI4ML1yCQLPJ0LXMRzqIfCprLcUEyxSdTXm9GeL4aojMwiKdsuecM6Uup46zVgeN6+PptvWyZGRnDrZbsxAymmMKU9KEpzPBdReDV9whddxqGk9js2FU0z9p3sdEcG45Km1pt9g24+LQacpBZR36ybn8XDDm49rlChZx2g+lcZobsLuvHWvJ8t1ovNeRnaq4q8HY7wuVw+hy6Qx+Hx83i6Rp6IexqrSxY0o1n+kpKJMUrLcbfcST1xJQ3WwIv1qKZYnNryimZ0qe2F5e/lAw5JhfUanug6VGYxZR/GTPDPz+KQ6Yr3IidAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="radarr-search-score.png" title="" src="/static/6bea3b352eca3892635d6e6eb4c9a0cb/00e65/radarr-search-score.png" srcset="/static/6bea3b352eca3892635d6e6eb4c9a0cb/12f09/radarr-search-score.png 148w, /static/6bea3b352eca3892635d6e6eb4c9a0cb/e4a3f/radarr-search-score.png 295w, /static/6bea3b352eca3892635d6e6eb4c9a0cb/00e65/radarr-search-score.png 327w" sizes="(max-width: 327px) 100vw, 327px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Now just as a footnote if you’re gonna play with this around some more: Radarr will always prioritize quality over whatever score a release may have been given. Meaning, if you have a release that has a higher quality than what matched your criteria, Radarr will choose that. Check out Radarr’s <a href="https://trash-guides.info/Radarr/Radarr-setup-custom-formats/#radarr-current-logic" target="_blank" rel="nofollow noopener noreferrer">complete priority list</a>.</p> <h3 id="6-optional-bazarr" style="position:relative;"><a href="#6-optional-bazarr" aria-label="6 optional bazarr permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>6. (Optional) Bazarr</h3> <p><strong>Note</strong>: This is only required if you’re going to use a media server that does not already fetch subtitles. Since I’ll be using Plex, I can skip this.</p> <p>Since we’re done with our optical media, it’s time to subtitle them.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 438px; " > <a class="gatsby-resp-image-link" href="/static/628e0164ae56452b2fd2e4789bcecfdf/50e4b/bazarr.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 70.27027027027026%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB/ElEQVR42pWTPasaQRSGRfwD1hbWaVKnSJHiEhIhxYU0gRSBC/kH+gcsFMTfYi8WgoUIFopfuxuv3yt+XMHV6K7u7rzZd9w1gXAT78BhZs7MPDPnPXNCQgjQHMfB+XyG67oIfM+Z4wgAAoNHgftPwN074PUr4ON7FyFvBYfDAYqiQFVVaJomwf9rwr30PzTg4Rvw9g3w4c4HlkolRCIRhMNhRKNRdLtduZmv/VcLljUV+PoF+HzvAwuFAmKxGBKJBOLxOOr1+k3AP6GqAnx/8IGbzQblchmNRkO+drfbXcISAre0AKrPfOBgMECz2US1WpV6vgR21VQQ7FyAo9EI7XYbw+EQx+MRlmXBtm0ZMrNPu+UC7pNAQhjmfD7HcrnEYrGAYRh4aZNA0zSRy+WQz+cxm82wWq2wXq9Bf6VSQTabRSaTkfo+lyiCeIZRhahZOp2W0O12i8lkgn6/L7UsFotIJpNIpVKo1Wp/AQMZKBHPyBfSGWi13+9x8DUkkB88WKeP0pxOJ7kmtfai8NG/Q+ahVqslK4TVMh6PZXI45630dTodOack0+lUjnu9HvqPA5jW6Yq8AlkZmld2BDDj3Mye34lGv67rV5+iXGDGSsdpM/Vq9wkwDTiuQIhUZpjGzNKoZTCmDIFxftlL/0/Y1gHC3MI97uB6Y9t28AuAhg6td+JnJQAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="bazarr.png" title="" src="/static/628e0164ae56452b2fd2e4789bcecfdf/50e4b/bazarr.png" srcset="/static/628e0164ae56452b2fd2e4789bcecfdf/12f09/bazarr.png 148w, /static/628e0164ae56452b2fd2e4789bcecfdf/e4a3f/bazarr.png 295w, /static/628e0164ae56452b2fd2e4789bcecfdf/50e4b/bazarr.png 438w" sizes="(max-width: 438px) 100vw, 438px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Now go open Bazarr’s web ui, go to Settings > Sonarr and tick Enabled. Input these settings. You can get Sonarr’s API key in Sonarr’s Settings > General > Security. Hit Test to validate.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/0ef2dccc3db139c053e30e03bd2337f6/0f529/bazarr-sonarr-config.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 53.37837837837838%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAyUlEQVR42q2SMQvCMBCF/f/+BQdXwVUXQRREF0EEQQc7OOhSaZpYMbF390xaC66tCTzuCMnHe7n0mBm51iiKJ2KsHlmCSnNY5yIBS8LDFBCRSEAf2RgD9sCADOCuqoFE0NrgZS2IuIZ2UGOocmitQxhOUBSHuVLgsoT4XuhbW8KYQ/XA0l82IW6w/RujLbCJLM7D1gtgOYPMp+DJCLxdQZi6OXT0RnI9IrnskN3O8PnB6l4fbDmY6g0zqzE4jdE/DLFJ99Um//EnP5B0YyP0UMdPAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="bazarr-sonarr-config.png" title="" src="/static/0ef2dccc3db139c053e30e03bd2337f6/fcda8/bazarr-sonarr-config.png" srcset="/static/0ef2dccc3db139c053e30e03bd2337f6/12f09/bazarr-sonarr-config.png 148w, /static/0ef2dccc3db139c053e30e03bd2337f6/e4a3f/bazarr-sonarr-config.png 295w, /static/0ef2dccc3db139c053e30e03bd2337f6/fcda8/bazarr-sonarr-config.png 590w, /static/0ef2dccc3db139c053e30e03bd2337f6/efc66/bazarr-sonarr-config.png 885w, /static/0ef2dccc3db139c053e30e03bd2337f6/c83ae/bazarr-sonarr-config.png 1180w, /static/0ef2dccc3db139c053e30e03bd2337f6/0f529/bazarr-sonarr-config.png 1259w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/c876c32451c8e0c268b0271dfdaba4af/35252/bazarr-radarr-config.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 55.4054054054054%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAwklEQVR42q2SsQrCMBCG+/w+hJtuRdCl4uLuIjqqUBErihSb0DQ1uftNWgRx0qYHf8j03XfcRXAlhESe5yAihFbElvG4PVAqhT4qYubGkJj6AfpHSglrLdj9yTXoGi/XAAtnqKoKxpggO8drR660hnULeXcJSWMoCoFnrd28BPaj+3QF+kfqGn4l/JkQQ7NeAcsESCag6Rg0j0GqbMHe+l9gdjnglG5wz3agawY6H1vQt/UPifz9jfYzDLZDxOki+A5fcfVi/hVi8OsAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="bazarr-radarr-config.png" title="" src="/static/c876c32451c8e0c268b0271dfdaba4af/fcda8/bazarr-radarr-config.png" srcset="/static/c876c32451c8e0c268b0271dfdaba4af/12f09/bazarr-radarr-config.png 148w, /static/c876c32451c8e0c268b0271dfdaba4af/e4a3f/bazarr-radarr-config.png 295w, /static/c876c32451c8e0c268b0271dfdaba4af/fcda8/bazarr-radarr-config.png 590w, /static/c876c32451c8e0c268b0271dfdaba4af/efc66/bazarr-radarr-config.png 885w, /static/c876c32451c8e0c268b0271dfdaba4af/c83ae/bazarr-radarr-config.png 1180w, /static/c876c32451c8e0c268b0271dfdaba4af/35252/bazarr-radarr-config.png 1204w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Now we add a Language Profile. We will set this profile to be applied to all incoming TV Shows and Movies.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/64e9a7eef786a4a1fabe40fb52707520/0d0e4/bazarr-language.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 70.94594594594594%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAABTElEQVR42qVS2ZKDMAzj/z90HwoBmgRCTq1ljp196A7bMtXY1EaR5XQpJRgzYp6fGKcZtVZ88nSlZCEzMMMD62IRtwVb8NgkMm81AU2gMe+5xvKCMEdM5gvBG+lx0ktYRZUcxR9gvhxR3mt4pbDoyCllGbehtgb5SYTm9cqx14+ePa8KchAX4TzPmMQ/a0UZ2T7xMMYkZBO4nL4f4JxT0hACxnEULzfxsWpkn7XuUpRzkf+jxHwts0tCyA2z8FBCj3VdsSwLrJB7v+ghzFk764SXnn4YpcfrgfvItcDJR/NTNiwq1T/6Qn/kJYsSkq1r0Fo5aifo5ZkrYXABQ2+E1CNwvLab/a6XXY4Z9unUQyqMMer4717wjkroEY3Vh8raz5W4g1/XZnObjryJMm6cYH42/FuhyNH7x3HPk4jTxzs4lR6EUP9IcpfgL8JvEmhPg7SRNPMAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="bazarr-language.png" title="" src="/static/64e9a7eef786a4a1fabe40fb52707520/fcda8/bazarr-language.png" srcset="/static/64e9a7eef786a4a1fabe40fb52707520/12f09/bazarr-language.png 148w, /static/64e9a7eef786a4a1fabe40fb52707520/e4a3f/bazarr-language.png 295w, /static/64e9a7eef786a4a1fabe40fb52707520/fcda8/bazarr-language.png 590w, /static/64e9a7eef786a4a1fabe40fb52707520/efc66/bazarr-language.png 885w, /static/64e9a7eef786a4a1fabe40fb52707520/c83ae/bazarr-language.png 1180w, /static/64e9a7eef786a4a1fabe40fb52707520/0d0e4/bazarr-language.png 1230w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Next we add our subtitle provider. Go to Settings > Providers. Do create an account first.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 499px; " > <a class="gatsby-resp-image-link" href="/static/f2f23e7cf4234075eb87e3fad248beb4/119c7/opensubtitles.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 66.89189189189189%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABWElEQVR42qWSu07DMBSG81i8BRIDax+DjQdACKbOsCDEwMpclQUYkToiVekliZM2CbGbi+38HDspbSUujWrpky376D//OcdOlmXwgwABUVXVQbiuC6ekQ5wkSJIUh675fA6nrmsYtNaQUlImubPvQ1lWVtBU6ZhDHMfW7mw2w3Q6sZk8zyPXCdI0/ZflcomiyBGGrBE0WZRBqTZjadm3dybWLMZawbwowMII0WJBbhNqATqhdb0raAaTpJ+WjHNI47QDFVW1Iyi1ghCrb+vaDKkDiga6EaQLHgkIvgIXAnleUC+1LeN36J2crZFSbaZcU8B4MAbzIwSUgbHQfqMuax1vHa7/4bbI9t2PUAWKC6iMQ9EfLLISeqXhe37TwyawFfvLStur/H2E8UkPk9MePs6ucHf8iJujW7w+vDUOO9Rmt8qdIrzsY3HdR3D/hOeLFwzPhxgNRvgCvuTvlmUlKUIAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="opensubtitles.png" title="" src="/static/f2f23e7cf4234075eb87e3fad248beb4/119c7/opensubtitles.png" srcset="/static/f2f23e7cf4234075eb87e3fad248beb4/12f09/opensubtitles.png 148w, /static/f2f23e7cf4234075eb87e3fad248beb4/e4a3f/opensubtitles.png 295w, /static/f2f23e7cf4234075eb87e3fad248beb4/119c7/opensubtitles.png 499w" sizes="(max-width: 499px) 100vw, 499px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Now Bazarr will automatically download English subtitles to our media and place it alongside the files.</p> <h3 id="7-lidarr" style="position:relative;"><a href="#7-lidarr" aria-label="7 lidarr permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>7. Lidarr</h3> <p>Our final Arr, for our aural media.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 440px; " > <a class="gatsby-resp-image-link" href="/static/f88647d3f6a7ca2d24be1fb1322720e2/48c0e/lidar.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 70.27027027027026%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAABr0lEQVR42p1TPUvDYBDur3F0cBBcRQcHEcHJ2cFJnOzk1HYSKt1dHPwJguCkSxGLFKWSxnz0S03aorFN2zRfj3neklgQwfbg3o9775577i5J+b6PMAyFUrgHQZDYZlFipbhQ7h7ucVI4RfnpMQGeVUgkxcO7aWJ1ewNLB1vY3NuFWtfnAk0An2UJy1trWDjeweL6CmRVmTiEweyAXCiX11fYPzrE2cU55pWEYbPZRKlUgqJrc/XuF6BhGCiXy+i023BGI/iBnzhwaPGX8O+Sh8Mh+v0+arUaWq0WRtF9boau66JQKCCbzaJer6MdsTSjqQ8GAxSLRWQyGeTzeXS73T8nzwoYIwDH47EIyOVyIogMNU3DIGJ5e3ODdDotQBnwFyAxFEX5KdnzPJGFDyx/FPWRLXAcJ/kLaLdtW7yRfXyfTpCUXKlURIZGowFVVcXUdV0XNt4lSYIsy0LZZ+H/8gKpWsWnZeHD+oLrTQaXIjsG0pGlEoiAPNMWA9NGYCaYJG+iY77BNjRYrwq8nomQDAnI8qgsYXqPz71eT2hstyJWPLvOEKHTRzi2ETi2aN03h+cifflR6AMAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="lidarr.png" title="" src="/static/f88647d3f6a7ca2d24be1fb1322720e2/48c0e/lidar.png" srcset="/static/f88647d3f6a7ca2d24be1fb1322720e2/12f09/lidar.png 148w, /static/f88647d3f6a7ca2d24be1fb1322720e2/e4a3f/lidar.png 295w, /static/f88647d3f6a7ca2d24be1fb1322720e2/48c0e/lidar.png 440w" sizes="(max-width: 440px) 100vw, 440px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Much like Sonarr and Radarr, let’s use the same settings.</p> <p>Set the root folder.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/22ccf4538cfa03ada170cc8252e94a79/eb4a1/lidarr-ui-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 64.86486486486486%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABSElEQVR42o2TDW6DMAyFe/+79Cg9QqVJ0xjaCoGSkF949UsXVFi3EunJiUm+2I45KKXQilTXIaWEeZ4xTdNi94jnONpW4eCcWzlpU4zw3mf/fcwbrQcv5zBaC1AOPjqttbgOA6rPGkr1svZwLsA6j9E6BLnsT6AxOPgNkFFpfUX98Ybq/Yz2UqFra5ihgTMK0dt9wPIhTVI7rzDrMxAaqYEW24sd7pr8fiDrR+egDb6+G0nRS4oJPlARzkfENP0PdA/AKPXhI43jmF8shLASL08p7o+QczoJ7bo+rwsoz+XCcvglkNEN8rr3lDUuTZPB/F7supVeALmRqZbDWqBW5k7axUq7sDS0pV93AenIKeeoityi3IO/M94AJSopFL3LBsJZgvzXFMn6Wbpl/wLsTyeY4xHhp+h8hAJ7hHL+TMyw7/lHsTNa3ADJcP1khOb2jQAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="lidarr-ui-settings.png" title="" src="/static/22ccf4538cfa03ada170cc8252e94a79/fcda8/lidarr-ui-settings.png" srcset="/static/22ccf4538cfa03ada170cc8252e94a79/12f09/lidarr-ui-settings.png 148w, /static/22ccf4538cfa03ada170cc8252e94a79/e4a3f/lidarr-ui-settings.png 295w, /static/22ccf4538cfa03ada170cc8252e94a79/fcda8/lidarr-ui-settings.png 590w, /static/22ccf4538cfa03ada170cc8252e94a79/efc66/lidarr-ui-settings.png 885w, /static/22ccf4538cfa03ada170cc8252e94a79/eb4a1/lidarr-ui-settings.png 1083w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Set the indexers.</p> <p>Add your qBittorrent download client.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/7b63d400c9d8165672cbd138a5c2ce57/c67d4/lidarr-add-client.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 132.43243243243242%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAYAAAC3g3x9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB90lEQVR42qWVWW7DMAxEc/+/HKC36gH6kcRLvcT7bpZPsYqk8SKgBghLMj0ckiPpVBSFhGEogZrv+2qBJEkit9tNgiCQvu/F9bler3Jq29ZM5nletXGaZNbvk463DB8eiJy6rluN1jSN5Mq+63q5aOQsyzYDTwtgmqbbgKxXVSV+kUit4NM4bqYK6CGgYZjn8hl+STcOu7VzAhyVEQyHYZDvKJL0fj+u4RFgXdfS9p1kyrTTbv8LkEKTdqMquCs72en0ISA1AaRShnxnvCUrpy7jhOBJmVSRj5MO9wARKaCD1pKG4LclcKcaIpmyLKXV74W+TaA1W0APAZEMKef5Y68DDnD5a5XxKTEdH+rwGZjIOFMGmFMC3r1qFJ3aA2QVkBTiODasAKIpMJWNdOdlm86uDBF1FCdGQjSJOexIP9NysGbYauBd2VjD8Sjo4V7mqPI83zjQZXTIT0joryEZSkKnnVK28qE5Nr28eKwxtp1mt2wC0jmczeGge3kv6Lz476aMA/uXyDSDrnNI1HVj5gRCe6w5AT4/tim87dgac9u8d8Bl0T5WyDjTpEgPWZiyhj65JU0WS33HvRq+sxxeWGHU1qb6wrDVCJPnyah38MyVuXLerR2+z2fhuFxg5hptLhdpzmdpPj6ortOFjgJgSykw2JI2DH8AQvL4flQr3W0AAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="lidarr-add-client.png" title="" src="/static/7b63d400c9d8165672cbd138a5c2ce57/fcda8/lidarr-add-client.png" srcset="/static/7b63d400c9d8165672cbd138a5c2ce57/12f09/lidarr-add-client.png 148w, /static/7b63d400c9d8165672cbd138a5c2ce57/e4a3f/lidarr-add-client.png 295w, /static/7b63d400c9d8165672cbd138a5c2ce57/fcda8/lidarr-add-client.png 590w, /static/7b63d400c9d8165672cbd138a5c2ce57/c67d4/lidarr-add-client.png 723w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Make sure qBittorrent has the required category.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/e7952638c0e248fd25129951c9f58440/76cea/qbittorrent-lidarr-category.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 68.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB20lEQVR42qWSXUsbQRSG9+f0Qmj0Qm0lzYWJYlNB0lKNqLFooCXXQkuvC/oXCqU0VG0VSYL5kJIPi1FQKN5YUkswKbZgMEKazW6zu7P7enZ0SSxFTT3sy8y+c+bZM3NWeOSfwVjgJZyPn6JzYBzd7gk+dt1vzJv9breP1hq+5d154EPP4CSEDpcX/SMBuIafob3Pi46+UdiHptBFSe1OL+4OPsG9oWnc7h3hvo08E9JDvimHxw8brd2ye9DmeAghuLSK98tRLEU+IRxLI0KKrn1GiMaP5K1EkwjF01gMJfCBNL8SQziRQTyVRSyZRSK9xd8Xw2ukBAQYBgxdB2CgTpJJEkklXQiex2j4y28KxhgEXTfOkuh5W9jB7LcUXuWSyJTy3FM1DWZOpfIbkizzjToVYG62pKgq5GoV6tERVXhFWBVVaYMoinyuUaXMhJJMuEbQeq0Gdnx8NdAKRVE49F9HNsEKVa+Xy60BrQpz1RI2ygfInhSQE0v8ajQ6NqP1awP53Z1Xt1kuYP7wCxYOd2l+cLEprQAv6zAHUgNbAjaDzWqZoXNZH/pv4KX/4U0AP+UKvksnUH4Ugb2vYMUiBJna3aokWYL2p46F/Dbm9tfx681raM9fQAy+wylUj+WeywRC2gAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="qbittorrent-lidarr-category.png" title="" src="/static/e7952638c0e248fd25129951c9f58440/fcda8/qbittorrent-lidarr-category.png" srcset="/static/e7952638c0e248fd25129951c9f58440/12f09/qbittorrent-lidarr-category.png 148w, /static/e7952638c0e248fd25129951c9f58440/e4a3f/qbittorrent-lidarr-category.png 295w, /static/e7952638c0e248fd25129951c9f58440/fcda8/qbittorrent-lidarr-category.png 590w, /static/e7952638c0e248fd25129951c9f58440/76cea/qbittorrent-lidarr-category.png 799w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="progress-check-1" style="position:relative;"><a href="#progress-check-1" aria-label="progress check 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Progress Check</h3> <p>Time for another one. Now I know we’ve really done a lot now. We’re now able to automatically procure media of all types. What’s left is a way to consume them.</p> <h3 id="8-plex" style="position:relative;"><a href="#8-plex" aria-label="8 plex permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>8. Plex</h3> <p>Arguably the reason for most NASs, Plex turns your collection into Netflix.</p> <p>Now I know we’ve been using Hotio’s images for a while but for this one, since I’m planning to buy Plex Pass, which is the pro version of this, and I was an idiot that didn’t use the correct network type and incorrectly blamed Hotio’s image for Plex not working, I went with the official Plex Media Server image.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 435px; " > <a class="gatsby-resp-image-link" href="/static/a4913c39686e438452a0252f358fbd35/330eb/plex.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 70.27027027027026%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAACFUlEQVR42pWSy2sTURTG8weICEKlGxeC4EJ33XRRMOBGRVdipdtqBRcJmJ2PZXRhSYSA5C8Qs3HhShDSnVihGVBa8p5JyLt5EPKezMzn/U4noQim8cLhnnvuub/zzTnjgSwHtu3Askwss2z7ZM9lgXu3gVte4Po14P5dGx5edFs1vHu1g+0HXnz+9OGkhLMY6rjQrII+2QY21hX8jgt8//Y1rlw6h93HK1hfuww9te8qsZdSmk4Bjx4CW5su8OXzHVy8cB4fX6xi7cYKtJ9fJdGypkqpI3YW9OgIePbUBRayh/Bt3cSm9yp23wRUxITj9vZ/elopK6BlWUilUjjY/469b1+gHfzAr9+HEtM0DclkEoZhLAUlS4CGbkBX1m53FCiDtGpKuVxGJpNRdzqq1eriAbktmU4VkIdut4vJZALTnCzs11lLFLbbbQSDQUSjUVFSqVTEhsMh4vE4QqEQwuGwqD2t5m9Qo9FQCqfw1Go1BAIBRCIR9Pt9FAoF5PN5jEYjxGIx+Hw++P1+JBKJf/5K4/FYCopCJtB4oKrBYCAJ9BmbrYmKjU8ZW8SipmnKzlxyPARk1e9OYxWqk2GoyXJnnD6nTb9YLEo8l8vJWVdD41exANvh6fV68wQ+rNfrAqVx0nxQKpXkcTqdFuAMRJ8wzmE+FMpnQ2m8aDab4rdarbl1Oh3Zec+9eXws/uxMEAdClX8AsiYCoQs1kiQAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="plex.png" title="" src="/static/a4913c39686e438452a0252f358fbd35/330eb/plex.png" srcset="/static/a4913c39686e438452a0252f358fbd35/12f09/plex.png 148w, /static/a4913c39686e438452a0252f358fbd35/e4a3f/plex.png 295w, /static/a4913c39686e438452a0252f358fbd35/330eb/plex.png 435w" sizes="(max-width: 435px) 100vw, 435px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>The config now has more fields. Primarily because of more volumes to map. Nothing complicated, however. One thing we need to do though is to generate our claim key. This assigns our Plex account to our NAS. Go to <a href="https://plex.tv/claim" target="_blank" rel="nofollow noopener noreferrer">https://plex.tv/claim</a> to log in and generate one.</p> <p><strong>Note</strong>: Set the Network Type to <strong>Host</strong>. This container is the only exception. <span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/d5aff3873e3b3717ba62dc07a48c9397/5148a/plex-container-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 43.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA+UlEQVR42oWRa46EIBCEuf8hJxFFXs37ALXd6OyaSZb5UUGl+agqldYax3HAWosY41I5Z6SUQES/+pxRIQSMMdB7/1eDVWvFpncYc/JzQSmXxmNGViXUr8DRUWrDSwdoQwhUEEmAbX5/SoltAa6gcnthh/thoVnWJ/iYJ5RynYqpIvGqpENx2VpbOByzP8NdE88mkvmKxpeI+7dmZGMMpEfpaBVb9p1zd3f1TiV749KdUJ0M/BZZDsiPiMGzqzIlF1TurDmD7nb0c0PP8eqwL+I+gYEPeRZ58wf0Fp3fu2VooRu4hF1AceXNBsei6K/oDG3uZIcHS0/gDxp3qqRmzCFSAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="plex-container-settings.png" title="" src="/static/d5aff3873e3b3717ba62dc07a48c9397/fcda8/plex-container-settings.png" srcset="/static/d5aff3873e3b3717ba62dc07a48c9397/12f09/plex-container-settings.png 148w, /static/d5aff3873e3b3717ba62dc07a48c9397/e4a3f/plex-container-settings.png 295w, /static/d5aff3873e3b3717ba62dc07a48c9397/fcda8/plex-container-settings.png 590w, /static/d5aff3873e3b3717ba62dc07a48c9397/efc66/plex-container-settings.png 885w, /static/d5aff3873e3b3717ba62dc07a48c9397/c83ae/plex-container-settings.png 1180w, /static/d5aff3873e3b3717ba62dc07a48c9397/5148a/plex-container-settings.png 1228w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Now let’s go to Plex web UI and configure our server. Add a name and all our media libraries.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/276065a7ceccad05f97f465034fea068/0ad97/plex-config.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 116.89189189189189%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAAACXBIWXMAAAsTAAALEwEAmpwYAAADDUlEQVR42o2U3U/TYBTG+Vs0so11W9t1bdfvz3Ubm4wxHFGjIogmgBrQhAtjMDHGC+5IvPTKeO+Fif51j+d9u40WCnjxS9u37/v0nPOc06WaFuIyjXaEZdHG+OEufv3+i939Y7w9+YzXh69wfjpCf7KNkmSjrkeLM3U9ZammZRcjjmjEuNew8GjnEF/OzvHh01d8+/4Tx0cH+HG2juF0hz5oLQTnYhnBCIIaotryCJ+zongQ26lwOxjC7oyhux3IZhdNp0/7g5xQSpQKMjG2MRxswe1NEAymsJMNVOmQQO/LTQ8l2UVFCTjsg1mRLEs1PRUUjQ6c+D4MfxV2NORIRgjFjDlNM4JMz7IRoMEPh4WiqSDRoPQ0h1Jq+5B0j6NaETqDDY4TraJp+CQeQLGTnCELD9ozwTlVLUVYENP6VebRsG7IpTwXFEhdNBNEwymcLkVDBgSDB5BojdVL4LUMeWkYRa3GxLjgPHTR7MDtjol1WPGIXF2Hk7D7Nbh0tWnNSUawojVo3ip0f8Bh9xrVvWFkBOuzGqr0suX20XJ6/J4dUF2qHUXKTJOthL9je3NQ3+YinJNNJ+3LgIQSDCZPMNp6jrXpNhnS4+lfrl2hYK4ms2cW0dO9N3hx8J5G8B1v8rSpZ2cYRYJsk0h9pvt93hYlyURZtggTd2sa7ggq52I9pa55aDRN6g6fu750ER1NQdNGy+pAc7sQdZ8f5gJEhQlI1mJtTqXJhA0qg5+PkKdJojK5Lag+bXRont2babm014PQcij1ICNITjERqR3Q+A35mLFNVYq41GgXI6bUFAs1Uae597jjJBgvImQ1qSoOzWpAcxzx64ri3EhFsVFW0ggzNYy5KTKJmCG5SKmwet3IzJQGM0UuMoUEK/RCsWKqY/pnYWkv8/SMYiSDnynTlZVslvJ1fXgLvO+y91E+wqLf0XWwKao0XTLCR7kVYpl+uoIeX52U22ARsHF0kjGOTk4xebyH85cy/nxUsdmj0qid/P/wf0TZHGveAJskFg23sD/RcfpMRxzaWNFi/ANi2gxNJUdgxwAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="plex-config.png" title="" src="/static/276065a7ceccad05f97f465034fea068/fcda8/plex-config.png" srcset="/static/276065a7ceccad05f97f465034fea068/12f09/plex-config.png 148w, /static/276065a7ceccad05f97f465034fea068/e4a3f/plex-config.png 295w, /static/276065a7ceccad05f97f465034fea068/fcda8/plex-config.png 590w, /static/276065a7ceccad05f97f465034fea068/0ad97/plex-config.png 717w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Et voila. We now have a fully functioning media aggregator in our server. This is accessible by any native Plex apps your devices can install (Android, iOS, Smart TV, etc.).</p> <p>Now let’s set a few more details for Plex. Starting with subtitles. Go to Settings > Your Server > Agents. Create an account in opensubtitles.org and use your credentials in this field. Rearrange the Local Media Assets tab to be the highest. This is so that if you ever use Bazarr or would like to use your own metadata for a specific entry then Plex will use that over whatever it has downloaded on its own.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/4699ab6f9a5e73dbb8f68b8d14cdba53/eb3fa/plex-agents.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 50.67567567567568%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZklEQVR42n3S2XaCMBQFUL5GQUWGMCNgLJNSrasvbZf//x2nJ8GhWtuHTabFvclNjLw+Qg4faPZf6I8n2En9y/IivWg4pqyBTYtoA5sczhvq4yQvcNkq82B9LxwtHkUjO5ZI5IDsZQ8va2HMuDhxc0y9FabuCqZXwPSJY9Va/oqKe2Jkcm0Zr9G9fWL7foIoOhg2J8I81rsURQ8vb3WmoNiy3yEoe7gcL58eveYxa55AYkbnI9eIqx4+g/lRgjQViBMBL90gWg/aXcCHYCq5SjxqVcAW4frAOuwR8+dE7hCWHcSqZ7vTBHcblGdMfO1TeE6o+AxqzASLm/aIqi31DNTq2ugaarluVS3NH6wLMdbZjir4WQ3DEuxUB1TdEdlmx4vJ/ufdmFquealEWDQqYIlYviJi8S0uTJ0Uk7+4N1Ptlsjl5YqcO1zwdlI56Lek3pfll5iJJ4J786Di7VbXd+okkvXt8A3hoUpUc9xypgAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="plex-agents.png" title="" src="/static/4699ab6f9a5e73dbb8f68b8d14cdba53/fcda8/plex-agents.png" srcset="/static/4699ab6f9a5e73dbb8f68b8d14cdba53/12f09/plex-agents.png 148w, /static/4699ab6f9a5e73dbb8f68b8d14cdba53/e4a3f/plex-agents.png 295w, /static/4699ab6f9a5e73dbb8f68b8d14cdba53/fcda8/plex-agents.png 590w, /static/4699ab6f9a5e73dbb8f68b8d14cdba53/efc66/plex-agents.png 885w, /static/4699ab6f9a5e73dbb8f68b8d14cdba53/eb3fa/plex-agents.png 1026w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Do the same for TV shows.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/1bfff3b49ab86f55ef0e504444ca9398/22c86/plex-agents-2.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 52.70270270270271%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABfklEQVR42n2T2VbCMBRF+RcHBOyYtCWd6FxaVETe/P//ON6bAHUB+rBXSgn7jsz8dEBc7zVpe4AV1Xex12eaCdXAoncO4cYt0WHmJT3W1buRNntYYY1XwtJUfwZgEeOnHWQ+aJkWrsIST7bCox3jwYoxd5MJLyUSvNB5wZ9YENV4xO74DZlu4agWM05dZAN9KOArRVF6uJS1oAsuXZD03XWZZxziXCrjJZ0R8o9kvoWnaohQQkRrcG+DfIRPctNDI7RO2L/65pxk3D4Stgg2A8JiR5mOCLKORL0OEmxGnb0JOEBQULkxzwHBEpNZPwlXsgBLw2KkIRTUlwwLken+XBCpecdI87ySGZZ0cl/9uNHV6aEs/Bxh+YmsP8CJChpGjGdH3eJOzDUxyRJ9WkEOkTQnodggzFqoctCRVjLXAr54gzfx4hkhs6QqnKg0JXOGaf2BcvhCUr9dov4vMyJeHV4rP6ZyVaW3Y2ZFzdXSVvdZT9j632HWhvFo2ueh/ADmIWsxcl0JiAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="plex-agents-2.png" title="" src="/static/1bfff3b49ab86f55ef0e504444ca9398/fcda8/plex-agents-2.png" srcset="/static/1bfff3b49ab86f55ef0e504444ca9398/12f09/plex-agents-2.png 148w, /static/1bfff3b49ab86f55ef0e504444ca9398/e4a3f/plex-agents-2.png 295w, /static/1bfff3b49ab86f55ef0e504444ca9398/fcda8/plex-agents-2.png 590w, /static/1bfff3b49ab86f55ef0e504444ca9398/efc66/plex-agents-2.png 885w, /static/1bfff3b49ab86f55ef0e504444ca9398/22c86/plex-agents-2.png 1143w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Next, go to Settings > Your Server > Library. Check the following boxes pertaining to Library sync. This makes sure that Plex’s libraries will reflect whatever you’ve downloaded or moved to your media folders.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/e6b8bbe4a44f55d6dc4721bbb0e56fe1/7bf07/plex-library.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 43.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABS0lEQVR42m2Sy07DMBRE+y8gtYjmXTVx7DQiidu0VaGPJT/ChhVCYsEClnztcH1tkyB1cXRvHprMjDOZ5y2yaotFtcOy3vMe0L1rhIWnGxCW2FCuMTGC+cMB1frMKH3CfNkgGJM3CMeC413YGXnBUGjMshVugoIQuCWmsXJITBOJmeMuVQMZPU8lEtlif3lGu7sgIuGJiRLXR4j2CWVnMV8yccyMS01xNM+/+MWAibqgmjLVW4dB3rGgFzOI5hFFc6A+e34xNZOISNh3ZrAxNd83JNIJLpsTVv0F1YYmUdOu1iekRkxZsbBwDsl5UPiD0C6FxQlqCDoUdteSM9pF6x1urcsR3u1QhRPzgiEJRvWZO5TdEVIf+UEiNzz9l/la+d11W14RNA4Xqz33VvdnvLy+4/PrB28f3+z2nn6bkGO6g6CowV9//+MawV82EzNJ07LtpwAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="plex-library.png" title="" src="/static/e6b8bbe4a44f55d6dc4721bbb0e56fe1/fcda8/plex-library.png" srcset="/static/e6b8bbe4a44f55d6dc4721bbb0e56fe1/12f09/plex-library.png 148w, /static/e6b8bbe4a44f55d6dc4721bbb0e56fe1/e4a3f/plex-library.png 295w, /static/e6b8bbe4a44f55d6dc4721bbb0e56fe1/fcda8/plex-library.png 590w, /static/e6b8bbe4a44f55d6dc4721bbb0e56fe1/efc66/plex-library.png 885w, /static/e6b8bbe4a44f55d6dc4721bbb0e56fe1/7bf07/plex-library.png 1128w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="9-organizr" style="position:relative;"><a href="#9-organizr" aria-label="9 organizr permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>9. Organizr</h3> <p>At this point you may be tired of either memorizing ports, bookmarking the different web UIs or just plain typing them out all the time in your browser to visit each. I know I was. So there’s a better way. There always is.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 440px; " > <a class="gatsby-resp-image-link" href="/static/94359ce2ba4b38de0a076f093b95460f/48c0e/organizr.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 69.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAACDUlEQVR42p1TS2sTURidP+TClUIt4sKFglsXQqHgHwj1FwTiwiSuIiiuKlVBilIQdOEQweLCQGiTEEMmyWTyJCmTx+Q5ycyd45ybTIWibfXCx8x8j3PPOXOv4jgOXCEgPIH5fAbB9wvCcQQAgUrFw727wK1N4OoV4MZ1D4rruuAqZNp4+uQtXu2+R5A7b3ne6qlXgIfbwM0NYOOaD8ikoZt48fI7uPH+vorPn77KZtcV54KKdVkrAttbwJ3ba8C9ZAZ7h5osVr8dQ319sBq4BNMAtFwGHtwnoM/dWth4/uUYb559xOHjXdjWeC3Lw2VWAFozBBSOmCcn+JFK4cO7A2SOjlDyjTFN859BaZHCgW63i2w2C6NmoFavwTAMjMcrlvIU+NKFEBf8JG8FyMbRaIR+v492u41qtYrhcIj/WcRSbNtGIpFANBqVzMq+u41GA9PpFCnfhng8jlgshnQ6fTr0JyCqpBJlNpshEokgHA7/ZqnrElBVVTza2UEoFEIymfwrIG0hEQnIBupnkr4xuMl8PpcNrDGWyyUmk4m0h5sx+M2+oFdKZiPRS6WSf5Uqkp1WLKLZbCKXy6FQKMhgXWdN02Q9n8/LYI71Xq8n2SqLxUIC/vSL9LBer6PVakkG/DlkQSssy8JgMJBecZg15vnsdDqn91wCUmbPP3c8e5TEXCA1sOTs+9kcJdO2X2GqGLw4H2ZjAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="organizr.png" title="" src="/static/94359ce2ba4b38de0a076f093b95460f/48c0e/organizr.png" srcset="/static/94359ce2ba4b38de0a076f093b95460f/12f09/organizr.png 148w, /static/94359ce2ba4b38de0a076f093b95460f/e4a3f/organizr.png 295w, /static/94359ce2ba4b38de0a076f093b95460f/48c0e/organizr.png 440w" sizes="(max-width: 440px) 100vw, 440px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>After installation, just add tabs like below:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/5b48eb97054ceeb74f73916f272c9af5/df88b/organizr-tab.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 39.86486486486486%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAvklEQVR42q2QSQ7CMAxFcw7ajM7cLlhwAMQaifuf5uO0SqUWIZBg8eQh0f+2RakVdZoRYoRSClrrnxC1Tgg+wBgD3QR/oQnmXFBShpbyf4I554+fFRuqL0xFigmJ7/dOpOfkCET+IL43cNZCFL6h54/thpYbHeccIpv1nJgWW00U+C0vBtZYGG0Yu/TEXHnllOCIXgS995vIHrcKMW3yFpfJh4FXvj0QzxcYXkGO447xUG/IjlwZTlCJN73e8QQl3twoUJUv5wAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="organizr-tab.png" title="" src="/static/5b48eb97054ceeb74f73916f272c9af5/fcda8/organizr-tab.png" srcset="/static/5b48eb97054ceeb74f73916f272c9af5/12f09/organizr-tab.png 148w, /static/5b48eb97054ceeb74f73916f272c9af5/e4a3f/organizr-tab.png 295w, /static/5b48eb97054ceeb74f73916f272c9af5/fcda8/organizr-tab.png 590w, /static/5b48eb97054ceeb74f73916f272c9af5/efc66/organizr-tab.png 885w, /static/5b48eb97054ceeb74f73916f272c9af5/c83ae/organizr-tab.png 1180w, /static/5b48eb97054ceeb74f73916f272c9af5/df88b/organizr-tab.png 1906w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>This is where the settings for disabling those things such as clickjacking come to play. This enables us to view our web UIs in iframes, so we never have to open another tab to view another web UI. Well, except Jackett. I haven’t been able to view that as an iframe yet. I didn’t bother because you never have to view it anyway.</p> <h3 id="10-spring-cleaning" style="position:relative;"><a href="#10-spring-cleaning" aria-label="10 spring cleaning permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>10. Spring Cleaning</h3> <p>Now all that’s left is to make sure that our server is all tidy and properly backed up. Luckily, Unraid already has plugins for them.</p> <h3 id="101-appdata-backup" style="position:relative;"><a href="#101-appdata-backup" aria-label="101 appdata backup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>10.1. Appdata Backup</h3> <p>First up is backing up our containers’ data. A lot of people gloss over this but with all the effort we spent painstakingly setting up our containers we should get this backed up properly, so we won’t have to do it again should our cache drive (where our appdata lives) fail.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 441px; " > <a class="gatsby-resp-image-link" href="/static/edcfe75817eb7e8105de36b06eabd897/efc6e/appdata-backup.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 69.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAACEElEQVR42p1TPa8SURDl/1hYWxg1amlhb2Ke0edfIFKQUBEpKPgJFHQUUPIseCQQCkICT752+Xh8gwmwy8cCsnu8Z2CfaCXeZDJ7Z+aee2bOXY9t27h0uUfuO8DbN8DLZ8DjR8DrFw48TMxmM6RSKSSTSeTz+X8CdZyj7yjQTx+Ap0+AV89PgOPxBOFwGJ+vrxGNRi9m2tSB9+/I9gRoGAYikQh8X3yIx+OnYluxcMTOv8/tHFTXgI9XCpCJw+GARCKBWCyGWq12asm5mOlwaB8ZNptNmV2xWBRA+kKhgHK5jHq9jmw2K/tSqSR5XdcxnU7/uJigJCaAvV5PQHiY1lGTbrfb6Ha74l1rtVoYjUaYTCYwTfMvkY6dSsvr9Rqr1Ur8YrGQxP8sAbQsC8FgEKFQCPP5XCk+VrMYYjAYoN/vC5NcLodAIAC/3y/tu4fdtd/vkbm9xXa7hWetmBHsqzK+R7ZP44zoyTyTycDn88Hr9SKdTj+8gnPAbzc3IDnP+ZPYbDZYLpfCip57joGFbt1ut5M941vlLTljPlziITqVoxgcOgWpVCrQNE3Up6LMMfb97k5iZF6pVtHQm2KVWl1YCiBvZNG9AtIaDfTU3KosVt8E4yWcJ2vcF6Cp+I9xH4t+A4tRG+a0q9jbvwH5p7BNKkzjLCkQY/SMuXlT1RqGiZ87C45lwNkuYStPkcjyF5R1DKBPpxMNAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="appdata-backup.png" title="" src="/static/edcfe75817eb7e8105de36b06eabd897/efc6e/appdata-backup.png" srcset="/static/edcfe75817eb7e8105de36b06eabd897/12f09/appdata-backup.png 148w, /static/edcfe75817eb7e8105de36b06eabd897/e4a3f/appdata-backup.png 295w, /static/edcfe75817eb7e8105de36b06eabd897/efc6e/appdata-backup.png 441w" sizes="(max-width: 441px) 100vw, 441px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Let’s start configuring by creating the share we want our backups to go.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/280b7f715c4f7680eb9ea950d89e593d/218a4/appdata-backup-share.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 57.432432432432435%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA9ElEQVR42pWS226EMAxE+f+fRIRLIJBwCTy7PZac7lZddvswEsLO8UycapomGYZBlmWRdV1l27Zb0cOZlNKf9WqeZ224rkvO81TlnOU4jpfiDAaAmhhErQohSNd1CkXjOEqM8SVs33ftA8pZAxcgxaZpxHtfpmH9Dtj3vQ5FBjKpQxoA0/wurgHNJQb4hxRIRByymDvQI9A5p1dDXNJgwowoEN3F/A3kzoG2batuMQOjRKbAtHdxEYOJS78txqRAllHX9b+AGMBRWKKkdSvLVCAfwD6JW55N+H5ifpTUOzkizn6MVI8X+ilQ311MkgcnefZPwC9yPEKWEVKYkAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="appdata-backup-share.png" title="" src="/static/280b7f715c4f7680eb9ea950d89e593d/fcda8/appdata-backup-share.png" srcset="/static/280b7f715c4f7680eb9ea950d89e593d/12f09/appdata-backup-share.png 148w, /static/280b7f715c4f7680eb9ea950d89e593d/e4a3f/appdata-backup-share.png 295w, /static/280b7f715c4f7680eb9ea950d89e593d/fcda8/appdata-backup-share.png 590w, /static/280b7f715c4f7680eb9ea950d89e593d/efc66/appdata-backup-share.png 885w, /static/280b7f715c4f7680eb9ea950d89e593d/218a4/appdata-backup-share.png 1052w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Then schedule the backup. Since I won’t be adding/configuring docker containers all that much, weekly is fine. Remember that this backup will turn off all your containers when it’s running. This may or may not affect the daily mover task. I prefer to keep just one daily scheduled task in my headspace.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/804fef266e97fcb66bb64b643f2173f3/74d4e/appdata-backup-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 18.243243243243242%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAX0lEQVR42p3OOQoAIQxAUe9/RwsLFRFccO3+kEKYVoukSODxlTEGay3ee3rvjDGuZs5JjBHnHLVWlNaavTdrrWvsgCklQgiUUlCy5PFS9wdzzrTWUJIpxxfsgIIJKoUfPMozjfaVYNoAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="appdata-backup-settings.png" title="" src="/static/804fef266e97fcb66bb64b643f2173f3/fcda8/appdata-backup-settings.png" srcset="/static/804fef266e97fcb66bb64b643f2173f3/12f09/appdata-backup-settings.png 148w, /static/804fef266e97fcb66bb64b643f2173f3/e4a3f/appdata-backup-settings.png 295w, /static/804fef266e97fcb66bb64b643f2173f3/fcda8/appdata-backup-settings.png 590w, /static/804fef266e97fcb66bb64b643f2173f3/efc66/appdata-backup-settings.png 885w, /static/804fef266e97fcb66bb64b643f2173f3/74d4e/appdata-backup-settings.png 1157w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="102-appdata-auto-update" style="position:relative;"><a href="#102-appdata-auto-update" aria-label="102 appdata auto update permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>10.2 Appdata Auto Update</h3> <p>Next is to schedule the updates of our plugins and Docker containers. Luckily, this works hand in hand with Appdata Backup.</p> <p>Simply install:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 438px; " > <a class="gatsby-resp-image-link" href="/static/484a078cd1a560a9c75f7b383e63c611/50e4b/autoupdate.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 70.27027027027026%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAACSklEQVR42p1TS4sTQRDO3/Hi2YMHQRQFDyJ42RUEUdCToKfEgyEQzEESjwuL3sRd9uzFw+aQsGaJMSTk/ZjJ5DVrXJLM5DGzmcdnV2UmqKgsNtRUd301X1fX1x2ANxzHgWEaOM8QqTw6HeD2LeDqFeDiBeDmdQcBAs4sE3uZXbw4eIKdT68hDZvrH13nr6Q+JEvAwwfA5UvAjWseYbadxmH1Iyr9Ap7v38d+5h0n2471z0otD26K/e9tAXfveIQfjnbx9P02vk1OsHf0Fl+lzx6hDdd12agl/vxPx28J0sePPML29xp20q/w7GAbbw5fwrLXW4vfz9VT2yNVVY9QljooFov4UjpGoVBANpvldaVSQS6XQz6f5zVhtVoNpmmuN/ypWqrUtu01YbfbRbVaxaA/RLlcRqPRwGAwQL/fZ4KOkFOWZTaKrVarXwjJ0XxDOJvNMJ/Poes6ptMpA/8zmNAwDESjUSQSCSZTVZWrGw6H7GmTdDqNSCSCcDiMTCazubd+hcvlEscivlgsEKDKYrEY4vE4xuMxer0e22g04uMRnkwmEQqFEAwGmfx3QiJKpVKcG/B7QUbVEqhpGoM0pxj1zCeganwzyFOO8Jsj04cEITFIAKndRqvVQr1eZ0/rpri5pHCpVIIkSSwaYYoQs1SuotmWxKvyCGl3AklB8kSqCFUVReE5k3okpHZXxGktifzp6QlOlSo0VQaMtZgBS7wfEoOMBKA+TiYTLMSRydPxCdMENhe3gWK6iNHNsM4MuKYO19BhLzVuzQ+sFQojeN0nrwAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="autoupdate.png" title="" src="/static/484a078cd1a560a9c75f7b383e63c611/50e4b/autoupdate.png" srcset="/static/484a078cd1a560a9c75f7b383e63c611/12f09/autoupdate.png 148w, /static/484a078cd1a560a9c75f7b383e63c611/e4a3f/autoupdate.png 295w, /static/484a078cd1a560a9c75f7b383e63c611/50e4b/autoupdate.png 438w" sizes="(max-width: 438px) 100vw, 438px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Configure (do the same for Docker):</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/c775be0173236e59e33354beadf79025/2e195/autoupdate-settings.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 31.08108108108108%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA4ElEQVR42l2QyQ6EMAxD+f8PZNMApRsFsZT16sGRBqE5WKZN+mKSxHmCVhWCt+hvBW/QWQ1nWnijEJyBtRZd1yGEAOccvPdy7vse+74/2rYNSVwW1E2DplHQ2ojatr0bDpzndfsmje9HdMKnaUKMEcvNoF/XhWSeZyilUNf1DW1EVfURqDFGAGw8z/PRcRwCWddV6nQOYU2ARVEgyzKUZSnfnE6x9ga9NY6jgCimowuQsdM0RZ7nD5i7+e3nPx3FO+5Vay0wMphYfplkTmMaisVf/PfC/8W+YRgExHcE8/4L5WDDrZ3i+5sAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="autoupdate-settings.png" title="" src="/static/c775be0173236e59e33354beadf79025/fcda8/autoupdate-settings.png" srcset="/static/c775be0173236e59e33354beadf79025/12f09/autoupdate-settings.png 148w, /static/c775be0173236e59e33354beadf79025/e4a3f/autoupdate-settings.png 295w, /static/c775be0173236e59e33354beadf79025/fcda8/autoupdate-settings.png 590w, /static/c775be0173236e59e33354beadf79025/2e195/autoupdate-settings.png 782w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>And toggle the Update Applications On Restart? checkbox in Appdata Backup.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/4a31472f6fbf8b4e65f62d7825ffe0c6/74d4e/appdata-backup-autoupdate.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 4.72972972972973%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAYAAADeko4lAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAMUlEQVR42o3LoQ0AMAhFwe6/Il+gkAQS0K9JJ6g4eUdmuDuSiAiqiplhd79l5nvdzQXrlUwTrQPJygAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="appdata-backup-autoupdate.png" title="" src="/static/4a31472f6fbf8b4e65f62d7825ffe0c6/fcda8/appdata-backup-autoupdate.png" srcset="/static/4a31472f6fbf8b4e65f62d7825ffe0c6/12f09/appdata-backup-autoupdate.png 148w, /static/4a31472f6fbf8b4e65f62d7825ffe0c6/e4a3f/appdata-backup-autoupdate.png 295w, /static/4a31472f6fbf8b4e65f62d7825ffe0c6/fcda8/appdata-backup-autoupdate.png 590w, /static/4a31472f6fbf8b4e65f62d7825ffe0c6/efc66/appdata-backup-autoupdate.png 885w, /static/4a31472f6fbf8b4e65f62d7825ffe0c6/74d4e/appdata-backup-autoupdate.png 1157w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="11-trakt" style="position:relative;"><a href="#11-trakt" aria-label="11 trakt permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>11. Trakt</h3> <p>Last but not least, we need a way to discover movies and shows to add to our collection. Plex does not offer this and Radarr and Sonarr are quite primitive at this, too. This is where Trakt shines.</p> <p>Trakt is a service to track your media consumption not just in Plex, but in every streaming service out there such as Netflix and Disney+.</p> <p><strong>Note</strong>: The following instructions are just a unidirectional sync of Trakt and Plex as you need a Plex Pass for bidirectional syncing. The sync is not even for Plex per se but more for Radarr and Sonarr to tell it what to add and download.</p> <p>Begin by creating an account in <a href="https://trakt.tv" target="_blank" rel="nofollow noopener noreferrer">https://trakt.tv</a></p> <p>Then head over to Radarr > Settings > Lists > Add List > Trakt List > Trakt User. In here I’ll be tracking my Watchlist public list. This is a list that every Trakt user gets by default. You can copy this or create your own list.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/a45e3f4e43a164247b196c14b246cf01/37523/radarr-trakt.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 146.6216216216216%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC+ElEQVR42pVVy47TQBD0t+9PrPgCuHPhBhcEJ9Ce4BBpA+zmYSd+2zN+TdPV7lkmKzsRllqeJJPqmurqnshaS4fDgYqioDiOZd11Hf3vM00Tnc9nirAYx/Ei8J1zTmLCW/8kn/k3Cf0NMbp5R5ZlFK1lNMZQVVXU9z0djkcJfBZgMAoBOQGeI+9ZBcSxm6ah0oxUVrWAIQnYDf4UCu6UYRwn64Bt21JRlvQnHaluLVkGg94IJAp1/gcYXwJiU5qmlOe5BFj9TgeqGiMJWgYFS8OgWOM7gEOWRUAcw/Amo39Egto6yvKCExQiel3XNAyDgCCwB4VcZYgvT1z+JEnESr/OA2VFRSWvwQiAYCWM9TPei4DQoufsoX0qZljVDUc9V9XbRq3l14uAHhRHQ4Chc9NLMWpmBnaeZYXq87pUOy0yxGYEwKSarFPK4AB8zXD07zUNAYgqI6svgIWurCcASQ3tggiNvXhkaSG2zPl0egE88RpdgER4xqD1nLrjqoYI2KaBRfg4OD5MDkBYZQpar1cLLQOq4ynZk33asgeteA5gPsA47GVYzWrXrAI2+ydKP37gPrYvbXWxLQD063UNddP47TNNZU5t11PNtphtUolF8PaJ3LVeDlm2mx/U/XyggdcV9GNAHJ9U41Dv6VaVBTBLyX79RG1diW0Q0FCGAgrG7SYJblXZs0TdzPcvZI47br9uHggcnR8KHDIXA4aQYn1io7qPGzLv31FalNRxxf10QQzaHS6QAFaLlgnqPWINDW/fkC24OMzS6AxEeO9dyLQGiN6EHhiyLbN53G4p4W4ZgosMa5mJamynUz66dT1iDsIqtpsnDlhi6rQ6efz76pGREQL7sVVydVHVUr+7dg9F4jtUKegIwx2CS9tP5t1uJ9fofr+XaW5YBtwraDkk6MIjh60VjiX/YDBgHmLi5LgG9L4BY6MSeNYzIAYni+6eny9YXnvcq5nouwV2iprNhs53d5Td35Ph8eSzrgXYgC2Y4yJDQGP//gtZE9rLPmNGPgAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="radarr-trakt.png" title="" src="/static/a45e3f4e43a164247b196c14b246cf01/fcda8/radarr-trakt.png" srcset="/static/a45e3f4e43a164247b196c14b246cf01/12f09/radarr-trakt.png 148w, /static/a45e3f4e43a164247b196c14b246cf01/e4a3f/radarr-trakt.png 295w, /static/a45e3f4e43a164247b196c14b246cf01/fcda8/radarr-trakt.png 590w, /static/a45e3f4e43a164247b196c14b246cf01/37523/radarr-trakt.png 720w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Same with Sonarr. Settings > Import Lists > Trakt User.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/73acefd27fc8b7283ee3509ee9b37241/71ee9/sonarr-trakt.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 97.97297297297297%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAABkElEQVR42pVU2Y6EMAzj/z9pXuZzVotguNpCOZqNUwJzwDKtFAGhNY5jkv385pQXJXXWUWtsDGupc06uH2GOo+mMYGTLslAIgXQFfkZuHD3N80wpKyyBMn2YpolBRjLGUNX2VJTMuusEdELwewQ+drawdwN0XGJd12QYpGg9VXUj4IP3MYZB4j/WL4BYYAhWfd9T+SjJ8/NWDsuC+JqhAloWfvCDsMV9lGKSzd6PaYCeSwM7RFVVckWZyG8Mnxp4CYjD0NIx0GMFlI9wHkyTALEZ+jlnuRmWS25EAr82ZANcQlrJkaWVkqWzK0MtOwkQDJumprJxZNj1h+ZN0RBdBWDt2MBBrbJbJt7T94DQSfTi367n5qApaBI27qAJDOExJ0ADFUX89eBB6Kf//Dyf+xDvs/ckDlsLDa3cayjgGUPNnwDaDVA9eNWUQ0AcxEBA2TnPSWgILyLmdeIsqQx18iB2Y+/T5pJh4ENBpwonwTCOqPDS2aMuP+d0aGT+fid/u22A7xvPwHQ6oQK3Wgxy/AFvBCkfj/TckAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="sonarr-trakt.png" title="" src="/static/73acefd27fc8b7283ee3509ee9b37241/fcda8/sonarr-trakt.png" srcset="/static/73acefd27fc8b7283ee3509ee9b37241/12f09/sonarr-trakt.png 148w, /static/73acefd27fc8b7283ee3509ee9b37241/e4a3f/sonarr-trakt.png 295w, /static/73acefd27fc8b7283ee3509ee9b37241/fcda8/sonarr-trakt.png 590w, /static/73acefd27fc8b7283ee3509ee9b37241/efc66/sonarr-trakt.png 885w, /static/73acefd27fc8b7283ee3509ee9b37241/71ee9/sonarr-trakt.png 1081w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>And that’s it. Soon as you add media into your Trakt watchlist be it using the web app or the iOS companion app, Sonarr and Radarr will add it.</p> <h3 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h3> <p>And we’re finally done. I’m planning to add more posts regarding my Unraid journey and possibly trying my hand in making automation tools of my own. Again, if you have any questions don’t hesitate to drop me a line or a comment down below, and I’ll do my best to respond and help.</p> <p>Here’s to hoping future me can read this and find this useful.</p><![CDATA[Building my own NAS]]>https://alecgerona.io/building-my-nas/https://alecgerona.io/building-my-nas/Sun, 06 Mar 2022 00:00:00 GMT<h2 id="what-for" style="position:relative;"><a href="#what-for" aria-label="what for permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>What for?</h2> <p>You know what. I don’t know. I just want to hoard data and have my own media server.</p> <h2 id="okay-what-do" style="position:relative;"><a href="#okay-what-do" aria-label="okay what do permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Okay, what do?</h2> <p>Well, this is actually not simple. I’ve decided right out of the gate that I wanted to build it myself. I’m not a stranger to a media server or a NAS before. If you could call a Raspberry Pi with a 16gB SD card a NAS. I also want something that <em>for the most part</em> I can plug and play, have high availability, flexible for updates, and can generally take care of itself.</p> <p>In the NAS world these two things are generally antithetical of each other. Good rules of thumb here are if you want to build it yourself, you can save money <em>but</em> you’d have to do a lot of legwork. Likewise, if you buy pre-built, you get access to their ecosystem (OS, parts) and is generally plug and play. Furthermore, dollar for dollar you get more with building it yourself (as it is with PC building in general).</p> <p>So, since I decided that I will be building it myself, Synology and Qnap (two of the most popular pre-built NAS vendors) are out.</p> <p>Which means I need to decide on two things: the OS and parts.</p> <h3 id="unraid-os" style="position:relative;"><a href="#unraid-os" aria-label="unraid os permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Unraid OS</h3> <p>When I first heard of Unraid I was immediately dismayed. It’s not open source and it’s not cheap. Given that the servers I manage professionally at work are all open source, this is a pill that’s very hard to swallow.</p> <p>However, Unraid offers a <em>lot</em> for what it is that is simply a dealbreaker in other OSs for me.</p> <ol> <li>It’s on Debian</li> </ol> <p>This is a no-brainer. Debian-based OS are some of the easiest servers to use and maintain. This is also what I’m most familiar with.</p> <ol start="2"> <li>Docker as a first-class citizen</li> </ol> <p>At this point I’m nearly sold to be honest. When I first experimented with the Raspberry Pi NAS, I’ve been using Docker containers to manage various services. The ease-of-use just trumps every other possible application hosting there is. I didn’t want to deal with having to set up Docker via a hack in other OSs. Especially if it’s FreeBSD like TrueNAS.</p> <ol start="3"> <li>You can use mismatched drives!</li> </ol> <p>And here it is. The most important part. Unraid uses a <a href="https://wiki.Unraid.net/Parity" target="_blank" rel="nofollow noopener noreferrer">parity system</a> to protect our drives. This is different from using traditional RAID systems that require you to have all your drives at once or all in the same size upfront. For someone just starting out using a proper NAS, the cost-entry to get say, six 20 tB drives at once is just not feasible.</p> <p>And so, Unraid it is.</p> <h3 id="parts" style="position:relative;"><a href="#parts" aria-label="parts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Parts</h3> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/69c3a3959442fc611c8e9ae9590db5ed/29007/my-parts.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD8ElEQVR42iWS629TZRzHzwv9F5AXaohRmeHae8/p9ZzTy9r19LRrNzrYutJ13To21m4TKrALA0XGMGOiIeEywkXmBjJu2YZolMQQ3xF94z/gCxM1RhLjC/XjQ3nxyzfPc57z+X1/F+mvZ7/y7I9f4L+/WVu/T1z2cXJoim8W15npOcFAboSHD1b5958/+f23n1n99gfWHz9l6d53LN95xNqXX7O+9oCfnj7i+8d3kMYPv8vRqTofHJ+gUulhx5adKHKGpJ4hY7SSTrdR6+/k7rXjLF0Y55OTQ1ycG2Hv7igB7w727Y1hxty0hO3EdAtS0+Y3sVisbG7azGuvb0TxaGRyNbSwSb5rD91dRbpSQS5/VGJuMs+5EwWWPq0wVIywJ+OhWopR7Y0z1m9QKyeQQpkbhFKr2NwjvPyShNXpJZToxuoOYJcV3njrHVIRO2tXx7hzqSpgA1yZK3PlTB/X5/tZPDvAzXNDrJyvcluE1DX5hPb6EyKFBTxeG9mwSq+xi6zfR3dMx3A7aW92sjA/zN3lc1yaH2PhdInLsz1cPl3k4sxebsyXWBaur8+XkYpHVtk3/RUtgw9Z/bzGj/c6OV5JoPuCaF4PfsVJMmwl3xYmZcbp6Ejz4dH93F+5yt1bC8xMFFk6f4hbFw7y2dn9SN7wdcLaGXab04yVDZZPKdw8bWB3OtnUtJ2mHXYC7rfJZXSCagC/3yNUY2ZmllptBNOIMFjZz0BpgOGhClJbtBXV5cJp2UpLIsGVj6cZ7c+JXrrRwxpmVEbe/iqhkBcjaTA8MkJzLM61xS8oFIviXmVm7hLvjc+S72wXQ9EDaLKDVl1hcnyUlduLFEolNmx8hb58gN5dXgKOJuwOG2nTpCMdR1Hc1A8dIW6YuBUfw7VxuntH6cqJKWdVD7v8NjK6g0wmzuBgiepwBZvVSjDoZcu2beghjXp9lISRFO3x43DaKPf3EgqHOTw+xcH6JJ35MoV8DqlVFWvStIFiJkK5uIfZU+9TKHRis9mw221CdxKPRenr6xEJTbJtadrbs1Srg5R6e5iammZi6hgTk0c5cLCOdOzAMIGtm9D8MkkjRk8xj6aryLIbq9UioJYG1ClcRaM6ZipOLB4l1hyluTmMrqlCo5imQWvaRBrcV8Hn8+Dze4lEdNKtoqywjlvsn9Nhb4BtNos4O8SEFVRRUVCEqvpES3zoInlMVJBoiZHNCuDzgyK7Gg5koYHAi0eaFhQA3wuw+OZ02vEoLpFYxh+QUTXxLhQUJkICGBE7aoh2pJAiEU1MzdVwIAv1esQPwm0w6G/cPwe5XI5GMp9PEfEcKJxqAVGJ2oAlky2k0glyuQz/Ay/Dcq7ns1CwAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="my-parts.png" title="" src="/static/69c3a3959442fc611c8e9ae9590db5ed/fcda8/my-parts.png" srcset="/static/69c3a3959442fc611c8e9ae9590db5ed/12f09/my-parts.png 148w, /static/69c3a3959442fc611c8e9ae9590db5ed/e4a3f/my-parts.png 295w, /static/69c3a3959442fc611c8e9ae9590db5ed/fcda8/my-parts.png 590w, /static/69c3a3959442fc611c8e9ae9590db5ed/efc66/my-parts.png 885w, /static/69c3a3959442fc611c8e9ae9590db5ed/c83ae/my-parts.png 1180w, /static/69c3a3959442fc611c8e9ae9590db5ed/29007/my-parts.png 1600w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Now on to parts. For a TL;DR here’s my <a href="https://pcpartpicker.com/b/Td4nTW" target="_blank" rel="nofollow noopener noreferrer">pcpartpicker link</a>.</p> <p>Due to availability issues, I had to make tradeoffs for this build. Let’s go one by one.</p> <ol> <li>CPU - <a href="https://pcpartpicker.com/product/qtqBD3/intel-core-i3-10100-36-ghz-quad-core-processor-bx8070110100" target="_blank" rel="nofollow noopener noreferrer">Intel Core i3 10100</a></li> </ol> <p>The only reason I went with Intel is that the 10100 is known as the king of energy efficient CPUs for NAS (as far as I read. YMMV.) and that it supports <a href="https://www.intel.com/content/www/us/en/architecture-and-technology/quick-sync-video/quick-sync-video-general.html" target="_blank" rel="nofollow noopener noreferrer">Quick Sync</a> aka Intel’s tech for CPU transcoding that supposedly makes it better. I wouldn’t know since I don’t plan to transcode, but it’s nice to have.</p> <ol start="2"> <li>Motherboard - <a href="https://rog.asus.com/ph/motherboards/rog-strix/rog-strix-b560-i-gaming-wifi-model/" target="_blank" rel="nofollow noopener noreferrer">Asus ROG Strix B60-I Gaming WIFI</a></li> </ol> <p>Now this is the tradeoff. Unfortunately ITX motherboards are unicorns in this day and age of gamers’ market that craves the biggest and most obnoxious cases out there. I had no choice but to get this expensive (and gaming) motherboard that is compatible with my CPU. To be fair, I could’ve gotten an mATX one, but I actually bought the CPU case first, which is amazing by the way, so there you go.</p> <ol start="3"> <li>CPU Cooler - <a href="https://pcpartpicker.com/product/hbnG3C/noctua-nh-l12s-5544-cfm-cpu-cooler-nh-l12s" target="_blank" rel="nofollow noopener noreferrer">Noctua NH-L12S</a></li> </ol> <p>One more goal for this build is to have an ultra-quiet NAS. We’re talking drives spinning and files copying quiet. What better way to achieve that than with a Noctua cooler? I actually tried putting my ear next to it while it’s running, and I swear I couldn’t tell it was on. Don’t do this at home though. My finger got caught in the spinning blade.</p> <ol start="4"> <li>RAM - <a href="https://pcpartpicker.com/product/Cf98TW/gskill-ripjaws-v-series-16-gb-2-x-8-gb-ddr4-3200-cl16-memory-f4-3200c16d-16gvkb" target="_blank" rel="nofollow noopener noreferrer">G.Skill Ripjaws V Series 16 GB</a></li> </ol> <p>Unraid actually boots off of a flash drive. Yes, you read that right. It doesn’t boot off of an SSD. After it boots, all data needed to maintain the OS’s running state is transferred in RAM. Even with that though, Unraid isn’t as memory hungry as TrueNAS. My utilization sits at 20%.</p> <ol start="5"> <li>Power Supply - <a href="https://pcpartpicker.com/product/bkp323/seasonic-focus-plus-gold-550w-80-gold-certified-fully-modular-atx-power-supply-ssr-550fx" target="_blank" rel="nofollow noopener noreferrer">SeaSonic FOCUS Plus Gold 550 W</a></li> </ol> <p>Apparently this line of power supplies are popular among NAS users. But go ahead and get what you need.</p> <ol start="6"> <li>Storage. Ah, now this is where it starts to get interesting.</li> </ol> <p>This is the highlight of NASs. As such we need to be very careful in choosing. To start with, I went with a <a href="https://pcpartpicker.com/product/TwWfrH/samsung-970-evo-plus-500-gb-m2-2280-nvme-solid-state-drive-mz-v7s500bam" target="_blank" rel="nofollow noopener noreferrer">Samsung 970 Evo Plus 500 GB</a> for my SSD cache. As a quick refresher, Unraid features the use of cache pools. Basically storage that’s supposed to be fast (faster than a hard drive at least) to store all your services (read: Docker containers) and handle intensive I/O operations. By default, Unraid then runs a “mover” daily that moves extra data present in the cache drive to the array of hard drives that are protected by parity.</p> <p>To that purpose, I’ve chosen two <a href="https://pcpartpicker.com/product/Ld6p99/western-digital-wd-red-plus-6-tb-35-5400rpm-internal-hard-drive-wd60efzx" target="_blank" rel="nofollow noopener noreferrer">Western Digital WD Red Plus 6 TB</a>s for my hard drives. One to serve as usable space and the other to serve as parity. Choosing this wasn’t easy as Seagate does offer a very compelling product as well plus WD didn’t do itself a lot of favors when <a href="https://www.storagereview.com/news/wd-responds-to-smr-gate" target="_blank" rel="nofollow noopener noreferrer">SMR gate</a> happened. But what finally led me to WD was that I made sure to choose the Plus version to ensure that it’s CMR and that it has a quieter operating noise than Ironwolves. To be sure however, I will be using Ironwolves for when the time comes to expand my array.</p> <ol start="7"> <li>Flash Drive. <a href="https://pcpartpicker.com/product/vRHRsY/samsung-32gb-bar-plus-metal-usb-31-flash-drive-speed-up-to-200mbs" target="_blank" rel="nofollow noopener noreferrer">Samsung 32 GB BAR Plus (Metal) USB 3.1 Flash Drive</a></li> </ol> <p>Like I said, Unraid boots off of a flash drive and this just happens to be, allegedly, the <a href="https://www.youtube.com/watch?v=jjkaidlZmgs" target="_blank" rel="nofollow noopener noreferrer">best flash drive for Unraid</a>. So there.</p> <ol start="8"> <li>Case. <a href="https://pcpartpicker.com/product/BWFPxr/fractal-design-case-fdcanode304bl" target="_blank" rel="nofollow noopener noreferrer">Fractal Design Node 304</a></li> </ol> <p>Finally, the thing that ties these all off. A small form factor, ITX case that can handle <strong>SIX</strong> 3.5” hard drives! In all my research I haven’t found another ITX case that I can buy that has this capacity. Plus it looks all nice and sleek.</p> <h3 id="build" style="position:relative;"><a href="#build" aria-label="build permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Build</h3> <p>Now that we got the parts together. Time to build. Here’s a montage of my NAS build.</p> <p>Do note that this case does not support both a power and reset switch. It only has a power switch. A two-lead power switch to be exact. <strong>You insert this in the middle row of the block where either is supposed to go.</strong> There I saved you a few rebuilds and hours. I wish I had taken a photo of this, but I forgot and you’re a big boy now so you can figure it out.</p> <figure> <span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; "> <a class="gatsby-resp-image-link" href="/static/a2dede7d7337aca7bcf45da18a79234b/1cfc2/build-1.png" style="display: block" target="_blank" rel="noopener"> <span class="gatsby-resp-image-background-image" style="padding-bottom: 133.1081081081081%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAYAAAB836/YAAAACXBIWXMAAAsTAAALEwEAmpwYAAAHB0lEQVR42i2VeVDU9xnGfx41oyBRueTYXZbd5dgLdjl2F1nkxuU+lGs1QHRRQcFjiIonEgQn9UQwWirqqIkaTbDGGI1OTZOmNU4mtZkkNqlNmmmnNSY1tpnOdDrz6ctv+sdvWPZ4vu/zvM/zfJUfHv+dR3/5iocPPuHzT+5x8fxJ9v/0RU6dGOXVs+OM/3yU0SP7GNyzg56etaxc2Upzcx0li/LJynJRUJBLvDEes9WM0+lEuXL5LBfOjdHcWMeRg4PcvnGZd956jUsXTzE2doT+3dvo7AiwetVyOuRve3sbq1evoLV1GQ0NS+hYHeDoyCG+efgFLw3tQXldfnj5wjiberrY07+VrVs2sqSuCq/XQ0qKlZycLBWob9c29g7J5CfHGBk5QFFxPil2K+fPnuZfTx7z338/5Y3XzqOs726nttpHcrKJoKBZpKWlUr+kmnVdHfzs2AgXzp/h/ffucO/eh9y69Q7DwweorCynurqMHdte4OEfPuPJt3/jn//4lju3bqBodPOZPz+cqVOnMHfus6zpXMGN6xN8/acv+OOXD/jzV19y/+N7jI+P0dqyDLM5AZ+viG1bNxEIPM+n9z/miezhxx++5/q1Kyh9axvJdMYxZcpUysqK+f39jwTocz68+2uOHxtm187NtAfaqChbhF6vJSIiHKslGbc7A5crnV/evsHT7x7JhI+59ovXUY4PbKC80IiiKBTk5zA01M+67jVUVZWKhhYcjhR8iwopLyvBZIonMjJCBaurrUSni+HqxCX+8+NTlfYrp8dRqiuyKc4zoonVki+AHk8merFBbW0VK1a04ffXU+orIC/XRXx8HC53umqXwIoWHKl2rr5xme8f/VUW8x2HDryEMgnQUJtPujORzIw0cnMXUC7TNTdW0NW5jMDyBtn6IrLcKRjloJqacux2i9iljaKiXKzWZPlOCwf27WXjhi4BlPEz0qxYLEb08Rqh4mOpgHWv8dPUUMZzS+toa1ksyzASEhIii3gOqy2ZlpZG2tr8GAxxIkE6DUtq1KmVFJuZhESjqo/DYaGpsRJ/cw0LF7rJK/AKcCsXzw3jb6pi1qyZIsESVd/KylK29m4U+pkihY6G+lpZXiuK3W4Wqg51g3Y5OT9vgdB2k7swg8IiL4MDvbx19QxrO/yUl3qFskjRtYrUVCv9EgS/fzFGk060T2ONBECxWpKETqLqxaiocNFJqz7lFUWUlxfxfGsDW15YSe+WVSKBT4DMAthOugyxY2sPmzetU7+7SjK+ccMalAShqtPGqgnRxWnQaqJlCZVCOVtolMq2S8TQi+nuCpCe7iAsfJ5kuEYc4ZWJi3ixr5fd4tWutQF5v1YAE+KI1+vIyHSSlGRSn0mfxcTEEBY2TwBCMQuLispFhIeHMeOZZwgNCyV4drDobqCpabFEtYbOztV0d3eg6A2xJMumXHYbFptF6OrFsBp1AbNnBzEvdK5Ecq4AhzFLsj59+nSRJ4JQeb9OSuSY5P3kyRNSbevZtWsLyvyYUBy2RJyiY1T0fEwCODl1SEgQM2bMICg4iFmTj4BpRZr0NDsr21t48+olPvv0d7x89Iga2cJCL/sGd6Lo4qKw2RNEZLt4SqemwWiKE1pzmaIWxhzxaBIWOXCd6Hj75gTffP1AMn9Xquw4OQsXMGfOs2L2ZNZ1LkeJ08dgStCJVTyqfpGRYf+nHStTzSQ6OlJNx5B04d3fvMv9j95j4tIpDkqrH9q/V9opQElJARptFM1NdSjJZoP8E8lCr0umSFJjZZM6nwR0SoJaWv0MDPQLtWHJ6hBjRwd55dQhAevj8KH9qpmzsjJkw5PZ96NkpKcSp4vG7UqR8T1oNDHYbEliG5dssJr6+mrxmU/qfTvDBwc4PjLI6IFeXj2xkyOHh6iSop1Mj8eTIVoWoXi9GdIaySSYNBQWZKuv83IzRYJMEpP0xBsmNTXQu3k9L4/u5dyJPUyc2c67EzvpaF+Mr7RY/JnC1GlTmDZtGkrP+uUiukmAkiR2HoqLc+SuSCTH61Z9ZkowkOqwU1Hu4/D+fsZGBrh2ppud6/OElV0WaiEiMlxNjlZkUm5fGcdX4hXtTGSmW+QDG+FiXE1stFxQHqkns7rpeEO8TLSUZU2lbOrIpTBbJzG0yeFmsha41eTs2N6D8qtr4/Rt6ZA+TBL/xUqVJYuOUWLqYFlWLEWFeVL7YUz/yQxMhijyF+jxZBrkGtCQ5rTicZhorCvGIjegy52G8sHN01y/NMyZY7upry1UQa1Wo5g4RvwVonpw8jKPiIhgumik1USKlaIwJujlwBjRO1umTBAGWvUCU3578xTvXx/ng7dPcGdilM5AndCXfkzUqxGbTIzDaceb7SZYEuNyZRCn14h2SRICLTODZ2KQIKQ5LVKwy/gfwekuW+lkoygAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> <img class="gatsby-resp-image-image" alt="build-1" title="" src="/static/a2dede7d7337aca7bcf45da18a79234b/fcda8/build-1.png" srcset="/static/a2dede7d7337aca7bcf45da18a79234b/12f09/build-1.png 148w, /static/a2dede7d7337aca7bcf45da18a79234b/e4a3f/build-1.png 295w, /static/a2dede7d7337aca7bcf45da18a79234b/fcda8/build-1.png 590w, /static/a2dede7d7337aca7bcf45da18a79234b/efc66/build-1.png 885w, /static/a2dede7d7337aca7bcf45da18a79234b/1cfc2/build-1.png 900w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async"> </a> </span> <figcaption> Always, always test everything using the BIOS with just the essential parts ready, first. This has always plagued. Just plug in the, RAM, CPU, Cooler, Power Supply, and a display. </figcaption> </figure> <p>This particular motherboard supports 11th and 10th Gen Intel CPUs and features two M.2 slots for NVMe SSDs. <strong>However, you must be using an 11th Gen Intel CPU to use the front slot (the one with the built-in shield/cover)</strong>. If you use a 10th Gen like I do, that slot will be disabled, and you won’t even see it pop up in the BIOS. You’d need to use the slot at the back of the motherboard. The box comes with an extra thermal pad. Use this between the case and the SSD underneath the board. This is very important.</p> <figure> <span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; "> <a class="gatsby-resp-image-link" href="/static/88258b4425156862b8f7d74b5b8d1927/29007/build-2.png" style="display: block" target="_blank" rel="noopener"> <span class="gatsby-resp-image-background-image" style="padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD7UlEQVR42h2T629TdRjHT2JA52UisHHp2LrRdV3X21nPaXtOr6enp5f1vnWtZZeywmAbY3MisMQIzMpF90IJGIO+kBAhYkiMRhJf+FZj4gv9jz7+wosn+f3efJ/v871IejiJrqXQIiaRkImqpPEHkjjdOsMOhZHxEMOjQYbtCkNixsZCTE5o+DxRptxh5IBGVEuKtw+XawJJC6UIqQI0WsA0KuSsGla2TjheI1FeY8qfQ9VrBNQ8spzE64vhcOhicYruyioRLY1hldi8fJnO2RWkSn0dJZJn+fxH7PX26fXucuPWHdY/3GP782ecu7TPTu8nrOo5DCNLvtgQ4AXuP3zKX3/+J/5tNrZ3efn7H/z860ukgDqDze4nrGeIxrPEEzlSRhFNt1AEi3J9kUR2AVnNMD4us9BaYH19jX///ofvHz3hTLPNzd49vn38gh9+fIE05gwxaHPjmJxmaSnPtWtVoWGcsGYRjmQIKBnKrUvo8QrTss6jr3rsfrDK3tonbC7usrW0zHf7O+zf7fHNo6+R2u0mthEXp8a9GOUK8y2LWNwklZ7BtMqoWomZ6mUK5Q6OCT+r55Z5+OlNbm9c4+bFK9y4uMbVTp7n96/w8M420m+/PMHtCXDkpIMhZxiXOyRMKRAIxhlzKoJ5lFpji6jRZOS0G29AJpNOc7Zd4+pGk/1bG2ytt3jw2SrXNxtIqxe64kSFA30DnLCN4p70kEiZAjDGqVE/slYkX2mjm8L5RF4Ahmg1LC50q9QrCdpzQpaAm0hEEX8LyeHyMupwcWLIjl8OkssZtN6fpVqrki0UWNu+yvrmFh/3vuDeg2fi/JaIjZ3ZepbWfEbIE8Q+dpqJSQderwep/9DgKzCPXyaohul0O7QXF6kIwLKYpW6XS9s71JpnKDWaTLjdHBk8RiYTorOYR1W9THmnODo4QN87h5D63jzMawfeRpIOcsrupF5v4PYpAqyGrIhWeFVihkVID6PoIWKtUTwpG5GYTNKIIQe9hMIBjh0/js12EunogI2Dr/fT/+4gwyNOxhxTaPEU/mlVLBjH5QuiG2mSlkGxanLxyyFW7tpZWK4yN58T+VXEZTKTbiexWBjJPuqk7633GBp2MnDcLjRJirhkRe6SRKIJwSyGkRNhz4qWVPIU237KK8I4SyOTT4jaJUibCWrVGRpzFSSfT6a/f5DDR2z4hIO5fIFSpYxhmuRLJaqzsyI2cxRrFYxsmoQZJZGJkLIimNkYpZLJQrvE7pUue9c7SKqii0p5OPDGUSY9Mo35ORoCwBBZMwWruWaDYrlE0jReaTgdCjAVcAqdHcKYMOc7RW7vLPL0/nWeP97jf4ZzI8aUwqTFAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> <img class="gatsby-resp-image-image" alt="build-2" title="" src="/static/88258b4425156862b8f7d74b5b8d1927/fcda8/build-2.png" srcset="/static/88258b4425156862b8f7d74b5b8d1927/12f09/build-2.png 148w, /static/88258b4425156862b8f7d74b5b8d1927/e4a3f/build-2.png 295w, /static/88258b4425156862b8f7d74b5b8d1927/fcda8/build-2.png 590w, /static/88258b4425156862b8f7d74b5b8d1927/efc66/build-2.png 885w, /static/88258b4425156862b8f7d74b5b8d1927/c83ae/build-2.png 1180w, /static/88258b4425156862b8f7d74b5b8d1927/29007/build-2.png 1600w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async"> </a> </span> <figcaption> Since the Ripjaws are a bit too tall, I needed to use the high-profile configuration of the Noctua cooler. This just means that I had to move the fan from underneath to up top. The front of the fan should face the heatsink. It will be quite obvious what the front and back of the fan are. </figcaption> </figure> <p>Also, don’t be alarmed if there’s a persisting LED light in the motherboard. As long as it’s only one, and you’re not using a graphics card like I am, it should be fine. The LED light just means that the motherboard cannot detect a graphics card.</p> <figure> <span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; "> <a class="gatsby-resp-image-link" href="/static/0021016d30db94637ae6ba8ff31e4ac3/1cfc2/build-3.png" style="display: block" target="_blank" rel="noopener"> <span class="gatsby-resp-image-background-image" style="padding-bottom: 133.1081081081081%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAYAAAB836/YAAAACXBIWXMAAAsTAAALEwEAmpwYAAAHA0lEQVR42jWWeVBV5xnGTxC1LgMJqMjlsly4rBdy2ZEAIsgmggqKaMXYiKjVgAQRN3DDpkO1Tks01dLEGlPFaDpTrTUtGhDZL/u+b6KOxvyVzrT//fqeM9M/ztxzvvOd533e533e97uKp6c7RqM7Hh5yya+Xl6fcG7Q1o9EDb28vWfPCz89Hu4KCzISFBhMeHkJU9CpS1yXwp89KeVB9gXs3KlAcVi7H0dEBJ70Onc4RFxdnPD09MBhccXc3aIA+Pt6YTL4EBwcSFGwmMCiA0NAgeTZj8vfnZPFuHv+tks/P5qMUFeaTn3+A/fvyOH26lMJD+axZs5q8PbspP3eao0eLtfUzZ0vZkZPF8ePF/O73F/j00zNUVl7kFx/lUFVZyqO7lziclYgyPNhDZ0crdbU1vHo5S1enhdjY1Zw/f5Y3r1/Qbmmmt6eD/t4uUlOTOV9+hpnpUZqb65maHKG4uJA/XjnFzcul7Fzjj9La0kB3l4XBgV6Gh3rp7+skIMCfpKREpqfG5Llb3rfL+x58fX1ITk5kdKQfS1uDvOugpEQYXzrB2f3ZbIx0Q2kTQJVhT3eH9vHszDgZm9KIiYkWBqN0CZilrZnR0SH27s1j9+5djI4N0txUT19vB9evV3H0kz3kJoaTHm1EaWl+Rkd7iwC20yugc3NTfH3zOocOfczU9DidIkG7vB8eHuDhw/tcuFDB1NQkFksrA0Kg5sk/2ZW5nvgAV/y8HVGaGp+KTk3CxKJpNTE+Qu2TR5JKPkMjA9q6CtgtAR/+4z5Xr17mp59eMz4+KBL10yEB8/N2EuLriN7hXZQn8nGLCPx/luomVYaiogLaO9o0IBWwTYpT8/g7qXgZL16OMzMzRH9/p8jUw86cbLGQD86OdijVt7+Wij2ltaVeY9PX28mIMNv3y308+u7vDA2rLNqwCGiLBCo5eoSW1ga6JFBLS6OmfVHRIdI3phIXZUb5rPISbVKxpsY6zSJqgaamRik5dpR7395lfGJY+7hTQHt61CJcp+7p99qaxdLCQH83ZWUnpPpr2ZSZjlJWdkxLt6GhToAbJb1m0WeIi7+9yI0bN5iWwvT1ddEjzIeFbVVVlTB/yOBgLx0SfHx0kIqKX2ltmJGZhpIrNlABmxrrJWKztmlCWH311Q3Kz5cz+3ySwaE+BsSHM7MTXL5SyfU/f8GkZNEtjGck4JdfXiMkJJCNYjclJSWZzvZWVIOrYN097UyI/1QWhZ8UaoCjwmJErpmZCb6vfcy39+4yOTmsBVHNf//+PSIjw0lZJ60XEhJMuxhXLYiqUV9/lwCO0Nj0jJOlpRqTCflIDTI3N02DZHK7+hbPn0+IBL28eTNHTc1DgoVhUlICiru7OzX/eiTtNKBFHBruY2xsSBgNUSCDold6eGZ2kjHx548/vqa27jHJKQmyZ4C3b19KAYf5/A+VeHkbSUiIR9HpVnKn+i/ScpPiq27RS3pawMdEx7S0VNl8mf/899+8FbCXr+Z48OCvePt6UXykkNzc3WRujMDkp8fZ2YW4uFgUdf4dkQZXAVU9XryY4YcfXolGo6QL4JYtGVy7eoXCg3vISk8gepUZV5mVTs5O2NjaysDwYJWs6XT2rFsXjaJO4CgZBM+e1fKsvo4vqq6RX3CQPXm7iFgVwkonHYFmEzFB3piNOgxuevRCwuhpxNbWhnUy0tRi2NnZEBERhBK/No7wVRHErI5G5+TIO/PewWqeFUuWLMLkayQ+OoTQ8GD85d7D2YEgs7SYqxM6vR4XV2fKTh/j+MnDcu8gEqWgZG7ZQPzaeNnkLGnoWbR0CUttlhK/JoKoMD+Sw73ZuCaYQF8DHwR7kRgbyHKHZbgZDMTFr6ZUuqTk2BGRQS/HQiBK1tZNZGVnESwPqjbv2b8nLOfxUU4a29M/IExGksnTiVBvPSUF2cREBRISFkRg4Pu4ubmwJWszpaeO4+vnLfKsRMnelkne3lxSUpOwW2aHzbu2LFq8GAcHe1ZHmslYH0PBgWxyslLZn7ddvBavnYYbNqwnXS4XNyeSkuPl1w0v/QqUnR9u5fiJw2yW1Fc4rMB+mb1Uz4ZFS9TUbXH3cJNUzJileIcKC/jm3h1J8yQ+vp6Y3jfhbliOyWU5ivUCwgwyYHN2ZnHiZDE7dmxDURSs589n/sIFkr6LdlRuFtsUFxdR8Ztfc+duNdXf3OLW7Zv4B/hhvXA+tnZLcXN1xE6kMsgZr2zfnsGBg7kUFn7MgoULsbKyYrGkHB0dKc6PJTYuhr3793Ku/Jwcpac4e+6UJpHJ3w9PLyMuBmciIsOIjIogQOylbNu+RTz3obAoYMHPBNB6HvOsrTGL6KlpSWRkbJB/BylkS+HUMzg5JZHQMPnnEBEi2sWx7edbMZn9xTY63I0u/A8B6Rcp799aEgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> <img class="gatsby-resp-image-image" alt="build-3" title="" src="/static/0021016d30db94637ae6ba8ff31e4ac3/fcda8/build-3.png" srcset="/static/0021016d30db94637ae6ba8ff31e4ac3/12f09/build-3.png 148w, /static/0021016d30db94637ae6ba8ff31e4ac3/e4a3f/build-3.png 295w, /static/0021016d30db94637ae6ba8ff31e4ac3/fcda8/build-3.png 590w, /static/0021016d30db94637ae6ba8ff31e4ac3/efc66/build-3.png 885w, /static/0021016d30db94637ae6ba8ff31e4ac3/1cfc2/build-3.png 900w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async"> </a> </span> <figcaption> The SATA power cable are usually chained together. It's absolutely safe to use one running cable to power multiple drives. </figcaption> </figure> <figure> <span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; "> <a class="gatsby-resp-image-link" href="/static/f8e46969e183fd702f2babc36d30ab8e/29007/build-4.png" style="display: block" target="_blank" rel="noopener"> <span class="gatsby-resp-image-background-image" style="padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD/UlEQVR42lWS608TVhjGmyzIpSgULKVX2gLTOiCo+7CpwRjFCeMyyaTgFVRkc44xCgyLgrJM3VBEM1mEWXEqV7UCRYEWGWAtBbRAAZn/zG+H6j7sw5Nz8ibv7zzv8x7JT9Zq8gvzOZCfR1raNlSqGHRxKmRR6wgLCyE4OJg1a4I+aE1Aq7XoKBlxOjU6rRb5+gjCpUEkJSqRVFaVc+JkEQcO7GfXrp3EJ8QTFR3F2rXhgcagoKD/6T0wBJVSiUJlIFgaRbQsjNCQj8hJ3yKAlWUUFR8hJyeLzMwvMJlMyOVyIiIikUqlhIaGfnD53tmqQkPD0RsSSEg0IZNFI4uQIlsXxpmifUgqKs5QWnocs/lrcnOzSd2cikajQbnqQKEgVpz/3eXyGCIjY1gfrUYft4HkT9PR6BIJCQkm0aCmwVKApKrqB2pqLBQU5FMsnGZlZaDT6QJQlUpkpNMSF6dHq9GLMfWslxuRKxL5eEOqiOkQycmpSMPXkp62lcbzx5DcuvELDRes1J6toP1uC+Xl32EwGDEajQGQwRgv7gkBRxrtJyhiN6FUJfP5Z7tpqKtlz+50YmKUnDqcyRWrAD7qvsOTR/ew996lt9tGw8WzpKSkBIAarQAaDBgN8Rj0m4jTbhaut6DWbCUn28zN5msi+1w2bdxIveUI9RUHkQz2dQpYO4+7/8Q5Yuf+/dvs2LGdeKMevU4jRtehFttUq0yoFFtRx2aLhWRz/NhJ7t5pFdkXkrVvF1dqT3K+zIxkpL+DYUcvzwd7Ahp+3ktGZgZF+7dz1fIVPx7dy9HcnXyZtoNi8yG+OTFAkqmKWks59/9q5/S3pyk9lsev50o4/70ATjjtTHtG8fk8uF86sT/8nUN5e6guyaL/Zgn25hKeNJ2iTQTedqGGujIvKUmH+aPxEl1dHZytrqT6dAE/W45yojALyYzHhW92HL/fy8KCl2dP73HVeoSmGjO36wtoqzNjqy+kzXqQ1tpSqoqr2b1tLx0tv+EacdD58A62lsu0Xq/D8aQTyeK8mzczY8z7Jlla8LDgczMy9BT74wf0dLRhu3WJ203naL5YxmVLEfVnCrGW5NBju8bfo4N43KPMz00zK6acnhxB8tb/ikXfOIsLUyz7PbxdnmHlrY93K/O8e7fA0uI0c6JhamoCe5eNlhuNtLY0MTTQi2vIzphrFTqGe3yISZdjFehhZXGKJf80K8uz+GfHBHwG/7xXOPaKB2aZe/2SKbcTV/8DscBuRp19PB8QS+zvYliAx8eeMTnh5MXwUyQrq46WZlheeh2A+sX4/6zMCdAb/HPCsah7X71gwtUnYJ04BOSZowdHXwd28YcH7A9wDvfxwjWAc/AR/wIMeaKIdlkzwwAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> <img class="gatsby-resp-image-image" alt="build-4" title="" src="/static/f8e46969e183fd702f2babc36d30ab8e/fcda8/build-4.png" srcset="/static/f8e46969e183fd702f2babc36d30ab8e/12f09/build-4.png 148w, /static/f8e46969e183fd702f2babc36d30ab8e/e4a3f/build-4.png 295w, /static/f8e46969e183fd702f2babc36d30ab8e/fcda8/build-4.png 590w, /static/f8e46969e183fd702f2babc36d30ab8e/efc66/build-4.png 885w, /static/f8e46969e183fd702f2babc36d30ab8e/c83ae/build-4.png 1180w, /static/f8e46969e183fd702f2babc36d30ab8e/29007/build-4.png 1600w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async"> </a> </span> </figure> <p>When flashing the boot drive with Unraid, <strong>make sure to check the “Allow boot from UEFI” checkbox</strong>. There is currently no way to allow legacy mode in this motherboard.</p> <p>And that’s it for the build. I hope this has been helpful to you all. My next post will be about media automation on this very NAS. If you have any questions, just drop a comment, and I’ll do my best to respond.</p><![CDATA[Love it or hate it: here's how I setup my Mac]]>https://alecgerona.io/macos-dev-environment/https://alecgerona.io/macos-dev-environment/Thu, 07 Oct 2021 00:00:00 GMT<h2 id="updates" style="position:relative;"><a href="#updates" aria-label="updates permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Updates</h2> <p>17 Apr 2023: Use starship prompt</p> <p>15 Aug 2022: Update the <code class="language-text">fzf</code> setup command</p> <h2 id="rationale" style="position:relative;"><a href="#rationale" aria-label="rationale permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Rationale</h2> <p>Gotta be honest. For the longest time, I’ve avoided the Apple ecosystem. I’m still not that okay with it, but we have to try ‘em all, right? What with <a href="https://forums.macrumors.com/threads/16-is-hot-noisy-with-an-external-monitor.2211747/page-173" target="_blank" rel="nofollow noopener noreferrer">overheating MacBook Pros</a>, to class action lawsuits over <a href="https://9to5mac.com/2021/09/16/class-action-lawsuit-screen-cracks/" target="_blank" rel="nofollow noopener noreferrer">cracked M1 screens</a>, there remains a lot to be desired in the so-called walled garden.</p> <h2 id="setup" style="position:relative;"><a href="#setup" aria-label="setup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setup</h2> <p>With that out of the way, this guide is how I set up my development environment on a MacBook Pro 2019 16in the way I want it, so I’d have something to reference should I need to do it all over again. Hope someone else finds it useful as well.</p> <h2 id="1-xcode" style="position:relative;"><a href="#1-xcode" aria-label="1 xcode permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>1. Xcode</h2> <p>Let’s start simple by installing Apple’s command line tools. Basically, things you need to get any sort of development work on your machine.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell">xcode-select <span class="token parameter variable">--install</span></code></pre></div> <h2 id="2-iterm2" style="position:relative;"><a href="#2-iterm2" aria-label="2 iterm2 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>2. <a href="https://iterm2.com/" target="_blank" rel="nofollow noopener noreferrer">iTerm2</a></h2> <p>I believe it’s already tradition by now (for developers at least) to immediately replace macOS’s default terminal with iTerm2. Some would say it’s a little bloated for what you use it for, but you’re using a Mac already, so you shouldn’t complain.</p> <h3 id="install" style="position:relative;"><a href="#install" aria-label="install permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install</h3> <p>Installation is as simple as downloading the .dmg and installing through that.</p> <h3 id="key-repeat-rate" style="position:relative;"><a href="#key-repeat-rate" aria-label="key repeat rate permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Key repeat rate</h3> <p>A severely underrated QoL change, this set up requires a restart after execution, but you’d be able to glide on your keyboard once your key repeat rate is up. A boon to Vim users, terminal junkies, and fast typists alike.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell">defaults <span class="token function">write</span> NSGlobalDomain KeyRepeat <span class="token parameter variable">-int</span> <span class="token number">1</span> defaults <span class="token function">write</span> NSGlobalDomain InitialKeyRepeat <span class="token parameter variable">-int</span> <span class="token number">10</span> defaults <span class="token function">write</span> NSGlobalDomain ApplePressAndHoldEnabled <span class="token parameter variable">-bool</span> <span class="token boolean">false</span></code></pre></div> <h3 id="skin" style="position:relative;"><a href="#skin" aria-label="skin permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://iterm2colorschemes.com/" target="_blank" rel="nofollow noopener noreferrer">Skin</a></h3> <p>For my terminal I’m using <a href="https://raw.githubusercontent.com/sindresorhus/iterm2-snazzy/main/Snazzy.itermcolors" target="_blank" rel="nofollow noopener noreferrer">iterm2-snazzy</a>. Just download the page and import in iTerm2 (Preferences > Profiles > Colors > Color Presets > Import).</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; " > <a class="gatsby-resp-image-link" href="/static/7bcb98a23a9bb3d968d609f41652a95d/63ec5/neofetch.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 48.64864864864865%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB5UlEQVR42n2Ty07bUBRF+RSg8iMPhcQPHCexr195OAkmKW2BqgIqEYVBKJQC6YAOmVad9Rfar1y9ua2QaAuDLZ+r67O0zz72WqniYZa3MQyHmhDUIoGuOVSdFnY3w0kyrCzF6XZx+j3qIqYWCCp2C132GCX3kdZ0w0WTF3rZxT4eUwlDNtcb+K2ANM1Js12SeEzQGWA1QqpVH12XINP9B6aAW+2QcD4lmE2UosUe9iCl3REUL4cEYkhH5OplzbTRS85/QQ/Ao8OC5ce3XC0O+HR+wPWHA4IowpMOJwrYU1DLkVGYjozHfR541gy59UOupG58wYU8l3ULrxOQjwr8dobXTPH8VDWovJ8Dvm92uWsP+dwaSOV86Qx5ZcmRw4jp3g5xkpPIHD0/U1lr0qVm2E8DE3fMfPeW0+KamdTZ7pJ9ccK216GYDEl7ffqDKXG6Q7OVESVj+eziNhPpvquc160A14uxXSG3XPWoTWfU3yzYmpxiHV7wwopkboIgG+DWM0TSl40RUTxSwDAa0rBDBbPdSDl/cGiuCrk9czWGVsc0V5+EQ9locJTHHN/POTm64+LynuL1OzY2t9TIqwX91l8jPwr5T62VtrEqTZb7Iy5/LLm5/M7Xbz/ZP56xvlFj9TM8leEvSM5TY262NoUAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="neofetch" title="" src="/static/7bcb98a23a9bb3d968d609f41652a95d/fcda8/neofetch.png" srcset="/static/7bcb98a23a9bb3d968d609f41652a95d/12f09/neofetch.png 148w, /static/7bcb98a23a9bb3d968d609f41652a95d/e4a3f/neofetch.png 295w, /static/7bcb98a23a9bb3d968d609f41652a95d/fcda8/neofetch.png 590w, /static/7bcb98a23a9bb3d968d609f41652a95d/63ec5/neofetch.png 812w" sizes="(max-width: 590px) 100vw, 590px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="hotkey-summon" style="position:relative;"><a href="#hotkey-summon" aria-label="hotkey summon permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://iterm2.com/documentation-hotkey.html" target="_blank" rel="nofollow noopener noreferrer">Hotkey summon</a></h3> <p>Coming from <a href="https://github.com/KDE/yakuake" target="_blank" rel="nofollow noopener noreferrer">yakuake</a> and <a href="https://github.com/Guake/guake" target="_blank" rel="nofollow noopener noreferrer">guake</a>, the ability to summon the terminal from any desktop with just a hotkey is a godsend. Here’s how to do it with iTerm2.</p> <p>Go to Preferences > Keys > Hotkey > Create dedicated Hotkey window. This will create a dedicated profile that iTerm2 will use when you summon it this way. You can then edit this profile as you wish.</p> <p>My hotkey is ⌘+`</p> <p>I set my transparency to 10% and window size to maximized.</p> <h3 id="shell-integration" style="position:relative;"><a href="#shell-integration" aria-label="shell integration permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://iterm2.com/documentation-shell-integration.html" target="_blank" rel="nofollow noopener noreferrer">Shell Integration</a></h3> <p>This is a utility that “keep track of your command history, current working directory, host name, and more—even over ssh.”</p> <p>This will be useful for the following feature of iTerm2.</p> <h3 id="ssh-workflow" style="position:relative;"><a href="#ssh-workflow" aria-label="ssh workflow permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>SSH workflow</h3> <p>Traditionally, we SSH to other machines by writing the full command such as <code class="language-text">ssh user@host</code>. We then learn to alias this by using the <code class="language-text">.ssh/config</code> file and writing <code class="language-text">ssh alias</code> instead. We can go much further in iTerm2 by not even needing to type anything. Simply make a profile and make it run the ssh command you need.</p> <p>For my setup I still prefer working mostly in my keyboard and having to open the profile from the tab is just extra overhead that I want to avoid. That said, there is still an advantage to using profiles and that is to visibly notify you that you are working on a different terminal by either having a <a href="https://iterm2.com/documentation-badges.html" target="_blank" rel="nofollow noopener noreferrer">badge</a> or a different theme or both.</p> <p>For production terminals I use the <a href="https://raw.githubusercontent.com/mbadolato/iTerm2-Color-Schemes/master/schemes/Red%20Alert.itermcolors" target="_blank" rel="nofollow noopener noreferrer">red alert</a> theme. I also use the instance name as its badge.</p> <p>Finally, since I prefer having to type the ssh command myself, I have to set the profile up so it would switch profiles once it detects that I’ve changed hosts. To do that, we need to implement <a href="https://iterm2.com/documentation-automatic-profile-switching.html" target="_blank" rel="nofollow noopener noreferrer">Automatic Profile Switching</a>.</p> <p>This iTerm2 feature requires Shell Integration which we did above. We then need to add the expected user/host entry iTerm2 needs to switch profiles.</p> <p>It’ll be something like this. It should end in a glob (*) or it won’t work.</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">user@host*</code></pre></div> <h2 id="3-homebrew" style="position:relative;"><a href="#3-homebrew" aria-label="3 homebrew permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>3. <a href="https://brew.sh" target="_blank" rel="nofollow noopener noreferrer">Homebrew</a></h2> <p>Now that we have our initial cli tools and a spiffy terminal emulator to work in, we need one more tool to be fully integrated in the macOS (sorta open source) ecosystem—homebrew, the package manager that, like most things in a Pro Apple product, never had built in.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell">/bin/bash <span class="token parameter variable">-c</span> <span class="token string">"<span class="token variable"><span class="token variable">$(</span><span class="token function">curl</span> <span class="token parameter variable">-fsSL</span> https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="token variable">)</span></span>"</span></code></pre></div> <p>Afterwards you get access to package manager staples such as <code class="language-text">brew install &lt;package-name></code> among others.</p> <h2 id="4-zsh" style="position:relative;"><a href="#4-zsh" aria-label="4 zsh permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>4. <a href="https://en.wikipedia.org/wiki/Z_shell" target="_blank" rel="nofollow noopener noreferrer">ZSH</a></h2> <p>zsh is the default (and better) shell in macOS. Aside from its <a href="https://medium.com/@harrison.miller13_28580/bash-vs-z-shell-a-tale-of-two-command-line-shells-c65bb66e4658" target="_blank" rel="nofollow noopener noreferrer">benefits over bash</a>, we’d be making it even better with some choice improvements.</p> <h3 id="starship" style="position:relative;"><a href="#starship" aria-label="starship permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://starship.rs//" target="_blank" rel="nofollow noopener noreferrer">starship</a></h3> <p>Before anything else, we need to de-clutter our terminal prompt. What better way to do so than by installing starship?</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell">brew <span class="token function">install</span> starship</code></pre></div> <p>This provides a minimalist yet information-filled prompt that changes with your context.</p> <p>Make sure that your iTerm2’s font has an alternative option for non-Ascii characters since Monaco (Apple’s default) does not support powerline characters that spaceship needs. I chose to go with <a href="https://github.com/tonsky/FiraCode" target="_blank" rel="nofollow noopener noreferrer">Fira code</a>. Just download and install.</p> <h3 id="zsh-autosuggest" style="position:relative;"><a href="#zsh-autosuggest" aria-label="zsh autosuggest permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://github.com/zsh-users/zsh-autosuggestions" target="_blank" rel="nofollow noopener noreferrer">zsh-autosuggest</a></h3> <p>Wouldn’t it be great if we had autosuggest? This may be the single most useful plugin for zsh. If you’d only install one plugin for zsh, this should be it. This allows zsh to suggest commands as you type them based on your history.</p> <p>Create a <code class="language-text">~/.zshrc.local</code> if you haven’t already. Since by default most general-purpose settings will be in <code class="language-text">.zshrc</code>, we’ll be using the local file for our own custom settings. Let’s also create a <code class="language-text">~/.zsh</code> directory. This is where zsh plugins are commonly installed by default. I prefer manually installing plugins manually (as opposed to using zsh managers such as Oh My Zsh since I think it’s easier to maintain that way) so we’re gonna clone the autosuggest repository ourselves.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token function">git</span> clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions</code></pre></div> <p>Then add the following line to the top of your <code class="language-text">.zshrc.local</code> file.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token builtin class-name">source</span> ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh</code></pre></div> <p>Restart your terminal for it to take effect.</p> <h3 id="zsh-syntax-highlighting" style="position:relative;"><a href="#zsh-syntax-highlighting" aria-label="zsh syntax highlighting permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://github.com/zsh-users/zsh-syntax-highlighting" target="_blank" rel="nofollow noopener noreferrer">zsh-syntax-highlighting</a></h3> <p>Next is syntax highlighting. A minor QoL sure, but still important for those long-winded command strings.</p> <p>Installation is pretty much similar.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token function">git</span> clone https://github.com/zsh-users/zsh-syntax-highlighting ~/.zsh/zsh-syntax-highlighting</code></pre></div> <p>Add the following line near the top of your <code class="language-text">.zshrc.local</code>.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token builtin class-name">source</span> ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh</code></pre></div> <p>As usual, restart your terminal for it to take effect.</p> <h3 id="vim-mode" style="position:relative;"><a href="#vim-mode" aria-label="vim mode permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Vim mode+</h3> <p>Since I’m a Vim user (and disciple, please use Vim), I tend to want to use Vim everywhere I can get it to work. And that means here in the terminal.</p> <p>Add these in <code class="language-text">.zshrc.local</code></p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token comment">##### Enable zsh vim mode</span> bindkey <span class="token parameter variable">-v</span> <span class="token comment">##### Change cursor shape for different vi modes.</span> <span class="token keyword">function</span> <span class="token function-name function">zle-keymap-select</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">${KEYMAP}</span> <span class="token operator">==</span> vicmd <span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">$1</span> <span class="token operator">=</span> <span class="token string">'block'</span> <span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span> <span class="token builtin class-name">echo</span> <span class="token parameter variable">-ne</span> <span class="token string">'\e[1 q'</span> <span class="token keyword">elif</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">${KEYMAP}</span> <span class="token operator">==</span> main <span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">${KEYMAP}</span> <span class="token operator">==</span> viins <span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">${KEYMAP}</span> <span class="token operator">=</span> <span class="token string">''</span> <span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">$1</span> <span class="token operator">=</span> <span class="token string">'beam'</span> <span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span> <span class="token builtin class-name">echo</span> <span class="token parameter variable">-ne</span> <span class="token string">'\e[5 q'</span> <span class="token keyword">fi</span> <span class="token punctuation">}</span> zle <span class="token parameter variable">-N</span> zle-keymap-select <span class="token function-name function">zle-line-init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> zle <span class="token parameter variable">-K</span> viins <span class="token comment"># initiate `vi insert` as keymap (can be removed if `bindkey -V` has been set elsewhere)</span> <span class="token builtin class-name">echo</span> <span class="token parameter variable">-ne</span> <span class="token string">"<span class="token entity" title="\e">\e</span>[5 q"</span> <span class="token punctuation">}</span> zle <span class="token parameter variable">-N</span> zle-line-init <span class="token builtin class-name">echo</span> <span class="token parameter variable">-ne</span> <span class="token string">'\e[5 q'</span> <span class="token comment"># Use beam shape cursor on startup.</span> <span class="token function-name function">preexec</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token builtin class-name">echo</span> <span class="token parameter variable">-ne</span> <span class="token string">'\e[5 q'</span> <span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token comment"># Use beam shape cursor for each new prompt.</span> <span class="token comment">##### Use vim keys traversing history the smart way:</span> autoload <span class="token parameter variable">-U</span> history-search-end zle <span class="token parameter variable">-N</span> history-beginning-search-backward-end history-search-end zle <span class="token parameter variable">-N</span> history-beginning-search-forward-end history-search-end bindkey <span class="token string">"^[[A"</span> history-beginning-search-backward-end bindkey <span class="token string">"^[[B"</span> history-beginning-search-forward-end bindkey <span class="token parameter variable">-M</span> vicmd <span class="token string">'k'</span> history-beginning-search-backward-end bindkey <span class="token parameter variable">-M</span> vicmd <span class="token string">'j'</span> history-beginning-search-forward-end</code></pre></div> <p>A bit of a mouthful I know but bear with me.</p> <p>As commented, these changes allow you to use Vim in the terminal, change the cursor shape in your terminal as you switch modes, and finally (a personal favorite) allow the down(j) and up(k) keys on Vim to search your history based on your already typed command!</p> <p>This means that if you typed <code class="language-text">git</code> and went to command mode and pressed <code class="language-text">k</code>, this will show the previous command you started with <code class="language-text">git</code> as well! Personally I use this feature just about every day.</p> <p>Again, restart your terminal for the changes to take effect.</p> <h3 id="fzf" style="position:relative;"><a href="#fzf" aria-label="fzf permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><a href="https://github.com/junegunn/fzf" target="_blank" rel="nofollow noopener noreferrer">fzf</a></h3> <p>We’re still not done with shell goodness with <code class="language-text">fzf</code> or fuzzy finder. This little tool allows you to zip around your terminal whether you need to quickly change directories or open a file you simply couldn’t remember the full path/name of. Just fuzzy find it!</p> <p>First of, install it.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell">brew <span class="token function">install</span> fzf <span class="token variable"><span class="token variable">$(</span>brew <span class="token parameter variable">--prefix</span><span class="token variable">)</span></span>/opt/fzf/install</code></pre></div> <p>This allows usage of the <code class="language-text">fzf</code> cli command and enables a bunch of commands out of the gate.</p> <p><code class="language-text">Ctrl + T</code> allows you to search for any file and selecting one returns it in your buffer.</p> <p><code class="language-text">Opt + C</code> allows you to search for any directory and selecting one moves you to it.</p> <p>By the way, to actually use <code class="language-text">Opt</code> as a modifier instead of inserting special characters, go to iTerm2’s Preferences -> Profiles -> Profile -> Keys and set your Option key to <code class="language-text">Esc+</code>.</p> <p>These alone however are not enough to maximize your productivity with fzf. By default, fzf uses <a href="https://man7.org/linux/man-pages/man1/find.1.html" target="_blank" rel="nofollow noopener noreferrer">GNU find</a> to execute its searches. Albeit well-featured, it’s not fast. To effectively fuzzy find, fzf will have to crawl over a lot of files to get you the most accurate match. To achieve this, you need to give it a helping hand (or two).</p> <p>First, use <a href="https://github.com/BurntSushi/ripgrep" target="_blank" rel="nofollow noopener noreferrer">ripgrep</a>. Arguably the fastest cli search tool out there, this makes it the best default go-to command for fzf. To do this, simply set the following environment variable in your <code class="language-text">.zshrc.local</code>.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token builtin class-name">export</span> <span class="token assign-left variable">FZF_DEFAULT_COMMAND</span><span class="token operator">=</span><span class="token string">'rg --files --hidden --follow -g "!{.git,node_modules}/*" 2> /dev/null'</span> <span class="token builtin class-name">export</span> <span class="token assign-left variable">FZF_CTRL_T_COMMAND</span><span class="token operator">=</span><span class="token string">"<span class="token variable">$FZF_DEFAULT_COMMAND</span>"</span></code></pre></div> <p>These let fzf know to use <code class="language-text">rg</code> as its default search tool. Next is to exclude certain paths from search. Basically paths where you know you won’t deal with in the terminal yourself. Examples of this are the <code class="language-text">/Library</code> and <code class="language-text">/Pictures</code> directories.</p> <p>These come with macOS with its implementation of iCloud and certain apps. If you don’t exclude these, fzf will have to go through a <em>lot</em> of files to even get to the relevant ones (probably the one in your <code class="language-text">~</code> directory). So if you do need to access those files, skip this step.</p> <p>Create a <code class="language-text">.rgignore</code> file. Any files/directories in this file will be ignored by ripgrep.</p> <p>Sample file:</p> <div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">/Library /Pictures</code></pre></div> <p>More experienced users might note that <code class="language-text">rg</code> won’t work for directories and you’re right. This is well documented in <a href="https://github.com/BurntSushi/ripgrep/issues/169" target="_blank" rel="nofollow noopener noreferrer">ripgrep#169</a> and <a href="https://github.com/BurntSushi/ripgrep/issues/388" target="_blank" rel="nofollow noopener noreferrer">ripgrep#388</a>.</p> <p>So if we can’t use ripgrep and by default fzf’s change directory feature is still using <code class="language-text">find</code> that doesn’t ignore directories, we can’t keep waiting for it to index all those files/directories all day now can we?</p> <p>We can’t. So we need another tool. Namely, <a href="https://github.com/sharkdp/fd" target="_blank" rel="nofollow noopener noreferrer">fd</a>. Touted as the simple and more user-friendly alternative to <code class="language-text">find</code>, fd has exactly the feature we need: an ignore file.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell">brew <span class="token function">install</span> fd</code></pre></div> <p>So much like before, we set the environment variable:</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token builtin class-name">export</span> <span class="token assign-left variable">FZF_ALT_C_COMMAND</span><span class="token operator">=</span><span class="token string">"fd --type d"</span></code></pre></div> <p>Then we create a <code class="language-text">.fdignore</code> file that has the same contents as <code class="language-text">.rgignore</code>. And we’re done.</p> <p>Okay we’re halfway done. The following steps for this guide are specific to the tech stack I commonly use.</p> <h2 id="5-node" style="position:relative;"><a href="#5-node" aria-label="5 node permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>5. Node</h2> <p>As one of the most common developer tools, there are a lot of ways to install this. My favorite is <a href="https://github.com/nvm-sh/nvm" target="_blank" rel="nofollow noopener noreferrer">nvm</a>. This allows you to have multiple node versions in your machine and can easily switch between them with just a simple command.</p> <p>Let’s get started.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token function">curl</span> -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh <span class="token operator">|</span> <span class="token function">bash</span></code></pre></div> <p>Afterwards, make sure the following snippet is in your <code class="language-text">.zshrc</code> file.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token builtin class-name">export</span> <span class="token assign-left variable">NVM_DIR</span><span class="token operator">=</span><span class="token string">"<span class="token variable"><span class="token variable">$(</span><span class="token punctuation">[</span> <span class="token parameter variable">-z</span> <span class="token string">"<span class="token variable">${XDG_CONFIG_HOME-}</span>"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> <span class="token builtin class-name">printf</span> %s <span class="token string">"<span class="token variable">${<span class="token environment constant">HOME</span>}</span>/.nvm"</span> <span class="token operator">||</span> <span class="token builtin class-name">printf</span> %s <span class="token string">"<span class="token variable">${XDG_CONFIG_HOME}</span>/nvm"</span><span class="token variable">)</span></span>"</span> <span class="token punctuation">[</span> <span class="token parameter variable">-s</span> <span class="token string">"<span class="token variable">$NVM_DIR</span>/nvm.sh"</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">\</span>. <span class="token string">"<span class="token variable">$NVM_DIR</span>/nvm.sh"</span> <span class="token comment"># This loads nvm</span></code></pre></div> <p>Restart your terminal and execute <code class="language-text">command -v nvm</code>. This should output “nvm” to tell you it’s working.</p> <p>Running <code class="language-text">nvm install node</code> will install the latest version and set it as your default Node version.</p> <h2 id="6-python" style="position:relative;"><a href="#6-python" aria-label="6 python permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>6. Python</h2> <p>macOS should already come packaged with Python by default. But any Python dev can tell you that it’s a bad idea to have all of your projects depend on a single version of Python, let alone the system-installed one.</p> <p>So how do we fix this? We use a tool much like nvm—<a href="https://github.com/pyenv/pyenv" target="_blank" rel="nofollow noopener noreferrer">pyenv</a>.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell">brew <span class="token function">install</span> pyenv pyenv-virtualenv</code></pre></div> <p>Make sure that the following line is in your <code class="language-text">.zshrc</code>.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token builtin class-name">eval</span> <span class="token string">"<span class="token variable"><span class="token variable">$(</span>pyenv init -<span class="token variable">)</span></span>"</span></code></pre></div> <p>Restart your terminal and pyenv should be working.</p> <h3 id="usage" style="position:relative;"><a href="#usage" aria-label="usage permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Usage</h3> <p>Start with setting the default python version you want to use (which is not the system-installed one).</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token comment">##### As of the time of writing, this is the latest I want my system python to run on</span> pyenv <span class="token function">install</span> <span class="token number">3.9</span>.7 pyenv global <span class="token number">3.9</span>.7</code></pre></div> <p>Running <code class="language-text">python</code> in your terminal should use the version you’ve set as global.</p> <p>Now say you’ve got a project that runs on Python 3.8.12 that as the experienced Python developer that you are, need to use a virtualenv on?</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token comment">##### Install the needed Python version first</span> pyenv <span class="token function">install</span> <span class="token number">3.8</span>.12 <span class="token comment"># 1</span> <span class="token builtin class-name">cd</span> my-python-project <span class="token comment"># 2</span> pyenv virtualenv <span class="token number">3.8</span>.12 my-python-project <span class="token comment"># 3</span> pyenv <span class="token builtin class-name">local</span> my-python-project <span class="token comment"># 4</span></code></pre></div> <p>So what exactly happens after you run these series of commands? 1 and 2 are pretty self-explanatory. 3 just creates the virtualenv with the name you specified (by convention it shares the name of the project) This is possible since we installed <code class="language-text">pyenv-virtualenv</code> along with <code class="language-text">pyenv</code> using Homebrew. And 4 creates a <code class="language-text">.python-version</code> file that has the name of the virtualenv you want to be activated as soon as you <code class="language-text">cd</code> into that directory. Neat, huh?</p> <h2 id="8-docker" style="position:relative;"><a href="#8-docker" aria-label="8 docker permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>8. Docker</h2> <p>Last, but not least, is Docker. Thankfully this is the easiest to install as it’s literally just going to <a href="https://www.docker.com/products/docker-desktop" target="_blank" rel="nofollow noopener noreferrer">Docker for Desktop’s website</a> and just downloading and installing. Once it’s good to go it gives you a UI that is sort of <a href="https://www.portainer.io/" target="_blank" rel="nofollow noopener noreferrer">Portainer</a>-lite that has brief information regarding the logged in Docker user, running containers, and downloaded images.</p> <p>Along with this of course is the Docker runtime that lets you run the <code class="language-text">docker</code> command on your terminal.</p> <p>And with that, we finally come to the end of this so-called 12-minute read which took anything but to write. I hope this helps you and my future self in setting up your development environment, be it in macOS or Linux, the way you want it.</p> <p>As long as it uses Vim, you’re cool.</p><![CDATA[How to handle the LetsEncrypt expiry (and others like it)]]>https://alecgerona.io/letsencrypt-expiry/https://alecgerona.io/letsencrypt-expiry/Sat, 02 Oct 2021 00:00:00 GMT<h2 id="what-happened-and-what-will" style="position:relative;"><a href="#what-happened-and-what-will" aria-label="what happened and what will permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>What happened (and what will)</h2> <p>As of 30 September 2021, LetsEncrypt’s DST Root CA X3 has expired. And unlike a lot of major shit that broke the internet, this was not something due to what LetsEncrypt did or failed to do. Read more about this <a href="https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-e021/" target="_blank" rel="nofollow noopener noreferrer">here</a>.</p> <p>Basically, certificates <em>will</em> expire.</p> <h2 id="what-to-do" style="position:relative;"><a href="#what-to-do" aria-label="what to do permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>What to do</h2> <p>Well, for starters, if you have been keeping on top of your updates, you should have no issues whatsoever. However, for legacy devices/servers that are not, well, that’s what this post is about. There’s already a lot of related write-up regarding the whys and hows so I’d focus on the actual things that I’ve had to do to get past this issue.</p> <h3 id="ubuntu-1404-lts" style="position:relative;"><a href="#ubuntu-1404-lts" aria-label="ubuntu 1404 lts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Ubuntu 14.04 LTS</h3> <p>Let’s start with the oldest. It’s as straightforward as deleting the expired certificate from the store.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token function">sudo</span> <span class="token function">rm</span> /usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt <span class="token function">sudo</span> update-ca-certificates</code></pre></div> <h3 id="ubuntu-1604-lts" style="position:relative;"><a href="#ubuntu-1604-lts" aria-label="ubuntu 1604 lts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Ubuntu 16.04 LTS</h3> <p>A bit newer but still outdated, this is more simple as it has the packages it needs to update your store for you.</p> <div class="gatsby-highlight" data-language="shell"><pre class="language-shell"><code class="language-shell"><span class="token function">sudo</span> <span class="token function">apt</span> <span class="token function">install</span> libgnutls-openssl27 libgnutls30</code></pre></div> <p>And there you go. For other devices such as Windows 10 and smartphone OSs, <a href="https://docs.certifytheweb.com/docs/kb/kb-202109-letsencrypt/" target="_blank" rel="nofollow noopener noreferrer">this</a> should help.</p> <p>I’ll update this post as I encounter related issues that can or can’t be fixed by the above methods.</p><![CDATA[PyRMQ, Python with RabbitMQ—simplified so you won't have to.]]>https://alecgerona.io/pyrmq/https://alecgerona.io/pyrmq/Sun, 28 Mar 2021 00:00:00 GMT<h2 id="the-need" style="position:relative;"><a href="#the-need" aria-label="the need permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>The need</h2> <p>Released almost a year ago, PyRMQ was created to make RabbitMQ more accessible than it is. RabbitMQ, in case you didn’t know, is an open source message broker. To summarize the technology in so little words: it’s a way to manage, direct, and even contain connections between systems or points in the form of messages. Okay, but what does that really mean?</p> <blockquote> <p>Exchanges, Queues, and Messages.</p> </blockquote> <p><a href="https://www.rabbitmq.com/" target="_blank" rel="nofollow noopener noreferrer">RabbitMQ</a> primarily works with the above three. Exchanges are bound to queues which in turn house the messages that get sent to exchanges. Weird loop? Bear with me. All you need to know about RabbitMQ is that you take your message (can be anything from a JSON payload, text, or even blank), pick an exchange to send it to, the exchange will direct it to whatever queue it’s bound to, and your intended recipient that is set up to listen or <em>consume</em> from that queue will receive it!</p> <p>Now, coming from a RESTful background, this may seem unfamiliar territory, and I agree. Since RabbitMQ follows a certain protocol, <a href="https://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol" target="_blank" rel="nofollow noopener noreferrer">AMQP</a>, it certainly has its own learning curve. As such, numerous libraries attempt to abstract all these in their respective languages. The one I’ll highlight in this post is <a href="https://pypi.org/project/pika/" target="_blank" rel="nofollow noopener noreferrer">pika</a> for Python. An already amazing library by itself, we felt that we could abstract it further (kinda like Gatsby for React); especially since our architecture revolves around microservices—we’d be reusing all this code to boilerplate our RabbitMQ multiple times!</p> <blockquote> <p>Enter, PyRMQ</p> </blockquote> <p>With PyRMQ, it’s as easy as instantiating one class!</p> <div class="gatsby-highlight" data-language="py"><pre class="language-py"><code class="language-py"><span class="token keyword">from</span> pyrmq <span class="token keyword">import</span> Publisher publisher <span class="token operator">=</span> Publisher<span class="token punctuation">(</span> exchange_name<span class="token operator">=</span><span class="token string">"exchange_name"</span><span class="token punctuation">,</span> queue_name<span class="token operator">=</span><span class="token string">"queue_name"</span><span class="token punctuation">,</span> routing_key<span class="token operator">=</span><span class="token string">"routing_key"</span><span class="token punctuation">,</span> <span class="token punctuation">)</span> publisher<span class="token punctuation">.</span>publish<span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string">"pyrmq"</span><span class="token punctuation">:</span> <span class="token string">"My first message"</span><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre></div> <p>And with that, you’ve already published your first message! Feel free to look over PyRMQ’s <a href="https://github.com/first-digital-finance/pyrmq" target="_blank" rel="nofollow noopener noreferrer">source code</a> to see exactly which pika classes/methods it uses to make all this work.</p> <p>Great, how do I receive this message then?</p> <div class="gatsby-highlight" data-language="py"><pre class="language-py"><code class="language-py"><span class="token keyword">from</span> pyrmq <span class="token keyword">import</span> Consumer <span class="token keyword">def</span> <span class="token function">callback</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string-interpolation"><span class="token string">f"Received </span><span class="token interpolation"><span class="token punctuation">{</span>data<span class="token punctuation">}</span></span><span class="token string">!"</span></span><span class="token punctuation">)</span> consumer <span class="token operator">=</span> Consumer<span class="token punctuation">(</span> exchange_name<span class="token operator">=</span><span class="token string">"exchange_name"</span><span class="token punctuation">,</span> queue_name<span class="token operator">=</span><span class="token string">"queue_name"</span><span class="token punctuation">,</span> routing_key<span class="token operator">=</span><span class="token string">"routing_key"</span><span class="token punctuation">,</span> callback<span class="token operator">=</span>callback <span class="token punctuation">)</span> consumer<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre></div> <p>Just like that. This class launches a thread safe instance to receive your message.</p> <p>As of the time of writing, PyRMQ has been battle-tested over at <a href="https://www.firstdigitalfinance.com/" target="_blank" rel="nofollow noopener noreferrer">FDFC</a> to achieve high availability with dealing with financial processes. Furthermore, PyRMQ is proud to hold <a href="https://codecov.io/gh/first-digital-finance/pyrmq" target="_blank" rel="nofollow noopener noreferrer">100% coverage</a> with its tests.</p> <p>We’re always looking for contributors! If you see an issue (even a typo, really), let’s do something about it at <a href="https://github.com/first-digital-finance/pyrmq" target="_blank" rel="nofollow noopener noreferrer">PyRMQ’s GitHub</a>!</p> <p>Wanna learn more? Head over to <a href="https://pyrmq.readthedocs.io" target="_blank" rel="nofollow noopener noreferrer">PyRMQ’s documentation</a>!</p><![CDATA[Dark mode with Gatsby.js and Tailwindcss]]>https://alecgerona.io/dark-mode/https://alecgerona.io/dark-mode/Tue, 11 Aug 2020 00:00:00 GMT<h2 id="modern-dark-mode" style="position:relative;"><a href="#modern-dark-mode" aria-label="modern dark mode permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Modern dark mode</h2> <p>Since you’re most probably a developer (let’s face it you’re only here because you googled “how to implement dark mode [tech stack]”), you surely know that dark mode is fortunately prevalent in mainstream UIs. It’s not unique to rated-R sites anymore. So naturally, you’d want this feature into as many screens you’re looking at.</p> <h2 id="what-were-working-with" style="position:relative;"><a href="#what-were-working-with" aria-label="what were working with permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>What we’re working with</h2> <p>Now, <a href="https://www.techopedia.com/definition/31094/evergreen-browser#:~:text=The%20term%20%22evergreen%20browser%22%20refers,the%20case%20with%20older%20browsers." target="_blank" rel="nofollow noopener noreferrer">evergreen browsers</a> have mechanisms in place to support dark mode, along with other accessibility features such as reduced motion toggle. They expose this through a flag called <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme" target="_blank" rel="nofollow noopener noreferrer"><code class="language-text">prefers-color-scheme</code></a>. This flag can only have two values: <code class="language-text">light</code> or <code class="language-text">dark</code>. Now you might be thinking that hey I already have a flag which tells me which theme the user wants by default, I can just base my styling around this! And you’re right.</p> <h2 id="but-what-if-you-want-to-toggle-it" style="position:relative;"><a href="#but-what-if-you-want-to-toggle-it" aria-label="but what if you want to toggle it permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>But what if you want to toggle it?</h2> <p>This is the meat of this blog post. You see, that flag <em>cannot</em> be toggled locally. It is based on the user’s system preferences therefore only being changeable through their system. Ergo, we need to find another way of making that logic work. So is my plot twist alert accurate here? Is it not easy? Like any self-respecting developer would tell you: it depends. In our case, it depends on Gatsby.js and Tailwincss, the two things I happened to build this website with. (If you want more info on <em>why</em> I chose those, feel free to read my <a href="https://alecgerona.io/my-first-website/" target="_blank" rel="nofollow noopener noreferrer">post about it</a>.</p> <h2 id="tailwindcss-implementation" style="position:relative;"><a href="#tailwindcss-implementation" aria-label="tailwindcss implementation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Tailwindcss implementation</h2> <p>Let’s get the easy stuff out of the way. How should we style our components with our requirement in mind? Again, this implementation is not unique to Tailwindcss, but if it gets you to use it, why the hell not? Tailwindcss is awesome.</p> <p>Now most guides will tell you to set your styles up with a <code class="language-text">dark</code> prefix or handler. This lets you organize your site and codebase based on separated style concerns.</p> <h3 id="so-what-prefix-do-i-use" style="position:relative;"><a href="#so-what-prefix-do-i-use" aria-label="so what prefix do i use permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>So what prefix do I use?</h3> <p>It’s easy to knee-jerk it with <code class="language-text">dark</code>. That’s what the majority uses anyway. It comes from what I believe the mobile-first design philosophy that dictates designs should revolve around mobile and just adapt for desktop. So why not do the same for dark mode?</p> <p>Let me propose a counter argument: dark first.</p> <p>Hear me out. Since my website’s theme is primarily “dark”, it makes sense to make the variant styles light. This is also in line with how Tailwindcss’ variants were designed to work: use plain utility classes for your default design and add variant prefixes for the alternate or secondary one. So obviously your design is different so trust your own judgment.</p> <h3 id="creating-the-variants" style="position:relative;"><a href="#creating-the-variants" aria-label="creating the variants permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating the variants</h3> <p>Creating your own mode prefix in Tailwindcss is done by adding a plugin to your <code class="language-text">tailwind.config.js</code> file.</p> <div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token comment">// ...</span> <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token function">plugin</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> addVariant<span class="token punctuation">,</span> e <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> lightSelector <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.light</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token function">addVariant</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">light</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> modifySelectors<span class="token punctuation">,</span> separator <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">modifySelectors</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> className <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightSelector<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> .</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token function">e</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">light</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>separator<span class="token interpolation-punctuation punctuation">}</span></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token comment">// ...</span></code></pre></div> <p>To summarize this block of code briefly, this just allows you to write Tailwincss utility classes with your specified selector (<code class="language-text">.light</code> in my case). <code class="language-text">modifySelectors</code> just formats your utility classes in a way that we can scope for when we actually implement the toggle logic.</p> <p>To actually use this variant, you have to enable it for the utility classes you actually need them for.</p> <div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token comment">// ...</span> <span class="token literal-property property">variants</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">backgroundColor</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">light</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token literal-property property">textColor</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">light</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token comment">// ...</span></code></pre></div> <p>This helps Tailwindcss be conservative in generating its utility classes, of which there are a lot by default due to its design. You can read more about Tailwincss’ variant implementation <a href="https://tailwindcss.com/docs/configuring-variants" target="_blank" rel="nofollow noopener noreferrer">here</a>.</p> <p>Now believe it or not, that’s actually it. You can now plug classes like <code class="language-text">text-white light:text-black</code> to your components and have the class names get manipulated properly by Tailwindcss according to our <code class="language-text">modifySelector</code> logic. But at this point, it’s not yet actually doing anything significant. The selector that our variant is depending on is still not present nor toggle-able.</p> <h2 id="gatsbyjs-implementation" style="position:relative;"><a href="#gatsbyjs-implementation" aria-label="gatsbyjs implementation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Gatsby.js implementation</h2> <p>Full disclosure, this solution is based on Dan Abramov’s implementation of dark mode in his <a href="https://overreacted.io/" target="_blank" rel="nofollow noopener noreferrer">blog</a> plus a few other tutorials I’ve read about the topic. Having said that, I believe this implementation of the solution is more approachable for developers looking for flexibility with this feature.</p> <p>So first off, we need to structure the logic that we need. For my blog, I wanted a simple button that will toggle the mode on and off. Like a bulb. So I made a simple component that would do this for me:</p> <div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>toggleTheme<span class="token punctuation">}</span></span> <span class="token punctuation">></span></span><span class="token plain-text"> </span><span class="token punctuation">{</span>theme <span class="token operator">===</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">light</span><span class="token template-punctuation string">`</span></span> <span class="token operator">?</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Night</span></span> <span class="token punctuation">/></span></span> <span class="token operator">:</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Day</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">}</span><span class="token plain-text"> </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre></div> <p>Simple enough. Then, I have to define what <code class="language-text">toggleTheme</code> does.</p> <div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token keyword">function</span> <span class="token function">toggleTheme</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> window<span class="token punctuation">.</span><span class="token function">__setPreferredTheme</span><span class="token punctuation">(</span>theme <span class="token operator">===</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">light</span><span class="token template-punctuation string">`</span></span> <span class="token operator">?</span> <span class="token string">"dark"</span> <span class="token operator">:</span> <span class="token string">"light"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></code></pre></div> <p>Okay hold up. Why are we suddenly accessing window functions? What exactly is this <code class="language-text">__setPreferredTheme()</code>?</p> <p>This is actually the trick to this feature. To give you a brief idea of the issues this approach solves, implementing dark mode, or really any theme picker feature, presents the web developer with the flicker problem. We have to execute (and set) our function early enough the browser is forced to evaluate its result before first paint happens aka that brief flicker of white (or your default bg color) you see before the browser applies the user-preferred theme.</p> <p>So how and where do we place this function? The how of course is by hooking it to <code class="language-text">window</code>. It’s global and easily set via script. As to where? Remember that we have to execute this function <em>before</em> anything visible is rendered. Gatsby.js offers a way to do this via their <code class="language-text">setPreBodyComponents</code> hook. As the name suggests, this allows us to set a component before our html body. And as you may have guessed, we’re gonna put a script tag.</p> <p>Since this Gatsby.js hook is trigered in the <code class="language-text">gatsby-ssr.js</code> file, we should edit it like so:</p> <div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token keyword">const</span> React <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"react"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> exports<span class="token punctuation">.</span><span class="token function-variable function">onRenderBody</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> setPreBodyComponents <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">setPreBodyComponents</span><span class="token punctuation">(</span><span class="token punctuation">[</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"script"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token literal-property property">key</span><span class="token operator">:</span> <span class="token string">"gatsby-dark-mode"</span><span class="token punctuation">,</span> <span class="token literal-property property">dangerouslySetInnerHTML</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">__html</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> void function() { window.__onThemeChange = function() {} var preferredTheme try { preferredTheme = localStorage.getItem('theme') } catch (err) { } function setTheme(newTheme) { if (preferredTheme &amp;&amp; document.documentElement.classList.contains(preferredTheme)) { document.documentElement.classList.replace(preferredTheme, newTheme) } else { document.documentElement.classList.add(newTheme) } window.__theme = newTheme preferredTheme = newTheme window.__onThemeChange(newTheme) } window.__setPreferredTheme = function(newTheme) { setTheme(newTheme) try { localStorage.setItem('theme', newTheme) } catch (err) {} } var darkQuery = window.matchMedia('(prefers-color-scheme: dark)') darkQuery.addListener(function(e) { window.__setPreferredTheme(e.matches ? 'dark' : 'light') }) setTheme(preferredTheme || (darkQuery.matches ? 'dark' : 'light')) }() </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div> <p>A bit of an eyeful to be sure, but let’s just focus on the important parts there. First, we define <code class="language-text">window.__onThemeChange</code> as a utility to be overridden by our component later. Next, we check <code class="language-text">localStorage</code> whether we already have the user’s preference locally. We just wrap it under a try-catch to silence any issues that may arise. You can improve this if you want. Then we just define a simple function that replaces the class defined in our <code class="language-text">html</code> tag with the theme the user chose. This function is wrapped globally with <code class="language-text">window.setPreferredTheme</code>.</p> <p>Next is just some quality-of-life line that gets and listens for the value of <code class="language-text">prefers-color-scheme</code>. So even if the user does change the setting on a system level, we can catch it. Finally, the <code class="language-text">setTheme()</code> at the end just initializes the theme for the first paint.</p> <p>With the above hook set, the pieces are now complete. We can top off our toggler component with the hooks it’d need to function as we’d like it to.</p> <div class="gatsby-highlight" data-language="jsx"><pre class="language-jsx"><code class="language-jsx"><span class="token keyword">const</span> <span class="token literal-property property">DarkModeToggle</span><span class="token operator">:</span> React<span class="token punctuation">.</span><span class="token function-variable function">FC</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>theme<span class="token punctuation">,</span> setTheme<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token keyword">undefined</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// @ts-ignore</span> <span class="token function">setTheme</span><span class="token punctuation">(</span>window<span class="token punctuation">.</span>__theme<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// @ts-ignore</span> window<span class="token punctuation">.</span><span class="token function-variable function">__onThemeChange</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// @ts-ignore</span> <span class="token function">setTheme</span><span class="token punctuation">(</span>window<span class="token punctuation">.</span>__theme<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">toggleTheme</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// @ts-ignore</span> window<span class="token punctuation">.</span><span class="token function">__setPreferredTheme</span><span class="token punctuation">(</span>theme <span class="token operator">===</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">light</span><span class="token template-punctuation string">`</span></span> <span class="token operator">?</span> <span class="token string">"dark"</span> <span class="token operator">:</span> <span class="token string">"light"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">className</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token operator">!</span>theme <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">invisible</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">visible cursor-pointer</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">}</span></span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>toggleTheme<span class="token punctuation">}</span></span> <span class="token punctuation">></span></span><span class="token plain-text"> </span><span class="token punctuation">{</span>theme <span class="token operator">===</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">light</span><span class="token template-punctuation string">`</span></span> <span class="token operator">?</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Night</span></span> <span class="token punctuation">/></span></span> <span class="token operator">:</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Day</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">}</span><span class="token plain-text"> </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></code></pre></div> <p>So by using React hooks, we now have a component that will load the theme on render via <code class="language-text">useEffect()</code> and set its displayed icon depending on the selector and use of <code class="language-text">useState()</code>.</p> <p>And there you have it. Once you load this component up, clicking on it should load the proper selector in our html tag which in turn triggers the loadout our variant requires which shows the correct styles. In short, we now have dark mode.</p> <p>To see all these components and logic written out in all their glory, take a quick look at <em>this</em> website’s <a href="https://github.com/alecgerona" target="_blank" rel="nofollow noopener noreferrer">source code</a>. It contains bonus content such as implementing dark mode on code that is effectively unreachable by your Tailwindcss variants such as this blog section that is styled by the Tailwindcss <a href="https://tailwindcss.com/docs/typography-plugin" target="_blank" rel="nofollow noopener noreferrer">typography plugin</a>. You can star or help improve it if you want. Or not. I’m not telling you what to do. Well, except for this tutorial.</p> <p>Again, if you’ve read up to this point and you’re not me, wow. And thank you. I hope you’ve found this helpful.</p><![CDATA[My first website]]>https://alecgerona.io/my-first-website/https://alecgerona.io/my-first-website/Mon, 20 Jul 2020 00:00:00 GMT<h2 id="ive-never-had-a-website-before" style="position:relative;"><a href="#ive-never-had-a-website-before" aria-label="ive never had a website before permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>I’ve never had a website before</h2> <p>I’ve been a programmer for years now, and I’ve never had my own personal website. Why? Probably due to a lot of factors. Never really been into frontend development for one. Javascript is <a href="http://mauricio.github.io/javascript-from-hell/" target="_blank" rel="nofollow noopener noreferrer">hell</a> for two. And I’m just not a fan of publicly sharing my thoughts.</p> <h2 id="but-i-need-one" style="position:relative;"><a href="#but-i-need-one" aria-label="but i need one permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>But I need one</h2> <p>I basically needed a place to write blogs (or self-tutorials since no one will read this blog but me if we’re being honest) on a place I control and won’t place a paywall for. Unlike *cough* <a href="https://www.reddit.com/r/Blogging/comments/b0vaat/what_are_you_doing_about_the_medium_paywall/" target="_blank" rel="nofollow noopener noreferrer">Medium</a> *cough*.</p> <h2 id="i-also-dislike-long-form-articles" style="position:relative;"><a href="#i-also-dislike-long-form-articles" aria-label="i also dislike long form articles permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>I also dislike long-form articles</h2> <p>So let’s get down to the nitty gritty. This article is meant to remind me of why the hell I decided to build this website this way while it’s still fresh in my mind. I’ll try to (hopefully) make sense of it all not just for me, but for you who must have mistakenly stumbled upon this site. Succeeding articles will be the bits that go deeper with code snippets regarding the tricky parts in developing this website.</p> <h2 id="gatsbyjs-tailwindcss-and-typescript" style="position:relative;"><a href="#gatsbyjs-tailwindcss-and-typescript" aria-label="gatsbyjs tailwindcss and typescript permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Gatsby.js, Tailwindcss, and Typescript</h2> <p>That’s one SEO to-do out of the way. For a quick TLDR, here’s the <a href="https://github.com/alecgerona/alecgerona.io" target="_blank" rel="nofollow noopener noreferrer">source code</a>.</p> <p>Let’s go one-by-one as to why I chose the stack I did.</p> <h2 id="gatsbyjs" style="position:relative;"><a href="#gatsbyjs" aria-label="gatsbyjs permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Gatsby.js</h2> <p>Personally, I just wanted to try React. My frontend experience up to this point was limited to Angular and Vue.js frameworks. Seeing that I didn’t want to spend a staggering amount of time boilerplating and benchmarking my website, I went with Gatsby.js. It has built-in features that I really wanted to try like GraphQL along with its claim that it’s <em>blazing fast</em>™. So when I was searching for a React framework, it boiled down to Gatsby vs Next since my website fit the case for <a href="https://jamstack.org/" target="_blank" rel="nofollow noopener noreferrer">JAMstack</a>. And between the two of them? Gatsby’s documentation and community simply ran circles around Next’s.</p> <h2 id="tailwindcss" style="position:relative;"><a href="#tailwindcss" aria-label="tailwindcss permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Tailwindcss</h2> <p>When I first encountered Tailwind, proponents were claiming that it’s the CSS framework to use for devs who don’t want to get down with CSS. Now frankly this actually is underrating Tailwind. You even hear this kind of sentiment all the time.</p> <blockquote> <p>Instead of learning X, use Y.</p> </blockquote> <p>This train of thought has always been a popular if not detrimental trope for new tech. Current thing too complicated or low-level to learn? Invent a new tool or solution to abstract it. In fact, this is the main push of CSS frameworks in general like Bootstrap or Foundation. Just use their components masquerading as classes and you’re off. But in my experience with Tailwind, it actually works both ways. Sure, you don’t need to write CSS. Sure, it’s practically inline styles. Sure, it may look “ugly” looking at it the first time.</p> <p><strong>But it actually teaches you how CSS inherently work</strong>. By combining the various utility classes you begin to understand why certain CSS styles work the way they do. Perennial questions such as how to center a <code class="language-text">div</code> both horizontally and vertically, done. How to align contents along its axis, done. How to use flex for various spacings, done.</p> <p>And when you’re done? Not only do you know how to style websites with Tailwind, you also know how to style it with just CSS.</p> <h2 id="typescript" style="position:relative;"><a href="#typescript" aria-label="typescript permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Typescript</h2> <p>You may be surprised to know that this one was a bit harder to justify. I’ve always been a fan of typed languages’ type checking. It simply helps you avoid common coding mistakes and have you really think about what your code does and what it needs or returns. Having Angular 2+ with built-in Typescript experience, this should be an easy choice for me.</p> <p>So what made it difficult?</p> <p>Community adoption. Loads of React tutorials or even Gatsby tutorials are written in plain Javascript. Naturally this presents a barrier for adoption as the very guides you read are not like your codebase. Having the latest and bleeding edge isn’t all rainbows and butterflies if you can’t maintain it.</p> <p>Nevertheless, I still want Typescript to be treated as a first-class citizen for frameworks such as Gatsby and similar frameworks. Its benefits still outweigh its cons, albeit barely. So I went ahead.</p> <h2 id="devops" style="position:relative;"><a href="#devops" aria-label="devops permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>DevOps</h2> <p>Nothing too fancy for this. I just wanted a development and release flow that’s cheap if not free, great with opensource, and easily maintainable. Furthermore, I would want to go back to this project not just to write articles, but to take as basis for my future frontend work. To that end, the following flow may be overkill.</p> <ol> <li>CI/CD is handled by Github’s Workflow.</li> <li>Commit formatting is handled by <a href="https://github.com/commitizen/cz-cli" target="_blank" rel="nofollow noopener noreferrer">Commitizen</a>.</li> <li>Versioning is handled by <a href="https://github.com/semantic-release/semantic-release" target="_blank" rel="nofollow noopener noreferrer">semantic-release</a>.</li> <li>Dependency maintenance is handled by <a href="https://github.com/renovatebot/renovate" target="_blank" rel="nofollow noopener noreferrer">Renovate</a>.</li> <li>Hosting is with <a href="https://www.netlify.com/" target="_blank" rel="nofollow noopener noreferrer">Netlify</a>. I’ve debated going with AWS, and I might, when I get around to developing</li> </ol> <p>my own comment section.</p> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>I think that covers just about everything for this site. I’ll periodically update this article as I iterate over its development.</p> <p>So if you’ve made it this far and you’re not me, wow.</p>