<?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: Konrad Kądzielawa</title>
    <description>The latest articles on DEV Community by Konrad Kądzielawa (@kkadzielawa).</description>
    <link>https://dev.to/kkadzielawa</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1223741%2F0c00409d-2414-4b93-a7f3-a976afc8b2f7.png</url>
      <title>DEV Community: Konrad Kądzielawa</title>
      <link>https://dev.to/kkadzielawa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kkadzielawa"/>
    <language>en</language>
    <item>
      <title>Post-Mortem: Diagnosing and Fixing Ceph Quorum Breakdown (Time Drift) in a Hybrid Proxmox VE Cluster</title>
      <dc:creator>Konrad Kądzielawa</dc:creator>
      <pubDate>Wed, 25 Mar 2026 21:42:53 +0000</pubDate>
      <link>https://dev.to/kkadzielawa/post-mortem-diagnosing-and-fixing-ceph-quorum-breakdown-time-drift-in-a-hybrid-proxmox-ve-cluster-3d3d</link>
      <guid>https://dev.to/kkadzielawa/post-mortem-diagnosing-and-fixing-ceph-quorum-breakdown-time-drift-in-a-hybrid-proxmox-ve-cluster-3d3d</guid>
      <description>&lt;p&gt;&lt;strong&gt;Key Takeaways &amp;amp; Conclusions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Root Cause:&lt;/strong&gt; A Time Drift between the physical Proxmox host and nested/external virtual machines exceeded Ceph's strict &lt;strong&gt;0.05s&lt;/strong&gt; tolerance limit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impact:&lt;/strong&gt; The time mismatch caused a continuous authorization loop (&lt;code&gt;electing&lt;/code&gt;/&lt;code&gt;probing&lt;/code&gt;) in the local Ceph Monitor (MON), corrupting its local RocksDB database and triggering a cascading failure of the dependent &lt;strong&gt;OSD.0&lt;/strong&gt; daemon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolution:&lt;/strong&gt; Enforced rigorous time synchronization via &lt;strong&gt;Chrony&lt;/strong&gt; and &lt;strong&gt;QEMU Guest Agent&lt;/strong&gt;, followed by a destructive purge and rebuild of the corrupted MON daemon using the surviving quorum.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification:&lt;/strong&gt; Chaos Engineering tests (&lt;code&gt;rados bench&lt;/code&gt;) confirmed that with a &lt;strong&gt;min_size = 2&lt;/strong&gt; replication policy, the cluster successfully survives a hard node power-off without dropping client I/O.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. The Architecture and The Incident
&lt;/h2&gt;

