<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Joey Manani: The Blog</title>
    <link>https://blog.joeymanani.com/</link>
    <description>It&#39;s me, your host Joey, and this is an insight into my life and the stuff I get up to</description>
    <pubDate>Sun, 19 Apr 2026 02:14:18 +0000</pubDate>
    <item>
      <title>Upgrading My Network: From Hub-and-Spoke WireGuard to a Full-Mesh Tailscale Setup</title>
      <link>https://blog.joeymanani.com/upgrading-my-network-from-hub-and-spoke-wireguard-to-a-full-mesh-tailscale</link>
      <description>&lt;![CDATA[For the past year, my network looked like one of those &#34;draw the star without lifting your pencil&#34; puzzles… except mine absolutely did lift the pencil. Everything passed through a central WireGuard hub: a hub-and-spoke setup. It worked, technically, but it also felt like driving across town just to talk to your neighbour - pretty slow and annoying.&#xA;&#xA;Switching to Tailscale completely changed the vibe. Suddenly everything could talk to everything else, securely, easily and without the hub getting overwhelmed with switching. &#xA;&#xA;img src=&#34;https://cdn.theflyingrat.com/images/blog/2025-11-30/network.webp&#34; alt=&#34;Hub-and-Spoke vs Mesh Networks&#34;&#xA;Hub-and-Spoke Network (left) vs Full Mesh Network (right) | Joey Manani&#xA;&#xA;!--more--&#xA;&#xA;The Old Setup: Hub-and-Spoke WireGuard&#xA;&#xA;Hub-and-spoke basically means:&#xA;&#xA;Every network node establishes a WireGuard tunnel only to the central hub&#xA;If two spokes want to talk, traffic must route through the hub&#xA;The hub must handle all encryption + forwarding&#xA;No peer-to-peer discovery; everything is statically configured&#xA;Peers basically don&#39;t know of each other&#39;s existence&#xA;&#xA;In practice, this meant:&#xA;&#xA;Devices on the same AP-Isolating LAN had to talk via the hub rather than directly on the LAN. AP-Isolation prevents LAN devices talking entirely (hello apartment Wi-Fi)&#xA;Latency was… BAD&#xA;&#xA;It works, but it’s very &#34;manual oldschool energy.&#34;&#xA;&#xA;The Upgrade: Tailscale Full Mesh&#xA;&#xA;Tailscale flips the entire model on its head. Instead of a rigid hub, you now get a full mesh overlay network:&#xA;&#xA;Every device is a WireGuard peer  &#xA;Peers discover each other automatically using DERP + magic DNS  &#xA;Connections become direct, peer-to-peer, and encrypted  &#xA;If NAT says &#34;no :)&#34;, Tailscale falls back to DERP relay without breaking anything  &#xA;No manual key management!&#xA;&#xA;The coolest part?  &#xA;It&#39;s still WireGuard under the hood - Tailscale just simplifies all of the annoying parts.&#xA;&#xA;Why Full Mesh Is Better&#xA;&#xA;1. Direct Peer-to-Peer Traffic&#xA;&#xA;With Tailscale, remote servers are able to talk to the home server directly and not zigzag through a hub.&#xA;&#xA;Result:&#xA;&#xA;Lower latency&#xA;Lower CPU usage&#xA;Faster file transfers&#xA;Hub doesn&#39;t have to process the same thing twice&#xA;&#xA;2. Automatic Key Management&#xA;&#xA;WireGuard’s biggest pain point basically disappears.&#xA;&#xA;Tailscale handles:&#xA;&#xA;Key distribution  &#xA;Key rotation&#xA;Device onboarding&#xA;Device removal  &#xA;Secure device signing&#xA;Revocation&#xA;&#xA;3. MagicDNS and Stable IPs&#xA;&#xA;Every node gets a stable 100.x address plus a nice readable DNS name:&#xA;&#xA;storage.tsxxxx.net&#xA;raspberrypi.tsxxxx.net&#xA;syncthing.tsxxxx.net&#xA;&#xA;Even if I&#39;m switching networks five times a day, nothing breaks and everything remains accessible.&#xA;&#xA;4. DERP &amp; NAT Traversal&#xA;&#xA;If two nodes can&#39;t reach each other directly (i.e., via CGNAT or an aggressive firewall), Tailscale relays traffic via DERP.&#xA;&#xA;Full mesh + fallback relay means the connection always exist and is very reliable.&#xA;&#xA;5. No More Central Point of Failure&#xA;&#xA;In hub-and-spoke, if the hub died, the entire VPN network died.&#xA;&#xA;This happened once and the TFR network came to a standstill.&#xA;&#xA;With Tailscale, one node disappearing affects only that node.&#xA;&#xA;Huge stability upgrade.&#xA;&#xA;How I Migrated&#xA;&#xA;Removed my WireGuard hub config from all nodes&#xA;Installed Tailscale everywhere:&#xA;&#xA;   Home server  &#xA;   Remote servers&#xA;   NAS  &#xA;   Laptop  &#xA;   Phone  &#xA;   Whatever else I needed&#xA;Enabled subnet routing for certain networks so local LANs are reachable&#xA;Turned on MagicDNS using my own internal DNS server including Ad and Tracker blocking&#xA;Sat back and enjoyed a network that Just Works™&#xA;&#xA;img src=&#34;https://cdn.theflyingrat.com/images/blog/2025-11-30/dns.webp&#34; alt=&#34;Tailscale DNS&#34;&#xA;Tailscale DNS | Joey Manani&#xA;&#xA;Final Thoughts&#xA;&#xA;Switching from a DIY hub-and-spoke WireGuard setup to Tailscale full mesh is gamechanging. Same fundamentals, wildly improved experience.&#xA;&#xA;If you&#39;ve got servers scattered across a few networks, this is the easiest quality-of-life network upgrade you can make.&#xA;&#xA;Everything just works how I like it, and every device knows about each other.&#xA;&#xA;#sysadmin #tailscale #networking #wireguard&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>For the past year, my network looked like one of those “draw the star without lifting your pencil” puzzles… except mine absolutely <em>did</em> lift the pencil. Everything passed through a central WireGuard hub: a hub-and-spoke setup. It worked, technically, but it also felt like driving across town just to talk to your neighbour – pretty slow and annoying.</p>

<p>Switching to Tailscale completely changed the vibe. Suddenly everything could talk to everything else, securely, easily and without the hub getting overwhelmed with switching.</p>

<p><img src="https://cdn.theflyingrat.com/images/blog/2025-11-30/network.webp" alt="Hub-and-Spoke vs Mesh Networks">
<em>Hub-and-Spoke Network (left) vs Full Mesh Network (right) | Joey Manani</em></p>



<h2 id="the-old-setup-hub-and-spoke-wireguard">The Old Setup: Hub-and-Spoke WireGuard</h2>

<p>Hub-and-spoke basically means:</p>
<ul><li>Every network node establishes a WireGuard tunnel only to the central hub</li>
<li>If two spokes want to talk, traffic must route through the hub</li>
<li>The hub must handle all encryption + forwarding</li>
<li>No peer-to-peer discovery; everything is statically configured</li>
<li>Peers basically don&#39;t know of each other&#39;s existence</li></ul>

<p>In practice, this meant:</p>
<ul><li>Devices on the same AP-Isolating LAN had to talk via the hub rather than directly on the LAN. AP-Isolation prevents LAN devices talking entirely (hello apartment Wi-Fi)</li>
<li>Latency was… BAD</li></ul>

<p>It works, but it’s very “manual oldschool energy.”</p>

<h2 id="the-upgrade-tailscale-full-mesh">The Upgrade: Tailscale Full Mesh</h2>

<p>Tailscale flips the entire model on its head. Instead of a rigid hub, you now get a full mesh overlay network:</p>
<ul><li>Every device is a WireGuard peer<br></li>
<li>Peers discover each other automatically using DERP + magic DNS<br></li>
<li>Connections become direct, peer-to-peer, and encrypted<br></li>
<li>If NAT says “no :)“, Tailscale falls back to DERP relay without breaking anything<br></li>
<li>No manual key management!</li></ul>

<p>The coolest part?<br>
It&#39;s still WireGuard under the hood – Tailscale just simplifies all of the annoying parts.</p>

<h2 id="why-full-mesh-is-better">Why Full Mesh Is Better</h2>

<h3 id="1-direct-peer-to-peer-traffic">1. Direct Peer-to-Peer Traffic</h3>

<p>With Tailscale, remote servers are able to talk to the home server directly and not zigzag through a hub.</p>

<p>Result:</p>
<ul><li>Lower latency</li>
<li>Lower CPU usage</li>
<li>Faster file transfers</li>
<li>Hub doesn&#39;t have to process the same thing twice</li></ul>

<h3 id="2-automatic-key-management">2. Automatic Key Management</h3>

<p>WireGuard’s biggest pain point basically disappears.</p>

<p>Tailscale handles:</p>
<ul><li>Key distribution<br></li>
<li>Key rotation</li>
<li>Device onboarding</li>
<li>Device removal<br></li>
<li>Secure device signing</li>
<li>Revocation</li></ul>

<h3 id="3-magicdns-and-stable-ips">3. MagicDNS and Stable IPs</h3>

<p>Every node gets a stable 100.x address plus a nice readable DNS name:</p>

<pre><code>storage.tsxxxx.net
raspberrypi.tsxxxx.net
syncthing.tsxxxx.net
</code></pre>

<p>Even if I&#39;m switching networks five times a day, nothing breaks and everything remains accessible.</p>

<h3 id="4-derp-nat-traversal">4. DERP &amp; NAT Traversal</h3>

<p>If two nodes can&#39;t reach each other directly (i.e., via CGNAT or an aggressive firewall), Tailscale relays traffic via DERP.</p>

<p>Full mesh + fallback relay means the connection always exist and is very reliable.</p>

<h3 id="5-no-more-central-point-of-failure">5. No More Central Point of Failure</h3>

<p>In hub-and-spoke, if the hub died, the entire VPN network died.</p>

<p>This happened once and the TFR network came to a standstill.</p>

<p>With Tailscale, one node disappearing affects only that node.</p>

<p>Huge stability upgrade.</p>

<h2 id="how-i-migrated">How I Migrated</h2>
<ol><li>Removed my WireGuard hub config from all nodes</li>

<li><p>Installed Tailscale everywhere:</p>
<ul><li>Home server<br></li>
<li>Remote servers</li>
<li>NAS<br></li>
<li>Laptop<br></li>
<li>Phone<br></li>
<li>Whatever else I needed</li></ul></li>

<li><p>Enabled subnet routing for certain networks so local LANs are reachable</p></li>

<li><p>Turned on MagicDNS using my own internal DNS server including Ad and Tracker blocking</p></li>

<li><p>Sat back and enjoyed a network that Just Works™</p></li></ol>

<p><img src="https://cdn.theflyingrat.com/images/blog/2025-11-30/dns.webp" alt="Tailscale DNS">
<em>Tailscale DNS | Joey Manani</em></p>

<h2 id="final-thoughts">Final Thoughts</h2>

<p>Switching from a DIY hub-and-spoke WireGuard setup to Tailscale full mesh is gamechanging. Same fundamentals, wildly improved experience.</p>

<p>If you&#39;ve got servers scattered across a few networks, this is the easiest quality-of-life network upgrade you can make.</p>

<p>Everything just works how I like it, and every device knows about each other.</p>

<p><a href="https://blog.joeymanani.com/tag:sysadmin" class="hashtag"><span>#</span><span class="p-category">sysadmin</span></a> <a href="https://blog.joeymanani.com/tag:tailscale" class="hashtag"><span>#</span><span class="p-category">tailscale</span></a> <a href="https://blog.joeymanani.com/tag:networking" class="hashtag"><span>#</span><span class="p-category">networking</span></a> <a href="https://blog.joeymanani.com/tag:wireguard" class="hashtag"><span>#</span><span class="p-category">wireguard</span></a></p>
]]></content:encoded>
      <guid>https://blog.joeymanani.com/upgrading-my-network-from-hub-and-spoke-wireguard-to-a-full-mesh-tailscale</guid>
      <pubDate>Sun, 30 Nov 2025 11:26:29 +0000</pubDate>
    </item>
    <item>
      <title>Understanding POSIX, Unix, and Linux: The Basics</title>
      <link>https://blog.joeymanani.com/understanding-posix-unix-and-linux-the-basics</link>
      <description>&lt;![CDATA[If you&#39;ve ever wondered what terms like POSIX, Unix, and Linux really mean, well, me too! These systems are foundational in computing, especially for developers, system admins, and tech enthusiasts. Here’s a breakdown of each, and why they matter.&#xA;&#xA;!--more--&#xA;&#xA;What is Unix?&#xA;&#xA;Unix is an operating system developed in the 1970s at Bell Labs. It was designed to be simple, stable, and highly portable, which made it a great choice for servers and professional environments. The original Unix code isn’t widely used anymore, but the Unix principles and standards heavily influenced the development of modern OSs. Unix&#39;s main characteristics include:&#xA;&#xA;File System Structure: Unix organises data in a hierarchical file system, starting at a root directory (/). Key directories like /bin, /usr, and /var have specific roles within the Unix system. Everything (including files, executables, devices, etc.) are organised in a tree structure.&#xA;  &#xA;Command-Line Interface (CLI): Unix’s CLI allows users to interact directly with the system using commands like ls (list files) or grep (search text). Shells like a href=&#34;https://tfrs.link/bash&#34; target=&#34;blank&#34;Bash/a or Zsh make scripting and automation in Unix easy.&#xA;&#xA;Multi-User &amp; Multi-Tasking: Unix supports multiple users and processes at once, making it ideal for server environments. Users can control processes and manage system resources directly.&#xA;&#xA;Permissions &amp; Security: Unix systems have a robust permissions model. Each file or folder has specific permissions for the owner, group, and others, ensuring secure access control. &#xA;&#xA;Modularity: Unix follows the &#34;a href=&#34;https://tfrs.link/do-one-thing-and-do-it-well&#34; target=&#34;blank&#34;do one thing and do it well/a&#34; philosophy. Programs are small, focused, and can be combined using pipes (|) to create more complex actions.&#xA;&#xA;What is POSIX?&#xA;&#xA;POSIX (Portable Operating System Interface) is a set of standards established to ensure compatibility across Unix systems. POSIX outlines how operating systems should handle core functions, so that software can run on any compliant system. Key components include:&#xA;&#xA;Standardised APIs: Defines common functions for programming, like reading/writing files, managing processes and handling input/output.&#xA;  &#xA;Shell &amp; Utilities: Specifies standard command-line tools like grep, ls, awk, and sed, and a default shell.&#xA;  &#xA;File System: POSIX sets rules for how files should be stored and managed, including permission systems and directory structures.&#xA;&#xA;POSIX compliance ensures that applications can run across different Unix systems (like Solaris or AIX) and Unix-like systems (like Linux or macOS) without needing major rewrites.&#xA;&#xA;What is Linux?&#xA;&#xA;Linux is a Unix-like operating system that follows many Unix principles but is not derived directly from Unix code. It’s an open-source OS created by Linus Torvalds in the early 1990s. Linux has since grown to power everything from servers to mobile devices. Its key features include:&#xA;&#xA;Open Source: Linux is free and open-source, meaning anyone can modify and distribute it. (See also: a href=&#34;https://tfrs.link/gnu&#34; target=&#34;_blank&#34;GNU/a)&#xA;  &#xA;Versatile: Available in different “distributions” (like Ubuntu, Debian, Fedora, CentOS and many more) tailored for specific use cases — desktop, server, or embedded systems.&#xA;  &#xA;Wide Adoption: Linux powers most web servers, supercomputers, and many IoT devices, making it highly versatile and widely supported.&#xA;&#xA;Why They Matter (tl;dr)&#xA;&#xA;Unix set the foundation for modern operating systems, with POSIX ensuring consistency across them. Linux, while Unix-like, has evolved to become dominant for its adaptability and open-source model. Understanding these systems helps users navigate the world of servers, networking, and software development more effectively.&#xA;&#xA;#blog #linux #comparison #sysadmin #joeymanani]]&gt;</description>
      <content:encoded><![CDATA[<p>If you&#39;ve ever wondered what terms like POSIX, Unix, and Linux really mean, well, me too! These systems are foundational in computing, especially for developers, system admins, and tech enthusiasts. Here’s a breakdown of each, and why they matter.</p>



<h2 id="what-is-unix">What is Unix?</h2>

<p><strong>Unix</strong> is an operating system developed in the 1970s at Bell Labs. It was designed to be simple, stable, and highly portable, which made it a great choice for servers and professional environments. The original Unix code isn’t widely used anymore, but the Unix principles and standards heavily influenced the development of modern OSs. Unix&#39;s main characteristics include:</p>
<ul><li><p><strong>File System Structure</strong>: Unix organises data in a hierarchical file system, starting at a root directory (<code>/</code>). Key directories like <code>/bin</code>, <code>/usr</code>, and <code>/var</code> have specific roles within the Unix system. Everything (including files, executables, devices, etc.) are organised in a tree structure.</p></li>

<li><p><strong>Command-Line Interface (CLI)</strong>: Unix’s CLI allows users to interact directly with the system using commands like <code>ls</code> (list files) or <code>grep</code> (search text). Shells like <a href="https://tfrs.link/bash" target="_blank"><strong>Bash</strong></a> or <strong>Zsh</strong> make scripting and automation in Unix easy.</p></li>

<li><p><strong>Multi-User &amp; Multi-Tasking</strong>: Unix supports multiple users and processes at once, making it ideal for server environments. Users can control processes and manage system resources directly.</p></li>

<li><p><strong>Permissions &amp; Security</strong>: Unix systems have a robust permissions model. Each file or folder has specific permissions for the owner, group, and others, ensuring secure access control.</p></li>

<li><p><strong>Modularity</strong>: Unix follows the “<a href="https://tfrs.link/do-one-thing-and-do-it-well" target="_blank">do one thing and do it well</a>” philosophy. Programs are small, focused, and can be combined using <strong>pipes</strong> (<code>|</code>) to create more complex actions.</p></li></ul>

<h2 id="what-is-posix">What is POSIX?</h2>

<p><strong>POSIX</strong> (Portable Operating System Interface) is a set of standards established to ensure compatibility across Unix systems. POSIX outlines how operating systems should handle core functions, so that software can run on any compliant system. Key components include:</p>
<ul><li><p><strong>Standardised APIs</strong>: Defines common functions for programming, like reading/writing files, managing processes and handling input/output.</p></li>

<li><p><strong>Shell &amp; Utilities</strong>: Specifies standard command-line tools like <code>grep</code>, <code>ls</code>, <code>awk</code>, and <code>sed</code>, and a default shell.</p></li>

<li><p><strong>File System</strong>: POSIX sets rules for how files should be stored and managed, including permission systems and directory structures.</p></li></ul>

<p>POSIX compliance ensures that applications can run across different Unix systems (like Solaris or AIX) and Unix-like systems (like Linux or macOS) without needing major rewrites.</p>

<h2 id="what-is-linux">What is Linux?</h2>

<p><strong>Linux</strong> is a Unix-like operating system that follows many Unix principles but is not derived directly from Unix code. It’s an open-source OS created by Linus Torvalds in the early 1990s. Linux has since grown to power everything from servers to mobile devices. Its key features include:</p>
<ul><li><p><strong>Open Source</strong>: Linux is free and open-source, meaning anyone can modify and distribute it. (See also: <a href="https://tfrs.link/gnu" target="_blank">GNU</a>)</p></li>

<li><p><strong>Versatile</strong>: Available in different “distributions” (like Ubuntu, Debian, Fedora, CentOS and many more) tailored for specific use cases — desktop, server, or embedded systems.</p></li>

<li><p><strong>Wide Adoption</strong>: Linux powers most web servers, supercomputers, and many <strong>IoT</strong> devices, making it highly versatile and widely supported.</p></li></ul>

<h2 id="why-they-matter-tl-dr">Why They Matter (tl;dr)</h2>

<p>Unix set the foundation for modern operating systems, with POSIX ensuring consistency across them. Linux, while Unix-like, has evolved to become dominant for its adaptability and open-source model. Understanding these systems helps users navigate the world of servers, networking, and software development more effectively.</p>

<p><a href="https://blog.joeymanani.com/tag:blog" class="hashtag"><span>#</span><span class="p-category">blog</span></a> <a href="https://blog.joeymanani.com/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a> <a href="https://blog.joeymanani.com/tag:comparison" class="hashtag"><span>#</span><span class="p-category">comparison</span></a> <a href="https://blog.joeymanani.com/tag:sysadmin" class="hashtag"><span>#</span><span class="p-category">sysadmin</span></a> <a href="https://blog.joeymanani.com/tag:joeymanani" class="hashtag"><span>#</span><span class="p-category">joeymanani</span></a></p>
]]></content:encoded>
      <guid>https://blog.joeymanani.com/understanding-posix-unix-and-linux-the-basics</guid>
      <pubDate>Tue, 12 Nov 2024 07:53:38 +0000</pubDate>
    </item>
    <item>
      <title>How to Install Python and VSCode on Windows</title>
      <link>https://blog.joeymanani.com/how-to-install-python-and-vscode-on-windows</link>
      <description>&lt;![CDATA[Want to get started with Python programming? Here’s a quick, step-by-step guide to installing Python and Visual Studio Code (VSCode) on Windows. &#xA;&#xA;div class=&#34;video-container&#34;&#xA;iframe src=&#34;https://www.youtube.com/embed/4uWb6Bo-9fw?si=6JpZW04VCEAyX6Vx&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; allowfullscreen/iframe&#xA;/div&#xA;&#xA;!--more--&#xA;&#xA;Step 1: Download and Install Python&#xA;&#xA;1. Download Python&#xA;Head to the official Python download page.&#xA;You should see a big yellow button labeled &#34;Download Python 3.x.x&#34; (the latest version number). Click it to start the download.&#xA;&#xA;    Python Download Page&#xA;&#xA;2. Install Python&#xA;Open the downloaded installer file.&#xA;Important: Check the box that says &#34;Add Python to PATH&#34;. This makes running Python from the command line easier.&#xA;Choose Install Now and let the installer run.&#xA;Once the installation finishes, click Close.&#xA;&#xA;    Python Installer - Select &#34;Add to PATH&#34;&#xA;&#xA;3. Verify the Installation&#xA;To confirm Python is installed correctly:&#xA;Open Command Prompt (search “cmd” in the Start menu).&#xA;Type python --version and hit Enter.&#xA;    If installed correctly, you should see the Python version number displayed. &#xA;&#xA;    Python Successful Install&#34;&#xA;&#xA;Step 2: Download and Install Visual Studio Code (VSCode)&#xA;&#xA;1. Download VSCode&#xA;Go to the VSCode download page.&#xA;Choose the Windows option to start the download.&#xA;&#xA;    VSCode Download Page&#34;&#xA;&#xA;2. Install VSCode&#xA;Open the downloaded installer file.&#xA;Follow the on-screen instructions, and when you reach the setup screen, check the following boxes:&#xA;   Add &#34;Open with Code&#34; action to Windows Explorer (optional but useful).&#xA;   Add to PATH (recommended for terminal usage).&#xA;Continue with the installation, and when it’s complete, click Finish.&#xA;&#xA;    VSCode Installer Options&#34;&#xA;&#xA;Step 3: Set Up Python in VSCode&#xA;&#xA;1. Open VSCode and Install the Python Extension&#xA;Launch VSCode.&#xA;Go to the Extensions sidebar (click the four-square boxes icon or press Ctrl+Shift+X).&#xA;Search for Python and select the one by Microsoft.&#xA;Click Install to add the Python extension.&#xA;&#xA;    VSCode Download Page&#34;&#xA;&#xA;2. Verify Python Extension in a New File&#xA;Create a new file by clicking File   New File.&#xA;Save it as test.py.&#xA;Type a simple line of code like print(&#34;Hello, Python!&#34;) and save the file.&#xA;&#xA;    VSCode Python Example Script&#34;&#xA;&#xA;3. Run Python Code in VSCode&#xA;Right-click on the code and choose Run Python File in Terminal. This will open a terminal at the bottom of VSCode and execute the code.&#xA;    You should see Hello, Python! printed in the terminal.&#xA;&#xA;    VSCode Python in VSCode Success&#34;&#xA;&#xA;That&#39;s It!&#xA;&#xA;🎉 Congratulations! You now have Python and VSCode fully set up on your Windows computer!&#xA;&#xA;Keep coding, and check back for more guides to improve your development experience.&#xA;&#xA;Further Reading&#xA;&#xA;Why Catching All Exceptions is a Bad Idea in Python&#xA;&#xA;#blog #python #vscode #tutorial #programming #joeymanani&#xA;&#xA;---&#xA;Sidenote&#xA;&#xA;The application I used to simulate the screenshots was the Windows Sandbox - similar to a VM - and can be installed on your host machine in the builtin program Turn Windows features on or off inside of your start menu.&#xA;&#xA;I realised that I can use a href=&#34;https://tfrs.link/ffmpeg&#34; target=&#34;blank&#34;FFmpeg/a to convert PNG screenshots to a href=&#34;https://tfrs.link/webp&#34; target=&#34;blank&#34;WebP/a to compress them and optimize webpage load times. Pretty cool!&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Want to get started with Python programming? Here’s a quick, step-by-step guide to installing Python and Visual Studio Code (VSCode) on Windows.</p>

<div class="video-container">
<iframe src="https://www.youtube.com/embed/4uWb6Bo-9fw?si=6JpZW04VCEAyX6Vx" frameborder="0" allowfullscreen=""></iframe>
</div>



<h2 id="step-1-download-and-install-python">Step 1: Download and Install Python</h2>

<h3 id="1-download-python">1. Download Python</h3>
<ol><li>Head to the official <a href="https://www.python.org/downloads/">Python download page</a>.</li>

<li><p>You should see a big yellow button labeled “<strong>Download Python 3.x.x</strong>” (the latest version number). Click it to start the download.</p>

<p><img src="https://cdn.theflyingrat.com/images/blog/2024-11-08/python-page.webp" alt="Python Download Page"></p></li></ol>

<h3 id="2-install-python">2. Install Python</h3>
<ol><li>Open the downloaded installer file.</li>
<li><strong>Important</strong>: Check the box that says <strong>“Add Python to PATH”</strong>. This makes running Python from the command line easier.</li>
<li>Choose <strong>Install Now</strong> and let the installer run.</li>

<li><p>Once the installation finishes, click <strong>Close</strong>.</p>

<p><img src="https://cdn.theflyingrat.com/images/blog/2024-11-08/python-installer.webp" alt="Python Installer - Select &#34;Add to PATH&#34;"></p></li></ol>

<h3 id="3-verify-the-installation">3. Verify the Installation</h3>

<p>To confirm Python is installed correctly:
1. Open <strong>Command Prompt</strong> (search “cmd” in the Start menu).
2. Type <code>python --version</code> and hit Enter.
    – If installed correctly, you should see the Python version number displayed.</p>

<p>    <img src="https://cdn.theflyingrat.com/images/blog/2024-11-08/python-installation-successful.webp" alt="Python Successful Install&#34;"></p>

<h2 id="step-2-download-and-install-visual-studio-code-vscode">Step 2: Download and Install Visual Studio Code (VSCode)</h2>

<h3 id="1-download-vscode">1. Download VSCode</h3>
<ol><li>Go to the <a href="https://code.visualstudio.com/Download">VSCode download page</a>.</li>

<li><p>Choose the <strong>Windows</strong> option to start the download.</p>

<p><img src="https://cdn.theflyingrat.com/images/blog/2024-11-08/vscode-page.webp" alt="VSCode Download Page&#34;"></p></li></ol>

<h3 id="2-install-vscode">2. Install VSCode</h3>
<ol><li>Open the downloaded installer file.</li>
<li>Follow the on-screen instructions, and when you reach the setup screen, check the following boxes:
<ul><li><strong>Add “Open with Code” action to Windows Explorer</strong> (optional but useful).</li>
<li><strong>Add to PATH</strong> (recommended for terminal usage).</li></ul></li>

<li><p>Continue with the installation, and when it’s complete, click <strong>Finish</strong>.</p>

<p><img src="https://cdn.theflyingrat.com/images/blog/2024-11-08/vscode-installer.webp" alt="VSCode Installer Options&#34;"></p></li></ol>

<h2 id="step-3-set-up-python-in-vscode">Step 3: Set Up Python in VSCode</h2>

<h3 id="1-open-vscode-and-install-the-python-extension">1. Open VSCode and Install the Python Extension</h3>
<ol><li>Launch VSCode.</li>
<li>Go to the <strong>Extensions</strong> sidebar (click the four-square boxes icon or press <code>Ctrl+Shift+X</code>).</li>
<li>Search for <strong>Python</strong> and select the one by Microsoft.</li>

<li><p>Click <strong>Install</strong> to add the Python extension.</p>

<p><img src="https://cdn.theflyingrat.com/images/blog/2024-11-08/vscode-python.webp" alt="VSCode Download Page&#34;"></p></li></ol>

<h3 id="2-verify-python-extension-in-a-new-file">2. Verify Python Extension in a New File</h3>
<ol><li>Create a new file by clicking <strong>File &gt; New File</strong>.</li>
<li>Save it as <code>test.py</code>.</li>

<li><p>Type a simple line of code like <code>print(&#34;Hello, Python!&#34;)</code> and save the file.</p>

<p><img src="https://cdn.theflyingrat.com/images/blog/2024-11-08/vscode-python-script.webp" alt="VSCode Python Example Script&#34;"></p></li></ol>

<h3 id="3-run-python-code-in-vscode">3. Run Python Code in VSCode</h3>
<ol><li><p>Right-click on the code and choose <strong>Run Python File in Terminal</strong>. This will open a terminal at the bottom of VSCode and execute the code.</p>
<ul><li>You should see <code>Hello, Python!</code> printed in the terminal.</li></ul>

<p><img src="https://cdn.theflyingrat.com/images/blog/2024-11-08/vscode-python-success.webp" alt="VSCode Python in VSCode Success&#34;"></p></li></ol>

<h2 id="that-s-it">That&#39;s It!</h2>

<h4 id="congratulations-you-now-have-python-and-vscode-fully-set-up-on-your-windows-computer">🎉 Congratulations! You now have Python and VSCode fully set up on your Windows computer!</h4>

<p>Keep coding, and check back for more guides to improve your development experience.</p>

<h2 id="further-reading">Further Reading</h2>

<h4 id="why-catching-all-exceptions-is-a-bad-idea-in-python-https-blog-joeymanani-com-why-catching-all-exceptions-is-a-bad-idea-in-python"><a href="https://blog.joeymanani.com/why-catching-all-exceptions-is-a-bad-idea-in-python">Why Catching All Exceptions is a Bad Idea in Python</a></h4>

<p><a href="https://blog.joeymanani.com/tag:blog" class="hashtag"><span>#</span><span class="p-category">blog</span></a> <a href="https://blog.joeymanani.com/tag:python" class="hashtag"><span>#</span><span class="p-category">python</span></a> <a href="https://blog.joeymanani.com/tag:vscode" class="hashtag"><span>#</span><span class="p-category">vscode</span></a> <a href="https://blog.joeymanani.com/tag:tutorial" class="hashtag"><span>#</span><span class="p-category">tutorial</span></a> <a href="https://blog.joeymanani.com/tag:programming" class="hashtag"><span>#</span><span class="p-category">programming</span></a> <a href="https://blog.joeymanani.com/tag:joeymanani" class="hashtag"><span>#</span><span class="p-category">joeymanani</span></a></p>

<hr>

<h2 id="sidenote">Sidenote</h2>

<p>The application I used to simulate the screenshots was the <code>Windows Sandbox</code> – similar to a VM – and can be installed on your host machine in the builtin program <code>Turn Windows features on or off</code> inside of your start menu.</p>

<p>I realised that I can use <a href="https://tfrs.link/ffmpeg" target="_blank">FFmpeg</a> to convert PNG screenshots to <a href="https://tfrs.link/webp" target="_blank">WebP</a> to compress them and optimize webpage load times. Pretty cool!</p>
]]></content:encoded>
      <guid>https://blog.joeymanani.com/how-to-install-python-and-vscode-on-windows</guid>
      <pubDate>Fri, 08 Nov 2024 00:04:16 +0000</pubDate>
    </item>
    <item>
      <title>Why Catching All Exceptions is a Bad Idea in Python</title>
      <link>https://blog.joeymanani.com/why-catching-all-exceptions-is-a-bad-idea-in-python</link>
      <description>&lt;![CDATA[When you&#39;re writing Python code, you’ll often need to handle exceptions to ensure your program doesn&#39;t crash unexpectedly. However, catching all exceptions might seem like an easy fix, but it&#39;s actually a bad practice. Here&#39;s why.&#xA;&#xA;Example Python traceback&#xA;Example Python traceback | Joey Manani&#xA;!--more--&#xA;&#xA;1. The Risk of Masking Bugs&#xA;&#xA;One of the most dangerous aspects of catching all exceptions is that you may unintentionally hide bugs in your code. When you use a broad except clause like this:&#xA;&#xA;try:&#xA;    # some risky code that could produce many errors&#xA;except Exception:&#xA;    pass  # Catching all exceptions&#xA;&#xA;You’re ignoring the actual error, which essentially masks what went wrong. If you don’t see the error, how can you fix it? The issue may lie somewhere deeper in your logic, and by swallowing the exception, you&#39;re potentially missing valuable debugging clues as well as providing ambiguous feedback to users about what failed.&#xA;&#xA;2. Makes Debugging Harder&#xA;&#xA;By catching all exceptions, you&#39;re reducing the amount of information you can use to debug your program. In the worst case, a pretty vague except Exception could make you miss critical errors that would be more obvious if they weren’t caught. &#xA;&#xA;You need the ability to identify specific errors and address them in a targeted way. For example, catching specific exceptions such as ValueError, TypeError, or FileNotFoundError gives you better control and clearer insight into the problem.&#xA;&#xA;Example:&#xA;&#xA;Instead of this:&#xA;&#xA;try:&#xA;    # Open a file&#xA;except Exception:&#xA;    pass  # Ignoring all errors&#xA;&#xA;You should handle specific exceptions (yes, you can chain them!):&#xA;&#xA;try:&#xA;    # Open a file&#xA;except FileNotFoundError:&#xA;    print(&#34;The file doesn&#39;t exist!&#34;)&#xA;except IOError:&#xA;    print(&#34;There was an error opening the file!&#34;)&#xA;&#xA;Now, the program provides more useful feedback for when something goes wrong.&#xA;&#xA;3. A False Sense of Security&#xA;&#xA;Catching every exception may create a false sense of security, thinking that you’ve &#34;handled&#34; the errors, but that&#39;s not really the case. When you swallow exceptions, you don&#39;t know how the application behaves under real error conditions. Sometimes, what you&#39;re doing is delaying the problem rather than addressing it directly causing a headache down the line.&#xA;&#xA;Additionally, if the exception is silent, you may not notice issues until they snowball into something bigger, potentially causing bigger failures later.&#xA;&#xA;4. Best Practices for Handling Exceptions&#xA;&#xA;Instead of catching all exceptions, follow these practices:&#xA;&#xA;Catch Specific Exceptions: Always try to handle specific exceptions instead of using a generic except Exception. This gives you better control over the errors you expect.&#xA;&#xA;    Example:&#xA;&#xA;        try:&#xA;        result = 10 / 0&#xA;    except ZeroDivisionError:&#xA;        print(&#34;You can&#39;t divide by zero!&#34;)&#xA;    &#xA;Log the Exceptions: Even if you must catch all exceptions, ensure you log the error somewhere to help with debugging later.&#xA;&#xA;    Example:&#xA;&#xA;        import logging&#xA;&#xA;    try:&#xA;        # Risky code&#xA;    except Exception as e:&#xA;        logging.error(f&#34;An error occurred: {e}&#34;)&#xA;    &#xA;Use Finally for Cleanup: If you need to clean up resources (like closing a file), always use a finally block. This ensures cleanup happens whether or not an exception is raised.&#xA;&#xA;    Example:&#xA;&#xA;        try:&#xA;        # Risky code&#xA;    except ValueError:&#xA;        print(&#34;Oops, something went wrong!&#34;)&#xA;    finally:&#xA;        print(&#34;Cleanup done!&#34;)&#xA;    &#xA;Conclusion&#xA;&#xA;In summary, catching all exceptions is like applying a bandage to a broken leg— it&#39;s not the greatest of solutions, and it may cause more harm than good. By catching specific exceptions and handling them intelligently, you&#39;ll write more robust, debuggable code that enhances the user experience. &#xA;&#xA;#blog #python #programming #joeymanani]]&gt;</description>
      <content:encoded><![CDATA[<p>When you&#39;re writing Python code, you’ll often need to handle exceptions to ensure your program doesn&#39;t crash unexpectedly. However, catching <em>all</em> exceptions might seem like an easy fix, but it&#39;s actually a bad practice. Here&#39;s why.</p>

<p><img src="https://cdn.theflyingrat.com/images/blog/2024-07-11/traceback.webp" alt="Example Python traceback">
<em>Example Python traceback | Joey Manani</em>
</p>

<h2 id="1-the-risk-of-masking-bugs">1. The Risk of Masking Bugs</h2>

<p>One of the most dangerous aspects of catching all exceptions is that you may unintentionally hide bugs in your code. When you use a broad <code>except</code> clause like this:</p>

<pre><code class="language-python">try:
    # some risky code that could produce many errors
except Exception:
    pass  # Catching all exceptions
</code></pre>

<p>You’re ignoring the actual error, which essentially masks what went wrong. If you don’t see the error, how can you fix it? The issue may lie somewhere deeper in your logic, and by swallowing the exception, you&#39;re potentially missing valuable debugging clues as well as providing ambiguous feedback to users about what failed.</p>

<h2 id="2-makes-debugging-harder">2. Makes Debugging Harder</h2>

<p>By catching all exceptions, you&#39;re reducing the amount of information you can use to debug your program. In the worst case, a pretty vague <code>except Exception</code> could make you miss critical errors that would be more obvious if they weren’t caught.</p>

<p>You need the ability to identify specific errors and address them in a targeted way. For example, catching specific exceptions such as <code>ValueError</code>, <code>TypeError</code>, or <code>FileNotFoundError</code> gives you better control and clearer insight into the problem.</p>

<h3 id="example">Example:</h3>

<p>Instead of this:</p>

<pre><code class="language-python">try:
    # Open a file
except Exception:
    pass  # Ignoring all errors
</code></pre>

<p>You should handle specific exceptions (yes, you can chain them!):</p>

<pre><code class="language-python">try:
    # Open a file
except FileNotFoundError:
    print(&#34;The file doesn&#39;t exist!&#34;)
except IOError:
    print(&#34;There was an error opening the file!&#34;)
</code></pre>

<p>Now, the program provides more useful feedback for when something goes wrong.</p>

<h2 id="3-a-false-sense-of-security">3. A False Sense of Security</h2>

<p>Catching every exception may create a false sense of security, thinking that you’ve “handled” the errors, but that&#39;s not really the case. When you swallow exceptions, you don&#39;t know how the application behaves under real error conditions. Sometimes, what you&#39;re doing is delaying the problem rather than addressing it directly causing a headache down the line.</p>

<p>Additionally, if the exception is silent, you may not notice issues until they snowball into something bigger, potentially causing bigger failures later.</p>

<h2 id="4-best-practices-for-handling-exceptions">4. Best Practices for Handling Exceptions</h2>

<p>Instead of catching all exceptions, follow these practices:</p>
<ol><li><p><strong>Catch Specific Exceptions</strong>: Always try to handle specific exceptions instead of using a generic <code>except Exception</code>. This gives you better control over the errors you expect.</p>

<p>Example:</p>

<pre><code class="language-python">try:
    result = 10 / 0
except ZeroDivisionError:
    print(&#34;You can&#39;t divide by zero!&#34;)
</code></pre></li>

<li><p><strong>Log the Exceptions</strong>: Even if you must catch all exceptions, ensure you log the error somewhere to help with debugging later.</p>

<p>Example:</p>

<pre><code class="language-python">import logging

try:
    # Risky code
except Exception as e:
    logging.error(f&#34;An error occurred: {e}&#34;)
</code></pre></li>

<li><p><strong>Use Finally for Cleanup</strong>: If you need to clean up resources (like closing a file), always use a <code>finally</code> block. This ensures cleanup happens whether or not an exception is raised.</p>

<p>Example:</p>

<pre><code class="language-python">try:
    # Risky code
except ValueError:
    print(&#34;Oops, something went wrong!&#34;)
finally:
    print(&#34;Cleanup done!&#34;)
</code></pre></li></ol>

<h2 id="conclusion">Conclusion</h2>

<p>In summary, catching all exceptions is like applying a bandage to a broken leg— it&#39;s not the greatest of solutions, and it may cause more harm than good. By catching specific exceptions and handling them intelligently, you&#39;ll write more robust, debuggable code that enhances the user experience.</p>

<p><a href="https://blog.joeymanani.com/tag:blog" class="hashtag"><span>#</span><span class="p-category">blog</span></a> <a href="https://blog.joeymanani.com/tag:python" class="hashtag"><span>#</span><span class="p-category">python</span></a> <a href="https://blog.joeymanani.com/tag:programming" class="hashtag"><span>#</span><span class="p-category">programming</span></a> <a href="https://blog.joeymanani.com/tag:joeymanani" class="hashtag"><span>#</span><span class="p-category">joeymanani</span></a></p>
]]></content:encoded>
      <guid>https://blog.joeymanani.com/why-catching-all-exceptions-is-a-bad-idea-in-python</guid>
      <pubDate>Thu, 07 Nov 2024 05:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Mayonnaise</title>
      <link>https://blog.joeymanani.com/mayonnaise</link>
      <description>&lt;![CDATA[mayonnaise&#xA;&#xA;That&#39;s the first word I posted to this blog to test if it worked. It does. &#xA;&#xA;In the middle of 2022, I had the ambition to create a blog... From scratch. I had drawn out visual diagrams on how everything would work, listed the tools I would need, and the features I&#39;d want. I still probably have this somewhere, just I can&#39;t be bothered looking for it.&#xA;&#xA;!--more--&#xA;&#xA;Today, I was searching through the a href=&#34;https://tfrs.link/awesome-selfhosted&#34; target=&#34;blank&#34;awesome-selfhosted/a website for some blogging solutions that I could just host myself, and get into writing straight away rather than building a full-scale solution from the ground up.&#xA;&#xA;I found this one. It&#39;s called a href=&#34;https://tfrs.link/writefreely&#34; target=&#34;blank&#34;WriteFreely/a and I think it&#39;s pretty cool.&#xA;&#xA;I was able to deploy this in about 10 minutes to already existing infrastructure. It was really easy to set up. It has a small CLI wizard that takes you through basic configuration, and it allows for reverse proxy-ing straight out of the box. Awesome.&#xA;&#xA;After running Certbot, and adding a DNS record on Cloudflare, it was up. Of course, in my haste, I made a typo in my Nginx configuration file, and spelt the domain as &#34;joeymnanani&#34; instead of &#34;joeymanani&#34;. Luckily, I fixed this after I realised static files weren&#39;t loading.&#xA;&#xA;Now, apparently, it supports Markdown, and if you don&#39;t know what that is, it allows me to do stuff like this:&#xA;&#xA;  📝 Hey, that&#39;s a Markdown feature...&#xA;&#xA;It allows me to customize the post however I choose, allowing me to add text formatting, titles, hyperlinks or even images. I&#39;m impressed.&#xA;&#xA;Anyways, that&#39;s it from me I think. Stay tuned for more, probably...&#xA;&#xA;Yours truly, &#xA;Joey Manani&#xA;&#xA;#tech #blog #joeymanani #sysadmin #writefreely]]&gt;</description>
      <content:encoded><![CDATA[<p>mayonnaise</p>

<p>That&#39;s the first word I posted to this blog to test if it worked. It does.</p>

<p>In the middle of 2022, I had the ambition to create a blog... From scratch. I had drawn out visual diagrams on how everything would work, listed the tools I would need, and the features I&#39;d want. I still probably have this somewhere, just I can&#39;t be bothered looking for it.</p>



<p>Today, I was searching through the <a href="https://tfrs.link/awesome-selfhosted" target="_blank">awesome-selfhosted</a> website for some blogging solutions that I could just host myself, and get into writing straight away rather than building a full-scale solution from the ground up.</p>

<p>I found this one. It&#39;s called <a href="https://tfrs.link/writefreely" target="_blank">WriteFreely</a> and I think it&#39;s pretty cool.</p>

<p>I was able to deploy this in about 10 minutes to already existing infrastructure. It was really easy to set up. It has a small CLI wizard that takes you through basic configuration, and it allows for reverse proxy-ing straight out of the box. Awesome.</p>

<p>After running Certbot, and adding a DNS record on Cloudflare, it was up. Of course, in my haste, I made a typo in my Nginx configuration file, and spelt the domain as “joeymnanani” instead of “joeymanani”. Luckily, I fixed this after I realised static files weren&#39;t loading.</p>

<p>Now, apparently, it supports Markdown, and if you don&#39;t know what that is, it allows me to do stuff like this:</p>

<blockquote><p>📝 Hey, that&#39;s a Markdown feature...</p></blockquote>

<p>It allows me to customize the post however I choose, allowing me to add text formatting, titles, hyperlinks or even images. I&#39;m impressed.</p>

<p>Anyways, that&#39;s it from me I think. Stay tuned for more, probably...</p>

<p>Yours truly,
Joey Manani</p>

<p><a href="https://blog.joeymanani.com/tag:tech" class="hashtag"><span>#</span><span class="p-category">tech</span></a> <a href="https://blog.joeymanani.com/tag:blog" class="hashtag"><span>#</span><span class="p-category">blog</span></a> <a href="https://blog.joeymanani.com/tag:joeymanani" class="hashtag"><span>#</span><span class="p-category">joeymanani</span></a> <a href="https://blog.joeymanani.com/tag:sysadmin" class="hashtag"><span>#</span><span class="p-category">sysadmin</span></a> <a href="https://blog.joeymanani.com/tag:writefreely" class="hashtag"><span>#</span><span class="p-category">writefreely</span></a></p>
]]></content:encoded>
      <guid>https://blog.joeymanani.com/mayonnaise</guid>
      <pubDate>Sun, 03 Nov 2024 08:38:34 +0000</pubDate>
    </item>
  </channel>
</rss>