<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luger Lex Pit-og</title>
    <description>The latest articles on DEV Community by Luger Lex Pit-og (@lugerlogic).</description>
    <link>https://dev.to/lugerlogic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3218475%2F38b682a6-1866-4427-8d6d-99a216bd86a5.jpg</url>
      <title>DEV Community: Luger Lex Pit-og</title>
      <link>https://dev.to/lugerlogic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lugerlogic"/>
    <language>en</language>
    <item>
      <title>[Lab Notes] Kubernetes the Hard Way, For Real This Time (Step 03)</title>
      <dc:creator>Luger Lex Pit-og</dc:creator>
      <pubDate>Thu, 10 Sep 2026 16:04:45 +0000</pubDate>
      <link>https://dev.to/lugerlogic/lab-notes-kubernetes-the-hard-way-for-real-this-time-step-03-3bc2</link>
      <guid>https://dev.to/lugerlogic/lab-notes-kubernetes-the-hard-way-for-real-this-time-step-03-3bc2</guid>
      <description>&lt;p&gt;Continuing my &lt;a href="https://github.com/kelseyhightower/kubernetes-the-hard-way" rel="noopener noreferrer"&gt;Kubernetes the Hard Way&lt;/a&gt; homelab build on Proxmox. Prerequisites and jumpbox setup (&lt;a href="https://dev.to/lugerlogic/lab-notes-kubernetes-the-hard-way-for-real-this-time-steps-01-02-nog"&gt;steps 01-02&lt;/a&gt;) are already done, this covers step 03 only.&lt;/p&gt;

&lt;p&gt;Steps 01 and 02 were straightforward. Well, this one was a reminder that I'm doing this manually. No scripts or AI to automate all of the setup for me. Just me and the guide. And man, even if you have a guide but if you needed to tweak something in your setup. A whole bunch of problems pop up. It goes something like: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Guide says do it this way, but I'm using a different tool, so I do it this way instead. Now something's broken because that tool needed extra config. Now the next step in the guide needs adjusting too."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's like a row of light switches wired together. Flip one, and a few others flip with it. Now you've got to figure out which ones to switch back. But hey, thats exactly how Ops/Infra work is done(to me at least).&lt;/p&gt;

&lt;p&gt;Anyway, here's how it went.&lt;/p&gt;

&lt;h2&gt;
  
  
  Machine database
&lt;/h2&gt;

&lt;p&gt;Created &lt;code&gt;machines.txt&lt;/code&gt; on the jumpbox, listing IP, FQDN, hostname, and pod subnet for each node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="nb"&gt;cat &lt;/span&gt;machines.txt
XXX.XXX.XXX.XXX k8s-solo.home.lab k8s-solo
XXX.XXX.XXX.XXX k8s-solo-w1.home.lab k8s-solo-w1 XXX.XXX.XXX.XXX/24
XXX.XXX.XXX.XXX k8s-solo-w2.home.lab k8s-solo-w2 XXX.XXX.XXX.XXX/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(IPs are masked cuz I'm this 🤏 close to wearing a tin foil hat... even if they're internal IPs)&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH access
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Enabling root login:&lt;/strong&gt; the guide assumes Debian, where root SSH login just needs to be turned on. On Ubuntu, root login is disabled by default too, so the fix was the same. Just edit &lt;code&gt;sshd_config&lt;/code&gt; and restart the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ubuntu@k8s-solo:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/^#*PermitRootLogin.*/PermitRootLogin yes/'&lt;/span&gt; /etc/ssh/sshd_config
ubuntu@k8s-solo:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Generating and distributing keys:&lt;/strong&gt; I originally planned to use root like the guide suggests, but kept hitting a &lt;code&gt;Please login as the user "ubuntu" rather than the user "root" prompt on every node&lt;/code&gt;. I didn't bother digging into it right away, so it wasn't until the end of this step that I actually tracked down why. Ubuntu's cloud images bake a forced command into /root/.ssh/authorized_keys that blocks direct root SSH login and prints that message instead. Rather than fight it, I just switched to the ubuntu user for all admin access. So keys were copied to ubuntu@ on each node instead of &lt;a href="mailto:root@"&gt;root@&lt;/a&gt;. Also used a dedicated keypair instead of overwriting any existing id_rsa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way# ssh-keygen
Enter file &lt;span class="k"&gt;in &lt;/span&gt;which to save the key &lt;span class="o"&gt;(&lt;/span&gt;/root/.ssh/id_rsa&lt;span class="o"&gt;)&lt;/span&gt;: /root/.ssh/id_rsa_kthw

