<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Huy Nguyen - I do things and sometimes I blog about it</title>
    
    
    
    <link>https://huynguyen.me/</link>
    <description>My personal website and blog documenting projects in regards to home lab, self-hosting and anything and everything of interest to me.</description>
    
    <language>en-us</language>
    
    
    <lastBuildDate>Wed, 24 Dec 2025 16:53:17 -0600</lastBuildDate>
    
	<atom:link href="https://huynguyen.me/rss.xml" rel="self" type="application/rss+xml" />
    
    
    
    <item>
      <title>Favorite Thangs in 2025</title>
      <link>https://huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/</link>
      <pubDate>Wed, 24 Dec 2025 16:53:17 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/</guid>
      <description>
        
          
          
          
        
        
        &lt;h2 id=&#34;intro&#34;&gt;
  Intro
  &lt;a href=&#34;#intro&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This year has been absolutely a joke for America and not in a good way. So while this country continues to crash out, there&amp;rsquo;s been some good things I&amp;rsquo;ve enjoyed this year. Let&amp;rsquo;s get started!&lt;/p&gt;
&lt;h2 id=&#34;favorite-movies-i-watched&#34;&gt;
  Favorite Movies I watched
  &lt;a href=&#34;#favorite-movies-i-watched&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;weapons-2025&#34;&gt;
  Weapons (2025)
  &lt;a href=&#34;#weapons-2025&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/weapons.jpg&#34;  alt=&#34;Weapons (2025)&#34;  /&gt;

One of my favorite horror movies of this year, not specifically because it was scary, but it played with some interesting ideas and that ending sequence, so good.&lt;/p&gt;
&lt;h3 id=&#34;sinners-2025&#34;&gt;
  Sinners (2025)
  &lt;a href=&#34;#sinners-2025&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/sinners.jpg&#34;  alt=&#34;Sinners (2025)&#34;  /&gt;

This was a fantastic horror movie staring Michael B. Jordan. I really love the idea of a period piece taking place in the south and dealing with Vampires. It combined a lot of interesting ideas in this one.&lt;/p&gt;
&lt;h3 id=&#34;m3gan-20-2025&#34;&gt;
  M3GAN 2.0 (2025)
  &lt;a href=&#34;#m3gan-20-2025&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/m3gan.jpg&#34;  alt=&#34;M3GAN (2025)&#34;  /&gt;

While the first movie was a &amp;ldquo;horror&amp;rdquo; movie, this one was anything but that. It was however a ridiculous movie that knew exactly what it was doing playing of the ridiculousness of the first one.&lt;/p&gt;
&lt;h3 id=&#34;superman-2025&#34;&gt;
  Superman (2025)
  &lt;a href=&#34;#superman-2025&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/superman.jpg&#34;  alt=&#34;Superman (2025)&#34;  /&gt;

This was an amazing super hero movie, we got a very boy scout Superman in this, which is great. The Justice Gang was amazing, loved the casting there. Oh and we cannot talk enough about how good of a boy Krypto was.&lt;/p&gt;
&lt;h3 id=&#34;thunderbolts-2025&#34;&gt;
  Thunderbolts* (2025)
  &lt;a href=&#34;#thunderbolts-2025&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/thunderbolts.jpg&#34;  alt=&#34;Thunderbolts* (2025)&#34;  /&gt;

In terms of favorite Super Hero movie of the year, it has to be Thunderbolts. This one hit all the notes for me, comedy, action, and real underlying story of depression and grief. This was definitely 🧑🏽‍🍳😘&lt;/p&gt;
&lt;h3 id=&#34;beginners-2010&#34;&gt;
  Beginners (2010)
  &lt;a href=&#34;#beginners-2010&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/beginners.jpg&#34;  alt=&#34;Beginners (2010)&#34;  /&gt;

I re-watched this movie this year and I&amp;rsquo;m still enamored about this movie. It&amp;rsquo;s such a good story about allowing one&amp;rsquo;s self to open up to the opportunity of something. Ewan McGregor who plays the main character, is depicted as this kinda depressed, quirky, plain human and how he tells the story of the events unfolding is lovely. The subplot about the late stage life of his father is just fantastic. If you&amp;rsquo;re a quirky kinda romantic, I think this is a good one to watch.&lt;/p&gt;
&lt;h3 id=&#34;babyteeth-2020&#34;&gt;
  Babyteeth (2020)
  &lt;a href=&#34;#babyteeth-2020&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/babyteeth.jpg&#34;  alt=&#34;Babyteeth (2020)&#34;  /&gt;

I knew this was gonna be a kinda depressing watch, I&amp;rsquo;ve had this movie on my list for a while and only this year did I get around to it. I don&amp;rsquo;t want to give much away about it, but it deals with a young girl&amp;rsquo;s late stage cancer and how she is dealing with it. As much as it was about Eliza Scanlen&amp;rsquo;s character, Milla, the story told of the parents dealing with the inevitable loss of their child was so great. The ending scenes in this movie really got me.&lt;/p&gt;
&lt;h3 id=&#34;the-friend-2024&#34;&gt;
  The Friend (2024)
  &lt;a href=&#34;#the-friend-2024&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/the_friend.jpg&#34;  alt=&#34;The Friend (2024)&#34;  /&gt;

I like a lot of weird little movies that Bill Murray is in, but this one staring Naomi Watts was so good. The main challenge was that Naomi&amp;rsquo;s character, Iris has to deal with wishes of her dear departed friend and take care of this old Great Dane. Having lost my dog in recent years, it really got to me.&lt;/p&gt;
&lt;h2 id=&#34;favorite-shows-i-watched&#34;&gt;
  Favorite Shows I watched
  &lt;a href=&#34;#favorite-shows-i-watched&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I watched a lot of shows this year, so I&amp;rsquo;ve tried to keep this list tidy. Here we go!&lt;/p&gt;
&lt;h3 id=&#34;the-residence&#34;&gt;
  The Residence
  &lt;a href=&#34;#the-residence&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/the_residence.jpg&#34;  alt=&#34;The Residence&#34;  /&gt;

Staring Uzo Aduba as Cordelia Cupp, this detective murder mystery series was amazing. I loved everything about it, the quirkiness of the characters, the mystery of the murder, it was just great. I really wished people enjoyed it more to get a second season.&lt;/p&gt;
&lt;h3 id=&#34;alien-earth&#34;&gt;
  Alien: Earth
  &lt;a href=&#34;#alien-earth&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/alien_earth.jpg&#34;  alt=&#34;Alien: Earth&#34;  /&gt;

First ever Alien franchise television series, yes please. While there was a lot to accept about this story, android children and taking place on Earth being some of the least desirable plot points to me, what they did really well was the inclusion of so many weird extraterrestrial species and I mean eyeball alien is definitely my new favorite.&lt;/p&gt;
&lt;h3 id=&#34;the-studio&#34;&gt;
  The Studio
  &lt;a href=&#34;#the-studio&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/the_studio.jpg&#34;  alt=&#34;The Studio&#34;  /&gt;

Seth Rogen&amp;rsquo;s comedy satire about hollywood was an amazing rollercoaster ride of a show, each episode was absolutely insane.&lt;/p&gt;
&lt;h3 id=&#34;normal-people-2020&#34;&gt;
  Normal People (2020)
  &lt;a href=&#34;#normal-people-2020&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/normal_people.jpg&#34;  alt=&#34;Normal People (2020)&#34;  /&gt;

I&amp;rsquo;ve heard high praises about this romance series, so I finally got around to checking it. I have to say that I really enjoyed the long drawn romance taking place over the course of high school to uni to after. I liked the complexity of the 2 main characters, Connell and Marianne, they&amp;rsquo;re also very Neurodivergent coded.&lt;/p&gt;
&lt;h3 id=&#34;star-trek-discovery&#34;&gt;
  Star Trek: Discovery
  &lt;a href=&#34;#star-trek-discovery&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/star_trek_discovery.jpg&#34;  alt=&#34;Star Trek: Discovery&#34;  /&gt;

So I got on a Star Trek kick this year and watched all of Discovery and then later Strange New Worlds. I really really enjoyed the characters and world building they did in Discovery. What&amp;rsquo;s great about Star Trek as a &amp;ldquo;space&amp;rdquo; franchise is that it&amp;rsquo;s always more so focused on hope and the possibility of adventure as opposed to Star Wars being more focused on battle and attrition. You can&amp;rsquo;t help but watch an episode and be wowed.&lt;/p&gt;
&lt;h3 id=&#34;star-trek-strange-new-worlds&#34;&gt;
  Star Trek: Strange New Worlds
  &lt;a href=&#34;#star-trek-strange-new-worlds&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/star_trek_strange_new_worlds.jpg&#34;  alt=&#34;Star Trek: Strange New Worlds&#34;  /&gt;

For as great as Discovery is, I think Strange New Worlds is my particular jam. Seeing a young Spock nail the weirdness/struggle of his character is amazing. As always each character on the series is just fantastic, top notch.&lt;/p&gt;
&lt;h3 id=&#34;king-of-the-hill-old--revival&#34;&gt;
  King of the Hill (Old + Revival)
  &lt;a href=&#34;#king-of-the-hill-old--revival&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/king_of_the_hill.jpg&#34;  alt=&#34;King of the Hill&#34;  /&gt;

When I heard that King of the Hill was getting a revival and picking up several years after the series ended. I had to go back and re-watch all of it all. The old series still holds up. The new season was amazing, they really aged the characters in terms of progression and character development really well. The voice actor shuffling wasn&amp;rsquo;t bad, I understand why the did and don&amp;rsquo;t have any issues there. I really enjoyed how Bobby went from this kinda unsure of himself and sometimes cocky kid to this stressed out adult trying to build something he can be proud of and living life. I can&amp;rsquo;t wait to see what they do for another new season and who they can bring back.&lt;/p&gt;
&lt;h3 id=&#34;honorable-mentions&#34;&gt;
  Honorable Mentions
  &lt;a href=&#34;#honorable-mentions&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;There were some great second and final seasons this year that I had to drop a mention below!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Silo (Season 2)&lt;/li&gt;
&lt;li&gt;Severance (Season 2)&lt;/li&gt;
&lt;li&gt;Platonic (Season 2)&lt;/li&gt;
&lt;li&gt;Peacemakere (Season 2)&lt;/li&gt;
&lt;li&gt;Resident Alien (Season 4)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;favorite-video-games-i-played&#34;&gt;
  Favorite Video Games I Played
  &lt;a href=&#34;#favorite-video-games-i-played&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;death-stranding-2&#34;&gt;
  Death Stranding 2
  &lt;a href=&#34;#death-stranding-2&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/death_stranding_2.jpg&#34;  alt=&#34;Death Stranding 2&#34;  /&gt;

The second and maybe final entry into this crazy game by Kojima. I have to say it&amp;rsquo;s just as weird and awesome as the first game.&lt;/p&gt;
&lt;h3 id=&#34;dispatch&#34;&gt;
  Dispatch
  &lt;a href=&#34;#dispatch&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/dispatch.jpg&#34;  alt=&#34;Dispatch&#34;  /&gt;

It&amp;rsquo;s been a long while since I played a game like the Telltale ones, but this Super Hero one really intrigued me. Loved how quirky, inappropriate and funny this game was. The whole dispatching super hero game mechanic really scratched that resource management itch.&lt;/p&gt;
&lt;h3 id=&#34;clair-obscur-expedition-33-currently-playing&#34;&gt;
  Clair Obscur: Expedition 33 (Currently playing)
  &lt;a href=&#34;#clair-obscur-expedition-33-currently-playing&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/clair_obscur.jpg&#34;  alt=&#34;Clair Obscur: Expedition 33&#34;  /&gt;

I&amp;rsquo;m currently still playing this one, but wow the beginning of this game really set the tone. I can&amp;rsquo;t wait to finish this. The only thing I really dislike, is the whole dodge/parry mechanic during turn based combat.&lt;/p&gt;
&lt;h2 id=&#34;favorite-things-i-read&#34;&gt;
  Favorite Things I read
  &lt;a href=&#34;#favorite-things-i-read&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This year I read a few different mediums, but only a handful of them I would call my favorite, so I&amp;rsquo;m combining comics, manga and novels this year.&lt;/p&gt;
&lt;h3 id=&#34;after-god-manga&#34;&gt;
  After God (Manga)
  &lt;a href=&#34;#after-god-manga&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/after_god.jpg&#34;  alt=&#34;After God (Manga)&#34;  /&gt;

It&amp;rsquo;s kinda hard to describe this one, it&amp;rsquo;s playing around with a lot of interesting concepts about these all powerful god like beings who exist in Japan and have devastated the land.&lt;/p&gt;
&lt;h3 id=&#34;hirayasumi-manga&#34;&gt;
  Hirayasumi (Manga)
  &lt;a href=&#34;#hirayasumi-manga&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/hirayasumi.jpg&#34;  alt=&#34;Hirayasumi (Manga)&#34;  /&gt;

This slice of life manga about a burnt out individual and his cousin living a simple life. It&amp;rsquo;s got a kind of summer cozy relaxing feel to the story.&lt;/p&gt;
&lt;h3 id=&#34;tokyo-alien-bros-manga&#34;&gt;
  Tokyo Alien Bros (Manga)
  &lt;a href=&#34;#tokyo-alien-bros-manga&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/tokyo_alien_bros.jpg&#34;  alt=&#34;Tokyo Alien Bros (Manga)&#34;  /&gt;

This was a lovely combination of weird + slice of life. Super short 3 volume series, totally worth a read.&lt;/p&gt;
&lt;h3 id=&#34;sex-criminals-comic&#34;&gt;
  Sex Criminals (Comic)
  &lt;a href=&#34;#sex-criminals-comic&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/sex_criminals.jpg&#34;  alt=&#34;Sex Criminals (Comic)&#34;  /&gt;

Obviously this comic deals with adult themes, but in terms of a premise it was interesting. While the adults are there to drive a plot, what I really enjoyed was the two main characters and how they grew throughout the series.&lt;/p&gt;
&lt;h3 id=&#34;silo-series-novel&#34;&gt;
  Silo Series (Novel)
  &lt;a href=&#34;#silo-series-novel&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/silo_series.jpg&#34;  alt=&#34;Silo Series (Novel)&#34;  /&gt;

The second season of Silo was so good when I found out it was based on a set of books (Wool / Shift / Dust), I knew I had to read them to get my fix. The first and second books are definitely my favorites in the series, the third book that wraps everything up is good, but definitely my least favorite of the 3.&lt;/p&gt;
&lt;h2 id=&#34;favorite-anime-i-watched&#34;&gt;
  Favorite Anime I watched
  &lt;a href=&#34;#favorite-anime-i-watched&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;tojima-wants-to-be-a-kamen-rider&#34;&gt;
  Tojima Wants to Be a Kamen Rider
  &lt;a href=&#34;#tojima-wants-to-be-a-kamen-rider&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/tojima.jpg&#34;  alt=&#34;Tojima Wants to Be a Kamen Rider&#34;  /&gt;

This is hands down my favorite Anime of this year. It&amp;rsquo;s extremely meta crafting a story in a fictional world that grew up with the Kamen Rider franchise, so you have these fanatic who&amp;rsquo;s main thing is that they aspire to be like their idol Kamen Riders. All while finding out that their world actually has the alien enemies from the show. So now these adults who worshiped Kamen Rider can now live out their power fantasy of becoming a Kamen Rider and defeating evil. The music and power ups and fights goes so hard in this Anime. Also the fact that the main character is in his thirties is also a plus, it&amp;rsquo;s kinda refreshing to watch anime of age appropriate people to yourself.&lt;/p&gt;
&lt;h3 id=&#34;yowamushi-pedal&#34;&gt;
  Yowamushi Pedal
  &lt;a href=&#34;#yowamushi-pedal&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/yowamushi_pedal.jpg&#34;  alt=&#34;Yowamushi Pedal&#34;  /&gt;

I re-watch this anime from time to time and this year, its just one of those wholesome sports anime that makes you want to get out there and do something.&lt;/p&gt;
&lt;h3 id=&#34;my-hero-academia-series-finale&#34;&gt;
  My Hero Academia (Series Finale)
  &lt;a href=&#34;#my-hero-academia-series-finale&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/my_hero.jpg&#34;  alt=&#34;My Hero Academia (Series Finale)&#34;  /&gt;

The manga finished publication last year so the anime was finally wrapping up this year. Seeing the action scenes animated from the manga was something amazing. My Hero gets kinda a bad wrap because of the fanbase or because it&amp;rsquo;s a typical Shonen, but it hits all the notes for me.&lt;/p&gt;
&lt;h2 id=&#34;favorite-items-i-own&#34;&gt;
  Favorite Items I own
  &lt;a href=&#34;#favorite-items-i-own&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;pixel-fold&#34;&gt;
  Pixel Fold
  &lt;a href=&#34;#pixel-fold&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/pixel_fold.jpg&#34;  alt=&#34;Pixel Fold&#34;  /&gt;

This year I had an international trip and so digital privacy was top of mind for me leaving the country AND re-entrying the country. I decided to buy a separate phone for travel and wanted to try out these foldables. However, no way was I ever gonna pay retail price for these things, it&amp;rsquo;s just way too pricey, but a used one on ebay, definitely worth a chance. The OG Pixel Fold is a fantastic device, while I did mostly used it like a regular slab phone, it was nice opening it up to read comics, browse websites or watching youtube. It&amp;rsquo;s really made me consider getting a Pixel 10 Fold as a daily driver.&lt;/p&gt;
&lt;h3 id=&#34;single-speed-bike-build&#34;&gt;
  Single Speed Bike (Build)
  &lt;a href=&#34;#single-speed-bike-build&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/single_speed_bike.jpg&#34;  alt=&#34;Single Speed Bike (Build)&#34;  /&gt;

After Watching Yowamushi Pedal, I got the itch to start riding a bike again this year. I had a old road bike from college that was long in the tooth, so I go the bright idea to build a bike this year. There is just something incredible about building something and using it, the level of satisfactions you get is indescribable. So much so that I have another bike build planed for 2026.&lt;/p&gt;
&lt;h3 id=&#34;ikea-donut-lamp&#34;&gt;
  Ikea Donut Lamp
  &lt;a href=&#34;#ikea-donut-lamp&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/12/24/favorite-thangs-in-2025/images/ikea_donut.jpg&#34;  alt=&#34;Ikea Donut Light&#34;  /&gt;