&lt;p&gt;Building a Ceph cluster typically requires dedicated bare-metal servers. My home lab topology, however, is a hybrid 3-node setup designed to simulate a full cluster using limited hardware:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;admin&lt;/strong&gt; (Physical Proxmox host, IP: &lt;code&gt;192.168.0.250&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;admin-02&lt;/strong&gt; (Nested VM 103 on the main host, IP: &lt;code&gt;192.168.0.251&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;admin-03&lt;/strong&gt; (External VM running on a separate Ubuntu desktop, IP: &lt;code&gt;192.168.0.252&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The incident began when the cluster state dropped to &lt;code&gt;HEALTH_WARN&lt;/code&gt;. Despite the underlying Corosync cluster and network layer (ICMP) functioning perfectly across the &lt;code&gt;192.168.0.0/24&lt;/code&gt; subnet, the main physical node (&lt;code&gt;admin&lt;/code&gt;) dropped out of the Ceph quorum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin:~# ceph &lt;span class="nt"&gt;-s&lt;/span&gt;
  cluster:
    &lt;span class="nb"&gt;id&lt;/span&gt;:     25f2d0a2-d64b-42a2-b93d-99a560571e0e
    health: HEALTH_WARN
            1/3 mons down, quorum admin-02,admin-03
            1 osds down
            1 host &lt;span class="o"&gt;(&lt;/span&gt;1 osds&lt;span class="o"&gt;)&lt;/span&gt; down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Debugging &amp;amp; Log Analysis
&lt;/h2&gt;

&lt;p&gt;To find the root cause, I inspected the &lt;code&gt;systemd&lt;/code&gt; journals for the failed Object Storage Daemon (&lt;code&gt;osd.0&lt;/code&gt;) located on the physical &lt;code&gt;admin&lt;/code&gt; host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin:~# journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; ceph-osd@0.service &lt;span class="nt"&gt;-n&lt;/span&gt; 50 &lt;span class="nt"&gt;--no-pager&lt;/span&gt;
Mar 25 21:08:21 admin ceph-osd[3147]: failed to fetch mon config &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--no-mon-config&lt;/span&gt; to skip&lt;span class="o"&gt;)&lt;/span&gt;
Mar 25 21:08:21 admin systemd[1]: ceph-osd@0.service: Main process exited, &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1/FAILURE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The OSD drive itself was physically healthy, but it crashed on startup because it could not retrieve the &lt;a href="https://www.google.com/search?q=https://docs.ceph.com/en/latest/architecture/%23cluster-map" rel="noopener noreferrer"&gt;Cluster Map&lt;/a&gt; from the local Monitor (&lt;code&gt;ceph-mon&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Next, I checked the local Monitor service on the &lt;code&gt;admin&lt;/code&gt; 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@admin:~# journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; ceph-mon@admin.service &lt;span class="nt"&gt;-n&lt;/span&gt; 30 &lt;span class="nt"&gt;--no-pager&lt;/span&gt;
Mar 25 21:49:55 admin ceph-mon[1377]: 2026-03-25T21:49:55.526+0100 7c00b3b756c0 &lt;span class="nt"&gt;-1&lt;/span&gt; mon.admin@0&lt;span class="o"&gt;(&lt;/span&gt;probing&lt;span class="o"&gt;)&lt;/span&gt; e3 get_health_metrics reporting 1 slow ops, oldest is auth&lt;span class="o"&gt;(&lt;/span&gt;proto 0 30 bytes epoch 0&lt;span class="o"&gt;)&lt;/span&gt;
Mar 25 21:50:50 admin ceph-mon[1377]: 2026-03-25T21:50:50.528+0100 7c00b3b756c0 &lt;span class="nt"&gt;-1&lt;/span&gt; mon.admin@0&lt;span class="o"&gt;(&lt;/span&gt;electing&lt;span class="o"&gt;)&lt;/span&gt; e3 get_health_metrics reporting 1 slow ops, oldest is auth&lt;span class="o"&gt;(&lt;/span&gt;proto 0 30 bytes epoch 0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logs revealed the local MON was stuck in an endless &lt;code&gt;electing&lt;/code&gt;/&lt;code&gt;probing&lt;/code&gt; state, constantly dropping cryptographic authorization packets (&lt;code&gt;auth slow ops&lt;/code&gt;). According to &lt;a href="https://www.google.com/search?q=https://docs.ceph.com/en/latest/rados/configuration/mon-config-ref/%23clock" rel="noopener noreferrer"&gt;Ceph's official clock synchronization documentation&lt;/a&gt;, Monitors require clocks to be synchronized within &lt;strong&gt;0.05 seconds&lt;/strong&gt;. Because &lt;code&gt;admin-02&lt;/code&gt; and &lt;code&gt;admin-03&lt;/code&gt; were virtual machines, their CPU clock cycles drifted away from the physical host's hardware clock, effectively locking the &lt;code&gt;admin&lt;/code&gt; node out of the quorum and corrupting its metadata database.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Action Plan: Fixing Time Drift &amp;amp; Rebuilding
&lt;/h2&gt;

&lt;p&gt;To stabilize the cluster, I had to enforce strict timekeeping on the virtual nodes and reconstruct the corrupted Monitor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table: Remediation Steps per Node&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;th&gt;Ceph Role&lt;/th&gt;
&lt;th&gt;Root Cause&lt;/th&gt;
&lt;th&gt;Implemented Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;admin&lt;/strong&gt; (Physical)&lt;/td&gt;
&lt;td&gt;MON, OSD.0&lt;/td&gt;
&lt;td&gt;Corrupted RocksDB&lt;/td&gt;
&lt;td&gt;Destroyed and recreated local MON daemon.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;admin-02&lt;/strong&gt; (VM &lt;strong&gt;103&lt;/strong&gt;)&lt;/td&gt;
&lt;td&gt;MON, OSD.1&lt;/td&gt;
&lt;td&gt;Hypervisor Time Drift&lt;/td&gt;
&lt;td&gt;Installed &lt;strong&gt;QEMU Guest Agent&lt;/strong&gt; for hardware sync.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;admin-03&lt;/strong&gt; (Ext. VM)&lt;/td&gt;
&lt;td&gt;MON, OSD.2&lt;/td&gt;
&lt;td&gt;OS-level Time Drift&lt;/td&gt;
&lt;td&gt;Deployed &lt;strong&gt;Chrony&lt;/strong&gt; to force strict NTP sync.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 1: Enforcing Strict NTP on the External VM (&lt;code&gt;admin-03&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Standard &lt;code&gt;systemd-timesyncd&lt;/code&gt; is too sluggish for Ceph. I replaced it with &lt;code&gt;chrony&lt;/code&gt; and forced an immediate clock step on the external Ubuntu VM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin-03:~# &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;chrony &lt;span class="nt"&gt;-y&lt;/span&gt;
root@admin-03:~# &lt;span class="nb"&gt;sudo &lt;/span&gt;chronyc makestep
root@admin-03:~# chronyc tracking
Reference ID    : C292FB72 &lt;span class="o"&gt;(&lt;/span&gt;host-194-146-251-114.virtuaoperator.pl&lt;span class="o"&gt;)&lt;/span&gt;
Stratum         : 2
System &lt;span class="nb"&gt;time&lt;/span&gt;     : 0.000000000 seconds slow of NTP &lt;span class="nb"&gt;time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output confirmed a &lt;strong&gt;0.000000000 seconds&lt;/strong&gt; deviation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Enabling QEMU Guest Agent (&lt;code&gt;admin-02&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;For the nested Proxmox node, time had to be injected directly from the physical hypervisor. I enabled the QEMU Guest Agent flag, performed a hard power cycle of VM &lt;strong&gt;103&lt;/strong&gt;, and verified the communication channel:&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="c"&gt;# Executed on the physical host (admin)&lt;/span&gt;
root@admin:~# qm &lt;span class="nb"&gt;set &lt;/span&gt;103 &lt;span class="nt"&gt;-agent&lt;/span&gt; 1
root@admin:~# qm shutdown 103
root@admin:~# qm start 103
root@admin:~# qm agent 103 ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Reconstructing the Corrupted Monitor (&lt;code&gt;admin&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;With the time drift neutralized, I had to fix the broken &lt;code&gt;ceph-mon&lt;/code&gt; daemon on the physical host. Attempting to repair a broken RocksDB is often futile. Since the other two nodes maintained a healthy quorum and an intact Cluster Map, I simply purged the broken node and recreated it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin:~# pveceph mon destroy admin
root@admin:~# pveceph mon create
root@admin:~# systemctl restart ceph-osd@0.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Immediately after the restart, &lt;code&gt;osd.0&lt;/code&gt; successfully authenticated with the fresh Monitor, and the cluster began the peering process, eventually returning to &lt;strong&gt;HEALTH_OK&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Verification: Chaos Engineering
&lt;/h2&gt;

&lt;p&gt;You can't trust a storage cluster until you break it while it's under load. To prove the fix worked, I initiated a continuous benchmark write on the &lt;code&gt;ceph-storage&lt;/code&gt; pool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin:~# rados bench &lt;span class="nt"&gt;-p&lt;/span&gt; ceph-storage 120 write &lt;span class="nt"&gt;--no-cleanup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the benchmark was running at &lt;strong&gt;~55 MB/s&lt;/strong&gt;, I executed a brutal &lt;code&gt;sudo systemctl poweroff&lt;/code&gt; on the external &lt;strong&gt;admin-03&lt;/strong&gt; node.&lt;/p&gt;

&lt;p&gt;Here is what happened in the benchmark logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  38       16       419       403   42.4168         0            -     1.12533
  39       16       419       403   41.3292         0            -     1.12533
2026-03-25T22:31:25.378550+0100 min lat: 0.334379 max lat: 3.14551 avg lat: 1.12533
  40       16       419       403   40.2959         0            -     1.12533
  41       16       419       403   39.3131         0            -     1.12533
  42       16       439       423   40.2816         8     0.399663      1.5659
  43       16       470       454   42.2282       124     0.593991      1.5049
  44       16       489       473   42.9956        76     0.755278     1.47177
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Seconds 38-41:&lt;/strong&gt; The moment the node died, the cluster momentarily paused client I/O. Throughput dropped to &lt;strong&gt;0 MB/s&lt;/strong&gt;, and latency spiked.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Second 42+:&lt;/strong&gt; The CRUSH map recalculated the topology. Because the pool was configured with &lt;strong&gt;min_size = 2&lt;/strong&gt;, the two surviving nodes authorized the writes. The cluster automatically resumed operations, quickly catching up and hitting speeds of &lt;strong&gt;124 MB/s&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the test concluded, I cleaned up the benchmark data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin:~# rados &lt;span class="nt"&gt;-p&lt;/span&gt; ceph-storage cleanup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; Time synchronization is the absolute lifeblood of Ceph. Never trust default virtual machine clocks in a production or simulated lab environment. By implementing &lt;code&gt;chrony&lt;/code&gt; and QEMU hardware sync, the cluster is now fully immune to node-level failures.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ceph</category>
      <category>proxmox</category>
    </item>
    <item>
      <title>Proxmox &amp; Ceph in a Home Lab: Building a Cluster from a Single Drive &amp; Surviving the CLI Battle</title>
      <dc:creator>Konrad Kądzielawa</dc:creator>
      <pubDate>Mon, 23 Mar 2026 19:58:21 +0000</pubDate>
      <link>https://dev.to/kkadzielawa/proxmox-ceph-in-a-home-lab-building-a-cluster-from-a-single-drive-surviving-the-cli-battle-4f6a</link>
      <guid>https://dev.to/kkadzielawa/proxmox-ceph-in-a-home-lab-building-a-cluster-from-a-single-drive-surviving-the-cli-battle-4f6a</guid>
      <description>&lt;p&gt;Building a &lt;a href="https://pve.proxmox.com/pve-docs/chapter-pveceph.html" rel="noopener noreferrer"&gt;Ceph cluster on Proxmox VE&lt;/a&gt; in a home lab is a fantastic proving ground. The catch is that Ceph is inherently a powerful Enterprise-grade system – and by default, it demands &lt;a href="https://docs.ceph.com/en/latest/start/hardware-recommendations/" rel="noopener noreferrer"&gt;entire, raw physical drives (raw block devices)&lt;/a&gt; for its OSD (Object Storage Daemon) daemons.&lt;/p&gt;

&lt;p&gt;But what if your "IT Bunker" only has one physical server with a single extra 111 GB SSD, and you want to simulate a full-fledged 3-node cluster? My architecture looked like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;admin&lt;/strong&gt; (Physical Proxmox host)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;admin-02&lt;/strong&gt; (Nested VM on the main server)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;admin-03&lt;/strong&gt; (VM... running remotely on a separate desktop PC)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the story of how I "cheated" Ceph's strict mechanics, sliced a single drive into pieces, bypassed hypervisor GUI errors, and ultimately achieved the coveted &lt;code&gt;HEALTH_OK&lt;/code&gt; status.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge 1: Handing an LVM Partition over to Ceph
&lt;/h2&gt;

&lt;p&gt;My plan was to split the physical &lt;code&gt;sdc&lt;/code&gt; (111.8 GB) drive on the main server into three 35 GB logical volumes using &lt;a href="https://wiki.debian.org/LVM" rel="noopener noreferrer"&gt;LVM (Logical Volume Manager)&lt;/a&gt;. Here is the &lt;code&gt;lsblk&lt;/code&gt; output from the main host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sdc                            111.8G LVM2_member disk 
├─vg_ceph_lab-ceph_admin          35G             lvm  
└─vg_ceph_lab-ceph_admin02        35G             lvm  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first node (&lt;code&gt;admin&lt;/code&gt;) took its piece without a hitch. The trouble started when I tried to add an OSD for the second node (&lt;code&gt;admin-02&lt;/code&gt;) via the main host's CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin:~# pveceph osd create /dev/vg_ceph_lab/ceph_admin
unable to get device info &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'/dev/dm-6'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Proxmox and Ceph hate shared LVM paths and standard partitions when creating an OSD. Since &lt;code&gt;admin-02&lt;/code&gt; is a virtual machine, I leveraged the built-in &lt;a href="https://www.google.com/search?q=%5Bhttps://pve.proxmox.com/pve-docs/qm.1.html%5D(https://pve.proxmox.com/pve-docs/qm.1.html)" rel="noopener noreferrer"&gt;QEMU/KVM Virtual Machine Manager (&lt;code&gt;qm&lt;/code&gt;) tool&lt;/a&gt;. Instead of fighting Ceph daemons on the host, I attached the virtual volume directly into the &lt;code&gt;admin-02&lt;/code&gt; VM, bypassing the filesystem layer entirely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qm &lt;span class="nb"&gt;set &lt;/span&gt;103 &lt;span class="nt"&gt;-scsi2&lt;/span&gt; /dev/vg_ceph_lab/ceph_admin02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the &lt;code&gt;admin-02&lt;/code&gt; VM, the OS saw new, "physical", and raw block hardware. A quick click on &lt;em&gt;Create OSD&lt;/em&gt; in the node's Proxmox GUI, and the drive initialized perfectly!&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge 2: An External Host and a Rebellious virt-manager
&lt;/h2&gt;

&lt;p&gt;That left the third node: &lt;code&gt;admin-03&lt;/code&gt;. The problem? This VM physically resided on my Linux Desktop PC across the room. The &lt;code&gt;qm set&lt;/code&gt; command was useless here because the sliced LVM volume was on the server in the rack.&lt;/p&gt;

&lt;p&gt;In a cluster architecture, Ceph doesn't care where the physical storage comes from. I decided to ditch the server's LVM for this node and create a new virtual disk locally on my PC. But trying to add a disk via the &lt;a href="https://virt-manager.org/" rel="noopener noreferrer"&gt;virt-manager GUI&lt;/a&gt; threw a hardware incompatibility error: &lt;code&gt;pc-q35-noble&lt;/code&gt;. The graphical interface completely refused to cooperate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; When the GUI throws weird exceptions, the terminal is your best friend. I fell back on native tools from the &lt;a href="https://libvirt.org/docs.html" rel="noopener noreferrer"&gt;libvirt&lt;/a&gt; and QEMU stack.&lt;/p&gt;

&lt;p&gt;First, I manually generated the disk file using &lt;a href="https://www.google.com/search?q=%5Bhttps://qemu-project.gitlab.io/qemu/tools/qemu-img.html%5D(https://qemu-project.gitlab.io/qemu/tools/qemu-img.html)" rel="noopener noreferrer"&gt;&lt;code&gt;qemu-img&lt;/code&gt;&lt;/a&gt;:&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;qemu-img create &lt;span class="nt"&gt;-f&lt;/span&gt; qcow2 /var/lib/libvirt/images/admin-03-ceph.qcow2 35G
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I hard-attached the generated image to the offline VM configuration using &lt;code&gt;virsh&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;&lt;span class="nb"&gt;sudo &lt;/span&gt;virsh attach-disk Proxmox-Lab /var/lib/libvirt/images/admin-03-ceph.qcow2 vdb &lt;span class="nt"&gt;--config&lt;/span&gt; &lt;span class="nt"&gt;--subdriver&lt;/span&gt; qcow2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon booting &lt;code&gt;admin-03&lt;/code&gt;, its internal Proxmox system recognized the &lt;code&gt;/dev/vdb&lt;/code&gt; drive. Adding the third OSD in the Proxmox GUI worked flawlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finale: Pools, Replication, and Green Status
&lt;/h2&gt;

&lt;p&gt;After adding the third OSD, I had a "Frankenstein" cluster: drives supplied by raw LVM from a physical server mixed with a remote &lt;code&gt;qcow2&lt;/code&gt; virtual disk. Did Ceph care? Not at all.&lt;/p&gt;

&lt;p&gt;The final step was to create a &lt;a href="https://docs.ceph.com/en/latest/rados/operations/pools/" rel="noopener noreferrer"&gt;Ceph Pool&lt;/a&gt;—the logical organizational layer where the actual data lands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Size: 3&lt;/strong&gt; (Every data block is replicated in 3 copies).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Min. Size: 2&lt;/strong&gt; (The cluster allows I/O writes as long as at least 2 out of 3 nodes are active).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CLI verification (on the main node) showed exactly what I had been fighting for all evening:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin:~# ceph &lt;span class="nt"&gt;-s&lt;/span&gt;
  cluster:
    &lt;span class="nb"&gt;id&lt;/span&gt;:     25f2d0a2-d64b-42a2-b93d-99a560571e0e
    health: HEALTH_OK

  services:
    mon: 3 daemons, quorum admin,admin-02,admin-03 &lt;span class="o"&gt;(&lt;/span&gt;age 6m&lt;span class="o"&gt;)&lt;/span&gt;
    mgr: admin&lt;span class="o"&gt;(&lt;/span&gt;active, since 60m&lt;span class="o"&gt;)&lt;/span&gt;, standbys: admin-02, admin-03
    osd: 3 osds: 3 up &lt;span class="o"&gt;(&lt;/span&gt;since 6m&lt;span class="o"&gt;)&lt;/span&gt;, 3 &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;since 6m&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check the &lt;a href="https://docs.ceph.com/en/latest/rados/operations/crush-map/" rel="noopener noreferrer"&gt;CRUSH (Controlled Replication Under Scalable Hashing)&lt;/a&gt; algorithm tree using the &lt;code&gt;ceph osd tree&lt;/code&gt; command to confirm the cluster topology:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@admin:~# ceph osd tree
ID  CLASS WEIGHT   TYPE NAME         STATUS  REWEIGHT  PRI-AFF
&lt;span class="nt"&gt;-1&lt;/span&gt;         0.10258 root default                      
&lt;span class="nt"&gt;-3&lt;/span&gt;         0.03419     host admin                     
 0   hdd  0.03419         osd.0          up   1.00000  1.00000
&lt;span class="nt"&gt;-5&lt;/span&gt;         0.03419     host admin-02                  
 1   hdd  0.03419         osd.1          up   1.00000  1.00000
&lt;span class="nt"&gt;-7&lt;/span&gt;         0.03419     host admin-03                  
 2   hdd  0.03419         osd.2          up   1.00000  1.00000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, Ceph's intelligent engine sees my crafted nodes as separate physical &lt;code&gt;hosts&lt;/code&gt; and correctly distributes the traffic, providing me with a single, unified &lt;code&gt;rbd&lt;/code&gt; (RADOS Block Device) storage pool labeled &lt;code&gt;ceph-storage&lt;/code&gt; in Proxmox.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Home lab experiments quickly expose the gap between dry documentation theory and actual implementations in simulated environments. This deployment taught me two key lessons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Understanding how to pass storage resources through the hypervisor (like the &lt;code&gt;qm set&lt;/code&gt; tool in PVE) is a game changer when Ceph insists on block access and you only have LVM partitions available.&lt;/li&gt;
&lt;li&gt; When GUI software (like desktop &lt;code&gt;virt-manager&lt;/code&gt; in my case) throws motherboard configuration errors, going back to the basics and pure CLI (&lt;code&gt;virsh&lt;/code&gt;, &lt;code&gt;qemu-img&lt;/code&gt;) lets you bypass those issues in just a few quick commands.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With a fully functioning, green cluster, I am ready for the next level: Chaos Engineering. I plan to disconnect drives while VMs are running just to see if my Ceph setup is truly as resilient as the documentation promises!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ceph</category>
      <category>proxmox</category>
    </item>
    <item>
      <title>DNS Troubleshooting on Windows: When the Internet Works but the Intranet Doesn’t</title>
      <dc:creator>Konrad Kądzielawa</dc:creator>
      <pubDate>Fri, 20 Mar 2026 12:10:01 +0000</pubDate>
      <link>https://dev.to/kkadzielawa/dns-troubleshooting-on-windows-when-the-internet-works-but-the-intranet-doesnt-1459</link>
      <guid>https://dev.to/kkadzielawa/dns-troubleshooting-on-windows-when-the-internet-works-but-the-intranet-doesnt-1459</guid>
      <description>&lt;p&gt;One of the more frustrating problems in IT is when a user says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The internet works, but this one internal site doesn’t.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first, it sounds simple. Public websites load fine. Email works. Teams works. But the internal app still refuses to open, or it loads painfully slowly.&lt;/p&gt;

&lt;p&gt;In situations like that, the application itself is not always the real problem. Quite often, the issue is one layer lower: DNS.&lt;/p&gt;

&lt;p&gt;That is also why I think DNS is worth understanding in a practical way, not just as a protocol you read about once and then forget. In day-to-day admin work, name resolution problems show up more often than people expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  A very typical scenario
&lt;/h2&gt;

&lt;p&gt;Let’s take a neutral example.&lt;/p&gt;

&lt;p&gt;A user tries to open:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://intranet-app01/portal&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;What they see is something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the page does not open at all, or takes too long to load,&lt;/li&gt;
&lt;li&gt;public websites still work,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nslookup intranet-app01&lt;/code&gt; returns an IP address,&lt;/li&gt;
&lt;li&gt;but the internal application still behaves as if something is wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At that point, it is very tempting to say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If &lt;code&gt;nslookup&lt;/code&gt; works, DNS is fine.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I used to think that too in simpler cases. But in real environments, that conclusion is often too optimistic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;nslookup&lt;/code&gt; helps — but does not always tell the full story
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/nslookup" rel="noopener noreferrer"&gt;&lt;code&gt;nslookup&lt;/code&gt;&lt;/a&gt; is still a useful tool. It is quick, simple, and good for checking what a DNS server returns for a given name.&lt;/p&gt;

&lt;p&gt;The catch is that a successful &lt;code&gt;nslookup&lt;/code&gt; result does &lt;strong&gt;not always mean the client is resolving names cleanly in real use&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Microsoft’s own &lt;a href="https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/troubleshoot-dns-client-resolution-issues" rel="noopener noreferrer"&gt;DNS client troubleshooting guide&lt;/a&gt; shows why this matters. If a machine has multiple DNS servers configured and some of them are unreachable, Windows may still eventually resolve the name — but only after retries and timeouts. From the user’s point of view, that can look like “the app is slow” or “the site is broken,” even though DNS eventually returns an answer.&lt;/p&gt;

&lt;p&gt;So when I troubleshoot DNS now, I try not to stop at:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Does the name resolve?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How does it resolve, from where, and how long does it take?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How Windows actually resolves a name
&lt;/h2&gt;

&lt;p&gt;One detail I find especially useful from Microsoft’s &lt;a href="https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/troubleshoot-dns-client-resolution-issues" rel="noopener noreferrer"&gt;troubleshooting article&lt;/a&gt; is that Windows does not immediately send every query to a DNS server.&lt;/p&gt;

&lt;p&gt;The client typically goes through these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;check the local DNS cache&lt;/li&gt;
&lt;li&gt;check the &lt;code&gt;Hosts&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;query the DNS server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That means a “correct” answer is not always coming from the place you think it is.&lt;/p&gt;

&lt;p&gt;Sometimes the client is using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an old cached entry,&lt;/li&gt;
&lt;li&gt;a negative cache result,&lt;/li&gt;
&lt;li&gt;or a static entry in the &lt;code&gt;Hosts&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So even when name resolution appears to work, it is still worth asking whether you are looking at live DNS behavior or just local state.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple workflow I usually follow
&lt;/h2&gt;

&lt;p&gt;When an internal hostname behaves strangely, I try not to jump between random fixes. I usually go through a short set of checks in the same order.&lt;/p&gt;

&lt;p&gt;It does not solve every case, but it helps narrow things down quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Check the client’s DNS configuration
&lt;/h3&gt;

&lt;p&gt;I usually start with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ipconfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/all&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives me a quick view of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which DNS servers are configured,&lt;/li&gt;
&lt;li&gt;in what order,&lt;/li&gt;
&lt;li&gt;and whether anything looks off right away.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I see multiple DNS servers, I want to know whether all of them are still reachable. Microsoft notes in its &lt;a href="https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/troubleshoot-dns-client-resolution-issues" rel="noopener noreferrer"&gt;DNS troubleshooting guide&lt;/a&gt; that unreachable DNS servers can introduce noticeable delays because the client keeps trying before moving on.&lt;/p&gt;

&lt;p&gt;That is one of those things that can make an application feel broken even though the underlying name eventually resolves.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Compare the default result with a specific DNS server
&lt;/h3&gt;

&lt;p&gt;Next, I usually run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;nslookup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;intranet-app01&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;nslookup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;intranet-app01.corp.example&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;192.0.2.53&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command tells me what happens with the machine’s default DNS configuration.&lt;/p&gt;

&lt;p&gt;The second helps remove some ambiguity, because I am querying a specific DNS server directly.&lt;/p&gt;

&lt;p&gt;According to the official &lt;a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/nslookup" rel="noopener noreferrer"&gt;&lt;code&gt;nslookup&lt;/code&gt; documentation&lt;/a&gt;, you can provide the DNS server explicitly in non-interactive mode, which makes this a useful comparison step.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Test the same name with &lt;code&gt;Resolve-DnsName&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;After that, I often repeat the test in PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Resolve-DnsName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;intranet-app01.corp.example&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Resolve-DnsName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;intranet-app01.corp.example&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;192.0.2.53&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Microsoft’s &lt;a href="https://learn.microsoft.com/en-us/powershell/module/dnsclient/resolve-dnsname?view=windowsserver2025-ps" rel="noopener noreferrer"&gt;&lt;code&gt;Resolve-DnsName&lt;/code&gt; documentation&lt;/a&gt; describes it as functionally similar to &lt;code&gt;nslookup&lt;/code&gt;, and I find it really useful when I want clearer, more structured output.&lt;/p&gt;

&lt;p&gt;It is especially helpful when I want to compare answers from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the default client path,&lt;/li&gt;
&lt;li&gt;and a specific DNS server I actually trust for that zone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This does not automatically fix anything, of course, but it helps answer a more precise question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is the issue really DNS, or is it the path the client is taking to get the answer?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Inspect the local DNS cache
&lt;/h3&gt;

&lt;p&gt;If the results still feel inconsistent, I check the local resolver cache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ipconfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/displaydns&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Microsoft’s &lt;a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig" rel="noopener noreferrer"&gt;&lt;code&gt;ipconfig&lt;/code&gt; reference&lt;/a&gt; explains that &lt;code&gt;/displaydns&lt;/code&gt; shows the DNS resolver cache, including entries loaded from the local &lt;code&gt;Hosts&lt;/code&gt; file and recently resolved records.&lt;/p&gt;

&lt;p&gt;I like this step because it helps explain a lot of confusing cases.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;maybe the client is not querying DNS at all anymore,&lt;/li&gt;
&lt;li&gt;maybe it is holding on to an old result,&lt;/li&gt;
&lt;li&gt;maybe there is a local entry that makes the test misleading.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Flush the cache if I suspect stale local state
&lt;/h3&gt;

&lt;p&gt;If I think the cache might be part of the problem, I clear it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ipconfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/flushdns&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, this is documented by Microsoft in the &lt;a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig" rel="noopener noreferrer"&gt;&lt;code&gt;ipconfig&lt;/code&gt; command reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I would not treat this as a magic fix, because it is not. But it is a reasonable troubleshooting step when I want to remove stale local state before testing again.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Check whether the short name is the real issue
&lt;/h3&gt;

&lt;p&gt;This is probably one of the most common things behind “it works for some people but not for others.”&lt;/p&gt;

&lt;p&gt;Users often type:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://intranet-app01&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;instead of:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://intranet-app01.corp.example&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That difference matters more than it seems.&lt;/p&gt;

&lt;p&gt;Microsoft’s &lt;a href="https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/troubleshoot-dns-client-resolution-issues" rel="noopener noreferrer"&gt;DNS troubleshooting guide&lt;/a&gt; includes examples showing how the DNS suffix search list can affect resolution time and behavior. If the suffix list is long, badly ordered, or just not aligned with the environment, short-name resolution can become slow or inconsistent.&lt;/p&gt;

&lt;p&gt;So sometimes the problem is not that DNS is “down.”&lt;/p&gt;

&lt;p&gt;Sometimes the problem is simply that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the short name is ambiguous,&lt;/li&gt;
&lt;li&gt;the client is trying the wrong suffixes first,&lt;/li&gt;
&lt;li&gt;or the right answer only shows up after too many failed attempts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What usually turns out to be wrong
&lt;/h2&gt;

&lt;p&gt;In many environments, DNS is not completely broken.&lt;/p&gt;

&lt;p&gt;It is just &lt;strong&gt;slow, inconsistent, or slightly misleading&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In practice, I have found that the most common causes are things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the primary DNS server is unreachable,&lt;/li&gt;
&lt;li&gt;DNS servers are configured in a bad order,&lt;/li&gt;
&lt;li&gt;the client is using a cached result,&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;Hosts&lt;/code&gt; file contains an override,&lt;/li&gt;
&lt;li&gt;users rely on short names instead of FQDNs,&lt;/li&gt;
&lt;li&gt;the DNS suffix search list is too long or poorly ordered,&lt;/li&gt;
&lt;li&gt;or the application is simply less tolerant of delays than a browser is.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why I try not to stop at “&lt;code&gt;nslookup&lt;/code&gt; works.”&lt;/p&gt;

&lt;p&gt;That statement may be true and still not explain the user’s experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question I actually want to answer
&lt;/h2&gt;

&lt;p&gt;When I troubleshoot something like this, I am not really asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Does the name resolve?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I am usually asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How is the client resolving it, what is it talking to first, and where is the delay happening?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That small shift in thinking helps a lot.&lt;/p&gt;

&lt;p&gt;It turns troubleshooting from random guessing into a more predictable workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick checklist I like to keep in mind
&lt;/h2&gt;

&lt;p&gt;Here is the short version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. ipconfig /all
2. nslookup shortname
3. nslookup FQDN &amp;lt;specific_DNS_server&amp;gt;
4. Resolve-DnsName -Name FQDN
5. Resolve-DnsName -Name FQDN -Server &amp;lt;specific_DNS_server&amp;gt;
6. ipconfig /displaydns
7. ipconfig /flushdns
8. test the FQDN instead of the short name
9. review DNS server order and suffix search list
10. only then move deeper into the application itself
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;A lot of DNS issues do not look like DNS issues at first.&lt;/p&gt;

&lt;p&gt;They look like browser problems, application issues, random network instability, or “something weird on this one computer.”&lt;/p&gt;

&lt;p&gt;But sometimes the underlying cause is much simpler than that:&lt;/p&gt;

&lt;p&gt;the client is asking the wrong place, in the wrong order, for too long.&lt;/p&gt;

&lt;p&gt;That is why I try to troubleshoot DNS methodically instead of jumping straight into random fixes. It saves time, and it usually makes the actual problem easier to explain — both to yourself and to the user who just wants the internal site to work again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;If you want to dig a bit deeper, these official Microsoft references are worth bookmarking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/nslookup" rel="noopener noreferrer"&gt;&lt;code&gt;nslookup&lt;/code&gt; command reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/powershell/module/dnsclient/resolve-dnsname?view=windowsserver2025-ps" rel="noopener noreferrer"&gt;&lt;code&gt;Resolve-DnsName&lt;/code&gt; PowerShell documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig" rel="noopener noreferrer"&gt;&lt;code&gt;ipconfig&lt;/code&gt; command reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/troubleshoot-dns-client-resolution-issues" rel="noopener noreferrer"&gt;Troubleshoot DNS client name resolution issues&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>dns</category>
      <category>microsoft</category>
      <category>networking</category>
    </item>
    <item>
      <title>Building a Zero-Maintenance SysOps Knowledge Base with React and the Dev.to API</title>
      <dc:creator>Konrad Kądzielawa</dc:creator>
      <pubDate>Wed, 18 Feb 2026 12:25:24 +0000</pubDate>
      <link>https://dev.to/kkadzielawa/building-a-zero-maintenance-sysops-knowledge-base-with-react-and-the-devto-api-36lp</link>
      <guid>https://dev.to/kkadzielawa/building-a-zero-maintenance-sysops-knowledge-base-with-react-and-the-devto-api-36lp</guid>
      <description>&lt;p&gt;After spending nearly a decade navigating different areas of IT—from building complex e-commerce frontends to managing the underlying Linux servers and infrastructure—I decided it was time to completely rebuild my personal portfolio.&lt;/p&gt;

&lt;p&gt;My old website was full of typical "frontend fireworks": heavy animations, flashy graphics, and complex layouts. But as my career naturally shifted towards IT Systems Administration and infrastructure management, that style no longer resonated with my daily work. I wanted a space that felt like home to a SysOps engineer: raw, minimalist, and terminal-inspired.&lt;/p&gt;

&lt;p&gt;However, as an admin, I had a strict set of requirements for this new platform:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero maintenance:&lt;/strong&gt; I don't want to deal with database backups or traditional CMS panels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No local Markdown files:&lt;/strong&gt; Pushing a commit to GitHub just to fix a typo in a blog post is an overkill that breaks the writing flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Source of Truth:&lt;/strong&gt; I want to write technical notes once and have them automatically distribute to my community profile and my personal website.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The solution? &lt;strong&gt;Using the Dev.to API as a free, headless CMS for a React Single Page Application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is a technical breakdown of how I designed this architecture&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Fetching the Data (The API Layer)
&lt;/h2&gt;

&lt;p&gt;Dev.to provides a fantastic, mostly undocumented perk for developers: a public, read-only API that returns your articles in JSON format. &lt;/p&gt;

&lt;p&gt;Instead of hardcoding data, my React app fetches the article list directly from my Dev.to profile upon initialization. To prevent unnecessary network requests and ensure a 0ms load time when navigating back and forth, I implemented a simple in-memory cache outside the component lifecycle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Global cache for instant UI rendering&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cachedArticles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DevToArticle&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MainAdmin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setArticles&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DevToArticle&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cachedArticles&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cachedArticles&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cachedArticles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[https://dev.to/api/articles?username=kkadzielawa](https://dev.to/api/articles?username=kkadzielawa)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setArticles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nx"&gt;cachedArticles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Cache the response&lt;/span&gt;
          &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&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;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="c1"&gt;// ... render logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Dynamic Tag Filtering
&lt;/h2&gt;

&lt;p&gt;Since the Dev.to API returns an array of tags (&lt;code&gt;tag_list&lt;/code&gt;) for each article, I didn't need to build a custom taxonomy system. I simply extract all unique tags dynamically from the fetched payload and generate a terminal-like filter menu &lt;code&gt;[ #linux ]&lt;/code&gt;, &lt;code&gt;[ #docker ]&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The "Optimistic UI" Trick
&lt;/h2&gt;

&lt;p&gt;One downside of the &lt;code&gt;/articles&lt;/code&gt; list endpoint is that it doesn't return the full Markdown body of the posts. To get the content, you have to make a second request to &lt;code&gt;/articles/{id}&lt;/code&gt; when the user clicks on a specific note.&lt;/p&gt;

&lt;p&gt;To prevent the annoying "layout shift" and loading spinners, I used React Router's &lt;code&gt;state&lt;/code&gt; to pass the title of the article from the main list directly to the reader component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; 
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/note/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
  &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Pass the title forward!&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to this, the note viewer immediately renders the title and structure, while the actual Markdown body stream loads discreetly in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Rendering Markdown with Syntax Highlighting
&lt;/h2&gt;

&lt;p&gt;Once the API returns the &lt;code&gt;body_markdown&lt;/code&gt;, it needs to be safely parsed into HTML. Since this is a SysOps blog, code snippets must look flawless. I combined &lt;code&gt;react-markdown&lt;/code&gt; with &lt;code&gt;react-syntax-highlighter&lt;/code&gt; using the VS Code Dark Plus theme for a native IDE feel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactMarkdown&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-markdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Prism&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SyntaxHighlighter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-syntax-highlighter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;vscDarkPlus&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-syntax-highlighter/dist/esm/styles/prism&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Inside the render function:&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReactMarkdown&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;code&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/language-&lt;/span&gt;&lt;span class="se"&gt;(\w&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SyntaxHighlighter&lt;/span&gt;
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;vscDarkPlus&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;PreTag&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"div"&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SyntaxHighlighter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"inline-code"&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ReactMarkdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By treating Dev.to as a completely touchless, headless CMS, I achieved a perfect &lt;strong&gt;Separation of Concerns&lt;/strong&gt;. Dev.to handles the database, image hosting, SEO, and the writing experience. My React application acts purely as a customized, terminal-themed presentation layer.&lt;/p&gt;

&lt;p&gt;My personal portfolio updates automatically. That's the exact kind of automation every IT Admin loves.&lt;/p&gt;

&lt;p&gt;Now, whenever I want to drop some technical meat (like a new Linux configuration or securing a server environment), I just hit "Publish" on Dev.to, and it's instantly live.&lt;/p&gt;

&lt;p&gt;Check out the live result at &lt;a href="https://kadzielawa.dev" rel="noopener noreferrer"&gt;kadzielawa.dev&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Server-Side Rendering (SSR) vs. Client-Side Rendering (CSR): The Fascinating World of Page Rendering</title>
      <dc:creator>Konrad Kądzielawa</dc:creator>
      <pubDate>Fri, 01 Dec 2023 15:28:31 +0000</pubDate>
      <link>https://dev.to/kkadzielawa/server-side-rendering-ssr-vs-client-side-rendering-csr-the-fascinating-world-of-page-rendering-2fba</link>
      <guid>https://dev.to/kkadzielawa/server-side-rendering-ssr-vs-client-side-rendering-csr-the-fascinating-world-of-page-rendering-2fba</guid>
      <description>&lt;p&gt;The choice between Server-Side Rendering (SSR) and Client-Side Rendering (CSR) is not just a technological decision. It's like choosing between classic art and modern cinema - each has its unique characteristics and hidden treasures to discover.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server-Side Rendering (SSR): Classical Elegance
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Advantages of SSR:&lt;/strong&gt;&lt;br&gt;
SEO Magic: With SSR, your website is like a well-written book, easy to find and read by search engines.&lt;br&gt;
Fast First Impression: SSR delivers content quickly, like an express courier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages of SSR:&lt;/strong&gt;&lt;br&gt;
Heavier Server Load: SSR is a bit like working full-time for the server - it requires continuous attention and resources.&lt;/p&gt;

&lt;p&gt;SSR is like visiting an elegant, classical art gallery, where each artwork is carefully prepared and presented with attention to detail. In SSR, every website is like a finely crafted painting, ready to be admired immediately upon entry. This approach combines solidity and reliability, offering users and search engines complete, ready-to-consume content. As a result, SSR pages are like well-tailored suits: stylish, professional, and always in good taste, perfectly suited for the world of SEO and making a fast first impression.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.google.com/search?q=Server-side+rendering" rel="noopener noreferrer"&gt;Discover the secrets of SSR.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Client-Side Rendering (CSR): Modern Theater of Interaction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Advantages of CSR:&lt;/strong&gt;&lt;br&gt;
Mastery of Interaction: CSR is like a director who adapts the scene to the audience's mood - dynamic and full of surprises.&lt;br&gt;
Server Resource Savings: It's like remote work for the server - fewer loads, more flexibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages of CSR:&lt;/strong&gt;&lt;br&gt;
SEO Puzzle: For search engines, CSR pages can sometimes be like a complicated puzzle.&lt;br&gt;
CSR is nothing but entering a modern theater of interaction, where each scene is created live, in response to the viewer's actions. CSR is like a dynamic, improvised performance in which the website's content unfolds and evolves in real-time in the user's browser. It's a world where interactivity and adaptability play the lead roles, and the website is constantly in motion, like a crowd in a bustling city center. CSR brings what is most modern and exciting in web development – a site that not only responds but dances to the user's rhythm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.google.com/search?q=client+side+rendering" rel="noopener noreferrer"&gt;Immerse yourself in the world of CSR.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Blending Dimensions: Hybrid Rendering Techniques
&lt;/h2&gt;

&lt;p&gt;Using hybrid rendering methods is like the art of culinary fusion, where the chef combines traditional ingredients with modern cooking techniques to create surprising and complex dishes. In the world of web development, hybrid approaches blend the solidity and reliability of SSR with the flexibility and dynamism of CSR, creating unique "dishes" in the digital space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Innovation in technology:&lt;/strong&gt; Tools like Next.js for React are redefining the frameworks in which developers create web experiences. By combining the fast loading and SEO optimization offered by SSR with the reactivity and rich interactions of CSR, hybrid approaches create platforms that are both efficient and engaging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting IT fact:&lt;/strong&gt; Using hybrid approaches in web design is like balancing between two worlds. Developers can decide which elements of the website are best rendered on the server-side and which on the client-side, similar to how a chef decides when to combine classic techniques with modern ones for the best effect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; Hybrid rendering techniques open up new possibilities in web development, allowing for the creation of websites that combine the best features of both worlds. Just as in culinary art, where the combination of old and new techniques creates amazing dishes, in web design, combining SSR and CSR creates unforgettable digital experiences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br&gt;
The choice between SSR and CSR is not just a technical decision. It's a choice between two different ways of storytelling on the internet - one old and proven, and the other new and exciting. Understanding their unique features and benefits allows for the creation of better, more engaging websites.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Programming in 2033 – Vision of the Future of Software Development</title>
      <dc:creator>Konrad Kądzielawa</dc:creator>
      <pubDate>Fri, 01 Dec 2023 15:20:47 +0000</pubDate>
      <link>https://dev.to/kkadzielawa/programming-in-2033-vision-of-the-future-of-software-development-2bbb</link>
      <guid>https://dev.to/kkadzielawa/programming-in-2033-vision-of-the-future-of-software-development-2bbb</guid>
      <description>&lt;p&gt;In the last decade, the world of technology has undergone a metamorphosis, and software development has become a part of an exciting future. In 2033, the work of programmers is full of extraordinary experiences, seeming like something out of fantasy from years past, which we could only dream of not too long ago. Let's contemplate what their reality looks like... let's delve into this future, discovering the latest innovations and futuristic trends in technology.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code-Generating Algorithms:&lt;/strong&gt;&lt;br&gt;
In the year 2033, programmers have become supervisors and process engineers, having long delegated some tasks to advanced code-generating algorithms. Thanks to advanced tools, programmers exclusively use a thought interface to communicate with artificial intelligence systems that create and optimize code according to their intentions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#Example: A programmer thinks about a function to add two numbers.&lt;br&gt;
Text = "Create a function that adds two numbers."&lt;br&gt;
AI.create_code(text)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.blog/2023-04-14-how-generative-ai-is-changing-the-way-developers-work/" rel="noopener noreferrer"&gt;Discover how AI is changing programming.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The World of Cybersecurity:&lt;/strong&gt;&lt;br&gt;
In an era full of advanced hackers and AI, the importance of cybersecurity has reached its zenith. Programmers are now cyber-wizards, using tools based on neural algorithms to defend our digital worlds against constantly evolving threats.&lt;/p&gt;

&lt;p&gt;Cybersecurity in 2033 is not just about fighting threats; it's also about the art of predicting potential attacks through predictive analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cybriant.com/top-cyber-security-websites-of-2022/" rel="noopener noreferrer"&gt;Explore the latest trends in cybersecurity.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Ubiquity of Clouds and Quantum Computing:&lt;/strong&gt;&lt;br&gt;
A key element of a programmer's work in 2033 is cloud computing and solutions based on quantum computing. Programmers use such computers to solve problems that were once thought impossible to solve in a traditional way. Serverless and microservices solutions have become the norm, requiring programmers to have the skills to manage complex, distributed systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bluexp.netapp.com/blog/cvo-blg-the-future-of-cloud-computing-5-trends-you-must-know-about" rel="noopener noreferrer"&gt;Get to know the future of the cloud.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Virtual and Augmented Reality in Everyday Work:&lt;/strong&gt;&lt;br&gt;
Programmers in 2033 use VR and AR technologies not only for design but also as their daily work tools. Using thought interfaces, they design three-dimensional software models that can be "touched" and edited in virtual space.&lt;/p&gt;

&lt;p&gt;In the world of VR, programmers work within their projects, moving through virtual spaces to solve problems and test applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.toptal.com/designers/ui/vr-ar-design-guide" rel="noopener noreferrer"&gt;Immerse yourself in the world of VR/AR for programmers.&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;The Blossoming of Soft Skills:&lt;/strong&gt;&lt;br&gt;
In an era where machines handle technical details, soft skills have become a key asset for programmers. Communication, creativity, and the ability to work in teams are essential for developing innovative solutions.&lt;/p&gt;

&lt;p&gt;Programmers participate in simulations of customer interactions to refine their soft skills and understand user needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.comptia.org/career-change/exploring-it/skills-for-it" rel="noopener noreferrer"&gt;Learn more about soft skills in IT.&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Never-ending Education:&lt;/strong&gt;&lt;br&gt;
In 2033, learning knows no bounds. Programmers are eternal students, using interactive learning interfaces that enable them to quickly grasp the latest technologies and concepts.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#Example: An interactive AI-based learning interface.&lt;br&gt;
AI.learn("New_Technology")&lt;br&gt;
AI.connect_with_mentor("Name Surname")&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://teambuilding.com/blog/online-learning-platforms" rel="noopener noreferrer"&gt;Check out the best educational platforms for programmers.&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
The work of programmers in 2033 is an exciting journey into the future, full of interactions with intelligent algorithms, quantum computing, virtual worlds, and continuous learning. It's a world where humans and machines collaborate to create innovative solutions that transform the face of technological reality. Artificial intelligence, cloud solutions, VR/AR, and cybersecurity play crucial roles. This evolution of the profession demonstrates how adaptability and the ability to learn are essential in a dynamically changing world of technology.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
