<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://freaky2112.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://freaky2112.github.io/" rel="alternate" type="text/html" /><updated>2026-10-08T00:23:49+00:00</updated><id>https://freaky2112.github.io/feed.xml</id><title type="html">Freaky’s Homelab</title><subtitle>Telecom tech by day, homelab hacker by night. Linux, Docker, self-hosting &amp; endless tinkering.</subtitle><author><name>Freaky</name></author><entry><title type="html">Turning a Raspberry Pi Into a Sleek Home Assistant Kiosk</title><link href="https://freaky2112.github.io/blog/2026/10/07/HA-Kiosk-mode-blog/" rel="alternate" type="text/html" title="Turning a Raspberry Pi Into a Sleek Home Assistant Kiosk" /><published>2026-10-07T00:00:00+00:00</published><updated>2026-10-07T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/10/07/HA-Kiosk-mode-blog</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/10/07/HA-Kiosk-mode-blog/"><![CDATA[<h1 id="turning-a-raspberry-pi-into-a-sleek-home-assistant-kiosk">Turning a Raspberry Pi Into a Sleek Home Assistant Kiosk</h1>

<p>Ever wanted a dedicated touchscreen on the wall to control your smart home?</p>

<p>A Raspberry Pi combined with a touchscreen makes a great <strong>Home Assistant wall panel</strong>. With a little configuration, the Pi can boot automatically, launch directly into Home Assistant, hide the mouse cursor, and stay running as a dedicated touchscreen dashboard.</p>

<p>The goal is simple:</p>

<p><strong>Power on → Raspberry Pi boots → Chromium launches → Home Assistant appears in full-screen kiosk mode.</strong></p>

<p>No keyboard, no mouse, and no desktop to interact with.</p>

<h2 id="1-flash-the-operating-system">1. Flash the Operating System</h2>

<p>Start by installing <strong>Raspberry Pi OS with Desktop</strong> onto the Raspberry Pi’s SD card.</p>

<p>Using the Raspberry Pi Imager makes this part straightforward.</p>

<p>Once the Pi boots, configure it for:</p>

<ul>
  <li>Desktop environment</li>
  <li>Automatic login</li>
  <li>Correct touchscreen/display settings</li>
  <li>Network connectivity</li>
</ul>

<p>The important part is enabling <strong>Desktop Autologin</strong> so the Raspberry Pi can start the graphical environment without requiring someone to log in manually.</p>

<p>After the initial setup, reboot the Pi and make sure the desktop loads automatically.</p>

<h2 id="2-install-the-required-software">2. Install the Required Software</h2>

<p>The kiosk doesn’t need much software.</p>

<p>The main components are:</p>

<h3 id="chromium">Chromium</h3>

<p>Chromium is responsible for displaying the Home Assistant dashboard.</p>

<p>Instead of using the browser like a normal desktop application, it will eventually launch directly in <strong>Kiosk Mode</strong>.</p>

<h3 id="unclutter">Unclutter</h3>

<p>Unclutter hides the mouse cursor after a short period of inactivity.</p>

<p>This is especially useful for a wall-mounted touchscreen where you don’t want a mouse pointer sitting over your dashboard.</p>

<h2 id="3-create-the-kiosk-startup-script">3. Create the Kiosk Startup Script</h2>

<p>The next step is creating a small startup script that handles the kiosk launch.</p>

<p>The script has three main jobs:</p>

<ul>
  <li>Prevent the display from going to sleep.</li>
  <li>Hide the mouse cursor.</li>
  <li>Launch Chromium in full-screen kiosk mode.</li>
</ul>

<p>The browser is configured to open directly to the Home Assistant dashboard.</p>

<p>For example, instead of starting on a normal browser homepage, the Raspberry Pi goes straight to your Home Assistant instance.</p>

<p><strong>The result:</strong></p>

<p><strong>Raspberry Pi Desktop → Kiosk Script → Chromium → Home Assistant</strong></p>

<p>No desktop interaction is required.</p>

<h2 id="4-start-the-kiosk-automatically">4. Start the Kiosk Automatically</h2>

<p>A kiosk isn’t very useful if you have to manually start it every time the Raspberry Pi reboots.</p>

<p>To solve this, create a <strong>systemd user service</strong> that starts the kiosk script when the graphical desktop session becomes available.</p>

<p>The service can also be configured to restart automatically if Chromium unexpectedly closes.</p>

<p>This gives the kiosk a simple recovery mechanism:</p>

<p><strong>Power failure → Raspberry Pi reboots → Desktop loads → Kiosk starts → Home Assistant appears</strong></p>

<p>This makes the setup much more suitable for a permanent wall-mounted installation.</p>

<h2 id="5-configure-home-assistant-for-kiosk-mode">5. Configure Home Assistant for Kiosk Mode</h2>

<p>The Raspberry Pi can already display Home Assistant in full screen, but the Home Assistant interface itself can still contain navigation elements.</p>

<p>For a cleaner wall-panel experience, install <strong>Kiosk Mode through HACS</strong>.</p>

<p>This can remove elements such as:</p>

<ul>
  <li>Sidebar</li>
  <li>Header</li>
  <li>Navigation controls</li>
  <li>Other unnecessary interface elements</li>
</ul>

<p>The result is a much cleaner dashboard designed specifically for a dedicated touchscreen.</p>

<p>Instead of looking like a website running inside a browser, it starts to feel more like a <strong>purpose-built smart-home control panel</strong>.</p>

<h2 id="6-design-the-touchscreen-dashboard">6. Design the Touchscreen Dashboard</h2>

<p>With the kiosk running, the final step is designing the Home Assistant dashboard.</p>

<p>For a wall-mounted display, keep things simple.</p>

<p>Large buttons and cards work much better than tiny controls.</p>

<p>Some useful sections could include:</p>

<ul>
  <li>💡 Lights</li>
  <li>🌡️ Temperature</li>
  <li>🚪 Doors</li>
  <li>🔒 Security</li>
  <li>🎵 Music</li>
  <li>🌤️ Weather</li>
  <li>⚡ Energy</li>
  <li>🏠 Home status</li>
</ul>

<p>The goal isn’t to put every Home Assistant entity on the screen.</p>

<p>The goal is to make the most important controls available with a quick tap.</p>

<h2 id="7-the-final-result">7. The Final Result</h2>

<p>After everything is configured, the Raspberry Pi becomes a dedicated <strong>Home Assistant wall panel</strong>.</p>

<p>There is no need to manually open a browser or navigate to Home Assistant.</p>

<p>Simply turn it on.</p>

<p><strong>Boot → Auto Login → Kiosk → Home Assistant</strong></p>

<p>And that’s it.</p>

<p>The Raspberry Pi is now a permanent touchscreen interface for the smart home.</p>

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

<p>This is one of those homelab projects that doesn’t require a huge amount of hardware or software but produces a really nice result.</p>

<p>A Raspberry Pi, touchscreen, and a few lightweight configuration changes can turn into a polished-looking <strong>Home Assistant control panel</strong>.</p>

<p>It also has the advantage of being easy to recover. If the Pi loses power or needs to reboot, the kiosk can automatically come back online without requiring manual intervention.</p>

<p>For a smart home, that’s exactly what you want.</p>

<p><strong>Power it on and forget about it.</strong></p>

<hr />

<h3 id="project-overview">Project Overview</h3>

<p><strong>Hardware:</strong></p>

<ul>
  <li>Raspberry Pi</li>
  <li>Raspberry Pi touchscreen</li>
  <li>MicroSD card</li>
  <li>Power supply</li>
</ul>

<p><strong>Software:</strong></p>

<ul>
  <li>Raspberry Pi OS with Desktop</li>
  <li>Chromium</li>
  <li>Unclutter</li>
  <li>Home Assistant</li>
  <li>HACS</li>
  <li>Kiosk Mode</li>
</ul>

<p><strong>The end goal:</strong></p>

<p><strong>🖥️ Raspberry Pi + 📱 Touchscreen → 🏠 Home Assistant Kiosk</strong></p>

<h2 id="a-simple-dedicated-and-always-ready-smart-home-dashboard">A simple, dedicated, and always-ready smart-home dashboard.</h2>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[Turning a Raspberry Pi Into a Sleek Home Assistant Kiosk]]></summary></entry><entry><title type="html">Building a NUT UPS Monitoring and Shutdown System</title><link href="https://freaky2112.github.io/blog/2026/09/10/nuts-sever/" rel="alternate" type="text/html" title="Building a NUT UPS Monitoring and Shutdown System" /><published>2026-09-10T00:00:00+00:00</published><updated>2026-09-10T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/09/10/nuts-sever</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/09/10/nuts-sever/"><![CDATA[<h1 id="building-a-nut-ups-monitoring-and-shutdown-system">Building a NUT UPS Monitoring and Shutdown System</h1>

<blockquote>
  <p>A UPS is great, but simply plugging your servers into it isn’t enough. The real goal is to make sure the servers <strong>know when the power goes out</strong>, react appropriately, and shut down cleanly before the batteries are exhausted.</p>
</blockquote>

<p>After setting up my UPS devices with <strong>Network UPS Tools (NUT)</strong>, I wanted to take things a little further.</p>