Orange is my favorite color and this thing is weird and whimsical for me. No notes, 10/10.&lt;/p&gt;
&lt;h2 id=&#34;favorite-youtube-channels-of-the-year&#34;&gt;
  Favorite Youtube Channels of the year
  &lt;a href=&#34;#favorite-youtube-channels-of-the-year&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve watched a lot of Youtube this year, but in terms of favorite channels, there weren&amp;rsquo;t too many that I was really excited to see that was new.&lt;/p&gt;
&lt;h3 id=&#34;cut-transform-gluehttpswwwyoutubecomcuttransformglue&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@CutTransformGlue&#34;&gt;Cut Transform Glue&lt;/a&gt;
  &lt;a href=&#34;#cut-transform-gluehttpswwwyoutubecomcuttransformglue&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve been on a maker kick this year, and I&amp;rsquo;ve really come to enjoy this particular channel for turning found items/parts into really amazing robots, vehicles, etc.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/voDVFEa_Dvw?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;awkward-virgo-tvhttpswwwyoutubecomawkwardvirgotv&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@AwkwardVirgoTV&#34;&gt;Awkward Virgo TV&lt;/a&gt;
  &lt;a href=&#34;#awkward-virgo-tvhttpswwwyoutubecomawkwardvirgotv&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;This channel created a web comedy series this year called The Comic Shop. It was such a fun nerdtastic comedy. Highly recommend checking it out.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/oMke8X0f7RM?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;caroline-winklerhttpswwwyoutubecomcaroline_winkler&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@Caroline_Winkler&#34;&gt;Caroline Winkler&lt;/a&gt;
  &lt;a href=&#34;#caroline-winklerhttpswwwyoutubecomcaroline_winkler&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Primarily she makes videos about home decor and this year has been a big journey for her and her betrothed partner as they&amp;rsquo;ve moved into a 1900 old victorian home and her journey to decorate it. It&amp;rsquo;s fun and interesting to watch and I&amp;rsquo;m getting design tips for a home I&amp;rsquo;ll probably never afford.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/nDAp3uydBe8?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;colleens-manga-recshttpswwwyoutubecomcolleensmangarecs&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@ColleensMangaRecs&#34;&gt;Colleen&amp;rsquo;s Manga Recs&lt;/a&gt;
  &lt;a href=&#34;#colleens-manga-recshttpswwwyoutubecomcolleensmangarecs&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Colleen makes videos essay about shoujo manga. While I am not the demographic for shoujo manga, it is interesting to learn about and a good way to broaden my horizon in terms of manga. Colleen&amp;rsquo;s love of Chihayafuru is what prompted me to read it last year.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/RSBM8DwY6Lc?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;rachel-maksyhttpswwwyoutubecomrachelmaksy&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@rachelmaksy&#34;&gt;Rachel Maksy&lt;/a&gt;
  &lt;a href=&#34;#rachel-maksyhttpswwwyoutubecomrachelmaksy&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;She&amp;rsquo;s a maker of all things whimsy. I&amp;rsquo;ve really enjoyed watching her make interesting costumes, cosplay, props and even sets. It&amp;rsquo;s really pulls at the nerdy fun heart strings.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/Ad0IZUNszYc?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h2 id=&#34;close-out&#34;&gt;
  Close out
  &lt;a href=&#34;#close-out&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I did not do as much blogging as I would have liked this year, but here&amp;rsquo;s hoping that I&amp;rsquo;ll be it a new resolution that I can actually stick to&amp;hellip; No promises however. While this year has been an absolute nightmare in the US, to the point I don&amp;rsquo;t think we can really even recover, let&amp;rsquo;s not end it on a complete failure of a note.&lt;/p&gt;
&lt;p&gt;Be kind to your neighbors, be kind to yourself, happy holidays and hope in 2026 we can slowly rebuild.&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Setting up a Fresh Worktop</title>
      <link>https://huynguyen.me/blog/2025/09/19/setting-up-a-fresh-worktop/</link>
      <pubDate>Fri, 19 Sep 2025 18:47:45 -0500</pubDate>
      
      <guid>https://huynguyen.me/blog/2025/09/19/setting-up-a-fresh-worktop/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Unlike most people who seem to work in Tech and have Tech blogs and/or a presence online, I work specifically in a Technical Support Role, so I don&amp;rsquo;t need a lot of fancy things to write code or do my job specifically. But I do have specific workflows and apps that I use on a frequent basis to help me communicate to customers, replicate issues, review configuration and logs as well as knowledge management. Over the years the stuff I&amp;rsquo;ve added and configured has sort of gotten away from me so I&amp;rsquo;ve been delaying a work machine replacement for a long time now. But enough is enough and it&amp;rsquo;s time to get things in order so that I can get going from 0.&lt;/p&gt;
&lt;h2 id=&#34;essential-apps&#34;&gt;
  Essential Apps
  &lt;a href=&#34;#essential-apps&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.raycast.com/&#34;&gt;Raycast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sublimetext.com/&#34;&gt;SublimeText&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://obsidian.md/&#34;&gt;Obsidian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://alacritty.org/&#34;&gt;Alacritty&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s been a few years since I had to sort of start fresh, so I wanted to see if there&amp;rsquo;s new apps to swap out for and turns out there was. At work I use a Mac and at home I use Linux, so I&amp;rsquo;ve tried to mirror as much of my essential apps as I can, but there are just a few apps that are specific to Mac that I need.&lt;/p&gt;
&lt;p&gt;I was using Alfred as my App Launcher, Spectacle pretty heavily for window movement and using the default MacOS Workspaces for virtual desktops as I primarily only worked off the single screen on the laptop. I know, I know, that&amp;rsquo;s probably weird as most people are gonna have at least a 2 monitor setup for work. It helps me to keep things compartmentalize and makes it easier for me to work from the desk, couch or coffee shop if I want to move around.&lt;/p&gt;
&lt;p&gt;While I&amp;rsquo;m still using Workspaces as my main virtual desktop, I&amp;rsquo;ve moved away from Spectacle and started using Raycast. Raycast is like a Applauncher on crack, it also has Window Management and an awesome plug-able extensions store. There&amp;rsquo;s also a text expander feature that I&amp;rsquo;m using for stuff that I type over and over everyday, like greetings, signatures, etc. Raycast is now replacing 2 apps for me and opening a door to new possibilities, I can&amp;rsquo;t wait to check out what else is in the extensions store.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been using SublimeText now for reviewing configuration files, small log files and typing scratch notes as I investigate application issues. My favorite feature is the little mini map as I&amp;rsquo;m a visual person and being able to see the shape of a log file really helps to take notice of things that you can easily miss if you&amp;rsquo;re only grepping for ERRORs. It also has a pretty sweet plugin system as well, which was extremely useful before I swapped to Obsidian for Knowledge Management.&lt;/p&gt;
&lt;p&gt;Of course I&amp;rsquo;ve been using Obsidian for quite a while now as it&amp;rsquo;s been the ultimate tool for Knowledge Management, Meeting Notes, Investigation notes, etc. Using Templater has really opened up automating a lot of my workflows here and I can&amp;rsquo;t imagine going back to simple text editors.&lt;/p&gt;
&lt;p&gt;In terms of the Terminal Emulator, I&amp;rsquo;m still using a Single Alacritty Window with Tmux for multi-terminal spaces and sessions. Sometimes I have to try and replicate a customer issue or bug and Tmux makes it easy to move around.&lt;/p&gt;
&lt;h2 id=&#34;dotfiles&#34;&gt;
  Dotfiles
  &lt;a href=&#34;#dotfiles&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;For the most part my dotfiles are nearly identical to my personal &lt;a href=&#34;https://github.com/sinicide/.dotfiles&#34;&gt;dotfiles&lt;/a&gt; except for a private sub repo that I&amp;rsquo;m using to include work specific configurations that differ from my personal ones. There&amp;rsquo;s also a mac specific initialization script for homebrew apps that I need installed.&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Email Challenges</title>
      <link>https://huynguyen.me/blog/2025/03/04/email-challenges/</link>
      <pubDate>Tue, 04 Mar 2025 14:13:15 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2025/03/04/email-challenges/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;So recently I decided to tackle learning a bit about Email as I needed to troubleshoot why emails from my custom domain were failing to send and why I was getting phishing emails routed through by my custom domain. I&amp;rsquo;ll admit, I have very little knowledge in the area of Emails. I originally had a setup for years that kinda just worked without issue, this was when G Suite was free. But now I really needed to tackle this.&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;
  The Problem
  &lt;a href=&#34;#the-problem&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/03/04/email-challenges/images/phishing_email.jpg&#34;  alt=&#34;Phishing Email&#34;  /&gt;

I started noticing emails arriving in my inbox that tried to look weirdly legitimate. For example the above email which I manually flagged for spam was mailed by my custom domain.&lt;/p&gt;
&lt;p&gt;How do I know the email was a phishing attempt? For 1, my name&amp;rsquo;s not Joel. 2, If you check things like the phone number to customer service there, it shows up as a suspicious Paypal scammer number.&lt;/p&gt;
&lt;p&gt;I later found out that emails I was sending was getting flag for spam as well. So I needed to fix my setup and do some research.&lt;/p&gt;
&lt;h2 id=&#34;the-setup&#34;&gt;
  The Setup
  &lt;a href=&#34;#the-setup&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;So how this works is that my custom domain which is hosted by Cloudflare, is configured to forward emails from my custom domain to a gmail account. That works without issue, because Cloudflare has you verify the destination email address before it&amp;rsquo;ll send it there. This covered receiving email for my custom domain, which is really what I need it for.&lt;/p&gt;
&lt;p&gt;Now sending email as my custom domain is not something I do frequently, but I do have a need to be able to legitimately do so. I had originally configured Gmail to send mail as this custom domain, via the &lt;code&gt;Send mail as&lt;/code&gt; configuration under the &lt;code&gt;Accounts and Import&lt;/code&gt; settings within Gmail. Originally I was using Gmail&amp;rsquo;s smtp servers to send mail. Unfortunately when inspecting email sent by my custom domain, it was failing DKIM and DMARC.&lt;/p&gt;
&lt;h2 id=&#34;terminology&#34;&gt;
  Terminology
  &lt;a href=&#34;#terminology&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Alright let&amp;rsquo;s go over some terminology so before going any further.&lt;/p&gt;
&lt;p&gt;SPF - Sender Policy Framework
DKIM - Domain Keys Identified Mail
DMARC - Domain Based Message Authentication Reporting and Conformance&lt;/p&gt;
&lt;h3 id=&#34;spf&#34;&gt;
  SPF
  &lt;a href=&#34;#spf&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Sender Policy Framework is a way to list or identify the approved domains/IPs which can send emails from. This is configured as a &lt;code&gt;TXT&lt;/code&gt; DNS Record for your custom domain. So this allows mail servers to verify if the email should come from an expected IP(s). This is simple enough to setup through Cloudflare and I&amp;rsquo;ve included both Cloudflare&amp;rsquo;s spf records as well as Gmail&amp;rsquo;s spf records.&lt;/p&gt;
&lt;p&gt;Below is what you typically see mentioned online.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;v=spf1 include:_spf.mx.cloudflare.net include:_spf.google.com ~all
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;dkim&#34;&gt;
  DKIM
  &lt;a href=&#34;#dkim&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Domain Keys Identified Mail, is a way to use Public Key Cryptography to verify that the email is actually sent from an approved sender. So when email is sent, it&amp;rsquo;ll contain a header that signs the email using a Private Key, then mail servers receiving the email can look up the public key via another DNS record to validate that the mail is legitimate. The problem here with my setup is that the way that I had configured &lt;code&gt;Send mail as&lt;/code&gt; in Gmail doesn&amp;rsquo;t actually sign my emails with DKIM because the free Gmail Account doesn&amp;rsquo;t offer this with &lt;code&gt;smtp.gmail.com&lt;/code&gt; I believe this worked fine when I had a free G Suite account.&lt;/p&gt;
&lt;p&gt;This is configured as a &lt;code&gt;TXT&lt;/code&gt; DNS Record who&amp;rsquo;s key is typically &lt;code&gt;xxxx._domainkey&lt;/code&gt; or something like that. Now you unfortunately cannot just add some random thing here, because you need an actual mail server to hold the Private Key, so that you can specify the Public key in this DNS record.&lt;/p&gt;
&lt;h3 id=&#34;dmarc&#34;&gt;
  DMARC
  &lt;a href=&#34;#dmarc&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Domain Based Message Authentication Reporting and Conformance, this is basically a rule/policy/instruction for mail servers on how to handle email received by your domain. This is configured as a &lt;code&gt;TXT&lt;/code&gt; DNS record with the key &lt;code&gt;_dmarc&lt;/code&gt;, which the mail servers can lookup.&lt;/p&gt;
&lt;p&gt;For example the contents of a &lt;code&gt;_dmarc&lt;/code&gt; record might look like&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;v=DMARC1; p=quarantine; sp=quarantine; rua=mailto:xxxx@example.com; ruf=mailto:xxxx@example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;v&lt;/code&gt; specifies the version, the &lt;code&gt;p&lt;/code&gt; specifies the policy, which accepts, &lt;code&gt;reject&lt;/code&gt; which will reject the email, &lt;code&gt;quarantine&lt;/code&gt; which will accept it but send it to Spam, and finally &lt;code&gt;none&lt;/code&gt; which will take no action.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;sp&lt;/code&gt; is the sub domain policy, which follows the same options. There&amp;rsquo;s also an additional default configuration here &lt;code&gt;pct&lt;/code&gt; which defaults to a value of &lt;code&gt;100&lt;/code&gt; the &lt;code&gt;pct&lt;/code&gt; configuration marks the percentage of failed DMARC email to apply the policy to. 100 being all email vs say 75 would mean 75 percent of failed DMARC emails would have the policy specified applied, so if you set the policy to be rejected, then 75 percentage of failed DMARC email would be rejected.&lt;/p&gt;
&lt;p&gt;The email addresses here are used for configuring DMARC reports, the &lt;code&gt;rua&lt;/code&gt; which indicates Aggregate reports and the &lt;code&gt;ruf&lt;/code&gt; which indicates Forensic reports. These get periodically sent to those &lt;code&gt;mailto:xxx@example.com&lt;/code&gt; addresses. This can be helpful for periodic review, but we&amp;rsquo;ll see if it&amp;rsquo;s extremely useful or another alert to ignore.&lt;/p&gt;
&lt;p&gt;Originally I had my policy set to &lt;code&gt;p=none&lt;/code&gt; but unfortunately that was not a solution for passing DMARC with Gmail.&lt;/p&gt;
&lt;p&gt;If you want to learn more? Check out Cloudflare&amp;rsquo;s excellent article on it &lt;a href=&#34;https://www.cloudflare.com/learning/email-security/dmarc-dkim-spf/&#34;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;tools-are-cool&#34;&gt;
  Tools are Cool
  &lt;a href=&#34;#tools-are-cool&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/03/04/email-challenges/images/learndmarc.jpg&#34;  alt=&#34;learndmarc.com&#34;  /&gt;

In my research, I stumbled across a pretty cool website tool called &lt;a href=&#34;https://learndmarc.com/&#34;&gt;www.learndmarc.com&lt;/a&gt; This was an interactive way to understand how SPF, DKIM, and DMARC were passing or failing. This was nicer than just looking at the email headers and trying to make sense of the gibberish.&lt;/p&gt;
&lt;p&gt;To get started you&amp;rsquo;d send an email to the email address that the tool tells you to. Once it receives your email, it&amp;rsquo;ll go through how it identifies it&amp;rsquo;s legitimacy and even breaks down the DMARC policy you may have configured.&lt;/p&gt;
&lt;p&gt;In my testing SPF was succeeding because it was being sent out by Google&amp;rsquo;s smtp server, but DKIM was failing, which ultimately resulted in DMARC failing. DKIM failed because the sender domain differ from the custom domain. This is due to me sending emails through Gmail&amp;rsquo;s smtp server, because it doesn&amp;rsquo;t sign the email with a Private Key for DKIM.&lt;/p&gt;
&lt;h2 id=&#34;the-solution&#34;&gt;
  The Solution
  &lt;a href=&#34;#the-solution&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;So clearly my main issue here is that while SPF can succeed, DKIM wasn&amp;rsquo;t configured and my DMARC configuration would essentially fail if the policy I configured told it to quarantine email (e.g. send to spam).
So it was pretty clear from the report that I needed to configure DKIM and that out of the box Free gmail didn&amp;rsquo;t offer this so I couldn&amp;rsquo;t configure my DNS records for DKIM. I could only configure SPF and DMARC policies.&lt;/p&gt;
&lt;p&gt;What I needed was a SMTP server that I could send mail through that would sign it with a Private Key. For my use case I don&amp;rsquo;t really need to send a ton of emails, nor do I need a bunch of email addresses, so I don&amp;rsquo;t want to pay $7 USD a month for the lowest tier offering with Google Workspace.&lt;/p&gt;
&lt;p&gt;What I ended up finding for a solution was &lt;a href=&#34;https://smtp2go.com/&#34;&gt;SMTP2GO&lt;/a&gt; which provided a Free Plan (without credit card) that would allow up to 1000 emails sent a month and up to 200 emails a day. This was perfect for my low use case needs, cause who doesn&amp;rsquo;t love free-ninty-free?&lt;/p&gt;

  &lt;img src=&#34;https://r2.huynguyen.me/blog/2025/03/04/email-challenges/images/smtp2go.jpg&#34;  alt=&#34;SMTP2GO&#34;  /&gt;

&lt;p&gt;Setup was extremely easy, they provided me with all the DNS record configuration that I needed to make on Cloudflare, the only trouble I ran into was that I initially created the DNS records with the proxy status enabled, which did not correctly resolve the specific smtp2go endpoints. Once that was fixed, the verification process succeeded.&lt;/p&gt;
&lt;p&gt;I then created my accounts for their smtp server. Went back into gmail and configured my &lt;code&gt;Send mail as&lt;/code&gt; with the new smtp server from smtp2go&amp;rsquo;s documentation. Finally I was ready to re-test with &lt;a href=&#34;https://learndmarc.com&#34;&gt;learndmarc.com&lt;/a&gt; which now passed DKIM and ultimately passed DMARC, policy. I can now actually configure the DMARC policy to correctly quarantine or reject failed mail.&lt;/p&gt;
&lt;p&gt;Not bad for a few hours worth of research, this has certainly been a long time coming and I&amp;rsquo;m glad I was able to learn something new and fix a problem. Hopefully you&amp;rsquo;ve learned something new as well.&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Ebay Access Denied Issue</title>
      <link>https://huynguyen.me/blog/2025/02/05/ebay-access-denied-issue/</link>
      <pubDate>Wed, 05 Feb 2025 22:23:29 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2025/02/05/ebay-access-denied-issue/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;For the longest time, I would encounter a strange &amp;ldquo;Access Denied&amp;rdquo; message sometimes when browsing Ebay. Which ends up locking me from using the site for a small period of time, sometimes even using a new browser wouldn&amp;rsquo;t work either.&lt;/p&gt;