root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;IP FQDN HOST SUBNET&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;ssh-copy-id &lt;span class="nt"&gt;-i&lt;/span&gt; /root/.ssh/id_rsa_kthw.pub ubuntu@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; machines.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verified access to all three nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;IP FQDN HOST SUBNET&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;ssh &lt;span class="nt"&gt;-n&lt;/span&gt; ubuntu@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;hostname
&lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; machines.txt
k8s-solo
k8s-solo-w1
k8s-solo-w2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hostnames
&lt;/h2&gt;

&lt;p&gt;The guide sets each machine's hostname to match its role: &lt;code&gt;server&lt;/code&gt;, &lt;code&gt;node-0&lt;/code&gt;, &lt;code&gt;node-1&lt;/code&gt;. I updated &lt;code&gt;machines.txt&lt;/code&gt; accordingly and ran the rename commands against the &lt;code&gt;ubuntu&lt;/code&gt; user instead of &lt;code&gt;root&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;IP FQDN HOST SUBNET&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sudo sed -i 's/^127.0.1.1.*/127.0.1.1&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FQDN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/' /etc/hosts"&lt;/span&gt;
    ssh &lt;span class="nt"&gt;-n&lt;/span&gt; ubuntu@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CMD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    ssh &lt;span class="nt"&gt;-n&lt;/span&gt; ubuntu@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;hostnamectl set-hostname &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
    ssh &lt;span class="nt"&gt;-n&lt;/span&gt; ubuntu@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart systemd-hostnamed
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; machines.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirmed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;IP FQDN HOST SUBNET&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;ssh &lt;span class="nt"&gt;-n&lt;/span&gt; ubuntu@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;hostname&lt;/span&gt; &lt;span class="nt"&gt;--fqdn&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; machines.txt
server.kubernetes.local
node-0.kubernetes.local
node-1.kubernetes.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;From this point on, the nodes are addressed as &lt;code&gt;server&lt;/code&gt;, &lt;code&gt;node-0&lt;/code&gt;, and &lt;code&gt;node-1&lt;/code&gt; per the guide's convention. Not the earlier &lt;code&gt;k8s-solo&lt;/code&gt; / &lt;code&gt;k8s-solo-w1&lt;/code&gt; / &lt;code&gt;k8s-solo-w2&lt;/code&gt; names.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Host lookup table
&lt;/h2&gt;

&lt;p&gt;No surprises here, followed the guide as-is. Built a &lt;code&gt;hosts&lt;/code&gt; file on the jumpbox and appended it to the jumpbox's own &lt;code&gt;/etc/hosts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# Kubernetes The Hard Way"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; hosts
root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;IP FQDN HOST SUBNET&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FQDN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; hosts
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; machines.txt
root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="nb"&gt;cat &lt;/span&gt;hosts &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verified hostname resolution works locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="k"&gt;for &lt;/span&gt;host &lt;span class="k"&gt;in &lt;/span&gt;server node-0 node-1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;ssh ubuntu@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done
&lt;/span&gt;server
node-0
node-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding &lt;code&gt;/etc/hosts&lt;/code&gt; entries to the remote machines
&lt;/h2&gt;

&lt;p&gt;Had to adjust the guide's command here too, same reason as before (&lt;code&gt;ubuntu&lt;/code&gt; user instead of &lt;code&gt;root&lt;/code&gt;), plus a gotcha with &lt;code&gt;sudo&lt;/code&gt; and output redirection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way# &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;IP FQDN HOST SUBNET&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;scp hosts ubuntu@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:~/
  ssh &lt;span class="nt"&gt;-n&lt;/span&gt; ubuntu@&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"sudo sh -c 'cat hosts &amp;gt;&amp;gt; /etc/hosts'"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; machines.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Interesting nugget of info I learned here:&lt;/strong&gt; &lt;code&gt;sudo somecommand &amp;gt;&amp;gt; file&lt;/code&gt; doesn't work the way you'd expect, &lt;code&gt;sudo&lt;/code&gt; only elevates the command itself, not the &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; redirection. The redirection is set up by your &lt;em&gt;current&lt;/em&gt; shell before &lt;code&gt;sudo&lt;/code&gt; ever runs, so it still tries to write as your regular user. Wrapping the whole thing in &lt;code&gt;sudo sh -c '...'&lt;/code&gt; fixes it, since now the shell doing the redirecting is the one running as root.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Step 03 set up the actual infrastructure: root/admin SSH access between the jumpbox and all three nodes, and consistent hostnames (&lt;code&gt;server&lt;/code&gt;, &lt;code&gt;node-0&lt;/code&gt;, &lt;code&gt;node-1&lt;/code&gt;) so every machine can address the others by name instead of IP.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>proxmox</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
    <item>
      <title>[Lab Notes] Kubernetes the Hard Way, For Real This Time (Steps 01-02)</title>
      <dc:creator>Luger Lex Pit-og</dc:creator>
      <pubDate>Mon, 07 Sep 2026 19:27:17 +0000</pubDate>
      <link>https://dev.to/lugerlogic/lab-notes-kubernetes-the-hard-way-for-real-this-time-steps-01-02-nog</link>
      <guid>https://dev.to/lugerlogic/lab-notes-kubernetes-the-hard-way-for-real-this-time-steps-01-02-nog</guid>
      <description>&lt;p&gt;Following &lt;a href="https://github.com/kelseyhightower/kubernetes-the-hard-way" rel="noopener noreferrer"&gt;Kelsey Hightower's Kubernetes the Hard Way&lt;/a&gt;, but on my own Proxmox homelab. These are my notes on what I did and what's different from the original guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm doing this
