<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Posts on Lead DevOps</title><link>https://lead-devops.blackdevhub.online/en/posts/</link><description>Recent content in Posts on Lead DevOps</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Sun, 04 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://lead-devops.blackdevhub.online/en/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>fixing memory leaks in python services: diagnostics and dump collection</title><link>https://lead-devops.blackdevhub.online/en/posts/python-memory-leaks-diagnostics/</link><pubDate>Sun, 04 Oct 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/python-memory-leaks-diagnostics/</guid><description>&lt;p&gt;Python services under load can silently consume memory until the cgroup limit triggers an OOM kill. Without systematic dump collection and introspection, root-cause analysis devolves into hypothesis spinning. Below is a practical set of commands and scripts for diagnostics, heap dump collection, and leak mitigation.&lt;/p&gt;&#10;&lt;h2 id="1-memory-consumption-diagnosis-commands"&gt;1. Memory Consumption Diagnosis Commands&#10;&lt;/h2&gt;&#10;&lt;p&gt;Basic level — &lt;code&gt;psutil&lt;/code&gt;. Installed in one line and works without process restart.&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-74c1b9f5-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="1"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-74c1b9f5-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install psutil&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Current process consumption:&lt;/p&gt;</description></item><item><title>SSH key best practices</title><link>https://lead-devops.blackdevhub.online/en/posts/post/</link><pubDate>Thu, 01 Oct 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/post/</guid><description>&lt;p&gt;SSH keys are the de facto standard for authenticating to infrastructure, but poor management turns every deployment into a potential vulnerability. This note collects proven practices: from key generation to revocation and rotation without service downtime.&lt;/p&gt;&#10;&lt;h2 id="introduction"&gt;Introduction&#10;&lt;/h2&gt;&#10;&lt;p&gt;SSH keys function as long‑lived credentials, and their lifecycle directly impacts supply‑chain security. Unlike passwords, keys are often created once and forgotten, leading to an accumulation of “zombie” keys with privileges that exceed current needs. Proper generation, binding to an agent, and regular rotation minimize the attack surface and enable auditing of changes. The following sections describe concrete commands and configurations used in operations.&lt;/p&gt;</description></item><item><title>kubectl cheatsheet: essential commands for Kubernetes</title><link>https://lead-devops.blackdevhub.online/en/posts/kubectl-cheatsheet/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/kubectl-cheatsheet/</guid><description>&lt;p&gt;kubectl is the primary interface to a Kubernetes cluster. This cheatheet covers routine operations — from context setup to pod debugging and namespace switching. All commands are verified against current kubectl versions (1.28+).&lt;/p&gt;&#10;&lt;h2 id="installation-and-context-setup"&gt;Installation and Context Setup&#10;&lt;/h2&gt;&#10;&lt;p&gt;Installation depends on your OS. On Linux, use the package manager or the binary directly:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-e824e41a-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="3"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-e824e41a-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -LO &lt;span class="s2"&gt;&amp;#34;https://dl.k8s.io/release/&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -L -s https://dl.k8s.io/release/stable.txt&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/bin/linux/amd64/kubectl&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x kubectl &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo mv kubectl /usr/local/bin/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl version --client&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Configuration lives in &lt;code&gt;~/.kube/config&lt;/code&gt;. A context defines the cluster, user, and default namespace.&lt;/p&gt;</description></item><item><title>Creating User and Role in Kubernetes and Binding Them via RBAC</title><link>https://lead-devops.blackdevhub.online/en/posts/k8s-user-role-rbac/</link><pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/k8s-user-role-rbac/</guid><description>&lt;p&gt;In Kubernetes there are no &amp;ldquo;users&amp;rdquo; in the traditional sense — there are ServiceAccounts and certificates, bound to roles through RBAC. Without proper configuration, anyone holding a kubeconfig gets full access to the cluster. Below is the complete cycle: create a ServiceAccount, define permissions, bind them, and verify.&lt;/p&gt;&#10;&lt;h2 id="creating-serviceaccount-and-generating-kubeconfig"&gt;Creating ServiceAccount and Generating kubeconfig&#10;&lt;/h2&gt;&#10;&lt;p&gt;Start by creating a ServiceAccount in the target namespace:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-912f8f44-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="1"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-912f8f44-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create serviceaccount devops-sa -n staging&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;To generate a kubeconfig, extract the token from secrets and build the config file:&lt;/p&gt;</description></item><item><title>Git Tag: Marking Releases and Bookmarks in History</title><link>https://lead-devops.blackdevhub.online/en/posts/git-tag/</link><pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/git-tag/</guid><description>&lt;h2 id="git-tag-marking-releases-and-bookmarks-in-history"&gt;Git Tag: Marking Releases and Bookmarks in History&#10;&lt;/h2&gt;&#10;&lt;p&gt;Tags are Git&amp;rsquo;s mechanism for assigning meaningful labels to specific commits. Unlike branches, tags don&amp;rsquo;t move — they&amp;rsquo;re pinned to a commit and serve as anchors for releases, versions, and critical checkpoints. Without tags, release history devolves into a hash search — and that&amp;rsquo;s a direct path to deployment errors.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="types-of-tags-lightweight-vs-annotated"&gt;Types of Tags: Lightweight vs Annotated&#10;&lt;/h2&gt;&#10;&lt;p&gt;There are two types of tags. Lightweight is just a name attached to a commit, with no additional metadata. Annotated is a full Git object with author, date, message, and signing capability.&lt;/p&gt;</description></item><item><title>Deploying with a post-receive Git Hook</title><link>https://lead-devops.blackdevhub.online/en/posts/git-hook-post-receive-dlya-deploya/</link><pubDate>Sat, 19 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/git-hook-post-receive-dlya-deploya/</guid><description>&lt;p&gt;Deploying through CI is great, but sometimes you just need to push code to a server with a single &lt;code&gt;git push&lt;/code&gt;. The &lt;code&gt;post-receive&lt;/code&gt; hook in a bare repository handles this without extra dependencies: push to the server, and the hook automatically checks out files into the working directory.&lt;/p&gt;&#10;&lt;h2 id="schema-bare-repo-as-a-deploy-trigger"&gt;Schema: bare repo as a deploy trigger&#10;&lt;/h2&gt;&#10;&lt;p&gt;The logic is straightforward:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;A bare repository is created on the server (e.g., &lt;code&gt;/srv/deploy/app.git&lt;/code&gt;).&lt;/li&gt;&#10;&lt;li&gt;The developer adds it as a remote and runs &lt;code&gt;git push origin main&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;Git receives the data and triggers &lt;code&gt;hooks/post-receive&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;The hook script runs &lt;code&gt;git --work-tree=/var/www/app --git-dir=/srv/deploy/app.git checkout -f main&lt;/code&gt;.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="td-callout td-callout--note" role="note"&gt;&#10; &lt;div class="td-callout__title"&gt;&lt;i class="td-callout__icon fa-solid fa-circle-info" aria-hidden="true"&gt;&lt;/i&gt;&lt;span class="td-callout__label"&gt;Note&lt;/span&gt;&lt;/div&gt;&#10; &lt;div class="td-callout__body"&gt;&#10;&lt;p&gt;A bare repository has no working directory. That is why &lt;code&gt;post-receive&lt;/code&gt; must explicitly pass &lt;code&gt;--work-tree&lt;/code&gt; so &lt;code&gt;checkout&lt;/code&gt; knows where to write files.&lt;/p&gt;</description></item><item><title>ulimit and systemd LimitNOFILE — why ulimit -n inside a unit doesn't stick</title><link>https://lead-devops.blackdevhub.online/en/posts/ulimit-i-systemd-limitnofile/</link><pubDate>Sat, 19 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ulimit-i-systemd-limitnofile/</guid><description>&lt;h2 id="what-is-nofile-and-where-it-lives"&gt;What is nofile and where it lives&#10;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;nofile&lt;/code&gt; is the maximum number of open file descriptors per process. That&amp;rsquo;s not just regular files — it covers sockets, pipes, stdin/stdout/stderr, logs shipped through journald — everything counts. When nginx or a Go app crashes with &lt;code&gt;too many open files&lt;/code&gt;, this is the limit to blame.&lt;/p&gt;&#10;&lt;p&gt;Limits live at three levels:&lt;/p&gt;&#10;&lt;div class="td-table-scroll td-table-scroll--static"&gt;&#10;&lt;table&gt;&#10; &lt;thead&gt;&#10; &lt;tr&gt;&#10; &lt;th scope="col"&gt;Level&lt;/th&gt;&#10; &lt;th scope="col"&gt;Where to check&lt;/th&gt;&#10; &lt;th scope="col"&gt;What it controls&lt;/th&gt;&#10; &lt;/tr&gt;&#10; &lt;/thead&gt;&#10; &lt;tbody&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;Kernel (system-wide)&lt;/td&gt;&#10; &lt;td&gt;&lt;code&gt;/proc/sys/fs/file-max&lt;/code&gt;, &lt;code&gt;/proc/sys/fs/nr_open&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Absolute ceiling for the whole system&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;PAM / login&lt;/td&gt;&#10; &lt;td&gt;&lt;code&gt;/etc/security/limits.conf&lt;/code&gt;, &lt;code&gt;/etc/security/limits.d/&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;For sessions via &lt;code&gt;pam_limits.so&lt;/code&gt;&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;systemd&lt;/td&gt;&#10; &lt;td&gt;&lt;code&gt;LimitNOFILE=&lt;/code&gt; in unit, &lt;code&gt;DefaultLimitNOFILE=&lt;/code&gt; in &lt;code&gt;system.conf&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;For systemd-managed services&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="td-callout td-callout--note" role="note"&gt;&#10; &lt;div class="td-callout__title"&gt;&lt;i class="td-callout__icon fa-solid fa-circle-info" aria-hidden="true"&gt;&lt;/i&gt;&lt;span class="td-callout__label"&gt;Note&lt;/span&gt;&lt;/div&gt;&#10; &lt;div class="td-callout__body"&gt;&#10;&lt;p&gt;&lt;code&gt;/proc/sys/fs/nr_open&lt;/code&gt; is the upper bound you can raise &lt;code&gt;nofile&lt;/code&gt; to for a single process. It defaults to &lt;code&gt;1073741816&lt;/code&gt; (≈1B) on most distros, but in practice you rarely need more than &lt;code&gt;1048576&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>coredumpctl: Finding a Binary Crash</title><link>https://lead-devops.blackdevhub.online/en/posts/coredumpctl-naiti-padenie-binarya/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/coredumpctl-naiti-padenie-binarya/</guid><description>&lt;h2 id="what-is-coredumpctl-and-how-it-works"&gt;What is coredumpctl and how it works&#10;&lt;/h2&gt;&#10;&lt;p&gt;When a binary crashes with SEGV, the kernel can save a core dump — a snapshot of process memory at the moment of the crash. In systemd-based distributions, &lt;code&gt;coredumpctl&lt;/code&gt; handles collecting, storing, and searching these dumps. It&amp;rsquo;s a wrapper around &lt;code&gt;systemd-coredump&lt;/code&gt;, which stores dumps in &lt;code&gt;/var/lib/systemd/coredump/&lt;/code&gt; and indexes metadata through journald.&lt;/p&gt;&#10;&lt;div class="td-callout td-callout--note" role="note"&gt;&#10; &lt;div class="td-callout__title"&gt;&lt;i class="td-callout__icon fa-solid fa-circle-info" aria-hidden="true"&gt;&lt;/i&gt;&lt;span class="td-callout__label"&gt;Note&lt;/span&gt;&lt;/div&gt;&#10; &lt;div class="td-callout__body"&gt;&#10;&lt;p&gt;Requires &lt;code&gt;systemd-coredump&lt;/code&gt; and an active journald. In minimal containers without systemd, this tool is unavailable.&lt;/p&gt;</description></item><item><title>curl --resolve and SNI: Testing Virtual Hosts Without /etc/hosts</title><link>https://lead-devops.blackdevhub.online/en/posts/curl-resolve-i-sni/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/curl-resolve-i-sni/</guid><description>&lt;p&gt;When you need to test a virtual host on a specific IP but don&amp;rsquo;t want to edit &lt;code&gt;/etc/hosts&lt;/code&gt; — whether due to permissions, conflicts with other services, or just the habit of keeping the file clean — &lt;code&gt;curl --resolve&lt;/code&gt; solves both problems at once: it overrides DNS resolution and sends the correct SNI in the TLS handshake.&lt;/p&gt;&#10;&lt;h2 id="problem-virtual-host-without-editing-etchosts"&gt;Problem: virtual host without editing /etc/hosts&#10;&lt;/h2&gt;&#10;&lt;p&gt;Multiple virtual hosts can live on a single IP, and the server picks the right one based on the &lt;code&gt;Host&lt;/code&gt; header (HTTP/1.1) and SNI (TLS). Without an entry in &lt;code&gt;/etc/hosts&lt;/code&gt;, curl first tries to resolve the name through DNS — getting the wrong IP, or no response at all.&lt;/p&gt;</description></item><item><title>Docker logs and journald: choosing a logging driver</title><link>https://lead-devops.blackdevhub.online/en/posts/docker-logs-i-journald/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/docker-logs-i-journald/</guid><description>&lt;p&gt;When a container crashes, logs are the first thing you need to see. &lt;code&gt;docker logs&lt;/code&gt; looks simple, but under the hood different logging drivers are at work, and the choice affects how logs are stored, rotated, and accessed. Here is what you should know before trusting the default.&lt;/p&gt;&#10;&lt;h2 id="how-docker-logs-works"&gt;How docker logs works&#10;&lt;/h2&gt;&#10;&lt;p&gt;The &lt;code&gt;docker logs &amp;lt;container&amp;gt;&lt;/code&gt; command reads the container&amp;rsquo;s stdout/stderr stream and outputs it to the terminal. Behind this sits a &lt;strong&gt;logging driver&lt;/strong&gt; — a component that determines where the data actually goes. By default it is &lt;code&gt;json-file&lt;/code&gt;: each container gets a JSON file on the host into which every output line is written.&lt;/p&gt;</description></item><item><title>scp — Secure Copy Over SSH</title><link>https://lead-devops.blackdevhub.online/en/posts/scp/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/scp/</guid><description>&lt;p&gt;scp — a utility for copying files over SSH using the SSH protocol. It works from the terminal, requires no extra server setup — just a running sshd and working authentication. In an era of rsync and bat, SCP survives as a simple tool for one-off transfers when you don&amp;rsquo;t want to deal with daemons or configuration files.&lt;/p&gt;&#10;&lt;h2 id="syntax-and-basic-scenarios"&gt;Syntax and Basic Scenarios&#10;&lt;/h2&gt;&#10;&lt;p&gt;General form:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-34b643d4-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="1"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-34b643d4-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scp &lt;span class="o"&gt;[&lt;/span&gt;flags&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; destination&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Source and destination can be local paths or remote addresses in the format &lt;code&gt;user@host:path&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Sudoers: NOPASSWD Without Holes</title><link>https://lead-devops.blackdevhub.online/en/posts/sudoers-nopasswd-bez-dyr/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/sudoers-nopasswd-bez-dyr/</guid><description>&lt;p&gt;Unrestricted &lt;code&gt;NOPASSWD&lt;/code&gt; in sudoers is a misconfiguration that grants root access without a password, turning any user script or library vulnerability into a full system compromise. The correct approach limits &lt;code&gt;NOPASSWD&lt;/code&gt; to specific commands only.&lt;/p&gt;&#10;&lt;h2 id="why-nopasswd--all-is-a-hole-not-a-solution"&gt;Why NOPASSWD + ALL Is a Hole, Not a Solution&#10;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;%admin ALL=(ALL) NOPASSWD: ALL&lt;/code&gt; — the most common sudoers error. The user receives unlimited root access without a password. Any script, any utility, any vulnerability in the user&amp;rsquo;s environment becomes a direct path to full machine control. &lt;code&gt;NOPASSWD&lt;/code&gt; without command restrictions is not convenience; it is a backdoor in plain sight.&lt;/p&gt;</description></item><item><title>ThinLinc: Remote Access to Linux Desktops</title><link>https://lead-devops.blackdevhub.online/en/posts/thinlinc/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/thinlinc/</guid><description>&lt;h2 id="thinlinc-remote-access-to-linux-desktops"&gt;ThinLinc: Remote Access to Linux Desktops&#10;&lt;/h2&gt;&#10;&lt;p&gt;In enterprise environments, remote access to Linux desktops often comes down to VNC with flaky encryption or RDP proxies held together with workarounds. ThinLinc by Cendio is a full-featured remote desktop solution that runs on top of VNC, supports RDP clients, and provides a web-based administration interface without the usual hassle with certificates and firewalls.&lt;/p&gt;&#10;&lt;h2 id="what-is-thinlinc"&gt;What Is ThinLinc&#10;&lt;/h2&gt;&#10;&lt;p&gt;ThinLinc is a remote desktop access solution with a server-plus-clients architecture. The server runs VNC sessions on the backend, and clients connect through a web browser or native ThinLinc clients. The protocol between client and server is tunneled over SSH, which solves the encryption problem out of the box.&lt;/p&gt;</description></item><item><title>Chrony Instead of ntpd</title><link>https://lead-devops.blackdevhub.online/en/posts/chrony-vmesto-ntpd/</link><pubDate>Thu, 17 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/chrony-vmesto-ntpd/</guid><description>&lt;p&gt;Chrony has replaced &lt;code&gt;ntpd&lt;/code&gt; as the default NTP client in most modern Linux distributions. It converges to accurate time faster, handles intermittent network connections better, and consumes fewer resources. If your machine still runs &lt;code&gt;ntpd&lt;/code&gt;, switching takes only a few minutes.&lt;/p&gt;&#10;&lt;h2 id="installation"&gt;Installation&#10;&lt;/h2&gt;&#10;&lt;p&gt;On RHEL-based systems:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-9c7c65e5-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="2"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-9c7c65e5-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dnf install chrony -y&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; --now chronyd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;On Debian/Ubuntu:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-9c7c65e5-fence-1" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="2"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-9c7c65e5-fence-1-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install chrony -y&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; --now chronyd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;If &lt;code&gt;ntpd&lt;/code&gt; was running on this machine before, stop and disable it to avoid port conflicts:&lt;/p&gt;</description></item><item><title>fail2ban: SSH Jail Configuration</title><link>https://lead-devops.blackdevhub.online/en/posts/fail2ban-jail-dlya-sshd/</link><pubDate>Thu, 17 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/fail2ban-jail-dlya-sshd/</guid><description>&lt;p&gt;Securing SSH against brute-force attacks is one of the first steps in hardening any server. fail2ban scans logs, detects repeated failed login attempts, and blocks the source via iptables or nftables. This note covers the sshd jail — from installation to fine-tuning ban durations.&lt;/p&gt;&#10;&lt;h2 id="installation-and-basic-configuration"&gt;Installation and Basic Configuration&#10;&lt;/h2&gt;&#10;&lt;p&gt;Install from the standard repository:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-c026252a-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="5"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-c026252a-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Debian/Ubuntu&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install fail2ban&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# RHEL/CentOS&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yum install fail2ban&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Enable and start the service:&lt;/p&gt;</description></item><item><title>journalctl: filters and follow</title><link>https://lead-devops.blackdevhub.online/en/posts/journalctl-filtry-i-follow/</link><pubDate>Thu, 17 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/journalctl-filtry-i-follow/</guid><description>&lt;p&gt;Systemd&amp;rsquo;s journal is the first place to look when a service crashes or a node starts burning CPU. &lt;code&gt;journalctl&lt;/code&gt; does far more than dump the entire log in sequence: it can filter by units, priorities, time windows, and stream in real time. Below is the working set I use daily.&lt;/p&gt;&#10;&lt;h2 id="follow-in-real-time"&gt;Follow in real time&#10;&lt;/h2&gt;&#10;&lt;p&gt;Behavior similar to &lt;code&gt;tail -f&lt;/code&gt;, but aware of journald&amp;rsquo;s structured format:&lt;/p&gt;</description></item><item><title>nftables: Basic Rule Set</title><link>https://lead-devops.blackdevhub.online/en/posts/nftables-bazovyi-nabor-pravil/</link><pubDate>Thu, 17 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/nftables-bazovyi-nabor-pravil/</guid><description>&lt;div class="td-callout td-callout--note" role="note"&gt;&#10; &lt;div class="td-callout__title"&gt;&lt;i class="td-callout__icon fa-solid fa-circle-info" aria-hidden="true"&gt;&lt;/i&gt;&lt;span class="td-callout__label"&gt;Note&lt;/span&gt;&lt;/div&gt;&#10; &lt;div class="td-callout__body"&gt;&#10;&lt;p&gt;All commands were verified on Debian/Ubuntu with the &lt;code&gt;nftables&lt;/code&gt; package and on RHEL/CentOS 8+. On older systems you may need &lt;code&gt;apt install nftables&lt;/code&gt; or &lt;code&gt;yum install nftables&lt;/code&gt;.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;nftables replaced iptables, but documentation for a basic rule set is often scattered. Here is the reference I use when bringing up a firewall on a new host.&lt;/p&gt;&#10;&lt;h2 id="creating-the-inet-filter-table"&gt;Creating the inet filter table&#10;&lt;/h2&gt;&#10;&lt;p&gt;The &lt;code&gt;inet&lt;/code&gt; family table unifies IPv4 and IPv6 under a single namespace. This is the preferred approach when both stacks are active on the host.&lt;/p&gt;</description></item><item><title>Debian — The Swiss Army Knife of Linux</title><link>https://lead-devops.blackdevhub.online/en/posts/debian-swiss-army-knife-linux/</link><pubDate>Tue, 15 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/debian-swiss-army-knife-linux/</guid><description>&lt;p&gt;Debian isn&amp;rsquo;t the flashiest distribution, but it&amp;rsquo;s the most reliable foundation in the Linux world. Behind it stands the largest community of volunteer developers, and behind its track record are decades of uninterrupted operation on servers, embedded systems, and cloud infrastructure. If you manage Linux machines in production, Debian (or one of its derivatives) is already in your stack — whether you&amp;rsquo;ve acknowledged it or not.&lt;/p&gt;&#10;&lt;h2 id="managing-packages-apt-and-dpkg"&gt;Managing Packages: apt and dpkg&#10;&lt;/h2&gt;&#10;&lt;p&gt;Two tools form the core of Debian&amp;rsquo;s packaging system. &lt;code&gt;apt&lt;/code&gt; is the high-level interface for working with repositories, resolving dependencies, and upgrading the system. &lt;code&gt;dpkg&lt;/code&gt; is the low-level engine that installs, removes, and inspects individual &lt;code&gt;.deb&lt;/code&gt; files without contacting repositories.&lt;/p&gt;</description></item><item><title>pipx: Isolated Python CLI Tools Without the Mess</title><link>https://lead-devops.blackdevhub.online/en/posts/pipx/</link><pubDate>Thu, 10 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/pipx/</guid><description>&lt;p&gt;pipx solves a simple but chronic problem: you need to run a Python utility once or occasionally, and &lt;code&gt;pip install&lt;/code&gt; pollutes the global environment or leaves behind a virtual environment you forget to clean up. pipx creates an isolated venv for each utility, installs dependencies there, and makes the binary available in &lt;code&gt;$PATH&lt;/code&gt;. One command and the tool works without conflicting with anything.&lt;/p&gt;&#10;&lt;h2 id="what-is-pipx-and-why-you-need-it"&gt;What Is pipx and Why You Need It&#10;&lt;/h2&gt;&#10;&lt;p&gt;pipx installs and runs Python applications in isolated virtual environments. Each utility lives in its own venv under &lt;code&gt;~/.local/pipx/venvs/&lt;/code&gt;, and its console-scripts are symlinked into &lt;code&gt;~/.local/bin/&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>uv — Fast Python Package Manager</title><link>https://lead-devops.blackdevhub.online/en/posts/uv-python-package-manager/</link><pubDate>Wed, 09 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/uv-python-package-manager/</guid><description>&lt;h2 id="what-is-uv"&gt;What is uv&#10;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;uv&lt;/code&gt; is a Python package manager written in Rust. It solves one problem: the standard &lt;code&gt;pip&lt;/code&gt; is slow at resolving dependencies, and &lt;code&gt;poetry&lt;/code&gt; adds its own project model on top of PEP 621. &lt;code&gt;uv&lt;/code&gt; works with &lt;code&gt;pyproject.toml&lt;/code&gt;, is compatible with PEP 621 and PEP 508, and does it significantly faster.&lt;/p&gt;&#10;&lt;p&gt;Under the hood is a caching resolver written in Rust that reuses data from pip-compatible indexes (PyPI by default). &lt;code&gt;uv&lt;/code&gt; can replace &lt;code&gt;pip&lt;/code&gt;, &lt;code&gt;pip-tools&lt;/code&gt;, &lt;code&gt;virtualenv&lt;/code&gt;, and &lt;code&gt;poetry&lt;/code&gt; in a single tool.&lt;/p&gt;</description></item><item><title>logrotate for Custom Daemons</title><link>https://lead-devops.blackdevhub.online/en/posts/logrotate-custom-daemons/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/logrotate-custom-daemons/</guid><description>&lt;p&gt;Log rotation is missing for your daemon, the log file has grown to dozens of gigabytes, the disk is full, and monitoring is screaming. systemd-journald and syslog-ng rotate on their own, but if your custom daemon writes directly to a file, rotation falls to logrotate. Here is how to configure it for a specific service.&lt;/p&gt;&#10;&lt;h2 id="why-write-a-custom-logrotate-config"&gt;Why write a custom logrotate config&#10;&lt;/h2&gt;&#10;&lt;p&gt;Packages from the repository usually drop their config into &lt;code&gt;/etc/logrotate.d/&lt;/code&gt;, but for self-built daemons or those compiled from source, there is none. Without a config the file grows without limits. logrotate runs via a systemd timer (&lt;code&gt;logrotate.timer&lt;/code&gt;) or cron and reads all files from &lt;code&gt;/etc/logrotate.d/&lt;/code&gt;. Creating a single file is enough to start the rotation cycle.&lt;/p&gt;</description></item><item><title>Rsync: Backing Up a Directory Over SSH</title><link>https://lead-devops.blackdevhub.online/en/posts/rsync-ssh-backup/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/rsync-ssh-backup/</guid><description>&lt;h2 id="rsync-backing-up-a-directory-over-ssh"&gt;Rsync: Backing Up a Directory Over SSH&#10;&lt;/h2&gt;&#10;&lt;p&gt;The classic way to copy a directory to a remote machine is &lt;code&gt;rsync&lt;/code&gt; over SSH. No extra ports to open, traffic is encrypted, and the tool itself handles incremental transfers and metadata preservation. One command and the backup is ready.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="basic-rsync-command-over-ssh"&gt;Basic rsync Command Over SSH&#10;&lt;/h2&gt;&#10;&lt;p&gt;The minimal invocation to copy a local directory to a remote host:&lt;/p&gt;</description></item><item><title>Setting Up Your Own SSH Bastion Server</title><link>https://lead-devops.blackdevhub.online/en/posts/ssh-bastion-server/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ssh-bastion-server/</guid><description>&lt;h2 id="why-you-need-a-bastion-and-where-it-lives"&gt;Why You Need a Bastion and Where It Lives&#10;&lt;/h2&gt;&#10;&lt;p&gt;A bastion is the single entry point into a private network segment. Instead of exposing SSH on every server to the internet, you funnel traffic through one hardened host with a strict access policy. Typical layout: internet → bastion (public IP) → internal servers (only private subnet, SSH listening on &lt;code&gt;127.0.0.1&lt;/code&gt; or a private interface).&lt;/p&gt;&#10;&lt;p&gt;The bastion sits in a demilitarized zone (DMZ) or a public subnet provided by your hosting platform. Internal machines have no route to the internet through the bastion — return traffic flows only over established connections. This is a baseline model you can deploy on any VPS in about 15 minutes.&lt;/p&gt;</description></item><item><title>tmux on Prod After Screen</title><link>https://lead-devops.blackdevhub.online/en/posts/tmux-after-screen/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/tmux-after-screen/</guid><description>&lt;h2 id="why-we-switched-from-screen-to-tmux"&gt;Why We Switched from Screen to tmux&#10;&lt;/h2&gt;&#10;&lt;p&gt;Screen was our primary tool for about five years. After migrating the cluster to new servers it became obvious: &lt;code&gt;screen&lt;/code&gt; drops sessions on SSH disconnect when &lt;code&gt;hardstatus&lt;/code&gt; isn&amp;rsquo;t configured, and &lt;code&gt;screen -r&lt;/code&gt; recovery sometimes hits a race condition when multiple admins connect simultaneously. tmux solves both problems out of the box — sessions live in server memory, are bound to a socket, and reconnection doesn&amp;rsquo;t depend on the TCP connection state.&lt;/p&gt;</description></item><item><title>bpftrace: one-liners that replace strace in production</title><link>https://lead-devops.blackdevhub.online/en/posts/bpftrace-one-liners-replace-strace/</link><pubDate>Mon, 07 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/bpftrace-one-liners-replace-strace/</guid><description>&lt;p&gt;strace halts a process on every syscall. On a live server at 2000 RPS, that means timeouts and alerts. bpftrace runs through eBPF in the kernel — tracing happens in parallel, without stopping anything. The overhead difference is orders of magnitude.&lt;/p&gt;&#10;&lt;h2 id="installation"&gt;Installation&#10;&lt;/h2&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-8a252501-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="11"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-8a252501-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Debian / Ubuntu&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install bpftrace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# RHEL / CentOS / Fedora&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dnf install bpftrace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Arch&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo pacman -S bpftrace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Verify&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo bpftrace -V&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Full probe coverage requires debug symbols:&lt;/p&gt;</description></item><item><title>ip: Network Setup and Diagnostics in CLI</title><link>https://lead-devops.blackdevhub.online/en/posts/ip-command-network-cli/</link><pubDate>Mon, 07 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ip-command-network-cli/</guid><description>&lt;p&gt;When ifconfig returns nothing and configuring a route requires a separate command, that&amp;rsquo;s not a system bug. It&amp;rsquo;s iproute2 — the package that replaced net-tools in modern Linux distributions. The &lt;code&gt;ip&lt;/code&gt; utility from iproute2 is the standard interface for managing the Linux network stack. It covers interfaces, addresses, routes, ARP cache, routing policies, and namespace isolation.&lt;/p&gt;&#10;&lt;h2 id="why-iproute2-replaced-net-tools"&gt;Why iproute2 replaced net-tools&#10;&lt;/h2&gt;&#10;&lt;p&gt;net-tools (ifconfig, route, arp, netstat, nameif) originated in BSD and migrated to Linux in the 1990s. By the 2000s it became clear: they cannot handle VLAN, IPsec, QoS, multicast routing, or Policy Routing. Each task required a separate command with unrelated syntax.&lt;/p&gt;</description></item><item><title>nslookup and drill: DNS resolution in terminal</title><link>https://lead-devops.blackdevhub.online/en/posts/nslookup-drill-dns-resolution/</link><pubDate>Mon, 07 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/nslookup-drill-dns-resolution/</guid><description>&lt;p&gt;The server won&amp;rsquo;t resolve a domain, but pings fly through. No familiar dig at hand — the BIOS is already loading a minimal busybox. Or on a host without bind-tools. nslookup and drill fill this gap: the first one is built into almost everything, the second gives more context when debugging.&lt;/p&gt;&#10;&lt;h2 id="nslookup-interactive-and-one-liner-modes"&gt;nslookup: interactive and one-liner modes&#10;&lt;/h2&gt;&#10;&lt;p&gt;nslookup ships with bind-utils and isc-dhcp-client. It works in two modes.&lt;/p&gt;</description></item><item><title>journalctl: Filtering and Formatting systemd Logs</title><link>https://lead-devops.blackdevhub.online/en/posts/journalctl-filtering-formatting/</link><pubDate>Sun, 06 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/journalctl-filtering-formatting/</guid><description>&lt;p&gt;Logs disappeared. Server rebooted, and the familiar &lt;code&gt;less /var/log/syslog&lt;/code&gt; returns nothing. On modern distros with systemd, logs are collected by journald and read with &lt;code&gt;journalctl&lt;/code&gt;. Without knowing its filters, system debugging turns into guesswork.&lt;/p&gt;&#10;&lt;h2 id="why-logs-disappear-after-reboot"&gt;Why Logs Disappear After Reboot&#10;&lt;/h2&gt;&#10;&lt;p&gt;By default, journal stores data in &lt;code&gt;/run/log/journal/&lt;/code&gt; — a tmpfs that wipes on reboot. To make logs survive reboots, create the directory:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-eaf2b1d9-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="2"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-eaf2b1d9-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkdir -p /var/log/journal&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemd-tmpfiles --create --prefix /var/log/journal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Then restart systemd-journald:&lt;/p&gt;</description></item><item><title>OpenSSL: TLS Certificate Verification and Parsing in CLI</title><link>https://lead-devops.blackdevhub.online/en/posts/openssl-check-tls-certificates/</link><pubDate>Sun, 06 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/openssl-check-tls-certificates/</guid><description>&lt;p&gt;Certificates expiring on prod at the worst moment — a familiar story. OpenSSL answers TLS certificate questions faster than any marketplace checker. Here are the key scenarios without the fluff.&lt;/p&gt;&#10;&lt;h2 id="basic-certificate-parsing"&gt;Basic Certificate Parsing&#10;&lt;/h2&gt;&#10;&lt;p&gt;The first command for any diagnostics is the text dump:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-63c22da9-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="1"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-63c22da9-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openssl x509 -text -noout -in cert.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Output shows Subject, Issuer, validity dates, signature algorithm, and public key. For a quick summary without the wall of text:&lt;/p&gt;</description></item><item><title>ProxyJump and bastion hosts via ~/.ssh/config</title><link>https://lead-devops.blackdevhub.online/en/posts/ssh-proxyjump-bastion-config/</link><pubDate>Sun, 06 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ssh-proxyjump-bastion-config/</guid><description>&lt;p&gt;Sometimes a server sits in a private network with no public IP. The only entry point is a bastion host with a public address. Typing &lt;code&gt;ssh -J user@bastion user@private&lt;/code&gt; every time gets old fast. Here&amp;rsquo;s how to configure everything in &lt;code&gt;~/.ssh/config&lt;/code&gt; so you can reach private networks in one command.&lt;/p&gt;&#10;&lt;h2 id="why-you-need-a-bastion-host"&gt;Why you need a bastion host&#10;&lt;/h2&gt;&#10;&lt;p&gt;A bastion (jump host, jump box) is an intermediate server with public access that proxies connections to infrastructure without external IPs. The typical topology:&lt;/p&gt;</description></item><item><title>auditd: file access and syscall logging</title><link>https://lead-devops.blackdevhub.online/en/posts/auditd-file-syscall-logging/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/auditd-file-syscall-logging/</guid><description>&lt;p&gt;Linux doesn&amp;rsquo;t write every access to &lt;code&gt;/etc/shadow&lt;/code&gt; or every &lt;code&gt;unlink&lt;/code&gt; call to syslog. For incident investigation and compliance this is critical. auditd solves this: the Linux Audit kernel subsystem records system calls, file access, and more.&lt;/p&gt;&#10;&lt;h2 id="installation-and-startup"&gt;Installation and Startup&#10;&lt;/h2&gt;&#10;&lt;p&gt;auditd comes in the &lt;code&gt;audit&lt;/code&gt; package available in any distribution.&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-b9f47e43-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="8"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-b9f47e43-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Debian/Ubuntu&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install auditd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# RHEL/CentOS/Alma&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yum install audit&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Arch&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pacman -S audit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;After installation, start the service via systemd.&lt;/p&gt;</description></item><item><title>logrotate: automatic log rotation and archiving</title><link>https://lead-devops.blackdevhub.online/en/posts/logrotate-auto-rotation/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/logrotate-auto-rotation/</guid><description>&lt;p&gt;Application logs fill up disk space within a week, and manually running &lt;code&gt;rm *.log&lt;/code&gt; is a recipe for trouble. logrotate handles this automatically: it rotates, compresses, and deletes old files on a schedule. Let&amp;rsquo;s see how it works and how to set it up in five minutes.&lt;/p&gt;&#10;&lt;h2 id="how-it-works"&gt;How It Works&#10;&lt;/h2&gt;&#10;&lt;p&gt;logrotate runs daily through cron. The default config lives in &lt;code&gt;/etc/logrotate.conf&lt;/code&gt;, and additional configs are included from &lt;code&gt;/etc/logrotate.d/&lt;/code&gt;. During rotation, the current file gets renamed, a new empty one is created, old copies are compressed and numbered.&lt;/p&gt;</description></item><item><title>sshd_config: baseline for a test stand</title><link>https://lead-devops.blackdevhub.online/en/posts/sshd-config-baseline/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/sshd-config-baseline/</guid><description>&lt;p&gt;SSH access to a test stand often gets opened in a hurry, and then the logs fill with brute-force attempts. A baseline sshd_config that blocks common attack vectors fits into five parameters and twenty minutes.&lt;/p&gt;&#10;&lt;h2 id="why-change-defaults"&gt;Why Change Defaults&#10;&lt;/h2&gt;&#10;&lt;p&gt;Distribution-provided sshd ships with permissive settings: root login via password, no user restrictions, three authentication attempts. On a test stand this is tolerable until the logs show:&lt;/p&gt;</description></item><item><title>systemd-run: Run Services Without Unit Files</title><link>https://lead-devops.blackdevhub.online/en/posts/systemd-run-transient-services/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/systemd-run-transient-services/</guid><description>&lt;p&gt;Sometimes you need to run a process under systemd&amp;rsquo;s control without writing a unit file — maybe you&amp;rsquo;re in a container without systemd, on someone else&amp;rsquo;s machine, or just need a quick one-off. That&amp;rsquo;s where &lt;code&gt;systemd-run&lt;/code&gt; comes in.&lt;/p&gt;&#10;&lt;h2 id="why-systemd-run"&gt;Why systemd-run&#10;&lt;/h2&gt;&#10;&lt;p&gt;The tool creates a &lt;strong&gt;transient unit&lt;/strong&gt; — a unit that exists only in systemd&amp;rsquo;s memory, with no file on disk. This is useful when you need:&lt;/p&gt;</description></item><item><title>curl: HTTP Debugging in CLI</title><link>https://lead-devops.blackdevhub.online/en/posts/curl-http-debugging-cli/</link><pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/curl-http-debugging-cli/</guid><description>&lt;p&gt;cURL is the standard tool for debugging HTTP in the terminal. It ships out of the box on Linux and macOS and is present in most Docker images. Need to quickly check an API, inspect response headers, or trace a redirect issue — one command line is enough.&lt;/p&gt;&#10;&lt;h2 id="basic-debug-flags"&gt;Basic Debug Flags&#10;&lt;/h2&gt;&#10;&lt;p&gt;The most common scenario: get a response and see what the server returned. The &lt;code&gt;-i&lt;/code&gt; flag prints headers before the body, &lt;code&gt;-v&lt;/code&gt; enables verbose mode with connection details.&lt;/p&gt;</description></item><item><title>ethtool: network interface diagnostics and tuning</title><link>https://lead-devops.blackdevhub.online/en/posts/ethtool-diagnosis-tuning-network-interface/</link><pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ethtool-diagnosis-tuning-network-interface/</guid><description>&lt;p&gt;Network issues hide well — interface is up, IP is assigned, iptables is quiet, yet packet loss or micro-freezes only surface under load. ethtool gives direct access to hardware state, driver behavior, and offload mechanisms that neither &lt;code&gt;ip&lt;/code&gt; nor &lt;code&gt;netstat&lt;/code&gt; expose.&lt;/p&gt;&#10;&lt;h2 id="basic-output-link-state"&gt;Basic Output: Link State&#10;&lt;/h2&gt;&#10;&lt;p&gt;Installation is straightforward:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-f5ba18e4-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="5"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-f5ba18e4-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# RHEL/Alma/Rocky&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dnf install ethtool -y&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Debian/Ubuntu&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install ethtool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Running ethtool without flags prints a summary:&lt;/p&gt;</description></item><item><title>lsof: which processes listen on port and hold file</title><link>https://lead-devops.blackdevhub.online/en/posts/lsof-port-file-processes/</link><pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/lsof-port-file-processes/</guid><description>&lt;p&gt;Service won&amp;rsquo;t start — port 8080 is already bound. You dig into who&amp;rsquo;s holding it, and discover the same process has your config file open while you&amp;rsquo;re trying to edit it. lsof answers both questions: which processes opened which files and sockets.&lt;/p&gt;&#10;&lt;h2 id="listening-ports"&gt;Listening Ports&#10;&lt;/h2&gt;&#10;&lt;p&gt;The classic task — find who is listening on a specific port.&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-9cff1145-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="1"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-9cff1145-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lsof -i -n -P&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div class="td-table-scroll td-table-scroll--static"&gt;&#10;&lt;table&gt;&#10; &lt;thead&gt;&#10; &lt;tr&gt;&#10; &lt;th scope="col"&gt;Flag&lt;/th&gt;&#10; &lt;th scope="col"&gt;Effect&lt;/th&gt;&#10; &lt;/tr&gt;&#10; &lt;/thead&gt;&#10; &lt;tbody&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;-i&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Show internet sockets&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;-n&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Skip DNS resolution (show IP instead of hostname)&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;tr&gt;&#10; &lt;td&gt;&lt;code&gt;-P&lt;/code&gt;&lt;/td&gt;&#10; &lt;td&gt;Skip port-to-service conversion (show 80 instead of http)&lt;/td&gt;&#10; &lt;/tr&gt;&#10; &lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;Without &lt;code&gt;-n -P&lt;/code&gt;, lsof wastes time on DNS lookups and resolves ports through /etc/services. On production hosts that&amp;rsquo;s unnecessary seconds.&lt;/p&gt;</description></item><item><title>mc — MinIO Client S3 CLI</title><link>https://lead-devops.blackdevhub.online/en/posts/minio-mc-s3-client-usage/</link><pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/minio-mc-s3-client-usage/</guid><description>&lt;p&gt;S3-compatible object storage is the default choice for buckets, backups, and static assets. When AWS CLI feels excessive and the web console is too clunky, MinIO Client (&lt;code&gt;mc&lt;/code&gt;) fills the gap. This CLI tool works with any S3-compatible storage: MinIO, Yandex Cloud, AWS S3, Backblaze B2. Zero dependencies, works out of the box, configured in under a minute.&lt;/p&gt;&#10;&lt;h2 id="installation"&gt;Installation&#10;&lt;/h2&gt;&#10;&lt;p&gt;Download the binary and make it executable:&lt;/p&gt;</description></item><item><title>nftables: Modern Linux Firewall</title><link>https://lead-devops.blackdevhub.online/en/posts/nftables-modern-firewall-linux/</link><pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/nftables-modern-firewall-linux/</guid><description>&lt;div class="td-callout td-callout--warning" role="note"&gt;&#10; &lt;div class="td-callout__title"&gt;&lt;i class="td-callout__icon fa-solid fa-triangle-exclamation" aria-hidden="true"&gt;&lt;/i&gt;&lt;span class="td-callout__label"&gt;Warning&lt;/span&gt;&lt;/div&gt;&#10; &lt;div class="td-callout__body"&gt;&#10;&lt;p&gt;Before changing nftables, make sure you have physical or console access to the server. A misconfigured input chain can block SSH and lock you out.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;nftables replaced iptables in the Linux kernel starting with version 3.13. If you&amp;rsquo;re still writing rules in iptables style, it&amp;rsquo;s time to reconsider. nftables performs better, has built-in dual-stack IPv4/IPv6 support, and lets you manage the entire ruleset as a whole instead of entering commands one by one.&lt;/p&gt;</description></item><item><title>ss: socket statistics instead of deprecated netstat</title><link>https://lead-devops.blackdevhub.online/en/posts/ss-replace-netstat/</link><pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ss-replace-netstat/</guid><description>&lt;p&gt;When &lt;code&gt;netstat&lt;/code&gt; hangs on a server with tens of thousands of connections, it&amp;rsquo;s time to switch to &lt;code&gt;ss&lt;/code&gt;. Part of the &lt;code&gt;iproute2&lt;/code&gt; package, &lt;code&gt;ss&lt;/code&gt; queries the kernel directly via netlink instead of parsing &lt;code&gt;/proc/net/*&lt;/code&gt;. The result is instant output with minimal overhead.&lt;/p&gt;&#10;&lt;h2 id="why-switch-from-netstat"&gt;Why switch from netstat&#10;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;netstat&lt;/code&gt; from &lt;code&gt;net-tools&lt;/code&gt; relies on a deprecated approach: it reads from &lt;code&gt;/proc/net/tcp&lt;/code&gt;, &lt;code&gt;/proc/net/unix&lt;/code&gt; and converts numeric IDs to symbolic names. On a server with active connections, this takes seconds and spikes CPU usage.&lt;/p&gt;</description></item><item><title>SSH Config: Wildcards and Dynamic Variable Substitution</title><link>https://lead-devops.blackdevhub.online/en/posts/ssh-config-wildcards-dynamic-variables/</link><pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ssh-config-wildcards-dynamic-variables/</guid><description>&lt;p&gt;SSH reads ~/.ssh/config line by line, but without variables the file quickly becomes copy-paste hell. Here&amp;rsquo;s how Host patterns, Match exec, and substitution tokens like %h, %r, %l cut config size by orders of magnitude while covering real scenarios — from dynamic routing to agent forwarding through bastion hosts.&lt;/p&gt;&#10;&lt;h2 id="templates-and-wildcards-in-ssh-config"&gt;Templates and wildcards in SSH config&#10;&lt;/h2&gt;&#10;&lt;p&gt;SSH supports glob-like patterns in the Host directive. The most common is &lt;code&gt;Host *&lt;/code&gt;, but compound patterns work too.&lt;/p&gt;</description></item><item><title>strace: System Call Tracing for Diagnosing Hangs and Leaks</title><link>https://lead-devops.blackdevhub.online/en/posts/strace-syscall-troubleshooting/</link><pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/strace-syscall-troubleshooting/</guid><description>&lt;p&gt;When a service hangs, standard tools like top, htop, and ps show the state but not the cause. If a process is in state D (uninterruptible sleep), it&amp;rsquo;s waiting on a syscall. strace attaches to a live process and outputs every system call in real time. This turns a mysterious hang into a specific syscall, its arguments, and return code.&lt;/p&gt;&#10;&lt;div class="td-callout td-callout--note" role="note"&gt;&#10; &lt;div class="td-callout__title"&gt;&lt;i class="td-callout__icon fa-solid fa-circle-info" aria-hidden="true"&gt;&lt;/i&gt;&lt;span class="td-callout__label"&gt;Note&lt;/span&gt;&lt;/div&gt;&#10; &lt;div class="td-callout__body"&gt;&#10;&lt;p&gt;strace uses ptrace, the kernel&amp;rsquo;s debugging mechanism. On production, tracing slows a process by 2–10x. Use it sparingly, targeting a single PID.&lt;/p&gt;</description></item><item><title>tcpdump and tshark: Packet Capture in CLI</title><link>https://lead-devops.blackdevhub.online/en/posts/tcpdump-tshark-cli-packet-capture/</link><pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/tcpdump-tshark-cli-packet-capture/</guid><description>&lt;p&gt;When debugging network issues in Linux infrastructure, &lt;code&gt;ping&lt;/code&gt; and &lt;code&gt;curl&lt;/code&gt; are not enough. Sometimes you need to see what is actually traveling over the wire. tcpdump is the standard tool for capturing packets from the CLI. tshark is its sibling from the Wireshark suite, convenient for scripting.&lt;/p&gt;&#10;&lt;h2 id="quick-start-with-tcpdump"&gt;Quick Start with tcpdump&#10;&lt;/h2&gt;&#10;&lt;p&gt;Check that packets are reaching the host:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-4d81bd54-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="1"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-4d81bd54-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tcpdump -i eth0 host 10.0.0.5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;The utility puts the interface into promiscuous mode and prints one line per packet passing through. By default it works with the first interface it finds, but specifying explicitly is better.&lt;/p&gt;</description></item><item><title>CasaOS: Web Dashboard for Home Lab</title><link>https://lead-devops.blackdevhub.online/en/posts/casaos-home-lab/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/casaos-home-lab/</guid><description>&lt;p&gt;CasaOS is a lightweight web dashboard for managing Docker containers on a single host. If you&amp;rsquo;re currently accessing each container through its own port, this replaces that mess with a unified interface where you can install apps with a couple of clicks, monitor resources, and manage storage — without touching Nginx or dealing with Portainer&amp;rsquo;s complexity.&lt;/p&gt;&#10;&lt;h2 id="installation"&gt;Installation&#10;&lt;/h2&gt;&#10;&lt;p&gt;CasaOS installs on a clean system with one command. Supported distros: Debian 10+, Ubuntu 18.04+, Raspbian. If Docker is already running, remove it first or accept that CasaOS will take over the Docker daemon.&lt;/p&gt;</description></item><item><title>cockpit-ufw-module: Uncomplicated Firewall in Cockpit</title><link>https://lead-devops.blackdevhub.online/en/posts/cockpit-ufw-module/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/cockpit-ufw-module/</guid><description>&lt;p&gt;UFW on a home or small server is usually configured over SSH: &lt;code&gt;ufw status numbered&lt;/code&gt;, then &lt;code&gt;ufw allow 443/tcp&lt;/code&gt;. &lt;a href="https://gitlab.com/cockpit-modules/cockpit-ufw-module"&gt;cockpit-ufw-module&lt;/a&gt; covers the same cycle in the browser: package, status, policies, rules. It is one panel from the &lt;a href="https://lead-devops.blackdevhub.online/en/posts/cockpit-modules/"&gt;cockpit-modules&lt;/a&gt; group — &lt;strong&gt;UFW&lt;/strong&gt; under &lt;strong&gt;Tools&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;p&gt;The UI is Russian, in PatternFly v5. You need Cockpit &lt;strong&gt;264+&lt;/strong&gt; and administrator rights for writes. MIT license; current release is tag &lt;code&gt;v.1.0.1&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h2 id="why-a-panel-if-ufw-already-exists"&gt;Why a panel if &lt;code&gt;ufw&lt;/code&gt; already exists&#10;&lt;/h2&gt;&#10;&lt;p&gt;The client is already there: system &lt;code&gt;ufw&lt;/code&gt;. What is missing is a view without a terminal and safe input: port, CIDR, rule number.&lt;/p&gt;</description></item><item><title>Creating a Custom Systemd Service</title><link>https://lead-devops.blackdevhub.online/en/posts/custom-systemd-service/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/custom-systemd-service/</guid><description>&lt;p&gt;Your application needs to start on boot, restart on crash, and log output. Shell scripts in /etc/rc.local give you none of that. Systemd solves all three with a single declarative file.&lt;/p&gt;&#10;&lt;h2 id="why-write-a-custom-unit-file"&gt;Why Write a Custom Unit File&#10;&lt;/h2&gt;&#10;&lt;p&gt;Supervisord and init scripts are overkill for most cases. Systemd provides a unified interface for service management: socket-based activation, dependency tracking, resource limits, and built-in logging via journald. You get all of it without additional tooling.&lt;/p&gt;</description></item><item><title>kubectl whoami and Service Account Permission Checks</title><link>https://lead-devops.blackdevhub.online/en/posts/kubectl-whoami-check-sa-rights/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/kubectl-whoami-check-sa-rights/</guid><description>&lt;p&gt;When deploying an application to Kubernetes, the most common failure is a service account that cannot do what it should. Permission denied when creating a secret, rejection on list pods, refusal on update. kubectl whoami and kubectl auth can-i let you quickly identify exactly who cannot do what.&lt;/p&gt;&#10;&lt;h2 id="kubectl-whoami-plugin"&gt;kubectl whoami plugin&#10;&lt;/h2&gt;&#10;&lt;div class="td-callout td-callout--note" role="note"&gt;&#10; &lt;div class="td-callout__title"&gt;&lt;i class="td-callout__icon fa-solid fa-circle-info" aria-hidden="true"&gt;&lt;/i&gt;&lt;span class="td-callout__label"&gt;Note&lt;/span&gt;&lt;/div&gt;&#10; &lt;div class="td-callout__body"&gt;&#10;&lt;p&gt;kubectl whoami is not a built-in kubectl command. It is a plugin from krew or a standalone binary. Install with &lt;code&gt;kubectl krew install whoami&lt;/code&gt; or download from GitHub.&lt;/p&gt;</description></item><item><title>ngrep: grep for Network Packets in Real Time</title><link>https://lead-devops.blackdevhub.online/en/posts/ngrep-setevoy-grep/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ngrep-setevoy-grep/</guid><description>&lt;p&gt;Ngrep applies grep-style pattern matching to network packets. When you need to see exactly what two services are exchanging over the wire and tcpdump drowns you in noise, ngrep isolates the payload content you care about.&lt;/p&gt;&#10;&lt;h2 id="installation"&gt;Installation&#10;&lt;/h2&gt;&#10;&lt;p&gt;Ngrep ships in the standard repositories of most distributions.&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-b19d843d-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="8"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-b19d843d-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Debian/Ubuntu&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install ngrep&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# RHEL/CentOS/Alma&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yum install ngrep&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# macOS&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install ngrep&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Running ngrep requires root privileges or the &lt;code&gt;CAP_NET_RAW&lt;/code&gt; and &lt;code&gt;CAP_NET_ADMIN&lt;/code&gt; capabilities.&lt;/p&gt;</description></item><item><title>socat: Forwarding Unix Sockets Over TCP</title><link>https://lead-devops.blackdevhub.online/en/posts/socat-unix-socket-tcp-forwarding/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/socat-unix-socket-tcp-forwarding/</guid><description>&lt;p&gt;Sometimes you need to reach a Unix socket from a host where that socket doesn&amp;rsquo;t physically exist. SSH tunnels won&amp;rsquo;t help — they only work with TCP ports. socat solves this: it opens a TCP listener and forwards connections to a Unix socket, and the client just connects over the network.&lt;/p&gt;&#10;&lt;h2 id="installation"&gt;Installation&#10;&lt;/h2&gt;&#10;&lt;p&gt;The package is available in every major distribution. On Debian/Ubuntu:&lt;/p&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-553060c8-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="1"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-553060c8-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install socat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;On RHEL/CentOS:&lt;/p&gt;</description></item><item><title>SSH Escape Sequences: Reviving a Frozen Terminal</title><link>https://lead-devops.blackdevhub.online/en/posts/ssh-escape-sequences-frozen-terminal/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ssh-escape-sequences-frozen-terminal/</guid><description>&lt;p&gt;SSH session froze, &lt;code&gt;Ctrl+C&lt;/code&gt; does nothing, &lt;code&gt;Ctrl+D&lt;/code&gt; spits out garbage — familiar situation. Before closing the terminal and losing the session, try built-in escape sequences. They operate at the SSH client level before data reaches the remote host.&lt;/p&gt;&#10;&lt;h2 id="how-to-invoke-escape-sequences"&gt;How to invoke escape sequences&#10;&lt;/h2&gt;&#10;&lt;p&gt;The default escape character is tilde (&lt;code&gt;~&lt;/code&gt;). The combination works only at the beginning of a line. Press Enter, then &lt;code&gt;~&lt;/code&gt;, then the desired symbol. For example, &lt;code&gt;~.&lt;/code&gt; terminates the connection.&lt;/p&gt;</description></item><item><title>What is Self-Hosted and Why It's So Popular</title><link>https://lead-devops.blackdevhub.online/en/posts/what-is-self-hosted/</link><pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/what-is-self-hosted/</guid><description>&lt;p&gt;You&amp;rsquo;re paying for Notion, Dropbox, and Google Drive. Then Notion raises prices, Dropbox caps storage, and Google &amp;ldquo;improves&amp;rdquo; the Docs interface. Self-hosted is taking infrastructure into your own hands and breaking the vendor dependency loop.&lt;/p&gt;&#10;&lt;h2 id="definition-not-your-cloud"&gt;Definition: Not Your Cloud&#10;&lt;/h2&gt;&#10;&lt;p&gt;Self-hosted means deploying and operating applications on your own servers or VPS instead of using SaaS alternatives. The server can sit at home, in a data center, or be a VM at a hosting provider—the point is that the hardware is under your control, not a third party&amp;rsquo;s.&lt;/p&gt;</description></item><item><title>cockpit-modules: web panels for day-to-day operations</title><link>https://lead-devops.blackdevhub.online/en/posts/cockpit-modules/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/cockpit-modules/</guid><description>&lt;p&gt;&lt;a href="https://cockpit-project.org/"&gt;Cockpit&lt;/a&gt; covers basic Linux administration in the browser: services, logs, networking, accounts. Firewall, fail2ban, cron, and Let&amp;rsquo;s Encrypt sit outside that set — either there is no panel, or it is too generic.&lt;/p&gt;&#10;&lt;p&gt;The &lt;a href="https://gitlab.com/cockpit-modules"&gt;cockpit-modules&lt;/a&gt; group is a set of separate modules for those jobs, plus a store that installs them on the host. Each module lives in its own repository. This is a map of the group, not a walkthrough of UI and commands. Individual panels get their own articles.&lt;/p&gt;</description></item><item><title>dig: DNS Query Debugging in CLI</title><link>https://lead-devops.blackdevhub.online/en/posts/dig-dns-cli-debugging/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/dig-dns-cli-debugging/</guid><description>&lt;p&gt;DNS resolvers return the wrong address, clients don&amp;rsquo;t see updates, or it&amp;rsquo;s unclear which server is handling requests. &lt;code&gt;dig&lt;/code&gt; (Domain Information Groper) is the standard CLI tool for DNS diagnostics. Works on Linux, macOS, and Windows via WSL.&lt;/p&gt;&#10;&lt;h2 id="installation"&gt;Installation&#10;&lt;/h2&gt;&#10;&lt;div class="td-code td-code--untitled" id="td-code-72265765-fence-0" data-td-code data-td-code-auto-id&#10; data-td-language="bash" data-td-line-count="8"&gt;&#10; &lt;div class="td-code__viewport" id="td-code-72265765-fence-0-viewport" data-td-code-viewport&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Debian/Ubuntu&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install dnsutils&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# RHEL/CentOS/Alma&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dnf install bind-utils&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# macOS — ships with the system&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Windows — via WSL or ISC official binaries&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;h2 id="basic-flags"&gt;Basic Flags&#10;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;dig&lt;/code&gt; has two classes of options: short flags (start with &lt;code&gt;-&lt;/code&gt;) control query behavior, while keywords with &lt;code&gt;+&lt;/code&gt; control output format.&lt;/p&gt;</description></item><item><title>MkDocs: Project Documentation from Markdown</title><link>https://lead-devops.blackdevhub.online/en/posts/mkdocs-quick-start/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/mkdocs-quick-start/</guid><description>&lt;p&gt;Documentation in a repository ages faster than anyone reads it: README links lead nowhere, sections are scattered across &lt;code&gt;docs/&lt;/code&gt;, &lt;code&gt;wiki/&lt;/code&gt;, and Confluence, and site search doesn&amp;rsquo;t work. MkDocs solves this predictably — it takes a folder of &lt;code&gt;.md&lt;/code&gt; files and builds a static site. One config, one command for the deploy, familiar Markdown.&lt;/p&gt;&#10;&lt;h2 id="what-is-mkdocs"&gt;What is MkDocs&#10;&lt;/h2&gt;&#10;&lt;p&gt;MkDocs is a static site generator for documentation written in Python. Input: a directory of Markdown files and a YAML config. Output: a ready &lt;code&gt;site/&lt;/code&gt; directory with HTML, served by any web server or hosted on GitHub Pages, GitLab Pages, S3. MkDocs core handles rendering; the theme defines look and features. The de-facto standard is &lt;a href="https://squidfunk.github.io/mkdocs-material/"&gt;Material for MkDocs&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Squid: Internet Forwarding to Remote VM</title><link>https://lead-devops.blackdevhub.online/en/posts/squid-proxy-remote-vm/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/squid-proxy-remote-vm/</guid><description>&lt;p&gt;Your VM in the cloud has no public IP or internet access is blocked via NAT, but the deployment needs wget/curl from inside. Squid on an intermediate host with a decent uplink solves this in ten minutes.&lt;/p&gt;&#10;&lt;h2 id="why-this-is-needed"&gt;Why This Is Needed&#10;&lt;/h2&gt;&#10;&lt;p&gt;I forward internet through Squid when a VM sits in an isolated network segment. An intermediate host with a public IP and network access becomes the proxy server. The application on the remote machine routes traffic through the tunnel.&lt;/p&gt;</description></item><item><title>SSH certificates instead of authorized_keys</title><link>https://lead-devops.blackdevhub.online/en/posts/ssh-certificates-instead-of-authorized-keys/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ssh-certificates-instead-of-authorized-keys/</guid><description>&lt;p&gt;authorized_keys works fine for a handful of servers. Once you hit a dozen, it becomes a liability. Onboarding a new developer means manually distributing their public key across every machine. SSH certificates flip this model: one CA signs all public keys, and authorized_keys stays empty.&lt;/p&gt;&#10;&lt;h2 id="why-authorized_keys-breaks-at-scale"&gt;Why authorized_keys breaks at scale&#10;&lt;/h2&gt;&#10;&lt;p&gt;authorized_keys requires your public key to exist on every target server. Scaling this creates:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;a separate deployment step for key distribution during onboarding&lt;/li&gt;&#10;&lt;li&gt;no centralized revocation — removing a key means touching each host&lt;/li&gt;&#10;&lt;li&gt;key rotation touches every machine&lt;/li&gt;&#10;&lt;li&gt;no expiration means stale access accumulates&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;An SSH certificate is a CA signature on your public key. The server only needs to trust the CA — your key never needs to be present locally.&lt;/p&gt;</description></item><item><title>systemd-timer: scheduling instead of cron</title><link>https://lead-devops.blackdevhub.online/en/posts/systemd-timer-scheduling/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/systemd-timer-scheduling/</guid><description>&lt;p&gt;cron works, but its logs are flat text files with no structure, and service dependencies require workarounds like embedding &lt;code&gt;Requires=&lt;/code&gt; logic inside shell scripts. systemd-timer fixes this: unified management interface, logs in journald, dependencies through the familiar &lt;code&gt;After=&lt;/code&gt; and &lt;code&gt;WantedBy=&lt;/code&gt; directives — all in one stack.&lt;/p&gt;&#10;&lt;h2 id="structure-service-and-timer"&gt;Structure: .service and .timer&#10;&lt;/h2&gt;&#10;&lt;p&gt;A timer is a separate unit that triggers a &lt;code&gt;.service&lt;/code&gt;. The separation is intentional: the service can be invoked manually or on a schedule.&lt;/p&gt;</description></item><item><title>Cron setup: a practical walkthrough</title><link>https://lead-devops.blackdevhub.online/en/posts/cron-setup/</link><pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/cron-setup/</guid><description>&lt;p&gt;Cron is the standard job scheduler in Linux, found in every infrastructure. Jobs pile up, logs accumulate, and the environment breaks things. Let&amp;rsquo;s walk through how to configure cron reliably and where it falls short.&lt;/p&gt;&#10;&lt;h2 id="when-to-use-cron-and-when-to-avoid-it"&gt;When to Use Cron and When to Avoid It&#10;&lt;/h2&gt;&#10;&lt;p&gt;Cron fits simple recurring tasks: backups, log rotation, temp file cleanup, periodic notifications. It&amp;rsquo;s a daemon that sleeps between runs — no resource consumption.&lt;/p&gt;</description></item><item><title>GNU Screen: sessions that survive an SSH drop</title><link>https://lead-devops.blackdevhub.online/en/posts/gnu-screen/</link><pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/gnu-screen/</guid><description>&lt;p&gt;A long &lt;code&gt;apt upgrade&lt;/code&gt;, a migration, a build — then the laptop sleeps. SSH dies, the process gets SIGHUP and dies with it. &lt;strong&gt;GNU Screen&lt;/strong&gt; keeps the terminal on the server: disconnect, come back, the work is still there.&lt;/p&gt;&#10;&lt;p&gt;It is not a &lt;code&gt;nohup&lt;/code&gt; replacement and not “another SSH”. It is a multiplexer: named sessions, several windows inside one, a shared session for two people. On older RHEL/Debian boxes &lt;code&gt;screen&lt;/code&gt; is often already installed when &lt;code&gt;tmux&lt;/code&gt; is not.&lt;/p&gt;</description></item><item><title>Kafka: Cluster Health Check</title><link>https://lead-devops.blackdevhub.online/en/posts/kafka-cluster-health-check/</link><pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/kafka-cluster-health-check/</guid><description>&lt;p&gt;A Kafka cluster in KRaft mode doesn&amp;rsquo;t forgive neglect until the first incident. Health checks need to be regular and quick — no graphs or dashboards, just the terminal. Here&amp;rsquo;s the command set that covers the typical checklist: processes, quorum, partition leaders, ISR, and a quick status report in one shot.&lt;/p&gt;&#10;&lt;h2 id="checking-kraft-processes"&gt;Checking KRaft Processes&#10;&lt;/h2&gt;&#10;&lt;p&gt;KRaft mode has no separate ZooKeeper — the &lt;code&gt;controller&lt;/code&gt; role is either co-located with the broker or isolated on dedicated nodes. First, verify the JVM processes are alive and see which mode each node started in.&lt;/p&gt;</description></item><item><title>kind: Local Kubernetes in Docker</title><link>https://lead-devops.blackdevhub.online/en/posts/kind-local-kubernetes-in-docker/</link><pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/kind-local-kubernetes-in-docker/</guid><description>&lt;p&gt;kind creates a Kubernetes cluster from Docker containers: control-plane and worker nodes are &lt;code&gt;kindest/node&lt;/code&gt; images. Primary use cases are local development and CI. GitHub Actions has an official &lt;code&gt;create-kind&lt;/code&gt; action that makes pipelines with K8s tests straightforward.&lt;/p&gt;&#10;&lt;p&gt;Compared to minikube, kind has no hypervisor dependency and natively supports multi-node topologies. Compared to k3d, it requires no Rancher and talks to CRI/containerd directly.&lt;/p&gt;&#10;&lt;h2 id="installation"&gt;Installation&#10;&lt;/h2&gt;&#10;&lt;p&gt;macOS, Linux, and Windows (via WSL2) — download the binary from GitHub Releases.&lt;/p&gt;</description></item><item><title>Too many authentication failures: SSH ran out of tries</title><link>https://lead-devops.blackdevhub.online/en/posts/ssh-too-many-authentication-failures/</link><pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ssh-too-many-authentication-failures/</guid><description>&lt;p&gt;&lt;code&gt;Received disconnect from 10.0.0.5 port 22:2: Too many authentication failures&lt;/code&gt; followed by &lt;code&gt;Permission denied (publickey)&lt;/code&gt; is not a broken server, and it is not necessarily a wrong password. The client &lt;strong&gt;spent the attempt budget&lt;/strong&gt; while walking agent keys and never reached the method you meant to use.&lt;/p&gt;&#10;&lt;p&gt;The budget is &lt;code&gt;MaxAuthTries&lt;/code&gt; on the server (&lt;strong&gt;6&lt;/strong&gt; by default). Each public key offered is one try. Five keys in &lt;code&gt;ssh-agent&lt;/code&gt; plus one more wrong key — the connection dies before the right key or a password prompt.&lt;/p&gt;</description></item><item><title>Trusting a custom CA: system store, browsers, and CLI</title><link>https://lead-devops.blackdevhub.online/en/posts/trust-custom-ca/</link><pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/trust-custom-ca/</guid><description>&lt;p&gt;A TLS error that says the certificate is untrusted almost never means the certificate is “broken”. The &lt;strong&gt;trust anchor&lt;/strong&gt; is in the wrong store.&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;openssl&lt;/code&gt;, Git, Python, and the browser are different clients. Some keep their own root lists. Updating the OS bundle on Linux will not fix Chrome or Firefox by itself.&lt;/p&gt;&#10;&lt;h2 id="what-to-import"&gt;What to import&#10;&lt;/h2&gt;&#10;&lt;p&gt;You trust the &lt;strong&gt;CA root&lt;/strong&gt; that signed the server certificate, not &lt;code&gt;localhost.crt&lt;/code&gt; / &lt;code&gt;app.example.internal&lt;/code&gt; itself.&lt;/p&gt;</description></item><item><title>ssh-connection-manager: a TUI for hosts in ~/.ssh/config</title><link>https://lead-devops.blackdevhub.online/en/posts/ssh-connection-manager/</link><pubDate>Sun, 30 Aug 2026 00:00:00 +0000</pubDate><guid>https://lead-devops.blackdevhub.online/en/posts/ssh-connection-manager/</guid><description>&lt;p&gt;When &lt;code&gt;~/.ssh/config&lt;/code&gt; holds dozens of stands, bastions, and jump hosts, memorizing aliases stops being fun. &lt;strong&gt;ssh-connection-manager&lt;/strong&gt; is a TUI on top of ordinary OpenSSH: a host list, a filter, a connect via the system &lt;code&gt;ssh&lt;/code&gt;, and a way to append a new block to the config.&lt;/p&gt;&#10;&lt;p&gt;The CLI command is &lt;code&gt;ssh-connect&lt;/code&gt;. Repository: &lt;a href="https://gitlab.com/public-projects-docff-devops/ssh-connection-manager"&gt;gitlab.com/unsorted-projects/ssh-connection-manager&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="why-not-another-ssh-client"&gt;Why not another SSH client&#10;&lt;/h2&gt;&#10;&lt;p&gt;The client already exists: the system &lt;code&gt;ssh&lt;/code&gt;. What is missing is navigation over the config file.&lt;/p&gt;</description></item></channel></rss>