&lt;h2 id=&#34;access-denied&#34;&gt;
  Access Denied
  &lt;a href=&#34;#access-denied&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;You don&amp;#39;t have permission to access &amp;#34;http://www.ebay.com/sch/i.html?&amp;#34; on this server.

Reference #18.1c043517.1738815757.f4abf3b1

https://errors.edgesuite.net/18.1c043517.1738815757.f4abf3b1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Eventually I&amp;rsquo;d get fed up and try searching the internet for an answer only to never find anything from the usual places, Duckduckgo, Google, even Reddit.&lt;/p&gt;
&lt;p&gt;That is until tonight when I decided to try my luck again. Low and behold I found this incredible Reddit &lt;a href=&#34;https://www.reddit.com/r/Ebay/comments/1bnfhue/access_denied_when_accessing_website/&#34;&gt;thread&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Apparently this whole time the issue was due to a browser plugin that I use often, which is &lt;a href=&#34;https://github.com/extesy/hoverzoom/&#34;&gt;HoverZoom+&lt;/a&gt; I&amp;rsquo;ve been using this handy plugin for years to load images so that I didn&amp;rsquo;t have to click into a image link or post, but never knew it was the cause of the issue. I had always thought it might have been an ad blocker extension or something related to my pfBlockerNG settings in my Router.&lt;/p&gt;
&lt;p&gt;Looking at the HoverZoom+ &lt;a href=&#34;https://github.com/extesy/hoverzoom/issues/1355&#34;&gt;Github Issues&lt;/a&gt;, it indeed looks like someone reported it as an issue as of last year without resolution.&lt;/p&gt;
&lt;p&gt;So for now I&amp;rsquo;m happy enough to just disable the Browser extension when browsing Ebay and making this blog post to hopefully help someone else out there that might be running into this issue.&lt;/p&gt;
&lt;p&gt;Case Closed.&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Hello 2025!</title>
      <link>https://huynguyen.me/blog/2025/01/01/hello-2025/</link>
      <pubDate>Wed, 01 Jan 2025 11:46:15 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2025/01/01/hello-2025/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Starting off 2025 with a small but major update to this blog. I&amp;rsquo;ve spent the past few days working on some needed maintenance for the theme and how this blog is deployed and figured I&amp;rsquo;d capture this information in the first blog post of the year.&lt;/p&gt;
&lt;h2 id=&#34;updating-blog-post-creation-workflow&#34;&gt;
  Updating Blog Post Creation workflow
  &lt;a href=&#34;#updating-blog-post-creation-workflow&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;How I have this blog structured is that I utilized 3 separate Github repositories to ultimately build the blog with &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sinicide/huynguyen-blog-build&#34;&gt;Main Build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sinicide/hugo-theme-hello-bulma&#34;&gt;Theme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sinicide/huynguyen-blog-content&#34;&gt;Content&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This allows for flexibility if I one day decided I wanted to move to a different Static Site Generator or if I want change up the theme without specifically affecting the other repos. Obviously I could keep everything in a single repo, but I really want to utilize git&amp;rsquo;s changelog to track markdown publicly.&lt;/p&gt;
&lt;p&gt;Hugo can generate blog posts via the following command.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;hugo new content &amp;lt;content_location&amp;gt;/blog_post.md
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will generate a markdown file using pre-determined frontmatter at the location specified by the path. While this is nice, it requires me to run Hugo to do this and it also requires me to manually update the &lt;code&gt;lastMod&lt;/code&gt; frontmatter whenever I make edits. I include this particular frontmatter because I value being transparent when it comes to information edits. This allows readers of my blog, who are observant to then check out the changelog link at the very bottom of this post to see what has been changed and when. This way I can utilize git&amp;rsquo;s changelog as opposed to keeping track elsewhere. Why is this even important? Well I believe public information can change over time and everyone deserves to understand those changes to better stay informed and formulate their own opinions on that information.&lt;/p&gt;
&lt;p&gt;Instead of using Hugo to generate new blog posts, I&amp;rsquo;ve opted to use an &lt;a href=&#34;https://obsidian.md/&#34;&gt;Obsidian&lt;/a&gt; vault to really power up my blog post creation flow.&lt;/p&gt;
&lt;h2 id=&#34;why-use-obsidian&#34;&gt;
  Why use Obsidian?
  &lt;a href=&#34;#why-use-obsidian&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been using Obsidian for note taking in my private and professional life. At it&amp;rsquo;s base level, it&amp;rsquo;s just a super neat markdown note taking app, but with a few community plugins it allows me to automate blog post generation as well as &lt;code&gt;lastMod&lt;/code&gt; frontmatter update on changes.&lt;/p&gt;
&lt;p&gt;In particular I&amp;rsquo;m using the following 2 Community Plugins&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/SilentVoid13/Templater&#34;&gt;Templater&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/beaussan/update-time-on-edit-obsidian&#34;&gt;Update time on edit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This gives a fairly nice gui experience as I can accomplish a lot of different workflows via the Command Palette. This allows me to automate including specific Hugo shortcodes from a templates folder and/or create a blog post based on a skeleton markdown file.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s neat is that the Obsidian configuration itself now lives in this content repo as a dot folder, which is handy because Hugo will ignore this directory in content. However the templates that I use are in a regular folder, which means I also needed to update the Main Build repo to ignore it as non-content otherwise it&amp;rsquo;ll break when trying to compile the site.&lt;/p&gt;
&lt;p&gt;This required a new inclusion of content &lt;a href=&#34;https://gohugo.io/hugo-modules/configuration/#module-configuration-mounts&#34;&gt;module&lt;/a&gt; in Hugo&amp;rsquo;s configuration yaml to exclude it from being processed. What&amp;rsquo;s cool about this is that I could also specify different content directories within the same repo for different environment builds if I wanted. But for now, I only need it as a way to exclude a specific directory.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;module&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;mounts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;source&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;target&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;excludeFiles&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;templates/**&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This was all done and completed with the last &lt;a href=&#34;https://huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/&#34; title=&#34;Favorite Thangs in 2024&#34;&gt;post&lt;/a&gt; I made.&lt;/p&gt;
&lt;h2 id=&#34;updating-the-theme&#34;&gt;
  Updating the Theme
  &lt;a href=&#34;#updating-the-theme&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Now let&amp;rsquo;s talk about what I updated for the theme. In case you&amp;rsquo;re not aware, my theme is based on a no longer maintained public theme called &lt;a href=&#34;https://github.com/panr/hugo-theme-hello-friend&#34;&gt;Hello Friend&lt;/a&gt; which I&amp;rsquo;ve refactored with the &lt;a href=&#34;https://bulma.io/&#34;&gt;Bulma&lt;/a&gt; Framework into what I&amp;rsquo;ve cutely named &lt;a href=&#34;https://github.com/sinicide/hugo-theme-hello-bulma&#34;&gt;Hello Bulma&lt;/a&gt;. Dragon Ball Z was a big part of my childhood, so I have a soft spot for this CSS framework.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Updated Font Awesome Free 6 to &lt;code&gt;6.7.2&lt;/code&gt;, prior version used was &lt;code&gt;6.4.2&lt;/code&gt; (so not a major jump)&lt;/li&gt;
&lt;li&gt;Updated Bulma CSS Framework to v1&lt;/li&gt;
&lt;li&gt;Update local Hugo Container to use version &lt;code&gt;0.140.1&lt;/code&gt; in Main Build repo&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;updating-the-dockerfile&#34;&gt;
  Updating the Dockerfile
  &lt;a href=&#34;#updating-the-dockerfile&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;In the main repo, I have a local Dockerfile, which I use to build a local Hugo container to stand up my website for local testing. This allows me to not have to install Hugo locally, because I run Archlinux (by the way), which means that I&amp;rsquo;m at the mercy of a Rolling Release structure for packages. So if I install Hugo locally via pacman, it&amp;rsquo;ll be updated whenever there&amp;rsquo;s a new update. That&amp;rsquo;s not what I want for anything I push to production, anything that is going to be considered &amp;ldquo;production&amp;rdquo; needs to be deterministic and remain on consistent versions.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s go over some of the major changes to my Dockerfile&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENV&lt;/span&gt; HUGO_VERSION 0.140.1&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;...&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENV&lt;/span&gt; DART_SASS_VERSION 1.83.0&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENV&lt;/span&gt; DART_SASS_FILENAME dart-sass-&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;DART_SASS_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;-linux-x64.tar.gz&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENV&lt;/span&gt; DART_SASS_URL https://github.com/sass/dart-sass/releases/download/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;DART_SASS_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;/&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;DART_SASS_FILENAME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# download Dart Sass&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; cd /tmp &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;curl -O -L &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;DART_SASS_URL&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;tar -xf &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;DART_SASS_FILENAME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;cp -r /tmp/dart-sass/* /usr/local/bin &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;rm -rf /tmp/dart-sass*&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;First and foremost is setting the &lt;code&gt;HUGO_VERSION&lt;/code&gt; to a newer version&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;ve also included Dart Sass installation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The inclusion of Dart Sass is necessary here because by default Hugo uses LibSass to transpile Sass to CSS and LibSass is deprecated by the Sass team in favor of Dart Sass as of 2020. Unfortunately the extended Hugo release packages doesn&amp;rsquo;t contain this so I&amp;rsquo;m forced to manually install this for local development. Luckily for Cloudflare Pages (where this blog is hosted), I don&amp;rsquo;t have to worry about this as Dart Sass is pre-installed in the Cloudflare Workers when generating the static files for Hugo.&lt;/p&gt;
&lt;p&gt;So for the most part I just copy-pasted what was in &lt;a href=&#34;https://gohugo.io/hugo-pipes/transpile-sass-to-css/#dart-sass&#34;&gt;Hugo&amp;rsquo;s Documentation&lt;/a&gt; opting for Dart Sass version &lt;code&gt;1.83.0&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The use of Dart Sass is also crucial here because Bulma V1 is built with it according to their &lt;a href=&#34;https://bulma.io/documentation/start/migrating-to-v1/#what-changes&#34;&gt;Migration documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;migrating-to-bulma-v1&#34;&gt;
  Migrating to Bulma v1
  &lt;a href=&#34;#migrating-to-bulma-v1&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;As with any major software changes, it&amp;rsquo;s always good to read any official documentation to account for any breaking changes. Luckily Bulma provides us 2 major recommendations/changes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Tiles&lt;/code&gt; are deprecated in favor of &lt;code&gt;Smart Grid&lt;/code&gt; (I don&amp;rsquo;t use either so this is irrelevant to me)&lt;/li&gt;
&lt;li&gt;Use of &lt;code&gt;@import&lt;/code&gt; is not recommended&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now I&amp;rsquo;ve been using &lt;code&gt;@import&lt;/code&gt; to import specific components from the Bulma sass directory to build the CSS as I have my own modifications and additions. So this means I need to migrate from &lt;code&gt;@import&lt;/code&gt; to &lt;code&gt;@forward&lt;/code&gt; or &lt;code&gt;@use&lt;/code&gt; in the main file that my Theme points to for css compiling.&lt;/p&gt;
&lt;p&gt;Unfortunately Font Awesome 6 still uses &lt;code&gt;@import&lt;/code&gt; in it&amp;rsquo;s scss files, so I&amp;rsquo;ll be keeping this around until it&amp;rsquo;s change.&lt;/p&gt;
&lt;p&gt;But now my &lt;code&gt;bulma.scss&lt;/code&gt; file looks like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-scss&#34; data-lang=&#34;scss&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// bulma.io v1.0.3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@use&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;../bulma/sass/&amp;lt;component&amp;gt;&amp;#34;&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;//my overrides&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;forward&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;../bulma/sass/&amp;lt;component&amp;gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;//&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;CUSTOM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;forward&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;./&amp;lt;components&amp;gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;//&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;Font&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;Awesome&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;.7.2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;../fontawesome/&amp;lt;filename&amp;gt;.scss&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Apparently the ordering of &lt;code&gt;@use&lt;/code&gt; , &lt;code&gt;@forward&lt;/code&gt; , and &lt;code&gt;@import&lt;/code&gt; here is important. I ran into some errors when compiling the CSS, so learned a lesson on that ordering. Had to spend a bit of time reading through the &lt;a href=&#34;https://sass-lang.com/documentation/at-rules/forward/&#34;&gt;Sass documentation&lt;/a&gt; on the usage of &lt;code&gt;@forward&lt;/code&gt; and doing a bit of back and forth testing to ensure everything compiled and rendered like before.&lt;/p&gt;
&lt;p&gt;Finally one more thing to note is how do we tell Hugo to use Dart Sass to compile these Sass files.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- Theme CSS --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ $opts := dict &amp;#34;transpiler&amp;#34; &amp;#34;dartsass&amp;#34; }} {{ $style := resources.Get
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;#34;scss/custom/bulma.scss&amp;#34; | toCSS $opts | minify | fingerprint }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;link&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;rel&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ $style.RelPermalink }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;integrity&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ $style.Data.Integrity }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;crossorigin&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This follows &lt;a href=&#34;https://gohugo.io/hugo-pipes/transpile-sass-to-css/#usage&#34;&gt;Hugo&lt;/a&gt;&amp;rsquo;s Guidance on the use of &lt;code&gt;toCSS&lt;/code&gt; with optional flags, unless specified it&amp;rsquo;ll default to use LibSass.&lt;/p&gt;
&lt;h2 id=&#34;pushing-to-production&#34;&gt;
  Pushing to Production
  &lt;a href=&#34;#pushing-to-production&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;With the theme update it was time to create a Pull Request to push the changes to master branch, which in turned triggered a commit on the Main Build repo with the new theme changes and is watched by Cloudflare for any changes to my Main Build repo to trigger a new deployment.&lt;/p&gt;
&lt;p&gt;So as you can see pretty much everything is intact. One minor change I did decide to do was change the strong text colors for headers and links to a white-ish color instead of the previous dark grey-ish ones, which should help with readability I suppose.&lt;/p&gt;
&lt;p&gt;Anyhow, Happy New Years! Here&amp;rsquo;s to accomplishing more things in 2025!&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Favorite thangs in 2024</title>
      <link>https://huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/</link>
      <pubDate>Thu, 26 Dec 2024 11:44:58 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/</guid>
      <description>
        
          
          
          
        
        
        &lt;h2 id=&#34;intro&#34;&gt;
  Intro
  &lt;a href=&#34;#intro&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;People often do a favorite things to sum up the year, this year marks the first year this blog went live. So to commemorate this occasion, I&amp;rsquo;ve decided to also do a favorite things in 2024. This is not specifically technology related, but something more personal and fun.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s kick of my first ever Favorite thangs in 2024!&lt;/p&gt;
&lt;h2 id=&#34;favorite-movies-i-watched&#34;&gt;
  Favorite Movies I watched
  &lt;a href=&#34;#favorite-movies-i-watched&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;the-iron-claw-2023&#34;&gt;
  The Iron Claw (2023)
  &lt;a href=&#34;#the-iron-claw-2023&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/the_iron_claw.jpg&#34;  alt=&#34;The Iron Claw (2023)&#34;  /&gt;

Last time I cared about wrestling was back in Highschool, I would normally pass up this type of genre, but when I found out what the subject matter was about, I knew I had to immediately watch it. What a beautifully tragic story.&lt;/p&gt;
&lt;h3 id=&#34;the-fall-guy-2024&#34;&gt;
  The Fall Guy (2024)
  &lt;a href=&#34;#the-fall-guy-2024&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/the_fall_guy.jpg&#34;  alt=&#34;The Fall Guy (2024)&#34;  /&gt;

This movie is just pure enjoyment and an amazing celebration of stunt people in the film industry. I think I&amp;rsquo;ve watched this many times since it&amp;rsquo;s released and it&amp;rsquo;s always such a fun watch.&lt;/p&gt;
&lt;h3 id=&#34;late-night-with-the-devil-2024&#34;&gt;
  Late Night with the Devil (2024)
  &lt;a href=&#34;#late-night-with-the-devil-2024&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/late_night_with.jpg&#34;  alt=&#34;Late Night with the Devil (2024)&#34;  /&gt;

I love the horror genre, so I&amp;rsquo;m always on the look out for new and interesting stories and settings. Late Night with the Devil paints an amazing portray of an era piece of late night talk show television with a demonic twist.&lt;/p&gt;
&lt;h3 id=&#34;longlegs-2024&#34;&gt;
  Longlegs (2024)
  &lt;a href=&#34;#longlegs-2024&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/longlegs.jpg&#34;  alt=&#34;Longlegs (2024)&#34;  /&gt;

Some of the magic of movies like Longlegs is that it blends the supernatural and reality together so well. It gives you patterns, clues to how the supernatural works, shows you the impossible and finally gives you a real world explanation for it. And still in the end it leaves a few crucial details out, just enough to make you doubt the facts.&lt;/p&gt;
&lt;h3 id=&#34;smile-2-2024&#34;&gt;
  Smile 2 (2024)
  &lt;a href=&#34;#smile-2-2024&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/smile_2.jpg&#34;  alt=&#34;Smile 2 (2024)&#34;  /&gt;

The sequel to Smile, and what a follow up this movie was. With sequels we already know the rules, so we need something more to hook us. Smiling has always felt terrifying to me and this movie really ramps up this horrific feeling to an 11, particularly with one scene in Skye&amp;rsquo;s apartment.&lt;/p&gt;
&lt;h3 id=&#34;exhibiting-forgiveness-2024&#34;&gt;
  Exhibiting Forgiveness (2024)
  &lt;a href=&#34;#exhibiting-forgiveness-2024&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/exhibiting_forgiveness.jpg&#34;  alt=&#34;The Exhibiting Forgiveness (2024)&#34;  /&gt;