&lt;/h2&gt;

&lt;p&gt;As a DevOps engineer, I wanted to actually understand Kubernetes instead of just knowing the commands. My real question going in was: why do we even need Kubernetes? If containers already package and run our apps, isn't that enough?&lt;/p&gt;

&lt;p&gt;My first attempt was to just spin up a cluster with AI/scripts doing most of the work. I provisioned a 1+2 node k3s cluster on this same Proxmox homelab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;k3sup&lt;/code&gt; and &lt;code&gt;kubectl&lt;/code&gt; installed on a WSL workstation&lt;/li&gt;
&lt;li&gt;k3s control plane running on &lt;code&gt;k3s-cp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Both worker nodes joined and healthy&lt;/li&gt;
&lt;li&gt;Cilium CNI v1.19.3 installed, all 3 nodes Ready&lt;/li&gt;
&lt;li&gt;kubeconfig merged and working on the WSL workstation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It worked. But I didn't understand jack of what I built. So I scrapped that and started over with Kubernetes the Hard Way instead, building each piece by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Host&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;OS&lt;/th&gt;
&lt;th&gt;Memory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UbuntuDesktop-Sandbox1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jumpbox&lt;/td&gt;
&lt;td&gt;Ubuntu 22.04 LTS (Jammy)&lt;/td&gt;
&lt;td&gt;16GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;k8s-solo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Controller&lt;/td&gt;
&lt;td&gt;Ubuntu Server 22.04.5 LTS&lt;/td&gt;
&lt;td&gt;4 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;k8s-solo-w1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Worker 1&lt;/td&gt;
&lt;td&gt;Ubuntu Server 22.04.5 LTS&lt;/td&gt;
&lt;td&gt;2 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;k8s-solo-w2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Worker 2&lt;/td&gt;
&lt;td&gt;Ubuntu Server 22.04.5 LTS&lt;/td&gt;
&lt;td&gt;2 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All VMs run on Proxmox. The jumpbox is an existing Ubuntu sandbox VM I already had, repurposed for this project. Static IPs and hostnames are set for all four VMs, and SSH keys are already set up from the jumpbox to all three nodes.&lt;/p&gt;

&lt;p&gt;Topology is 1 controller + 2 workers.&lt;/p&gt;

&lt;h2&gt;
  
  
  01 - Prerequisites
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt; is installed on the jumpbox:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way/downloads#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl version &lt;span class="nt"&gt;--client&lt;/span&gt;
&lt;span class="go"&gt;Client Version: v1.32.3
Kustomize Version: v5.5.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  02 - Jumpbox
&lt;/h2&gt;

&lt;p&gt;Repo cloned to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;span class="go"&gt;/root/kubernetes-the-hard-way
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Binaries downloaded into &lt;code&gt;downloads/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@luger-VirtualBox:~/kubernetes-the-hard-way/downloads#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-ltr&lt;/span&gt;
&lt;span class="go"&gt;total 16
drwxr-xr-x 2 root root 4096 Jan  7  2025 cni-plugins
drwxr-xr-x 2 root root 4096 Sep  7 03:59 controller
drwxr-xr-x 2 root root 4096 Sep  7 03:59 client
drwxr-xr-x 2 root root 4096 Sep  7 03:59 worker
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SSH from the jumpbox to &lt;code&gt;k8s-solo&lt;/code&gt;, &lt;code&gt;k8s-solo-w1&lt;/code&gt;, and &lt;code&gt;k8s-solo-w2&lt;/code&gt; is already working with key-based auth, no passwords.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>proxmox</category>
      <category>devops</category>
      <category>beginners</category>
    </item>
    <item>
      <title>[Quick Notes] "Docker-fying" my Portfolio Website</title>
      <dc:creator>Luger Lex Pit-og</dc:creator>
      <pubDate>Thu, 03 Sep 2026 19:31:04 +0000</pubDate>
      <link>https://dev.to/lugerlogic/quick-notes-docker-fying-my-portfolio-website-anc</link>
      <guid>https://dev.to/lugerlogic/quick-notes-docker-fying-my-portfolio-website-anc</guid>
      <description>&lt;p&gt;&lt;em&gt;Notes to my future self, in plain English.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Was Trying To Do
