<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Systemd on Lead DevOps</title><link>https://lead-devops.blackdevhub.online/en/tags/systemd/</link><description>Recent content in Systemd on Lead DevOps</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Sat, 19 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://lead-devops.blackdevhub.online/en/tags/systemd/index.xml" rel="self" type="application/rss+xml"/><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>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>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>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>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>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>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>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>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></channel></rss>