I really enjoy movies where the character has broken free of their former life only to have to return one day to face unresolved trauma. I&amp;rsquo;ve been a fan of André Holland as an actor ever since I saw him Moolight and Castle Rock, so I wanted to check this out.&lt;/p&gt;
&lt;h3 id=&#34;your-monster-2024&#34;&gt;
  Your Monster (2024)
  &lt;a href=&#34;#your-monster-2024&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/your_monster.jpg&#34;  alt=&#34;Your Monster (2024)&#34;  /&gt;

This is just a silly premise where your imaginary monster from childhood turns out to be real as your life is falling apart. It&amp;rsquo;s a fun watch.&lt;/p&gt;
&lt;h2 id=&#34;favorite-shows-i-watched&#34;&gt;
  Favorite Shows I watched
  &lt;a href=&#34;#favorite-shows-i-watched&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;abbot-elementary&#34;&gt;
  Abbot Elementary
  &lt;a href=&#34;#abbot-elementary&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/abbot.jpg&#34;  alt=&#34;Abbot Elementary&#34;  /&gt;

I finally started watching Abbot Elementary and holy heck did I wish I would have watched this sooner! I absolutely love each of the teachers, they&amp;rsquo;re all so quirky and wholesome in the ways that I remember my teachers growing up.&lt;/p&gt;
&lt;h3 id=&#34;ted-lasso&#34;&gt;
  Ted Lasso
  &lt;a href=&#34;#ted-lasso&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/ted_lasso.jpg&#34;  alt=&#34;Ted Lasso&#34;  /&gt;

I also finally got around to watching all of Ted Lasso this year and I totally why this series was so beloved. It&amp;rsquo;s the kind of story that has an underdog team that you just want to root for, the characters are all great.&lt;/p&gt;
&lt;h3 id=&#34;the-bear-season-3&#34;&gt;
  The Bear (Season 3)
  &lt;a href=&#34;#the-bear-season-3&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/the_bear.jpg&#34;  alt=&#34;The Bear (Season 3)&#34;  /&gt;

It&amp;rsquo;s good, we all know this. But I just want to really share my favorite episode of this recent season, Napkins. I don&amp;rsquo;t know what it says about me, but I really empathize with characters who get shitted on in life, but put on a smile and persevere right up to their breaking point and beyond. Liza Colon-Zayas&amp;rsquo; performance in this episode was absolutely incredible. Fun fact her husband plays her husband in the show.&lt;/p&gt;
&lt;h3 id=&#34;x-men-97&#34;&gt;
  X-Men &amp;lsquo;97
  &lt;a href=&#34;#x-men-97&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/xmen_97.jpg&#34;  alt=&#34;X-Men &amp;#39;97&#34;  /&gt;

&amp;ldquo;The Name&amp;rsquo;s Gambit, Mon Ami&amp;hellip; Remember it.&amp;rdquo; This shit went so fucking hard and it exhibits everything I love about characters like Gambit. Of course the rest of the season was an amazing nostalgia trip as well and I highly recommend this series to anyone who grew up watching the X-Men cartoon.&lt;/p&gt;
&lt;h3 id=&#34;mr-and-mrs-smith&#34;&gt;
  Mr. and Mrs. Smith
  &lt;a href=&#34;#mr-and-mrs-smith&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/mr_and_mrs_smith.jpg&#34;  alt=&#34;Mr. and Mrs. Smith (Series)&#34;  /&gt;

I think what I really enjoyed most about this show was the chemistry between Donald and Maya&amp;rsquo;s character. They&amp;rsquo;re weird, there&amp;rsquo;s a bit of romance, there&amp;rsquo;s spycraft and it all blends together so well. I&amp;rsquo;m looking forward to what they do for a season 2.&lt;/p&gt;
&lt;h3 id=&#34;the-brothers-sun&#34;&gt;
  The Brothers Sun
  &lt;a href=&#34;#the-brothers-sun&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/the_brothers_sun.jpg&#34;  alt=&#34;The Brothers Sun&#34;  /&gt;

Being first generation from an immigrant family, this show hits a few of the notes from my childhood, I mean without all the mafia stuff. There&amp;rsquo;s not too many majority led asian cast television shows in the west and especially ones that tells stories with some level of seriousness. This show had it all, martial arts, comedy, familial expectations, striving to want something for yourself. I loved it and I wish it would get a follow up season.&lt;/p&gt;
&lt;h3 id=&#34;one-day&#34;&gt;
  One Day
  &lt;a href=&#34;#one-day&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/one_day.jpg&#34;  alt=&#34;One Day (Series)&#34;  /&gt;

I got sucked into the tiktok hype about this one. I saw all these reaction videos of people crying over this series that I had to give it a watch. I have to say as far as love stories go, I really enjoyed this one. It&amp;rsquo;s not the typical they fall in love and live happily ever after, no, years goes by as this love is developed and tested. It&amp;rsquo;s a good watch.&lt;/p&gt;
&lt;h3 id=&#34;the-queen-of-villains&#34;&gt;
  The Queen of Villains
  &lt;a href=&#34;#the-queen-of-villains&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/queen_of_villains.jpg&#34;  alt=&#34;The Queen of Villains&#34;  /&gt;

My second mention of a wrestling related media, which I also thoroughly enjoyed. It follows our lead, Dump Matsumoto, who is portrayed by Yuriyan Retriever and gives one heck of a performance, during the very real rising era of female japanese wrestling. I love non-stereotypical lead characters and you can&amp;rsquo;t help but want to root for her.&lt;/p&gt;
&lt;h3 id=&#34;dead-boy-detectives&#34;&gt;
  Dead Boy Detectives
  &lt;a href=&#34;#dead-boy-detectives&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/dead_boy_detectives.jpg&#34;  alt=&#34;Dead Boy Detectives&#34;  /&gt;

What I&amp;rsquo;ve come to appreciate about DC in the wake of the Marvel takeover is that they&amp;rsquo;re no stranger to take chances on characters and stories the typical super hero movie enjoyer may know about. This is like Hardy Boys meets the supernatural, or at least what I imagine the Hardy Boys were like (never read them growing up, too busy reading comics instead).&lt;/p&gt;
&lt;h3 id=&#34;a-virtuous-business&#34;&gt;
  A Virtuous Business
  &lt;a href=&#34;#a-virtuous-business&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/a_virtuous_business.jpg&#34;  alt=&#34;A Virtuous Business&#34;  /&gt;

I don&amp;rsquo;t often watch k-dramas, usually because I feel it&amp;rsquo;s all the same, just a bunch of extremely good looking people with some kind of romance problems. However this one has a really interesting premise in which an unlikely bunch of women start a risque women&amp;rsquo;s lingerie business. What I really enjoyed about this one is how different of a story it was from the typical ones. I really like the main cast of women and the stories that&amp;rsquo;s told from their perspectives.&lt;/p&gt;
&lt;h2 id=&#34;favorite-video-games-i-played&#34;&gt;
  Favorite Video Games I played
  &lt;a href=&#34;#favorite-video-games-i-played&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;lies-of-p&#34;&gt;
  Lies of P
  &lt;a href=&#34;#lies-of-p&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/lies_of_p.jpg&#34;  alt=&#34;Lies of P&#34;  /&gt;

It&amp;rsquo;s a soulsborne like game set in a fictitious gothic fairy tale like world. Combat took a while for me to get the hang of because the timing of the blocks/deflect was not what I was used to. But I love the artistic take on a classic fairy tale.&lt;/p&gt;
&lt;h3 id=&#34;black-myth-wukong&#34;&gt;
  Black Myth Wukong
  &lt;a href=&#34;#black-myth-wukong&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/wukong.jpg&#34;  alt=&#34;Black Myth Wukong&#34;  /&gt;

I was already familiar with the story of Wukong through an old cartoon from my childhood called Monkey Magic. But to experience more of the tales of Wukong and see just how weird it all was in the game styles of soulsborne mechanics was fantastic. I made sure to fight each and every boss possible. Highly recommend.&lt;/p&gt;
&lt;h3 id=&#34;helldivers-2&#34;&gt;
  Helldivers 2
  &lt;a href=&#34;#helldivers-2&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/helldivers_2.jpg&#34;  alt=&#34;Helldivers 2&#34;  /&gt;

I don&amp;rsquo;t much play multi-player games outside of Destiny 2. So when some old friends wanted to give it a go, I have to say I was delightfully surprised at how enjoyable the experience was. It may not be so much the game itself, but the combination of good company and fun mechanics is really want made the experience very enjoyable.&lt;/p&gt;
&lt;h2 id=&#34;favorite-comics-i-read&#34;&gt;
  Favorite Comics I read
  &lt;a href=&#34;#favorite-comics-i-read&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;die&#34;&gt;
  DIE
  &lt;a href=&#34;#die&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/die.jpg&#34;  alt=&#34;DIE&#34;  /&gt;

This is probably my favorite read of the year. Out of all the nerd stuff I&amp;rsquo;m into, Dungeons and Dragons has never been something I&amp;rsquo;ve personally been interested in. But man this comic&amp;rsquo;s story and artwork was so cool, I couldn&amp;rsquo;t pass up giving it a shot. I love the power fantasy for each of the character in the game world and how non-traditional hero like behaviors they had to grapple with.&lt;/p&gt;
&lt;h3 id=&#34;saga&#34;&gt;
  Saga
  &lt;a href=&#34;#saga&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/saga.jpg&#34;  alt=&#34;Saga&#34;  /&gt;

It&amp;rsquo;s an amazing Space Opera. It&amp;rsquo;s hard to really hate any characters in this story, even villains become lovable. I can&amp;rsquo;t wait to read more as they come out.&lt;/p&gt;
&lt;h2 id=&#34;favorite-manga-i-read&#34;&gt;
  Favorite Manga I read
  &lt;a href=&#34;#favorite-manga-i-read&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;a-man-and-his-cat&#34;&gt;
  A Man and His Cat
  &lt;a href=&#34;#a-man-and-his-cat&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/a_man_and_his_cat.jpg&#34;  alt=&#34;A Man and His Cat&#34;  /&gt;

This is a slice of life manga I suppose. I actually started reading this years ago, but I think I&amp;rsquo;ve come to appreciate it more in the past year with the absence of my dog. It&amp;rsquo;s silly, emotional, and very enjoyable.&lt;/p&gt;
&lt;h3 id=&#34;chihayafuru&#34;&gt;
  Chihayafuru
  &lt;a href=&#34;#chihayafuru&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/chihayafuru.jpg&#34;  alt=&#34;Chihayafuru&#34;  /&gt;

I knew nothing of what &lt;a href=&#34;https://en.wikipedia.org/wiki/Karuta&#34;&gt;Karuta&lt;/a&gt; was but the Japanese just have a way with taking a subject matter that I either know nothing of or have interest in and making it worth reading about. Obviously the story is more than just about the game, but it makes for an interesting vehicle in which to tell a story.&lt;/p&gt;
&lt;h3 id=&#34;dandadan&#34;&gt;
  Dandadan
  &lt;a href=&#34;#dandadan&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/dandadan.jpg&#34;  alt=&#34;Dadadan&#34;  /&gt;

Pure ridiculousness and the facial expressions of the characters is so funny. They also recently came out with the Anime this year as well.&lt;/p&gt;
&lt;h3 id=&#34;hinamatsuri&#34;&gt;
  Hinamatsuri
  &lt;a href=&#34;#hinamatsuri&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/hinamatsuri.jpg&#34;  alt=&#34;Hinamatsuri&#34;  /&gt;

This is lowkey comedic gold and I finally finished reading all of it this year. Highly recommend.&lt;/p&gt;
&lt;h3 id=&#34;jagaaaaaan&#34;&gt;
  Jagaaaaaan
  &lt;a href=&#34;#jagaaaaaan&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/jagaaaaaan.jpg&#34;  alt=&#34;Jagaaaaaan&#34;  /&gt;

I love weird shit and Jagaaaaaan is this mixture of weird, violence and ridiculous. It reminds me a lot of Gantz back in the day.&lt;/p&gt;
&lt;h3 id=&#34;sakamoto-days&#34;&gt;
  Sakamoto Days
  &lt;a href=&#34;#sakamoto-days&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/sakamoto_days.jpg&#34;  alt=&#34;Sakamoto Days&#34;  /&gt;

What if the most notorious assassin wanted to settle down and live a quiet life? Well its not gonna go smoothly for everyone else trying to collect that bounty on his head.&lt;/p&gt;
&lt;h2 id=&#34;favorite-anime-i-watched&#34;&gt;
  Favorite Anime I watched
  &lt;a href=&#34;#favorite-anime-i-watched&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;yuru-camp&#34;&gt;
  Yuru Camp
  &lt;a href=&#34;#yuru-camp&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/yuru_camp.jpg&#34;  alt=&#34;Yuru Camp&#34;  /&gt;

This is just a superb slice of life anime about camping. It doesn&amp;rsquo;t get deep and it kinda just makes you want to go camping.&lt;/p&gt;
&lt;h3 id=&#34;orb-on-the-movements-of-the-earth&#34;&gt;
  Orb: On the Movements of the Earth
  &lt;a href=&#34;#orb-on-the-movements-of-the-earth&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/orb.jpg&#34;  alt=&#34;Orb: On the Movements of the Earth&#34;  /&gt;

This anime started airing late in the year, but man has it been so interesting. The plot revolves around Heliocentrism and takes place through iterations of characters studying this &amp;ldquo;taboo&amp;rdquo; during a time of Geocentrism. There&amp;rsquo;s a manga to this as well.&lt;/p&gt;
&lt;h2 id=&#34;favorite-items-i-own&#34;&gt;
  Favorite Items I own
  &lt;a href=&#34;#favorite-items-i-own&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;bambu-labs-a1-mini&#34;&gt;
  Bambu Lab&amp;rsquo;s A1 Mini
  &lt;a href=&#34;#bambu-labs-a1-mini&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/bambulab_a1_mini.jpg&#34;  alt=&#34;Bambu Lab&amp;#39;s A1 Mini&#34;  /&gt;

I already own a fantastic Prusa MK3S, but wanted to see what the hype was around the Bambulab printers. So on a whim with some spare change, I bought the Bambulab A1 Mini. Man what a printer it is! The speed and accuracy in which it printed a benchy was pretty incredible, and at the price point, I totally understood the hype. It&amp;rsquo;s pretty great for prototyping small prints and even fairly large ones (well large for it&amp;rsquo;s build volume)&lt;/p&gt;
&lt;h3 id=&#34;steamdeck&#34;&gt;
  Steamdeck
  &lt;a href=&#34;#steamdeck&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;
  &lt;img src=&#34;https://r2.huynguyen.me/blog/2024/12/26/favorite-thangs-in-2024/images/steamdeck.jpg&#34;  alt=&#34;Steamdeck OLED&#34;  /&gt;

I used to travel back to my home town lugging my PS5 to keep up with my Destiny 2 addiction. But circumstances changed and I was no longer in a position to travel with my PS5. So I sold myself on the practicality of the Steamdeck. Not only could it play games from my Library, I could even play Destiny 2&amp;hellip;. if I installed Windows, which I had no plans to do. Instead what it acted great as was a Sony Remote Play and it worked great being able to stream my PS5 from the Steamdeck. Only bottleneck became the network, so unfortunately it did not run well outside of my home network. However it did allow me to start taking a crack at that backlog. I am thoroughly impressed by the device and I really hope this helps bring more attention to Linux gaming. It also makes for the perfect gaming session before bed.&lt;/p&gt;
&lt;h2 id=&#34;favorite-youtube-channels-of-the-year&#34;&gt;
  Favorite Youtube Channels of the year
  &lt;a href=&#34;#favorite-youtube-channels-of-the-year&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;adam-savages-testedhttpswwwyoutubecomtested&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@tested&#34;&gt;Adam Savage&amp;rsquo;s Tested&lt;/a&gt;
  &lt;a href=&#34;#adam-savages-testedhttpswwwyoutubecomtested&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve always enjoyed the maker that is Adam Savage, his build videos are always a delight to watch. I love how he approaches organizing his workspace and how he explains his thoughts and process in his videos. Every year the Tested team does a Favorite Things of the year, which is sort of what inspired this among many other things. He has an immense appreciation for tools and I love hearing him talk at length about some of his favorites.