&lt;/h2&gt;

&lt;p&gt;I already had my portfolio website working on my computer using Hugo and a template for the design. I wanted to package it up in Docker so I could run it the same way anywhere, instead of relying on my machine's setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson 1: Hugo Doesn't Actually "Run" a Website
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When I ran &lt;code&gt;hugo server&lt;/code&gt; on my computer, it felt like a website was "running." But that command is really just a &lt;strong&gt;preview tool&lt;/strong&gt; for editing. It's not meant to be used for real, live traffic.&lt;/li&gt;
&lt;li&gt;The command &lt;code&gt;hugo --minify&lt;/code&gt; does something different: it takes all my content and the template and &lt;strong&gt;converts it into plain files&lt;/strong&gt; — HTML, CSS, images — and dumps them in a folder called &lt;code&gt;public/&lt;/code&gt;. Then it stops. Nothing is left running. It's like exporting a Word doc to PDF — a one-time conversion, not an app that stays open.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So a real website needs two separate things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Something to &lt;strong&gt;build&lt;/strong&gt; the files (Hugo).&lt;/li&gt;
&lt;li&gt;Something to &lt;strong&gt;serve&lt;/strong&gt; those files to visitors (a web server — I used nginx).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's why my Docker setup has two stages.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson 2: The Two-Stage Dockerfile
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;hugomods/hugo:exts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /src&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;hugo &lt;span class="nt"&gt;--minify&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /src/public /usr/share/nginx/html&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nginx", "-g", "daemon off;"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it as two mini-containers glued together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First part:&lt;/strong&gt; a temporary workspace with Hugo installed. It builds my site into plain files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second part:&lt;/strong&gt; a clean, lightweight container with just nginx (the web server). It grabs the finished files from the first part and throws away everything else — no Hugo, no build tools, just the website files and something to hand them out.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Lesson 3: My Template Needed an Extra Build Step
&lt;/h2&gt;

&lt;p&gt;My first build failed. After digging in, the real problem was simple: my Hugo template also needed some JavaScript/CSS tooling (npm) to build properly, and I wasn't running that step. Without it, the template's styling code came up empty and broke the build.&lt;/p&gt;

&lt;p&gt;Fix: install Node.js in the build stage and run the extra setup commands before building the site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;hugomods/hugo:exts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; nodejs npm
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;hugo mod npm pack &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;hugo &lt;span class="nt"&gt;--minify&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /src/public /usr/share/nginx/html&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nginx", "-g", "daemon off;"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; if a template comes with its own JavaScript/CSS setup, I need to run that setup too — Hugo alone won't do it automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson 4: Ports Are Confusing At First
&lt;/h2&gt;

&lt;p&gt;Two separate mistakes here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistake A:&lt;/strong&gt; I typed &lt;code&gt;-p 80:8080&lt;/code&gt;, but Docker's format is &lt;code&gt;-p my_computer_port:container_port&lt;/code&gt;. Nginx inside the container listens on port &lt;code&gt;80&lt;/code&gt;, so the second number always has to be &lt;code&gt;80&lt;/code&gt; — no matter what port I want to use on my own machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistake B:&lt;/strong&gt; Even after fixing that, port &lt;code&gt;80&lt;/code&gt; on my actual computer was already being used by something else. Easiest fix: just pick a different, unused port on my side.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:80 portfolio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; the &lt;code&gt;EXPOSE&lt;/code&gt; line in a Dockerfile is just a note for humans — it doesn't control anything. The real listening port comes from nginx's own settings.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson 5: The &lt;code&gt;/cv&lt;/code&gt; Page Redirect Bug
&lt;/h2&gt;

&lt;p&gt;Visiting &lt;code&gt;mysite.com/cv&lt;/code&gt; sent me somewhere broken.&lt;/p&gt;