<p>The goal was to have one central NUT server managing multiple UPS devices, with remote Linux and Windows machines monitoring those UPS units over the network.</p>

<p>I also wanted a simple web interface to see what was happening.</p>

<h2 id="the-setup">The Setup</h2>

<p>The basic architecture looks like this:</p>

<p><strong>UPS → NUT Server → Network → Clients</strong></p>

<p>My NUT server is connected directly to the UPS devices through USB.</p>

<p>The NUT server handles communication with the UPS hardware and makes the UPS information available over the network.</p>

<p>Remote machines then connect to the NUT server and monitor the UPS status.</p>

<p>This means I don’t need to connect every server directly to a UPS.</p>

<h2 id="multiple-ups-devices">Multiple UPS Devices</h2>

<p>One of the nice things about NUT is that a single server can manage multiple UPS devices.</p>

<p>In my setup, I have several UPS units connected through USB.</p>

<p>Each UPS gets its own name inside NUT.</p>

<p>For example:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">tripplite</code></li>
  <li><code class="language-plaintext highlighter-rouge">apc-network</code></li>
  <li><code class="language-plaintext highlighter-rouge">apc-modem</code></li>
</ul>

<p>This makes it possible for clients to monitor a specific UPS depending on which equipment they are protecting.</p>

<p>The important part is identifying each UPS correctly.</p>

<p><code class="language-plaintext highlighter-rouge">nut-scanner</code> makes this much easier because it can detect compatible USB UPS devices and provide the information needed for the NUT configuration.</p>

<h2 id="usb-detection">USB Detection</h2>

<p>When troubleshooting a UPS, one of the first things I check is USB detection.</p>

<p>The simplest check is:</p>

<p><code class="language-plaintext highlighter-rouge">lsusb</code></p>

<p>If the UPS appears there, Linux can at least see the USB device.</p>

<p>For more detailed information, <code class="language-plaintext highlighter-rouge">lsusb -D</code> can be used against the appropriate USB device path.</p>

<p>This can be especially useful when troubleshooting multiple UPS devices that use the same vendor and product IDs.</p>

<p>For example, two APC UPS units may both report the same USB vendor and product ID.</p>

<p>In that situation, the serial number can be used to distinguish between them.</p>

<h2 id="nut-server">NUT Server</h2>

<p>The NUT server is the central part of the setup.</p>

<p>The UPS drivers communicate directly with the physical UPS devices.</p>

<p>NUT then exposes the UPS information through <code class="language-plaintext highlighter-rouge">upsd</code>.</p>

<p>The server can provide information such as:</p>

<ul>
  <li>UPS status</li>
  <li>Battery charge</li>
  <li>Battery runtime</li>
  <li>Input voltage</li>
  <li>Output voltage</li>
  <li>Load</li>
  <li>Battery voltage</li>
  <li>Whether the UPS is online</li>
  <li>Whether the UPS is running on battery</li>
</ul>

<p>The important part is that clients don’t need direct USB access to the UPS.</p>

<p>They simply connect to the NUT server over the network.</p>

<h2 id="network-mode">Network Mode</h2>

<p>The NUT server runs in:</p>

<p><code class="language-plaintext highlighter-rouge">MODE=netserver</code></p>

<p>This allows remote clients to connect to it.</p>

<p>The NUT server listens on port:</p>

<p><code class="language-plaintext highlighter-rouge">3493</code></p>

<p>Once the server is listening on the network, a remote Linux machine can test the connection with <code class="language-plaintext highlighter-rouge">upsc</code>.</p>

<p>For example:</p>

<p><code class="language-plaintext highlighter-rouge">upsc yourupsname@your-nut-server</code></p>

<p>If everything is working, NUT will return the UPS information.</p>

<p>This is a great first test before configuring automatic shutdown.</p>

<h2 id="remote-linux-clients">Remote Linux Clients</h2>

<p>The remote Linux machines only need the NUT client components.</p>

<p>They don’t need to have the UPS physically connected to them.</p>

<p>The client connects to the central NUT server and monitors the UPS.</p>

<p>The important configuration is the <code class="language-plaintext highlighter-rouge">MONITOR</code> entry in <code class="language-plaintext highlighter-rouge">upsmon.conf</code>.</p>

<p>This tells the machine which UPS to monitor and what credentials to use.</p>

<p>The client can then react to events such as:</p>

<ul>
  <li>UPS goes onto battery</li>
  <li>UPS returns to utility power</li>
  <li>UPS battery becomes critically low</li>
  <li>Communication with the UPS is lost</li>
  <li>A forced shutdown is requested</li>
</ul>

<h2 id="automatic-shutdown">Automatic Shutdown</h2>

<p>This is where NUT becomes much more useful than simply monitoring battery percentage.</p>

<p>A power outage might only last a few seconds.</p>

<p>In that case, there’s no reason to shut down everything immediately.</p>

<p>Instead, the client can wait and see whether power returns.</p>

<p>For longer outages, <code class="language-plaintext highlighter-rouge">upssched</code> can be used to schedule actions.</p>

<p>For example:</p>

<p><strong>Power goes out</strong></p>

<p>↓</p>

<p><strong>UPS switches to battery</strong></p>

<p>↓</p>

<p><strong>Start a timer</strong></p>

<p>↓</p>

<p><strong>Power comes back</strong></p>

<p>↓</p>

<p><strong>Cancel the timer</strong></p>

<p>Or:</p>

<p><strong>Power goes out</strong></p>

<p>↓</p>

<p><strong>UPS stays on battery</strong></p>

<p>↓</p>

<p><strong>Timer expires</strong></p>

<p>↓</p>

<p><strong>Trigger a controlled shutdown</strong></p>

<p>This gives the system some protection against short power interruptions without unnecessarily shutting down the homelab.</p>

<h2 id="the-importance-of-upssched">The Importance of <code class="language-plaintext highlighter-rouge">upssched</code></h2>

<p><code class="language-plaintext highlighter-rouge">upssched</code> is useful because it gives the shutdown process some intelligence.</p>

<p>Instead of:</p>

<blockquote>
  <p>Battery detected → immediately shutdown</p>
</blockquote>

<p>I can define something closer to:</p>

<blockquote>
  <p>Battery detected → wait → check again → shutdown only if the situation continues.</p>
</blockquote>

<p>It can also react to communication problems.</p>

<p>For example, if the client temporarily loses communication with the NUT server, a timer can be started rather than immediately shutting down the machine.</p>

<p>If communication comes back, the timer can be cancelled.</p>

<p>This helps avoid unnecessary shutdowns caused by a temporary network or service problem.</p>

<h2 id="testing-the-shutdown-process">Testing the Shutdown Process</h2>

<p>UPS shutdown systems should be tested.</p>

<p>A configuration that looks correct on paper isn’t enough.</p>

<p>One simple test is to disconnect the UPS from utility power while keeping the equipment connected to the UPS.</p>

<p>The UPS should switch to battery.</p>

<p>The NUT server should detect the change.</p>

<p>The remote clients should also detect the event.</p>

<p>Logs can then be checked to confirm that everything is behaving as expected.</p>

<p>On Debian-based systems, the system logs can be inspected with:</p>

<p><code class="language-plaintext highlighter-rouge">tail /var/log/syslog</code></p>

<p>Depending on the distribution and logging configuration, <code class="language-plaintext highlighter-rouge">journalctl</code> can also be useful.</p>

<h2 id="webnut">Webnut</h2>

<p>Once the NUT server was working, I wanted an easier way to see the UPS status.</p>

<p>For that, I added <strong>WebNUT</strong>.</p>

<p>WebNUT provides a web interface for viewing information from a NUT server.</p>

<p>I run it as a Docker container.</p>

<p>The container connects to the NUT server over port <code class="language-plaintext highlighter-rouge">3493</code> and exposes its own web interface on port <code class="language-plaintext highlighter-rouge">6543</code>.</p>

<p>This gives me a simple dashboard for checking the UPS without having to SSH into the NUT server and run <code class="language-plaintext highlighter-rouge">upsc</code> manually.</p>

<h2 id="docker">Docker</h2>

<p>The PeaNuts container is intentionally kept separate from the NUT server itself.</p>

<p>The architecture is:</p>

<p><strong>Physical UPS</strong></p>

<p>↓</p>

<p><strong>NUT Server</strong></p>

<p>↓</p>

<p><strong>Peanuts Docker Container</strong></p>

<p>↓</p>

<p><strong>Web Browser</strong></p>

<p>This is convenient because Peanuts doesn’t need direct access to the USB UPS devices.</p>

<p>It only needs network access to the NUT server.</p>

<h2 id="windows-clients">Windows Clients</h2>

<p>NUT isn’t limited to Linux.</p>

<p>Windows machines can also monitor the NUT server.</p>

<p>For Windows, I use <strong>WinNUT Client</strong>.</p>

<p>The Windows client connects to the NUT server in the same general way as a Linux NUT client.</p>

<p>This is particularly useful in a homelab where you might have a mixture of:</p>

<ul>
  <li>Linux servers</li>
  <li>Windows PCs</li>
  <li>Virtual machines</li>
  <li>NAS systems</li>
  <li>Other network-connected equipment</li>
</ul>

<p>One UPS can therefore provide power information to many different systems.</p>