Here&amp;rsquo;s one of my favorite videos of the year, would probably only interest people who are makers who enjoy the workspace they build in.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/PXfg4Qib-5I?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;possedbyhorrorhttpswwwyoutubecompossessedbyhorror&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@PossessedbyHorror&#34;&gt;PossedbyHorror&lt;/a&gt;
  &lt;a href=&#34;#possedbyhorrorhttpswwwyoutubecompossessedbyhorror&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Being the big horror fan that I am I of course watch youtubers talk about horror. This is certainly one of my favorite channels on the subject. I find Sarah&amp;rsquo;s appreciation of the Found Footage horror refreshing considering that most people seem to write of these shaky cam style horror movies as being bad. I personally love that style of horror. Here&amp;rsquo;s Sarah&amp;rsquo;s ranking of Found Footage style horror movies.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/wPaWn6m8L1k?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;kidologyhttpswwwyoutubecomkidologyco&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@KidologyCO&#34;&gt;Kidology&lt;/a&gt;
  &lt;a href=&#34;#kidologyhttpswwwyoutubecomkidologyco&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;A youtuber who does analytical eassy type videos about society. I think she has interesting thoughts and ideas that she brings up for discussion and appreciate the data she brings into the discussion. She recently made a video on the discussion of the end of reading, which I found really fascinating.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/7fz-W-jVT1s?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;flatlander-techhttpswwwyoutubecomflatlandertech&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@FlatLanderTech&#34;&gt;FLATLANDER TECH&lt;/a&gt;
  &lt;a href=&#34;#flatlander-techhttpswwwyoutubecomflatlandertech&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s a interesting maker / film maker type channel. Watching his custom desk build has been really satisfying.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/cPbujol_d9M?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;diggnationhttpswwwyoutubecomdiggnation&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@diggnation&#34;&gt;Diggnation&lt;/a&gt;
  &lt;a href=&#34;#diggnationhttpswwwyoutubecomdiggnation&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;After over a decade since Diggnation last aired, Kevin and Alex get together and do a special reboot episode and boy was it everything I remembered. Diggnation has a special place in my heart as being probably the first podcast I ever watched back in my college days. The subject matter was never really special given that they just picked a few digg article to talk about, but what really made it magical was the chemistry they had, this was a real friendship on display, having a good time, drinking some booze and shooting the shit.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/nJWIrYEm2mo?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;antscanadahttpswwwyoutubecomantscanada&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@AntsCanada&#34;&gt;AntsCanada&lt;/a&gt;
  &lt;a href=&#34;#antscanadahttpswwwyoutubecomantscanada&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;I don&amp;rsquo;t know where to begin with this one, but I loved watching this man build this ridiculously giant indoor Vivarium. I couldn&amp;rsquo;t stop watching every week for a new update.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/e5Uvmf9iTpY?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;mina-lehttpswwwyoutubecomgremlita&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@gremlita&#34;&gt;Mina Le&lt;/a&gt;
  &lt;a href=&#34;#mina-lehttpswwwyoutubecomgremlita&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Another one of those video essay youtubers who talks about a wide variety of societal topics. She has a background in the fashion world so she often dresses up for her videos and sometimes the topic of discussion does have an overlay into that world.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/pPnIin0JLro?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;gawx-arthttpswwwyoutubecomgawxart&#34;&gt;
  &lt;a href=&#34;https://www.youtube.com/@GawxArt&#34;&gt;Gawx Art&lt;/a&gt;
  &lt;a href=&#34;#gawx-arthttpswwwyoutubecomgawxart&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;I only just stumbled upon his videos this year, but damn does this guy know how to make cinematic and aesthetically pleasing videos. I think it was this video that got me into his channel.&lt;/p&gt;

    &lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/u4HxS000Wv0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;some-honorable-mentions&#34;&gt;
  Some honorable mentions
  &lt;a href=&#34;#some-honorable-mentions&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/@MachoNachoProductions&#34;&gt;Macho Nacho Productions&lt;/a&gt; - Retro Game Console Repair and mods&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/@yourcoolunclemarisa&#34;&gt;YourCoolUncleMarisa&lt;/a&gt; - Sharing her love and story telling of retro consoles&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/@vuhlandes&#34;&gt;Vuhlandes&lt;/a&gt; - Photography, Film Making and story teller&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/@GxAce&#34;&gt;GxAce&lt;/a&gt; - Photography story telling with a cyber punk aesthetic.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;close-out&#34;&gt;
  Close out
  &lt;a href=&#34;#close-out&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;With that, my favorite thangs in 2024 has come to a close. Hope you all have a lovely time spending it with your loved ones and here&amp;rsquo;s to learning and growing in 2025!&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Moving Apartments and Moving the Homelab</title>
      <link>https://huynguyen.me/blog/2024/09/moving-apartments-and-moving-the-home-lab/</link>
      <pubDate>Sun, 15 Sep 2024 20:44:14 -0500</pubDate>
      
      <guid>https://huynguyen.me/blog/2024/09/moving-apartments-and-moving-the-home-lab/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Sometimes you just encounter some of the weirdest quirks with your tech and homelab and it only becomes apparent when you power off, dismantle, and move the whole shebang. I&amp;rsquo;ve recently moved and had to dismantle, box up, and relocate everything. Now let me preface this by saying while I would like to physically clean my servers on a more frequent bases, it&amp;rsquo;s generally difficult with the limiting space that I often find myself in with apartments. So most maintenance tends to happen during apartment moves or when something goes haywire. Most of my gear has not changed for several years and I often don&amp;rsquo;t really buy new parts outside of my desktop and hard drives.&lt;/p&gt;
&lt;p&gt;So with this move, I ended up encountering 2 major issues and I figured documenting them might be good in case someone else comes across similar issues and just needs some ideas to get the brain motors turning.&lt;/p&gt;
&lt;h2 id=&#34;problem-1&#34;&gt;
  Problem #1
  &lt;a href=&#34;#problem-1&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start with my main PC. I built this over 2 years ago, so here are the current specs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gigabyte X570 Aorus Ultra Motherboard&lt;/li&gt;
&lt;li&gt;AMD Ryzen 9 5900X&lt;/li&gt;
&lt;li&gt;64GB of RAM&lt;/li&gt;
&lt;li&gt;A bunch of SSDs&lt;/li&gt;
&lt;li&gt;1x Nvidia GeForce RTX 3080 Ti powering 4 monitors&lt;/li&gt;
&lt;li&gt;1x Nvidia Quadro M4000 for passthrough on VMs connected to a Wacom Cintiq 22HD&lt;/li&gt;
&lt;li&gt;OS: Archlinux&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maybe some day I&amp;rsquo;ll go over my main setup in further detail, but for now. Let&amp;rsquo;s go over the issue.
When powering on, the fans come on, but the BIOS doesn&amp;rsquo;t POST and holding down the power button doesn&amp;rsquo;t actually turn off the PC. I have to manually switch off the Power Supply. So already something weird is going on.&lt;/p&gt;
&lt;p&gt;No clue what could have happened during the move, but my guess is that either something got dislodged or a build up of static charge or something has caused an issue. So let&amp;rsquo;s go over some of the basic things I&amp;rsquo;ve tried.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Re-seating the RAM modules, moving the 2 sticks around, starting with 1 stick only. No changes.&lt;/li&gt;
&lt;li&gt;Re-seating the 2 Graphics cards, swapping them around, leaving in only one and removing them both. Still no changes.&lt;/li&gt;
&lt;li&gt;I took out the CMOS battery, waited 30 seconds to a minute and re-added it back. Again still no changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point I was starting to think that maybe the motherboard had gone bad and that I would need a whole new board replacement. But out of a final act of desperation I decided to re-seat the CPU itself. Amazingly this worked and my BIOS posted. I still don&amp;rsquo;t understand why re-seating the CPU did the trick, or perhaps by re-seating the CPU I had allowed some built up static to discharge or maybe the CMOS battery was finally able to dissipate?
Either way, I&amp;rsquo;m glad this was a no-cost fix.&lt;/p&gt;
&lt;h2 id=&#34;problem-2&#34;&gt;
  Problem #2
  &lt;a href=&#34;#problem-2&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;My NAS was not detecting any of the harddrives outside of the boot drives. For my setup, I&amp;rsquo;m running a 20 Hot-swap bay Norco Chassis, that I built well over a decade ago at this point. The only thing recent in this machine is the Hard Drives for the ZFS pools. Now normally I&amp;rsquo;d be really concern that the hard drives died, but not this time since I manually transported the hard drives myself, only the server was moved via hired movers. So I was 99.9% confident that the hard drives are not the issue here.
This means that the possible points of failure can be any device/component between the hard drive to the PCI-E slot. Since the boot drives are directly connect to the Sata ports on the motherboard. Let&amp;rsquo;s go over how a storage hard drive is connected.&lt;/p&gt;
&lt;p&gt;Hard Drive -&amp;gt; Backplane -&amp;gt; Sata to SFF Cable -&amp;gt; SAS Expander Card -&amp;gt; SFF to SFF Cable to HBA Card&lt;/p&gt;
&lt;p&gt;So I worked backwards, simply unplugging and replugging in cables and re-seating the HBA and Expander cards. It may seem dumb but sometimes things get loose in a move and just reseating/replugging them back in can solve the issue.&lt;/p&gt;
&lt;p&gt;This was not the case for me. So I then tried move the PCIE slots that the HBA and SAS cards were connected in around. Still no dice. So next step was to swap more cables around, still nothing really.&lt;/p&gt;
&lt;p&gt;Finally by shear coincidence, I started to really pay attention to the hot swap caddies during boot up as they do contain indicator lights for power and activity. I realized at somepoint that I was not seeing any green activity light during the startup phase when TrueNAS is trying to import the zfs pool. Since the power light shown, I started to suspect that maybe it was a sata/SFF cable issue. I decided to skip the SAS expander entirely and plug Sata/SFF cable directly into the HBA card instead. Plugged in a spare hard drive and I found out it was an issue with the SAS expander not being recognized. I made sure I tested all combination of SFF slots on the SAS expander with the HBA card, but none of it connected.&lt;/p&gt;
&lt;p&gt;Luckily the SAS expander was cheap and I was able to buy a used replacement from ebay, which is great because when I first put together this NAS, I also bought this used. So anytime I can used gear for cheap it&amp;rsquo;s a win in my book.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intel RES2SV240 24 port 6Gbps Sata SAS controller for around 30 USD&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The great thing is that this is just a drop in replacement, once I replaced the card, TureNAS was able to import the zfs pool and I was back in business.&lt;/p&gt;
&lt;p&gt;For gear that I bought used 10+ years ago it still works like a champ!&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Dotfiles for 2024</title>
      <link>https://huynguyen.me/blog/2024/04/dotfiles-for-2024/</link>
      <pubDate>Tue, 16 Apr 2024 11:56:51 -0500</pubDate>
      
      <guid>https://huynguyen.me/blog/2024/04/dotfiles-for-2024/</guid>
      <description>
        
          
          
          
        
        
        &lt;h2 id=&#34;intro&#34;&gt;
  Intro
  &lt;a href=&#34;#intro&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been on this kick to update my &lt;a href=&#34;https://github.com/sinicide/.dotfiles&#34;&gt;dotfiles&lt;/a&gt; so that I can also revamp my dotfiles that I use for work as well in an effort to optimize my workflow. With this I&amp;rsquo;m also making the switch from Vim to Neovim as my default text editor in order to really force myself to use and learn vim motions more. I&amp;rsquo;m not a software engineer, so my typical usage with Vim has just been to edit configuration files, write bash scripts or perform small edits. I&amp;rsquo;ve been using VSCode a lot for writing configuration yamls and anything remotely close to programming. So I&amp;rsquo;m going cold turkey and cutting VSCode out of my repertoire.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s go over some goals I have for iterating over my existing dotfiles.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Creating a new branch for the update before merging to master.&lt;/li&gt;
&lt;li&gt;Adding new configurations for neovim and tmux.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But before we go all in on what I&amp;rsquo;m adding, let&amp;rsquo;s go over a bit on how my dotfiles are structured for modularity.&lt;/p&gt;
&lt;h2 id=&#34;the-basic-structure&#34;&gt;
  The basic structure
  &lt;a href=&#34;#the-basic-structure&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;It was a few years ago that I learned about GNU &lt;a href=&#34;https://www.gnu.org/software/stow/manual/stow.html&#34;&gt;stow&lt;/a&gt; which allows you to create and manage symlinks. With this we can manage symlinks appearing in a given location following the structured format of another.&lt;/p&gt;
&lt;p&gt;To illustrate this, let&amp;rsquo;s say we have the following directory structure in my home directory&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;drwx--x---+ 53 sinicide sinicide 4.0K Apr 14 18:37 .
drwxr-xr-x   3 root     root     4.0K Sep 16  2021 ..
drwxr-xr-x   2 sinicide sinicide 4.0K Feb 17 20:41 bin
drwxr-xr-x  72 sinicide sinicide 4.0K Apr 14 15:55 .config
drwxr-xr-x  10 sinicide sinicide 4.0K Apr  5 07:41 .dotfiles
drwxr-xr--+ 30 sinicide sinicide  80K Apr 14 13:37 Downloads
lrwxrwxrwx   1 sinicide sinicide   29 Jan 23  2022 .gitconfig -&amp;gt; .dotfiles/personal/.gitconfig
drwxr-xr-x   3 sinicide sinicide 4.0K Aug 11  2023 Pictures
drwxr-xr-x   2 sinicide sinicide 4.0K Dec  7 16:52 .ssh
lrwxrwxrwx   1 sinicide sinicide   20 Mar 30 00:28 .tmux -&amp;gt; .dotfiles/tmux/.tmux
lrwxrwxrwx   1 sinicide sinicide   25 Mar 30 00:28 .tmux.conf -&amp;gt; .dotfiles/tmux/.tmux.conf
lrwxrwxrwx   1 sinicide sinicide   18 Mar 29 14:42 .vim -&amp;gt; .dotfiles/vim/.vim
-rw-------   1 sinicide sinicide  32K Mar 29 15:39 .viminfo
lrwxrwxrwx   1 sinicide sinicide   20 Mar 29 14:42 .vimrc -&amp;gt; .dotfiles/vim/.vimrc
-rw-------   1 sinicide sinicide  21K Oct 17  2021 .zhistory
-rw-r--r--   1 sinicide sinicide   87 Mar 13 00:26 .zlogin
lrwxrwxrwx   1 sinicide sinicide   21 Mar 29 14:42 .zshenv -&amp;gt; .dotfiles/zsh/.zshenv
-rw-------   1 sinicide sinicide 349K Apr 14 18:37 .zsh_history
lrwxrwxrwx   1 sinicide sinicide   20 Mar 29 14:42 .zshrc -&amp;gt; .dotfiles/zsh/.zshrc
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;From this you can see how the symlinks are mapped to the files within my &lt;code&gt;.dotfiles&lt;/code&gt; directory, I&amp;rsquo;ve split up configurations into their own specific directories, such as &lt;code&gt;tmux&lt;/code&gt;, &lt;code&gt;zsh&lt;/code&gt;, and &lt;code&gt;vim&lt;/code&gt; So the base of these subdirectories act as the base home directory and how I structure the files and subdirectories within this maps back to the home directory.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/home/sinicide/ = /home/sinicide/.dotfiles/zsh/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This makes it very modular and if I want to add new configs that are specific to an application I can just create a new directory for it. So for example, I&amp;rsquo;ll be adding Neovim configs which will live in&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/home/sinicide/.dotfiles/nvim/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Neovim configs are stored within a user&amp;rsquo;s &lt;code&gt;.config&lt;/code&gt; directory. So we&amp;rsquo;ll structure them the same way within our sub directory and when we run the stow command it&amp;rsquo;ll map it accordingly in our home directory.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/home/sinicide/.dotfiles/nvim/.config/nvim/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;How &lt;code&gt;stow&lt;/code&gt; works is that it can take a target directory, which is where &lt;code&gt;stow&lt;/code&gt; should create the symlinks and then it takes a given directory that it maps.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd ~/.dotfiles
stow -t ~ nvim
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the above command here will take our Home directory as a target and will map our &lt;code&gt;nvim&lt;/code&gt; directory. So when I navigate into the &lt;code&gt;~/.config&lt;/code&gt; directory I&amp;rsquo;ll see the following symlink.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;nvim -&amp;gt; ../.dotfiles/nvim/.config/nvim
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;neovim&#34;&gt;
  Neovim
  &lt;a href=&#34;#neovim&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;So one of my biggest undertaking here is switching to Neovim, with this comes a slew of possible plugins and key remaps. I had the following goals in mind to help make my choices.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Keep key remaps to a minimum to start&lt;/li&gt;