&lt;p&gt;Turns out this was expected behavior gone slightly wrong: Hugo saves that page as a folder (&lt;code&gt;/cv/index.html&lt;/code&gt;), so nginx automatically redirects &lt;code&gt;/cv&lt;/code&gt; to &lt;code&gt;/cv/&lt;/code&gt;. That part's normal.&lt;/p&gt;

&lt;p&gt;The bug was that nginx was guessing the wrong port when building that redirect, it assumed port &lt;code&gt;80&lt;/code&gt; (the port &lt;em&gt;inside&lt;/em&gt; the container) instead of &lt;code&gt;8888&lt;/code&gt; (the port I was actually using on my computer). So it sent my browser to the wrong address.&lt;/p&gt;

&lt;p&gt;Fix: tell nginx not to guess the full address, just use a relative path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;absolute_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And load that file into the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; nginx.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Final Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;hugomods/hugo:exts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; nodejs npm
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;hugo mod npm pack &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;hugo &lt;span class="nt"&gt;--minify&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /src/public /usr/share/nginx/html&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; nginx.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nginx", "-g", "daemon off;"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;nginx.conf:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;absolute_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;.dockerignore:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public/
resources/
.git/
node_modules/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;To run it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; portfolio &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:80 portfolio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Short Version, In Plain Words
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hugo builds a website into files. It doesn't keep a website "running" — that's nginx's job.&lt;/li&gt;
&lt;li&gt;A Docker build can use one big toolbox to build something, then hand the finished result to a small, clean container to actually serve it.&lt;/li&gt;
&lt;li&gt;Some templates need an extra JavaScript/CSS setup step — don't skip it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXPOSE&lt;/code&gt; in a Dockerfile is just a label. The real port comes from the app's own settings.&lt;/li&gt;
&lt;li&gt;When mapping ports, the right-hand number always has to match what the app inside is really listening on.&lt;/li&gt;
&lt;li&gt;Redirects inside a container can point to the wrong port if you don't tell the web server to keep them relative.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Quick Notes] Growing My Ubuntu VM's Boot Disk</title>
      <dc:creator>Luger Lex Pit-og</dc:creator>
      <pubDate>Thu, 03 Sep 2026 19:00:47 +0000</pubDate>
      <link>https://dev.to/lugerlogic/quick-notes-growing-my-ubuntu-vms-boot-disk-1d8o</link>
      <guid>https://dev.to/lugerlogic/quick-notes-growing-my-ubuntu-vms-boot-disk-1d8o</guid>
      <description>&lt;p&gt;Made the VM disk bigger and had to tell the OS to actually use the extra space. Took 3 steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Grow the disk (hypervisor side)
&lt;/h2&gt;

&lt;p&gt;Resized the virtual disk in Proxmox/VirtualBox, adding extra space (e.g. +20G). OS doesn't see it yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Grow the partition
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;cloud-guest-utils
&lt;span class="nb"&gt;sudo &lt;/span&gt;growpart /dev/vda 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;growpart&lt;/code&gt; stretches a partition to fill new space.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;3&lt;/code&gt; is the partition number (from &lt;code&gt;lsblk&lt;/code&gt;), not part of the disk name.&lt;/li&gt;
&lt;li&gt;Ignored an unrelated &lt;code&gt;shim-signed&lt;/code&gt; error during install — didn't affect anything.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Grow the filesystem
&lt;/h2&gt;

&lt;p&gt;Checked for LVM first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pvresize /dev/vda3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Got "command not found" → no LVM here, skip it.&lt;/p&gt;

&lt;p&gt;Then resized the filesystem directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;resize2fs /dev/vda3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Use &lt;code&gt;xfs_growfs /&lt;/code&gt; instead if filesystem is XFS, not ext4.)&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Confirm
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Showed full new size. And we're done! No reboot needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cheat sheet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check disk/partitions&lt;/th&gt;
&lt;th&gt;&lt;code&gt;lsblk&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Check filesystem usage&lt;/td&gt;
&lt;td&gt;&lt;code&gt;df -h /&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grow partition&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo growpart /dev/vda 3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grow filesystem (ext4)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo resize2fs /dev/vda3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grow filesystem (XFS)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo xfs_growfs /&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Remember
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Back up/snapshot before resizing.&lt;/li&gt;
&lt;li&gt;"Command not found" on LVM tools = you're not using LVM, that's fine.&lt;/li&gt;
&lt;li&gt;Whole thing can be done live, no reboot.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ubuntu</category>
      <category>linux</category>
      <category>sysadm</category>
      <category>ops</category>
    </item>
    <item>
      <title>[Quick Notes] RDP Into a Proxmox VM Without Opening It Up to the Network</title>
      <dc:creator>Luger Lex Pit-og</dc:creator>
      <pubDate>Thu, 03 Sep 2026 16:08:29 +0000</pubDate>
      <link>https://dev.to/lugerlogic/rdp-into-a-proxmox-vm-without-opening-it-up-to-the-network-52nj</link>
      <guid>https://dev.to/lugerlogic/rdp-into-a-proxmox-vm-without-opening-it-up-to-the-network-52nj</guid>
      <description>&lt;p&gt;I run an Ubuntu Desktop VM on my Proxmox server and wanted to RDP into it  without exposing port 3389 to my whole network. What i ended up with: &lt;strong&gt;tunnel RDP through SSH&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;I already trust my SSH connection to the Proxmox host. So instead of opening RDP up directly, I have SSH secretly carry the RDP traffic for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Laptop] --localhost:3389--&amp;gt; [SSH tunnel] --&amp;gt; [Proxmox host] --3389--&amp;gt; [VM]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My RDP client just connects to &lt;code&gt;localhost:3389&lt;/code&gt; like normal. It has no idea SSH is quietly relaying that traffic all the way to the VM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;VM side: install and run xrdp like usual.&lt;/p&gt;

