<?xml version="1.0" encoding="UTF-8"?>
<rss 
    version="2.0"
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:content="http://purl.org/rss/1.0/modules/content/" 
    xmlns:atom="http://www.w3.org/2005/Atom" 
    xmlns:media="http://search.yahoo.com/mrss/" 
>
    <channel>
        <title><![CDATA[Linux Handbook]]></title>
        <description><![CDATA[An independent, reader-supported publication focusing on Linux Command Line, Server, Self-hosting, DevOps and Cloud Learning]]></description>
        <link>https://linuxhandbook.com</link>
        <image>
            <url>https://linuxhandbook.com/favicon.png</url>
            <title>Linux Handbook</title>
            <link>https://linuxhandbook.com</link>
        </image>
        <generator>Ghost 6.62</generator>
        <lastBuildDate>Sun, 04 Oct 2026 23:47:50 +0530</lastBuildDate>
        <atom:link href="https://linuxhandbook.com" rel="self" type="application/rss+xml"/>
        <ttl>60</ttl>

                <item>
                    <title><![CDATA[Learn SSH]]></title>
                    <description><![CDATA[SSH is how you log in to and work on remote Linux machines. Start with the basics, then secure your setup and fix the errors you are most likely to run into.]]></description>
                    <link>https://linuxhandbook.com/learn-ssh/</link>
                    <guid isPermaLink="false">6ac10ad55616fe0001937d2f</guid>

                        <category><![CDATA[Learn SSH]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Sat, 03 Oct 2026 19:31:57 +0530</pubDate>


                    <content:encoded><![CDATA[<p>SSH is how you log in to and work on remote Linux machines. Start with the basics, then secure your setup and fix the errors you are most likely to run into.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.14: Free CTF, Special Permissions, Process Substitution and More]]></title>
                    <description><![CDATA[Time to challenge yourself and test your Linux command line knowledge.]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-14/</link>
                    <guid isPermaLink="false">6ab652bc5616fe000192f7ce</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Fri, 02 Oct 2026 19:05:45 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/10/lhb-newsletter-1-.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/10/lhb-newsletter-1-.webp" alt="LHB Linux Digest #26.14: Free CTF, Special Permissions, Process Substitution and More"/> <p>We've built something new for you. A free Linux CTF game, and I've had more fun testing it than I'd like to admit.</p><p>A <a href="https://linuxhandbook.com/ctf/">CTF</a> (capture the flag) teaches you Linux by making you work for it. You get a locked-down system, a riddle, and a hidden flag (a string), and you have to use real commands to dig it out. </p><p>These challenges force you to think, employ your reasoning and logical skill along with your Linux command line skills.</p><p>While the entire CTF is played locally on your own system, your progress can be shown on a public leaderboard. </p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/10/image.png" class="kg-image" alt="CTF leaderboard" loading="lazy" width="1368" height="783" srcset="https://linuxhandbook.com/content/images/size/w600/2026/10/image.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/10/image.png 1000w, https://linuxhandbook.com/content/images/2026/10/image.png 1368w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%9A%A9-command-conqueror-our-free-linux-ctf">🚩 Command Conqueror: our free Linux CTF</h2><p>It starts with hidden files and ends with a full SUID privilege escalation. Each level drops you into a small Linux system ruled by Lord Tuxi, who leaves you a riddle and hides a flag somewhere. You find it, submit it, and climb the leaderboard.</p><p>It's free, and you don't need an account to play. If you do link your Linux Handbook account, your progress saves across machines.</p><p>You need Docker and Python 3.7+ (WSL 2 on Windows), then:</p><pre><code class="language-bash">curl -fsSLO https://ctf.linuxhandbook.com/play.py
python3 play.py
</code></pre><p>You don't need to know Docker or Python. The CTF runs with those two.</p><p>Pick a handle, choose Command Conqueror, and type <code>play</code> to start. The early levels are gentle if you've spent time in a terminal.</p><p>Play it <a href="https://linuxhandbook.com/ctf/command-conqueror/">here</a>. There is a demo here that shows <a href="https://linuxhandbook.com/ctf/#how-to-play">how to play the CTF</a>.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://linuxhandbook.com/ctf/command-conqueror/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Command Conqueror: Free Linux CTF Challenge</div><div class="kg-bookmark-description">Ten Linux command line puzzles, from hidden files to SUID privilege escalation. Free, no account needed, runs in Docker on your computer.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/Linux-Handbook-New-Logo-897e7887-a7e7-4ce7-afef-ca615fdc35d9.png" alt=""><span class="kg-bookmark-author">Linux Handbook</span><span class="kg-bookmark-publisher">Yash Kiran Patil</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/lhb-ctf-command-ad71186e-6166-47cf-acd2-6d4b45d4caec.webp" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%8E%93-see-who-can-do-what">🎓 See who can do what</h2><p>Level 10 of the CTF ends with privilege escalation, which sounds scarier than it is. Most of it comes down to one question: on this system, what can I actually do, and what can I do that I'm not supposed to?</p><p>A few commands answer that fast. <code>ls -l</code> shows the <a href="https://linuxhandbook.com/linux-file-permissions/" rel="noreferrer">permission bits</a>, and an <code>s</code> where you'd expect an <code>x</code> (like <code>-rwsr-xr-x</code>) is the SUID bit, meaning the file runs with its owner's privileges instead of yours. That's the first thing a CTF player, or an attacker, goes looking for.</p><p>To find every SUID binary on a box:</p><pre><code class="language-bash">find / -perm -4000 -type f 2&gt;/dev/null
</code></pre><p>From there, <code>sudo -l</code> lists exactly what your user is allowed to run as root, <code>id</code> shows the groups you're in, and <code>getcap -r / 2&gt;/dev/null</code> shows binaries with special capabilities that <code>ls</code> won't show you.</p><p>It's the same audit you'd run on your own server to check nothing has more power than it should. If you want details, our guide on <a href="https://linuxhandbook.com/suid-sgid-sticky-bit/">SUID, SGID and the sticky bit</a> breaks down what those permission bits really mean.</p><h2 id="%F0%9F%92%A1-quick-terminal-tip">💡 Quick terminal tip</h2><p>Bash and zsh let you feed one command's output to another as if it were a file, using <code>&lt;(...)</code>. No temp files, no cleanup.</p><p>It's great for comparing two states. Say you want to see what differs between two directories, or two command outputs:</p><pre><code class="language-bash">diff &lt;(ls dir1) &lt;(ls dir2)
</code></pre><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/diff-substitution.png" class="kg-image" alt="Feed a commands output to another command." loading="lazy" width="1011" height="211" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/diff-substitution.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/09/diff-substitution.png 1000w, https://linuxhandbook.com/content/images/2026/09/diff-substitution.png 1011w" sizes="(min-width: 720px) 720px"></figure><p>This is called <a href="https://linuxhandbook.com/bash-process-substitution/">process substitution</a>, and is pretty handy in bash scripts.</p><h2 id="%F0%9F%93%A6-self-hosting-cyberchef">📦 Self-hosting: CyberChef</h2><p>If the CTF throws a wall of base64 at you (level 5 will), this is what you want open in another tab. <a href="https://github.com/gchq/CyberChef?ref=linuxhandbook.com">CyberChef</a> is a browser-based, drag-and-drop toolkit for encoding, decoding, encryption, hashing and data parsing.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/gchq/CyberChef?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - gchq/CyberChef: The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis</div><div class="kg-bookmark-description">The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis - gchq/CyberChef</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-05c61325-0309-490f-95d5-488ed57e699e.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">gchq</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/137c6d1b-4aac-4408-a361-c2a27f125b04-fdc56bdd-1076-41d2-a1c9-2a43abc4fd31" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%9B%A0%EF%B8%8F-tool-discovery-gopass">🛠️ Tool discovery: gopass</h2><p><a href="https://github.com/gopasspw/gopass?ref=linuxhandbook.com">gopass</a> is a command-line password manager built for teams. It stores everything in GPG or age-encrypted files with git-backed version history, so your credentials live in a repo you control instead of someone else's cloud.</p><p>It works fully offline, which makes it a good fit for shared credentials across a distributed team or a CI/CD pipeline.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/gopasspw/gopass?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - gopasspw/gopass: The slightly more awesome standard unix password manager for teams</div><div class="kg-bookmark-description">The slightly more awesome standard unix password manager for teams - gopasspw/gopass</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-804ace74-8f2d-4751-a20c-461095dbbe5d.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">gopasspw</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/gopass-8403cacb-eddf-4a7f-929a-4a88724bc0c5" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%93%B0-linux-news-that-matters">📰 Linux news that matters</h2><ul><li><a href="https://www.linuxjournal.com/content/ubuntu-container-escape-vulnerability-gets-public-exploit-kernel-patch-arrives?ref=linuxhandbook.com">A newly public exploit for a Linux kernel bug</a> (CVE-2026-80521) lets attackers escape an Ubuntu container and get root on the host, and Ubuntu still hasn't shipped the patch.</li><li><a href="https://itsfoss.com/news/ubuntu-kernel-sru-cycle-update/?ref=linuxhandbook.com">Canonical is merging its split kernel update tracks</a> into a single 2-week SRU cycle that overlaps weekly, so Ubuntu kernel fixes ship faster, largely because AI-assisted vulnerability hunting is finding kernel bugs faster than the old process could keep up with.</li><li><a href="https://itsfoss.com/news/portainer-community-edition-freeze/?ref=linuxhandbook.com">Portainer's Community Edition is being frozen</a> on the 2.x line, while all new Kubernetes-first development goes exclusively into the closed-source Portainer 3.0.</li><li><a href="https://www.phoronix.com/news/Orphaned-VMs-Linux-Patches?ref=linuxhandbook.com">A Google engineer has posted a 46-patch RFC series for "Orphaned VMs,"</a> an early-stage Linux kernel mechanism that uses the Live Update Orchestrator to keep virtual machines executing on preserved physical CPUs while the host kernel reboots or applies updates.</li><li><a href="https://thenewstack.io/aws-strands-harness-agent/?ref=linuxhandbook.com">AWS has open-sourced Strands Harness</a>, an agent runtime that bundles tools, context management, memory, and session handling on top of its Strands SDK. While it defaults to Amazon Bedrock, it works with Anthropic, OpenAI, Google, or local Ollama models, and AWS claiming 45% lower cost than Claude Code and Codex on benchmark tasks.</li><li>Starting October 19, <a href="https://devops.com/gitlab-tightens-rate-limits-as-coding-agents-drive-demand/?ref=linuxhandbook.com">GitLab will enforce new tiered API rate limits by subscription plan</a>, driven by surging traffic from AI coding agents, so teams running automated tools should authenticate their requests and watch for rate-limit warnings to avoid getting throttled.</li></ul><h2 id="%F0%9F%98%82-geek-humor">😂 Geek humor</h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/lhb-meme-sep-last-final.jpg" class="kg-image" alt="" loading="lazy" width="1440" height="1533" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/lhb-meme-sep-last-final.jpg 600w, https://linuxhandbook.com/content/images/size/w1000/2026/09/lhb-meme-sep-last-final.jpg 1000w, https://linuxhandbook.com/content/images/2026/09/lhb-meme-sep-last-final.jpg 1440w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%92%8C-keep-on-loving-linux-handbook">💌 Keep on loving Linux Handbook</h2><p>This CTF is free and there will be more. It's the kind of thing our Pro members make possible. Pro gets you that plus every other course, all our eBooks, and every tutorial we've published.</p><p><a href="https://linuxhandbook.com/#/portal/signup" rel="noreferrer">Become a Pro member</a> · <a href="https://linuxhandbook.com/courses/">Browse courses</a> · <a href="https://linuxhandbook.com/ebooks/">eBooks</a></p><p>Missed the previous editions? You can <a href="https://linuxhandbook.com/newsletter/">access the newsletter archives</a>. </p><p>I like reading your messages, so just hit reply and tell me how far you got in the CTF 😄</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Command Conqueror]]></title>
                    <description><![CDATA[Ten Linux command line puzzles, from hidden files to SUID privilege escalation. Free, no account needed, runs in Docker on your computer.]]></description>
                    <link>https://linuxhandbook.com/ctf/command-conqueror/</link>
                    <guid isPermaLink="false">6abce9a65616fe000192fc27</guid>

                        <category><![CDATA[CTF]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Wed, 30 Sep 2026 17:11:25 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/09/lhb-ctf-command.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/09/lhb-ctf-command.webp" alt="Command Conqueror"/> <p>Command Conqueror is a capture-the-flag game with 10 levels of Linux command line puzzles. It starts with hidden files and ends with a privilege escalation.</p><p>Each level drops you into a small Linux system ruled by <strong>Lord Tuxi</strong>, who leaves you a riddle and hides a flag. Use real commands to find the flag, submit it and climb the leaderboard.</p><p>It's free, and you don't need an account to play. Although, you can link it with your Linux Handbook member account and have your progress saved across time and systems.</p><h2 id="quick-start">Quick start</h2><p>You need Linux or macOS with Docker running, and Python 3.7 or newer. On Windows, use WSL 2.</p><p>Download the game and run it:</p><pre><code class="language-bash">curl -fsSLO https://ctf.linuxhandbook.com/play.py
python3 play.py
</code></pre><p>Pick a handle, then choose <strong>Command Conqueror</strong> from the menu. Type <code>play</code> to enter the first level and start with:</p><pre><code class="language-bash">cat hint.txt
</code></pre><p>When you find a flag (it looks like <code>LHB{...}</code>), copy it, type <code>exit</code> and submit it:</p><pre><code>submit LHB{...}
</code></pre><p>If Docker complains about permissions, run <code>sudo python3 play.py</code> instead. For the full setup, the commands and the FAQ, see the <a href="https://linuxhandbook.com/ctf/">main CTF page</a>.</p><h2 id="the-levels">The levels</h2><p>Here's what each level tests, without giving anything away.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:center">Level</th>
<th style="text-align:center">Points</th>
<th>Skills</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">1</td>
<td style="text-align:center">100</td>
<td>Hidden files</td>
</tr>
<tr>
<td style="text-align:center">2</td>
<td style="text-align:center">150</td>
<td>Searching the filesystem</td>
</tr>
<tr>
<td style="text-align:center">3</td>
<td style="text-align:center">200</td>
<td>Awkward file names</td>
</tr>
<tr>
<td style="text-align:center">4</td>
<td style="text-align:center">250</td>
<td>Archives</td>
</tr>
<tr>
<td style="text-align:center">5</td>
<td style="text-align:center">300</td>
<td>Cron and encrypted archives</td>
</tr>
<tr>
<td style="text-align:center">6</td>
<td style="text-align:center">350</td>
<td>Processes and local network services</td>
</tr>
<tr>
<td style="text-align:center">7</td>
<td style="text-align:center">400</td>
<td>Process environments</td>
</tr>
<tr>
<td style="text-align:center">8</td>
<td style="text-align:center">450</td>
<td>Log filtering and text processing</td>
</tr>
<tr>
<td style="text-align:center">9</td>
<td style="text-align:center">500</td>
<td>Hard links and inodes</td>
</tr>
<tr>
<td style="text-align:center">10</td>
<td style="text-align:center">600</td>
<td>SUID and privilege escalation</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>That's 3,300 points in total. You solve the levels in order, and each one gives its points once.</p><p>The first few are friendly if you've used a terminal before. By level 8, you'll be chaining <code>grep</code>, <code>awk</code> and friends together. Level 10 starts you as an ordinary user and asks you to think like an attacker.</p><h2 id="leaderboard">Leaderboard</h2>
<!--kg-card-begin: html-->
<div class="ctf-root" data-api="https://ctf.linuxhandbook.com" data-ctf="command-conqueror">
    <!-- Linux Handbook CTF: live stats + leaderboard for one CTF.
         Paste the whole snippet into a Ghost HTML card and set data-ctf to the
         CTF's folder name (e.g. command-conqueror). Refreshes every 30 seconds. -->
    <style>
        .ctf-root {
            --ctf-accent: var(--ghost-accent-color, #a52c5b);
            --ctf-muted: color-mix(in srgb, currentColor 60%, transparent);
            --ctf-border: color-mix(in srgb, currentColor 15%, transparent);
            --ctf-soft: color-mix(in srgb, currentColor 5%, transparent);
            font: inherit;
            margin: 0 auto;
        }
        .ctf-stats {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 12px;
            margin-bottom: 20px;
        }
        .ctf-stat {
            border: 1px solid var(--ctf-border);
            border-radius: 8px;
            padding: 14px 12px;
            text-align: center;
        }
        .ctf-stat b {
            display: block;
            font-size: 1.8em;
            line-height: 1.1;
            color: var(--ctf-accent);
            font-variant-numeric: tabular-nums;
        }
        .ctf-stat span { font-size: 0.8em; color: var(--ctf-muted); }
        .ctf-levels {
            display: grid;
            grid-template-columns: repeat(10, 1fr);
            gap: 4px;
            align-items: end;
            height: 70px;
            margin: 0 0 4px;
        }
        .ctf-levels div {
            background: var(--ctf-accent);
            border-radius: 3px 3px 0 0;
            min-height: 2px;
            opacity: 0.85;
        }
        .ctf-levels-axis {
            display: grid;
            grid-template-columns: repeat(10, 1fr);
            gap: 4px;
            font-size: 0.7em;
            color: var(--ctf-muted);
            text-align: center;
            margin-bottom: 20px;
        }
        .ctf-caption { font-size: 0.8em; color: var(--ctf-muted); margin: 0 0 6px; }
        .ctf-table { width: 100%; border-collapse: collapse; font-size: 0.9em; }
        .ctf-table th, .ctf-table td {
            padding: 8px 10px;
            border-bottom: 1px solid var(--ctf-border);
            text-align: left;
        }
        .ctf-table th { font-size: 0.8em; color: var(--ctf-muted); font-weight: 600; }
        .ctf-table td.num, .ctf-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
        .ctf-table tbody tr:nth-child(-n+3) td:first-child { font-weight: 700; color: var(--ctf-accent); }
        .ctf-table td.handle { font-family: var(--font-mono, ui-monospace, monospace); word-break: break-all; }
        .ctf-done { color: var(--ctf-accent); font-size: 0.8em; margin-left: 6px; }
        .ctf-member { font-size: 0.75em; margin-left: 4px; opacity: 0.7; }
        .ctf-more {
            display: block;
            margin: 12px auto 0;
            padding: 6px 16px;
            border: 1px solid var(--ctf-border);
            border-radius: 6px;
            background: none;
            color: inherit;
            font: inherit;
            font-size: 0.85em;
            cursor: pointer;
        }
        .ctf-more:hover { background: var(--ctf-soft); }
        .ctf-more[hidden] { display: none; }
        .ctf-empty { text-align: center; color: var(--ctf-muted); padding: 20px 0; }
        @media (max-width: 480px) {
            .ctf-stat b { font-size: 1.4em; }
            .ctf-table th, .ctf-table td { padding: 7px 6px; }
            .ctf-hide-sm { display: none; }
        }
    </style>

    <div class="ctf-stats">
        <div class="ctf-stat"><b data-stat="players">–</b><span>players</span></div>
        <div class="ctf-stat"><b data-stat="solves">–</b><span>flags captured</span></div>
        <div class="ctf-stat"><b data-stat="finishers">–</b><span>finished every level</span></div>
    </div>

    <p class="ctf-caption">Players who cleared each level</p>
    <div class="ctf-levels" aria-hidden="true"></div>
    <div class="ctf-levels-axis" aria-hidden="true"></div>

    <table class="ctf-table">
        <thead>
            <tr>
                <th class="num">#</th>
                <th>Handle</th>
                <th class="num ctf-hide-sm">Levels</th>
                <th class="num">Score</th>
            </tr>
        </thead>
        <tbody><tr><td colspan="4" class="ctf-empty">Loading leaderboard…</td></tr></tbody>
    </table>
    <button class="ctf-more" type="button" hidden>Show top 100</button>

    <script>
        (function () {
            var root = document.currentScript.closest(".ctf-root");
            var api = root.getAttribute("data-api") + "/api/ctfs/" + root.getAttribute("data-ctf");
            var TOTAL_LEVELS = 10; // replaced by the real count from /stats
            var shown = 20;
            var rows = [];

            function $(sel) { return root.querySelector(sel); }
            function setText(key, n) { $('[data-stat="' + key + '"]').textContent = n.toLocaleString(); }

            function renderTable() {
                var tbody = $("tbody");
                tbody.textContent = "";
                if (!rows.length) {
                    tbody.innerHTML = '<tr><td colspan="4" class="ctf-empty">No flags captured yet. Your handle could be first.</td></tr>';
                } else {
                    rows.slice(0, shown).forEach(function (r, i) {
                        var tr = document.createElement("tr");
                        var levels = (r.solvedLevels || []).length;
                        tr.innerHTML = '<td class="num"></td><td class="handle"></td><td class="num ctf-hide-sm"></td><td class="num"></td>';
                        tr.children[0].textContent = i + 1;
                        tr.children[1].textContent = r.handle;   // textContent: handles are user input
                        if (r.member) {
                            var m = document.createElement("span");
                            m.className = "ctf-member";
                            m.title = "Linux Handbook member";
                            m.textContent = "✓";
                            tr.children[1].appendChild(m);
                        }
                        if (levels === TOTAL_LEVELS) {
                            var done = document.createElement("span");
                            done.className = "ctf-done";
                            done.textContent = "★ finished";
                            tr.children[1].appendChild(done);
                        }
                        tr.children[2].textContent = levels + "/" + TOTAL_LEVELS;
                        tr.children[3].textContent = r.score.toLocaleString();
                        tbody.appendChild(tr);
                    });
                }
                $(".ctf-more").hidden = rows.length <= shown;
            }

            function renderStats(s) {
                TOTAL_LEVELS = s.solvesByLevel.length;
                $(".ctf-levels").style.gridTemplateColumns = $(".ctf-levels-axis").style.gridTemplateColumns = "repeat(" + TOTAL_LEVELS + ", 1fr)";
                setText("players", s.players);
                setText("finishers", s.finishers);
                setText("solves", s.solvesByLevel.reduce(function (a, b) { return a + b; }, 0));
                var max = Math.max.apply(null, s.solvesByLevel.concat([1]));
                var bars = $(".ctf-levels"), axis = $(".ctf-levels-axis");
                bars.textContent = ""; axis.textContent = "";
                s.solvesByLevel.forEach(function (n, i) {
                    var bar = document.createElement("div");
                    bar.style.height = (n / max * 100) + "%";
                    bar.title = "Level " + (i + 1) + ": " + n.toLocaleString() + " players";
                    bars.appendChild(bar);
                    var label = document.createElement("span");
                    label.textContent = "L" + (i + 1);
                    axis.appendChild(label);
                });
            }

            function load() {
                Promise.all([
                    fetch(api + "/leaderboard").then(function (r) { return r.json(); }),
                    fetch(api + "/stats").then(function (r) { return r.json(); })
                ]).then(function (res) {
                    rows = res[0];
                    renderStats(res[1]);
                    renderTable();
                }).catch(function () {
                    if (!rows.length) {
                        $("tbody").innerHTML = '<tr><td colspan="4" class="ctf-empty">The leaderboard is taking a break. Try again in a bit.</td></tr>';
                    }
                });
            }

            $(".ctf-more").addEventListener("click", function () { shown = 100; renderTable(); });
            load();
            setInterval(function () { if (!document.hidden) load(); }, 30000);
        })();
    </script>
</div>
<!--kg-card-end: html-->
<p>The leaderboard updates live. Players with the same score are ranked by who got there first. A ✓ next to a handle means it's linked to a Linux Handbook account.</p><h2 id="tips">Tips</h2><p>Read the hint more than once. Lord Tuxi likes wordplay, so read the verses closely, not just the words.</p><p>Look beyond the folder you start in. Many flags are elsewhere on the system, or held by something that's running.</p><p>If you break a level, type <code>restart</code> to get a fresh copy. It doesn't cost you anything.</p><h2 id="brush-up-on-the-skills">Brush up on the skills</h2><p>Stuck on a level? Rather than looking for a walkthrough, read up on the skill it tests. These tutorials cover everything you need.</p><ul><li><a href="https://linuxhandbook.com/ls-show-hidden-files/" rel="noreferrer">hidden files</a> and <code>ls -a</code></li><li><a href="https://linuxhandbook.com/find-command-examples/" rel="noreferrer">find command</a></li><li><a href="https://linuxhandbook.com/filename-spaces-linux/" rel="noreferrer">quoting and special characters</a> in file names</li><li>tar and unzip</li><li><a href="https://linuxhandbook.com/crontab/" rel="noreferrer">cron jobs</a>, <code>base64</code></li><li><code>ps</code>, <code>netstat</code>/<code>ss</code>, <code>curl</code> with headers</li><li><code>/proc</code> and process environment</li><li><code>grep</code>, <code>awk</code>, <code>tr</code></li><li><a href="https://linuxhandbook.com/hard-link/" rel="noreferrer">hard links</a> and <a href="https://linuxhandbook.com/inode-linux/" rel="noreferrer">inodes</a></li><li><a href="https://linuxhandbook.com/suid-sgid-sticky-bit/" rel="noreferrer">SUID permissions</a></li></ul><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">🐛</div><div class="kg-callout-text">Found a bug in a level? <a href="https://github.com/linuxhandbook/ctf/issues?ref=linuxhandbook.com">Open an issue on GitHub</a>.</div></div><h2 id="play-fair">Play fair</h2><p>The flags are inside the Docker images on your computer, so you could dig them out instead of solving the puzzles. Please don't. You'd skip exactly the part that teaches you something.</p><p>And please don't post flags or full solutions. Share how you approached a level instead.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Link Your CTF Handle to Your Linux Handbook Account]]></title>
                    <description><![CDATA[Link your Linux Handbook CTF handle to your account to keep it on every computer and unlock members-only games.]]></description>
                    <link>https://linuxhandbook.com/ctf/link/</link>
                    <guid isPermaLink="false">6abce5635616fe000192fc09</guid>

                        <category><![CDATA[CTF]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Wed, 30 Sep 2026 16:56:35 +0530</pubDate>


                    <content:encoded><![CDATA[
<!--kg-card-begin: html-->
<div class="ctfl-root" data-api="https://ctf.linuxhandbook.com">
    <!-- Linux Handbook CTF: link a play.py handle to a member account.
         For the post linuxhandbook.com/ctf-link/ (keep the post itself public:
         this card handles sign-in through Portal). Paste the whole snippet into
         a Ghost HTML card. play.py sends players here as /ctf-link/?code=XXXX-XXXX.

         How it works: Ghost gives a signed-in member a short-lived signed token
         (/members/api/entitlements). This card passes it to the CTF server with
         the code, and the server checks Ghost's signature. No email or password
         ever leaves Ghost. -->
    <style>
        .ctfl-root {
            --ctfl-accent: var(--ghost-accent-color, #a52c5b);
            --ctfl-muted: color-mix(in srgb, currentColor 62%, transparent);
            --ctfl-border: color-mix(in srgb, currentColor 16%, transparent);
            --ctfl-soft: color-mix(in srgb, var(--ctfl-accent) 8%, transparent);
            max-width: 560px;
            margin: 0 auto;
            font: inherit;
        }
        .ctfl-card {
            border: 1px solid var(--ctfl-border);
            border-radius: 12px;
            padding: 28px 24px;
            text-align: center;
        }
        .ctfl-code {
            display: inline-block;
            font-family: var(--font-mono, ui-monospace, monospace);
            font-size: 1.5em;
            letter-spacing: 0.08em;
            padding: 6px 14px;
            border-radius: 8px;
            background: var(--ctfl-soft);
            color: var(--ctfl-accent);
            margin: 4px 0 16px;
        }
        .ctfl-card h3 { margin: 0 0 10px; font-size: 1.25em; }
        .ctfl-card p { margin: 0 0 14px; }
        .ctfl-muted { color: var(--ctfl-muted); font-size: 0.9em; }
        .ctfl-handle { font-family: var(--font-mono, ui-monospace, monospace); font-weight: 700; }
        .ctfl-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 18px; }
        .ctfl-btn {
            display: inline-block;
            padding: 10px 20px;
            border-radius: 8px;
            border: 1px solid var(--ctfl-accent);
            background: var(--ctfl-accent);
            color: #fff !important;
            font: inherit;
            font-weight: 600;
            text-decoration: none !important;
            cursor: pointer;
        }
        .ctfl-btn.ctfl-ghost { background: none; color: var(--ctfl-accent) !important; }
        .ctfl-btn:disabled { opacity: 0.6; cursor: wait; }
        .ctfl-warn {
            margin-top: 16px;
            padding: 10px 12px;
            border-radius: 8px;
            background: var(--ctfl-soft);
            font-size: 0.85em;
            text-align: left;
        }
        .ctfl-input {
            font-family: var(--font-mono, ui-monospace, monospace);
            font-size: 1.1em;
            text-transform: uppercase;
            padding: 8px 12px;
            border: 1px solid var(--ctfl-border);
            border-radius: 8px;
            background: none;
            color: inherit;
            width: 12em;
            text-align: center;
        }
        .ctfl-big { font-size: 2.4em; line-height: 1; margin-bottom: 8px; }
    </style>

    <div class="ctfl-card" aria-live="polite">
        <p class="ctfl-muted">Loading…</p>
    </div>

    <script>
        (function () {
            var root = document.currentScript.closest(".ctfl-root");
            var api = root.getAttribute("data-api");
            var card = root.querySelector(".ctfl-card");
            var codeRe = /^[A-Z2-9]{4}-[A-Z2-9]{4}$/;
            var code = (new URLSearchParams(location.search).get("code") || "").toUpperCase().trim();

            function esc(s) {
                return String(s).replace(/[&<>"']/g, function (c) {
                    return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c];
                });
            }
            function show(html) { card.innerHTML = html; }
            function codeBadge() { return '<div class="ctfl-code">' + esc(code) + "</div>"; }

            // Ghost returns a signed token for a signed-in member, 204 otherwise.
            function memberToken() {
                return fetch("/members/api/entitlements", { credentials: "same-origin" })
                    .then(function (r) { return r.status === 200 ? r.text() : null; });
            }

            function askForCode(msg) {
                show('<h3>Link your CTF handle</h3>' +
                    '<p class="ctfl-muted">' + (msg || "Run <code>python3 play.py link</code> and enter the code it shows.") + "</p>" +
                    '<form class="ctfl-actions"><input class="ctfl-input" placeholder="ABCD-1234" maxlength="9" autocomplete="off" required>' +
                    '<button class="ctfl-btn" type="submit">Continue</button></form>');
                card.querySelector("form").addEventListener("submit", function (e) {
                    e.preventDefault();
                    var v = card.querySelector("input").value.toUpperCase().replace(/\s/g, "");
                    if (v.length === 8) v = v.slice(0, 4) + "-" + v.slice(4);
                    if (!codeRe.test(v)) return;
                    code = v;
                    history.replaceState(null, "", "?code=" + encodeURIComponent(code));
                    start();
                });
            }

            function signInPrompt() {
                show(codeBadge() +
                    "<h3>Sign in to continue</h3>" +
                    "<p>Use your Linux Handbook account. A free account is enough.</p>" +
                    '<div class="ctfl-actions">' +
                    '<a class="ctfl-btn" href="#/portal/signin" data-portal="signin">Sign in</a>' +
                    '<a class="ctfl-btn ctfl-ghost" href="#/portal/signup" data-portal="signup">Create free account</a>' +
                    "</div>" +
                    '<p class="ctfl-muted" style="margin-top:16px">After signing in, come back to this page. The code stays valid for 10 minutes.</p>');
            }

            function confirmPrompt(info) {
                var what = info.kind === "link"
                    ? "Link the handle <span class=\"ctfl-handle\">" + esc(info.handle) + "</span> to your Linux Handbook account?"
                    : "Sign in to <strong>play.py</strong> on your computer with your Linux Handbook account?";
                var after = info.kind === "link"
                    ? "You'll be able to play as this handle on any computer, and it can't be lost with your ~/.ctf_user file."
                    : "If your account already has a handle, that computer will play as it. If not, you'll pick one in the terminal.";
                show(codeBadge() + "<h3>" + what + "</h3>" +
                    '<p class="ctfl-muted">' + after + "</p>" +
                    '<div class="ctfl-actions"><button class="ctfl-btn" type="button">Yes, continue</button></div>' +
                    '<div class="ctfl-warn">⚠️ Only continue if <strong>you</strong> just ran play.py and it showed this exact code. ' +
                    "If someone sent you this link, close this page.</div>");
                var btn = card.querySelector("button");
                btn.addEventListener("click", function () {
                    btn.disabled = true;
                    btn.textContent = "Linking…";
                    complete();
                });
            }

            function complete() {
                memberToken().then(function (token) {
                    if (!token) return signInPrompt();
                    return fetch(api + "/api/link/complete", {
                        method: "POST",
                        headers: { "Content-Type": "application/json" },
                        body: JSON.stringify({ code: code, token: token })
                    }).then(function (r) {
                        return r.json().then(function (body) { return { ok: r.ok, body: body }; });
                    }).then(function (res) {
                        if (!res.ok) return failed(res.body.error);
                        var s = res.body.status, h = esc(res.body.handle || "");
                        var msg = s === "linked" ? "Your handle <span class=\"ctfl-handle\">" + h + "</span> is now linked."
                            : s === "signed-in" ? "Signed in as <span class=\"ctfl-handle\">" + h + "</span>."
                            : "Signed in. Your account has no handle yet, so pick one in the terminal.";
                        show('<div class="ctfl-big">✅</div><h3>Done!</h3><p>' + msg + '</p>' +
                            '<p class="ctfl-muted">Go back to your terminal. play.py picks it up in a couple of seconds.</p>');
                    });
                }).catch(function () { failed("Couldn't reach the CTF server. Please try again."); });
            }

            function failed(msg) {
                show('<div class="ctfl-big">😕</div><h3>That didn\'t work</h3><p>' + esc(msg || "Something went wrong.") + "</p>" +
                    '<p class="ctfl-muted">Run <code>python3 play.py link</code> again to get a new code.</p>');
            }

            function start() {
                if (!codeRe.test(code)) return askForCode();
                fetch(api + "/api/link/info?code=" + encodeURIComponent(code))
                    .then(function (r) { return r.json().then(function (b) { return { ok: r.ok, body: b }; }); })
                    .then(function (res) {
                        if (!res.ok) return askForCode(esc(res.body.error || "That code has expired."));
                        if (res.body.status !== "pending") return failed("This code has already been used.");
                        return memberToken().then(function (token) {
                            token ? confirmPrompt(res.body) : signInPrompt();
                        });
                    })
                    .catch(function () { failed("Couldn't reach the CTF server. Please try again."); });
            }

            start();
        })();
    </script>
</div>
<!--kg-card-end: html-->
<p>Your CTF handle is tied to the computer you play on, through a key saved in <code>~/.ctf_user</code>. Link it to your Linux Handbook account and it goes wherever you go. A free account is enough.</p><h2 id="why-link-your-handle">Why link your handle</h2><p>You can play as the same handle, with the same progress, on any computer. You also don't lose it if you delete <code>~/.ctf_user</code> or reinstall your system.</p><p>Some future games will be for Linux Handbook members. A linked handle is how you get into those.</p><h2 id="how-to-link">How to link</h2><p>In your terminal, run:</p><pre><code class="language-bash">python3 play.py link
</code></pre><p>You can also type <code>link</code> in the game menu. The game shows a short code and opens this page with it.</p><p>Sign in to Linux Handbook if you aren't already, check that the code on this page matches the one in your terminal, and confirm. The game picks it up in a couple of seconds.</p><p>Only confirm a code your own terminal is showing right now. If someone sent you a link to this page with a code in it, close the page.</p><h2 id="playing-on-another-computer">Playing on another computer</h2><p>Run <code>play.py</code> on the new computer. On the first run, choose "I've played before: sign in with my Linux Handbook account" instead of picking a new handle. Confirm the code here, and you're back to your handle and progress.</p><h2 id="what-gets-stored">What gets stored</h2><p>The CTF server stores your Linux Handbook member ID and whether your membership is paid. That's how it finds your handle again.</p><p>Your email address and password never reach the CTF server. When you confirm, Linux Handbook hands this page a short-lived signed token, and the CTF server checks the signature.</p><p>Want your handle unlinked? Contact us.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Linux CTF Challenges]]></title>
                    <description><![CDATA[Free capture-the-flag games that test your Linux command line skills. No account needed. The levels run in Docker on your own computer.]]></description>
                    <link>https://linuxhandbook.com/ctf/</link>
                    <guid isPermaLink="false">6abcaa415616fe000192fb97</guid>

                        <category><![CDATA[CTF]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Wed, 30 Sep 2026 16:56:04 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/09/lhb-ctf.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/09/lhb-ctf.webp" alt="Linux CTF Challenges"/> <p>Think you know your way around the Linux command line? Prove it.</p><p>A capture-the-flag game, or CTF, hides a secret string somewhere in a system and challenges you to find it. It's a long-standing tradition in the security world. </p><p>Here, the idea is simpler: each game is a set of small Linux puzzles, and you solve them with the same commands you use every day.</p><p>There's no browser-based hand-holding and no multiple choice. You get a shell, a hint and a hidden flag. Find the flag, submit it and move on to the next level.</p><p>The games are free, and you don't need an account to play.</p><h2 id="the-games">The games</h2><p>Pick one and start. Each game page has its own quick start, so you can jump straight in.</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">📋</div><div class="kg-callout-text">More games are on the way. Some will be for Linux Handbook members only. Perfect time to get a membership.</div></div><h2 id="how-it-works">How it works</h2><p>Every level is a small Linux system that runs in a Docker container on your own computer. You get a real shell to poke around in, and it stays fast no matter how many people are playing.</p><p>A small program, <code>play.py</code>, handles everything else. It downloads one level at a time, starts it, opens a shell for you and sends your flags to the Linux Handbook server. The only things that leave your computer are your handle and the flags you submit.</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/how-it-works-dark.svg" class="kg-image" alt="How the CTF works on LHB" loading="lazy" width="960" height="470"></figure><h2 id="what-you-need">What you need</h2><p>You need Linux or macOS with Docker installed and running. On Windows, play inside WSL 2.</p><p>If you don't have Docker yet, follow the <a href="https://docs.docker.com/engine/install/?ref=linuxhandbook.com">official install guide</a>.</p><pre><code class="language-bash">sudo apt install docker.io
</code></pre><p>You also need Python 3.7 or newer. It's already there on most Linux distributions, and the game needs nothing beyond Python's standard library.</p><h2 id="get-the-game">Get the game</h2><p>Download <code>play.py</code> :</p><pre><code class="language-bash">curl -fsSLO https://ctf.linuxhandbook.com/play.py
</code></pre><p>And then run it:</p><pre><code>python3 play.py</code></pre><p>On the first run, you pick a handle. That's the name shown on the leaderboards. Then choose a game from the menu.</p><p>If Docker needs root on your system, use <code>sudo python3 play.py</code>. Or add yourself to the <code>docker</code> group so you don't need <code>sudo</code>:</p><pre><code class="language-bash">sudo usermod -aG docker $USER
</code></pre><p>Log out and back in for the group change to apply.</p><h2 id="how-to-play">How to play</h2><p>Every game works the same way. Choose it from the menu, then type <code>play</code> to enter the level. Your first command inside should be:</p><pre><code class="language-bash">cat hint.txt
</code></pre><p>The hint is a riddle. Every word in it matters. Flags look like <code>LHB{...}</code>. When you find one, copy it, type <code>exit</code> to leave the level and submit it:</p><pre><code>submit LHB{...}
</code></pre><p>These are the commands you can use at the game prompt:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Command</th>
<th>What it does</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>play</code></td>
<td>Open a shell inside the level. Type <code>exit</code> to come back</td>
</tr>
<tr>
<td><code>submit LHB{...}</code></td>
<td>Submit the flag for this level</td>
</tr>
<tr>
<td><code>leaderboard</code></td>
<td>Top 10 for this game</td>
</tr>
<tr>
<td><code>restart</code></td>
<td>Throw the level away and start it fresh</td>
</tr>
<tr>
<td><code>menu</code></td>
<td>Back to the list of games</td>
</tr>
<tr>
<td><code>quit</code></td>
<td>Leave. Your progress is saved</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>You play the levels in order, and each one gives its points once. Quit whenever you like. Run <code>python3 play.py</code> again later and you continue from the same level.</p>
<!--kg-card-begin: html-->
<div class="muse-video-player" data-video="9LRZVMB" data-links="0" data-logo="https://linuxhandbook.com/content/images/2021/08/linux-handbook-cover.png" data-title="0" data-autoplay="0" data-subtitles="auto" data-width="100%"></div><script src="https://skiv.com/static/js/embed-player.min.js"></script>
<!--kg-card-end: html-->
<h2 id="your-handle">Your handle</h2><p>There's no sign-up. The first time you play, <code>play.py</code> creates a random key for your computer and saves it in <code>~/.ctf_user</code>. The server ties your handle to that key, so nobody else can play as you.</p><p>The catch is that your handle lives on that one computer. Lose the file or switch machines, and the handle stays behind. If you have a free Linux Handbook account, <a href="https://linuxhandbook.com/ctf/link/" rel="noreferrer">link your handle to it</a> and you can play from anywhere.</p><h2 id="play-fair">Play fair</h2><p>The levels run on your computer, and the flags are inside them. So yes, you could <a href="https://linuxhandbook.com/docker-inspect-command/" rel="noreferrer">dig the flags out of the Docker images</a> instead of solving anything.</p><p>I can't stop you, but you'd only be cheating yourself. The point is to learn something, and the fun is in that moment when the flag finally shows up in your terminal.</p><p>Please don't share flags or full solutions publicly. Talking about approaches is fine.</p><h2 id="faqs">FAQs</h2><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><span style="white-space: pre-wrap;">Is it free?</span></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">Most CTF games are. This will be mentioned on the game page.</span></p></div>
        </div><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><span style="white-space: pre-wrap;">Is it safe to run on my computer?</span></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">The levels run inside Docker containers, not on your system directly, and they're removed once you solve them. </span><code spellcheck="false" style="white-space: pre-wrap;"><span>play.py</span></code><span style="white-space: pre-wrap;"> is a single Python file you can read on </span><a href="https://github.com/linuxhandbook/ctf?ref=linuxhandbook.com"><span style="white-space: pre-wrap;">GitHub</span></a><span style="white-space: pre-wrap;"> before running it. </span></p></div>
        </div><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><span style="white-space: pre-wrap;">Can I play on Windows?</span></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">Yes, inside WSL 2 with Docker available there. Native Windows isn't supported.</span></p></div>
        </div><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><span style="white-space: pre-wrap;">I'm stuck. Where are the solutions?</span></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">There are no published walkthroughs, and that's on purpose. Read the hint again, then look up the commands it points you toward. Each game page links to tutorials that cover the skills it tests. So that could give you some hint as well. If nothing works and you really want to know, just send us a message.</span></p></div>
        </div><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><b><strong style="white-space: pre-wrap;">A level seems broken.</strong></b></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">Type </span><code spellcheck="false" style="white-space: pre-wrap;"><span>restart</span></code><span style="white-space: pre-wrap;"> to reset it. If it's still broken, </span><a href="https://github.com/linuxhandbook/ctf/issues?ref=linuxhandbook.com"><span style="white-space: pre-wrap;">open an issue on GitHub</span></a><span style="white-space: pre-wrap;"> and tell me which level and what you saw.</span></p></div>
        </div><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><span style="white-space: pre-wrap;">What do you store about me?</span></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">Your handle, a hash to identify your handle and machine, and which levels you solved and when. If you link a Linux Handbook account, also your member ID and whether your membership is paid. Your email never reach the CTF server and there is no password anywhere.</span></p></div>
        </div><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><span style="white-space: pre-wrap;">How do I start over?</span></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">Run </span><code spellcheck="false" style="white-space: pre-wrap;"><span>python3 play.py -r</span></code><span style="white-space: pre-wrap;">. If your handle isn't linked to a Linux Handbook account, this gives it up for good. Your handle and score stay on the leaderboard.</span></p></div>
        </div><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><span style="white-space: pre-wrap;">How do I clean up afterwards?</span></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">Solved levels are removed automatically. To delete any leftover images, run </span><code spellcheck="false" style="white-space: pre-wrap;"><span>docker rmi $(docker images -q ghcr.io/linuxhandbook/ctf)</span></code></p></div>
        </div><div class="kg-card kg-toggle-card" data-kg-toggle-state="close">
            <div class="kg-toggle-heading">
                <h4 class="kg-toggle-heading-text"><span style="white-space: pre-wrap;">How do I delete my handle and scores completely?</span></h4>
                <button class="kg-toggle-card-icon" aria-label="Expand toggle to read content">
                    <svg id="Regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path class="cls-1" d="M23.25,7.311,12.53,18.03a.749.749,0,0,1-1.06,0L.75,7.311"></path>
                    </svg>
                </button>
            </div>
            <div class="kg-toggle-content"><p><span style="white-space: pre-wrap;">Run </span><code spellcheck="false" style="white-space: pre-wrap;"><span>python3 play.py --delete-me</span></code><span style="white-space: pre-wrap;"> and it will delete your handle and the scores associated with it. Your username and score is removed from the leaderboard as well. This is permanent and cannot be reversed.</span></p></div>
        </div><p>Enjoy capturing the flags 🎏</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.13: Know Your File, File-based Workspace Certifications and More]]></title>
                    <description><![CDATA[Sometimes the fastest fix is just asking the right question first.]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-13/</link>
                    <guid isPermaLink="false">6aacc09e5616fe00019278c1</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Fri, 18 Sep 2026 18:17:47 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/09/lhb-newsletter-1--1.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/09/lhb-newsletter-1--1.png" alt="LHB Linux Digest #26.13: Know Your File, File-based Workspace Certifications and More"/> <p>There is a new addition to the Digest from this edition. There's a dedicated self-hosting section. Actually, it's a re-entry, as there used to be such a section earlier. Self-hosting is gaining even more popularity. </p><p>Docker compose has made things easier and then the privacy concern has made people aware. And thus the dedicated self-host section is back. Even if you do not self-host, at least you can discover some cool new tool.</p><h2 id="know-your-file-before-you-open-it">Know your file before you open it</h2><p>Everything is a file in Linux and you'd be surprised how much a file will tell you before you even open it. The trick is knowing which command to ask.</p><p>Start with the <a href="https://linuxhandbook.com/file-command/" rel="noreferrer">file command</a>. It ignores the extension entirely and reads the actual contents to tell you what something really is. That download with no extension, or the <code>.txt</code> that's secretly a JPEG? Just run file on it:</p><pre><code>file mysterious-file</code></pre><p>Once you know what it is, <a href="https://linuxhandbook.com/stat-command/" rel="noreferrer">stat</a> fills in everything else: exact size, owner, permissions, and <a href="https://linuxhandbook.com/file-timestamps/" rel="noreferrer">three separate timestamps</a> for when the file was last read, when its contents changed, and when its metadata was last touched. Think of it as <code>ls -l</code> but for a specific file and with more details.</p><p>Then there's <a href="https://linuxhandbook.com/get-file-path/">realpath</a>, for when you're not even sure where the file is located. That's why the name "real path". It resolves every symlink and those <code>..</code> in the path and gives you the real location of the file. Handy when you're inside a symlinked directory and a script keeps writing to the "wrong" place.</p><p>And if a file won't budge with a "resource busy" error, <a href="https://linuxhandbook.com/lsof-command/" rel="noreferrer">lsof</a> shows you exactly which process is holding it open, so you know what to stop before trying again.</p><h2 id="%F0%9F%92%A1quick-terminal-tip"><strong>💡</strong>Quick terminal tip</h2><p>The <code>namei</code> command breaks down a file path component by component to display the permissions of every ancestor directory.</p><pre><code>namei -l &lt;/home/linuxhandbook/Projects/scripts.sh&gt;
</code></pre><p>The above command will show the permission of each item in the path in a compact list.</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/namei-command.png" class="kg-image" alt="" loading="lazy" width="715" height="175" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/namei-command.png 600w, https://linuxhandbook.com/content/images/2026/09/namei-command.png 715w"></figure><p>This is especially useful when resolving unexplained "Permission Denied" errors where a file is readable, but a parent directory lacks execute (<code>+x</code>) access.</p><h2 id="%F0%9F%8E%93-make-your-linux-skills-official">🎓 Make your Linux skills official </h2><figure class="kg-card kg-image-card"><a href="https://www.awin1.com/cread.php?awinmid=85919&awinaffid=429005&ued=https%3A%2F%2Ftraining.linuxfoundation.org%2Fseptember-2026-promo%2F&ref=linuxhandbook.com"><img src="https://linuxhandbook.com/content/images/2026/09/lf-deal.webp" class="kg-image" alt="" loading="lazy" width="1200" height="628" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/lf-deal.webp 600w, https://linuxhandbook.com/content/images/size/w1000/2026/09/lf-deal.webp 1000w, https://linuxhandbook.com/content/images/2026/09/lf-deal.webp 1200w" sizes="(min-width: 720px) 720px"></a></figure><p>Either you are an expert or you are learning. But a certification is how you prove your skill to someone who's hiring.</p><p>Linux Foundation, the official organization behind the Linux project, offers numerous certification and training exams that hold value in the job market.</p><p>Their <a href="https://www.awin1.com/cread.php?awinmid=85919&awinaffid=429005&ued=https%3A%2F%2Ftraining.linuxfoundation.org%2Fseptember-2026-promo%2F&ref=linuxhandbook.com">back-to-school sale is running until September 22</a>. The LFCS, their Certified System Administrator exam, is the obvious pick if Linux is your day job. Bundle it with the LFS207 course and the price drops from $645 to $387.</p><p>Going for the more lucrative Kubernetes and DevOps instead? The CKA course-and-exam bundle is also $645 down to $387, and the full CKA + CKAD + CKS exam bundle goes from $1245 to $747.</p><p>There are two codes depending on what you pick. <code>SEPT26BTS35</code> takes 35% off individual courses and certifications, and <code>SEPT26BTS40</code> takes 40% off bundles and instructor-led courses.</p><p>If a cert has been sitting on your list for months (or years), take advantage of the discount. It closes on September 22.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://www.awin1.com/cread.php?awinmid=85919&awinaffid=429005&ued=https%3A%2F%2Ftraining.linuxfoundation.org%2Fseptember-2026-promo%2F&ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Get 40% off on Certifications</a></div><h2 id="%F0%9F%93%A6-self-hosting">📦 Self-hosting </h2><p><a href="https://github.com/fccview/jotty?ref=linuxhandbook.com">Jotty</a> is a self-hosted, file-based workspace for personal notes, checklists, and project tasks. There's no external database to run, it just reads and writes plain files, which makes backups and syncing easier. A good fit if Notion feels like overkill and you'd rather own the data.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/fccview/jotty?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - fccview/jotty at linuxhandbook.com</div><div class="kg-bookmark-description">Lightweight but powerful alternative for managing your personal, file based, notes and checklists. - fccview/jotty</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-7d702d3b-92cc-4518-8fd8-c2861f2907f3.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">fccview</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/jotty-bd0e0523-848f-442b-b22c-4aead3bdf9e4" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%9B%A0%EF%B8%8F-tool-discovery">🛠️ Tool discovery</h2><p><a href="https://github.com/lerd-env/lerd?ref=linuxhandbook.com">Lerd</a> is an open-source local PHP dev environment inspired by Laravel Herd. It gives you a rootless, zero-Docker workflow on Linux, macOS, and WSL2. If you've been spinning up containers just to run a PHP project locally, try this lighter alternative.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/lerd-env/lerd?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - lerd-env/lerd: Open-source, Herd-like local PHP development environment for Linux and macOS. Automatic .test domains, per-project PHP/Node isolation, one-command TLS. Podman-native, rootless.</div><div class="kg-bookmark-description">Open-source, Herd-like local PHP development environment for Linux and macOS. Automatic .test domains, per-project PHP/Node isolation, one-command TLS. Podman-native, rootless. - lerd-env/lerd</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-94d5cbb5-daa1-4b98-aec5-3c84472a108d.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">lerd-env</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/f3cbb867-0869-41d0-a2ae-e3ae55a1f8a5-87220666-e8f8-4167-a6c9-53bb07d65a4c" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%93%B0-linux-news-that-matters">📰 Linux news that matters</h2><ul><li><a href="https://itsfoss.com/linux-stories/italian-logistics-company-migration/?ref=linuxhandbook.com">An Italian logistics company in Bergamo successfully migrated its office operations from Windows</a> to Kubuntu LTS, Nextcloud, and Mattermost, cutting recurring licensing fees and eliminating daily workstation slowdowns without disrupting freight operations.</li><li><a href="https://www.securityweek.com/1-million-sandbox-challenge-uncovers-linux-kernel-flaws/?ref=linuxhandbook.com">Vercel’s two-week, $1 million sandbox bug bounty challenge</a> against its Firecracker microVMs received 1,285 submissions that breached no customer data, but exposed two upstream Linux kernel networking defects causing deterministic host crashes and host memory leaks.</li><li><a href="https://www.phoronix.com/news/Ubuntu-Considers-Linux-Firm-HWE?ref=linuxhandbook.com">Canonical developers are proposing a dedicated linux-firmware-hwe package</a> for Ubuntu LTS releases to decouple newer hardware enablement firmware from General Availability kernels, preventing driver regressions for users staying on older kernel baselines.</li><li><a href="https://www.prnewswire.com/news-releases/open-secure-ai-alliance-joins-the-linux-foundation-to-build-a-shared-open-defense-stack-for-the-ai-era-302877844.html?ref=linuxhandbook.com">The Open Secure AI Alliance has joined the Linux Foundation</a> to establish neutral governance for open-source AI defense tools, opening an RFC on its SAFE initiative to standardize incident reporting.</li><li><a href="https://www.prnewswire.com/news-releases/sidero-labs-launches-talos-enterprise-linux-302877045.html?ref=linuxhandbook.com">Sidero Labs has launched Talos Enterprise Linux</a>, introducing a commercial tier with FIPS 140-3 builds, SBOMs, and regulatory compliance artifacts while keeping the core operating system fully open source under MPL-2.0.</li></ul><h2 id="%F0%9F%98%82-geek-humor">😂 Geek humor</h2><p>Actually, I do both ;)</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/lhb-meme-sep-18.jpg" class="kg-image" alt="" loading="lazy" width="1440" height="1800" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/lhb-meme-sep-18.jpg 600w, https://linuxhandbook.com/content/images/size/w1000/2026/09/lhb-meme-sep-18.jpg 1000w, https://linuxhandbook.com/content/images/2026/09/lhb-meme-sep-18.jpg 1440w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%92%8C-keep-on-loving-linux-handbook">💌 Keep on loving Linux Handbook</h2><p>The GitOps course is nearly ready and lands next week, built on the Git basics course. <a href="https://linuxhandbook.com/#/portal/signup">Get your Pro membership</a> now and you'll have it the moment it drops, plus unlimited access to our <a href="https://linuxhandbook.com/ebooks/">eBooks</a>, <a href="https://linuxhandbook.com/courses/">courses</a>, and every tutorial we've published.</p><p><strong>Missed the previous editions?</strong>&nbsp;You can&nbsp;<a href="https://linuxhandbook.com/newsletter/">access the newsletter archives.</a></p><p>I like reading your messages, so just hit the reply button and share your thoughts 😄</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.12: Demystifying diff, Process Substitution, History Trick, and More]]></title>
                    <description><![CDATA[Keep on Linux-ing :)]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-12/</link>
                    <guid isPermaLink="false">6aa3a0e25616fe000191f4b3</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Fri, 11 Sep 2026 17:29:04 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/09/lhb-newsletter-1--1.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/09/lhb-newsletter-1--1.png" alt="LHB Linux Digest #26.12: Demystifying diff, Process Substitution, History Trick, and More"/> <p>Last week, we revealed the <a href="https://linuxhandbook.com/courses/tmux/">Free Tmux course</a>. I am also working on creating roadmaps so that members can follow a dedicated learning path with all the resources we have created in the last 8 years. </p><p>Next week, we should have the GitOps course, focusing on ArgoCD. This will build upon the foundation of the <a href="https://linuxhandbook.com/courses/git/">Git basics course</a>. </p><h2 id="essential-linux-concept-diff">Essential Linux concept: diff</h2><p>All that Git talk actually rests on a very old, very simple Linux idea. You compare two versions of something, and then you act on the difference.</p><p>That's exactly what the <a href="https://linuxhandbook.com/diff-command/">diff command</a> does. You give it two files, and it tells you what you'd need to change in one to make it match the other. It's the same mental model your version control uses under the hood.</p><p>The output looks cryptic the first time you meet it, with things like <code>2c2</code>, <code>3a4</code> and <code>5d5</code>. Once you learn to read it, it makes complete sense. We explain the output line by line in <a href="https://linuxhandbook.com/diff-command/">this guide</a>.</p><p>Here's the part most of us forget: <code>diff</code> isn't limited to single files. With <code>diff -r</code> you can <a href="https://linuxhandbook.com/compare-directories/">compare two entire directories</a> and spot exactly how two config folders drifted apart. And if you find yourself creating temporary files just to compare two command outputs, <a href="https://linuxhandbook.com/bash-process-substitution/">process substitution</a> lets you do it in one line: <code>diff &lt;(command1) &lt;(command2)</code>.</p><h2 id="%F0%9F%92%A1quick-terminal-tip"><strong>💡</strong>Quick terminal tip</h2><p>Using history expansions like <code>!$</code> (last argument) or <code>!!</code> (entire previous command) can feel like a gamble when running destructive operations. You only see what it resolved to after you have pressed the Enter key.</p><p>Bind Readline's magic-space to expand history references instantly as soon as you press the Spacebar:</p><p>Open the <code>~/.inputrc</code> file and add the following line at the end.</p><pre><code class="language-bash">Space: magic-space
</code></pre><p>Restart the terminal session.</p><p>When you type <code>sudo !!</code> or <code>rm -rf !$</code> and hit Space, the shell immediately replaces the tokens with the full command string right in front of your eyes. You can review, edit, or back out before executing, eliminating both keystrokes and blind execution risk.</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/expansion.gif" class="kg-image" alt="" loading="lazy" width="826" height="493" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/expansion.gif 600w, https://linuxhandbook.com/content/images/2026/09/expansion.gif 826w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%9B%A0%EF%B8%8F-tool-discovery">🛠️ Tool discovery</h2><p>Let's see if you find your next favorite tool.</p><h3 id="monoscope-open-source-observability-and-trace-aggregator-for-distributed-microservices">Monoscope: Open-Source Observability and Trace Aggregator for Distributed Microservices</h3><p><a href="https://github.com/monoscope-tech/monoscope?ref=linuxhandbook.com">Monoscope</a> is an open-source observability engine tailored for developers needing unified log, metric, and distributed trace visibility across local containers and multi-service staging environments.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/monoscope-tech/monoscope?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - monoscope-tech/monoscope: Monoscope lets you ingest and explore your logs, traces and metrics. We store these in S3 compatible buckets. Query in natural language via LLMs.</div><div class="kg-bookmark-description">Monoscope lets you ingest and explore your logs, traces and metrics. We store these in S3 compatible buckets. Query in natural language via LLMs. - monoscope-tech/monoscope</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-52635665-88cc-48f3-9bb3-5a9f57fd4f90.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">monoscope-tech</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/monoscope-a2663e6d-d664-4511-b443-11fc5bc54be8" alt="" onerror="this.style.display = 'none'"></div></a></figure><h3 id="colanode-open-source-local-first-collaboration-workspace">Colanode: Open-Source, Local-First Collaboration Workspace</h3><p><a href="https://github.com/colanode/colanode?ref=linuxhandbook.com">Colanode</a> is an open-source, local-first collaboration platform designed to unify documents, structured databases, real-time chat, and file management under a self-hosted architecture.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/colanode/colanode?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - colanode/colanode: Open-source and local-first Slack and Notion alternative that puts you in control of your data</div><div class="kg-bookmark-description">Open-source and local-first Slack and Notion alternative that puts you in control of your data - colanode/colanode</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-2dfbdc72-08ac-4300-b39b-c57ba9001e03.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">colanode</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/colanode-89234355-a983-4274-92b2-23ab8a3ee963" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%93%A3-event-alert">📣 Event alert</h2><p>AGNTCon + MCPCon Europe is happening in Amsterdam on 17–18 September, and if you're building anything in the agentic AI or MCP space, this is the event to attend.</p><p>The event is full of open source maintainers, enterprise engineers, infra and tooling folks, and researchers. </p><p>You'll bump into the people building MCP itself, alongside teams from AWS, Google, Hugging Face, Microsoft, Anthropic, Solo.io, and a long list of startups exploring Agentic AI.</p><p><strong>You can knock off your ticket prices with code ITSFOSS_50.</strong></p><p>🗓 17–18 September<br>📍 RAI Amsterdam</p><div class="kg-card kg-button-card kg-align-center"><a href="https://events.linuxfoundation.org/agntcon-mcpcon-europe/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Register for AGNTCon + MCPCon Europe</a></div><h2 id="%F0%9F%93%B0-linux-news-that-matters">📰 Linux news that matters</h2><ul><li><a href="https://itsfoss.com/news/broadcom-removes-vmware-vddk-downloads/?ref=linuxhandbook.com">Broadcom has quietly removed all public download pages for the VMware Virtual Disk Development Kit (VDDK)</a>, restricting future access exclusively to authorized Technology Alliance partners.</li><li><a href="https://www.bleepingcomputer.com/news/security/hackers-breach-f5-big-ip-apm-devices-to-deploy-linux-rootkit/?ref=linuxhandbook.com">Threat actors are actively breaching F5 BIG-IP APM appliances</a> to deploy "PoisonedRefresh," a stealthy Linux rootkit that persists across firmware upgrades and modifies SELinux policies.</li><li><a href="https://itsfoss.com/news/cern-debian-push/?ref=linuxhandbook.com">CERN is migrating over 2,200 accelerator control computers to Debian 13</a> to bypass restrictive enterprise CPU requirements and modernize hardware lifecycle management. In a parallel push toward digital sovereignty, the <a href="https://itsfoss.com/news/switzerland-replace-microssoft-pilot/?ref=linuxhandbook.com">Swiss government has launched a CHF 9 million pilot</a> deploying openDesk to replace Microsoft 365 across 3,000 federal workstations.</li><li><a href="https://www.phoronix.com/news/Intel-Dynamic-PAMT-For-7.4?ref=linuxhandbook.com">Intel's Dynamic PAMT support has been queued in the x86/tdx tree for Linux 7.4</a>, reducing the ~0.4% baseline memory overhead required by Trust Domain Extensions by allocating the Physical Address Metadata Table dynamically rather than upfront.</li><li><a href="https://www.marktechpost.com/2026/09/09/google-open-sources-mantis-a-modular-skills-toolkit-that-lets-coding-agents-find-reproduce-and-patch-vulnerabilities/?ref=linuxhandbook.com">Google has open-sourced Mantis under Apache 2.0</a>, providing a modular framework of slash-command skills that enables AI coding agents to manage end-to-end vulnerability triage.</li></ul><h2 id="%F0%9F%98%82-geek-humor">😂 Geek humor</h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/linuxhandbook_meme_september_2.jpg" class="kg-image" alt="" loading="lazy" width="1440" height="1440" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/linuxhandbook_meme_september_2.jpg 600w, https://linuxhandbook.com/content/images/size/w1000/2026/09/linuxhandbook_meme_september_2.jpg 1000w, https://linuxhandbook.com/content/images/2026/09/linuxhandbook_meme_september_2.jpg 1440w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%92%8C-keep-on-loving-linux-handbook">💌 Keep on loving Linux Handbook</h2><p>GitOps course is nearly ready. It should arrive next week. </p><p>Perfect time to <a href="https://linuxhandbook.com/#/portal/signup">become a Pro member</a> and enjoy unlimited access to our <a href="https://linuxhandbook.com/ebooks/">eBooks</a>, <a href="https://linuxhandbook.com/courses/">courses</a> and in-depth tutorials.</p><p><strong>Missed the previous editions?</strong>&nbsp;You can&nbsp;<a href="https://linuxhandbook.com/newsletter/">access the newsletter archives.</a></p><p>You may also <a href="https://linuxhandbook.com/write-for-us/">contribute to Linux Handbook</a> and share your experience and expertise with the community.</p><p>I like reading your messages, so just hit the reply button and share your thoughts 😄</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.11: New Free Course, Named Pipes, Multi-kernel and More]]></title>
                    <description><![CDATA[Enjoy the new course]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-11/</link>
                    <guid isPermaLink="false">6a97f1ccc2467700014999bb</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 19:00:39 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/09/lhb-newsletter-1-.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/09/lhb-newsletter-1-.png" alt="LHB Linux Digest #26.11: New Free Course, Named Pipes, Multi-kernel and More"/> <p>We have a new course, <a href="https://linuxhandbook.com/courses/tmux/">Tmux Fundamentals</a>. As evident from the name itself, the course teaches you the fundamentals of Tmux. </p><p>A terminal multiplexer like Tmux is a lifesaver if you connect to remote servers via SSH. No more session drops because your laptop went in sleep mode or if you forgot to stay connected in the terminal.</p><p>Tmux has a little learning curve, and that's the reason we created this new course. It is available to everyone for free. Enjoy 😄</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://linuxhandbook.com/courses/tmux/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Tmux Fundamentals: Free Course on Terminal Multiplexing</div><div class="kg-bookmark-description">Never lose a terminal session again! Learn tmux sessions, panes, and windows in this free, beginner-friendly course. No signup required.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/Linux-Handbook-New-Logo-fc83b8b6-6673-4a6f-8ee0-4730af602253.png" alt=""><span class="kg-bookmark-author">Linux Handbook</span><span class="kg-bookmark-publisher">Yash Kiran Patil</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/tmux-fundamentals-05e3dc3f-60a9-46ae-a66b-9907076fa22a.png" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="essential-linux-concept-named-pipe-redirection">Essential Linux concept: Named pipe redirection</h2><p>Most linux users are familiar with the concept of <a href="https://linuxhandbook.com/redirection-linux/">redirection</a>. One of the redirections is pipe. The vertical line | in the commands gives Linux an incredible power for combining commands.</p><p>But did you know that there is also <a href="https://linuxhandbook.com/pipe-redirection/">named pipes that exist like a file in the system</a>. Well, everything is file in Linux so that's not surprising. Named pipes can store output in memory buffer. It's an interesting concept that most of us Linux users don't come across every day.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://linuxhandbook.com/pipe-redirection/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Pipe redirection in Linux: Named and Unnamed Pipes</div><div class="kg-bookmark-description">There are two kinds of pipes in Linux: named and unnamed. Here’s a detailed look at pipe redirection.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/Linux-Handbook-New-Logo-428a1b97-5077-4356-bef3-e87d7cd3d71e.png" alt=""><span class="kg-bookmark-author">Linux Handbook</span><span class="kg-bookmark-publisher">Debdut Chakraborty</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/pipe-redirection-1-17911276-322c-487b-9ab7-b8400b276dca.png" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="interested-in-linux-kernel-developments">Interested in Linux kernel developments?</h2><p>Linux Foundation's instructor led training program on <a href="https://training.linuxfoundation.org/training/linux-kernel-internals-and-development/?ref=linuxhandbook.com">Linux Kernel Internals and Developments</a> is for you. The course is designed to provide experienced programmers with a solid understanding of the Linux kernel. </p><p>It is an instructor-led virtual session that will run from 9 to 5 for 4 days. Which means that it is like attending a training class but live on your computer. The next session runs on 28th September.</p><p>If you are working in a company, you can ask your boss or company to pay for this training. Tell them that you are getting a <strong>50% discount with ILTGTRITSFOSS coupon code that saves $1750</strong> on this specialized course.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://training.linuxfoundation.org/instructor-led-training-courses/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Use ILTGTRITSFOSS Coupon to get 50% off</a></div><h2 id="%F0%9F%92%A1quick-terminal-tip"><strong>💡Quick terminal tip</strong></h2><p>In a pipeline like <code>commandA | commandB | commandC</code>, the shell only records the exit code of the final command (commandC), quietly masking crashes or errors produced upstream.</p><p>Bash solves this with the built-in <code>${PIPESTATUS[@]}</code> array, which captures the discrete exit codes of every stage in your pipeline.</p><p>For example, in the below command:</p><pre><code>cat app.log | grep "FATAL" | awk '{print $2}'
echo "${PIPESTATUS[@]}"
</code></pre><p>The <code>${PIPESTATUS[@]}</code> array preserves the discrete exit code of every process in the pipeline, not just the <code>awk</code> command.</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/using-pipestatus.png" class="kg-image" alt="" loading="lazy" width="765" height="578" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/using-pipestatus.png 600w, https://linuxhandbook.com/content/images/2026/09/using-pipestatus.png 765w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%9B%A0%EF%B8%8F-tool-discovery">🛠️ Tool discovery</h2><p>Let's see if you find your next favorite tool.</p><h3 id="listmonk-self-hosted-newsletter-and-mailing-list-manager">Listmonk: Self-hosted, newsletter and mailing list manager</h3><p><a href="https://github.com/knadh/listmonk?ref=linuxhandbook.com">Listmonk</a> is an open-source, AGPL-licensed newsletter and mailing list manager packed into a single Go binary backed by a PostgreSQL database. It features a modern web dashboard with multi-threaded SMTP queues, dynamic templating, SQL-based subscriber segmentation, and an HTTP webhook interface for transactional messaging.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/knadh/listmonk?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - knadh/listmonk: High performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.</div><div class="kg-bookmark-description">High performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app. - knadh/listmonk</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-b6c33d2a-bc65-49cf-b27f-5a54d0decfef.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">knadh</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/8d94bb7b-e76e-4a8e-8944-ebee3c0d0e70-289b118f-21b5-4f6f-b921-68188e8d66e6" alt="" onerror="this.style.display = 'none'"></div></a></figure><h3 id="updo-real-time-uptime-monitoring-tool">Updo: Real-Time Uptime Monitoring Tool</h3><p><a href="https://github.com/Owloops/updo?ref=linuxhandbook.com">Updo</a> is an open-source Go CLI tool that monitors website uptime, response latency breakdowns (DNS, TCP, TTFB), and SSL certificate expiration in real time via an interactive TUI or plain-text mode.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Owloops/updo?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - Owloops/updo: Uptime monitoring CLI tool with alerting and advanced settings</div><div class="kg-bookmark-description">Uptime monitoring CLI tool with alerting and advanced settings - Owloops/updo</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-20467a9d-122f-4027-b31c-ff16fd50015a.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Owloops</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/f3f3ee71978813c484f281b94eb38b123b64537b699bc7498982480d18b41dd6/Owloops/updo" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%93%B0-linux-news-that-matters">📰 Linux news that matters</h2><ul><li><a href="https://www.tomshardware.com/software/linux/linux-kernel-nears-2-000-cves-per-release-as-ai-bug-hunters-scour-40-million-lines-of-code-maintainers-say-they-are-completely-overwhelmed?ref=linuxhandbook.com">The Linux kernel is approaching 2,000 fixed CVEs</a> per release as automated LLM analysis floods maintainers with low-priority bug reports and hallucinated fixes across obscure code paths.</li><li><a href="https://itsfoss.com/news/multikernel-public-release/?ref=linuxhandbook.com">Multikernel Technologies has launched mklinux v7.0-mk2</a>, an open-source kernel fork that allows physical servers to run multiple independent Linux kernels side by side without a hypervisor.</li><li><a href="https://itsfoss.com/news/linux-kernel-repo-ai-overrun/?ref=linuxhandbook.com">Automated AI web scrapers are consuming</a> roughly 20% of git.kernel.org's total compute capacity by requesting individual HTML commit views instead of cloning repositories directly.</li><li><a href="https://itsfoss.com/news/debian-allows-ai-contribution/?ref=linuxhandbook.com">Debian has officially voted to allow generative AI tools</a> for development, maintenance, and documentation, placing full legal and technical accountability directly on the human contributor to review and test all submissions.</li><li><a href="https://www.phoronix.com/news/California-AB-1856-Passes?ref=linuxhandbook.com">California lawmakers have passed Assembly Bill 1856</a>, amending the upcoming Digital Age Assurance Act to formally exempt software and operating systems distributed under permissive licenses allowing copying, modification, and redistribution.</li></ul><h2 id="%F0%9F%98%82-geek-humor">😂 Geek humor</h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/09/lhb_meme-sept-1st-2026.jpg" class="kg-image" alt="" loading="lazy" width="1080" height="1080" srcset="https://linuxhandbook.com/content/images/size/w600/2026/09/lhb_meme-sept-1st-2026.jpg 600w, https://linuxhandbook.com/content/images/size/w1000/2026/09/lhb_meme-sept-1st-2026.jpg 1000w, https://linuxhandbook.com/content/images/2026/09/lhb_meme-sept-1st-2026.jpg 1080w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%92%8C-keep-on-loving-linux-handbook">💌 Keep on loving Linux Handbook</h2><p>GitOps course is nearly ready. It should arrive next week. </p><p>Perfect time to <a href="https://linuxhandbook.com/#/portal/signup">become a Pro member</a> and enjoy unlimited access to our <a href="https://linuxhandbook.com/ebooks/">eBooks</a>, <a href="https://linuxhandbook.com/courses/">courses</a> and in-depth tutorials.</p><p><strong>Missed the previous editions?</strong>&nbsp;You can&nbsp;<a href="https://linuxhandbook.com/newsletter/">access the newsletter archives.</a></p><p>You may also <a href="https://linuxhandbook.com/write-for-us/">contribute to Linux Handbook</a> and share your experience and expertise with the community.</p><p>I like reading your messages, so just hit the reply button and share your thoughts 😄</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 9: Your First Tmux Configuration]]></title>
                    <description><![CDATA[At this point, you can create sessions, organize them with windows, split windows into panes, navigate between them, resize and zoom panes, search terminal history, and build a complete tmux workspace.

So why configure tmux at all? The answer is simple.

After using tmux for a while, you&#39;ll]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/tmux-configuration/</link>
                    <guid isPermaLink="false">6a94f540c246770001499721</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 17:33:27 +0530</pubDate>


                    <content:encoded><![CDATA[<p>At this point, you can create sessions, organize them with windows, split windows into panes, navigate between them, resize and zoom panes, search terminal history, and build a complete tmux workspace.</p><p>So why configure tmux at all? The answer is simple.</p><p>After using tmux for a while, you'll start noticing small things you'd like to change. Maybe you want to use the mouse. Maybe you don't like the default prefix key. Maybe you want a shortcut for something you do repeatedly.</p><p>This is where the <strong>tmux configuration file</strong> comes in.</p><p>Don't worry, we're not going to turn this into an advanced configuration tutorial. The goal of this chapter is to make a few useful changes and, more importantly, help you understand how tmux configuration works.</p><h2 id="what-is-tmuxconf">What Is <code>.tmux.conf</code>?</h2><p>Tmux reads its configuration from a file called:</p><pre><code>~/.tmux.conf</code></pre><p>The <code>~</code> means your home directory. So if your username is <code>yash</code>, the file would normally be:</p><pre><code>/home/yash/.tmux.conf</code></pre><p>This file contains settings and key bindings that tell tmux how you want it to behave.</p><p>Think of it like this:</p><pre><code>Your preferences
      ↓
~/.tmux.conf
      ↓
Tmux
      ↓
Your customized workflow</code></pre><p>Without this file, tmux uses its default settings. With it, you can change those defaults.</p><h2 id="do-you-need-a-configuration-file">Do You Need a Configuration File?</h2><p>Not at all.</p><p>Tmux works perfectly well without one. The default configuration is enough to learn everything we've covered so far. In fact, I recommend using the defaults for a while before customizing anything.</p><p>Why?</p><p>Because you first want to understand <strong>how tmux works</strong>. Once you've actually used it, you'll know what you want to change. So think of configuration as:<strong> Making tmux fit your workflow, not fixing something that is broken.</strong></p><h2 id="create-your-first-tmuxconf">Create Your First <code>.tmux.conf</code></h2><p>Let's create the file. From your normal shell, run:</p><pre><code>touch ~/.tmux.conf</code></pre><p>Now open it in your editor. For example:</p><pre><code>nano ~/.tmux.conf</code></pre><p>You now have an empty tmux configuration file. Don't add ten settings at once. We'll start with something simple.</p><h3 id="enable-mouse-support">Enable Mouse Support</h3><p>One of the easiest beginner-friendly customizations is mouse support.</p><p>Add:</p><pre><code>set -g mouse on</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-9.png" class="kg-image" alt="Enable mouse in config" loading="lazy" width="989" height="730" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-9.png 600w, https://linuxhandbook.com/content/images/2026/08/image-9.png 989w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Enable mouse in config</span></figcaption></figure><p>Save the file. This enables mouse interaction for things such as selecting panes, resizing panes, scrolling and switching between windows.</p><p>This can make tmux feel much more familiar when you're just getting started.</p><h3 id="reload-the-configuration">Reload the Configuration</h3><p>There is one thing you need to understand before testing the change. Editing <code>.tmux.conf</code> does not automatically change an already-running tmux server. You need to tell tmux to reload the file.</p><p>Inside tmux, press:</p><pre><code>Ctrl+b :</code></pre><p>This opens the tmux command prompt. Now type:</p><pre><code>source-file ~/.tmux.conf</code></pre><p>and press Enter. Tmux will read the configuration file again. You can also run the same command from a shell using:</p><pre><code>tmux source-file ~/.tmux.conf</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-42-27_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-42-27.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="989" height="730" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 989 / 730; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-42-27_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:12</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Source config file</span></p></figcaption>
        </figure><p>You might wonder: Why not just close tmux and start it again?</p><p>You can. But reloading the configuration is much more convenient when you're experimenting. Imagine you are changing a key binding.</p><p>You edit the configuration:</p><pre><code>save</code></pre><p>Then reload:</p><pre><code>tmux source-file ~/.tmux.conf</code></pre><p>Test it. If you don't like it, change the file again and reload. You don't need to destroy your existing sessions and windows every time you make a small configuration change.</p><p>This becomes especially useful as your configuration grows.</p><h3 id="customizing-the-prefix-key">Customizing the Prefix Key</h3><p>You've been using the default prefix throughout this course:</p><pre><code>Ctrl+b</code></pre><p>Tmux uses this prefix to distinguish tmux commands from commands intended for your shell. For example:</p><pre><code>Ctrl+b c</code></pre><p>means: Send <code>c</code> to tmux to create a new window. Some users eventually change the prefix because <code>Ctrl+b</code> can feel inconvenient. A popular alternative is:</p><pre><code>Ctrl+a</code></pre><p>You can configure it with:</p><pre><code>set -g prefix C-a
unbind C-b
bind C-a send-prefix</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-10.png" class="kg-image" alt="Set new Prefix Key" loading="lazy" width="989" height="730" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-10.png 600w, https://linuxhandbook.com/content/images/2026/08/image-10.png 989w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Set new Prefix Key</span></figcaption></figure><p>Let's not rush into this one. If you're comfortable with <code>Ctrl+b</code>, <strong>there is no requirement to change it</strong>. In fact, for this beginner course, I recommend keeping the default unless you have a specific reason to change it.</p><h3 id="adding-a-simple-custom-key-binding">Adding a Simple Custom Key Binding</h3><p>Configuration becomes much more interesting when you start creating your own shortcuts. For example, suppose you frequently reload your tmux configuration. Instead of typing:</p><pre><code>Ctrl+b :
source-file ~/.tmux.conf</code></pre><p>you can create a shortcut. Add:</p><pre><code>bind r source-file ~/.tmux.conf</code></pre><p>Now:</p><pre><code>Ctrl+b r</code></pre><p>reloads your configuration. This is a simple example of the power of <code>.tmux.conf</code>:</p><pre><code>Shortcut
   ↓
Custom action
   ↓
Less repetitive typing</code></pre><p>Reload the configuration after adding it:</p><pre><code>tmux source-file ~/.tmux.conf</code></pre><p>Then test:</p><pre><code>Ctrl+b r</code></pre><p>At this point, you might have something like:</p><pre><code>set -g mouse on
bind r source-file ~/.tmux.conf</code></pre><p>That's enough. You do <strong>not</strong> need a huge configuration file to be productive. In fact, starting small makes troubleshooting much easier.</p><p>If something breaks later, you have only a few settings to investigate.</p><h2 id="what-you-have-learned">What You Have Learned</h2><p>You've now gone from starting your first tmux session to customizing how tmux behaves.</p><p>More importantly, you've learned the complete beginner workflow:</p><pre><code>Start tmux
    ↓
Create a session
    ↓
Organize with windows
    ↓
Split into panes
    ↓
Navigate and resize
    ↓
Search terminal history
    ↓
Detach
    ↓
Reconnect
    ↓
Customize</code></pre><p>You no longer need to think of tmux as a collection of shortcuts.</p><p>You can now think of it as a <strong>persistent workspace that you can organize and adapt to your own workflow</strong>.</p><p><strong>You've completed the beginner tmux workflow. From here, the best way to improve is simply to keep using it! See you next time!</strong></p><h2 id=""></h2>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 8: Build a Real Tmux Workflow]]></title>
                    <description><![CDATA[So far, you have learned the individual building blocks of tmux.

You know how to create sessions, organize work with windows, split windows into panes, move between panes, resize them, and use copy mode to work with terminal output.

But knowing these features separately is different from actually using tmux.]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/tmux-real-workflow/</link>
                    <guid isPermaLink="false">6a94f0c4c2467700014996ea</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 17:32:59 +0530</pubDate>


                    <content:encoded><![CDATA[<p>So far, you have learned the individual building blocks of tmux.</p><p>You know how to create sessions, organize work with windows, split windows into panes, move between panes, resize them, and use copy mode to work with terminal output.</p><p>But knowing these features separately is different from actually using tmux. So in this chapter, we're going to put everything together. Instead of learning another set of commands, we're going to build a <strong>real tmux workspace</strong> from scratch.</p><p>Imagine you're working on an application running on a remote Linux server. You need to start the application, watch its logs, run commands, and keep an eye on the system.</p><p>By the end of this chapter, you'll have a workflow you can adapt to your own work.</p><h2 id="the-workflow-were-going-to-build">The Workflow We're Going to Build</h2><p>Let's start by deciding what we need. For this example, we'll use one session called:</p><pre><code>my-api</code></pre><p>Inside that session, we'll have three windows:</p><pre><code>my-api
│
├── app
├── logs
└── system</code></pre><p>The idea is simple:</p><ul><li><strong>app</strong>: run application commands</li><li><strong>logs</strong>: watch application output</li><li><strong>system</strong>: monitor the server and run diagnostics</li></ul><p>We can also split the <code>app</code> window into panes when we need multiple things visible at the same time.</p><p>Our final workspace will look roughly like this:</p><pre><code>Session: my-api

Window 0: app
┌──────────────────────────┬────────────────────┐
│                          │                    │
│      application         │      commands      │
│                          │                    │
└──────────────────────────┴────────────────────┘

Window 1: logs
┌─────────────────────────────────────────────────┐
│                                                 │
│              application logs                   │
│                                                 │
└─────────────────────────────────────────────────┘

Window 2: system
┌──────────────────────────┬────────────────────┐
│                          │                    │
│       monitoring         │     diagnostics    │
│                          │                    │
└──────────────────────────┴────────────────────┘</code></pre><p>Don't worry about building this perfectly on the first attempt. The goal is to understand <strong>how you decide what belongs in a session, window, or pane</strong>.</p><h2 id="step-1-create-the-session">Step 1: Create the Session</h2><p>Start from your normal terminal. Create a named session:</p><pre><code>tmux new -s my-api</code></pre><p>You're now inside the <code>my-api</code> session. This session represents the entire application context. If you're working remotely, you can think of it as:</p><pre><code>Server
  │
  └── my-api session</code></pre><p>Everything we create next will belong to this session.</p><h2 id="step-2-create-the-windows">Step 2: Create the Windows</h2><p>Your first window already exists. Let's use it for the application.</p><p>Rename it:</p><pre><code>Ctrl+b ,</code></pre><p>Enter:</p><pre><code>app</code></pre><p>Now create another window:</p><pre><code>Ctrl+b c</code></pre><p>Rename it:</p><pre><code>Ctrl+b ,</code></pre><p>and call it:</p><pre><code>logs</code></pre><p>Create one more:</p><pre><code>Ctrl+b c</code></pre><p>Rename it:</p><pre><code>Ctrl+b ,</code></pre><p>and enter:</p><pre><code>system</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-17-55-42_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-17-55-42.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1011" height="757" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1011 / 757; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-17-55-42_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:41</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Creating the structure </span></p></figcaption>
        </figure><p>You should now have:</p><pre><code>0:app
1:logs
2:system</code></pre><p>in your tmux status bar.</p><h2 id="step-3-set-up-the-application-window">Step 3: Set Up the Application Window</h2><p>Move back to window 0:</p><pre><code>Ctrl+b 1</code></pre><p>Now let's create two panes. Split the window:</p><pre><code>Ctrl+b %</code></pre><p>You now have two panes side by side. Use one for the application and the other for commands. For example, you might run:</p><pre><code>./start-app.sh</code></pre><p>in one pane. And leave the other available for commands such as:</p><pre><code>git status</code></pre><p>or:</p><pre><code>curl http://localhost:8080/health</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-20-11_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-20-11.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1011" height="757" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1011 / 757; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-20-11_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:19</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Apps window with two panes</span></p></figcaption>
        </figure><p>The exact commands will depend on your project. The important part is the workflow.</p><pre><code>app window

┌────────────────────────┬─────────────────────┐
│                        │                     │
│      Application       │      Commands       │
│                        │                     │
└────────────────────────┴─────────────────────┘</code></pre><p>Now you don't need to keep switching between two terminals just to see your application and run a command.</p><h2 id="step-4-set-up-the-logs-window">Step 4: Set Up the Logs Window</h2><p>Move to the logs window:</p><pre><code>Ctrl+b 2</code></pre><p>Now imagine your application writes to:</p><pre><code>application.log</code></pre><p>You might run:</p><pre><code>tail -f application.log</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-21-31_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-21-31.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1011" height="757" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1011 / 757; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-21-31_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:08</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Logs window of the application</span></p></figcaption>
        </figure><p>The terminal will continuously display new log entries. This window now has one clear purpose:<strong> Watch what's happening inside the application.</strong></p><p>If an error occurs, you can immediately see it without interrupting the application window. For a real project, you might instead use commands such as:</p><pre><code>journalctl -f</code></pre><p>or whatever logging tool your application uses. The exact command isn't the point here. The important idea is that the <strong>window has a dedicated responsibility</strong>.</p><h2 id="step-5-set-up-the-system-window">Step 5: Set Up the System Window</h2><p>Now move to:</p><pre><code>Ctrl+b 3</code></pre><p>This window can be used for system monitoring. Split it:</p><pre><code>Ctrl+b %</code></pre><p>In one pane, you could run:</p><pre><code>top</code></pre><p>and use the other pane for diagnostic commands:</p><pre><code>df -h</code></pre><p>or:</p><pre><code>free -h</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-22-40_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-22-40.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1011" height="757" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1011 / 757; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-22-40_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:15</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">System window of application</span></p></figcaption>
        </figure><p>Now your workspace has three distinct areas:</p><pre><code>my-api
│
├── app
│    ├── application
│    └── commands
│
├── logs
│    └── application logs
│
└── system
     ├── monitoring
     └── diagnostics</code></pre><p>This is a much more useful setup than simply opening six unrelated terminal windows.</p><h2 id="step-6-move-around-the-workspace">Step 6: Move Around the Workspace</h2><p>Now practice navigating. Jump directly to your windows:</p><pre><code>Ctrl+b 1
Ctrl+b 2
Ctrl+b 3</code></pre><p>Move between panes:</p><pre><code>Ctrl+b ←
Ctrl+b →
Ctrl+b ↑
Ctrl+b ↓</code></pre><p>You can now move from:</p><pre><code>application
   ↓
logs
   ↓
monitoring</code></pre><p>without opening another terminal. This is where the session → window → pane model starts becoming natural.</p><h2 id="step-7-deal-with-a-large-log-output">Step 7: Deal With a Large Log Output</h2><p>Now imagine something goes wrong. Your logs contain a large amount of output and you need to find an error. Move to the logs window:</p><pre><code>Ctrl+b 1</code></pre><p>Enter copy mode:</p><pre><code>Ctrl+b [</code></pre><p>Search for:</p><pre><code>/</code></pre><p>Then enter something like:</p><pre><code>ERROR</code></pre><p>You can now inspect the matching output. This is where the things you learned in Chapter 7 become part of the workflow rather than isolated commands.</p><p>You are using:</p><pre><code>Window → Logs
      ↓
Copy Mode
      ↓
Search
      ↓
Inspect error</code></pre><h2 id="step-8-what-if-you-need-to-leave-without-disconnecting">Step 8: What If You Need to Leave Without Disconnecting?</h2><p>You don't always need to wait for your SSH connection to disappear. You can safely leave your tmux workspace whenever you want. Press:</p><pre><code>Ctrl+b d</code></pre><p>The session continues running. Later:</p><pre><code>tmux attach -t my-api</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-35-53_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-35-53.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1011" height="757" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1011 / 757; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-31-18-35-53_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:08</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Detach the current session and reattach</span></p></figcaption>
        </figure><p>You're back. This is the workflow you will eventually use almost automatically when working on remote servers:</p><pre><code>SSH
 ↓
Attach/Create tmux
 ↓
Work
 ↓
Detach
 ↓
Leave server
 ↓
Return later
 ↓
Attach
 ↓
Continue</code></pre><p>You know how to create the workspace, organize it, work inside it, leave it running, and come back later. That's already enough to make tmux useful in everyday work.</p><p>But there is one final step. Once you've used tmux for a while, you'll probably notice small things you'd like to change.</p><p>Maybe you want mouse support. Maybe you prefer a different prefix key. Maybe you want a custom shortcut. That's where configuration comes in.</p><p>In the <strong>final chapter</strong>, we'll create your <strong>first <code>.tmux.conf</code></strong> and make a few practical customizations without turning tmux into a complicated configuration project.</p><h2 id=""></h2>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 7: Copy Mode - Scroll, Search and Copy Terminal Output]]></title>
                    <description><![CDATA[So far, you&#39;ve learned how to organize your tmux workspace using sessions, windows, and panes. But there&#39;s one problem you&#39;ll run into very quickly.

Your terminal can produce a lot of output.

Maybe you&#39;re checking application logs. Maybe a command printed hundreds]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/tmux-copy-mode-2/</link>
                    <guid isPermaLink="false">6a93eadbc246770001499597</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 16:39:43 +0530</pubDate>


                    <content:encoded><![CDATA[<p>So far, you've learned how to organize your tmux workspace using sessions, windows, and panes. But there's one problem you'll run into very quickly.</p><p>Your terminal can produce <strong>a lot of output</strong>.</p><p>Maybe you're checking application logs. Maybe a command printed hundreds of lines. Maybe an error happened somewhere near the top of the output.</p><p>You try to scroll up and suddenly you're not looking at the part you need.</p><p>This is where <strong>tmux copy mode</strong> becomes useful.</p><p>Copy mode lets you move through the history of a tmux pane, search through that output, select text, and copy it.</p><p>In this chapter, we'll learn how to use it without getting into complicated clipboard configuration. By the end, you'll be able to inspect large amounts of terminal output and grab the information you need.</p><h2 id="why-do-we-need-copy-mode">Why Do We Need Copy Mode?</h2><p>Let's start with a simple example.</p><p>Run:</p><pre><code>seq 1 100</code></pre><p>You'll get:</p><pre><code>1
2
3
4
...
97
98
99
100</code></pre><p>Now imagine this wasn't 100 lines but several thousand lines of application logs.</p><p>You might want to go back and find something that appeared earlier.</p><p>That's what copy mode is designed for.</p><p>Instead of treating your terminal as a screen that only shows the latest output, tmux gives you a way to scroll through the <strong>scrollback history</strong> of the pane.</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-27-53_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-27-53.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="995" height="725" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 995 / 725; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-27-53_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:14</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Scrollback history in copy mode</span></p></figcaption>
        </figure><h2 id="move-through-terminal-history">Move Through Terminal History</h2><p>Once you're in copy mode, you can move through the output.</p><p>Use the arrow keys to move around:</p><pre><code>↑
↓
←
→</code></pre><p>You can also use the Page Up and Page Down keys to move through larger sections of output.</p><p>For example:</p><pre><code>Page Up   → Move back through output
Page Down → Move forward</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-32-23_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-32-23.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="995" height="725" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 995 / 725; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-32-23_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:22</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Moving through terminal history</span></p></figcaption>
        </figure><p>You can also use the mouse wheel in environments where mouse support is enabled, but for now I want you to understand the actual tmux copy mode workflow.</p><p>This is particularly useful with logs.</p><h2 id="search-through-output">Search Through Output</h2><p>Scrolling is useful when you know roughly where the information is. But what if your log contains thousands of lines and you're looking specifically for:</p><pre><code>Hit</code></pre><p>You don't want to scroll through everything manually. You can search. While inside copy mode, press:</p><pre><code>/ </code></pre><p>This will <strong>Scroll Down Search.</strong></p><pre><code class="language-bash">?</code></pre><p>This will help to <strong>Scroll Up Search. </strong>Then try to search for the keyword you are looking for in the search history.</p><pre><code>Hit</code></pre><p>Press Enter. Tmux will search through the available history and take you to a matching result.</p><p>You can move to the next match using:</p><pre><code>n</code></pre><p>and search in the opposite direction with:</p><pre><code>N</code></pre><p>The exact search behavior can depend on the mode and configuration you're using, but the basic workflow is:</p><pre><code>Ctrl+b [
   ↓
/
   ↓
Type search term
   ↓
Enter
   ↓
Inspect matching output</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-43-48_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-43-48.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="995" height="725" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 995 / 725; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-43-48_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:16</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Searching in the tmux copy mode </span></p></figcaption>
        </figure><p>If you are not able to perform these set of commands you can set the following in the last of your tmux config file:</p><pre><code class="language-bash">set -g mode-keys vi
set -g search-default-case-insensitive on</code></pre><h2 id="select-and-copy-text">Select and Copy Text</h2><p>Now let's do the second important job of copy mode. Suppose you've found an error like this:</p><pre><code> An error occurred during the signature verification.</code></pre><p>You may want to copy that line and paste it somewhere else, likely your AI buddy. Inside copy mode, you can enter selection mode by pressing:</p><pre><code>Space</code></pre><p>Now move the cursor to select the text you need.</p><p>Depending on your tmux configuration and version, you can navigate through the text using the keyboard and extend the selection.</p><p>Once you've selected the text, press:</p><pre><code>Enter</code></pre><p>to copy the selected text into tmux's paste buffer.</p><p>The important workflow is:</p><pre><code>Enter copy mode
      ↓
Find the text
      ↓
Start selection
      ↓
Select text
      ↓
Copy</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-53-51_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-53-51.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="995" height="725" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 995 / 725; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-53-51_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:23</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Select and copy text form output</span></p></figcaption>
        </figure><h2 id="pasting-what-you-copied">Pasting What You Copied</h2><p>Once you've copied something, tmux stores it in its <strong>paste buffer</strong>.</p><p>To paste the most recently copied text, use:</p><pre><code>Ctrl+b ]</code></pre><p>For example:</p><pre><code>Ctrl+b [</code></pre><p>Find and copy:</p><pre><code>ERROR: connection refused</code></pre><p>Then return to your shell and press:</p><pre><code>Ctrl+b ]</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-56-41_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-56-41.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="995" height="725" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 995 / 725; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-17-56-41_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:06</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Pasting the recently copied output</span></p></figcaption>
        </figure><p>The copied text will be pasted into the current pane. This is different from your operating system's normal clipboard.</p><p>Tmux maintains its own paste buffers, which means it can keep text copied from its terminal environment even when you're working inside a remote session.</p><h2 id="exiting-copy-mode">Exiting Copy Mode</h2><p>Once you're finished looking through the history, press:</p><pre><code>q</code></pre><p>This exits copy mode and returns you to the normal tmux pane.</p><p>So the complete basic workflow becomes:</p><pre><code>Ctrl+b [
   ↓
Copy mode
   ↓
Scroll / Search
   ↓
Select / Copy
   ↓
Ctrl+b ]
   ↓
Paste
   ↓
q
   ↓
Back to normal shell</code></pre><p>You don't have to think about all of these operations every time.</p><p>Most of the time, you'll use copy mode because you need to <strong>inspect something that has already scrolled away</strong>.</p><h2 id="what-about-mouse-support">What About Mouse Support?</h2><p>You may have noticed that using the keyboard for copy mode can feel different from how you normally select text in a terminal.</p><p>Tmux also supports mouse interaction when mouse mode is enabled. For example, with mouse support configured, you can use the mouse to:</p><ul><li>scroll through panes</li><li>select text</li><li>interact with panes and windows</li></ul><p>We'll cover mouse support more properly when we introduce tmux configuration in the final chapter. For now, learn the keyboard-based copy mode workflow first.</p><p>That way, you won't depend on a particular terminal emulator or mouse setup.</p><p>In the next chapter, we'll build a <strong>complete real-world tmux workflow</strong> using sessions, windows, panes, persistence, and copy mode.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 6: Panes - Split, Navigate, Resize and Zoom]]></title>
                    <description><![CDATA[In the previous chapter, you learned how to use windows to organize different tasks inside a tmux session.

Now let&#39;s make those windows more useful.

Imagine you are working on a server and want to watch your application logs while running commands at the same time. Opening another]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/tmux-panes/</link>
                    <guid isPermaLink="false">6a93b563c246770001499516</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 16:38:39 +0530</pubDate>


                    <content:encoded><![CDATA[<p>In the previous chapter, you learned how to use windows to organize different tasks inside a tmux session.</p><p>Now let's make those windows more useful.</p><p>Imagine you are working on a server and want to watch your application logs while running commands at the same time. Opening another window would work, but you'd have to keep switching back and forth.</p><p>What if you could see both at once? That's exactly what <strong>panes</strong> are for.</p><p>A pane is simply a terminal area inside a tmux window. You can split one window into multiple panes and work in each of them independently.</p><p>By the end of this chapter, you'll be able to create splits, move between panes, resize them, and temporarily make one pane fill the entire screen.</p><h2 id="what-is-a-pane">What Is a Pane?</h2><p>Let's start with the hierarchy you've already learned:</p><pre><code>Session
   │
   └── Window
          │
          ├── Pane
          └── Pane</code></pre><p>A window can contain one pane or several panes. For example, a single window normally looks like:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-7.png" class="kg-image" alt="" loading="lazy" width="1069" height="754" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-7.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/08/image-7.png 1000w, https://linuxhandbook.com/content/images/2026/08/image-7.png 1069w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">single window terminal</span></figcaption></figure><p>After splitting it vertically:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-8.png" class="kg-image" alt="" loading="lazy" width="1069" height="754" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-8.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/08/image-8.png 1000w, https://linuxhandbook.com/content/images/2026/08/image-8.png 1069w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">vertically split window</span></figcaption></figure><p>Now both panes are terminals, and you can run a different command in each one. This is one of the most useful everyday features of tmux.</p><h2 id="create-your-first-pane-split">Create Your First Pane Split</h2><p>Let's try it. Start inside a tmux session and press:</p><pre><code>Ctrl+b %</code></pre><p>The <code>%</code> tells tmux to split the current window vertically. You'll now have two panes side by side. Try running a command in one pane:</p><pre><code>ls</code></pre><p>Then move to the other pane and run:</p><pre><code>pwd</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-28-34_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-28-34.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1069" height="754" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1069 / 754; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-28-34_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:13</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">split panes and perform indivisual commands</span></p></figcaption>
        </figure><p>You now have two independent shells visible at the same time.</p><h2 id="split-horizontally">Split Horizontally</h2><p>You can also split the window from top to bottom.</p><p>Press:</p><pre><code>Ctrl+b "</code></pre><p>This creates a horizontal split.</p><p>For example:</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-30-28_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-30-28.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1069" height="754" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1069 / 754; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-30-28_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:09</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">split pane horizantally</span></p></figcaption>
        </figure><p>The two split commands are easy to confuse at first:</p><pre><code>Ctrl+b %   → vertical split
Ctrl+b "   → horizontal split</code></pre><p>Don't worry if these shortcuts don't feel intuitive yet. After using them a few times, they become much easier to remember.</p><h2 id="move-between-panes">Move Between Panes</h2><p>Creating panes is only half the job. Now you need to move between them.</p><p>Use:</p><pre><code>Ctrl+b ↑
Ctrl+b ↓
Ctrl+b ←
Ctrl+b →</code></pre><p>Press the prefix first, release it, and then press the arrow key.</p><p>So, for example:</p><pre><code>Ctrl+b →</code></pre><p>moves you to the pane on the right.</p><p>Similarly:</p><pre><code>Ctrl+b ↓</code></pre><p>moves you to the pane below.</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-33-08_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-33-08.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1103" height="794" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1103 / 794; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-33-08_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:13</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Moving between panes</span></p></figcaption>
        </figure><p>This is one of those shortcuts that becomes second nature fairly quickly.</p><h2 id="resize-a-pane">Resize a Pane</h2><p>By default, tmux gives your panes roughly equal space. But sometimes you need one pane to be larger.</p><p>For example, your logs might need most of the screen while your command pane only needs a small section.</p><p>You can resize panes using the prefix and arrow keys:</p><pre><code>Ctrl+b Ctrl+↑
Ctrl+b Ctrl+↓
Ctrl+b Ctrl+←
Ctrl+b Ctrl+→</code></pre><p>Notice that this is slightly different from navigation.</p><p>For navigation:</p><pre><code>Ctrl+b ↑</code></pre><p>For resizing:</p><pre><code>Ctrl+b Ctrl+↑</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-36-45_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-36-45.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1103" height="794" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1103 / 794; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-36-45_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:12</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Resizing panes </span></p></figcaption>
        </figure><p>You press the prefix, then hold <code>Ctrl</code> while pressing the arrow key. You can repeat the command to make the pane larger or smaller.</p><h2 id="why-would-you-resize-panes">Why Would You Resize Panes?</h2><p>Let's use a practical example.</p><p>Suppose you're following a log:</p><pre><code>tail -f application.log</code></pre><p>You may want that pane to be large because you're constantly reading new output. Your second pane might only be used for occasional commands.</p><p>So instead of:</p><pre><code>┌────────────────────┬────────────────────┐
│                    │                    │
│       logs         │      shell         │
│                    │                    │
└────────────────────┴────────────────────┘</code></pre><p>you could resize it to:</p><pre><code>┌──────────────────────────────┬───────────┐
│                              │           │
│            logs              │   shell   │
│                              │           │
│                              │           │
└──────────────────────────────┴───────────┘</code></pre><p>This is one of the reasons panes are more useful than simply opening multiple terminal windows. You can adjust the layout to match the task you're doing.</p><h2 id="zoom-a-pane">Zoom a Pane</h2><p>Sometimes even a resized pane isn't enough. Maybe you're working inside a small pane and suddenly need the whole screen.</p><p>You don't need to destroy your layout. You can <strong>zoom the current pane</strong>.</p><p>Press:</p><pre><code>Ctrl+b z</code></pre><p>The current pane expands to fill the entire tmux window. The other panes are still there; they're simply hidden temporarily.</p><p>Press:</p><pre><code>Ctrl+b z</code></pre><p>again to return to the previous layout. For more clarity, you can see below.</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-43-30_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-43-30.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1103" height="794" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1103 / 794; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-43-30_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:07</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Zooming into one pane and return</span></p></figcaption>
        </figure><p>This is particularly useful when you have a complicated layout but need to focus on one task for a moment.</p><h2 id="close-a-pane">Close a Pane</h2><p>When you're finished with a pane, you can simply type:</p><pre><code>exit</code></pre><p>That closes the shell running inside that pane.</p><p>You can also use:</p><pre><code>Ctrl+b x</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-45-02_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-45-02.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1103" height="794" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1103 / 794; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-30-13-45-02_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:10</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Closing a pane</span></p></figcaption>
        </figure><p>Tmux will ask you to confirm before closing the pane. Remember that closing a pane also closes the processes running inside it.</p><p>So if you have a server running there, closing the pane can stop that server.</p><h2 id="panes-in-a-real-workflow">Panes in a Real Workflow</h2><p>Now think about the kind of workflow you might actually use.</p><p>For a web application, you could have:</p><pre><code>┌──────────────────────────────┬─────────────────┐
│                              │                 │
│        Application           │      Logs       │
│                              │                 │
├──────────────────────────────┴─────────────────┤
│               Monitoring                       │
│          top / htop / other tool               │
└────────────────────────────────────────────────┘</code></pre><p>For a development workflow:</p><pre><code>┌───────────────────────────┬─────────────────────┐
│                           │                     │
│         Editor            │      Terminal       │
│                           │                     │
├───────────────────────────┴─────────────────────┤
│                 Test output                     │
└─────────────────────────────────────────────────┘</code></pre><p>And for remote server troubleshooting:</p><pre><code>┌──────────────────────────┬──────────────────────┐
│                          │                      │
│          Logs            │       Commands       │
│                          │                      │
├──────────────────────────┴──────────────────────┤
│               System monitoring                 │
└─────────────────────────────────────────────────┘</code></pre><p>The important idea isn't to memorize one perfect layout.</p><p>It's to understand that <strong>you can build the layout around the work you're doing</strong>.</p><p>In the next chapter, we'll learn how to move through terminal history, search output, select text, and copy information from a tmux pane.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 5: Windows - Organize Your Work Inside a Session]]></title>
                    <description><![CDATA[In the previous chapter, you learned how to create, name, detach, and reattach tmux sessions.

Now you already have the main workspace. But imagine you&#39;re working on a project and need to do several things at once.

You want one terminal for your application, another for logs, another]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/tmux-windows/</link>
                    <guid isPermaLink="false">6a8fa72cc24677000149916e</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 16:37:22 +0530</pubDate>


                    <content:encoded><![CDATA[<p>In the previous chapter, you learned how to create, name, detach, and reattach tmux sessions.</p><p>Now you already have the main workspace. But imagine you're working on a project and need to do several things at once.</p><p>You want one terminal for your application, another for logs, another for Git commands, and another for testing. You could open four separate terminal windows.</p><p>Or, you can keep everything inside the same tmux session. That's where <strong>windows</strong> come in.</p><p>A tmux window is essentially a terminal tab inside a session. Once you understand sessions, windows are the next layer of organization.</p><h2 id="what-is-a-tmux-window">What Is a Tmux Window?</h2><p>Remember the hierarchy from Chapter 1:</p><pre><code>Session
   │
   ├── Window
   ├── Window
   └── Window</code></pre><p>A session represents the overall context. Windows represent the different tasks inside that context. For example, imagine you're working on an application called <code>my-api</code>.</p><p>You could have: my-api: (editor, server, logs, git), which will look like below in tmux:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-6.png" class="kg-image" alt="" loading="lazy" width="1258" height="601" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-6.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/08/image-6.png 1000w, https://linuxhandbook.com/content/images/2026/08/image-6.png 1258w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">multiple windows in a session</span></figcaption></figure><p>All four windows belong to the same <code>my-api</code> session. This is useful because everything related to the project stays together.</p><h2 id="create-a-new-window">Create a New Window</h2><p>Let's create one. Inside your tmux session, press:</p><pre><code>Ctrl+b c</code></pre><p>Remember the prefix sequence:</p><ol><li>Press <code>Ctrl+b</code></li><li>Release the keys</li><li>Press <code>c</code></li></ol><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-38-42_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-38-42.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1126" height="723" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1126 / 723; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-38-42_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:18</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">new window creation in tmux</span></p></figcaption>
        </figure><p>A new window appears. You are now working inside that new window. You can run any normal commands here.</p><p>The important part is that you haven't created a new session. You've simply created another workspace <strong>inside the same session</strong>.</p><h2 id="switch-between-windows">Switch Between Windows</h2><p>Once you have multiple windows, you need a way to move between them.</p><p>Use:</p><pre><code>Ctrl+b n</code></pre><p>This moves to the <strong>next window</strong>.</p><p>To move to the previous window:</p><pre><code>Ctrl+b p</code></pre><p>You can also jump directly to a window by its number.</p><p>For example:</p><pre><code>Ctrl+b 2</code></pre><p>takes you to window <code>2</code>.</p><p>And:</p><pre><code>Ctrl+b 1</code></pre><p>takes you to window <code>1</code>.</p><p>You can see below how the star pointer changes when we change windows:</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-46-10_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-46-10.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1126" height="723" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1126 / 723; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-46-10_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:13</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Switching between windows in tmux</span></p></figcaption>
        </figure><p>This is one reason the numbers shown in the tmux status bar are useful.</p><h2 id="rename-a-window">Rename a Window</h2><p>The default window name is usually based on the process running inside it.</p><p>For example, you might see:</p><pre><code>0:bash</code></pre><p>That's not very descriptive.</p><p>Let's give the window a useful name.</p><p>Press:</p><pre><code>Ctrl+b ,</code></pre><p>Tmux will ask you for a new name.</p><p>For example:</p><pre><code>editor</code></pre><p>Press Enter.</p><p>Your status bar should now show something similar to:</p><pre><code>1:editor</code></pre><p>Now you immediately know what that window is for.</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-49-05_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-49-05.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1126" height="723" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1126 / 723; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-49-05_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:13</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">renaming a window in tmux</span></p></figcaption>
        </figure><p>Good names make a big difference once you have several windows.</p><h2 id="close-a-window">Close a Window</h2><p>When you're finished with a window, you can close it by exiting the shell running inside it:</p><pre><code>exit</code></pre><p>If that is the only shell in the window, the window closes.</p><p>You can also use the tmux command:</p><pre><code>Ctrl+b &amp;</code></pre><p>Tmux will ask you to confirm before killing the current window.</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-52-16_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-52-16.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1126" height="723" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1126 / 723; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-27-08-52-16_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:16</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Closing a window in tmux</span></p></figcaption>
        </figure><p>Be careful with this command because closing a window also closes the processes running inside it.</p><p>For example, if a server is running in that window, closing the window will terminate that server process.</p><p>So think of it this way:</p><pre><code>Create window → Start work
Close window  → Finish that workspace</code></pre><p>All of these windows are still part of the <strong>same session</strong>. That means you can detach from the session and later reattach your windows will still be there. This is the combination that makes tmux powerful.</p><h2 id="practice">Practice</h2><div class="kg-card kg-callout-card kg-callout-card-accent"><div class="kg-callout-emoji">✏️</div><div class="kg-callout-text"><i><b><strong class="italic" style="white-space: pre-wrap;">Try This:</strong></b></i><br>Spend a few minutes switching between your windows without looking at the shortcut table. The goal isn't perfect memorization yet; it's becoming comfortable moving around your tmux workspace.</div></div><p>Create a session called:</p><pre><code>tmux new -s practice</code></pre><p>Create three windows and name them:</p><pre><code>commands
logs
monitoring</code></pre><p>Practice moving between them. Then detach:</p><pre><code>Ctrl+b d</code></pre><p>and reattach:</p><pre><code>tmux attach -t practice</code></pre><p>Your windows should still be exactly where you left them. You now know how to organize different tasks using windows. But sometimes switching between windows isn't enough.</p><p>What if you want to see your application logs <strong>and</strong> run commands at the same time? Instead of creating another window, you can split the current window into multiple terminal areas.</p><p>Those are called <strong>panes</strong>. In the next chapter, we'll create, navigate, resize, and zoom panes!</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 4: Sessions - Create, Name, Detach and Reattach]]></title>
                    <description><![CDATA[So far, you have installed tmux, started your first session, and learned how the prefix key works.

Now we get to the feature that makes tmux genuinely useful. Sessions. A tmux session is a workspace that can keep running even after you leave it. This is what allows you to]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/tmux-sessions/</link>
                    <guid isPermaLink="false">6a8e5718c246770001498fd7</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 16:33:15 +0530</pubDate>


                    <content:encoded><![CDATA[<p>So far, you have installed tmux, started your first session, and learned how the prefix key works.</p><p>Now we get to the feature that makes tmux genuinely useful. <strong>Sessions. </strong>A tmux session is a workspace that can keep running even after you leave it. This is what allows you to disconnect from a server and come back later without rebuilding everything from scratch.</p><p>Let's see how that works.</p><h2 id="what-is-a-tmux-session">What Is a Tmux Session?</h2><p>Whenever you run:</p><pre><code class="language-bash">tmux</code></pre><p>tmux creates a session for you. You can think of a session as a container for your terminal work.</p><p>For example:</p><pre><code class="language-bash">Session: my-project 
          │ 
          ├── Window 0 
          ├── Window 1 
          └── Window 2</code></pre><p>Later, those windows can contain multiple panes, but for now, focus on the session itself.A session usually represents one main context.</p><p>For example:</p><pre><code>my-project
production
debugging</code></pre><p>You might use separate sessions for separate projects, servers, or tasks.</p><h2 id="create-a-named-session">Create a Named Session</h2><p>If you know what the session is for, it's much better to give it a name. Use:</p><pre><code>tmux new -s my-project</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-37-44_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-37-44.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1104" height="728" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1104 / 728; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-37-44_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:13</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Create a named session → my-project</span></p></figcaption>
        </figure><p>Here:<code>new</code> tells tmux to create a new session. <code>-s</code> means we are giving the session a name.<code>my-project</code> is the session name. </p><p>Now you have a session called <code>my-project</code>. Naming sessions becomes especially useful when you have more than one. Instead of wondering which session is which, the name tells you immediately.</p><h2 id="see-your-sessions">See Your Sessions</h2><p>Now let's say you have created a few sessions. How do you find out which ones are currently running?</p><p>Run:</p><pre><code>tmux ls</code></pre><p>or:</p><pre><code>tmux list-sessions</code></pre><p>You'll see something similar to:</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-41-58_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-41-58.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1104" height="728" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1104 / 728; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-41-58_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:13</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><p>The exact output will be different on your system. The important part is that tmux is showing you the sessions that currently exist.</p><p>This becomes one of the commands you'll use often when working with multiple sessions.</p><h2 id="detach-without-stopping-your-work">Detach Without Stopping Your Work</h2><p>Now let's try the most important part. Suppose you're inside your <code>my-project</code> session and a command is running.</p><p>You don't want to close the session. You simply want to leave it for now. This is where <strong>detach</strong> comes in.</p><p>Press:</p><pre><code>Ctrl+b d</code></pre><p>Remember how the prefix works:  Press <code>Ctrl+b,</code> Release both keys, Press <code>d</code>.</p><p>You should see something like:</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-47-54_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-47-54.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1104" height="728" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1104 / 728; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-47-54_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:04</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Detached session is still running</span></p></figcaption>
        </figure><p>You are now back in your normal terminal. But here's the important part:<strong> The tmux session is still running.</strong> You have left the session without shutting it down.</p><div class="kg-card kg-callout-card kg-callout-card-accent"><div class="kg-callout-emoji">💡</div><div class="kg-callout-text">This distinction is one of the most important in tmux:<br>Detach → Leave session running <br>Exit → Close the shell/session</div></div><h2 id="reattach-to-your-session">Reattach to Your Session</h2><p>Now let's get back into the session. First, list your sessions:</p><pre><code>tmux ls</code></pre><p>Then attach to <code>my-project</code>:</p><pre><code>tmux attach -t my-project</code></pre><p>You can also use the shorter form:</p><pre><code>tmux a -t my-project</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-52-17_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-52-17.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1104" height="728" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1104 / 728; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-52-17_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:13</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Reattaching the session in tmux</span></p></figcaption>
        </figure><p>You're back. Your windows are still there. Your windows are still there. Your panes are still there and any process that continued running is still there.</p><h2 id="rename-a-session">Rename a Session</h2><p>Sometimes you create a session with a temporary name and later realize you want something clearer.</p><p>You can rename the current session using:</p><pre><code>Ctrl+b $</code></pre><p>Enter the new name and press Enter.</p><p>You can also rename a session from the command line:</p><pre><code>tmux rename-session -t my-project api-server</code></pre><p>Now the session is called:</p><pre><code>api-server</code></pre><p>It will look similar like this:</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-57-19_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-57-19.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1104" height="728" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1104 / 728; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-57-19_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:17</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Renaming a session</span></p></figcaption>
        </figure><h2 id="kill-a-session">Kill a Session</h2><p>When you are completely finished with a session, you can remove it.</p><p>From outside tmux:</p><pre><code>tmux kill-session -t api-server</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-59-25_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-59-25.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1104" height="728" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1104 / 728; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-26-08-59-25_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:13</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Kill a detached session</span></p></figcaption>
        </figure><p>Or, while inside the session, you can simply exit all shells in that session. Be careful here.<strong> Killing a session closes it and terminates the processes running inside it.</strong></p><p>Now you can now manage the basic lifecycle of a tmux session: Create, Name, Use, Detach, Reattach, Rename / Kill a session.</p><p>But a session alone isn't enough for a useful workflow.</p><p>Soon you'll want one place for logs, another for your editor, another for commands, and perhaps another for monitoring.</p><p>That's where <strong>windows</strong> come in. In the next chapter, we'll learn how to organize multiple tasks inside the same tmux session.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 3: The Tmux Prefix Key &amp; Essential Shortcuts]]></title>
                    <description><![CDATA[In the previous chapter, you started tmux and saw that it still feels like a normal terminal. You can run commands, work with files, and use your shell just as you normally would.

Now you need a way to tell tmux: &quot;I want you to do something, not my]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/tmux-essential-shortcuts/</link>
                    <guid isPermaLink="false">6a8da16dc246770001498ed7</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 16:23:46 +0530</pubDate>


                    <content:encoded><![CDATA[<p>In the previous chapter, you started tmux and saw that it still feels like a normal terminal. You can run commands, work with files, and use your shell just as you normally would.</p><p>Now you need a way to tell tmux: "I want you to do something, not my shell." That is what the <strong>prefix key</strong> does.</p><p>Once you understand this one idea, tmux shortcuts stop feeling like a collection of random key combinations. Almost every tmux action follows the same pattern: <strong>press the prefix, then choose the action you want</strong>.</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-25-20-05-12_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-25-20-05-12.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1104" height="711" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1104 / 711; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-25-20-05-12_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:11</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Prefix key with different actions</span></p></figcaption>
        </figure><h2 id="what-is-the-tmux-prefix">What Is the Tmux Prefix?</h2><p>By default, tmux uses: <code>Ctrl+b</code> as its <strong>prefix key</strong>.</p><p>The prefix is like a signal to tmux: Pay attention. The next key I press is a command for you. </p><p>For example, to create a new window, you use: <code>Ctrl+b</code> then <code>c</code> The important part is how you press it. You press: <code>Ctrl+b</code> release both keys, and then press: <code>c</code> So don't think of this as one large keyboard combination.</p><p>That two-step pattern is the foundation for the rest of tmux.</p><h2 id="why-does-tmux-need-a-prefix">Why Does Tmux Need a Prefix?</h2><p>You might be wondering why tmux cannot simply use keys such as <code>c</code>, <code>n</code>, or <code>z</code> directly. The reason is that those keys already belong to your shell and the programs running inside it.</p><p>Imagine you are typing:</p><pre><code>cd projects</code></pre><p>You expect your shell to receive those characters.</p><p>Tmux cannot treat every <code>c</code> you type as: "Create a new window." That would make normal terminal work impossible. The prefix gives tmux a clean boundary between <strong>normal keyboard input</strong> and <strong>tmux commands</strong>.</p><p>Without the prefix:</p><pre><code>Your keyboard
     ↓
   Shell</code></pre><p>With the prefix:</p><pre><code>Your keyboard
     ↓
   Ctrl+b
     ↓
   Tmux
     ↓
 Action key</code></pre><p>So when you press <code>Ctrl+b</code> tmux knows that the next key has a special meaning. That is why you can continue typing normal Linux commands without tmux constantly getting in the way.</p><h2 id="learn-the-shortcut-pattern">Learn the Shortcut Pattern</h2><p>The easiest way to learn tmux is not to memorize every shortcut separately.</p><p>Learn the pattern first:</p><pre><code>Ctrl+b then &lt;key&gt;</code></pre><p>Then learn what the key represents.</p><p>For example:</p><pre><code>Ctrl+b then c</code></pre><p>means: <em>Create a new window.</em></p><p>And:</p><pre><code>Ctrl+b then d</code></pre><p>means: <em>Detach from the current session.</em></p><p>The prefix stays the same. Only the action key changes.</p><p>This is what makes tmux much easier to learn than it initially appears. You are not learning a completely different interface for every feature. You are learning one command pattern and gradually adding actions to it.</p><h2 id="the-essential-shortcuts">The Essential Shortcuts</h2><p>Let's start with the shortcuts you will use throughout this course.</p><table>
<thead>
<tr>
<th>Shortcut</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Ctrl+b</code> then <code>c</code></td>
<td>Create a new window</td>
</tr>
<tr>
<td><code>Ctrl+b</code> then <code>n</code></td>
<td>Move to the next window</td>
</tr>
<tr>
<td><code>Ctrl+b</code> then <code>p</code></td>
<td>Move to the previous window</td>
</tr>
<tr>
<td><code>Ctrl+b</code> then <code>,</code></td>
<td>Rename the current window</td>
</tr>
<tr>
<td><code>Ctrl+b</code> then <code>%</code></td>
<td>Split the window vertically</td>
</tr>
<tr>
<td><code>Ctrl+b</code> then <code>"</code></td>
<td>Split the window horizontally</td>
</tr>
<tr>
<td><code>Ctrl+b</code> then <code>z</code></td>
<td>Zoom the current pane</td>
</tr>
<tr>
<td><code>Ctrl+b</code> then <code>d</code></td>
<td>Detach from tmux</td>
</tr>
</tbody>
</table>
<p>You do <strong>not</strong> need to memorize all of these immediately. Instead, understand what problem each shortcut solves. </p><p>You don't have to memorize every tmux binding because tmux can show you its key bindings.</p><p>Inside tmux, press:</p><pre><code>Ctrl+b then ?</code></pre><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-25-21-23-16_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-25-21-23-16.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="1104" height="711" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 1104 / 711; background: transparent url('https://linuxhandbook.com/content/media/2026/08/Screencast-from-2026-08-25-21-23-16_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:07</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">tmux available key bindings</span></p></figcaption>
        </figure><p>Tmux will display a list of available key bindings. That makes learning much less stressful.</p><p>If these shortcuts make sense, you're ready for the next step. You now know <strong>how to communicate with tmux</strong>. </p><p>In the next chapter, we'll use these shortcuts to work with <strong>sessions,</strong> creating named workspaces, detaching from them, finding them again, and reattaching later without losing your work.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 2: Get Tmux Running]]></title>
                    <description><![CDATA[In the previous chapter, we looked at the problem tmux solves and why persistent terminal sessions are useful, especially when working over SSH.

Now it&#39;s time to actually use tmux.

In this chapter, we&#39;ll install tmux on your system, verify that everything is working, start your]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/get-tmux/</link>
                    <guid isPermaLink="false">6a85ab4ac246770001490894</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 15:28:26 +0530</pubDate>


                    <content:encoded><![CDATA[<p>In the previous chapter, we looked at the problem tmux solves and why persistent terminal sessions are useful, especially when working over SSH.</p><p>Now it's time to actually use tmux.</p><p>In this chapter, we'll install tmux on your system, verify that everything is working, start your first tmux session, and understand what you see when tmux starts.</p><p>We won't configure anything yet. For now, the goal is simple:</p><blockquote><strong>Get tmux running and get comfortable inside your first session.</strong></blockquote><p>Once that works, we'll start learning how to control tmux in the next chapter.</p><h2 id="installing-tmux">Installing Tmux</h2><p>The good news is that tmux is available through the package manager on most Linux distributions, so installation is usually just one command.</p><p>On Ubuntu or Debian-based systems, run:</p><pre><code class="language-bash">sudo apt update
sudo apt install tmux</code></pre><p>The first command refreshes your package information, and the second installs tmux.</p><p>On Arch:</p><pre><code>sudo pacman -S tmux</code></pre><p>If you're using another distribution, use the command for your system from the examples above. Verify the Installation before starting tmux: </p><pre><code class="language-bash">tmux -V</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-4.png" class="kg-image" alt="tmux version" loading="lazy" width="759" height="217" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-4.png 600w, https://linuxhandbook.com/content/images/2026/08/image-4.png 759w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">tmux version</span></figcaption></figure><h2 id="start-tmux">Start Tmux</h2><p>Now comes the fun part. Type <code>tmux</code> in your terminal and that's it, you have just started your first tmux session. </p><p>At first glance, almost nothing may seem different. Your shell still works normally, and you can still run Linux commands just like before.</p><p>But look at the <strong>bottom of your terminal</strong>. You should now see a tmux status bar. A typical tmux screen looks roughly like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/Screencastfrom2026-08-1918-49-13-ezgif.com-video-to-gif-converter.gif" class="kg-image" alt="Tmux first session" loading="lazy" width="800" height="500" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/Screencastfrom2026-08-1918-49-13-ezgif.com-video-to-gif-converter.gif 600w, https://linuxhandbook.com/content/images/2026/08/Screencastfrom2026-08-1918-49-13-ezgif.com-video-to-gif-converter.gif 800w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Tmux first session</span></figcaption></figure><p>Let's break down the status bar without going too deep yet. You may see something similar to:</p><pre><code>[0] 1:bash*</code></pre><p>The <code>1</code> represents the first window. The <code>bash</code> part tells you the shell running inside that window. The <code>*</code> marks the active window.</p><p>The Linux commands behave exactly as they normally would. Tmux isn't replacing your shell or changing how Linux commands work. It is managing the terminal environment around your shell.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-5.png" class="kg-image" alt="persistent session and multiple panes of Tmux" loading="lazy" width="1680" height="944" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-5.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/08/image-5.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/08/image-5.png 1600w, https://linuxhandbook.com/content/images/2026/08/image-5.png 1680w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">persistent session and multiple panes of Tmux</span></figcaption></figure><p>Type <code>exit</code> and press Enter. The tmux status bar disappears, and you return to your normal terminal. Later, you'll learn another operation called <strong><code>detach</code></strong>.</p><p>So far, we've only started tmux and observed what it looks like. But you may already be wondering <strong>how do I actually control tmux? </strong>That's what we'll answer next.</p><p>In the next chapter, we'll learn the <strong>tmux prefix key</strong> - the small but important concept that lets you send commands to tmux without accidentally sending them to your shell.</p><p>Once you understand the prefix key, the rest of tmux starts to feel much more predictable.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Chapter 1: Why Tmux? Understanding Terminal Multiplexing]]></title>
                    <description><![CDATA[If you have ever run a long command over SSH and lost it because your connection dropped, you already understand the pain tmux solves.

Tmux is a terminal multiplexer. In plain language, it lets you run and manage multiple terminal workspaces inside one terminal environment, and it keeps those workspaces]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/why-tmux/</link>
                    <guid isPermaLink="false">6a81432aa56acc000174915f</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 15:23:15 +0530</pubDate>


                    <content:encoded><![CDATA[<p>If you have ever run a long command over SSH and lost it because your connection dropped, you already understand the pain tmux solves.</p><p>Tmux is a terminal multiplexer. In plain language, it lets you run and manage multiple terminal workspaces inside one terminal environment, and it keeps those workspaces alive even when your network session dies.</p><p>In this chapter, I want you to understand that core idea first. We will get into the shortcuts and commands later. For now, let us focus on <strong>why tmux is useful and what problem it actually solves</strong>.</p><h2 id="the-problem-tmux-solves">The Problem Tmux Solves</h2><p>Without tmux, your remote shell is tied to your current SSH connection.</p><pre><code class="language-bash">ssh user@server
</code></pre><p>You now have a shell running through that connection. Perhaps you start a long command:</p><pre><code class="language-bash">./deploy.sh
</code></pre><p>Everything is fine as long as the connection stays alive.<br>But what happens if your network drops? The connection disappears, and your shell can disappear with it. For demo I will connect to my localhost and try a long-running command without Tmux:</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/08/without_tmux-1_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/08/without_tmux-1.mp4" poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="931" height="657" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="aspect-ratio: 931 / 657; background: transparent url('https://linuxhandbook.com/content/media/2026/08/without_tmux-1_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:11</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><p>This becomes frustrating when you are running: database imports, backups, deployment scripts, long test runs, builds, log monitoring, etc.</p><p>Tmux adds a persistent layer between your SSH connection and the work you are doing. Now your SSH connection can disappear while the tmux session continues running on the server.</p><p>Later, you reconnect and attach to the same session.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/with_turmux.gif" class="kg-image" alt="scenario with tmux" loading="lazy" width="800" height="564" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/with_turmux.gif 600w, https://linuxhandbook.com/content/images/2026/08/with_turmux.gif 800w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">scenario with tmux</span></figcaption></figure><p>The visual representation below explains the problem Tmux solves for your use cases </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image.png" class="kg-image" alt="The problem TMUX solves" loading="lazy" width="1536" height="1024" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/08/image.png 1000w, https://linuxhandbook.com/content/images/2026/08/image.png 1536w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The problem TMUX solves</span></figcaption></figure><h2 id="what-does-terminal-multiplexer-mean"><strong>What Does "Terminal Multiplexer" Mean?</strong></h2><p>The name sounds complicated, but the idea is simple.<strong> </strong>Tmux gives you three main layers:</p><p>Think of them like this:<strong> Session -</strong> your main workspace, <strong>Window</strong> - a tab inside that workspace, <strong>Pane -</strong> a split terminal inside a window</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-1.png" class="kg-image" alt="window and pane view" loading="lazy" width="1302" height="596" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-1.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/08/image-1.png 1000w, https://linuxhandbook.com/content/images/2026/08/image-1.png 1302w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">window and pane view</span></figcaption></figure><p>This structure lets you keep related work together without opening a huge number of separate terminal windows.</p><h2 id="who-benefits-most-from-tmux"><strong>Who Benefits Most From Tmux?</strong></h2><p>Tmux can help anyone who spends a lot of time in the terminal, but it is especially useful for: developers, DevOps and SRE engineers, system administrators, anyone running long terminal processes, or Linux learners who want a more organized workflow.</p><p>Even on your local machine, tmux can reduce terminal-tab clutter. And you don't need to be an advanced Linux user to benefit from it. The basic workflow already gives you most of the value: <strong>sessions → windows → panes → detach → reattach</strong> </p><h2 id="a-real-world-scenario"><strong>A Real-World Scenario</strong></h2><p>Imagine you are debugging an application on a production server.<br>You need to:</p><pre><code class="language-bash">Logs
Monitoring
Diagnostics
Health checks</code></pre><p>Without tmux, you might open four separate terminal tabs. With tmux, you can organize everything inside one session:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/08/image-3.png" class="kg-image" alt="real world scenario for tmux" loading="lazy" width="788" height="599" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/image-3.png 600w, https://linuxhandbook.com/content/images/2026/08/image-3.png 788w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">real world scenario for tmux</span></figcaption></figure><p>That's the basic flow you need to understand. In the next chapter, we'll install tmux and get our hands on it for the first time!<br></p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Tmux Fundamentals]]></title>
                    <description><![CDATA[Never lose a terminal session again! Learn tmux sessions, panes, and windows in this free, beginner-friendly course. No signup required.]]></description>
                    <link>https://linuxhandbook.com/courses/tmux/</link>
                    <guid isPermaLink="false">6a9a9048c246770001499bee</guid>

                        <category><![CDATA[Tmux]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 04 Sep 2026 15:18:37 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/09/tmux-fundamentals.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/09/tmux-fundamentals.png" alt="Tmux Fundamentals"/> <p>Your SSH connection drops mid-deploy. Your laptop goes to sleep. You accidentally close the wrong tab. And just like that, the build log you were watching, the SSH session you had open on three servers, the half-finished debugging session...all gone.</p><p><strong>Tmux fixes this.</strong></p><p>Tmux (terminal multiplexer) lets you run multiple terminal sessions inside a single window, keep them alive even after you disconnect, and pick up exactly where you left off, on the same machine or a different one entirely. </p><p><strong>It's one of those tools that, once you learn it, you wonder how you worked without it.</strong></p><h2 id="why-learn-tmux">Why learn tmux?</h2><ul><li><strong>Sessions that survive disconnects: </strong>Close your laptop, lose your SSH connection, or walk away entirely. Your session keeps running and you reattach right where you left off.</li><li><strong>Split panes, no extra windows:</strong> View logs, edit a file, and run a build, all in one terminal window, side by side.</li><li><strong>Multiple windows, one session: O</strong>rganize your work like browser tabs, but built into your terminal.</li><li><strong>Works everywhere: N</strong>o GUI required. If you can SSH into it, you can run tmux on it.</li><li><strong>Build repeatable workflows:</strong> Script your entire dev environment to open exactly the way you like it, every time.</li></ul><p>If you spend any real time in a terminal like SSHing into servers, running long processes, working across multiple projects at once, tmux isn't optional for you. You will save a lot of frustration and productive hours.</p><p>Tmux has a little learning curve, but it pays off in the long run. Ask any senior engineer.</p><h2 id="what-youll-learn">What you'll learn</h2><p>By the end of this free Tmux course, you'll be able to:</p><ul><li>Keep a terminal session running even after your SSH connection drops or your laptop sleeps</li><li>Split your terminal into multiple panes and jump between them without touching your mouse</li><li>Organize different tasks across windows, all inside a single tmux session</li><li>Scroll back through terminal output and copy text using only the keyboard</li><li>Set up a real, repeatable workflow instead of retyping the same commands every time</li><li>Write your own tmux configuration so it starts up exactly the way you want, every time</li></ul><p>No prior tmux experience needed, just basic comfort with a terminal.</p><h2 id="who-this-course-is-for">Who this course is for</h2><ul><li>Developers and sysadmins who SSH into remote servers regularly</li><li>Anyone who's lost work to a dropped connection or an accidentally closed terminal</li><li>Self-hosters and homelab enthusiasts managing multiple long-running processes</li><li>Command-line users who are tired of juggling a dozen terminal windows</li><li>Complete tmux beginners</li></ul><h2 id="why-learn-tmux-with-us">Why learn tmux with us?</h2><p>Most tmux guides stop at a keybinding cheat sheet. This course doesn't.</p><p>It's built around <strong>actually using tmux</strong>, not memorizing commands in isolation. It also includes a dedicated chapter on building a real, practical workflow, and another on writing your own tmux configuration so it feels like <em>your</em> terminal, not a default install. </p><p>Every chapter is short, hands-on, and something you can follow along with in your own terminal as you read.</p><p><strong>And it's completely free. No signup, no paywall, no catch.</strong></p><h2 id="ready-to-start">Ready to start?</h2><p>Jump into <strong>Chapter 1: Why Tmux? Understanding Terminal Multiplexing</strong> and get your first session running in the next few minutes.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.10: systemd Playbook, Redirection, &quot;forgit&quot; and More]]></title>
                    <description><![CDATA[Time to explore systemd]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-10/</link>
                    <guid isPermaLink="false">6a86d3f5c246770001490a32</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Fri, 21 Aug 2026 18:11:17 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/08/lhb-newsletter.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/08/lhb-newsletter.png" alt="LHB Linux Digest #26.10: systemd Playbook, Redirection, &quot;forgit&quot; and More"/> <p>Even after all these years, some people still have a strong dislike for systemd. My colleague, Umair, <a href="https://linuxhandbook.com/dont-hate-systemd/">stopped hating systemd</a> after realizing its automation capabilities.</p><p>He has created two courses on systemd:</p><ul><li><a href="https://linuxhandbook.com/courses/systemd-playbook/">Systemd playbook</a>: A hands-on, text-based course to turn you into a confident systemd user.</li><li><a href="https://linuxhandbook.com/courses/systemd-automation/">Systemd automation</a>: Learn to schedule, monitor, sandbox, and optimize automated workflows.</li></ul><p>The best way to learn anything on Linux is by getting your hands on the system. That's the approach we take on Linux Handbook.</p><p>Other than us, here are several other platforms you can use to <a href="https://linuxhandbook.com/blog/platforms-learn-devops-hands-on/">learn DevOps with practical, hands-on labs</a>.</p><h2 id="basic-but-essential-linux-concept-and">Basic but essential Linux concept: &lt;, &lt;&lt; and &lt;&lt;&lt;</h2><p>You'll often see &lt;, &lt;&lt; and &lt;&lt;&lt; in various Linux command examples. It is important to know what they mean.</p><ul><li><code>&lt;</code> : It is known as <strong><code>Input Redirection</code></strong> and is used to take input from a file rather than typing instructions manually.</li><li><code>&lt;&lt;</code>: It is known as <strong><code>Here Document</code> </strong>which is used to provide multiple lines of input directly to the command.</li><li><code>&lt;&lt;&lt;</code>: It is known as <strong><code>Here String</code></strong> and used to provide a single line of input to the command.</li></ul><p>I know it sounds super complex but <a href="https://linuxhandbook.com/here-input-redirections/">this article explains it in details</a>.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://linuxhandbook.com/here-input-redirections/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">What do &lt;, &lt;&lt; and &lt;&lt;&lt; mean in Linux?</div><div class="kg-bookmark-description">The &lt;, &lt;&lt; and &lt;&lt;&lt; look similar to redirection indicators but they have a different purpose. Learn about them.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/Linux-Handbook-New-Logo-cfcb2c95-dd66-478c-94a8-6de624ebce77.png" alt=""><span class="kg-bookmark-author">Linux Handbook</span><span class="kg-bookmark-publisher">Sagar Sharma</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/what-is--in-input-redirection-linux-3b445b87-012f-4b05-b9f2-ed44997801ff.png" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%8E%AB-event-alert-agntconmcpcon-japan">🎫 Event alert: AGNTCon+MCPCon Japan</h2><p>Whether you're building AI agents, adopting the Model Context Protocol (MCP), developing MCP servers and clients, or exploring the future of agentic AI, this is the event where the community comes together to share ideas, solve challenges, and shape what's next for the AI ecosystem.</p><p>Happening in Tokyo, Japan, on 10-11th September. <strong>If you want to attend, use coupon code ITSFOSS30 to get 30% discount on the event ticket pricing.</strong></p><div class="kg-card kg-button-card kg-align-center"><a href="https://events.linuxfoundation.org/agntcon-mcpcon-japan/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Event details (use ITSFOSS30 for discount)</a></div><h2 id="%F0%9F%92%A1quick-terminal-tip"><strong>💡Quick terminal tip</strong></h2><p>In Bash (and other Readline-based shells), navigating complex directories often means dealing with annoying typos or mixed case sensitivity. You can make Tab auto-complete paths regardless of capitalization while cleanly expanding common file prefixes before cycling through options.</p><p>Add these lines to your <code>~/.inputrc</code> file:</p><pre><code class="language-bash"># Ignore uppercase/lowercase differences during Tab completion
set completion-ignore-case on

# Treat hyphens (-) and underscores (_) as equivalent
set completion-map-case on

# Complete shared prefixes before cycling through individual choices
set menu-complete-display-prefix on
</code></pre><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/08/completion-new.gif" class="kg-image" alt="" loading="lazy" width="1040" height="560" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/completion-new.gif 600w, https://linuxhandbook.com/content/images/size/w1000/2026/08/completion-new.gif 1000w, https://linuxhandbook.com/content/images/2026/08/completion-new.gif 1040w" sizes="(min-width: 720px) 720px"></figure><p>Now, if you have files named <code>Project-Alpha.txt</code> and <code>Project-Beta.txt</code>, typing <code>cd pro</code> and pressing Tab will first safely expand your prompt to the longest shared prefix (<code>cd Project-</code>). Pressing Tab a second time begins stepping smoothly through each matching file, completely ignoring letter case.</p><h2 id="%F0%9F%9B%A0%EF%B8%8F-tool-discovery">🛠️ Tool discovery</h2><p>Check out these hidden gems.</p><h3 id="tuicr-terminal-native-code-review">tuicr: Terminal Native Code Review</h3><p><a href="https://github.com/agavra/tuicr?ref=linuxhandbook.com" rel="noopener nofollow"><code>tuicr</code></a> is an open-source Rust TUI utility designed to streamline code review workflows across multiple version control systems using modal, Vim-style navigation. The application aggregates multi-file diffs into a unified stream, allowing users to leave granular, line-level comments and submit them directly as live reviews to major code hosting platforms.</p><ul><li>⚡ Terminal-native, Vim-centric diffs with seamless modal navigation</li><li>🔄 Multi-VCS compatibility for unified reviews across git, jj, and hg</li><li>💬 Inline line-level commenting submitted directly to GitHub, GitLab, and Bitbucket</li><li>🤖 Structured markdown export to clipboard/stdout tailored for AI agent workflows</li><li>🦀 Ultra-fast Rust binary delivering zero-dependency CLI execution</li></ul><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/agavra/tuicr?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - agavra/tuicr: a code review TUI with vim keybindings</div><div class="kg-bookmark-description">a code review TUI with vim keybindings. Contribute to agavra/tuicr development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-2bffe746-39d8-478b-bb74-ff1d254339d8.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">agavra</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/tuicr-1d7fe1a3-338c-49a2-85cf-cc5832de97ed" alt="" onerror="this.style.display = 'none'"></div></a></figure><h3 id="forgit-interactive-git-usage-with-fzf">forgit: Interactive Git usage with fzf</h3><p><a href="https://github.com/wfxr/forgit?ref=linuxhandbook.com" rel="noopener nofollow">Forgit</a> is a shell utility that leverages fzf to provide interactive, terminal-native interfaces for routine version control operations. The tool integrates directly with CLI syntax highlighters while remaining lightweight and shell-agnostic across common terminal environments.</p><ul><li>⚡ Fuzzy-search Git selectors with interactive diff and log previews</li><li>🌿 Interactive branch and worktree management for seamless switching</li><li>🛠️ Automated <code>.gitignore</code> generator to fetch templates straight from your terminal</li><li>⏪ Interactive rebase and fixup tools to easily squash and reorder commits</li><li>🎨 Extensible preview integration using external tools like delta for diffs and bat for syntax highlighting</li></ul><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/wfxr/forgit?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - wfxr/forgit: :zzz: A utility tool powered by fzf for using git interactively.</div><div class="kg-bookmark-description">:zzz: A utility tool powered by fzf for using git interactively. - wfxr/forgit</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-ff0d4bbe-db05-4700-be54-682fd1fb224a.png" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">wfxr</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/forgit-c7071854-8457-4bbf-950b-523665b2a6fc" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%93%B0-linux-news-that-matters">📰 Linux news that matters</h2><ul><li><a href="https://www.phoronix.com/news/Synx?ref=linuxhandbook.com" rel="noopener nofollow">Qualcomm has started a Linux kernel discussion about upstreaming Synx</a>, a vendor-agnostic global synchronization framework for coordinating fences across different processors, firmware, and Linux-hosted clients. </li><li>Linux wireless maintainer Johannes Berg has announced that <a href="https://www.phoronix.com/news/Linux-WiFi-Strict-AI-Slop-Patch?ref=linuxhandbook.com" rel="noopener nofollow">AI/LLM-generated patches will generally be ignored</a> unless a quick review makes the fix “obviously right,” following a similar move in the kernel staging area. </li><li><a href="https://arstechnica.com/ai/2026/08/cloudflare-open-sources-vibe-coding-platform-for-people-who-arent-coders/?ref=linuxhandbook.com" rel="noreferrer">Cloudflare has open-sourced Cloudflare OS</a> (VibeSDK), an internal platform enabling non-technical personnel to build and deploy applications via natural language prompts. </li><li><a href="https://www.marktechpost.com/2026/08/06/microsoft-open-sources-code-testing-generator/?ref=linuxhandbook.com" rel="noopener nofollow">Microsoft has open-sourced code-testing-generator</a>, an MIT-licensed polyglot unit test creation agent hosted within the dotnet/skills repository. </li><li>Senior Linux kernel maintainer Greg Kroah-Hartman has <a href="https://itsfoss.com/news/linux-drivers-staging-ai-rejection/?ref=linuxhandbook.com" rel="noopener nofollow">established a explicit policy rejecting LLM-generated patch submissions</a> targeting the drivers/staging tree. </li><li><a href="https://devops.com/flooding-dropper-is-hitting-npm-with-a-tidal-wave-of-malicious-packages/?ref=linuxhandbook.com" rel="noopener nofollow">Sonatype researchers have identified an automated supply-chain campaign</a> dubbed "Flooding Dropper" that has published nearly 850 malicious npm packages distributed across hundreds of disposable accounts. </li><li><a href="https://www.phoronix.com/news/Modular-Mojo-Open-Source?ref=linuxhandbook.com" rel="noreferrer">Modular has released the complete source code for the Mojo language compiler</a>, runtime, and development tooling under the Apache 2.0 license with LLVM exceptions following its 1.0 release. </li></ul><h2 id="%F0%9F%98%82-geek-humor">😂 Geek humor</h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/08/lhb-meme-aug-2026.jpg" class="kg-image" alt="" loading="lazy" width="1080" height="1080" srcset="https://linuxhandbook.com/content/images/size/w600/2026/08/lhb-meme-aug-2026.jpg 600w, https://linuxhandbook.com/content/images/size/w1000/2026/08/lhb-meme-aug-2026.jpg 1000w, https://linuxhandbook.com/content/images/2026/08/lhb-meme-aug-2026.jpg 1080w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%92%8C-keep-on-loving-linux-handbook">💌 Keep on loving Linux Handbook</h2><p>GitOps course is nearly ready. It should arrive next week. </p><p>Perfect time to <a href="https://linuxhandbook.com/#/portal/signup">become a Pro member</a> and enjoy unlimited access to our <a href="https://linuxhandbook.com/ebooks/">eBooks</a>, <a href="https://linuxhandbook.com/courses/">courses</a> and in-depth tutorials.</p><p><strong>Missed the previous editions?</strong>&nbsp;You can&nbsp;<a href="https://linuxhandbook.com/newsletter/">access the newsletter archives.</a></p><p>You may also <a href="https://linuxhandbook.com/write-for-us/">contribute to Linux Handbook</a> and share your experience and expertise with the community.</p><p>I like reading your messages, so just hit the reply button and share your thoughts 😄</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[12 Best Free Platforms to Learn DevOps with Hands-On]]></title>
                    <description><![CDATA[Practice makes a devops perfect.]]></description>
                    <link>https://linuxhandbook.com/blog/platforms-learn-devops-hands-on/</link>
                    <guid isPermaLink="false">6a277ea70fd5850001a07c08</guid>

                        <category><![CDATA[blog]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 21 Aug 2026 14:47:06 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/08/learn-devops.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/08/learn-devops.png" alt="12 Best Free Platforms to Learn DevOps with Hands-On"/> <p>Watching DevOps tutorials is easy. Actually knowing what to do when a server is broken at in production is not.</p><p>The gap between the two is hands-on practice and if you have been searching for structured, interactive DevOps labs, you have probably run into the same problem: most good platforms cost money, and the free ones are scattered across a dozen different sites with no clear path connecting them.</p><p>I went through the platforms the DevOps community actually recommends on Reddit, in Discord servers, in job prep threads and pulled together the 12 best ones where you can practice for free. These are not passive reading resources. Every platform here puts you in front of a terminal and makes you figure something out.</p><p><strong>This list is not for you if</strong> you are looking for video courses or reading material that is a different category. This guide is about interactive labs, broken-server challenges, browser-based environments, and hands-on projects where you learn by doing.</p><p><strong>Short on time?</strong> Jump to the comparison table below, or use the headers to find platforms that match your current skill level.</p><h2 id="at-a-glance-all-12-platforms-compared">At a Glance: All 12 Platforms Compared</h2><table>
<thead>
<tr>
<th>Platform</th>
<th>Style</th>
<th>Skill Level</th>
<th>Free?</th>
<th>Best For</th>
</tr>
</thead>
<tbody>
<tr>
<td>SadServers</td>
<td>Broken-server CTF</td>
<td>Beginner → Advanced</td>
<td>✅ Fully</td>
<td>Troubleshooting &amp; debugging</td>
</tr>
<tr>
<td>OverTheWire (Bandit)</td>
<td>SSH wargame</td>
<td>Beginner → Mid</td>
<td>✅ Fully</td>
<td>Linux terminal mastery</td>
</tr>
<tr>
<td>Learn Git Branching</td>
<td>Visual puzzle game</td>
<td>Beginner → Mid</td>
<td>✅ Fully</td>
<td>Git fundamentals</td>
</tr>
<tr>
<td>Killercoda</td>
<td>Browser labs</td>
<td>All levels</td>
<td>✅ Mostly</td>
<td>Daily DevOps practice</td>
</tr>
<tr>
<td>Play with Docker</td>
<td>Docker playground</td>
<td>Beginner</td>
<td>✅ Fully</td>
<td>Docker basics</td>
</tr>
<tr>
<td>Play with Kubernetes</td>
<td>K8s cluster</td>
<td>Beginner → Mid</td>
<td>✅ Fully</td>
<td>Kubernetes fundamentals</td>
</tr>
<tr>
<td>pwn.college</td>
<td>Shell challenges</td>
<td>Beginner → Mid</td>
<td>✅ Fully</td>
<td>Deep Linux internals</td>
</tr>
<tr>
<td>Grafana Play</td>
<td>Live Grafana instance</td>
<td>All levels</td>
<td>✅ Fully</td>
<td>Observability practice</td>
</tr>
<tr>
<td>Linux Upskill Challenge</td>
<td>20-day course</td>
<td>Beginner</td>
<td>✅ Fully</td>
<td>Structured Linux sysadmin</td>
</tr>
<tr>
<td>Kubernetes The Hard Way</td>
<td>Manual K8s bootstrap</td>
<td>Advanced</td>
<td>✅ Fully</td>
<td>K8s architecture understanding</td>
</tr>
<tr>
<td>iximiuz Labs</td>
<td>Investigative labs</td>
<td>Mid → Advanced</td>
<td>✅ Partial</td>
<td>Container &amp; K8s internals</td>
</tr>
<tr>
<td>Terraform Tutorials</td>
<td>Interactive IaC labs</td>
<td>Beginner → Mid</td>
<td>✅ Fully</td>
<td>Infrastructure as Code</td>
</tr>
</tbody>
</table>
<h2 id="sadserversthe-leetcode-of-devops-troubleshooting">SadServers - The LeetCode of DevOps Troubleshooting</h2><p>SadServers is the closest thing DevOps has to LeetCode. You are given a broken Linux or DevOps environment, a problem statement, and a timer. Your job is to fix it. No hints, no hand-holding, just a terminal and a server that is doing something wrong.</p><p><strong>Who it's best for: </strong>Anyone who wants to practice the skill that actually matters most in DevOps: diagnosing and fixing production problems under pressure. Especially useful if you are preparing for DevOps interviews, where live troubleshooting scenarios are increasingly common.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image.png" class="kg-image" alt="SadServers problem listing page" loading="lazy" width="1848" height="968" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image.png 1600w, https://linuxhandbook.com/content/images/2026/06/image.png 1848w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">SadServers problem listing page</span></figcaption></figure><p>The scenarios cover real DevOps situations: a web server that refuses to start, a disk that is mysteriously full, a process that keeps dying, a misconfigured database. Each one is an actual production-style failure.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- The most realistic DevOps troubleshooting practice available for free<br>- Browser-based, no local setup, no SSH key management<br>- Growing library of scenarios across difficulty levels<br>- Community-submitted problems mean diverse coverage</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br><b><strong style="white-space: pre-wrap;">-</strong></b> No structured learning path, you pick your own scenarios<br>- Some advanced scenarios assume prior knowledge to even understand the problem<br>- No built-in explanations after solving, you figure out the "why" yourself</div></div><p><strong>Verdict:</strong> The single best platform for practicing the skill that defines a working DevOps engineer, fixing things that are broken. Bookmark this and do one scenario a week.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://sadservers.com/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | SadServers</a></div><h2 id="overthewirebandit-learn-linux-by-breaking-in">OverTheWire - Bandit: Learn Linux by Breaking In</h2><p>OverTheWire Bandit is a wargame where you SSH into a live server and solve challenges to discover the password for the next level. Level 0 to Level 34, each one teaching a specific Linux skill through a concrete puzzle rather than a lecture.</p><p><strong>Who it's best for: </strong>Complete beginners who need real Linux terminal practice and people who are comfortable with commands but want to understand file permissions, process management, and shell scripting by actually using them under pressure.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-1.png" class="kg-image" alt="OverTheWire Bandit challenges" loading="lazy" width="1848" height="968" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-1.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-1.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-1.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-1.png 1848w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">OverTheWire Bandit challenges</span></figcaption></figure><p>The early levels cover navigation, file reading, and hidden files. By the time you reach the middle levels, you are working with SSH keys, port forwarding, shell scripting, and basic cryptography. Every concept sticks because you needed it to progress.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Zero setup, just SSH in from any terminal<br>- Progressive difficulty that builds real skills in sequence<br>- Community walkthroughs exist for every level if you get stuck<br>- Completely free, no account required</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Purely Linux/security focused, not a broad DevOps curriculum<br>- No browser-based terminal (you need an SSH client - WSL, Terminal, or PuTTY)</div></div><p><strong>Verdict:</strong> The best free tool to build Linux command-line confidence from scratch. There is a reason DevOps engineers still recommend it to juniors in 2026; it works.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://overthewire.org/wargames/bandit/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | OverTheWire Bandit</a></div><h2 id="learn-git-branchingmaster-git-visually">Learn Git Branching - Master Git Visually</h2><p>Learn Git Branching is a browser-based, interactive Git tutorial that teaches branching, rebasing, merging, and cherry-picking through visual puzzles. You type real Git commands and watch the commit graph update in real time.</p><p><strong>Who it's best for: </strong>Anyone who uses Git daily but secretly does not understand what <code>rebase</code>, <code>cherry-pick</code>, or <code>HEAD~2</code> actually does, which is most engineers at some point.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-2.png" class="kg-image" alt="LearnGitBranching Visual Challenges" loading="lazy" width="1857" height="965" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-2.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-2.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-2.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-2.png 1857w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">LearnGitBranching Visual Challenges</span></figcaption></figure><p>The platform covers two tracks: Main (local Git operations) and Remote (push, pull, fetch, tracking branches). Each level sets a goal state for the commit graph and you have to figure out which commands produce it.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Instant visual feedback makes abstract Git concepts concrete<br>- Covers advanced operations most tutorials skip (rebase -i, cherry-pick, reflog)<br>- Completely free, no account needed, works in any browser<br>- One of the most linked Git resources in the entire developer community</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Only covers Git, nothing else in the DevOps toolchain<br>- The visual metaphor breaks down slightly for very complex rebases<br>- No real repository, the environment is simulated</div></div><p><strong>Verdict: </strong> The fastest way to actually understand what your Git commands are doing. Run through both tracks once and Git will never feel mysterious again.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://learngitbranching.js.org/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | Learn Git Branching</a></div><h2 id="killercodathe-devops-lab-that-is-always-open">Killercoda - The DevOps Lab That Is Always Open</h2><p>Killercoda gives you a real Linux environment in your browser, no install, no account required for the free tier. Choose a scenario, and within seconds, you have a terminal connected to a real server. The scenario library covers Linux, Docker, Kubernetes, Ansible, ArgoCD, Terraform, and more.</p><p><strong>Who it's best for: </strong>Anyone who wants a quick, no-friction DevOps practice, especially useful for learning a new tool without setting up a local environment first, or for keeping skills sharp between projects.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-3.png" class="kg-image" alt="Killercoda playground and lessons" loading="lazy" width="1857" height="965" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-3.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-3.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-3.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-3.png 1857w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Killercoda playground and lessons</span></figcaption></figure><p>The free library includes hundreds of official and community-created scenarios. Many are contributed by tool vendors themselves, Grafana, Cilium and others publish their official getting-started tutorials directly on Killercoda.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Real terminals in a real Linux environment, not a simulation<br>- Hundreds of free scenarios across the full DevOps toolchain<br>- No install, no local setup, works from any browser<br>- New scenarios added regularly by community and vendors</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Free tier sessions time out, you cannot leave and come back to a running environment<br>- Some advanced scenarios are PLUS-only (paid)<br>- No structured learning path, you curate your own sequence</div></div><p><strong>Verdict:</strong> The best free option for hands-on practice with any specific DevOps tool right now. Anytime you encounter something new, ArgoCD, Cilium, Flux, check if there is a Killercoda scenario before setting up a local environment.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://killercoda.com/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | Killercoda</a></div><h2 id="play-with-dockera-real-docker-daemon-in-your-browser">Play with Docker - A Real Docker Daemon in Your Browser</h2><p>Play with Docker gives you a free, 4-hour Linux instance with a real Docker daemon running, directly in your browser. Run containers, build images, write Compose files, and experiment with Docker networking without touching your local machine.</p><p><strong>Who it's best for: </strong>Beginners who want to learn Docker without installing it locally, and people who need a quick sandbox to test a Docker command or Compose configuration without affecting their machine.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-4.png" class="kg-image" alt="Play with Docker Classrooms" loading="lazy" width="1852" height="970" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-4.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-4.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-4.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-4.png 1852w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Play with Docker Classrooms</span></figcaption></figure><p>You can create multiple instances and connect them, useful for practicing Docker Swarm or multi-container networking scenarios. The official Docker documentation uses Play with Docker for many of its interactive examples.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Officially maintained by Docker, Inc. always up to date<br>- Real Docker environment, not an emulator- Multiple instances for networking and Swarm practice<br>- No credit card, no account needed for basic use</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- 4-hour session limit work gets lost when sessions expire<br>- Can be slow during peak hours</div></div><p><strong>Verdict:</strong> The zero-friction way to start with Docker. No installation, no configuration, just a terminal and a Docker daemon. Use this before committing to a local Docker Desktop setup.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://labs.play-with-docker.com/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | Play with Docker</a></div><h2 id="play-with-kubernetesa-multi-node-cluster-in-minutes">Play with Kubernetes - A Multi-Node Cluster in Minutes</h2><p>Play with Kubernetes provides a free, browser-based Kubernetes playground where you can bootstrap a real multi-node cluster and run workloads, without any local Kubernetes installation or cloud account.</p><p><strong>Who it's best for: </strong>People learning Kubernetes fundamentals who want to practice <code>kubectl</code>commands, deploy real workloads, and understand cluster architecture without the complexity of setting up minikube or a cloud cluster.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-5.png" class="kg-image" alt="Play with Kubernetes Classrooms" loading="lazy" width="1852" height="970" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-5.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-5.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-5.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-5.png 1852w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Play with Kubernetes Classrooms</span></figcaption></figure><p>Sessions give you a 4-hour window with enough compute to bootstrap a control plane and add worker nodes. Every standard kubectl operation works: deployments, services, configmaps, namespaces and RBAC.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Real multi-node cluster, not a single-node simulation<br>- Bootstrapping the cluster yourself teaches how it actually works<br>- Free with a Docker Hub account<br>- Ideal for CKA/CKAD exam concept practice</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- 4-hour session limit, not suitable for long-running experiments<br>- Bootstrapping the cluster from scratch every session takes 5-10 minutes<br>- No persistent volumes that survive session restarts</div></div><p><strong>Verdict:</strong> The most accessible way to get a real Kubernetes cluster for practice without a cloud bill. Pair it with Kubernetes The Hard Way for a deeper understanding of what that bootstrap process is actually doing.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://labs.play-with-k8s.com/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | Play with Kubernetes</a></div><h2 id="pwncollegedeep-linux-internals-through-structured-challenges">pwn.college - Deep Linux Internals Through Structured Challenges</h2><p>pwn.college is a university-backed (Arizona State University) platform that teaches Linux internals through a structured series of challenges. Unlike typical beginner Linux tutorials, it covers how the shell works, process interactions, file descriptors, environment variables, and privilege escalation, concepts that are foundational to DevOps but rarely taught explicitly.</p><p><strong>Who it's best for: </strong>Engineers who use Linux daily but want to deeply understand what is actually happening beneath the commands, process spawning, shell internals and permissions at the kernel level. Especially valuable if you work with Docker, because containers are Linux primitives underneath.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-6.png" class="kg-image" alt="pwn.college structured paths" loading="lazy" width="1851" height="910" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-6.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-6.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-6.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-6.png 1851w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">pwn.college structured paths</span></figcaption></figure><p>The platform is organized into modules (Linux Luminarium is the entry point for DevOps practitioners) and every challenge is a real binary running on a real Linux system that you interact with directly.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- University-quality curriculum, completely free<br>- Teaches the Linux concepts that Docker and container knowledge depend on<br>- Structured modules with clear progression<br>- Discord community with active support from instructors</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Leans toward security/CTF in its later modules (beyond DevOps needs)<br>- Browser-based terminal can be slower than a native SSH session</div></div><p><strong>Verdict:</strong> The best free resource for understanding <strong><em>why</em></strong> Linux behaves the way it does, not just memorizing commands. If you use containers daily and want to understand what namespaces and cgroups actually are, start here.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://pwn.college/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | pwn.college</a></div><h2 id="grafana-playlive-observability-practice-with-zero-setup">Grafana Play - Live Observability Practice With Zero Setup</h2><p>Grafana Play is a fully functional, live Grafana instance that anyone can open in a browser right now, pre-loaded with dashboards, Loki log data, Prometheus metrics, alerting rules, and Tempo traces. No installation, no Docker Compose stack, no Prometheus setup.</p><p><strong>Who it's best for: </strong>Engineers who want to get comfortable with Grafana dashboards, PromQL queries, Loki log queries, and alert configuration before setting up a full observability stack locally or in production.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-7.png" class="kg-image" alt="Grafana Play interface" loading="lazy" width="1787" height="967" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-7.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-7.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-7.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-7.png 1787w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Grafana Play interface</span></figcaption></figure><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- No setup whatsoever, open a URL, start exploring<br>- Pre-loaded with real dashboards covering Linux, Kubernetes, and application metrics<br>- Covers the full Grafana stack: Metrics, Logs (Loki), Traces (Tempo), Alerting</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- No local date source testing<br>- Covers Linux fundamentals, not higher-level DevOps tooling</div></div><p><strong>Verdict:</strong> If your Linux skills feel shaky and you want to fix that with a structured, real-world approach, the Linux Upskill Challenge is the most complete free answer. Twenty focused days produce a genuine foundation.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://grafana.com/grafana/dashboards/14125-grafana-play-home/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | Grafana Play</a></div><h2 id="linux-upskill-challenge20-days-to-real-linux-sysadmin-skills">Linux Upskill Challenge - 20 Days to Real Linux Sysadmin Skills</h2><p>The Linux Upskill Challenge is a free, community-run 20-day course where you rent a cheap VPS (or use a free cloud trial) and learn to manage it as a real system administrator would. Each day introduces new concepts with clear instructions, exercises, and a community forum for questions.</p><p><strong>Who it's best for: </strong>Beginners who want a structured, day-by-day Linux learning path that produces a real skill foundation, not just knowledge of commands, but actual comfort managing a remote server. The VPS-based approach means everything you do is real.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-11.png" class="kg-image" alt="Linux Upskill Challenge 20 Days" loading="lazy" width="1847" height="966" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-11.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-11.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-11.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-11.png 1847w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Linux Upskill Challenge 20 Days</span></figcaption></figure><p>The course covers everything a working sysadmin needs: SSH key management, file permissions, package management, process management, system services with systemd, firewalls, cron jobs, log analysis, and basic security hardening.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- A complete, structured 20-day curriculum, always know what to do next<br>- Working on a real VPS means skills transfer directly to real systems<br>- Community forum for everyday exercises, never stuck alone<br>- Free forever; the GitHub repository is open source</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Requires a VPS, most cloud-free tiers work, but it is not purely zero-cost<br>- 20 days of consistent daily work require commitment<br>- Covers Linux fundamentals, not higher-level DevOps tooling</div></div><p><strong>Verdict:</strong> If your Linux skills feel shaky and you want to fix that with a structured, real-world approach, the Linux Upskill Challenge is the most complete free answer. Twenty focused days produces a genuine foundation.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://linuxupskillchallenge.org/?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | Linux Upskill Challenge</a></div><h2 id="kubernetes-the-hard-waybuild-a-cluster-from-scratch">Kubernetes The Hard Way - Build a Cluster From Scratch</h2><p>Kubernetes The Hard Way, created by Kelsey Hightower (Google), guides you through bootstrapping a Kubernetes cluster manually, without kubeadm, without any helper scripts, every component configured by hand. It is not the easiest way to get a cluster, which is exactly the point.</p><p><strong>Who it's best for: </strong>Engineers who already use Kubernetes daily but feel like they are operating it without truly understanding it. Going through this once answers questions that years of <code>kubectl apply</code> never will.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-8.png" class="kg-image" alt="Kubernetes The Hard Way Git Repo" loading="lazy" width="1787" height="967" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-8.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-8.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-8.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-8.png 1787w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Kubernetes The Hard Way Git Repo</span></figcaption></figure><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- The definitive resource for understanding Kubernetes internals<br>- Goes through the components no other tutorial explains (etcd, API server internals)<br>- Completely free on GitHub; cloud provider-specific forks exist (GCP, AWS, bare metal)<br>- Highly respected in the DevOps community, a milestone for K8s practitioners</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Takes significant time (4-8 hours minimum for a careful first pass)<br>- Requires cloud instances or VMs, not purely browser-based<br>- Not a daily practice tool - it is a one-time deep understanding exercise</div></div><p><strong>Verdict:</strong> Not something you do every day, but something every serious Kubernetes practitioner should do at least once. The understanding it provides changes how you operate clusters permanently.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/kelseyhightower/kubernetes-the-hard-way?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | Kubernetes The Hard Way</a></div><h2 id="iximiuz-labsinvestigate-how-containers-and-k8s-actually-work">iximiuz Labs - Investigate How Containers and K8s Actually Work</h2><p>iximiuz Labs takes a deliberately different approach to DevOps learning: instead of guided tutorials, it puts you in an environment and asks you to investigate how something works. Labs cover container networking, Linux namespaces, Kubernetes control plane behavior, and distributed systems concepts through exploration rather than instruction.</p><p><strong>Who it's best for: </strong>Intermediate to advanced practitioners who want to understand <strong><em>why</em></strong> containers and Kubernetes behave the way they do, the Linux primitives underneath Docker, why pod networking works the way it does and what the scheduler actually considers.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-9.png" class="kg-image" alt="ixium Labs official collection of playgrounds" loading="lazy" width="1690" height="962" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-9.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-9.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-9.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-9.png 1690w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">ixium Labs official collection of playgrounds</span></figcaption></figure><p>The free tier includes a solid selection of foundational labs on container runtimes, networking, and Kubernetes basics. The platform is built by Ivan Velichko, widely respected in the cloud-native community for the depth of his writing on container internals.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Teaches the "why" that most DevOps platforms skip<br>- Browser-based multi-terminal environment with relevant tools pre-installed<br>- Covers container/K8s concepts that no other free platform addresses<br>- Built by a practitioner known for technical accuracy</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Some advanced labs require a paid subscription<br>- Not beginner-friendly, assumes comfort with containers and Linux already<br>- Investigative format requires more patience than step-by-step tutorials</div></div><p><strong>Verdict:</strong> The best platform for going from "I can use Kubernetes" to "I understand Kubernetes." If you have been using containers for a year and still feel uncertain about the internals, this fills that gap.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://labs.iximiuz.com/playgrounds?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | iximiuz Labs</a></div><h2 id="terraform-tutorialsofficial-interactive-iac-practice">Terraform Tutorials - Official Interactive IaC Practice</h2><p>HashiCorp's official Terraform tutorials on the Developer portal are interactive, browser-based labs that teach Infrastructure as Code without requiring a cloud account for most foundational content. They cover AWS, Azure, GCP, and local Terraform workflows with a consistent, practical structure.</p><p><strong>Who it's best for: </strong>Engineers who know containers and Kubernetes but have not yet learned Infrastructure as Code and anyone preparing for the Terraform Associate certification who wants practice alongside the theory.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-10.png" class="kg-image" alt="Terraform Tutorials Homepage" loading="lazy" width="1690" height="962" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-10.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-10.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/06/image-10.png 1600w, https://linuxhandbook.com/content/images/2026/06/image-10.png 1690w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Terraform Tutorials Homepage</span></figcaption></figure><p>The tutorials build progressively: start with a local Docker provider (no cloud account needed), move to cloud providers once you understand the workflow. Each tutorial includes working code, an explanation of what each block does, and a real-world step.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Official documentation and tutorials from HashiCorp, always accurate and up to date<br>- Many tutorials run entirely locally with no cloud account needed<br>- Covers the full Terraform workflow: init, plan, apply, state, modules, workspaces</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Cloud provider tutorials require an AWS/Azure/GCP account (though free tier works)<br>- No challenge/puzzle format, more guided tutorial than active problem-solving</div></div><p><strong>Verdict:</strong> The most reliable starting point for Terraform. If IaC is the gap in your DevOps skillset and for many practitioners it is, start here before looking anywhere else.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://developer.hashicorp.com/terraform/tutorials?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">Visit | Terraform Tutorials</a></div><h2 id="how-to-use-these-platforms-together">How to Use These Platforms Together</h2><p>These platforms are not competing alternatives; they cover different skills and different learning modes. A practical sequence:</p><ul>
<li><strong>Start with Linux fundamentals</strong> : Linux Upskill Challenge (structured) + OverTheWire Bandit (challenges)</li>
<li><strong>Add Git mastery early</strong> : Learn Git Branching (spend one afternoon, do both tracks)</li>
<li><strong>Learn containers hands-on</strong> : Play with Docker, then Killercoda Docker scenarios</li>
<li><strong>Move to Kubernetes</strong> : Play with Kubernetes for basics → Killercoda K8s scenarios → Kubernetes The Hard Way for deep understanding → iximiuz Labs for internals</li>
<li><strong>Add IaC</strong> : Terraform Tutorials (start with local Docker provider, no cloud account needed)</li>
<li><strong>Add observability</strong> : Grafana Play (explore before setting up your own stack)</li>
<li><strong>Keep troubleshooting sharp</strong> : SadServers (one scenario per week) + pwn.college Linux modules</li>
</ul>
<p>None of these require paid subscriptions to start; all have free tiers that cover the core learning value.</p><h2 id="faq">FAQ</h2><p><strong>Do I need a powerful computer to use these platforms?</strong><br>
No. Every platform on this list is either browser-based or requires only a basic setup. Your local machine is just a browser or SSH client.</p>
<p><strong>Which platform should a complete beginner start with?</strong><br>
Start with Linux Upskill Challenge for structured foundations, then add OverTheWire Bandit for command-line confidence, then Learn Git Branching for Git. After those three, Killercoda opens up most of the rest of the DevOps toolchain at a reasonable pace.</p>
<p><strong>Are these platforms useful for certification preparation (CKA, CKAD, Terraform Associate)?</strong><br>
Yes. Play with Kubernetes and Killercoda are both consistently recommended for CKA/CKAD practice. Terraform Tutorials covers the Terraform Associate curriculum directly. SadServers builds the troubleshooting speed that the CKA exam requires.</p>
<p><strong>Is Kubernetes The Hard Way still relevant with modern tools like k3s and minikube?</strong><br>
Yes, and for the same reason, reading a car manual is still useful even if you use a GPS. K3s and minikube are better for daily use. The Hard Way is for understanding what they are abstracting. Do it once, then use the convenient tools with actual understanding.</p>
<h2 id="conclusion"><strong>Conclusion</strong></h2><p>The best DevOps skill is not knowing which tool to use; it is knowing what to do when something breaks. Every platform on this list gets you closer to that, whether you are starting from zero with the Linux Upskill Challenge, building Git intuition with Learn Git Branching, diagnosing broken servers on SadServers, or finally understanding what Kubernetes is actually doing under the hood with Kubernetes The Hard Way and iximiuz Labs.<br><br>You do not need to work through all twelve at once; pick the one that matches your current gap, spend a few hours a week, and let the practice compound. The engineers who stand out in DevOps are the ones who have broken things, fixed things, and done it enough times that the instinct becomes automatic. These platforms give you the reps. <strong>If you know of such a platform, do drop it in the comments!</strong></p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Why GitOps is in Trend]]></title>
                    <description><![CDATA[]]></description>
                    <link>https://linuxhandbook.com/courses/gitops/why-gitops-in-trend/</link>
                    <guid isPermaLink="false">6a880361c246770001490b4d</guid>

                        <category><![CDATA[GitOps]]></category>

                        <dc:creator><![CDATA[Sachin H R]]></dc:creator>

                    <pubDate>Fri, 21 Aug 2026 13:23:14 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.09: Docker Compose Override, Claude Skills for DevOps, Solidtime and More]]></title>
                    <description><![CDATA[Override the compose]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-09-2/</link>
                    <guid isPermaLink="false">6a633a36b5d4b60001763d8d</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Fri, 24 Jul 2026 17:05:24 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/05/lhb-newsletter.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/05/lhb-newsletter.png" alt="LHB Linux Digest #26.09: Docker Compose Override, Claude Skills for DevOps, Solidtime and More"/> <p>Don't we learn something new everyday? Something that might be obvious to others but feels like discovery to you?</p><p>I had that feeling when I learned about the concept of compose override in Docker. In my self-hosted Ghost CMS deployment, I made <a href="https://linuxhandbook.com/docker-log-space-issue/">modifications in the compose file to introduce log rotation</a>. But now the compose file was modified and any upstream change would complain about modified file. Git stash comes to rescue, but it's an additional pain.</p><p>And that pain went away with the override compose file. It's an excellent way of separating local and upstream changes, local and production compose files. I <a href="https://linuxhandbook.com/blog/docker-compose-override-trick-ghost/">wrote about it here</a>.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://linuxhandbook.com/blog/docker-compose-override-trick-ghost/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Git Pull Kept Failing on My Ghost Server. Docker Compose Override Fixed It</div><div class="kg-bookmark-description">Modifying your docker-compose.yml directly and now git pull throws a “local changes would be overwritten” error? Use a compose.override.yml file to keep your changes separate from the file Ghost’s repo manages.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/Linux-Handbook-New-Logo-be40298b-d73d-4e08-8138-2b39b5215b22.png" alt=""><span class="kg-bookmark-author">Linux Handbook</span><span class="kg-bookmark-publisher">Abhishek Prakash</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/docker-compose-override-file-a29dae2d-bfc4-4c42-a82f-74b707592e19.png" alt="" onerror="this.style.display = 'none'"></div></a></figure><p>Claude (or other mainstream AI tools) can be an excellent help in troubleshooting your infrastructure issues. But if you just ask it "find me for this error message", you'll get generic answers. Yash who has recently started working as a <a href="https://linuxhandbook.com/blog/devops-engineer-claude-skills/">DevOps engineer shares some of the Claude skills he uses</a>. You can take inspiration and modify these skills as needed or use them as it is.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://linuxhandbook.com/blog/devops-engineer-claude-skills/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">8 Claude Skills I Use Everyday as a DevOps Engineer</div><div class="kg-bookmark-description">Sharing the skills I use for troubleshooting and other purposes as a devops engineer. They are primarily for Claude but should work with other AI tools, too.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/Linux-Handbook-New-Logo-653d08b4-f910-4356-8611-3fcef24f4b64.png" alt=""><span class="kg-bookmark-author">Linux Handbook</span><span class="kg-bookmark-publisher">Yash Kiran Patil</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/claude-skills-devops-e03461f9-a65c-4b3b-a98a-df0f4408193c.webp" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%92%A1quick-terminal-tip"><strong>💡Quick terminal tip</strong></h2><p>In bash (and other readline-based shells), press <code>Alt+Shift+3</code> (or <code>Alt+#</code>) while typing a command. It prefixes the line with <code>#</code>, submits it, and since <code>#</code> starts a comment, the command won't execute.</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/07/command-to-comment-1.gif" class="kg-image" alt="" loading="lazy" width="780" height="605" srcset="https://linuxhandbook.com/content/images/size/w600/2026/07/command-to-comment-1.gif 600w, https://linuxhandbook.com/content/images/2026/07/command-to-comment-1.gif 780w" sizes="(min-width: 720px) 720px"></figure><p>It stays in your shell history for later. Handy for jotting down a command you're not ready to run yet.</p><p>Now that you know this one, <a href="https://itsfoss.com/linux-terminal-shortcuts/?ref=linuxhandbook.com" rel="noopener nofollow">here are a few more shortcuts</a> worth adding to your muscle memory.</p><h2 id="%F0%9F%9B%A0%EF%B8%8F-tool-discovery">🛠️ Tool discovery</h2><p>Let's find your next favorite software in this section.</p><h3 id="buzz-self-hostable-workspace-for-humans-and-ai-agents">Buzz: Self-Hostable Workspace for Humans and AI Agents</h3><p><a href="https://github.com/block/buzz?ref=linuxhandbook.com" rel="noopener nofollow">Buzz</a> is an open-source collaboration platform from Block that brings team chat, Git repositories, and AI agents into a single workspace. Built on the Nostr protocol, it lets organizations self-host their collaboration platform while allowing AI agents to participate as authenticated team members with their own identities and permissions.</p><ul><li>💬 Integrated Team Collaboration – Channels, threads, DMs, media sharing, and search in one workspace (voice huddles in progress).</li><li>🤖 AI Agents as Teammates – Agents hold cryptographic identities and can review code, submit patches, and collaborate alongside humans.</li><li>🌐 Self-Hostable &amp; Open Source – Apache 2.0 licensed; deploy on your own infrastructure with full data control.</li><li>🛠️ Built-in Git Collaboration – Host repos, submit patches, and manage code review without external Git hosting.</li><li>🔐 Nostr-Based Architecture – Every event is signed via Nostr, giving verifiable identity and a full audit trail.</li></ul><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/block/buzz?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - block/buzz: A hive mind communication platform</div><div class="kg-bookmark-description">A hive mind communication platform. Contribute to block/buzz development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-f86fc362-a27a-42f0-8ff0-a6a9f7d8e329.svg" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">block</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/51dc14c1d9091832156118c3168485f81b7efb63db9843a348e1fd467d23abe4/block/buzz" alt="" onerror="this.style.display = 'none'"></div></a></figure><h3 id="solidtime-modern-open-source-time-tracking-for-teams">Solidtime: Modern Open-Source Time Tracking for Teams</h3><p><a href="https://github.com/solidtime-io/solidtime?ref=linuxhandbook.com" rel="noopener nofollow">Solidtime</a> is an open-source time tracking platform built for freelancers, agencies, and teams that need an easy way to track work, manage projects, and generate invoices. It offers a polished web and desktop experience, supports self-hosting, and keeps activity tracking privacy-friendly by processing desktop activity locally before converting it into time entries.</p><ul><li>⏱️ Time Tracking – Simple, modern interface to track work time.</li><li>📁 Projects &amp; Tasks – Create projects and tasks, and assign them to team members.</li><li>👥 Clients – Manage clients and link them to projects.</li><li>💰 Billable Rates – Set rates per project, member, or organization.</li><li>🏢 Multiple Organizations – Manage several organizations from one account.</li><li>🔑 Roles &amp; Permissions – Control access within organizations.</li><li>📥 Data Import – Import from Toggl, Clockify, or CSV.</li></ul><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/solidtime-io/solidtime?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - solidtime-io/solidtime: Modern open-source time-tracking app</div><div class="kg-bookmark-description">Modern open-source time-tracking app. Contribute to solidtime-io/solidtime development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/favicon-0b30dc03-a11a-4da8-9323-ac5ea991f0db.svg" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">solidtime-io</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/4d582af8-81df-4bf4-adbd-e22ad295bce0-d68d5be7-a706-438d-91ed-2a6fd1af43c3" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%93%B0-linux-news-that-matters">📰 Linux news that matters</h2><ul><li><a href="https://www.theregister.com/security/2026/07/22/linux-kernel-team-publishes-432-cves-in-two-days/5276497?ref=linuxhandbook.com" rel="noopener nofollow"><strong>The Linux kernel CVE team published 432 CVEs over just two days</strong></a>, prompting concerns from security engineers about the practicality of reviewing and prioritizing individual kernel vulnerabilities. The surge reflects the kernel project's policy of assigning CVEs to virtually every qualifying security-related bug fix in stable releases, with AI-assisted bug discovery also contributing to the growing number of reports reaching maintainers.</li><li><a href="https://www.networkworld.com/article/4200847/networkmanager-update-advances-ipv6-only-support-wi-fi-management-and-security-for-linux-based-operating-systems.html?ref=linuxhandbook.com" rel="noopener nofollow"><strong>NetworkManager 1.58 adds support for IPv6-only deployments</strong></a> through RFC 8925 IPv6-only-preferred signaling and 464XLAT (CLAT), enabling legacy IPv4 applications to continue working on IPv6-only networks. The release also introduces GENEVE tunnel management for virtualized environments, 6 GHz Wi-Fi enhancements, persistent managed state across reboots for automation, and fixes multiple DHCP-related security issues, including CVE-2026-10805.</li><li><a href="https://www.securityweek.com/cisco-launches-low-cost-ai-models-for-source-code-security/?ref=linuxhandbook.com" rel="noopener nofollow"><strong>Cisco has released Antares-350M and Antares-1B</strong></a>, two open-weight small language models purpose-built to locate known vulnerabilities within large source code repositories. Unlike general-purpose coding models, Antares focuses on repository-level vulnerability localization. Can run locally without uploading proprietary code to the cloud, and Cisco claims it achieves comparable accuracy at up to 172× lower cost than leading frontier AI models while also releasing a benchmark to measure this task.</li><li><a href="https://www.theregister.com/devops/2026/07/23/model-context-protocol-prepares-to-break-with-its-stateful-past/5276722?ref=linuxhandbook.com" rel="noopener nofollow"><strong>The Model Context Protocol (MCP) is preparing its 2026-07-28 specification</strong></a>, replacing its stateful architecture with a stateless protocol core by removing session IDs and the initialization handshake while introducing a new extensions framework and stronger authorization mechanisms. The redesign allows MCP servers to run behind standard HTTP load balancers without sticky sessions or shared session stores, making large-scale deployments significantly easier, although existing implementations will require migration because of breaking protocol changes.</li><li><a href="https://devops.com/githubs-redesigned-pr-inbox-tackles-the-review-bottleneck-ai-created/?ref=linuxhandbook.com" rel="noopener nofollow"><strong>GitHub has made its redesigned Pull Requests Dashboard generally available</strong></a>, introducing an Inbox that surfaces review requests, CI failures, merge-ready pull requests, saved views, advanced search, and support for identifying AI agent-created pull requests. The update reflects a broader industry shift where AI coding assistants generate code faster than humans can review it, prompting GitHub to focus on review triage rather than code generation alone.</li></ul><h2 id="%F0%9F%98%82-geek-humor">😂 Geek humor</h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/07/LHB-meme-july-24.jpeg" class="kg-image" alt="" loading="lazy" width="1080" height="1080" srcset="https://linuxhandbook.com/content/images/size/w600/2026/07/LHB-meme-july-24.jpeg 600w, https://linuxhandbook.com/content/images/size/w1000/2026/07/LHB-meme-july-24.jpeg 1000w, https://linuxhandbook.com/content/images/2026/07/LHB-meme-july-24.jpeg 1080w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%92%8C-keep-on-loving-linux-handbook">💌 Keep on loving Linux Handbook</h2><p>GitOps course is nearly ready. It should arrive next week. </p><p>Perfect time to <a href="https://linuxhandbook.com/#/portal/signup">become a Pro member</a> and enjoy unlimited access to our <a href="https://linuxhandbook.com/ebooks/">eBooks</a>, <a href="https://linuxhandbook.com/courses/">courses</a> and in-depth tutorials.</p><p><strong>Missed the previous editions?</strong>&nbsp;You can&nbsp;<a href="https://linuxhandbook.com/newsletter/">access the newsletter archives.</a></p><p>You may also <a href="https://linuxhandbook.com/write-for-us/">contribute to Linux Handbook</a> and share your experience and expertise with the community.</p><p>I like reading your messages, so just hit the reply button and share your thoughts 😄</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[8 Claude Skills I Use Everyday as a DevOps Engineer]]></title>
                    <description><![CDATA[Sharing the skills I use for troubleshooting and other purposes as a devops engineer. They are primarily for Claude but should work with other AI tools, too.]]></description>
                    <link>https://linuxhandbook.com/blog/devops-engineer-claude-skills/</link>
                    <guid isPermaLink="false">6a410a04668db800010d5b83</guid>

                        <category><![CDATA[blog]]></category>
                        <category><![CDATA[AI 🤖🧠]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Fri, 24 Jul 2026 16:47:27 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/07/claude-skills-devops.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/07/claude-skills-devops.webp" alt="8 Claude Skills I Use Everyday as a DevOps Engineer"/> <p>I was skeptical about AI tools in a DevOps workflow for a long time. Every demo I saw showed someone asking AI Agent to write a Hello World Dockerfile. That's not a DevOps use case, that's a simple chat.</p><p>What changed my mind was using Claude for things that actually slow me down at work. Not boilerplate code generation, but the genuinely tedious parts of the job: interpreting a cryptic error from a stack trace buried inside a Kubernetes pod, converting a Bash script someone wrote in 2017 into something readable, or asking "what does this flag do again" without having to leave the terminal context I'm already in.</p><p>But here's the thing: generic Claude and <a href="https://code.claude.com/docs/en/skills?ref=linuxhandbook.com" rel="noreferrer"><strong><em>skilled</em> <em>Claude</em></strong></a> are two very different tools.</p><p>Out of the box, Claude gives you general-purpose answers. When you add a SKILL.md, a structured instruction file that tells Claude exactly how to approach a specific task, you get a focused, deterministic workflow instead of a guess. The difference matters in DevOps, where a half-correct answer about a Kubernetes misconfiguration or a Terraform plan can cause real problems.</p><p>This article covers both sides: the skills themselves, and the concrete difference between using Claude with and without them. I'm running this on VS Code with Claude Sonnet 4.6.</p><h2 id="what-are-claude-skills">What Are Claude Skills?</h2><p>Claude Code supports a feature called <a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview?ref=linuxhandbook.com" rel="noreferrer"><strong>skills</strong></a>: markdown files named <code>SKILL.md</code> that live inside a <code>.claude/skills/</code> directory in your project. When you ask Claude something that matches a skill's trigger phrases, it automatically uses the structured workflow defined in that file instead of its default behavior.</p><p>Think of it like the difference between asking a new colleague a question and asking someone who's already written the runbook for it. Same knowledge, completely different depth and reliability.</p><p>I've written 8 of my own, one for each workflow I find myself using regularly.</p><h2 id="why-skills-actually-matter">Why Skills Actually Matter</h2><p>Let me show the difference concretely before going through each skill.</p><p>I'll use the <strong>error-decoder</strong> skill as the example, with a Docker container that keeps exiting. This is something you can reproduce on any machine with Docker installed.</p><p><strong>The prompt</strong>: "My Docker container keeps exiting immediately. Here's the output." (with <code>docker logs</code> and <code>docker inspect</code> output pasted in)</p><p>Here's what I actually pasted in:</p><pre><code class="language-bash">$ docker run --name my-app myrepo/my-app:2.1.0
Error: DATABASE_URL environment variable is not set.
Exiting.

$ docker inspect my-app --format='{{.State.ExitCode}} {{.State.OOMKilled}}'
1 false

$ docker ps -a | grep my-app
my-app   myrepo/my-app:2.1.0   Exited (1) 3 seconds ago</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-21.png" class="kg-image" alt="Before applying the skill.md for error-decoding" loading="lazy" width="876" height="524" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-21.png 600w, https://linuxhandbook.com/content/images/2026/06/image-21.png 876w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Before applying the skill.md for error-decoding</span></figcaption></figure><p>The response is accurate but completely generic. It lists common causes without engaging with the actual output that was pasted. The real answer is sitting right there in the logs (<code>DATABASE_URL environment variable is not set</code>) but Claude, without the skill, doesn't structure its analysis to find it.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-22.png" class="kg-image" alt="After applying the skill.md for error-decoding" loading="lazy" width="812" height="588" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-22.png 600w, https://linuxhandbook.com/content/images/2026/06/image-22.png 812w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">After applying the skill.md for error-decoding</span></figcaption></figure><p>The response now follows the skill's output format. It pulls the specific root cause directly from the logs, gives the exact fix command, tells you what a successful run looks like, and gives the next diagnostic step if it still fails.</p><p>The skill didn't add knowledge Claude didn't have. It added <em><strong>structure and focus</strong>,</em> it forces Claude to identify the root cause separately from the proximate cause, and to give a verification step instead of stopping at "here's the fix."</p><h2 id="the-8-claude-skills-in-my-toolbox">The 8 Claude Skills in My Toolbox</h2><p>Below are the 8 skills you will have in your project, which will give you a focused and structured workflow for your projects. I will also show you the results I get after the prompt I give to the agent with the skills enforced. You are free to download them and modify them as per your requirements.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">💡</div><div class="kg-callout-text">You can use the skills that fits your workflow. Use them as base and modify them as needed.</div></div><p>The skills folder structure will look like this:</p><p>.claude/<br>
└── skills/<br>
├── error-decoder/<br>
│   └── SKILL.md       ← Diagnose Kubernetes, Terraform, Helm errors<br>
├── bash-auditor/<br>
│   └── SKILL.md       ← Write and audit Bash scripts<br>
├── k8s-manifest-reviewer/<br>
│   └── SKILL.md       ← Explain and audit Kubernetes YAML<br>
├── format-converter/<br>
│   └── SKILL.md       ← Convert between DevOps formats and tools<br>
├── runbook-drafter/<br>
│   └── SKILL.md       ← Draft runbooks, postmortems, SOPs<br>
├── terraform-explainer/<br>
│   └── SKILL.md       ← Explain and audit Terraform code and plans<br>
├── api-tester/<br>
│   └── SKILL.md       ← Generate cURL and API test commands<br>
└── cicd-auditor/<br>
└── SKILL.md       ← Audit GitHub Actions, GitLab CI, Jenkins</p>
<h3 id="error-decoderdiagnosing-cryptic-errors">error-decoder - Diagnosing Cryptic Errors</h3><p>This is the one I use most often. DevOps tools are notoriously bad at error messages. Docker exits a container with code 137 and you're left guessing whether it's <a href="https://linuxhandbook.com/oom-killer/" rel="noreferrer">OOM</a> or a signal. Terraform throws a provider error with a reference ID you have to track down. Helm fails on a templating issue with a line number that doesn't match your file. Kubernetes gives you a pod in <code>CrashLoopBackOff</code> with no explanation of why. In all of these cases, the raw error is pointing <strong>at</strong> a symptom, not <strong><em>at</em></strong> the cause.</p><p>My workflow: paste the full error, not a summary, the full thing and add two sentences of context:</p><pre><code class="language-bash">Here is the error from my Kubernetes pod. This pod was working yesterday.
The only change was updating the image tag from 1.3.2 to 1.4.0.

[full kubectl describe pod output]</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-23.png" class="kg-image" alt="Output of Claude with error-decoder skill.md" loading="lazy" width="939" height="831" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-23.png 600w, https://linuxhandbook.com/content/images/2026/06/image-23.png 939w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Output of Claude with error-decoder skill.md</span></figcaption></figure><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://linuxhandbook.com/content/files/2026/06/SKILL.md" title="Download" download=""><div class="kg-file-card-contents"><div class="kg-file-card-title">error-decoder</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">SKILL.md</div><div class="kg-file-card-filesize">5 KB</div></div></div><div class="kg-file-card-icon"><svg viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"></polyline><line class="a" x1="12" y1="6.75" x2="12" y2="18"></line><circle class="a" cx="12" cy="12" r="11.25"></circle></svg></div></a></div><p>The single biggest thing that improved my results: treating Claude like a knowledgeable colleague who needs to be briefed, not a search engine. The skill enforces this by requiring full context before proceeding.</p><h3 id="bash-auditorwriting-and-reviewing-bash-scripts">bash-auditor - Writing and Reviewing Bash Scripts</h3><p><a href="https://linuxhandbook.com/courses/bash/" rel="noreferrer">Bash</a> is the lingua franca of DevOps and also one of the most footgun-prone languages in existence. A script that looks fine will silently fail because someone forgot <code>set -e</code>. A loop will do something destructive because the variable expansion wasn't quoted. A condition will always evaluate to true because of the way <code>[[ ]]</code> handles empty strings.</p><p>I use this skill for three things: Writing scripts from a plain-English description, reviewing scripts I didn't write, explaining what a script does, etc.</p><pre><code class="language-bash"># My Prompt

Review this Bash script as if you're performing a production code review.

Identify:
- Bugs
- Security issues
- Reliability problems
- Quoting mistakes
- Error handling issues
- Race conditions
- Portability concerns
- Performance improvements

Explain why each issue matters and then provide a corrected production-ready version with comments.</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-24.png" class="kg-image" alt="Output of Claude with bash-auditor skill.md" loading="lazy" width="1132" height="670" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-24.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-24.png 1000w, https://linuxhandbook.com/content/images/2026/06/image-24.png 1132w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Output of Claude with bash-auditor skill.md</span></figcaption></figure><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://linuxhandbook.com/content/files/2026/06/SKILL-1.md" title="Download" download=""><div class="kg-file-card-contents"><div class="kg-file-card-title">bash-auditor</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">SKILL.md</div><div class="kg-file-card-filesize">5 KB</div></div></div><div class="kg-file-card-icon"><svg viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"></polyline><line class="a" x1="12" y1="6.75" x2="12" y2="18"></line><circle class="a" cx="12" cy="12" r="11.25"></circle></svg></div></a></div><p>A note on trust: I always read through generated Bash before running it, especially anything that touches the filesystem or makes external requests. The skill produces a first draft with proper structure, not production-certified code.</p><h3 id="k8s-manifest-reviewerunderstanding-kubernetes-yaml">k8s-manifest-reviewer - Understanding Kubernetes YAML</h3><p>Kubernetes YAML is verbose by design. A single Deployment manifest can be 80 lines long and most of it is boilerplate. The meaningful parts, resource limits, liveness probes, affinity rules and security contexts are buried in the middle.</p><p>I use this skill in two ways:</p><p><strong>Explaining what a manifest does:</strong> Paste in a Deployment or StatefulSet YAML I haven't seen before and the skill walks through it section by section, calling out anything non-obvious. Particularly useful when you inherit infrastructure and need to quickly understand what's running and why.</p><p><strong>Spotting misconfigurations:</strong> The skill audits against a production-readiness checklist</p><pre><code class="language-bash"># My prompt
Review this Kubernetes Deployment as if you're the platform engineer responsible for approving it for production.

Please:
1. Explain what each section of the manifest does.
2. Point out any security, reliability, scalability, or performance issues.
3. Identify Kubernetes best-practice violations.
4. Rank the issues by severity (Critical, High, Medium, Low).
5. Explain why each issue matters.
6. Suggest concrete fixes.
7. Provide a corrected production-ready manifest.

Context:
- This is running in a production EKS cluster.
- It was migrated from a development environment.
- Traffic is expected to reach 800-1000 requests per second.
- High availability is required.
- Zero-downtime deployments are expected.

Here's the manifest provided:</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-25.png" class="kg-image" alt="Output of Claude with k8s-manifest-reviewer skill.md" loading="lazy" width="1132" height="670" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-25.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-25.png 1000w, https://linuxhandbook.com/content/images/2026/06/image-25.png 1132w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Output of Claude with k8s-manifest-reviewer skill.md</span></figcaption></figure><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://linuxhandbook.com/content/files/2026/06/SKILL-2.md" title="Download" download=""><div class="kg-file-card-contents"><div class="kg-file-card-title">k8s-manifest-reviewer</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">SKILL.md</div><div class="kg-file-card-filesize">5 KB</div></div></div><div class="kg-file-card-icon"><svg viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"></polyline><line class="a" x1="12" y1="6.75" x2="12" y2="18"></line><circle class="a" cx="12" cy="12" r="11.25"></circle></svg></div></a></div><p>Things the skill catches that are easy to miss: Memory limit lower than memory request, missing <code>readinessProbe</code>, <code>hostNetwork: true</code> left in from a debugging session, <code>:latest</code> image tag in a production manifest, no <code>podAntiAffinity</code> rules, etc.</p><h3 id="format-converterconverting-between-devops-formats">format-converter - Converting Between DevOps Formats</h3><p>DevOps involves a lot of format conversion work that nobody talks about because it's unglamorous. Docker Compose files that need to become Helm charts. Bash scripts that need to become Ansible playbooks. <a href="https://linuxhandbook.com/curl-command-examples/#what-is-curl" rel="noreferrer"><code>cURL</code></a> commands from API docs that need to become Python scripts. JSON that needs to become YAML.</p><p>All of this is mechanical but error-prone when you do it by hand.</p><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://linuxhandbook.com/content/files/2026/06/SKILL-3.md" title="Download" download=""><div class="kg-file-card-contents"><div class="kg-file-card-title">format-converter</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">SKILL.md</div><div class="kg-file-card-filesize">5 KB</div></div></div><div class="kg-file-card-icon"><svg viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"></polyline><line class="a" x1="12" y1="6.75" x2="12" y2="18"></line><circle class="a" cx="12" cy="12" r="11.25"></circle></svg></div></a></div><p>The skill enforces that constraints are explicit before generating output. The more specific your constraints, the less cleanup you do afterwards.</p><h3 id="runbook-drafterwriting-operational-documentation"><strong>runbook-drafter - Writing Operational Documentation</strong></h3><p>A runbook is only useful if it's actually written. Most teams have "runbooks" that are either a Confluence page last updated in 2021 or just "the person who knows how to restart the thing."</p><p>My process: do the thing first, then write a quick stream-of-consciousness description of what I did and why:</p><pre><code class="language-bash"># My prompt

I just fixed a production database connectivity issue. Here's what happened:
the app pods were getting connection refused on port 5432, which turned out to
be a NetworkPolicy that was blocking traffic from the app namespace to the db
namespace after a recent namespace label change. I fixed it by updating the
namespaceSelector in the NetworkPolicy. Write a runbook section for this.</code></pre><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://linuxhandbook.com/content/files/2026/06/SKILL-4.md" title="Download" download=""><div class="kg-file-card-contents"><div class="kg-file-card-title">runbook-drafter</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">SKILL.md</div><div class="kg-file-card-filesize">5 KB</div></div></div><div class="kg-file-card-icon"><svg viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"></polyline><line class="a" x1="12" y1="6.75" x2="12" y2="18"></line><circle class="a" cx="12" cy="12" r="11.25"></circle></svg></div></a></div><p>The skill turns that stream-of-consciousness into a structured runbook section in about 30 seconds. I edit it, add the actual commands I ran, and it becomes something a teammate could actually follow at 2am.</p><p>The same approach works for postmortems. Dump the timeline, dump the actions, ask the skill to organize it into a postmortem structure. You still write the "lessons learned" section yourself; that's the part that requires judgment.</p><h3 id="terraform-explainerunderstanding-infrastructure-as-code">terraform-explainer - Understanding Infrastructure as Code</h3><p><a href="https://linuxhandbook.com/courses/terraform/infrastructure-as-code/#2-uses-hcl-hashicorp-configuration-language" rel="noreferrer">Terraform's</a> HCL is readable enough on its own, but complex module structures - especially third-party modules with 40 variables, can be hard to parse quickly. I use this skill to understand infrastructure I didn't write.</p><p><strong>Reading a module:</strong> </p><pre><code class="language-bash">Explain what this Terraform module does. I specifically want to understand:
- What resources it creates
- What the required vs. optional variables are
- Whether anything here creates a public-facing resource
- Anything that might be surprising in a production AWS account</code></pre><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://linuxhandbook.com/content/files/2026/06/SKILL-5.md" title="Download" download=""><div class="kg-file-card-contents"><div class="kg-file-card-title">terraform-explainer</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">SKILL.md</div><div class="kg-file-card-filesize">5 KB</div></div></div><div class="kg-file-card-icon"><svg viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"></polyline><line class="a" x1="12" y1="6.75" x2="12" y2="18"></line><circle class="a" cx="12" cy="12" r="11.25"></circle></svg></div></a></div><p>Provider APIs go stale. Terraform and cloud provider APIs evolve constantly. For anything version-sensitive, verify against the official registry before trusting the output.</p><h3 id="api-testergenerating-curl-and-api-test-commands">api-tester - Generating cURL and API Test Commands</h3><p>Every time I'm integrating a new service or debugging a webhook, I end up constructing <code>cURL</code> commands from API documentation. JWT auth headers, JSON body formatting, the right Content-Type; this is tedious and the skill is fast at it.</p><p><strong>The prompt I put:</strong></p><pre><code class="language-bash">Give me a cURL command to call the GitHub REST API to list all open pull
requests for the repo "myorg/myrepo", authenticated with a personal access
token stored in $GITHUB_TOKEN, with output formatted as JSON and piped to jq
to show only the PR title and number.</code></pre><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://linuxhandbook.com/content/files/2026/06/SKILL-6.md" title="Download" download=""><div class="kg-file-card-contents"><div class="kg-file-card-title">api-tester</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">SKILL.md</div><div class="kg-file-card-filesize">5 KB</div></div></div><div class="kg-file-card-icon"><svg viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"></polyline><line class="a" x1="12" y1="6.75" x2="12" y2="18"></line><circle class="a" cx="12" cy="12" r="11.25"></circle></svg></div></a></div><p>The skill knows the auth patterns for common APIs (GitHub, Slack, Prometheus, Alertmanager, PagerDuty) without needing to be told. It also enforces that credentials are always environment variables and generated commands never contain a literal token.</p><p>I use this for any API I haven't touched before: Prometheus remote write, Alertmanager webhooks, AWS API Gateway, Slack, PagerDuty, wherever I need a quick working example to start from. </p><h3 id="cicd-auditorreviewing-cicd-pipeline-configs">cicd-auditor - Reviewing CI/CD Pipeline Configs</h3><p>CI/CD pipelines written in YAML accumulate complexity over time. Stages that nobody remembers the purpose of. Jobs that run sequentially because nobody added <code>needs:</code> correctly. Secrets being printed to logs somewhere. Docker layers not being cached.</p><p><strong>My review prompt:</strong></p><pre><code class="language-bash">Review this GitHub Actions workflow for common issues:
- Steps that could be parallelized but aren't
- Secrets being exposed in logs
- Missing caching for dependencies or Docker layers
- Jobs that will always run even when they should be conditional
- Third-party actions not pinned to a SHA</code></pre><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://linuxhandbook.com/content/files/2026/06/SKILL-7.md" title="Download" download=""><div class="kg-file-card-contents"><div class="kg-file-card-title">cicd-auditor</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">SKILL.md</div><div class="kg-file-card-filesize">6 KB</div></div></div><div class="kg-file-card-icon"><svg viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"></polyline><line class="a" x1="12" y1="6.75" x2="12" y2="18"></line><circle class="a" cx="12" cy="12" r="11.25"></circle></svg></div></a></div><p><br>The skill specifically checks for something that most miss: <a href="https://docs.github.com/en/actions/reference/security/secure-use?ref=linuxhandbook.com#using-third-party-actions" rel="noreferrer"><strong>third-party GitHub Actions pinned to mutable tags</strong></a>. <code>uses: some-action/tool@v3</code> looks fine, but it can be hijacked; the tag can be moved to point at different code. The safe version is pinning to a commit SHA.</p><h2 id="wrapping-up">Wrapping Up</h2><p>The value I get from Claude in a DevOps context is concentrated in specific places: decoding errors faster, auditing configs I didn't write, handling format conversion that's mechanical but annoying, and getting documentation drafted while the context is fresh. You can refer the official documentation for <a href="https://docs.anthropic.com/en/docs/claude-code/skills?ref=linuxhandbook.com" rel="noreferrer">Claude skills</a>.</p><p>The skills are what make this reliable instead of hit-or-miss. Without them, Claude gives you general advice. With them, it follows a deterministic workflow - asks for the right inputs, applies a consistent checklist, and formats the output in a way you can actually act on. </p><p><strong>If you have more such skill.md that you use, share them in the comments and tell how these skills enhance your workflow!</strong> </p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Why GitOps is Not Just CI/CD]]></title>
                    <description><![CDATA[]]></description>
                    <link>https://linuxhandbook.com/courses/gitops/gitops-is-not-just-ci-cd/</link>
                    <guid isPermaLink="false">6a6342f4b5d4b60001763dd6</guid>

                        <category><![CDATA[GitOps]]></category>

                        <dc:creator><![CDATA[Sachin H R]]></dc:creator>

                    <pubDate>Fri, 24 Jul 2026 16:20:36 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[GitOps vs Traditional DevOps]]></title>
                    <description><![CDATA[]]></description>
                    <link>https://linuxhandbook.com/courses/gitops/gitops-vs-traditional-devops/</link>
                    <guid isPermaLink="false">6a6341a8b5d4b60001763db7</guid>

                        <category><![CDATA[GitOps]]></category>

                        <dc:creator><![CDATA[Sachin H R]]></dc:creator>

                    <pubDate>Fri, 24 Jul 2026 16:16:52 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[What GitOps Really Is]]></title>
                    <description><![CDATA[]]></description>
                    <link>https://linuxhandbook.com/courses/gitops/what-is-gitops/</link>
                    <guid isPermaLink="false">6a632767b5d4b60001763d4a</guid>

                        <category><![CDATA[GitOps]]></category>

                        <dc:creator><![CDATA[Sachin H R]]></dc:creator>

                    <pubDate>Fri, 24 Jul 2026 14:45:42 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[GitOps Handbook (Work in Progress)]]></title>
                    <description><![CDATA[Learn GitOps with ArgoCD in this hands-on course. Go from Kubernetes deployment basics to safe, production-grade rollouts.]]></description>
                    <link>https://linuxhandbook.com/courses/gitops/</link>
                    <guid isPermaLink="false">6a031dceb8e78b00019294e4</guid>

                        <category><![CDATA[GitOps]]></category>

                        <dc:creator><![CDATA[Sachin H R]]></dc:creator>

                    <pubDate>Fri, 24 Jul 2026 14:16:20 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/07/gitops-course.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/07/gitops-course.png" alt="GitOps Handbook (Work in Progress)"/> <p>Have you ever deployed an app to Kubernetes and later realized you don't really know what changed, who changed it, or how to roll it back safely? Maybe dev looked fine, staging looked stable, and production still broke at midnight, right when nobody wanted to touch it.</p><p><em>This is exactly the problem GitOps exists to solve.</em></p><p>GitOps isn't just another DevOps trend. It's a deployment model where Git becomes the single source of truth for your infrastructure and applications. Your cluster continuously pulls the desired state from Git, so every change is auditable, reversible, and predictable.</p><p>Tools like ArgoCD make this possible on Kubernetes, and that's exactly what this course teaches you, starting from the core concepts and working all the way to real production deployments.</p><h2 id="what-youll-learn">What you'll learn</h2><p>This course is split into four modules, taking you from concepts to implementation to production-grade, safe deployments.</p><p><strong>Module 1: GitOps Foundations</strong></p><ul><li>What GitOps really is, and how it compares to traditional DevOps</li><li>Why GitOps is not just CI/CD, and why it's trending right now</li><li>Push vs pull deployments, explained with real-world examples</li></ul><p><strong>Module 2: Getting Started with ArgoCD</strong></p><ul><li>Installing ArgoCD and understanding its architecture</li><li>Deploying your first application the GitOps way</li><li>Setting up RBAC and managing user access</li></ul><p><strong>Module 3: Working with ArgoCD</strong></p><ul><li>Secret management in GitOps</li><li>Helm vs Kustomize deployments</li><li>Multi-environment GitOps strategy across dev, staging, and production</li></ul><p><strong>Module 4: Progressive Delivery with Argo Rollouts</strong></p><ul><li>Blue-green and canary deployments</li><li>Automated rollbacks </li><li>Metrics based decision and safe production releases</li></ul><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">💡</div><div class="kg-callout-text">The course includes a complete, end-to-end, real world project so that you can get hands-on practice on what you learned.</div></div><h2 id="who-this-course-is-for">Who this course is for</h2><p>This course is for you if you deploy applications to Kubernetes and want a safer, more predictable way to do it. It works well whether you're a DevOps engineer tired of manual deployments, a platform engineer building GitOps workflows for your team, or a developer and student who just wants to understand what ArgoCD and Argo Rollouts are actually doing under the hood.</p><p>You don't need any prior experience with ArgoCD to start. A <a href="https://linuxhandbook.com/courses/kubernetes/" rel="noreferrer">basic understanding of Kubernetes</a> will help you get more out of the course, but the first module builds up the concepts from scratch anyway.</p><h2 id="start-the-course">Start the course</h2><p>Start with Module 1 and go through the four modules in order. Each one builds on the last, so you move from GitOps concepts, to your first ArgoCD deployment, to running progressive, production-grade rollouts by the end.</p><p>By the time you finish the final project in Module 5, you'll have hands-on experience with the same GitOps setup used to run real production systems.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Git Pull Kept Failing on My Ghost Server. Docker Compose Override Fixed It]]></title>
                    <description><![CDATA[Modifying your docker-compose.yml directly and now git pull throws a &quot;local changes would be overwritten&quot; error? Use a compose.override.yml file to keep your changes separate from the file Ghost&#x27;s repo manages.]]></description>
                    <link>https://linuxhandbook.com/blog/docker-compose-override-trick-ghost/</link>
                    <guid isPermaLink="false">6a5f3878b5d4b6000176381b</guid>

                        <category><![CDATA[blog]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Tue, 21 Jul 2026 19:19:18 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/07/docker-compose-override-file.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/07/docker-compose-override-file.png" alt="Git Pull Kept Failing on My Ghost Server. Docker Compose Override Fixed It"/> <p>If editing your docker-compose.yml directly is breaking git pull from upstream, here's the fix: move your customizations into a separate compose.override.yml file instead of editing the original.</p><h2 id="the-fix-use-a-compose-override-file">The fix: use a compose override file</h2><p>Create a <code>compose.override.yml</code> in the same folder as your <code>compose.yml</code>, and use the exact service names from your original file (<code>ghost</code> and <code>caddy</code>, in my case). </p><pre><code class="language-yaml">services:
  ghost:
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "5"
  caddy:
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "5"
</code></pre><p> Docker Compose picks up <code>compose.override.yml</code> automatically and merges it into <code>compose.yml</code> at runtime, so you don't need to pass any extra flags. </p><p>So, when you run:</p><pre><code>docker compose up</code></pre><p>It is equivalent to running:</p><pre><code>docker compose -f compose.yml -f compose.override.yml up</code></pre><p>Your original <code>compose.yml</code> never gets touched, so there's nothing left for <code>git pull</code> to conflict with and so no complaints from git.</p><h2 id="how-i-ran-into-this">How I ran into this</h2><p>I run my Ghost sites using <a href="https://docs.ghost.org/install/docker?ref=linuxhandbook.com">Ghost's official Docker Compose self-hosting method</a>. Eventually, I noticed that Ghost's default setup generates a lot of log output, so I <a href="https://linuxhandbook.com/docker-log-space-issue/">added log rotate option in the docker compose file</a> for the <code>ghost</code> and <code>caddy</code> services directly inside <code>compose.yml</code>. </p><p>This solved the logs eating up disk space problem, but updating the Ghost version became inconvenient. </p><p>Updating to a newer Ghost version after that is meant to be a simple three-step routine: </p><ul><li>git pull</li><li>docker compose pull</li><li>docker compose up -d.</li></ul><p>That routine broke because I modified <code>compose.yml</code>. Every <code>git pull</code> started failing with the same error:</p><pre><code class="language-text">root@ghost-learnubuntu:/opt/ghost# git pull
remote: Enumerating objects: 89, done.
remote: Counting objects: 100% (68/68), done.
remote: Compressing objects: 100% (46/46), done.
remote: Total 89 (delta 52), reused 29 (delta 20), pack-reused 21 (from 2)
Unpacking objects: 100% (89/89), 31.28 KiB | 485.00 KiB/s, done.
From https://github.com/TryGhost/ghost-docker
   14cc722..d3204b2  main                                   -&gt; origin/main
Updating 14cc722..d3204b2
error: Your local changes to the following files would be overwritten by merge:
        compose.yml
Please commit your changes or stash them before you merge.
Aborting
</code></pre><p>For a while, my workaround was keeping a backup of the untouched <code>compose.yml</code>, or running <code>git stash</code> before every pull. It worked, but it meant remembering an extra step every single time I wanted to update Ghost. </p><p>And one day, I came across the concept of compose override file.</p><h2 id="what-is-a-compose-override-file">What is a compose override file</h2><p>A compose override file is just a <a href="https://docs.docker.com/compose/how-tos/multiple-compose-files/?ref=linuxhandbook.com">second compose file</a> that sits next to your main one. Anything you define inside it gets layered on top of <code>compose.yml</code> automatically, without you having to pass any extra flags to <code>docker compose</code>. </p><p>Since it's a separate file, it's not the one git is tracking against upstream, so pulling new changes from Ghost's repo doesn't touch anything you've customized.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">💡</div><div class="kg-callout-text">The only thing that matters is getting the service names right. If a service name in your override file doesn't match the one in <code spellcheck="false" style="white-space: pre-wrap;">compose.yml</code> exactly, Docker Compose treats it as a new service instead of merging into the existing one.</div></div><p>Here's the compose.override.yml file for my Ghost.</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/07/compose-override-file.png" class="kg-image" alt="Docker compose override file" loading="lazy" width="1103" height="579" srcset="https://linuxhandbook.com/content/images/size/w600/2026/07/compose-override-file.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/07/compose-override-file.png 1000w, https://linuxhandbook.com/content/images/2026/07/compose-override-file.png 1103w" sizes="(min-width: 720px) 720px"></figure><p>This solved the problem for me completely. My <code>compose.yml</code> now stays exactly as it comes from upstream, and <code>git pull</code>, <code>docker compose pull</code>, <code>docker compose up -d</code> goes back to being a clean three-step routine.</p><h2 id="using-override-files-to-separate-test-and-production">Using override files to separate test and production</h2><p>The same mechanism works for more than just logging. Since an override file just layers extra configuration on top of the base file, you can use a similar setup to separate test and production: keep one <code>compose.override.yml</code> for local tweaks like lighter resource limits or different ports, and a separate file, say <code>compose.prod.yml</code>, for anything specific to production. You pick which one applies at deploy time with the <code>-f</code> flag.</p><h2 id="other-ways-to-use-override-files">Other ways to use override files</h2><p>Let's see various ways you can use the overrride compose file.</p><h3 id="run-without-override">Run without override</h3><p>If you ever need to deploy without applying the override, point <code>docker compose</code> at only the base file explicitly:</p><pre><code class="language-bash">docker compose -f compose.yml up -d
</code></pre><p>Passing <code>-f</code> like this skips the automatic override merge entirely.</p><h3 id="use-multiple-override-files">Use multiple override files</h3><p>You're also not limited to one override file. Layer as many as you need by repeating <code>-f</code> in order, with later files taking priority over earlier ones:</p><pre><code>docker compose -f compose.yml -f compose.override.yml -f compose.prod.yml up -d
</code></pre><h3 id="see-what-the-final-compose-file-looks-like">See what the final compose file looks like</h3><p>Whenever you want to double check what's actually being applied after all that layering, run: </p><pre><code>docker compose config </code></pre><p>It prints the fully merged result.</p><h2 id="%F0%9F%92%A1add-override-to-gitignore">💡Add override to gitignore</h2><p>I have added my <code>compose.override.yml</code> to the <code>.gitignore</code>. It's local to my setup, not something upstream needs to know about, and keeping it out of git means I'll never run into a merge conflict over it either. You can do the same if it fits your scenario.</p><p>I'm sure there's more you can do with override files depending on your setup, but this fixed the problem I had: keeping my logging tweaks out of the file Ghost's repo manages. </p><p>If you're running Ghost, or anything else, through docker compose and editing the compose file directly, it's worth switching to an override file before you reach for <code>git stash</code> every time.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.08: Two Kernel Bugs You Need to Know, SSH Tunneling, and AI Pentesting]]></title>
                    <description><![CDATA[Imagine you could automate pentesting with a bunch of AI agents.]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-09/</link>
                    <guid isPermaLink="false">6a4f88cf3dddcd0001738f30</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Fri, 10 Jul 2026 17:21:32 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/05/lhb-newsletter.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/05/lhb-newsletter.png" alt="LHB Linux Digest #26.08: Two Kernel Bugs You Need to Know, SSH Tunneling, and AI Pentesting"/> <p>Short one this week my friend, energy's a bit low on my end, but two kernel vulnerabilities landed that are too important to skip, so let's get into it.</p><p>Two old, nasty kernel bugs got public exploits this week. If you're running KVM or any kind of multi-tenant containers, this is a "patch today, not this weekend" situation.</p><p><a href="https://thehackernews.com/2026/07/15-year-old-ghostlock-flaw-enables-root.html?ref=linuxhandbook.com">GhostLock (CVE-2026-43499) is a 15-year-old use-after-free bug</a> in the Linux kernel's futex/rtmutex subsystem. It lets an unprivileged local user grab root and escape containers on unpatched systems. This one's been sitting quietly since 2011, affects pretty much every major distro, and researchers have already shown a reliable exploit that gets root in about five seconds. It also breaks container isolation, so if you're self-hosting anything multi-tenant, take this seriously.</p><p><a href="https://www.bleepingcomputer.com/news/linux/new-januscape-linux-kernel-flaw-allows-vm-escape-on-intel-amd-devices/?ref=linuxhandbook.com" rel="noreferrer">Januscape (CVE-2026-53359) is a 16-year-old use-after-free in KVM</a>'s shadow MMU implementation. It can let an attacker escape a guest VM and run code on the host, on both Intel and AMD systems. Cloud providers and anyone running untrusted workloads in virtualized environments are the biggest targets, but if you run KVM at home, it's worth checking your patch status too.</p><p>Two decade-plus-old bugs surfacing with working exploits in the same week is a good reminder that "old and stable" doesn't mean "safe to ignore."</p><h2 id="%F0%9F%93%9A-worth-reading-from-linux-handbook">📚 Worth reading from Linux Handbook</h2><p>A Postgres instance on a remote server, port 5432 not exposed to the internet (rightly so). How to access it? The fix is SSH tunneling, and <a href="https://linuxhandbook.com/ssh-tunneling/">this tutorial</a> walks through all three flavors with the actual commands and real use cases behind them.</p><ul><li><strong>Local forwarding (<code>-L</code>)</strong> to reach a remote service, like that Postgres box, as if it were running on your own machine</li><li><strong>Remote forwarding (<code>-R</code>)</strong> to expose something local, like a webhook receiver on your dev machine, to the outside world through a VPS</li><li><strong>Dynamic forwarding (<code>-D</code>)</strong> to turn your SSH connection into a SOCKS proxy for encrypting your traffic on untrusted WiFi</li></ul><p> If you've ever wanted to skip standing up a VPN just to reach one service, this is worth ten minutes of your time. <a href="https://linuxhandbook.com/ssh-tunneling/">Read the full guide</a>.</p><p><strong>Also recent, in case you missed them:</strong></p><ul><li><a href="https://linuxhandbook.com/blog/fzf-command/">I Like This Fuzzy Search Finder Better Than Find Command in Linux</a>, a quick case for swapping <code>find</code> for <code>fzf</code> in your daily workflow</li><li><a href="https://linuxhandbook.com/blog/docker-workflow-tools/">These 11 Open Source Tools Completely Improved My Docker Workflow</a>, a practical roundup if you're managing more than a couple of containers</li></ul><h2 id="%F0%9F%92%A1quick-terminal-tip"><strong>💡Quick terminal tip</strong></h2><p>Most Linux users know how to extract archives, but tar includes several lesser-known options that can make working with archives safer and more efficient.</p><p>Before extracting an archive, inspect its contents:</p><pre><code>tar -tf archive.tar.gz
</code></pre><p>This lists every file and directory inside the archive without extracting anything.</p><p>To avoid cluttering your current directory, extract the archive into its own automatically created folder:</p><pre><code>tar -xf archive.tar.gz --one-top-level
</code></pre><p>If you prefer a custom directory name instead, specify it explicitly:</p><pre><code>tar -xf archive.tar.gz --one-top-level=archive
</code></pre><p>Finally, you don't have to extract the entire archive. To restore only specific files or directories, list them after the archive name:</p><pre><code>tar -xf archive.tar.gz path/to/file.txt docs/
</code></pre><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/07/tar-tip-command.png" class="kg-image" alt="" loading="lazy" width="1248" height="665" srcset="https://linuxhandbook.com/content/images/size/w600/2026/07/tar-tip-command.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/07/tar-tip-command.png 1000w, https://linuxhandbook.com/content/images/2026/07/tar-tip-command.png 1248w" sizes="(min-width: 720px) 720px"></figure><p>This is particularly useful when working with large source archives or backups where you only need a handful of files.</p><h2 id="%F0%9F%9B%A0%EF%B8%8F-tool-discovery">🛠️ Tool discovery</h2><p>Let's find your next favorite software in this section.</p><h3 id="darkmoon-ai-powered-autonomous-penetration-testing-platform">DarkMoon: AI-Powered Autonomous Penetration Testing Platform</h3><p><a href="https://github.com/ASCIT31/Dark-Moon?ref=linuxhandbook.com">DarkMoon</a> is an open-source platform that runs full penetration tests using AI agents that plan, execute, and validate real exploits against a target, across web apps, Active Directory, and Kubernetes.</p><p>Why use it? Well, manual pentesting takes weeks and a proper consultant costs thousands a day, and Dark-Moon automates that entire loop, from recon to a structured, evidence-backed report, using 50+ integrated tools like Nuclei, sqlmap, and BloodHound under the hood. </p><p>It also runs a local privacy gateway that keeps your real IPs, hosts, and credentials from ever reaching the LLM provider. Good fit for DevSecOps pipelines, bug bounty workflows, or just testing your own homelab exposure before someone else does. </p><p>You can <a href="https://github.com/ASCIT31/Dark-Moon?ref=linuxhandbook.com">self-host it</a> or purchase a <a href="https://dark-moon.org/?ref=linuxhandbook.com">plan from their website</a>.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/ASCIT31/Dark-Moon?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - ASCIT31/Dark-Moon: Autonomous AI pentesting engine, continuous offensive security across web, cloud, AD &amp; Kubernetes. Agentic reasoning + real exploit execution deliver proof-based vulnerabilities. Privacy gateway: the LLM never sees your real IPs, hosts, creds or paths (deterministic placeholders rehydrated locally), nothing leaves your perimeter.</div><div class="kg-bookmark-description">Autonomous AI pentesting engine, continuous offensive security across web, cloud, AD &amp;amp; Kubernetes. Agentic reasoning + real exploit execution deliver proof-based vulnerabilities. Privacy gatewa…</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/pinned-octocat-093da3e6fa40-f245d2c8-e7fd-4b0f-b7dc-bad39609d3b7.svg" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">ASCIT31</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/Dark-Moon-d9a1ee7d-8df5-46e9-8907-062f3e20702c" alt="" onerror="this.style.display = 'none'"></div></a></figure><h3 id="dashy-self-hosted-dashboard-for-homelab-and-infrastructure-services">Dashy: Self-Hosted Dashboard for Homelab and Infrastructure Services</h3><p><a href="https://github.com/Lissy93/dashy?ref=linuxhandbook.com" rel="noreferrer">Dashy</a> is an open-source, self-hosted dashboard that provides a unified homepage for accessing infrastructure services, applications, and development tools. It combines link management with service health monitoring, widgets, authentication, and extensive customization, making it a practical landing page for homelabs, self-hosted environments, and DevOps teams managing numerous services.</p><ul><li>🚦 <strong>Service Health Monitoring</strong>: Displays real-time availability and status checks for configured applications and services.</li><li>📊 <strong>Rich Widget Ecosystem</strong>: Integrates dynamic widgets for self-hosted services, system information, and external APIs to create an operational dashboard.</li><li>🎨 <strong>Highly Customizable UI</strong>: Supports multiple themes, icon packs, custom CSS, configurable layouts, and a built-in visual configuration editor.</li><li>🔍 <strong>Fast Navigation</strong>: Includes instant search, keyboard shortcuts, multiple pages, and flexible launch options for quickly accessing services.</li><li>🐳 <strong>Easy Deployment</strong>: Runs via Docker, Docker Compose, or directly from source, with support for multi-architecture container images.</li></ul><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Lissy93/dashy?ref=linuxhandbook.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - lissy93/dashy: 🚀 A self-hostable personal dashboard built for you. Includes status-checking, widgets, themes, icon packs, a UI editor and tons more!</div><div class="kg-bookmark-description">🚀 A self-hostable personal dashboard built for you. Includes status-checking, widgets, themes, icon packs, a UI editor and tons more! - lissy93/dashy</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/pinned-octocat-093da3e6fa40-827d0cec-983c-4d1a-a579-a29e6cefa93e.svg" alt=""><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">lissy93</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/82f850a2-b1af-4e9f-9245-c92700d74856-f62e909c-bf5f-4d38-967e-7bc16354f3fe" alt="" onerror="this.style.display = 'none'"></div></a></figure><h2 id="%F0%9F%93%B0-linux-news-that-matters">📰 Linux news that matters</h2><ul><li><a href="https://www.helpnetsecurity.com/2026/07/07/apple-container-open-source-linux-mac/?ref=linuxhandbook.com">Apple has released version 1.0 of its open-source Container project</a>, a Swift-based tool that runs OCI-compatible Linux containers inside lightweight virtual machines on Apple silicon Macs. The stable release introduces persistent Linux environments through the new container machine command, adopts TOML-based configuration, and adds capabilities such as host-to-container file copying while establishing a stable baseline for future development.</li><li>The German state of <a href="https://itsfoss.com/news/german-state-ditches-sharepoint/?ref=linuxhandbook.com">Mecklenburg-Vorpommern is expanding its open-source strategy</a> by rolling out a self-hosted Nextcloud platform across state and municipal administration, with a long-term target of more than 50,000 public-sector employees. The initiative replaces Microsoft SharePoint for collaboration, is operated on state-controlled infrastructure, and forms part of a broader digital sovereignty strategy that also includes OpenProject and a locally controlled AI assistant based on OpenWebUI while emphasizing open standards and European technologies.</li><li>AWS has expanded its <a href="https://www.infoq.com/news/2026/07/aws-devops-ai-agent/?ref=linuxhandbook.com">DevOps Agent with release management capabilities</a> that automatically review code changes, validate dependency impacts and access controls, and execute functional verification in managed environments before software is deployed. The enhancement moves the agent beyond troubleshooting and operations into pre-production quality assurance, positioning it as an AI-assisted release engineer integrated into the software delivery lifecycle.</li><li>Researchers at Noma Security disclosed <a href="https://devops.com/gitlost-flaw-lets-attackers-trick-github-ai-agent-into-leaking-private-repos/?ref=linuxhandbook.com">GitLost, a prompt-injection technique</a> that tricks GitHub Agentic Workflows into reading data from private repositories and publishing it in a public repository comment. The attack requires only a crafted GitHub Issue in a public repository when the organization's AI workflow has read access to private repositories, illustrating how natural-language instructions embedded in untrusted content can override the agent's intended behavior.</li></ul><h2 id="%F0%9F%98%82-geek-humor">😂 Geek humor</h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/07/meme-july-9-2026.jpg" class="kg-image" alt="" loading="lazy" width="1080" height="1080" srcset="https://linuxhandbook.com/content/images/size/w600/2026/07/meme-july-9-2026.jpg 600w, https://linuxhandbook.com/content/images/size/w1000/2026/07/meme-july-9-2026.jpg 1000w, https://linuxhandbook.com/content/images/2026/07/meme-july-9-2026.jpg 1080w" sizes="(min-width: 720px) 720px"></figure><h2 id="%F0%9F%92%8C-keep-on-loving-linux-handbook">💌 Keep on loving Linux Handbook</h2><p>GitOps course is nearly ready. It should arrive next week. </p><p>Perfect time to <a href="https://linuxhandbook.com/#/portal/signup">become a Pro member</a> and enjoy unlimited access to our <a href="https://linuxhandbook.com/ebooks/">eBooks</a>, <a href="https://linuxhandbook.com/courses/">courses</a> and in-depth tutorials.</p><p><strong>Missed the previous editions?</strong>&nbsp;You can&nbsp;<a href="https://linuxhandbook.com/newsletter/">access the newsletter archives.</a></p><p>You may also <a href="https://linuxhandbook.com/write-for-us/">contribute to Linux Handbook</a> and share your experience and expertise with the community.</p><p>I like reading your messages, so just hit the reply button and share your thoughts 😄</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[SSH Tunneling: How I Securely Access Anything From Anywhere]]></title>
                    <description><![CDATA[By default, you can only ssh into other machines on your local network. With SSH tunneling, remote connections are made possible.]]></description>
                    <link>https://linuxhandbook.com/ssh-tunneling/</link>
                    <guid isPermaLink="false">6a315dd60fd5850001a08cd0</guid>

                        <category><![CDATA[SSH Advanced]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 29 Jun 2026 17:24:26 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/06/ssh-tunneling.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/06/ssh-tunneling.png" alt="SSH Tunneling: How I Securely Access Anything From Anywhere"/> <p>There's a moment every Linux user eventually hits, you need to access something on a remote machine, but it's not exposed to the internet. Maybe it's a database running on port 5432, a local web app on port 3000, or a service hidden behind a firewall. The "obvious" solution is to punch a hole in the firewall and expose it. The <em>*right*</em> solution is SSH tunneling.</p><p>I started using SSH tunnels out of necessity. I had a PostgreSQL database running on a remote server, and the sysadmin (correctly) refused to open port 5432 to the internet. Someone in the team mentioned that I could just "tunnel through SSH" to access it. I had no idea what that meant. Twenty<em> </em>minutes<em> </em>of<em> </em>reading<em> </em>later<em>, </em>I had it working and I've been using SSH tunnels regularly ever since for everything from accessing remote services to getting around restrictive networks.</p><p>I'll walk through what SSH tunneling actually is, how each type works, how I set them up, and <strong>importantly,</strong> what the risks are and how to stay on the right side of them.</p><h2 id="what-is-ssh-tunneling"><strong>What is SSH Tunneling?</strong></h2><p>SSH (Secure Shell) is usually thought of as a way to get a remote terminal. But <a href="https://linuxhandbook.com/ssh-port-forwarding/" rel="noreferrer">SSH also has the ability to forward ports</a>; it can take network traffic on one port and route it through the encrypted SSH connection to emerge somewhere else entirely.</p><p>That's SSH tunneling in a sentence: <strong>using an SSH connection as a secure pipe to route other traffic.</strong></p><p>The traffic inside that pipe is encrypted by SSH, which means it gets the same protection as your terminal session. A service that has no encryption of its own, an old database, a plain HTTP admin panel, a Redis instance, suddenly gets full TLS-grade protection just because you're reaching it through SSH.</p><p>There are three types of SSH tunnels. Understanding which one solves your problem is most of the battle:</p><p><strong>Local forwarding:</strong> <code>-L</code> tunnel forwards a port on <em>your machine</em> to somewhere the <em>remote server</em> can reach.<br><strong>Remote forwarding:</strong> <code>-R</code> tunnel forwards a port on the <em>remote server</em> to something on <em>your machine.</em><br><strong>Dynamic forwarding:</strong> SOCKS proxy, <code>-D</code> tunnel turns the SSH connection into a proxy that routes any traffic through the remote.</p><p>Let's go through each one the way I actually use them.</p><h2 id="local-port-forwarding-accessing-remote-services-locally">Local Port Forwarding: Accessing Remote Services Locally</h2><p>This is the one I use most. Local forwarding lets me open a port on my laptop and have traffic on that port come out on the remote server, as if I'm connecting from the server itself.</p><p><strong>My exact use case:</strong> I needed to connect my local database client (DBeaver) to a PostgreSQL instance running on a remote server. Port 5432 was not open to the internet. SSH port 22 was.</p><pre><code class="language-bash">ssh -L 5433:localhost:5432 username@remote-server.example.com
</code></pre><p>Breaking this down: <code>-L</code> tells SSH we're doing local forwarding, <code>5433</code> is the port I'm opening on <em><strong>my machine,</strong></em> <code>localhost:5432</code> is where the traffic should go <em>from the remote server's perspective,</em> <code>lhb@remote-server.example.com</code> is the SSH server I'm tunneling through.</p><p>After running this, I opened DBeaver, pointed it at <code>localhost:5433</code>, and it connected to the PostgreSQL instance on the remote server, over an encrypted channel, as if the database were running locally.</p><p>The tunnel is active for as long as the SSH session stays open. When you exit, the tunnel closes. If you don't need an interactive shell, just the tunnel - add <code>-N</code> to suppress it:</p><pre><code class="language-bash">ssh -N -L 5433:localhost:5432 username@remote-server.example.com</code></pre><p>And if you want it to run in the background:</p><pre><code class="language-bash">ssh -N -f -L 5433:localhost:5432 username@remote-server.example.com</code></pre><p><code>-f</code> sends the process to the background after authenticating. The tunnel stays open without occupying your terminal.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-12.png" class="kg-image" alt="Using locally hosted docker container as remote server for example" loading="lazy" width="956" height="398" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-12.png 600w, https://linuxhandbook.com/content/images/2026/06/image-12.png 956w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Using locally hosted docker container as remote server for example</span></figcaption></figure><p>Here, I have used a <a href="https://hub.docker.com/_/postgres?ref=linuxhandbook.com" rel="noreferrer">Docker PostgreSQL</a> container to show the SSH connection to the remote server.</p><h2 id="remote-port-forwarding-exposing-your-local-machine-to-the-world">Remote Port Forwarding: Exposing Your Local Machine to the World</h2><p>Remote forwarding is local forwarding in reverse. Instead of bringing a remote service to me, I'm pushing something on my machine out to a remote server.</p><p><strong>My use case for this:</strong> I was developing a webhook receiver locally. The service I needed to receive webhooks from (a payment processor) needed a public URL to send to. My development machine is behind NAT, with no public IP. I had a cheap VPS with a public IP. Remote forwarding solved it.</p><pre><code class="language-bash">ssh -R 8080:localhost:3000 username@my-vps.example.com</code></pre><p>Here, <code>-R</code> for remote forwarding, <code>8080</code> is the port that opens on the <strong><em>remote server, </em></strong><code>localhost:3000</code> is where traffic on that remote port gets forwarded, back to my machine, port 3000.</p><p>After running this, anyone hitting <code>my-vps.example.com:8080</code> would have their request tunneled back to port 3000 on my laptop. My local dev server was now reachable from the internet, through an encrypted SSH connection. For the example I have setup the container for the vps as:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-14.png" class="kg-image" alt="VPS container running for reverse tunnel" loading="lazy" width="778" height="571" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-14.png 600w, https://linuxhandbook.com/content/images/2026/06/image-14.png 778w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">VPS container running for reverse tunnel</span></figcaption></figure><p>The VPS container is running for reverse tunneling for the requests that are coming.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-15.png" class="kg-image" alt="simulate external request to vps:8080" loading="lazy" width="1040" height="578" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-15.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/06/image-15.png 1000w, https://linuxhandbook.com/content/images/2026/06/image-15.png 1040w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">simulate external request to vps:8080</span></figcaption></figure><p>curl from inside the container simulates the external request to the vps:8080 endpoint.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-16.png" class="kg-image" alt="python server logs" loading="lazy" width="790" height="243" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-16.png 600w, https://linuxhandbook.com/content/images/2026/06/image-16.png 790w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">python server logs</span></figcaption></figure><p>Python server verifying and logging the connected request from the internet that comes to the VPS and then to the <code>localhost:3000</code></p><p><strong>When to use this:</strong> Remote forwarding is incredibly useful for quick webhook testing, sharing a local demo with a client, or giving someone remote access to something on your internal network without setting up a VPN.</p><h2 id="dynamic-port-forwarding-ssh-as-a-socks-proxy">Dynamic Port Forwarding: SSH as a SOCKS Proxy</h2><p>Dynamic forwarding is the most flexible of the three. Instead of forwarding a specific port to a specific destination, it creates a <a href="https://en.wikipedia.org/wiki/SOCKS?ref=linuxhandbook.com">SOCKS proxy</a> on your machine. Any application that supports SOCKS proxies can route all its traffic through your SSH connection and it will appear as if that traffic is coming from the remote server.</p><p>Command that can be used:</p><pre><code class="language-bash">ssh -D 1080 -N yash@remote-server.example.com</code></pre><p>This opens a SOCKS5 proxy on <code>localhost:1080</code> on my machine. Any traffic I route through that proxy goes through the SSH tunnel and exits from <code>remote-server.example.com</code>.</p><p>I have used it as:</p><pre><code class="language-bash">ssh -f -D 1080 -N \
  -i ~/ITSFOSS/REVIEW/SSH\ Tunneling/docker-demo/demo_key \
  -p 2223 -o StrictHostKeyChecking=no \
  vpsuser@localhost
ss -tlnp | grep 1080</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-17.png" class="kg-image" alt="proxy is bound to localhost:1080" loading="lazy" width="772" height="242" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-17.png 600w, https://linuxhandbook.com/content/images/2026/06/image-17.png 772w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">proxy is bound to localhost:1080</span></figcaption></figure><p>Then I can setup the network proxy through the network settings as:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-18.png" class="kg-image" alt="Network SOCKS proxy setup" loading="lazy" width="922" height="547" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-18.png 600w, https://linuxhandbook.com/content/images/2026/06/image-18.png 922w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Network SOCKS proxy setup</span></figcaption></figure><p>Then, you need to set up the SOCKS proxy through the network settings.</p><p><strong>When to use this:</strong> When you are in a coffee shop with WiFi and want to encrypt all your browsing, you need to access something that's only reachable from a specific server (e.g., an internal admin panel that only allows connections from the VPS's IP), or you want to test how your website looks from the perspective of another geographic location.</p><h2 id="making-tunnels-persistent">Making Tunnels Persistent</h2><p>Running long <code>ssh -L ...</code> commands every time is annoying. I put my common tunnels in <code>~/.ssh/config</code> so I can activate them with a short alias:</p><pre><code class="language-bash">Host db-tunnel
    HostName remote-server.example.com
    User yash
    LocalForward 5433 localhost:5432
    ServerAliveInterval 60
    ServerAliveCountMax 3

Host socks-proxy
    HostName my-vps.example.com
    User yash
    DynamicForward 1080
    ServerAliveInterval 60
    ServerAliveCountMax 3</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/06/image-19.png" class="kg-image" alt="config at ~/.ssh/config" loading="lazy" width="777" height="543" srcset="https://linuxhandbook.com/content/images/size/w600/2026/06/image-19.png 600w, https://linuxhandbook.com/content/images/2026/06/image-19.png 777w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">config at ~/.ssh/config</span></figcaption></figure><p>Now activating the database tunnel is just:</p><pre><code class="language-bash">ssh -N db-tunnel</code></pre><p>And the SOCKS proxy:</p><pre><code class="language-bash">ssh -N socks-proxy</code></pre><h2 id="the-risks-and-how-to-handle-them">The Risks And How to Handle Them</h2><p>SSH tunneling is powerful, and like most powerful tools, it can cause problems if misused or misconfigured. This is the part most tutorials skip.</p><h3 id="risk-1-unauthorized-tunnel-creation">Risk 1: Unauthorized Tunnel Creation</h3><p>The flip side of remote forwarding (<code>-R</code>) is that if someone has SSH access to your server, they can open tunnels out of it, potentially bypassing your network security controls. An attacker with a compromised SSH key could use your server as a relay to reach systems inside your network.</p><p><strong>Mitigation:</strong> Restrict what SSH users can do. In <code>/etc/ssh/sshd_config</code>:</p><pre><code class="language-bash"># Disable port forwarding for all users by default
AllowTcpForwarding no
GatewayPorts no

# Then allow it only for specific trusted users:
Match User deploy-user
    AllowTcpForwarding local</code></pre><p>Use SSH keys (not passwords), enforce key-based auth only, and audit your <code>~/.ssh/authorized_keys</code> files regularly.</p><h3 id="risk-2-tunnel-misuse-on-corporatemanaged-networks">Risk 2: Tunnel Misuse on Corporate/Managed Networks</h3><p>Dynamic SSH tunneling (<code>-D</code>) is a common technique for bypassing network monitoring and content filters. On a corporate or university network, using a SOCKS proxy to route traffic through an external server may violate acceptable use policies, even if you have a legitimate reason.</p><p>I use it when I'm on untrusted public WiFi to protect my own traffic, which is reasonable. Using it to bypass your employer's security controls on company equipment is a different matter; read your acceptable use policy, and don't be surprised if your IT team can see that you're making an encrypted SSH connection to an external server even if they can't see inside it.</p><h3 id="risk-3-exposing-tunnels-beyond-localhost">Risk 3: Exposing Tunnels Beyond Localhost</h3><p>When you run <code>-L 5433:localhost:5432</code>, by default the tunnel binds to <code>127.0.0.1</code> on your machine, only you can use it. But if you bind it to <code>0.0.0.0</code>, anyone on your local network (or beyond) can use that forwarded port to reach the remote service.</p><pre><code class="language-bash"># DANGEROUS — binds to all interfaces
ssh -L 0.0.0.0:5433:localhost:5432 user@remote-server.example.com</code></pre><p>Unless you specifically need to share a tunnel with other people on your network, always let the tunnel bind to <code>127.0.0.1</code> (the default). You can explicitly enforce this:</p><pre><code class="language-bash"># Safe — explicitly binds to loopback only
ssh -L 127.0.0.1:5433:localhost:5432 user@remote-server.example.com</code></pre><h3 id="risk-4-keeping-ssh-keys-secure">Risk 4: Keeping SSH Keys Secure</h3><p>All of this relies on the security of your SSH keys. If your private key is stolen, your tunnels and everything behind them are compromised.</p><p><strong>My key hygiene:</strong> Use <code>ssh-keygen -t ed25519</code> for new keys, as Ed25519 keys are smaller, faster, and considered stronger than RSA-4096 for most use cases, always set a passphrase on private keys, use <code>ssh-agent</code> to avoid retyping the passphrase constantly while keeping the key protected at rest, never share private keys or put them in version control.</p><pre><code class="language-bash"># Generate a new Ed25519 key with a passphrase
ssh-keygen -t ed25519 -C "yash@workstation" -f ~/.ssh/id_ed25519_tunnel

# Add it to ssh-agent so you don't retype the passphrase every session
ssh-add ~/.ssh/id_ed25519_tunnel
```
</code></pre><h2 id="a-quick-reference-when-to-use-which-tunnel">A Quick Reference: When to Use Which Tunnel</h2><table>
<thead>
<tr>
<th>Situation</th>
<th>Tunnel type</th>
<th>Command pattern</th>
</tr>
</thead>
<tbody>
<tr>
<td>Access a remote database or service locally</td>
<td>Local <code>-L</code></td>
<td><code>ssh -L localport:host:remoteport user@server</code></td>
</tr>
<tr>
<td>Share a local dev server with the internet</td>
<td>Remote <code>-R</code></td>
<td><code>ssh -R remoteport:localhost:localport user@server</code></td>
</tr>
<tr>
<td>Encrypt all browsing on untrusted WiFi</td>
<td>Dynamic <code>-D</code></td>
<td><code>ssh -D 1080 -N user@server</code></td>
</tr>
</tbody>
</table>
<h2 id="wrapping-up">Wrapping Up</h2><p>What I like about SSH tunneling is that it solves real problems without adding infrastructure. No VPN server to configure, no WireGuard keypairs to exchange, no nginx proxy rules to write. The SSH connection you already use for server access can also carry your database traffic, your webhook traffic, or your browsing traffic, all encrypted, all without opening extra firewall ports.</p><p>Local forwarding (<code>-L</code>) is the one I reach for most often, any time I need to access a service on a remote machine from a local client. Remote forwarding (<code>-R</code>) is what I use when I need to do the reverse: expose something local to the internet temporarily. Dynamic forwarding (<code>-D</code>) is the occasional privacy tool for when I'm not on a network I trust.</p><p>The risks are real but manageable: keep port forwarding locked down on your SSH servers, bind tunnels to localhost unless you have a specific reason not to, and treat your SSH keys with the same care you'd give a password.</p><p>The setup is one command. The maintenance is minimal. The usefulness compounds the more remote infrastructure you work with.</p>]]></content:encoded>
                </item>
    </channel>
</rss>