<h2 id="one-central-point-of-monitoring">One Central Point of Monitoring</h2>

<p>The biggest advantage of this setup is that the UPS hardware doesn’t have to be distributed everywhere.</p>

<p>Instead, I have a central NUT server.</p>

<p>Something like:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>                 ┌───────────────┐
                 │   UPS #1      │
                 │   Tripp Lite  │
                 └───────┬───────┘
                         │ USB
                 ┌───────▼───────┐
                 │               │
                 │   NUT Server  │
                 │               │
                 └───────┬───────┘
                         │ Network
             ┌───────────┼───────────┐
             │           │           │
             ▼           ▼           ▼
          Linux       Windows     WebNUT
          Client       Client      Docker
</code></pre></div></div>

<p>Additional UPS devices can be connected to the same NUT server.</p>

<p>The result is a centralized UPS monitoring system for the homelab.</p>

<h2 id="what-happens-during-a-power-outage">What Happens During a Power Outage?</h2>

<p>The complete sequence now looks something like this:</p>

<p><strong>1. Utility power fails</strong></p>

<p>The UPS switches to battery.</p>

<p><strong>2. NUT detects the change</strong></p>

<p>The NUT driver reports that the UPS is running on battery.</p>

<p><strong>3. Remote clients receive the event</strong></p>

<p>Linux and Windows clients know that the UPS is no longer receiving utility power.</p>

<p><strong>4. Timers can start</strong></p>

<p><code class="language-plaintext highlighter-rouge">upssched</code> can wait for a configurable amount of time.</p>

<p><strong>5. Power returns</strong></p>

<p>The UPS goes back online and the timers can be cancelled.</p>

<p><strong>6. Power stays off</strong></p>

<p>If the outage continues, the configured shutdown action can be triggered.</p>

<p><strong>7. Servers shut down cleanly</strong></p>

<p>Instead of suddenly losing power when the battery dies, the machines have an opportunity to shut down properly.</p>

<h2 id="why-i-like-this-setup">Why I Like This Setup</h2>

<p>The important part isn’t really the web dashboard.</p>

<p>It’s the automation behind it.</p>

<p>A UPS protects hardware from sudden power loss, but NUT makes the UPS part of the infrastructure.</p>

<p>Instead of having a UPS silently beep during an outage, the homelab can actually understand what’s happening and react to it.</p>

<p>The final setup gives me:</p>

<ul>
  <li>Multiple UPS devices</li>
  <li>Centralized monitoring</li>
  <li>Remote Linux clients</li>
  <li>Windows client support</li>
  <li>Automatic shutdown</li>
  <li>Delayed shutdown timers</li>
  <li>Web-based monitoring</li>
  <li>USB-level UPS detection</li>
  <li>Network-based UPS access</li>
</ul>

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

<p>NUT is one of those homelab services that you don’t think about much when everything is working.</p>

<p>That’s actually the point.</p>

<p>When the power goes out, I don’t want to be scrambling around trying to shut down servers manually.</p>

<p>I want the UPS to detect the outage, NUT to report it, the clients to react, and the systems to shut down cleanly if the outage lasts long enough.</p>

<p>With a central NUT server and network clients, the UPS becomes another managed service in the homelab rather than just a battery sitting underneath a server.</p>

<p>And hopefully, the next power outage will be boring.</p>

<h2 id="which-is-exactly-what-i-want">Which is exactly what I want.</h2>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[Building a NUT UPS Monitoring and Shutdown System]]></summary></entry><entry><title type="html">Building a GitHub-Based Bash Alias Library</title><link href="https://freaky2112.github.io/blog/2026/08/07/aliases/" rel="alternate" type="text/html" title="Building a GitHub-Based Bash Alias Library" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/08/07/aliases</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/08/07/aliases/"><![CDATA[<h1 id="building-a-github-based-bash-alias-library">Building a GitHub-Based Bash Alias Library</h1>

<p>I use a lot of Linux systems in my homelab, and after a while I started collecting more and more Bash aliases.</p>

<p>The problem?</p>

<p>Every time I set up a new server, I had to remember which aliases I had, copy my <code class="language-plaintext highlighter-rouge">.bashrc</code>, or manually recreate everything.</p>

<p>So I decided to build something a little more convenient: <strong>a centralized Bash alias library hosted on GitHub.</strong></p>

<p>The idea is simple:</p>

<blockquote>
  <p>Keep my aliases in one GitHub repository and let an installation script automatically discover and install them.</p>
</blockquote>

<h2 id="the-basic-idea">The Basic Idea</h2>

<p>Instead of putting every alias directly inside <code class="language-plaintext highlighter-rouge">.bashrc</code>, I keep them organized in my GitHub repository.</p>

<p>For example:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aliases/
├── docker.bash
├── linux.bash
├── network.bash
├── proxmox.bash
└── system.bash
</code></pre></div></div>

<p>Each file contains aliases related to a particular topic.</p>

<p>The installer downloads the repository, discovers the available alias files, and makes them available to the current user.</p>

<p>That means when I add a new alias to GitHub, I don’t have to manually modify <code class="language-plaintext highlighter-rouge">.bashrc</code> on every machine.</p>

<h2 id="why-do-this">Why Do This?</h2>

<p>There are a few advantages to this approach.</p>

<h3 id="one-place-to-maintain-everything">One Place to Maintain Everything</h3>

<p>Instead of having slightly different <code class="language-plaintext highlighter-rouge">.bashrc</code> files across multiple servers, my aliases live in one repository.</p>

<h3 id="easy-to-deploy">Easy to Deploy</h3>

<p>When I install a new Debian or Ubuntu server, I can simply run the installer and get my usual command shortcuts.</p>

<h3 id="easy-to-update">Easy to Update</h3>

<p>If I add or change an alias, I can update the repository and pull the changes onto my other systems.</p>

<h3 id="organized">Organized</h3>

<p>Rather than having a <code class="language-plaintext highlighter-rouge">.bashrc</code> containing hundreds of aliases, I can separate them into logical files.</p>

<hr />

<h2 id="a-few-example-aliases">A Few Example Aliases</h2>

<p>I don’t need hundreds of aliases to demonstrate the idea. Even a few simple ones make the concept useful.</p>

<p>For example, some Docker shortcuts:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">alias </span><span class="nv">dps</span><span class="o">=</span><span class="s1">'docker ps'</span>
<span class="nb">alias </span><span class="nv">dpa</span><span class="o">=</span><span class="s1">'docker ps -a'</span>
<span class="nb">alias </span><span class="nv">dcu</span><span class="o">=</span><span class="s1">'docker compose up -d'</span>
<span class="nb">alias </span><span class="nv">dcd</span><span class="o">=</span><span class="s1">'docker compose down'</span>
</code></pre></div></div>

<p>Some useful Linux shortcuts:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">alias </span><span class="nv">ll</span><span class="o">=</span><span class="s1">'ls -lah'</span>
<span class="nb">alias</span> ..<span class="o">=</span><span class="s1">'cd ..'</span>
<span class="nb">alias </span><span class="nv">c</span><span class="o">=</span><span class="s1">'clear'</span>
</code></pre></div></div>

<p>And some system-related shortcuts:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">alias </span><span class="nv">update</span><span class="o">=</span><span class="s1">'sudo apt update &amp;&amp; sudo apt upgrade'</span>
<span class="nb">alias </span><span class="nv">ports</span><span class="o">=</span><span class="s1">'sudo ss -tulpn'</span>
</code></pre></div></div>

<p>The important part isn’t the aliases themselves.</p>

<p>It’s <strong>where they are stored and how they get installed.</strong></p>

<hr />

<h2 id="automatic-alias-discovery">Automatic Alias Discovery</h2>

<p>One of the things I wanted was to avoid hard-coding every alias file into the installation script.</p>

<p>Instead, the installer looks at the repository and discovers the available files automatically.</p>

<p>So if I add:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aliases/network.bash
</code></pre></div></div>

<p>later, the installer can find it without me having to modify the installer itself.</p>

<p>This also makes the repository easier to maintain.</p>

<p>I can simply create another <code class="language-plaintext highlighter-rouge">.bash</code> file whenever I want to add a new category.</p>

<hr />

<h2 id="the-bashrc-integration">The <code class="language-plaintext highlighter-rouge">.bashrc</code> Integration</h2>

<p>The installer doesn’t need to replace the user’s entire <code class="language-plaintext highlighter-rouge">.bashrc</code>.</p>

<p>Instead, it adds a small section that loads the alias library.</p>