&lt;p&gt;Laptop side, add this to &lt;code&gt;~/.ssh/config&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;Host&lt;/span&gt; proxmox-rdp
    &lt;span class="k"&gt;HostName&lt;/span&gt; &amp;lt;proxmox-host-ip&amp;gt;
    &lt;span class="k"&gt;User&lt;/span&gt; &amp;lt;your-user&amp;gt;
    &lt;span class="k"&gt;LocalForward&lt;/span&gt; &lt;span class="m"&gt;3389&lt;/span&gt; &amp;lt;VM_IP&amp;gt;:3389
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;LocalForward&lt;/code&gt; line forwards local port 3389 to the VM's port 3389.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting
&lt;/h2&gt;

&lt;p&gt;1.Start the VM in Proxmox.&lt;br&gt;
2.Open the tunnel(ran on my client):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ssh proxmox-rdp &lt;span class="nt"&gt;-N&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(&lt;code&gt;-N&lt;/code&gt; = just forward the port. It'll look frozen. That's normal, just leave it open.)&lt;/p&gt;

&lt;p&gt;3.RDP to &lt;code&gt;localhost:3389&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Close that terminal, tunnel's gone, RDP stops working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bother
&lt;/h2&gt;

&lt;p&gt;Only SSH needs to be exposed, not RDP. All the traffic rides inside SSH's encryption.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch Out For
&lt;/h2&gt;

&lt;p&gt;If the VM's IP is DHCP and changes after a reboot, the &lt;code&gt;LocalForward&lt;/code&gt; line goes stale. Set a static IP or DHCP reservation to avoid this.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>proxmox</category>
      <category>ops</category>
      <category>security</category>
    </item>
    <item>
      <title>[2026] Passed the AWS Certified Security Specialty (SCS-C03)</title>
      <dc:creator>Luger Lex Pit-og</dc:creator>
      <pubDate>Wed, 02 Sep 2026 16:47:26 +0000</pubDate>
      <link>https://dev.to/lugerlogic/2026-passed-the-aws-certified-security-specialty-scs-c03-2dfa</link>
      <guid>https://dev.to/lugerlogic/2026-passed-the-aws-certified-security-specialty-scs-c03-2dfa</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Passed - Score: &lt;strong&gt;831&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frnhyos3foiw4goo7usy2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frnhyos3foiw4goo7usy2.png" alt="Screenshot of SCS Exam Results" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A quick log of how I prepped for and passed the AWS Security Specialty exam.&lt;/p&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevOps/Cloud Engineer&lt;/strong&gt;, 5+ years of experience&lt;/li&gt;
&lt;li&gt;~2-3 years hands-on with AWS&lt;/li&gt;
&lt;li&gt;AWS Certs held before attempting SCS-C03:

&lt;ul&gt;
&lt;li&gt;AWS Certified Solutions Architect - Associate &lt;em&gt;(Oct 2025)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;AWS Certified CloudOps Engineer - Associate &lt;em&gt;(Jan 2026)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So yeah, I already had some XP with AWS and got 2x Associate-level certs before attempting the Security Specialty.&lt;/p&gt;




&lt;h2&gt;
  
  
  Timeline
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;~2 months, on and off&lt;/strong&gt; - Struggled a bit with staying consistent in trying to finish the Udemy Courses. Kept starting and stopping without finishing them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final 3 weeks, locked in&lt;/strong&gt; - Annoyed at my progress with the Udemy Courses, I switched entirely to using Practice Exams. Found it more interactive. This is where things actually clicked and prep became consistent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson learned:&lt;/strong&gt; For a cert like this (with real AWS experience already backing it up), practice-exam prep was far more effective for me.&lt;/p&gt;