&lt;li&gt;Choose plugins that are useful instead of just providing a visual cool factor&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With that said, let&amp;rsquo;s take a look at my nvim config directory and how I&amp;rsquo;ve structure it.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[sinicide        4096]  .
├── [sinicide          42]  init.lua
├── [sinicide        2123]  lazy-lock.json
├── [sinicide        4096]  lua
│   ├── [sinicide        4096]  core
│   │   ├── [sinicide          42]  init.lua
│   │   ├── [sinicide         591]  remap.lua
│   │   └── [sinicide         915]  set.lua
│   ├── [sinicide        4096]  packagemanager
│   │   └── [sinicide         494]  init.lua
│   └── [sinicide        4096]  plugins
│       ├── [sinicide         902]  conform.lua
│       ├── [sinicide        4591]  lsp-config.lua
│       ├── [sinicide         211]  markdown-preview.lua
│       ├── [sinicide         955]  mason.lua
│       ├── [sinicide         281]  monokai-pro.lua
│       ├── [sinicide        1252]  nvim-cmp.lua
│       ├── [sinicide         954]  nvim-lint.lua
│       ├── [sinicide         891]  telescope.lua
│       ├── [sinicide         906]  treesitter.lua
│       ├── [sinicide          91]  undotree.lua
│       ├── [sinicide         111]  vim-paper.lua
│       └── [sinicide         528]  vim-tmux-navigator.lua
└── [sinicide        4096]  undodir
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At the core of it, we have the &lt;code&gt;init.lua&lt;/code&gt; inside nvim, which starts off all the requirements. This is a pretty simple file that only contains 2 things for my setup&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;require(&amp;#34;core&amp;#34;)
require(&amp;#34;packagemanager&amp;#34;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The required just points to non-plugin configurations, which are essentially the vim configurations and remaps. The other one just points to &lt;a href=&#34;https://github.com/folke/lazy.nvim&#34;&gt;lazy.nvim&lt;/a&gt; plugin manager. Now I do want to note that the docs recommends structuring the lazy config within the top level &lt;code&gt;init.lua&lt;/code&gt;, &lt;code&gt;plugins.lua&lt;/code&gt; or &lt;code&gt;plugins/init.lua&lt;/code&gt; However I structured mine within a directory I called &lt;code&gt;packagemanager&lt;/code&gt; and called it from the &lt;code&gt;init.lua&lt;/code&gt; just to help me understand the structure of loading things in neovim.&lt;/p&gt;
&lt;h3 id=&#34;nvim-core-configs&#34;&gt;
  nvim core configs
  &lt;a href=&#34;#nvim-core-configs&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;So the &lt;code&gt;core&lt;/code&gt; directory here contains 2 main things, vim default configs and key remappings, the &lt;code&gt;init.lua&lt;/code&gt; just points to 2 these two files. I won&amp;rsquo;t go into detail on the vim configs, these are primarily carried over from my original vim dotfiles and are less interesting I think.&lt;/p&gt;
&lt;p&gt;As for the key remaps, I do want to touch base on them since I&amp;rsquo;m trying to use VIM motions more and more so I&amp;rsquo;ve kept my remaps to a minimum for now to ensure that I learn the remaps as muscle memory.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve taken these remaps from &lt;a href=&#34;https://github.com/ThePrimeagen/init.lua/blob/master/lua/theprimeagen/remap.lua&#34;&gt;ThePrimeagen&lt;/a&gt; I did a little testing here and there to determine their benefits for my workflow. So let&amp;rsquo;s go over the ones I&amp;rsquo;ve chosen.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-- page up/down, keeping cursor centered
vim.keymap.set(&amp;#34;n&amp;#34;, &amp;#34;&amp;lt;C-d&amp;gt;&amp;#34;, &amp;#34;&amp;lt;C-d&amp;gt;zz&amp;#34;)
vim.keymap.set(&amp;#34;n&amp;#34;, &amp;#34;&amp;lt;C-u&amp;gt;&amp;#34;, &amp;#34;&amp;lt;C-u&amp;gt;zz&amp;#34;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I like the idea of keeping focus towards the center of the screen, so basically this remaps combines the default page up/down and then centers the cursor in the middle of the screen.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-- search, but keep item middle of screen
vim.keymap.set(&amp;#34;n&amp;#34;, &amp;#34;n&amp;#34;, &amp;#34;nzzzv&amp;#34;)
vim.keymap.set(&amp;#34;n&amp;#34;, &amp;#34;N&amp;#34;, &amp;#34;Nzzzv&amp;#34;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following keeps this same thing in mind, which is to keep the search pattern in center focus.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-- yank/paste to/from system clipboard
vim.keymap.set({&amp;#34;n&amp;#34;, &amp;#34;v&amp;#34;}, &amp;#34;&amp;lt;leader&amp;gt;y&amp;#34;, [[&amp;#34;+y]])
vim.keymap.set(&amp;#34;n&amp;#34;, &amp;#34;&amp;lt;leader&amp;gt;p&amp;#34;, [[&amp;#34;+p]])
-- delete into blackhole register
vim.keymap.set({&amp;#34;n&amp;#34;, &amp;#34;v&amp;#34;}, &amp;#34;&amp;lt;leader&amp;gt;d&amp;#34;, [[&amp;#34;_d]])
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above here should keep 2 separate copy buffers, one for vim and one for system clipboard.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-- shift highlighted line up/down
vim.keymap.set(&amp;#34;v&amp;#34;, &amp;#34;J&amp;#34;, &amp;#34;:m &amp;#39;&amp;gt;+1&amp;lt;CR&amp;gt;gv=gv&amp;#34;)
vim.keymap.set(&amp;#34;v&amp;#34;, &amp;#34;K&amp;#34;, &amp;#34;:m &amp;#39;&amp;lt;-2&amp;lt;CR&amp;gt;gv=gv&amp;#34;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally the above remap seems super nice for being able to highlight a block of text and shifting it up or down without having to yank/paste.&lt;/p&gt;
&lt;h3 id=&#34;the-plugins&#34;&gt;
  The plugins
  &lt;a href=&#34;#the-plugins&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s talk plugins, I&amp;rsquo;m keeping my approach with this to the absolute minimal for now, so you can see that I&amp;rsquo;m not installing a filemanager like NERDTree and just sticking with the default &lt;code&gt;netrw&lt;/code&gt; while it ain&amp;rsquo;t pretty, it does get the job done. I&amp;rsquo;m also not doing much in the way of customizing the bottom bar either, no lualine or anything as it&amp;rsquo;s really just for aesthetics.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using &lt;a href=&#34;https://github.com/nvim-telescope/telescope.nvim&#34;&gt;telescope&lt;/a&gt; to fuzzy find my way around files, &lt;a href=&#34;https://github.com/mbbill/undotree&#34;&gt;undotree&lt;/a&gt; for viewing previous iterations of a file, this is particularly helpful for configuration orientated files which I find myself working with often in my workflow. &lt;a href=&#34;https://github.com/christoomey/vim-tmux-navigator&#34;&gt;vim-tmux-navigator&lt;/a&gt; is for some nice keybindings for navigating between vim and tmux. &lt;a href=&#34;https://github.com/iamcco/markdown-preview.nvim&#34;&gt;Markdown Preview&lt;/a&gt; for being able to view what my markdown looks like rendered in a web browser, this is useful in particular for this blog as all content is written in Markdown, previously I&amp;rsquo;ve been using something similar in VSCode, so this is totally a nice to have.&lt;/p&gt;
&lt;p&gt;Finally we have 2 themes, monokai-pro is my default theme, but I have a nice vim-paper one for light mode if I ever need to do screensharing/presenting that way vim in my terminal is actually readable.&lt;/p&gt;
&lt;p&gt;The rest are for LSPs, linting and formatting, with the use of &lt;a href=&#34;https://github.com/nvim-treesitter/nvim-treesitter&#34;&gt;treesitter&lt;/a&gt;, &lt;a href=&#34;https://github.com/williamboman/mason.nvim&#34;&gt;mason&lt;/a&gt; for managing LSPs, and &lt;a href=&#34;https://github.com/stevearc/conform.nvim&#34;&gt;conform&lt;/a&gt; for managing Linters/Formatters.
Mason is pretty awesome for being able to manage installing LSPs, Linters, and Formatters, however the only thing it can auto install it seems are LSPs. Hence why we have Conform which helps to automating the installation of Linters and Formatters.&lt;/p&gt;
&lt;p&gt;With that my Neovim setup is complete.&lt;/p&gt;
&lt;h2 id=&#34;tmux-configs&#34;&gt;
  Tmux Configs
  &lt;a href=&#34;#tmux-configs&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;My tmux configs are split between 2 main components, the &lt;code&gt;.tmux.conf&lt;/code&gt; configuration file and a custom theme.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start by talking about the configuration file as this primarily contains my key bindings. Like most people, I&amp;rsquo;ve rebind the leader prefix from the default &lt;code&gt;C-b&lt;/code&gt; to &lt;code&gt;C-a&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Most important rebinds I have are, changing the pane navigation to VIM movements ala &lt;code&gt;hjkl&lt;/code&gt; and the splits. I&amp;rsquo;ve opted to use &lt;code&gt;|&lt;/code&gt; for horiztonal splits and &lt;code&gt;-&lt;/code&gt; for vertical splits, simply because they look like their respective cuts as opposed to the defaults, which are &lt;code&gt;%&lt;/code&gt; and &lt;code&gt;&amp;quot;&lt;/code&gt; , while it wouldn&amp;rsquo;t be difficult to learn them over time, my visual splits are just easier for me to remember.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# rebind navigation to VIM keys
bind -r h select-pane -L # move left
bind -r j select-pane -D # move down
bind -r k select-pane -U # move up
bind -r l select-pane -R # move right

# rebind splits
unbind |
unbind -
unbind %
unbind &amp;#39;&amp;#34;&amp;#39;
bind | split-window -h -c &amp;#34;#{pane_current_path}&amp;#34;
bind - split-window -v -c &amp;#34;#{pane_current_path}&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Like most, I also change the default numbering from starting 0 to 1. The reasoning behind this is that the 1 key is just closer on the left hand, so it&amp;rsquo;s a bit more optimized for session switching, as opposed to using 2 hands to hit the prefix keys + session number.&lt;/p&gt;
&lt;p&gt;I also have the configurations in place for loading the Tmux Plugin Manager, however I&amp;rsquo;m not currently using any plugins at the moment. I was testing out the vim-tmux-navigator, but have decided against the keybinds that it default for moving windows, which is to not use leader key prefix and only relay on &lt;code&gt;&amp;lt;ctrl&amp;gt; + &amp;lt;key&amp;gt;&lt;/code&gt;. Personally I like keeping this leader key prefix style specific for tmux so that I have it separate in my mind. With the keybindings it also removes the clear line key mapping in the terminal, so that was the main motivator for me to remove this plugin. I don&amp;rsquo;t need to necessarily use tmux all the time, so I don&amp;rsquo;t need to keep 2 different key bindings in my brain for the same action.&lt;/p&gt;
&lt;p&gt;Finally we have my custom theme, I looked at a bunch of the other themes out there for tmux and honestly I didn&amp;rsquo;t care for what they offered. So of course I had to create my own. So what makes my theme different? Mostly the removal of hostname + time as these are unnecessary give modern desktops generally show a clock somewhere.&lt;/p&gt;
&lt;p&gt;So I thought about the type of information that would be important to me with managing multiple terminal windows. This essentially boils down to,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What Session am I on?&lt;/li&gt;
&lt;li&gt;What Window am I on?&lt;/li&gt;
&lt;li&gt;How many panes are in a given window?&lt;/li&gt;
&lt;li&gt;Am I zoomed into a pane?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So I&amp;rsquo;ve customized the theme with these in mind and have removed the necessary things.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# left status bar
set-option -g status-left-style &amp;#39;bg=#19181a&amp;#39;
set-option -g status-left &amp;#39; &amp;#39;

# right status bar
set-option -g status-right-length 40
set-option -g status-right-style &amp;#39;bg=#19181a,fg=#a9dc76&amp;#39;
set-option -g status-right &amp;#39;#{?client_prefix,#[bg=#fc9868]#[fg=#19184a],} [#{=30:session_name}] &amp;#39;

# windows status
set-option -g window-status-format &amp;#39;#{window_index}#(echo &amp;#34;:&amp;#34;)#{=20:#{b:window_name}}#{window_flags}&amp;#39;
# window current/active status
set-option -g window-status-current-format &amp;#39;#{?client_prefix,#[bg=#fc9868]#[fg=#19184a],}#{window_index}:#(echo &amp;#34;#{b:window_name}&amp;#34;)#{?window_zoomed_flag,[Z],[#{window_panes}]}#{?mouse,[M],}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So you can see that this is split into 3 sections, a left side, right side and window-status, gets pushed to the left side. A nice little addition I added was the &lt;code&gt;Z&lt;/code&gt; indicator whenever I&amp;rsquo;m zoomed into a pane.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;
  Conclusion
  &lt;a href=&#34;#conclusion&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;With these new changes implemented, I can &lt;code&gt;git pull&lt;/code&gt; and update my existing dotfiles and stow the new changes all at once or one at a time. This becomes quite flexible when I want to integrate a personal or work folder given whether I&amp;rsquo;m using my work computer or my personal computer.&lt;/p&gt;
&lt;p&gt;All and all dotfiles are great and no two need be alike. I quite enjoy seeing how people setup their own dotfiles and take inspiration and snippets where it makes sense for my own workflow.&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>K8S The Number of the Beast Part 3</title>
      <link>https://huynguyen.me/blog/2024/01/anki-sync-server-part-3/</link>
      <pubDate>Mon, 22 Jan 2024 16:37:15 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2024/01/anki-sync-server-part-3/</guid>
      <description>
        
          
          
          
        
        
        &lt;h2 id=&#34;deploying-in-kubernetes&#34;&gt;
  Deploying in Kubernetes
  &lt;a href=&#34;#deploying-in-kubernetes&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Now that we have the container image I can work on deploying this to my Kubernetes Cluster. Now obviously I can deploy this to Docker and just be done with it, but a good chunk of my self hosted applications are deployed to Kubernetes. I don&amp;rsquo;t have any greater reasons for deploying in Kubernetes other than it&amp;rsquo;s beneficial for my understanding and helps with my day job. Now with deployments in Kubernetes I don&amp;rsquo;t have to worry so much if/when I take down a node for upgrade as the container will just move to another node for high up time.&lt;/p&gt;
&lt;h2 id=&#34;breaking-it-down&#34;&gt;
  Breaking it Down
  &lt;a href=&#34;#breaking-it-down&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Compared to deploying with &lt;code&gt;docker-compose&lt;/code&gt; yaml, there&amp;rsquo;s quite a bit more needed to deploy in Kubernetes. Containers deployed in Kubernetes are grouped as Pods, which can contain 1 or more containers, but for our use case we will only have 1 container in our pod. What we need to decide on is if our Application is stateful or not, which will help to determine if we should use a Deployment or a Statefulset. For my use case I only need 1 container and the application itself isn&amp;rsquo;t so state sensitive that I need to use a Statefulset. Next is Storage, we do need a big amount of storage but we need it to persist if the container is terminated, within my Kubernetes Cluster I&amp;rsquo;m using &lt;a href=&#34;https://longhorn.io/&#34;&gt;Longhorn&lt;/a&gt; for my Storage Class, this offers a number of useful features such as replicas and NFS/S3 backup solutions. Finally I&amp;rsquo;ll need a Reverse Proxy/Ingress solution to allow traffic from outside the Kubernetes Cluster to route to my Application, for that I&amp;rsquo;ll be using &lt;a href=&#34;https://traefik.io/&#34;&gt;Traefik&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So breaking down the yaml files we&amp;rsquo;ll need are the following&amp;hellip;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;deployment.yaml&lt;/code&gt; (defines our application)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ingressroute.yaml&lt;/code&gt; (defines our ingress routing)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pvc.yaml&lt;/code&gt; (defines our persistent volume claim)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;service.yaml&lt;/code&gt; (defines our service/routing)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;secrets.yaml&lt;/code&gt; (defines our environment variables as a Kubernetes Secret)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;deploymentyaml&#34;&gt;
  deployment.yaml
  &lt;a href=&#34;#deploymentyaml&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The following is an extremely basic Kubernetes deployment yaml that will deploy 1 replica (e.g. 1 pod) that is our &lt;code&gt;anki-syncserver&lt;/code&gt;. The pod exposes port &lt;code&gt;8080&lt;/code&gt; just like our &lt;code&gt;docker-compose&lt;/code&gt; example did.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;apps/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;replicas&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;selector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;matchLabels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;template&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;containers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ghcr.io/sinicide/anki-syncserver:v1.0.2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;envFrom&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;secretRef&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-secrets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;http&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;containerPort&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;volumeMounts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-pv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;mountPath&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-pv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;persistentVolumeClaim&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;claimName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-claim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;volumes&lt;/code&gt; section here defines the referenced Persistent Volume Claim, which our Pod will use.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	- &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-pv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	  &lt;span style=&#34;color:#f92672&#34;&gt;persistentVolumeClaim&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;claimName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-claim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we mount that Claim via the &lt;code&gt;volumeMounts&lt;/code&gt; sections of the Container definition, and in my case we&amp;rsquo;re mounting the PVC to &lt;code&gt;/data&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;volumeMounts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-pv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;mountPath&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally we&amp;rsquo;re taking the key/value pairs from our Kubernetes Secret and using them as Environment Variables within the Container.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;envFrom&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;secretRef&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-secrets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;pvcyaml&#34;&gt;
  pvc.yaml
  &lt;a href=&#34;#pvcyaml&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The persistent volume claim is fairly straight forward, it simply defines which Storage Class is used and the requested resource values.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-claim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;accessModes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;ReadWriteMany&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;storageClassName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;longhorn-retain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;requests&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;storage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;512M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since I&amp;rsquo;m not entirely sure how much disk space I&amp;rsquo;ll truly need to sync, I figured &lt;code&gt;512M&lt;/code&gt; will be a good starting point. The Storage Class itself will allow for volume expansion and my custom Storage Class also enables the persistent volume to be retained when the pod is terminated. I&amp;rsquo;m also not overtly concerned with backing up this data volume as I don&amp;rsquo;t consider this data necessarily mission critical, but Longhorn create multiple Replicas of my data and does allow for backing up to an NFS share or an S3 bucket as I mentioned earlier.&lt;/p&gt;
&lt;h3 id=&#34;serviceyaml&#34;&gt;
  service.yaml
  &lt;a href=&#34;#serviceyaml&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The service resource defines an endpoint and can be of type Load Balancer for requests outside the cluster to route to our application. However we&amp;rsquo;ll be using Traefik for our Ingress routing instead, meaning we just define a basic service resource, Traefik will have it&amp;rsquo;s own Load Balancer Service defined which will route traffic on port &lt;code&gt;80&lt;/code&gt; to our application&amp;rsquo;s port &lt;code&gt;8080&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;selector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;protocol&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;TCP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;http&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;inrgressrouteyaml&#34;&gt;
  inrgressroute.yaml
  &lt;a href=&#34;#inrgressrouteyaml&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Since I&amp;rsquo;m using Traefik for Ingress, we need to define a Custom Resource called &lt;code&gt;IngressRoute&lt;/code&gt; that will match a rule to route the DNS hostname &lt;code&gt;anki-temp.sin.lan&lt;/code&gt; on port 80 to our service on port &lt;code&gt;8080&lt;/code&gt;. Traefik has this concept of &lt;code&gt;entryPoints&lt;/code&gt; which are typically just &lt;code&gt;http/80&lt;/code&gt; or &lt;code&gt;https/443&lt;/code&gt; which we can then redirect to our application&amp;rsquo;s specific port. Since there&amp;rsquo;s no SSL configuration for Anki Sync Server out of the box and it&amp;rsquo;s not a huge deal for me to use a super crackable password, I don&amp;rsquo;t have a need to offload SSL handling with my Ingress Controller. I&amp;rsquo;ve simply opted to just use the http endpoint called &lt;code&gt;web&lt;/code&gt; for the time being. I primarily still use Self-Signed Certificates in my home network and these typically will fail validation in most application unless there&amp;rsquo;s a way to specify a Truststore, so I don&amp;rsquo;t want to bother with that hassle for now.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;traefik.containo.us/v1alpha1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;IngressRoute&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-http&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;entryPoints&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;web&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;routes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;match&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Host(`anki-temp.sin.lan`)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Rule&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this, I can reach my Anki Sync Server at the following address &lt;code&gt;http://anki-temp.sin.lan/&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;secretsyaml&#34;&gt;
  secrets.yaml
  &lt;a href=&#34;#secretsyaml&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Since I need to provide an Environment Variable with our username+password, I&amp;rsquo;ve opted to use a Kubernetes Secret to hold this sensitive information as opposed to simply defining it within the Deployment yaml. So in this resource, I&amp;rsquo;m providing a key/value data, our Environment Variable &lt;code&gt;SYNC_USER1&lt;/code&gt; and it&amp;rsquo;s associating value which is composed of the username and password separated by a colon &lt;code&gt;anki_username:anki_password&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver-secrets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Opaque&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;stringData&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;SYNC_USER1&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;anki_username:anki_password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-cicd-way&#34;&gt;
  The CI/CD Way
  &lt;a href=&#34;#the-cicd-way&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been playing around with around with ArgoCD for my Continuous Deployment solution in my Kubernetes cluster, so of course I had to get my Anki Sync Server Deployment going here. This allows me to update my github repo and ArgoCD will pull down the changes when detected and deploy the changes in my Kubernetes Cluster.&lt;/p&gt;
&lt;p&gt;ArgoCD provides a Custom Resource Definition for deploying Applications in Kubernetes, This yaml can reference a github repo or Helm chart that it&amp;rsquo;ll use to deploy and keep watch on. So the following is what I&amp;rsquo;m using, which is extremely bare minimum to get my Anki Sync Server deployed in my Kubernetes Cluster.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Application&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;argocd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# remove this for prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;finalizers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;resources-finalizer.argocd.argoproj.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;project&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;source&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;repoURL&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;https://github.com/sinicide/sh-repo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;targetRevision&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;HEAD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;yamls/anki-syncserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;destination&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;server&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;https://kubernetes.default.svc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;apps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;syncPolicy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;automated&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;prune&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;syncOptions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;CreateNamespace=true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;retry&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;limit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;backoff&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;duration&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;factor&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;maxDuration&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;revisionHistoryLimit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Please note, my &lt;a href=&#34;https://github.com/sinicide/sh-repo&#34;&gt;sh-repo&lt;/a&gt; for Anki Sync Server doesn&amp;rsquo;t provide an example for the Kubernetes Secret yaml, so that&amp;rsquo;s something that needs to be deployed manually before hand and needs to exist before ArgoCD can successfully deploy the Anki Sync Server Git Repo if you are using my github repo for your own deployment.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sinicide/sh-repo&#34;&gt;sh-repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sinicide/sh-repo/blob/main/argocd/application/anki-syncserver.yaml&#34;&gt;ArgoCD Yaml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sinicide/sh-repo/tree/main/yamls/anki-syncserver&#34;&gt;Anki-Syncserver&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;
  Conclusion
  &lt;a href=&#34;#conclusion&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;With my Anki Sync Server now deployed, I can point my local Anki Instances to the Sync Server &lt;code&gt;http://anki-temp.sin.lan&lt;/code&gt; and will be able to sync progress and decks between my Desktop and Phone. Frankly it&amp;rsquo;s working really well for all the extra work I went through to do this. Now comes the hard part which is learning Japanese with this Anki System, until next time.&lt;/p&gt;
&lt;p&gt;じゃあね&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Building and Deploying Anki Sync Server Part 2</title>
      <link>https://huynguyen.me/blog/2024/01/anki-sync-server-part-2/</link>
      <pubDate>Wed, 10 Jan 2024 19:11:27 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2024/01/anki-sync-server-part-2/</guid>
      <description>
        
          
          
          
        
        
        &lt;h2 id=&#34;continuing&#34;&gt;
  Continuing&amp;hellip;
  &lt;a href=&#34;#continuing&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Alright now that we have our &lt;code&gt;Dockerfile&lt;/code&gt; fleshed out and we&amp;rsquo;ve verified that we can start it up without it crashing, let&amp;rsquo;s move on and figure out how to automate all this so that we don&amp;rsquo;t need to build locally and/or push a container image locally. Now I&amp;rsquo;ve only used Github Actions sparingly, this blog uses Github Actions to make a commit on the main repository whenever I update either the Theme or create a new blog post, this way I can keep my blog separated into standalone components should I one day want to move to a brand new theme or move to a different Static Site Generator.&lt;/p&gt;
&lt;h2 id=&#34;github-actions&#34;&gt;
  Github Actions
  &lt;a href=&#34;#github-actions&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.github.com/en/actions&#34;&gt;Github&lt;/a&gt; provides a framework to help you build workflows/pipelines for your projects. These actions can be triggered based on specific activities such as a &lt;code&gt;Push&lt;/code&gt; to the repository. In fact Github themselves provides an example yaml for &lt;a href=&#34;https://docs.github.com/en/actions/publishing-packages/publishing-docker-images&#34;&gt;Publishing Docker Images&lt;/a&gt; which we&amp;rsquo;ll use as a base for our own workflow.&lt;/p&gt;
&lt;p&gt;The following is the workflow I&amp;rsquo;ll be using&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Publish Docker image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;workflow_dispatch&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;push_to_registries&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Push Docker image to multiple registries&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;packages&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Check out the repo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/checkout@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Log in to Docker Hub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;username&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ secrets.DOCKER_USERNAME }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;password&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ secrets.DOCKER_PASSWORD }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Log in to the Container registry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;registry&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ghcr.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;username&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ github.actor }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;password&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Extract metadata (tags, labels) for Docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;meta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;images&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            ${{ secrets.DOCKER_REPO }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            ghcr.io/${{ github.repository }}&lt;/span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Build and push Docker images&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;context&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;push&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;tags&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ steps.meta.outputs.tags }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;labels&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ steps.meta.outputs.labels }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For now the trigger is a manual execution, meaning this won&amp;rsquo;t trigger unless I do so from the Github Actions UI.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;on:
  workflow_dispatch:
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But let&amp;rsquo;s break down what this workflow is doing. Here we have our job id &lt;code&gt;push_to_registries&lt;/code&gt; and in Github Actions, jobs run parallel with each other by default, so you can have multiple jobs execute at the same time when triggered. You can also specify conditions for each job, so you can build out complex and robust workflows where 1 or more jobs are triggered. This can be useful for automating tests. However for our needs, we&amp;rsquo;ll just stick to one job.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;push_to_registries:
    name: Push Docker image to multiple registries
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Jobs contains a list of sequential steps which are executed when ran. Here we&amp;rsquo;re doing the following.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check out the repo&lt;/li&gt;
&lt;li&gt;Log in to Docker Hub&lt;/li&gt;
&lt;li&gt;Log in to the Container registry&lt;/li&gt;
&lt;li&gt;Extract metadata (tags, labels) for Docker&lt;/li&gt;
&lt;li&gt;Build and push Docker images&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this workflow we&amp;rsquo;ll be pushing to both the Docker&amp;rsquo;s Container Registry and Github Container Registry in one single action and we&amp;rsquo;re doing this by using reusable actions, &lt;code&gt;uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671&lt;/code&gt; What are reusable actions? Basically they&amp;rsquo;re other workflows that perform a set of steps that we&amp;rsquo;re now referencing. Think of it like a function call, you or others build out a function that does something specific and now you can reuse that function in other parts of your program.&lt;/p&gt;
&lt;p&gt;Now an important consideration here is the Tagging, by default if you&amp;rsquo;re just executing a workflow based on a given branch such as &lt;code&gt;main&lt;/code&gt; you&amp;rsquo;ll end up with an image  name + version like &lt;code&gt;sinicide/anki-syncserver:main&lt;/code&gt; which is fine if I was never ever going to update this again, but really what I want is that nice &lt;code&gt;sinicide/anki-syncserver:v1.0.0&lt;/code&gt; versioning.&lt;/p&gt;
&lt;h2 id=&#34;semantic-versioning&#34;&gt;
  Semantic Versioning
  &lt;a href=&#34;#semantic-versioning&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;So we need to take a detour here and figure out what the heck is Semantic Versioning and how can I get that nice Release Tagging. Luckily there is a handy website &lt;a href=&#34;https://semver.org/&#34;&gt;semver.org&lt;/a&gt; that goes over the whole version numbering. But really all we need to know is that the format is &lt;code&gt;MAJOR.MINOR.PATCH&lt;/code&gt; and that&amp;rsquo;s how the version number is formatted. The &lt;strong&gt;Major&lt;/strong&gt; number generally dictates a big change, that is incompatible with the old Major number. The &lt;strong&gt;Minor&lt;/strong&gt; number is for functionality changes that are backwards compatible. And finally the &lt;strong&gt;Patch&lt;/strong&gt; number is generally for bug fixes. If you want to learn more, I highly recommend reading the link I referenced.&lt;/p&gt;
&lt;p&gt;Doing some research online I found that a pretty popular Semantic Versioning automation is &lt;a href=&#34;https://semantic-release.gitbook.io/semantic-release/&#34;&gt;semantic-release&lt;/a&gt; which is an NPM package that uses &lt;a href=&#34;https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-format&#34;&gt;Angular&amp;rsquo;s Commit Message Conventions&lt;/a&gt; meaning that as we work on our project and commit our changes to Git, we can add little prefixes which semantic-release&amp;rsquo;s workflow will be able to read and determine if it needs to set the Major, Minor, and Patch version, this combined with Github&amp;rsquo;s Actions gives us a very powerful automation workflow.&lt;/p&gt;
&lt;h2 id=&#34;semantic-release-setup&#34;&gt;
  Semantic-Release Setup
  &lt;a href=&#34;#semantic-release-setup&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Now I wouldn&amp;rsquo;t say that this is a typical application development since I&amp;rsquo;m just repackaging an existing program into a docker container so there&amp;rsquo;s a lot in the Example workflow that I didn&amp;rsquo;t need to make use of. So let&amp;rsquo;s go over how I implemented semantic-release for this docker project.&lt;/p&gt;
&lt;h3 id=&#34;configuration-file&#34;&gt;
  Configuration File
  &lt;a href=&#34;#configuration-file&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Semantic-release uses a configuration file, I initially started trying do this with a &lt;code&gt;.releaserc&lt;/code&gt; file but found in my testing that I needed a &lt;code&gt;package.json&lt;/code&gt; for some npm stuff, so I just opted to use a &lt;code&gt;package.json&lt;/code&gt; solely instead of having both.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;anki-syncserver&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;private&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;release&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;branches&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here I&amp;rsquo;m setting &lt;code&gt;private=true&lt;/code&gt; because we are not publishing this to npm, so we have no need of an NPM Token which would be necessary to publish to npm.
The important thing here is the &lt;code&gt;branches&lt;/code&gt; which can take an array of string objects to determine which branches a release should be applied to. Since I&amp;rsquo;m only testing locally and publishing only final releases, I&amp;rsquo;m just gonna stick with the &lt;code&gt;main&lt;/code&gt; branch in the Github repo.&lt;/p&gt;
&lt;h3 id=&#34;semantic-release-workflow&#34;&gt;
  Semantic-Release Workflow
  &lt;a href=&#34;#semantic-release-workflow&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Now semantic-release provides a sample &lt;a href=&#34;https://semantic-release.gitbook.io/semantic-release/recipes/ci-configurations/github-actions&#34;&gt;Github workflow yaml example&lt;/a&gt;, but we don&amp;rsquo;t need a bunch of the configuration on there by default because again I&amp;rsquo;m not publishing this to npm.&lt;/p&gt;
&lt;p&gt;So below is what I&amp;rsquo;ve settled on.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Release&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;branches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;release&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Release&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;issues&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;pull-requests&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Checkout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/checkout@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;fetch-depth&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Setup Node.js&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/setup-node@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;node-version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;lts/*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Release&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;env&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;GITHUB_TOKEN&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npx semantic-release@22.0.12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here I&amp;rsquo;ve stripped out &lt;code&gt;id-token&lt;/code&gt; for permissions, gotten rid of &lt;code&gt;Install dependencies&lt;/code&gt; and &lt;code&gt;Verify the integrity....&lt;/code&gt; and finally removed the &lt;code&gt;NPM_TOKEN&lt;/code&gt; as well. These would be used for publishing to npm, which I don&amp;rsquo;t need.&lt;/p&gt;
&lt;p&gt;Finally I&amp;rsquo;m also specifying a specific version of &lt;code&gt;semantic-release&lt;/code&gt; npm package and bumping up the &lt;code&gt;actions/xxxx@v4&lt;/code&gt; since it&amp;rsquo;s generally good practice to have a consistent experience using the same version until you are ready to upgrade to a newer version. Otherwise you might eventually run into unexpected behaviors as it tries to use the latest.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;
  What&amp;rsquo;s Next
  &lt;a href=&#34;#whats-next&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;So now we have a workflow that generates tags with Semantic Versioning in Github. These Tags can then be used for Publishing Docker containers to the Container Registries. For the moment Pushing Docker images is a manual trigger, at some point I&amp;rsquo;ll work on getting that automated based on the releases, I just need to learn a bit more on Github Actions.&lt;/p&gt;
&lt;p&gt;Next time we&amp;rsquo;ll go over how I&amp;rsquo;m deploying the public containers in my Kubernetes setup.&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Building and Deploying Anki Sync Server Part 1</title>
      <link>https://huynguyen.me/blog/2024/01/anki-sync-server-part-1/</link>
      <pubDate>Sat, 06 Jan 2024 19:39:23 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2024/01/anki-sync-server-part-1/</guid>
      <description>
        
          
          
          
        
        
        &lt;h2 id=&#34;learning-japanese&#34;&gt;
  Learning Japanese
  &lt;a href=&#34;#learning-japanese&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m really trying to learn how to Read and Speak Japanese this year for a future trip to Japan. Part of this goal is to learn to read Hiragana and Katakana and I was having trouble finding a learning method that would help with this in a way I wanted. I wanted a flash card system for learning the characters, but specially to learn both Hiragana and Katakana at the same time. So instead of learning one writing system&amp;rsquo;s characters and sound, I&amp;rsquo;d learn both the character system at the same time since they&amp;rsquo;re pretty much the same, plus I got it in my head that it&amp;rsquo;d probably be easier to learn it this way. Now there&amp;rsquo;s tons of applications/programs/etc to actually learn this. Tons of practice writing charts and what not. However I don&amp;rsquo;t specifically want to learn how to write (I know, I know, insane 🤯) I mean, when was the last time I actually hand wrote something? It&amp;rsquo;s all type type type in today&amp;rsquo;s world. For my use cases, I really only need to understand speech, be able to speak back and then be able to read signs, menus, dialogue, etc. So I want a flash card system that can accommodate this, most learning apps probably aren&amp;rsquo;t built this way.&lt;/p&gt;
&lt;p&gt;For my requirements, I need the following in an application/system&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Runs on Linux/Android&lt;/li&gt;
&lt;li&gt;Can create my own flashcards that contains images &lt;strong&gt;and&lt;/strong&gt; sound so that I can learn the character and the sound for said character&lt;/li&gt;
&lt;li&gt;Regularly maintained&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So in comes &lt;a href=&#34;https://apps.ankiweb.net/&#34;&gt;Anki&lt;/a&gt; a flash card application that runs on multiple platforms (Windows, MacOS, Linux, iOS, and Android) &lt;em&gt;and&lt;/em&gt; can sync between devices as well. From what I understand, Anki is extremely customizable and easy to get started with. And if youtube is any indication, if it&amp;rsquo;s good enough for Medical Students, it&amp;rsquo;s good enough for my basic language learning needs.&lt;/p&gt;
&lt;h2 id=&#34;ankiweb&#34;&gt;
  AnkiWeb
  &lt;a href=&#34;#ankiweb&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You can use AnkiWeb to sync your Flashcards between devices (e.g. desktop and smartphone), however while I have no intentions of doing anything malicious or illegal, it&amp;rsquo;s very likely that me scrapping the internet for graphics and sound is not exactly within &lt;a href=&#34;https://ankiweb.net/account/terms#Acceptable%20Content&#34;&gt;Acceptable Content&lt;/a&gt; usage for a Free AnkiWeb sync account. But there is a Self-Hosted option for a &lt;a href=&#34;https://docs.ankiweb.net/sync-server.html&#34;&gt;Anki Self-Hosted Sync Server&lt;/a&gt; so that&amp;rsquo;s perfect, I can just spin up a docker container and have a local sync server that I can point my devices to.&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;
  The Problem
  &lt;a href=&#34;#the-problem&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Doing some research there doesn&amp;rsquo;t appear to be a regularly maintained Docker Image in English from what I can tell. Now I did find one from &lt;a href=&#34;https://github.com/ankicommunity/anki-sync-server&#34;&gt;AnkiCommunity Github&lt;/a&gt;  however that doesn&amp;rsquo;t look to be actively maintained. I would really prefer not to use out of date software, so how hard could it be to build a docker image for the Anki Sync Server?&lt;/p&gt;
&lt;h2 id=&#34;challenge-accepted&#34;&gt;
  Challenge Accepted
  &lt;a href=&#34;#challenge-accepted&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s go over the requirements for hosting an Anki Sync Server in my Homelab&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Running the Anki Sync Server in a Docker Container&lt;/li&gt;
&lt;li&gt;Deploy the Container Image in my Kubernetes Cluster&lt;/li&gt;
&lt;li&gt;Automate the Build process for the Docker Image so that I can build new images easily in the future&lt;/li&gt;
&lt;li&gt;Push said Docker Image to both Github Container Registry &lt;strong&gt;and&lt;/strong&gt; Docker Hub Registry&lt;/li&gt;
&lt;li&gt;Automate Release Version Tagging for the docker images pushed&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;rtfm&#34;&gt;
  RTFM
  &lt;a href=&#34;#rtfm&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;So let&amp;rsquo;s start with the Sync Server &lt;a href=&#34;https://docs.ankiweb.net/sync-server.html&#34;&gt;Documentation&lt;/a&gt; Reading this tells me that their Sync Server is part of their Anki application and I can install the application in Linux or install via Python Module. I decided to go with the Python module as I can easily install specific versions via &lt;code&gt;pip&lt;/code&gt;  so with that in mind, I can build a &lt;code&gt;Dockerfile&lt;/code&gt; based on the &lt;code&gt;python:3.9.18&lt;/code&gt; base image.&lt;/p&gt;
&lt;p&gt;From the doc, we can see that running the Sync Server really only requires&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First User Credentials (requires the environment variable &lt;code&gt;SYNC_USER1=username:password&lt;/code&gt; additional users can be added via &lt;code&gt;SYNC_USER2&lt;/code&gt; and so on)&lt;/li&gt;
&lt;li&gt;Web Port (defaults to &lt;code&gt;SYNC_PORT=8080&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Sync Directory (where the sync data is stored, this defaults to &lt;code&gt;/.syncserver&lt;/code&gt; and can be overriden via environment variable &lt;code&gt;SYNC_BASE&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In case you just want to check out the repository here you go &lt;a href=&#34;https://github.com/sinicide/anki-syncserver&#34;&gt;Anki SyncServer Repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now below is what I came up with for the &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; python:3.9.18&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENV&lt;/span&gt; SYNC_HOST &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENV&lt;/span&gt; SYNC_PORT &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ENV&lt;/span&gt; SYNC_BASE &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; /&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;COPY&lt;/span&gt; requirements.txt .&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; python -m pip install --upgrade pip &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    python -m pip install -r ./requirements.txt&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; ${SYNC_PORT}&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;python&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-m&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;anki.syncserver&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is super basic, we&amp;rsquo;re setting up the necessary Environment Variable (omitting &lt;code&gt;SYNC_USER1&lt;/code&gt; for now). We&amp;rsquo;re passing a &lt;code&gt;requirements.txt&lt;/code&gt; which will be used by &lt;code&gt;pip&lt;/code&gt; to install our Anki Python Module and specific version&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;anki == 23.12.1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At the time of this writing the latest version of Anki is &lt;code&gt;23.12.1&lt;/code&gt; so that&amp;rsquo;s what I&amp;rsquo;m going with.&lt;/p&gt;
&lt;p&gt;Now I wrote a &lt;code&gt;Makefile&lt;/code&gt; to build the docker image locally for testing just to make sure it all works as expected.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;APP_VERSION &lt;span style=&#34;color:#f92672&#34;&gt;?=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;23.12.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;APP_NAME &lt;span style=&#34;color:#f92672&#34;&gt;?=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;anki-syncserver&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	docker build --no-cache -t &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;APP_NAME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;APP_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This only has one option &lt;code&gt;build&lt;/code&gt; and will run the &lt;code&gt;docker build&lt;/code&gt; command to create a docker image called &lt;code&gt;anki-syncserver:23.12.1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So I can just run a simple &lt;code&gt;make build&lt;/code&gt; command to get that going.&lt;/p&gt;
&lt;h2 id=&#34;testing&#34;&gt;
  Testing
  &lt;a href=&#34;#testing&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;While I can run a &lt;code&gt;docker run&lt;/code&gt; command to deploy my container, I&amp;rsquo;d rather test using a &lt;code&gt;docker-compose&lt;/code&gt; yaml file.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-docker-compose&#34; data-lang=&#34;docker-compose&#34;&gt;version: &amp;#39;3&amp;#39;
services:
  anki-sync:
    image: anki-syncserver:23.12.1
    container_name: anki-sync
    environment:
      SYNC_USER1: &amp;#34;username:password&amp;#34;
    ports:
      - 8080:8080
    volumes:
      - ./data:/data
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here we&amp;rsquo;re putting it all together, I&amp;rsquo;m running a single service specifying our local docker image and version. Exposing the web port &lt;code&gt;8080&lt;/code&gt;. Mounting a local directory for the Data volume. By default I&amp;rsquo;m mapping the Sync Directory to &lt;code&gt;/data&lt;/code&gt; in the docker image, but this could also be overwritten by specifying the &lt;code&gt;SYNC_BASE&lt;/code&gt; environment variable.
Finally I&amp;rsquo;m setting our 1 and only user, &lt;code&gt;SYNC_USER1=username:password&lt;/code&gt; which is by no means secure in any shape of form.&lt;/p&gt;
&lt;p&gt;Next a simple &lt;code&gt;docker-compose up&lt;/code&gt; will show that our application is running successfully as it&amp;rsquo;s listening on port &lt;code&gt;8080&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;anki-sync  | 2024-01-07T05:13:58.351480Z  INFO listening addr=0.0.0.0:8080
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;next-time-on-dragon-ball-z&#34;&gt;
  Next Time &lt;del&gt;on Dragon Ball Z&lt;/del&gt;
  &lt;a href=&#34;#next-time-on-dragon-ball-z&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;And that&amp;rsquo;s it! We now have a simple docker image, next time we&amp;rsquo;ll cover automating the build process because I really don&amp;rsquo;t want to manually push the docker image to the container registries.&lt;/p&gt;
&lt;p&gt;つづく&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Migrating to Unifi Network Application</title>
      <link>https://huynguyen.me/blog/2023/11/migrating-to-unifi-network-application/</link>
      <pubDate>Sun, 26 Nov 2023 18:23:57 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2023/11/migrating-to-unifi-network-application/</guid>
      <description>
        
          
          
          
        
        
        &lt;h2 id=&#34;the-backstory&#34;&gt;
  The Backstory
  &lt;a href=&#34;#the-backstory&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;In my home network, I use Ubiquiti products for my Wireless Access Points. In particular I have Unifi AP AC Lite deployed in both my Apartment and in my Parent&amp;rsquo;s home for Wifi. Recently I also bought a used Unifi Standard USW-24 Managed Switch, that I need to migrate to as I&amp;rsquo;ve been using a Dell PowerConnect 2824 Managed Switch for a several years now.&lt;/p&gt;
&lt;p&gt;You might be asking why I use Unifi Wireless Access Points, when most consumer grade Router/Wifi combos already include Wifi. Well I also don&amp;rsquo;t use Consumer Grade Routers or at least I haven&amp;rsquo;t for the better part of a decade now.&lt;/p&gt;
&lt;p&gt;The entry point into my Home Networking typically follows&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Modem -&amp;gt; pfSense (Router) -&amp;gt; Switch -&amp;gt; Unifi AP (wifi)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;While pfSense can handle Wifi as well, it was preferred back in the day to have that be handled by something else (not sure if this is still true or not), either a Consumer Grade Wifi/Router acting as a Wifi only Access Point or a Unifi AP.&lt;/p&gt;
&lt;p&gt;The Unifi Wifi Access Points can be Powered over Ethernet, so if you have a PoE switch, you can power the Access Points directly with 1 cable instead of having a power dongle to go with the Ethernet, unfortunately I don&amp;rsquo;t yet have a PoE switch, so I&amp;rsquo;m still using the power dongle.&lt;/p&gt;
&lt;p&gt;With these Ubiquiti products, you&amp;rsquo;ll need an Application to configure them. For Self-Hosted minded individuals, this is where the Unifi Controller Web Application comes in.&lt;/p&gt;
&lt;p&gt;For years now I&amp;rsquo;ve been using the &lt;code&gt;unifi-controller&lt;/code&gt; docker image by &lt;a href=&#34;https://github.com/linuxserver/docker-unifi-controller&#34;&gt;linuxserver.io&lt;/a&gt; This was/is a relatively painless setup. However in January 1st, 2024, linuxserver.io will be deprecating the &lt;code&gt;unifi-controller&lt;/code&gt; image and instead we&amp;rsquo;ll need to upgrade/migrate to &lt;a href=&#34;https://github.com/linuxserver/docker-unifi-network-application&#34;&gt;Unifi Network Application&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since the new year is fast approaching, I went ahead and made the necessary changes. So let&amp;rsquo;s go over the migration requirements and steps to perform.&lt;/p&gt;
&lt;h2 id=&#34;requirements&#34;&gt;
  Requirements
  &lt;a href=&#34;#requirements&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In place upgrade does not work (e.g. can&amp;rsquo;t just swap container image)&lt;/li&gt;
&lt;li&gt;Create a backup of existing unifi-controller&lt;/li&gt;
&lt;li&gt;Unifi Network Application requires Mongo DB&lt;/li&gt;
&lt;li&gt;Create docker-compose file for new deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my existing deployment of &lt;code&gt;unifi-controller&lt;/code&gt; I used a docker-compose file, so I&amp;rsquo;ll need to replace that with a new one.&lt;/p&gt;
&lt;h2 id=&#34;backing-up-the-config&#34;&gt;
  Backing Up the Config
  &lt;a href=&#34;#backing-up-the-config&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This is extremely straight forward, just go to the Unifi Controller &lt;code&gt;Settings &amp;gt; System &amp;gt; Backups&lt;/code&gt; and download a copy of the backup file. Yay! now you have a &lt;code&gt;.unf&lt;/code&gt; backup file, we&amp;rsquo;ll need this to restore our Unifi Settings when we&amp;rsquo;ve deployed the Unifi Network Application since it won&amp;rsquo;t have any configuration on start essentially being a brand new setup.&lt;/p&gt;
&lt;h2 id=&#34;lets-talk-docker-compose&#34;&gt;
  Let&amp;rsquo;s talk docker-compose
  &lt;a href=&#34;#lets-talk-docker-compose&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We need to create a new docker-compose file that containers the Unifi Network Application image in addition to the Mongo DB image, since that&amp;rsquo;s now a requirement.&lt;/p&gt;
&lt;p&gt;Below is what I&amp;rsquo;m using for my deployment.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  unifi-db:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    image: mongo:4.4.25&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    container_name: unifi-db&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    networks:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - traefik_proxy&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    volumes:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data/containers/unifi-db/data:/data/db&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data/containers/unifi-db/initialize/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    restart: unless-stopped&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  unifi-network-application:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    image: lscr.io/linuxserver/unifi-network-application:8.0.7&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    container_name: unifi-network-application&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    hostname: unifi-app&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    depends_on:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - unifi-db&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    networks:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - traefik_proxy&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    ports:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Unifi STUN port&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - 3478:3478/udp&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Required for AP Discovery&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - 10001:10001/udp&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Required for controller to be discoverable on L2 Network&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - 1900:1900/udp&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Required for device communication&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - 8080:8080&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Remote syslog capture&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - 5514:5514/udp&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    environment:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# MongoDB configuration, evaluated on first run&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      MONGO_USER: &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MONGO_DB_USERNAME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      MONGO_PASS: &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MONGO_DB_PASSWORD&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      MONGO_HOST: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi-db&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      MONGO_PORT: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;27017&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      MONGO_DBNAME: &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MONGO_DBNAME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    restart: unless-stopped&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    volumes:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data/containers/unifi-network-application:/config&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    labels:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-http.entrypoints=web&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-http.middlewares=redirect-to-https@file&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-http.rule=Host(`unifi-app.sin.lan`)&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-https.entrypoints=websecure&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-https.rule=Host(`unifi-app.sin.lan`)&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.unifi-network-application-https.loadBalancer.server.port=8443&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.unifi-network-application-https.loadBalancer.server.scheme=https&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-https.middlewares=unifi-network-application-headers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.middlewares.unifi-network-application-headers.headers.customRequestHeaders.Authorization=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.middlewares.unifi-network-application-headers.headers.customRequestHeaders.X-Forwarded-Proto=https&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.serverstransports.unifi-network-application-st.insecureSkipVerify=true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;networks:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  traefik_proxy:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    external: true&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-mongo-requirement&#34;&gt;
  The Mongo Requirement
  &lt;a href=&#34;#the-mongo-requirement&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;So starting off is the MongoDB deployment. Here, I&amp;rsquo;m following the guidance of &lt;a href=&#34;https://docs.linuxserver.io/images/docker-unifi-network-application/?h=unifi+network#setting-up-your-external-database&#34;&gt;linuxserver.io&lt;/a&gt; and configuring Mongo with version &lt;code&gt;4.4.25&lt;/code&gt; as it&amp;rsquo;s document that Unifi Network Application supporting only Mongo &lt;code&gt;3.6.x&lt;/code&gt; to &lt;code&gt;4.4.x&lt;/code&gt; versions. Here I&amp;rsquo;m also specifying an initialization file that will create user for the unifi database.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unifi-db:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  image: mongo:4.4.25&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  container_name: unifi-db&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  networks:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - traefik_proxy&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  volumes:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data/containers/unifi-db/data:/data/db&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data/containers/unifi-db/initialize/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  restart: unless-stopped&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;init-mongo.js&lt;/code&gt; as referenced by linuxserver.io, this create our &lt;code&gt;unifi-user&lt;/code&gt; to connect to the database named &lt;code&gt;unifi&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;db&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getSiblingDB&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;createUser&lt;/span&gt;({&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi-user&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;pwd&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi-password&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;roles&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [{&lt;span style=&#34;color:#a6e22e&#34;&gt;role&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dbOwner&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;db&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi&amp;#34;&lt;/span&gt;}]});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;db&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getSiblingDB&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi_stat&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;createUser&lt;/span&gt;({&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi-user&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;pwd&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi-password&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;roles&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [{&lt;span style=&#34;color:#a6e22e&#34;&gt;role&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dbOwner&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;db&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi_stat&amp;#34;&lt;/span&gt;}]});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In my setup, I have multiple docker-compose files that use a common Network so that containers can talk to each other and use a common Proxy Manager, otherwise each container deployed via docker-compose is potentially isolated to it&amp;rsquo;s own network.&lt;/p&gt;
&lt;p&gt;No ports are exposed here because we don&amp;rsquo;t need to directly access anything ourselves.&lt;/p&gt;
&lt;h2 id=&#34;unifi-network-application&#34;&gt;
  Unifi Network Application
  &lt;a href=&#34;#unifi-network-application&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unifi-network-application:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  image: lscr.io/linuxserver/unifi-network-application:8.0.7&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  container_name: unifi-network-application&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  hostname: unifi-app&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  depends_on:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - unifi-db&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  networks:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - traefik_proxy&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  ports:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Unifi STUN port&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - 3478:3478/udp&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Required for AP Discovery&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - 10001:10001/udp&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Required for controller to be discoverable on L2 Network&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - 1900:1900/udp&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Required for device communication&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - 8080:8080&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Remote syslog capture&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    - 5514:5514/udp&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  environment:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# MongoDB configuration, evaluated on first run&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    MONGO_USER: &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MONGO_DB_USERNAME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    MONGO_PASS: &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MONGO_DB_PASSWORD&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    MONGO_HOST: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unifi-db&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    MONGO_PORT: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;27017&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    MONGO_DBNAME: &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;MONGO_DBNAME&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At the time of this writing, version &lt;code&gt;8.0.7&lt;/code&gt; is the latest. Here we&amp;rsquo;re specifying a dependency on &lt;code&gt;unifi-db&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;My original &lt;code&gt;unifi-controller&lt;/code&gt; deployment exposes the same Ports that are necessary for device communication. However I&amp;rsquo;m not exposing Unifi Guest Portal ports nor mobile throughput test port and finally I&amp;rsquo;m not exposing the Unifi Web Admin Ports (http/https) since I&amp;rsquo;m using Traefik to Proxy the requests so that I don&amp;rsquo;t have to type in a port value in the browser.&lt;/p&gt;
&lt;p&gt;Finally new Docker Environment configurations are included to tell our Unifi Network Application how to connect to the Mongo Database.&lt;/p&gt;
&lt;h2 id=&#34;bonus-traefik-configuration&#34;&gt;
  Bonus Traefik configuration
  &lt;a href=&#34;#bonus-traefik-configuration&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I think most of the Self-Hosted community seems to use Nginx Proxy Manager, but in case you&amp;rsquo;re using &lt;a href=&#34;https://traefik.io/traefik/&#34;&gt;Traefik Proxy&lt;/a&gt; here&amp;rsquo;s what I&amp;rsquo;m using, my Traefik Proxy looks at docker labels to configure the routing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;label&lt;/span&gt;s:&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-http.entrypoints=web&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-http.middlewares=redirect-to-https@file&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-http.rule=Host(`unifi-app.sin.lan`)&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-https.entrypoints=websecure&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-https.rule=Host(`unifi-app.sin.lan`)&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.unifi-network-application-https.loadBalancer.server.port=8443&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.unifi-network-application-https.loadBalancer.server.scheme=https&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-https.middlewares=unifi-network-application-headers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.middlewares.unifi-network-application-headers.headers.customRequestHeaders.Authorization=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.middlewares.unifi-network-application-headers.headers.customRequestHeaders.X-Forwarded-Proto=https&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.serverstransports.unifi-network-application-st.insecureSkipVerify=true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above specifies an &lt;code&gt;http&lt;/code&gt; entrypoint, this is port &lt;code&gt;80&lt;/code&gt;that does a redirect to &lt;code&gt;https&lt;/code&gt; on port &lt;code&gt;443&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Next we&amp;rsquo;re specifying the &lt;code&gt;loadBalancer&lt;/code&gt; port, which specifies the Unifi Web Admin Port &lt;code&gt;8443&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.unifi-network-application-https.loadBalancer.server.port=8443&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;- &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.services.unifi-network-application-https.loadBalancer.server.scheme=https&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So essentially Web Request goes from &lt;code&gt;80&lt;/code&gt; -&amp;gt; &lt;code&gt;443&lt;/code&gt; -&amp;gt; &lt;code&gt;8443&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The Unifi Application handles TLS itself, so we&amp;rsquo;ll include HTTP headers and ignore the TLS cert presented by the Unifi Application.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.routers.unifi-network-application-https.middlewares=unifi-network-application-headers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;- &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.middlewares.unifi-network-application-headers.headers.customRequestHeaders.Authorization=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;- &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.middlewares.unifi-network-application-headers.headers.customRequestHeaders.X-Forwarded-Proto=https&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;- &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;traefik.http.serverstransports.unifi-network-application-st.insecureSkipVerify=true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;deploying-mongo-and-unifi-network-application&#34;&gt;
  Deploying Mongo and Unifi Network Application
  &lt;a href=&#34;#deploying-mongo-and-unifi-network-application&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A simple &lt;code&gt;docker-compose -f unifi.yaml up -d&lt;/code&gt; will start everything.&lt;/p&gt;
&lt;p&gt;Check logs to make sure there&amp;rsquo;s no errors in Mongo&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker logs -f unifi-db
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally check the new Unifi Network Application&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker logs -f unifi-network-application
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If all went well we should see&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;*** Waiting for MONGO_HOST unifi-db to be reachable. ***

Generating 4,096 bit RSA key pair and self-signed certificate (SHA384withRSA) with a validity of 3,650 days

	for: CN=unifi

[custom-init] No custom files found, skipping...

[ls.io-init] done.
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;restoring-the-old-configuration&#34;&gt;
  Restoring the old configuration
  &lt;a href=&#34;#restoring-the-old-configuration&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Now we can navigate to our application in browser and click on &lt;code&gt;Restore Server from a Backup&lt;/code&gt; then click on &lt;code&gt;Upload Backup File&lt;/code&gt; and selecting our &lt;code&gt;.unf&lt;/code&gt; file. Restoring should take a few minutes at most and we&amp;rsquo;ll be redirect to the login page when it&amp;rsquo;s done.
Logging in and we can verify that our previous Unifi AP devices are found and connected.&lt;/p&gt;
&lt;h2 id=&#34;postmortem&#34;&gt;
  Postmortem
  &lt;a href=&#34;#postmortem&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;While migrating to this new deployment is fairly painless, the need for Mongo is an additional overhead that we didn&amp;rsquo;t need previously and as far as I can tell, Unifi Network Application is still generating backup &lt;code&gt;.unf&lt;/code&gt; files in the same &lt;code&gt;autobackup&lt;/code&gt; location, so in terms of backing and restoring in the future, we really only need the &lt;code&gt;.unf&lt;/code&gt; files and mongo database can be discarded without issue, if this changes in the future, I&amp;rsquo;ll update this post to note what we&amp;rsquo;ll be losing without backing up Mongo.&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Initial Commit</title>
      <link>https://huynguyen.me/blog/2023/11/initial-commit/</link>
      <pubDate>Sun, 19 Nov 2023 17:23:58 -0600</pubDate>
      
      <guid>https://huynguyen.me/blog/2023/11/initial-commit/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;This blog has been a long time coming. I think I&amp;rsquo;ve owned this domain for the better part of a decade now. But finally in the year 2023, I think it&amp;rsquo;s time that the internet gets yet another blog.&lt;/p&gt;
&lt;p&gt;For the better part of the last decade, I&amp;rsquo;ve been working in Technical Support Engineering roles and at home I spend a good chunk of my time moonlighting as some psuedo DevOps Engineer, standing up Self-Hosted applications and services within my home network. My goal with this blog is to document the goals and challenges of Self-Hosting and having a Home Lab. With the occasional fun posts on just things I&amp;rsquo;m interested in general such as 3d printing, art, design, tech gear, and much more.&lt;/p&gt;
&lt;p&gt;So I hope you&amp;rsquo;ll hit that bookmark and check me out in the next one.&lt;/p&gt;

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