<p>Conceptually, it looks something like this:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># My GitHub Bash Aliases</span>
<span class="k">for </span>file <span class="k">in</span> ~/.bash_aliases/<span class="k">*</span>.bash<span class="p">;</span> <span class="k">do</span>
    <span class="o">[</span> <span class="nt">-f</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">source</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span>
<span class="k">done</span>
</code></pre></div></div>

<p>This keeps the actual aliases separate from the main Bash configuration.</p>

<p>It also means I can continue using my normal <code class="language-plaintext highlighter-rouge">.bashrc</code> without worrying about losing existing settings.</p>

<hr />

<h2 id="adding-a-new-alias">Adding a New Alias</h2>

<p>Once everything is set up, adding a new alias is simple.</p>

<p>I create or modify one of the files in the repository:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aliases/docker.bash
</code></pre></div></div>

<p>Add the alias:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">alias </span><span class="nv">dlogs</span><span class="o">=</span><span class="s1">'docker logs -f'</span>
</code></pre></div></div>

<p>Commit and push the change to GitHub.</p>

<p>Then I can update the alias library on another machine.</p>

<p>No copying and pasting between servers.</p>

<hr />

<h2 id="the-installer">The Installer</h2>

<p>The other part of the project is a small installation script.</p>

<p>Its job is basically:</p>

<ol>
  <li>Check that the alias repository is available.</li>
  <li>Download or clone the repository.</li>
  <li>Find the <code class="language-plaintext highlighter-rouge">aliases/*.bash</code> files.</li>
  <li>Install them for the current user.</li>
  <li>Add the required <code class="language-plaintext highlighter-rouge">.bashrc</code> section.</li>
  <li>Reload the Bash configuration.</li>
</ol>

<p>The goal is to make installing my personal Linux environment almost as easy as installing a package.</p>

<hr />

<h2 id="keeping-it-simple">Keeping It Simple</h2>

<p>I deliberately didn’t want to turn this into a huge configuration-management project.</p>

<p>For my homelab, I wanted something lightweight.</p>

<p>GitHub handles the version control.</p>

<p>Bash handles loading the aliases.</p>

<p>The installer handles deployment.</p>

<p>That’s really all I need.</p>

<hr />

<h2 id="whats-next">What’s Next?</h2>

<p>This could easily be expanded later.</p>

<p>For example:</p>

<ul>
  <li>Separate aliases for Debian, Docker, Proxmox, networking, and Home Assistant.</li>
  <li>OS detection.</li>
  <li>Automatic updates.</li>
  <li>Versioned releases.</li>
  <li>Optional alias categories.</li>
  <li>An interactive installer.</li>
  <li>Shell support beyond Bash.</li>
  <li>A command to update the alias library without reinstalling everything.</li>
</ul>

<p>For now, though, the important part is having <strong>one central place for my Bash aliases</strong>.</p>

<p>It makes setting up a new homelab server just a little bit easier — and saves me from constantly asking myself:</p>

<blockquote>
  <p>“What was that alias I made six months ago?”</p>
</blockquote>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[Building a GitHub-Based Bash Alias Library]]></summary></entry><entry><title type="html">Technitium DNS Cluster</title><link href="https://freaky2112.github.io/blog/2026/07/02/Technitium-cluster/" rel="alternate" type="text/html" title="Technitium DNS Cluster" /><published>2026-07-02T00:00:00+00:00</published><updated>2026-07-02T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/07/02/Technitium-cluster</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/07/02/Technitium-cluster/"><![CDATA[<h1 id="building-a-resilient-technitium-dns-cluster-zone-replication--automatic-failover">Building a Resilient Technitium DNS Cluster: Zone Replication &amp; Automatic Failover</h1>
<p>DNS is one of those services you rarely think about—until it stops working. When your DNS server becomes unavailable, every device on your network suddenly struggles to find websites, services, and even other local machines.</p>

<p>In this guide, we’ll transform a single Technitium DNS Server into a resilient, highly available DNS platform using two servers. By combining Technitium’s built-in cluster replication with Keepalived’s automatic failover, you’ll create a setup that continues serving DNS even if one server unexpectedly goes offline.</p>

<hr />

<h1 id="why-build-a-dns-cluster">Why Build a DNS Cluster?</h1>

<p>Running a single DNS server creates a single point of failure. Even if your server is extremely reliable, hardware failures, maintenance, updates, or power outages can leave your entire network without name resolution.</p>

<p>A high-availability deployment solves this problem by using two independent components working together.</p>

<p>The first is <strong>cluster replication</strong>, which keeps DNS zones synchronized between multiple Technitium servers. Every record you create or modify is automatically replicated so both servers always contain identical DNS data.</p>

<p>The second is <strong>automatic failover</strong> using a floating Virtual IP (VIP). Instead of clients knowing about two different DNS servers, every device simply points to one IP address. If the primary server becomes unavailable, the secondary automatically assumes ownership of that IP address and continues answering DNS requests without requiring any client changes.</p>

<p>Neither feature is sufficient on its own. Replication ensures both servers contain the same information, while failover ensures clients always reach a healthy server.</p>

<hr />

<h1 id="creating-the-cluster">Creating the Cluster</h1>

<p>The process begins by configuring one server as the primary cluster member.</p>

<p>Within the Technitium administration interface, create a new cluster and assign it a descriptive name. During this step, the server registers itself as the initial cluster node.</p>

<p>Next, move to your secondary DNS server and choose the option to join an existing cluster. You’ll provide the address of the primary server along with administrative credentials so the secondary can securely join.</p>

<p>Depending on your environment, you may temporarily allow self-signed certificates during the initial connection. Once both systems communicate successfully, the secondary server appears in the cluster management page, confirming that both nodes recognize each other and are ready to synchronize.</p>

<p>Before continuing, verify that both servers report a healthy status and can communicate without firewall restrictions.</p>

<hr />

<h1 id="zone-replication">Zone Replication</h1>

<p>With the cluster established, Technitium begins synchronizing DNS data between both nodes.</p>

<p>Whenever a DNS zone is created or modified on the primary server, the changes are automatically replicated to the secondary. This includes new host records, aliases, TXT records, MX records, and virtually every other zone modification.</p>

<p>It’s worth verifying that all of your important zones are participating in replication. If certain zones existed before clustering was configured, they may require a quick save or synchronization before becoming fully replicated.</p>

<p>A good practice is to make a small DNS change on the primary server and confirm that the same change appears on the secondary within a few moments.</p>

<p>Once replication is functioning correctly, both servers are capable of providing identical DNS responses.</p>

<hr />

<h1 id="automatic-failover-with-keepalived">Automatic Failover with Keepalived</h1>

<p>Although replication keeps the DNS data synchronized, clients still need a single destination for their DNS requests.</p>

<p>This is where Keepalived enters the picture.</p>

<p>Keepalived uses the Virtual Router Redundancy Protocol (VRRP) to create a floating Virtual IP address shared between both DNS servers. At any given time, one server owns the VIP while the other remains on standby.</p>

<p>Every client, router, DHCP server, and network device simply uses this Virtual IP as its DNS server.</p>

<p>If the primary node becomes unavailable because of maintenance, hardware failure, or a system crash, Keepalived automatically transfers ownership of the Virtual IP to the secondary server. From the perspective of your clients, nothing changes—they continue sending DNS requests to the exact same IP address.</p>

<p>Once the primary server returns online, it can either reclaim ownership of the Virtual IP or remain as the standby node, depending on your preferred failover behavior.</p>

<p>This entire process happens automatically and typically completes within only a few seconds.</p>

<hr />

<h1 id="testing-the-setup">Testing the Setup</h1>

<p>High availability should never be considered complete until it has been tested.</p>

<p>Begin by confirming that clients successfully resolve DNS using the Virtual IP instead of either server’s individual address.</p>

<p>Next, simulate a failure by shutting down the primary DNS server or disconnecting it from the network. Within moments, the secondary server should assume ownership of the Virtual IP.</p>

<p>While the failover occurs, continue performing DNS lookups from another device. Name resolution should continue without interruption.</p>

<p>Finally, restore the primary server and verify that the cluster returns to its expected operating state while maintaining synchronized DNS data.</p>

<p>Testing these scenarios before relying on the cluster in production provides confidence that failover will work when it’s actually needed.</p>

<hr />

<h1 id="benefits-of-this-setup">Benefits of This Setup</h1>

<p>Combining Technitium’s clustering capabilities with Keepalived provides several advantages:</p>

<ul>
  <li>Elimination of a single point of failure.</li>
  <li>Automatic synchronization of DNS zones.</li>
  <li>Seamless client failover through a floating Virtual IP.</li>
  <li>Simplified DNS configuration across your network.</li>
  <li>Minimal downtime during maintenance or unexpected outages.</li>
  <li>A scalable foundation for larger homelab or self-hosted environments.</li>
</ul>

<hr />

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

<p>DNS is one of the foundational services every network depends on, yet it’s often overlooked until something goes wrong.</p>

<p>By deploying two Technitium DNS servers with cluster replication and automatic failover, you create a resilient infrastructure capable of surviving server outages with little to no impact on your users.</p>

<p>The initial setup requires only a bit more effort than a standalone installation, but the reward is a highly available DNS platform that quietly does its job—even when one of your servers doesn’t.</p>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[Building a Resilient Technitium DNS Cluster: Zone Replication &amp; Automatic Failover DNS is one of those services you rarely think about—until it stops working. When your DNS server becomes unavailable, every device on your network suddenly struggles to find websites, services, and even other local machines.]]></summary></entry><entry><title type="html">Discord Notification</title><link href="https://freaky2112.github.io/blog/2026/06/08/discord-notification/" rel="alternate" type="text/html" title="Discord Notification" /><published>2026-06-08T00:00:00+00:00</published><updated>2026-06-08T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/06/08/discord-notification</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/06/08/discord-notification/"><![CDATA[<h1 id="get-discord-notifications-for-unattended-upgrades-on-linux">Get Discord Notifications for Unattended Upgrades on Linux</h1>

<p>Keeping servers updated is one of the most important tasks in any homelab or production environment. Linux distributions such as Ubuntu and Debian make this easy through <strong>Unattended Upgrades</strong>, automatically installing security and package updates without manual intervention.</p>

<p>The challenge is visibility. Updates may be happening in the background, but unless you’re actively checking logs, you might never know when a system has been patched, what was updated, or whether a reboot is required.</p>

<p>A simple solution is to integrate unattended upgrades with <strong>Discord notifications</strong>.</p>

<h2 id="why-send-upgrade-notifications">Why Send Upgrade Notifications?</h2>

<p>For homelab operators and system administrators, notifications provide immediate awareness of maintenance activity across your infrastructure.</p>

<p>Benefits include:</p>

<ul>
  <li>Confirmation that automatic updates are working correctly</li>
  <li>Visibility into when systems were patched</li>
  <li>Faster identification of upgrade failures</li>
  <li>Awareness of pending reboots after kernel updates</li>
  <li>Centralized monitoring directly from Discord</li>
</ul>

<p>Instead of logging into each server and reviewing package logs, you receive updates in a dedicated channel where all infrastructure events can be tracked.</p>

<h2 id="using-discord-webhooks">Using Discord Webhooks</h2>

<p>Discord webhooks provide a lightweight method for servers to post messages directly into a channel.</p>

<p>Once configured, a server can automatically send notifications whenever unattended upgrades complete. Typical notification details might include:</p>

<ul>
  <li>Hostname</li>
  <li>Date and time of the upgrade</li>
  <li>Number of packages updated</li>
  <li>Package names</li>
  <li>Reboot requirements</li>
  <li>Upgrade status</li>
</ul>

<p>This creates a simple but effective audit trail for system maintenance.</p>

<h2 id="integrating-with-unattended-upgrades">Integrating with Unattended Upgrades</h2>

<p>There are several ways to trigger notifications:</p>

<h3 id="after-successful-package-operations">After Successful Package Operations</h3>

<p>A notification can be sent whenever package management completes successfully. This approach is easy to implement and ensures administrators receive frequent feedback about system activity.</p>

<h3 id="after-actual-upgrade-installation">After Actual Upgrade Installation</h3>

<p>A more refined method is to trigger notifications only when unattended upgrades have installed packages. This reduces noise and keeps alerts focused on meaningful changes.</p>

<h3 id="systemd-integration">Systemd Integration</h3>

<p>Modern Linux systems use systemd to manage services. By linking notification tasks to the unattended-upgrades service, notifications can be delivered automatically after update operations finish.</p>

<p>This approach is reliable, clean, and aligns well with standard Linux service management practices.</p>

<h2 id="taking-it-further-with-apprise">Taking It Further with Apprise</h2>

<p>While Discord webhooks work well, larger homelabs often benefit from a notification platform such as Apprise.</p>

<p>Apprise acts as a universal notification gateway, allowing a single script to send messages to multiple destinations without modification.</p>

<p>Supported services include:</p>

<ul>
  <li>Discord</li>
  <li>Email</li>
  <li>Slack</li>
  <li>Microsoft Teams</li>
  <li>Telegram</li>
  <li>ntfy</li>
  <li>Pushover</li>
  <li>Many others</li>
</ul>

<p>This makes it easy to expand your alerting strategy as your environment grows.</p>

<p>For example, a notification that starts in Discord today could later be delivered simultaneously to email, mobile push notifications, and team collaboration tools without rewriting automation scripts.</p>

<h2 id="homelab-use-cases">Homelab Use Cases</h2>

<p>Discord upgrade notifications are especially useful for environments running multiple self-hosted services such as:</p>

<ul>
  <li>Docker hosts</li>
  <li>Home Assistant</li>
  <li>Grafana</li>
  <li>Alloy</li>
  <li>Technitium DNS</li>
  <li>Navidrome</li>
  <li>Media servers</li>
  <li>Virtualization hosts</li>
  <li>Raspberry Pi clusters</li>
</ul>

<p>Instead of manually checking each machine, you receive a centralized stream of maintenance events directly in your monitoring channel.</p>

<h2 id="best-practices">Best Practices</h2>

<p>When implementing upgrade notifications, consider the following:</p>

<ul>
  <li>Create a dedicated Discord channel for infrastructure alerts.</li>
  <li>Include the hostname in every notification.</li>
  <li>Report whether a reboot is required.</li>
  <li>Parse upgrade logs to display the actual packages updated.</li>
  <li>Use embeds for cleaner and more readable messages.</li>
  <li>Retain upgrade logs for troubleshooting and auditing purposes.</li>
</ul>

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

<p>Automatic updates are only half of the equation. Knowing that updates have been successfully applied is equally important.</p>

<p>By connecting unattended upgrades to Discord, administrators gain immediate visibility into system maintenance without adding complexity. Whether you’re managing a single server or an entire homelab, upgrade notifications provide peace of mind and help ensure that critical security updates never go unnoticed.</p>

<p>As your infrastructure grows, solutions like Apprise can further enhance your notification workflow by delivering alerts across multiple platforms while maintaining a single automation process.</p>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[Get Discord Notifications for Unattended Upgrades on Linux]]></summary></entry><entry><title type="html">S-nail (Mailrc)</title><link href="https://freaky2112.github.io/blog/2026/06/07/s-nail/" rel="alternate" type="text/html" title="S-nail (Mailrc)" /><published>2026-06-07T00:00:00+00:00</published><updated>2026-06-07T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/06/07/s-nail</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/06/07/s-nail/"><![CDATA[<h1 id="s-nail-a-practical-guide-to-configuring-email-from-the-linux-command-line">S-nail: A Practical Guide to Configuring Email from the Linux Command Line</h1>

<p>If you’ve ever needed to send emails directly from a Linux server, script, monitoring system, or homelab service, S-nail is one of the most powerful command-line mail clients available. It is lightweight, highly configurable, and works well for everything from simple notifications to full-featured email workflows.</p>

<p>In this guide, we’ll cover the major components of an S-nail setup and explain what each part does, without focusing on the specific configuration syntax.</p>

<h2 id="what-is-s-nail">What Is S-nail?</h2>

<p>S-nail is a modern implementation of the classic Unix mail client. It allows users and applications to send and receive email directly from the command line.</p>

<p>Many administrators use it for:</p>

<ul>
  <li>Server notifications</li>
  <li>Backup reports</li>
  <li>Monitoring alerts</li>
  <li>Automated scripts</li>
  <li>Homelab services</li>
  <li>Cron job reports</li>
</ul>

<p>Because it has built-in SMTP support, S-nail can send emails directly through your mail provider without requiring a local mail server.</p>

<h2 id="understanding-the-configuration-file">Understanding the Configuration File</h2>

<p>S-nail reads its settings from a configuration file. This file defines how emails are sent, which account is used, security settings, and various user preferences.</p>

<p>Think of this file as the central location where all mail-related settings are stored.</p>

<h2 id="configuring-your-identity">Configuring Your Identity</h2>

<p>One of the first things you’ll configure is your sender identity.</p>

<p>This includes:</p>

<ul>
  <li>The email address that appears in the “From” field</li>
  <li>Your display name</li>
  <li>Character encoding preferences</li>
  <li>Where copies of sent messages should be stored</li>
</ul>

<p>These settings ensure that messages appear professional and are properly formatted for recipients.</p>

<h2 id="connecting-to-an-smtp-server">Connecting to an SMTP Server</h2>

<p>Most modern email providers require outgoing mail to be sent through an SMTP server.</p>

<p>This section of the configuration defines:</p>

<ul>
  <li>The SMTP server address</li>
  <li>The connection port</li>
  <li>Whether encryption is required</li>
  <li>Authentication credentials</li>
</ul>

<p>Without this information, S-nail won’t know how to deliver messages to the outside world.</p>

<h2 id="encryption-and-security">Encryption and Security</h2>

<p>Email providers almost always require encrypted connections.</p>

<p>S-nail supports:</p>

<ul>
  <li>STARTTLS connections</li>
  <li>SSL/TLS encrypted connections</li>
  <li>Certificate validation</li>
  <li>Custom certificate authorities</li>
</ul>

<p>Using proper certificate validation is strongly recommended in production environments to protect against man-in-the-middle attacks.</p>

<h2 id="authentication">Authentication</h2>

<p>Most SMTP servers require users to authenticate before sending mail.</p>

<p>Common authentication methods include:</p>

<ul>
  <li>Login authentication</li>
  <li>Plain authentication</li>
  <li>OAuth-based authentication (provider dependent)</li>
</ul>

<p>For personal accounts such as Gmail or Microsoft 365, application-specific passwords are often required instead of your normal account password.</p>

<h2 id="using-multiple-email-accounts">Using Multiple Email Accounts</h2>

<p>One of S-nail’s most useful features is support for multiple mail profiles.</p>

<p>For example, you can maintain separate accounts for:</p>

<ul>
  <li>Personal email</li>
  <li>Work email</li>
  <li>Monitoring alerts</li>
  <li>Automated notifications</li>
</ul>

<p>This allows a single system to send messages from different identities depending on the task being performed.</p>

<h2 id="receiving-mail-with-imap">Receiving Mail with IMAP</h2>

<p>Although many users only send mail with S-nail, it can also access mailboxes through IMAP.</p>

<p>This enables:</p>

<ul>
  <li>Reading messages</li>
  <li>Managing folders</li>
  <li>Accessing remote mailboxes</li>
  <li>Synchronizing mail from providers</li>
</ul>

<p>For users who prefer command-line workflows, this provides a complete email solution.</p>

<h2 id="logging-and-troubleshooting">Logging and Troubleshooting</h2>

<p>When things don’t work as expected, S-nail includes extensive debugging capabilities.</p>

<p>Troubleshooting usually focuses on:</p>

<ul>
  <li>SMTP connectivity</li>
  <li>Authentication failures</li>
  <li>Certificate validation errors</li>
  <li>DNS issues</li>
  <li>Firewall restrictions</li>
</ul>

<p>Enabling verbose logging can quickly reveal where a connection attempt is failing.</p>

<h2 id="securing-credentials">Securing Credentials</h2>

<p>A common mistake is storing mail passwords in plain text without proper protection.</p>

<p>Best practices include:</p>

<ul>
  <li>Restricting configuration file permissions</li>
  <li>Using dedicated mail accounts</li>
  <li>Using application passwords when available</li>
  <li>Separating alerting accounts from personal accounts</li>
</ul>

<p>For servers and homelabs, creating a dedicated notification account is often the safest approach.</p>

<h2 id="common-use-cases">Common Use Cases</h2>

<p>S-nail is frequently used in environments such as:</p>

<h3 id="monitoring-and-alerting">Monitoring and Alerting</h3>

<p>Send alerts from:</p>

<ul>
  <li>Grafana</li>
  <li>Uptime Kuma</li>
  <li>Prometheus</li>
  <li>Home Assistant</li>
  <li>Custom monitoring scripts</li>
</ul>

<h3 id="backup-reporting">Backup Reporting</h3>

<p>Automatically email backup results and status reports after scheduled jobs complete.</p>

<h3 id="cron-notifications">Cron Notifications</h3>

<p>Receive reports whenever scheduled maintenance tasks succeed or fail.</p>

<h3 id="homelab-automation">Homelab Automation</h3>

<p>Integrate email notifications into Docker containers, home servers, and self-hosted applications.</p>

<h2 id="recommended-approach-for-homelabs">Recommended Approach for Homelabs</h2>

<p>For most homelab users, the simplest and most reliable setup is:</p>

<ol>
  <li>Create a dedicated alert email account.</li>
  <li>Enable SMTP access.</li>
  <li>Configure encrypted connections.</li>
  <li>Enable certificate validation.</li>
  <li>Test email delivery before integrating with applications.</li>
</ol>

<p>This approach keeps monitoring messages separate from personal email while making troubleshooting much easier.</p>

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

<p>S-nail remains one of the most flexible command-line mail clients available for Linux. Whether you’re running a small homelab or managing production infrastructure, it provides a reliable way to send and receive email without the complexity of a full mail server.</p>

<p>Once configured correctly, S-nail becomes an excellent tool for automation, monitoring, reporting, and system administration tasks.</p>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[S-nail: A Practical Guide to Configuring Email from the Linux Command Line]]></summary></entry><entry><title type="html">Unattended Upgrades &amp;amp; Gmail SMTP Alerts</title><link href="https://freaky2112.github.io/blog/2026/06/06/unattended-upgrade/" rel="alternate" type="text/html" title="Unattended Upgrades &amp;amp; Gmail SMTP Alerts" /><published>2026-06-06T00:00:00+00:00</published><updated>2026-06-06T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/06/06/unattended-upgrade</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/06/06/unattended-upgrade/"><![CDATA[<p>Automate security patching on your server and get emailed when something actually happens — no babysitting required.</p>

<hr />

<h2 id="01--install--enable">01 — Install &amp; Enable</h2>

<p>Get it running in two commands. Install the package, then run <code class="language-plaintext highlighter-rouge">dpkg-reconfigure</code> to enable it. This sets up two systemd timers — one to refresh the package list daily, one to apply updates.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>unattended-upgrades apt-listchanges
<span class="nb">sudo </span>dpkg-reconfigure <span class="nt">-plow</span> unattended-upgrades
</code></pre></div></div>

<hr />

<h2 id="02--configure">02 — Configure</h2>

<p>Edit <code class="language-plaintext highlighter-rouge">/etc/apt/apt.conf.d/50unattended-upgrades</code> to tune the behavior. By default it only touches security packages, which is the safest scope for any internet-facing box. The two options most worth considering are unused dependency cleanup and auto-reboots — if you enable the latter, schedule it during a low-traffic window.</p>

<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Unattended</span>-<span class="n">Upgrade</span>::<span class="n">Remove</span>-<span class="n">Unused</span>-<span class="n">Dependencies</span> <span class="s2">"true"</span>;
<span class="n">Unattended</span>-<span class="n">Upgrade</span>::<span class="n">Automatic</span>-<span class="n">Reboot</span>-<span class="n">Time</span> <span class="s2">"02:00"</span>;
</code></pre></div></div>

<blockquote>
  <p><strong>Tip:</strong> The safest default for any internet-facing server is security-only updates with auto-reboot disabled. You stay protected without unexpected downtime.</p>
</blockquote>

<hr />

<h2 id="03--test-it">03 — Test It</h2>

<p>Always verify the config works before leaving it unattended. The dry-run flag runs the full logic without touching any packages.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>unattended-upgrade <span class="nt">--dry-run</span> <span class="nt">--debug</span>
</code></pre></div></div>

<hr />

<h2 id="04--gmail-notifications">04 — Gmail Notifications</h2>

<p>Silent background updates are great until something breaks quietly. <code class="language-plaintext highlighter-rouge">s-nail</code> lets your server send email via Gmail SMTP. You’ll need a Gmail App Password — Google blocks regular passwords for CLI tools, so generate a dedicated one from your account security settings (requires 2FA). Then drop it into <code class="language-plaintext highlighter-rouge">~/.mailrc</code> with one quirk: the <code class="language-plaintext highlighter-rouge">@</code> in your address must be written as <code class="language-plaintext highlighter-rouge">%40</code> inside the URL string.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>set v15-compat
set from="Your Name &lt;you@gmail.com&gt;"
set mta=smtp://you%40gmail.com:apppassword@smtp.gmail.com:587
set smtp-use-starttls
</code></pre></div></div>

<hr />

<h2 id="05--lock-it-down--test">05 — Lock It Down &amp; Test</h2>

<p>The <code class="language-plaintext highlighter-rouge">~/.mailrc</code> file holds your App Password in plain text — restrict it immediately. Then fire off a test message and look for <code class="language-plaintext highlighter-rouge">250 2.0.0 OK</code> in the output to confirm the handshake worked.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">chmod </span>600 ~/.mailrc
<span class="nb">echo</span> <span class="s2">"test"</span> | s-nail <span class="nt">-v</span> <span class="nt">-s</span> <span class="s2">"Test"</span> you@example.com
</code></pre></div></div>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[Automate security patching on your server and get emailed when something actually happens — no babysitting required.]]></summary></entry><entry><title type="html">Docker Install</title><link href="https://freaky2112.github.io/blog/2026/06/04/docker-install/" rel="alternate" type="text/html" title="Docker Install" /><published>2026-06-04T00:00:00+00:00</published><updated>2026-06-04T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/06/04/docker-install</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/06/04/docker-install/"><![CDATA[<hr />
<h1 id="install-docker-engine-on-debian">Install Docker Engine on Debian</h1>

<hr />

<h2 id="step-1--clean-up-old-versions">Step 1 — Clean Up Old Versions</h2>

<ul>
  <li>
    <p>If you have older versions of Docker installed, remove them first to prevent conflicts:</p>
  </li>
  <li>
    <p>Don’t worry if apt reports that none of these packages are installed — you can safely continue.</p>
  </li>
</ul>

<hr />

<h2 id="step-2--install-prerequisites">Step 2 — Install Prerequisites</h2>

<ul>
  <li>
    <p>Update your package index and install the packages needed for <code class="language-plaintext highlighter-rouge">apt</code> to use a repository over HTTPS:</p>

    <p>“ca-certificates curl gnupg”</p>
  </li>
</ul>

<hr />

<h2 id="step-3--add-dockers-official-gpg-key">Step 3 — Add Docker’s Official GPG Key</h2>

<ul>
  <li>Create a directory for keyrings, then download and store Docker’s GPG key. This ensures the packages you download are authentic and unmodified:</li>
  <li>Set permission for folder to 0755  /etc/apt/keyrings</li>
  <li>curl keyring : https://download.docker.com/linux/debian/gpg</li>
  <li>and save it in /etc/apt/keyrings/docker.gpg</li>
  <li>change permission to everybody read /etc/apt/keyrings/docker.gpg</li>
</ul>

<hr />

<h2 id="step-4--set-up-the-repository">Step 4 — Set Up the Repository</h2>

<ul>
  <li>
    <p>Add the official Docker repository to your system’s source list:</p>

    <p>“deb [arch=”$(dpkg –print-architecture)” signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian <br />
“$(. /etc/os-release &amp;&amp; echo “$VERSION_CODENAME”)” stable” | \</p>
  </li>
</ul>

<hr />

<h2 id="step-5--install-docker-engine">Step 5 — Install Docker Engine</h2>

<ul>
  <li>
    <p>Update your package index again (so it picks up the new Docker repository), then install Docker, the CLI, and Docker Compose:</p>
  </li>
  <li>update</li>
  <li>install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin</li>
</ul>

<hr />

<h2 id="step-6--verify-the-installation">Step 6 — Verify the Installation</h2>

<ul>
  <li>Run the <code class="language-plaintext highlighter-rouge">hello-world</code> test image to confirm Docker is installed and the service is running:</li>
</ul>

<p>docker run hello-world</p>

<p>If successful, Docker will pull a small test image, run it, and print a <strong>“Hello from Docker!”</strong> message. You’re all set. ✅</p>

<hr />

<h2 id="run-docker-without-sudo">Run Docker Without <code class="language-plaintext highlighter-rouge">sudo</code></h2>

<p>By default, Docker commands require root privileges. To run Docker as your regular non-root user, add yourself to the <code class="language-plaintext highlighter-rouge">docker</code> group:</p>

<p>Create the <code class="language-plaintext highlighter-rouge">docker</code> group</p>

<p>Add your user to the group</p>

<p>Apply the changes</p>

<p>Log out and log back in</p>

<p>You can verify it works by running <code class="language-plaintext highlighter-rouge">docker run hello-world</code> without <code class="language-plaintext highlighter-rouge">sudo</code>.</p>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[Install Docker Engine on Debian]]></summary></entry><entry><title type="html">It Tool Docker</title><link href="https://freaky2112.github.io/blog/2026/05/17/it-tools-docker/" rel="alternate" type="text/html" title="It Tool Docker" /><published>2026-05-17T00:00:00+00:00</published><updated>2026-05-17T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/05/17/it-tools-docker</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/05/17/it-tools-docker/"><![CDATA[<h1 id="it-tools-the-self-hosted-swiss-army-knife-for-developers">IT-Tools: The Self-Hosted Swiss Army Knife for Developers</h1>

<p>How many browser tabs do you have open with tools like “base64 decode online”, “jwt decoder”, or “json formatter”? If you’re a developer or sysadmin, probably more than you’d like to admit.</p>

<p><strong>IT-Tools</strong> solves that. It’s a self-hosted, open-source collection of 86+ developer utilities — all in one clean web interface, running entirely in your browser, with no data sent anywhere.</p>

<hr />

<h2 id="whats-inside--86-tools-across-10-categories">What’s Inside — 86 Tools Across 10 Categories</h2>

<h3 id="-crypto">🔐 Crypto</h3>
<p>Token Generator, Hash Text (MD5/SHA-256/SHA-512), Bcrypt, UUID &amp; ULID Generator, AES Encryption/Decryption, RSA Key Pair Generator, HMAC Generator, BIP39 Passphrase, Password Strength Analyser, PDF Signature Checker.</p>

<h3 id="-converter">🔄 Converter</h3>
<p>Base64 (string &amp; file), Color (HEX/RGB/HSL), Case (camelCase/snake_case/kebab-case), Date-Time, Integer Base, YAML ↔ JSON ↔ TOML, XML ↔ JSON, Markdown to HTML, List Converter, Text to Binary/Unicode/NATO Alphabet.</p>

<h3 id="-web">🌐 Web</h3>
<p>JWT Parser, URL Encoder/Decoder &amp; Parser, HTML Entities, Basic Auth Generator, OTP Code Generator, MIME Types reference, HTTP Status Codes reference, Meta Tag Generator, User Agent Parser, JSON Diff, Slugify String, HTML WYSIWYG Editor.</p>

<h3 id="️-development">🛠️ Development</h3>
<p><strong>Docker Run → Compose Converter</strong>, Crontab Generator, Chmod Calculator, Regex Tester &amp; Memo, JSON Viewer/Minifier/to CSV, SQL Prettify, YAML Viewer, XML Formatter, Git Memo, Random Port Generator.</p>

<blockquote>
  <p>The Docker Run → Compose converter alone is worth the deployment. Paste a <code class="language-plaintext highlighter-rouge">docker run</code> command, get a clean <code class="language-plaintext highlighter-rouge">compose.yml</code> back instantly.</p>
</blockquote>

<h3 id="-network">🌍 Network</h3>
<p>IPv4 Subnet Calculator, IPv4 Address Converter, IPv4 Range Expander, MAC Address Lookup &amp; Generator, IPv6 ULA Generator.</p>

<h3 id="️-images--videos">🖼️ Images &amp; Videos</h3>
<p>QR Code Generator, WiFi QR Code Generator, SVG Placeholder Generator, Camera Recorder.</p>

<h3 id="-text--math">📝 Text &amp; Math</h3>
<p>Lorem Ipsum Generator, Text Diff, Text Statistics, String Obfuscator, Emoji Picker, ASCII Art, Math Evaluator, Percentage Calculator, ETA Calculator, Temperature Converter, Chronometer.</p>

<h3 id="-data">📊 Data</h3>
<p>Phone Parser &amp; Formatter, IBAN Validator &amp; Parser.</p>

<hr />

<h2 id="why-self-host">Why Self-Host?</h2>

<p>The official demo at <a href="https://it-tools.tech">it-tools.tech</a> is publicly available — but self-hosting makes sense for a few reasons:</p>

<p><strong>Privacy</strong> — Even though everything runs client-side, keeping it internal is the right call when handling sensitive values like API tokens, private keys, or JWTs.</p>

<p><strong>Always available</strong> — No dependency on external uptime or internet access.</p>

<p><strong>It’s 20 MB.</strong> There’s genuinely no reason not to.</p>

<hr />

<h2 id="quick-reference">Quick Reference</h2>

<table>
  <thead>
    <tr>
      <th>Property</th>
      <th>Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Image</strong></td>
      <td><code class="language-plaintext highlighter-rouge">corentinth/it-tools:latest</code></td>
    </tr>
    <tr>
      <td><strong>Image size</strong></td>
      <td>~20 MB</td>
    </tr>
    <tr>
      <td><strong>Exposed port</strong></td>
      <td>80</td>
    </tr>
    <tr>
      <td><strong>Database</strong></td>
      <td>None</td>
    </tr>
    <tr>
      <td><strong>Volumes</strong></td>
      <td>None</td>
    </tr>
    <tr>
      <td><strong>Data sent externally</strong></td>
      <td>Nothing — 100% client-side</td>
    </tr>
    <tr>
      <td><strong>Source</strong></td>
      <td><a href="https://github.com/CorentinTh/it-tools">github.com/CorentinTh/it-tools</a></td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="installation-link">Installation Link</h2>

<p>IT-Tools docker SetUp:</p>

<p>Links: <a href="/docs/it-tools/">It-Tools</a></p>

<hr />
<p><em>Questions / idea? Open an issue on <a href="https://github.com/Freaky2112/freaky2112.github.io">GitHub</a>.</em></p>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[IT-Tools: The Self-Hosted Swiss Army Knife for Developers]]></summary></entry><entry><title type="html">Grafana</title><link href="https://freaky2112.github.io/blog/2026/05/12/grafana/" rel="alternate" type="text/html" title="Grafana" /><published>2026-05-12T00:00:00+00:00</published><updated>2026-05-12T00:00:00+00:00</updated><id>https://freaky2112.github.io/blog/2026/05/12/grafana</id><content type="html" xml:base="https://freaky2112.github.io/blog/2026/05/12/grafana/"><![CDATA[<h1 id="grafana-installation">Grafana Installation</h1>

<h2 id="simple-docker-installtion-of-grafana">Simple Docker installtion of Grafana</h2>

<p>If you’ve ever set up a monitoring stack and found yourself staring at a list of tools wondering <em>“wait, why do I need all of these?”</em> — you’re not alone. The Grafana ecosystem is powerful, but it can feel like a lot of moving parts at first glance.</p>

<p>This post breaks down each component, what it does, and why it exists in your stack.</p>

<hr />

<h2 id="the-big-picture">The Big Picture</h2>

<p>Before diving in, here’s the mental model: <strong>data flows from your systems → through collectors → into storage → and finally into dashboards</strong>. Each tool owns one part of that pipeline.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Your Systems → [ Exporters / Agents ] → [ Storage ] → [ Grafana ]
</code></pre></div></div>

<hr />

<h2 id="component-breakdown">Component Breakdown</h2>

<h3 id="-grafana--the-dashboard-layer">🟠 Grafana — The Dashboard Layer</h3>

<p><strong>Role:</strong> Visualization and dashboards</p>

<p>Grafana is the face of your observability stack — the UI you actually look at. It doesn’t collect or store any data itself; it connects to data sources (like Prometheus or Loki) and renders charts, graphs, alerts, and dashboards from whatever those sources return.</p>

<p>Think of Grafana as the <strong>display screen</strong> in a control room. All the real work happens behind the scenes; Grafana just makes it human-readable.</p>

<p><strong>Key features:</strong></p>
<ul>
  <li>Connects to dozens of data sources (Prometheus, Loki, InfluxDB, Postgres, and more)</li>
  <li>Supports alerting rules and notification channels</li>
  <li>Provides a drag-and-drop dashboard builder</li>
</ul>

<hr />

<h3 id="-prometheus--the-metrics-database">🔴 Prometheus — The Metrics Database</h3>

<p><strong>Role:</strong> Collect and store time-series metrics</p>

<p>Prometheus is a pull-based metrics system. On a schedule, it scrapes HTTP endpoints (called <code class="language-plaintext highlighter-rouge">/metrics</code>) exposed by your services and stores the data as time-series values. It has its own query language called <strong>PromQL</strong>, which Grafana uses to pull data for your dashboards.</p>

<p><strong>How it works:</strong></p>
<ol>
  <li>Your services expose a <code class="language-plaintext highlighter-rouge">/metrics</code> endpoint</li>
  <li>Prometheus scrapes those endpoints every N seconds</li>
  <li>Data is stored locally in a time-series database</li>
  <li>Grafana queries Prometheus using PromQL</li>
</ol>

<p>Prometheus answers questions like: <em>“What was my CPU usage over the last 6 hours?”</em> or <em>“How many HTTP 500 errors per minute is my app throwing?”</em></p>

<hr />

<h3 id="️-node-exporter--linux-system-metrics">⚙️ Node Exporter — Linux System Metrics</h3>

<p><strong>Role:</strong> Expose host-level metrics (CPU, RAM, disk, network)</p>

<p>Prometheus can only scrape what is exposed to it. Node Exporter is a small agent you run on each Linux machine that reads system-level stats from the kernel and exposes them in Prometheus format.</p>

<p>Without Node Exporter, Prometheus knows nothing about the machine it’s running on. With it, you get rich hardware and OS metrics automatically.</p>

<p><strong>What it exposes:</strong></p>
<ul>
  <li>CPU usage (per core, idle, iowait, etc.)</li>
  <li>RAM and swap usage</li>
  <li>Disk I/O and filesystem usage</li>
  <li>Network traffic (bytes in/out, errors, drops)</li>
  <li>System load averages</li>
</ul>

<blockquote>
  <p><strong>One per host.</strong> Run one Node Exporter instance on each Linux machine you want to monitor.</p>
</blockquote>

<hr />

<h3 id="-loki--the-log-database">🟡 Loki — The Log Database</h3>

<p><strong>Role:</strong> Collect and store logs</p>

<p>Loki is Prometheus, but for logs. It stores log lines indexed by labels (not full-text), which makes it lightweight and cost-effective compared to alternatives like Elasticsearch. Grafana queries Loki using <strong>LogQL</strong>, a language very similar to PromQL.</p>

<p>The key design philosophy: <strong>Loki doesn’t index the content of your logs</strong> — only the metadata (labels like <code class="language-plaintext highlighter-rouge">app</code>, <code class="language-plaintext highlighter-rouge">host</code>, <code class="language-plaintext highlighter-rouge">env</code>). This keeps storage costs low while still making logs searchable.</p>

<p><strong>Loki answers questions like:</strong> <em>“Show me all error logs from the <code class="language-plaintext highlighter-rouge">payment-service</code> in the last 30 minutes.”</em></p>

<hr />

<h3 id="-alloy--the-modern-collector-recommended">🟣 Alloy — The Modern Collector (Recommended)</h3>

<p><strong>Role:</strong> Gather metrics, logs, and traces — and ship them to the right backends</p>

<p>Alloy is Grafana’s modern, unified collector agent. It replaces Promtail (and partially replaces other agents) with a single, composable pipeline tool. You define <strong>components</strong> that connect to sources, transform data, and forward it to destinations.</p>

<p>Alloy can:</p>
<ul>
  <li>Tail log files and send them to Loki</li>
  <li>Scrape Prometheus metrics</li>
  <li>Collect traces and send to Tempo</li>
  <li>Transform, filter, and enrich data along the way</li>
</ul>

<p>It uses a configuration language called <strong>River (Alloy syntax)</strong>, which makes complex pipelines readable and maintainable.</p>

<blockquote>
  <p><strong>New stacks should use Alloy.</strong> It’s actively developed and the strategic direction for the Grafana agent ecosystem.</p>
</blockquote>

<hr />

<h3 id="-promtail--the-legacy-log-shipper">🔵 Promtail — The Legacy Log Shipper</h3>

<p><strong>Role:</strong> Gather logs from files/systemd and send to Loki</p>

<p>Promtail is the older, simpler agent specifically designed to ship logs to Loki. It watches log files (or systemd journal) and forwards new lines to Loki with labels attached.</p>

<p>It works well and is stable, but it’s <strong>single-purpose</strong> — it only ships logs. Alloy can do everything Promtail does, plus much more.</p>

<p><strong>When to use Promtail:</strong> If you’re maintaining an existing setup that already uses it, there’s no urgent need to migrate. For new deployments, prefer Alloy.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>Promtail</th>
      <th>Alloy</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ships logs to Loki</td>
      <td>✅</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>Scrapes Prometheus metrics</td>
      <td>❌</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>Collects traces</td>
      <td>❌</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>Actively developed</td>
      <td>⚠️ Maintenance mode</td>
      <td>✅</td>
    </tr>
  </tbody>
</table>

<hr />

<h3 id="-cadvisor--docker-container-metrics">🐳 cAdvisor — Docker Container Metrics</h3>

<p><strong>Role:</strong> Expose resource usage metrics for Docker containers</p>

<p>Node Exporter tells you about the host machine. cAdvisor tells you about the <strong>containers running on it</strong>. It monitors Docker containers in real time and exposes per-container CPU, memory, network, and disk metrics in Prometheus format.</p>

<p><strong>What cAdvisor exposes:</strong></p>
<ul>
  <li>CPU usage per container</li>
  <li>Memory usage and limits</li>
  <li>Network I/O per container</li>
  <li>Container uptime and restart counts</li>
</ul>

<blockquote>
  <p><strong>Works alongside Node Exporter</strong>, not instead of it. You typically run both on any host running Docker containers.</p>
</blockquote>

<hr />

<h2 id="how-it-all-fits-together">How It All Fits Together</h2>

<p>Here’s the complete picture of a typical stack:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌─────────────────────────────────────────────┐
│                  Grafana                    │  ← You look at this
│           (Dashboards &amp; Alerts)             │
└──────────────┬──────────────────────────────┘
               │ queries
       ┌───────┴───────┐
       │               │
  Prometheus          Loki
  (metrics DB)      (log DB)
       │               │
       │ scrapes    receives logs
       │               │
  ┌────┴────┐     ┌────┴────┐
  │  Node   │     │  Alloy  │
  │Exporter │     │(or      │
  │cAdvisor │     │Promtail)│
  └─────────┘     └─────────┘
  Host &amp; container  Log shipper
  metrics
</code></pre></div></div>

<hr />

<h2 id="quick-reference">Quick Reference</h2>

<table>
  <thead>
    <tr>
      <th>Tool</th>
      <th>Type</th>
      <th>Role</th>
      <th>Ships Data To</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Grafana</strong></td>
      <td>Visualization</td>
      <td>Dashboards and alerts</td>
      <td>—</td>
    </tr>
    <tr>
      <td><strong>Prometheus</strong></td>
      <td>Database</td>
      <td>Stores time-series metrics</td>
      <td>Grafana</td>
    </tr>
    <tr>
      <td><strong>Node Exporter</strong></td>
      <td>Exporter</td>
      <td>Linux host metrics</td>
      <td>Prometheus</td>
    </tr>
    <tr>
      <td><strong>Loki</strong></td>
      <td>Database</td>
      <td>Stores logs</td>
      <td>Grafana</td>
    </tr>
    <tr>
      <td><strong>Alloy</strong></td>
      <td>Agent</td>
      <td>Collects &amp; ships metrics/logs/traces</td>
      <td>Prometheus, Loki, Tempo</td>
    </tr>
    <tr>
      <td><strong>Promtail</strong></td>
      <td>Agent (legacy)</td>
      <td>Ships logs</td>
      <td>Loki</td>
    </tr>
    <tr>
      <td><strong>cAdvisor</strong></td>
      <td>Exporter</td>
      <td>Docker container metrics</td>
      <td>Prometheus</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="summary">Summary</h2>

<p>Each tool in the Grafana stack has a focused, well-defined job:</p>

<ul>
  <li><strong>Grafana</strong> shows you everything</li>
  <li><strong>Prometheus</strong> and <strong>Loki</strong> store your metrics and logs</li>
  <li><strong>Node Exporter</strong> and <strong>cAdvisor</strong> expose what’s happening on your machines and containers</li>
  <li><strong>Alloy</strong> (or Promtail) moves log data into Loki</li>
</ul>

<p>Once you understand what each piece owns, the stack stops feeling complicated and starts feeling elegant — every component does exactly one thing, and they all plug together cleanly.</p>

<hr />

<h2 id="installation-link">Installation Link</h2>

<p>Grafana on docker:</p>

<p>Links: <a href="/docs/grafana/">Grafana</a></p>

<hr />
<p><em>Questions / idea? Open an issue on <a href="https://github.com/Freaky2112/freaky2112.github.io">GitHub</a>.</em></p>]]></content><author><name>Freaky</name></author><summary type="html"><![CDATA[Grafana Installation Simple Docker installtion of Grafana]]></summary></entry></feed>