&lt;h2&gt;
  
  
  Study Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Primary: Practice Exams
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://portal.tutorialsdojo.com/courses/aws-certified-security-specialty-practice-exams-scs-c03/" rel="noopener noreferrer"&gt;Tutorials Dojo – AWS Certified Security Specialty Practice Exams (SCS-C03)&lt;/a&gt;&lt;/strong&gt;
This was the backbone of my prep, especially in the final 3 weeks. I went ahead and did a consistent grind and review of all the questions. If I made a mistake, I took note of it. Why I was wrong, what the correct answer was. If I still didn't get it, I asked AI to dumb it down until I did. Here's my Practice Exam Logs before actually taking the exam.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Practice Exam&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Randomized Test&lt;/td&gt;
&lt;td&gt;52.31%&lt;/td&gt;
&lt;td&gt;Jul 6, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review Mode Set 1&lt;/td&gt;
&lt;td&gt;75.71%&lt;/td&gt;
&lt;td&gt;Jul 30, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review Mode Set 2&lt;/td&gt;
&lt;td&gt;65.71%&lt;/td&gt;
&lt;td&gt;Aug 1, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review Mode Set 3&lt;/td&gt;
&lt;td&gt;64.62%&lt;/td&gt;
&lt;td&gt;Aug 9, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Randomized Test&lt;/td&gt;
&lt;td&gt;89.23%&lt;/td&gt;
&lt;td&gt;Aug 9, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Randomized Test&lt;/td&gt;
&lt;td&gt;89.23%&lt;/td&gt;
&lt;td&gt;Aug 11, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timed Mode Set 2&lt;/td&gt;
&lt;td&gt;90.77%&lt;/td&gt;
&lt;td&gt;Aug 14, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timed Mode Set 1&lt;/td&gt;
&lt;td&gt;89.23%&lt;/td&gt;
&lt;td&gt;Aug 14, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Supplementary: Video Courses (targeted, not full playthroughs)
&lt;/h3&gt;

&lt;p&gt;Used these reactively. I'd just search a topic on their courses where I was weak at, then watch that. Maarek courses are a given when doing AWS Cert Preps. But Zeal Vora's course, although quite lengthy, was kinda fun to watch. The guy sometimes goes off on tangents and tells anecdotes from his industry experience and how it relates to the topic at hand.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Ultimate AWS Certified Security Specialty [NEW 2026] SCS-C03&lt;/em&gt; — Stephane Maarek&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;[NEW] AWS Certified Security Specialty 2026&lt;/em&gt; — Zeal Vora&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AI-Assisted Deep Dives
&lt;/h3&gt;

&lt;p&gt;So AI obviously is a must nowadays. When I didn't get something, I'd use AI to further break it down, ask follow-up questions, get analogies, or clarify edge cases until it stuck.&lt;/p&gt;

&lt;h3&gt;
  
  
  Staying Motivated
&lt;/h3&gt;

&lt;p&gt;Every time I felt a bit down with my progress, I'd just lurk on the &lt;a href="https://www.reddit.com/r/AWSCertifications/" rel="noopener noreferrer"&gt;r/AWSCertifications&lt;/a&gt; sub. Seeing other folks in the trenches, sharing their prep, posting their pass stories, honestly hit different. Gave me that "if they can do it, so can I" push to lock back in.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Worked
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Practice exams &amp;gt; passive video watching.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Targeted topic review&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI as a tutor&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prior hands-on AWS experience&lt;/strong&gt; made a real difference.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start the practice-exam-heavy approach earlier instead of spending the first ~6 weeks trying to grind through full video courses.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;I already had the hands-on AWS experience. I already had 2x AWS Associate Certs going in. So really, I should've just trusted that and gone straight to practice exams to find my weak spots, instead of grinding through full courses first. &lt;u&gt;This is what worked for me&lt;/u&gt;. If you're already coming in with real AWS experience, don't sleep on practice exams.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>Running Tiny LLMs on Your Local Machine with vLLM + WSL2 (No Cloud Needed!)</title>
      <dc:creator>Luger Lex Pit-og</dc:creator>
      <pubDate>Thu, 03 Jul 2025 16:40:33 +0000</pubDate>
      <link>https://dev.to/lugerlogic/running-tiny-llms-on-your-local-machine-with-vllm-wsl2-no-cloud-needed-5c44</link>
      <guid>https://dev.to/lugerlogic/running-tiny-llms-on-your-local-machine-with-vllm-wsl2-no-cloud-needed-5c44</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“Surely my gaming laptop can handle a 7B model, right?”&lt;br&gt;
— Me, before reality hit me like an OOM error.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So here’s the story: I dove into the world of local LLMs thinking my Lenovo Legion 5i Gaming Laptop—rocking 6GB of VRAM, 32GB of RAM, and a solid Intel i7 CPU could surely handle running a local LLM right? I figured, “Let’s try running Mistral-7B locally. Psssh, what could go wrong?”&lt;/p&gt;

&lt;p&gt;Everything. Everything went wrong.&lt;/p&gt;

&lt;p&gt;The moment I tried, my GPU begged for mercy, RAM usage spiked like it saw a ghost, and the model refused to even load. That's when I realized something important: bigger isn’t always better, especially when it comes to LLMs and local hardware.&lt;/p&gt;

&lt;p&gt;But hey, that failure was a blessing in disguise. It led me to the world of tiny but mighty LLMs—specifically TinyLlama—paired with the vLLM inference engine, which is optimized for performance and memory efficiency. This combo actually works on my hardware, and it might work for yours too.&lt;/p&gt;

&lt;p&gt;If you're in the same boat—curious about LLMs, want to run them locally, but don't have an RTX 4090 lying around—then this guide is for you.&lt;/p&gt;

&lt;p&gt;Let’s get into it. 👇&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bother with Local "Tiny" vLLMs?
&lt;/h2&gt;

&lt;p&gt;Running AI models locally has a lot of benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No OpenAI/HuggingFace API costs&lt;/li&gt;
&lt;li&gt;Full control over the system&lt;/li&gt;
&lt;li&gt;Great for testing, hacking, or even building apps offline&lt;/li&gt;
&lt;li&gt;You learn a LOT more doing it this way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But we're also being realistic here—if you're like me and you're not running an RTX 4090, you need something that fits your hardware. That's why I'm using TinyLlama—a small but capable model—and leveraging vLLM, a super-efficient inference engine built for LLMs.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠 Step-by-Step: How I Set It Up
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Install WSL2&lt;/strong&gt;&lt;br&gt;
First things first, we need WSL2 set up. I didn’t go through the Microsoft Store route—just used good old command line.&lt;/p&gt;

&lt;p&gt;Open PowerShell as Administrator and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wsl --install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That installs WSL2 along with the default Ubuntu distro. If you want a specific Ubuntu version (like 20.04), you can install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wsl --install -d Ubuntu-20.04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot if necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Launch Ubuntu and Prep Your Environment&lt;/strong&gt;&lt;br&gt;
Once Ubuntu is installed, launch it via your Start Menu or run wsl from a terminal. From here, it’s just regular Linux commands.&lt;/p&gt;

&lt;p&gt;Inside Ubuntu, I did the usual system update and installed Python tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y
sudo apt install python3 python3-pip python3-venv -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I set up a Python virtual environment for this project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 -m venv vllm-env
source vllm-env/bin/activate
pip install --upgrade pip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Run vLLM with TinyLlama&lt;/strong&gt;&lt;br&gt;
Now we launch the vLLM API server with TinyLlama. This runs a local OpenAI-compatible endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m vllm.entrypoints.openai.api_server \
  --model TinyLlama/TinyLlama-1.1B-Chat-v1.0 \
  --host 0.0.0.0 \
  --port 8000 \
  --gpu-memory-utilization 0.7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;What these flags mean:&lt;/em&gt;&lt;br&gt;
--model: Specifies the model from Hugging Face&lt;br&gt;
--host 0.0.0.0: Exposes the API to your host machine&lt;br&gt;
--port 8000: Runs it on port 8000&lt;br&gt;
--gpu-memory-utilization 0.7: Only uses 70% of your GPU’s memory (you can tweak this)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing It&lt;/strong&gt;&lt;br&gt;
Once it’s up and running, try hitting the endpoint from your browser or a tool like Postman:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8000/docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use it like the OpenAI API—just pass in your prompt, model name, and get a response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;So yeah—turns out you can run LLMs locally, just don’t expect your laptop to handle a 7B model without crying. TinyLlama + vLLM is a great combo for tinkering and learning without frying your GPU.&lt;/p&gt;

&lt;p&gt;Now that it’s running, I’ll be hacking away at this black-box AI, trying to make it actually follow my prompts—especially when I ask for a specific word count (seriously, why is that so hard?).&lt;/p&gt;

&lt;p&gt;More experiments to come. Stay tuned!&lt;/p&gt;

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