<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>storage devices Archives | Abdul Wahab Junaid</title>
	<atom:link href="https://awjunaid.com/tag/storage-devices/feed/" rel="self" type="application/rss+xml" />
	<link>https://awjunaid.com/tag/storage-devices/</link>
	<description>Offensive Security Researcher &#38; Quantum Cryptography Analyst</description>
	<lastBuildDate>Sat, 01 Aug 2026 00:35:12 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://i0.wp.com/awjunaid.com/wp-content/uploads/2023/06/cropped-1668274976669.jpeg?fit=32%2C32&#038;ssl=1</url>
	<title>storage devices Archives | Abdul Wahab Junaid</title>
	<link>https://awjunaid.com/tag/storage-devices/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">220030102</site>	<item>
		<title>How to Export a File System with NFS in Linux</title>
		<link>https://awjunaid.com/networking/how-to-export-file-system-with-nfs-in-linux/</link>
					<comments>https://awjunaid.com/networking/how-to-export-file-system-with-nfs-in-linux/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Mon, 24 Jul 2023 02:22:43 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=3456</guid>

					<description><![CDATA[<p>Imagine you have a directory full of important project files on one Linux server, and you want multiple&#8230;</p>
<p>The post <a href="https://awjunaid.com/networking/how-to-export-file-system-with-nfs-in-linux/">How to Export a File System with NFS in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Imagine you have a directory full of important project files on one Linux server, and you want multiple other computers on your network to access those files as if they were stored locally, without copying them around manually. This is exactly what <strong>NFS (Network File System)</strong> allows you to do. The process of making a local directory available to remote clients over NFS is called <strong>exporting a file system</strong>.</p>



<p class="wp-block-paragraph">In this article, we&#8217;ll explain what NFS is, how exporting works from first principles, and walk through the complete process of configuring an NFS export on Linux, step by step, with troubleshooting and best practices.</p>



<h2 class="wp-block-heading">Table of Contents</h2>



<ol class="wp-block-list">
<li>What Is NFS?</li>



<li>How Does NFS Work Under the Hood?</li>



<li>What Does &#8220;Exporting&#8221; a File System Mean?</li>



<li>Prerequisites</li>



<li>Step-by-Step: Installing NFS Server</li>



<li>Step-by-Step: Creating and Configuring the Export</li>



<li>Understanding the /etc/exports File Syntax</li>



<li>Applying and Verifying Exports</li>



<li>Firewall Configuration</li>



<li>NFS Versions Explained</li>



<li>Real-World Example</li>



<li>Cisco/Network Context</li>



<li>Python Example: Checking NFS Export Availability</li>



<li>Comparison Table: NFS Export Options</li>



<li>Best Practices</li>



<li>Troubleshooting Common Issues</li>



<li>Conclusion</li>
</ol>



<h2 class="wp-block-heading">1. What Is NFS?</h2>



<p class="wp-block-paragraph"><strong>NFS (Network File System)</strong> is a distributed file system protocol, originally developed by Sun Microsystems, that allows a computer (the <strong>NFS server</strong>) to share directories over a network so that other computers (<strong>NFS clients</strong>) can mount and access those directories as though they were part of their own local file system.</p>



<p class="wp-block-paragraph">Unlike simply copying files between machines, NFS provides <strong>live, real-time access</strong> — when a file changes on the server, every client sees the change immediately, because they&#8217;re all reading from the same underlying storage.</p>



<h2 class="wp-block-heading">2. How Does NFS Work Under the Hood?</h2>



<p class="wp-block-paragraph">NFS operates using a client-server model over the network, historically relying on <strong>RPC (Remote Procedure Call)</strong> to communicate between the client and server. When a client wants to read or write a file:</p>



<ol class="wp-block-list">
<li>The client sends an RPC request to the NFS server, referencing the exported directory and the desired file operation (read, write, list, etc.).</li>



<li>The server checks whether the client is authorized to access that export (based on IP address, hostname, or network range).</li>



<li>The server performs the operation on the actual file system and sends the result back to the client.</li>



<li>The client&#8217;s operating system presents this remote directory to local applications exactly like a normal local folder.</li>
</ol>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">sequenceDiagram
    participant Client as NFS Client
    participant Server as NFS Server
    participant Disk as Local Disk (Server)

    Client->>Server: Mount request for /shared
    Server->>Server: Check /etc/exports permissions
    Server->>Client: Mount granted
    Client->>Server: Read file request
    Server->>Disk: Fetch file data
    Disk->>Server: Return file data
    Server->>Client: File data returned</pre></div>



<h2 class="wp-block-heading">3. What Does &#8220;Exporting&#8221; a File System Mean?</h2>



<p class="wp-block-paragraph"><strong>Exporting</strong> is the process, performed on the <strong>NFS server</strong>, of declaring which local directories are available for remote clients to mount, and defining the rules for who can access them and what permissions they have (read-only, read-write, etc.). This is configured in a special file called <code>/etc/exports</code>.</p>



<p class="wp-block-paragraph">Think of exporting as &#8220;publishing&#8221; a folder to the network with a specific access policy — similar to sharing a folder in Windows, but using the NFS protocol instead of SMB.</p>



<h2 class="wp-block-heading">4. Prerequisites</h2>



<p class="wp-block-paragraph">Before exporting a file system with NFS, you need:</p>



<ul class="wp-block-list">
<li>A Linux server (Ubuntu, Debian, CentOS, RHEL, etc.) that will act as the NFS server.</li>



<li>Root or <code>sudo</code> access on that server.</li>



<li>A directory you want to share (e.g., <code>/srv/nfs/shared</code>).</li>



<li>Basic knowledge of the client machines&#8217; IP addresses or subnet that should be allowed access.</li>



<li>An open network path between server and clients (typically port 2049 for NFS).</li>
</ul>



<h2 class="wp-block-heading">5. Step-by-Step: Installing NFS Server</h2>



<p class="wp-block-paragraph"><strong>On Ubuntu/Debian-based systems:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo apt update
sudo apt install nfs-kernel-server -y</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">update</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-kernel-server</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>On CentOS/RHEL/Fedora-based systems:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo dnf install nfs-utils -y
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dnf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-utils</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Start and enable the NFS service so it runs on boot</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo systemctl start nfs-server
sudo systemctl enable nfs-server
sudo systemctl status nfs-server</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">systemctl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">start</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-server</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">systemctl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">enable</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-server</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">systemctl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">status</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-server</span></span></code></pre></div>



<h2 class="wp-block-heading">6. Step-by-Step: Creating and Configuring the Export</h2>



<p class="wp-block-paragraph"><strong>Step 1: Create the directory you want to share.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo mkdir -p /srv/nfs/shared</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/srv/nfs/shared</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Step 2: Set appropriate ownership and permissions.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo chown nobody:nogroup /srv/nfs/shared   # Ubuntu/Debian
sudo chown nobody:nobody /srv/nfs/shared    # CentOS/RHEL
sudo chmod 755 /srv/nfs/shared</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">chown</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nobody:nogroup</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/srv/nfs/shared</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88"># Ubuntu/Debian</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">chown</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nobody:nobody</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/srv/nfs/shared</span><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># CentOS/RHEL</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">chmod</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">755</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/srv/nfs/shared</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Step 3: Edit the <code>/etc/exports</code> file to declare the export.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo nano /etc/exports</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nano</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/etc/exports</span></span></code></pre></div>



<p class="wp-block-paragraph">Add a line like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/srv/nfs/shared    192.168.1.0/24(rw,sync,no_subtree_check)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">/srv/nfs/shared</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.0/24</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">rw,sync,no_subtree_check</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph">This line tells the NFS server: &#8220;Export the <code>/srv/nfs/shared</code> directory to any client on the <code>192.168.1.0/24</code> subnet, allow read-write access, use synchronous writes, and don&#8217;t check subtree permissions.&#8221;</p>



<h2 class="wp-block-heading">7. Understanding the /etc/exports File Syntax</h2>



<p class="wp-block-paragraph">The general syntax of an entry in <code>/etc/exports</code> is:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;directory>   &lt;client_specification>(&lt;options>)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF">directory</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">   </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF">client_specification</span><span style="color: #ECEFF4">&gt;(</span><span style="color: #81A1C1">&lt;</span><span style="color: #A3BE8C">options</span><span style="color: #81A1C1">&gt;</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Common client specifications:</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Specification</th><th>Meaning</th></tr></thead><tbody><tr><td><code>192.168.1.10</code></td><td>A single specific client IP</td></tr><tr><td><code>192.168.1.0/24</code></td><td>An entire subnet</td></tr><tr><td><code>*.example.com</code></td><td>Any host matching this DNS wildcard</td></tr><tr><td><code>*</code></td><td>Any client (not recommended for security reasons)</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Common export options:</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Option</th><th>Meaning</th></tr></thead><tbody><tr><td><code>rw</code></td><td>Read-write access</td></tr><tr><td><code>ro</code></td><td>Read-only access</td></tr><tr><td><code>sync</code></td><td>Writes are committed to disk before responding to the client (safer, slightly slower)</td></tr><tr><td><code>async</code></td><td>Writes are acknowledged before being committed to disk (faster, riskier on crash)</td></tr><tr><td><code>no_subtree_check</code></td><td>Disables subtree checking, improving reliability</td></tr><tr><td><code>root_squash</code></td><td>Maps remote root user to an unprivileged user (default, more secure)</td></tr><tr><td><code>no_root_squash</code></td><td>Allows remote root user to have root privileges on the export (use with caution)</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">8. Applying and Verifying Exports</h2>



<p class="wp-block-paragraph"><strong>Apply the changes without restarting the whole service:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo exportfs -ra</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">exportfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-ra</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>View all currently active exports:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo exportfs -v</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">exportfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-v</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Sample output:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/srv/nfs/shared  192.168.1.0/24(rw,wdelay,root_squash,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">/srv/nfs/shared</span><span style="color: #D8DEE9FF">  </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.0/24</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">rw,wdelay,root_squash,no_subtree_check,sec</span><span style="color: #D8DEE9FF">=sys,rw,secure,root_squash,no_all_squash</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Verify the NFS server is listening on the correct port:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo ss -tulnp | grep nfs</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ss</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-tulnp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">grep</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs</span></span></code></pre></div>



<h2 class="wp-block-heading">9. Firewall Configuration</h2>



<p class="wp-block-paragraph">NFS uses several ports, primarily <strong>2049 (TCP/UDP)</strong>, along with additional ports for related services like <code>rpcbind</code> and <code>mountd</code>.</p>



<p class="wp-block-paragraph"><strong>On systems using <code>firewalld</code> (CentOS/RHEL):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --permanent --add-service=rpc-bind
sudo firewall-cmd --permanent --add-service=mountd
sudo firewall-cmd --reload</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">firewall-cmd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--permanent</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--add-service=nfs</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">firewall-cmd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--permanent</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--add-service=rpc-bind</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">firewall-cmd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--permanent</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--add-service=mountd</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">firewall-cmd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--reload</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>On systems using <code>ufw</code> (Ubuntu/Debian):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo ufw allow from 192.168.1.0/24 to any port nfs</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ufw</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">allow</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.0/24</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">any</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">port</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs</span></span></code></pre></div>



<h2 class="wp-block-heading">10. NFS Versions Explained</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Version</th><th>Key Characteristics</th></tr></thead><tbody><tr><td>NFSv2</td><td>Legacy, rarely used today, 32-bit file size limits</td></tr><tr><td>NFSv3</td><td>Widely supported, supports larger files, still requires <code>rpcbind</code></td></tr><tr><td>NFSv4</td><td>Stateful protocol, integrated security (Kerberos support), works over a single port (2049), no longer requires <code>rpcbind</code> for basic operation</td></tr><tr><td>NFSv4.1/4.2</td><td>Adds performance improvements like parallel NFS (pNFS), server-side copy, sparse file support</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Modern deployments should prefer <strong>NFSv4</strong> for its simplified firewall requirements (single port) and improved security model.</p>



<h2 class="wp-block-heading">11. Real-World Example</h2>



<p class="wp-block-paragraph">A university research lab has a central Linux server storing large genomic datasets. Instead of copying multi-gigabyte files to every researcher&#8217;s workstation, the lab administrator exports the dataset directory via NFS:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/data/genomics    10.10.20.0/24(ro,sync,no_subtree_check)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">/data/genomics</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">10.10</span><span style="color: #A3BE8C">.20.0/24</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">ro,sync,no_subtree_check</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph">Every workstation on the <code>10.10.20.0/24</code> subnet can now mount <code>/data/genomics</code> as read-only, allowing dozens of researchers to analyze the same dataset simultaneously without duplicating storage.</p>



<h3 class="wp-block-heading">Extended Example: Multi-Tier Access for a Media Production Team</h3>



<p class="wp-block-paragraph">A video production company stores raw footage, editing project files, and final rendered exports on a central Linux storage server. Different teams need different levels of access:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/srv/nfs/raw-footage      192.168.10.0/24(ro,sync,no_subtree_check)
/srv/nfs/editing-projects 192.168.10.0/24(rw,sync,no_subtree_check)
/srv/nfs/final-renders    192.168.10.50(rw,sync,no_subtree_check)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">/srv/nfs/raw-footage</span><span style="color: #D8DEE9FF">      </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.10.0/24</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">ro,sync,no_subtree_check</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #88C0D0">/srv/nfs/editing-projects</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.10.0/24</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">rw,sync,no_subtree_check</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #88C0D0">/srv/nfs/final-renders</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.10.50</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">rw,sync,no_subtree_check</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph">Here, the entire editing subnet has read-only access to raw footage (protecting original camera files from accidental modification), read-write access to active editing projects, and only the rendering workstation (<code>192.168.10.50</code>) has write access to the final renders directory — a practical illustration of how granular, per-directory export rules support real production workflows.</p>



<h2 class="wp-block-heading">12. Cisco/Network Context</h2>



<p class="wp-block-paragraph">While Cisco switches and routers don&#8217;t run NFS themselves, they are responsible for ensuring the network path between NFS clients and the server is reliable, since NFS is sensitive to packet loss and latency (especially with <code>sync</code> writes). Network administrators should ensure:</p>



<p class="wp-block-paragraph"><strong>QoS prioritization for NFS traffic on a Cisco switch (example, marking NFS traffic for priority handling):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Switch(config)# access-list 101 permit tcp any any eq 2049
Switch(config)# class-map match-all NFS-TRAFFIC
Switch(config-cmap)# match access-group 101
Switch(config-cmap)# exit
Switch(config)# policy-map QOS-POLICY
Switch(config-pmap)# class NFS-TRAFFIC
Switch(config-pmap-c)# priority percent 30</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">Switch(config</span><span style="color: #D8DEE9FF">)# access-list 101 permit tcp any any eq 2049</span></span>
<span class="line"><span style="color: #88C0D0">Switch(config</span><span style="color: #D8DEE9FF">)# class-map match-all NFS-TRAFFIC</span></span>
<span class="line"><span style="color: #88C0D0">Switch(config-cmap</span><span style="color: #D8DEE9FF">)# match access-group 101</span></span>
<span class="line"><span style="color: #88C0D0">Switch(config-cmap</span><span style="color: #D8DEE9FF">)# exit</span></span>
<span class="line"><span style="color: #88C0D0">Switch(config</span><span style="color: #D8DEE9FF">)# policy-map QOS-POLICY</span></span>
<span class="line"><span style="color: #88C0D0">Switch(config-pmap</span><span style="color: #D8DEE9FF">)# class NFS-TRAFFIC</span></span>
<span class="line"><span style="color: #88C0D0">Switch(config-pmap-c</span><span style="color: #D8DEE9FF">)# priority percent 30</span></span></code></pre></div>



<p class="wp-block-paragraph">This ensures NFS traffic (port 2049) receives prioritized bandwidth on a congested network, which is especially important in environments like the CAN/MAN networks discussed in earlier articles.</p>



<h2 class="wp-block-heading">13. Python Example: Checking NFS Export Availability</h2>



<p class="wp-block-paragraph">The following Python script uses a simple socket check to verify whether the NFS port (2049) is open and reachable on the server before a client attempts to mount it — a handy pre-flight check.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import socket

def check_nfs_port(server_ip, port=2049, timeout=3):
    try:
        with socket.create_connection((server_ip, port), timeout=timeout):
            return True
    except (socket.timeout, ConnectionRefusedError, OSError):
        return False

server_ip = "192.168.1.100"

if check_nfs_port(server_ip):
    print(f"NFS server at {server_ip} is reachable on port 2049.")
else:
    print(f"NFS server at {server_ip} is NOT reachable on port 2049. Check firewall/service status.")</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> socket</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">check_nfs_port</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">server_ip</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">port</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">2049</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">timeout</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">3</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">try</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> socket</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">create_connection</span><span style="color: #ECEFF4">((</span><span style="color: #D8DEE9FF">server_ip</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> port</span><span style="color: #ECEFF4">),</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">timeout</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">timeout</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">True</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">except</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">socket</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">timeout</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">ConnectionRefusedError</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">OSError</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">False</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">server_ip </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">192.168.1.100</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">check_nfs_port</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">server_ip</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">print</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;NFS server at </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">server_ip</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C"> is reachable on port 2049.&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">print</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;NFS server at </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">server_ip</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C"> is NOT reachable on port 2049. Check firewall/service status.&quot;</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Sample Output:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>NFS server at 192.168.1.100 is reachable on port 2049.</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">NFS</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">server</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">at</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.100</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">reachable</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">on</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">port</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2049</span><span style="color: #A3BE8C">.</span></span></code></pre></div>



<h2 class="wp-block-heading">14. Comparison Table: NFS Export Options</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Option</th><th>Use Case</th><th>Security Impact</th></tr></thead><tbody><tr><td><code>ro</code></td><td>Sharing reference data, documentation</td><td>Safest, prevents accidental modification</td></tr><tr><td><code>rw</code></td><td>Collaborative work directories</td><td>Requires trust in client network</td></tr><tr><td><code>root_squash</code></td><td>Default for most exports</td><td>Prevents remote root from having full server access</td></tr><tr><td><code>no_root_squash</code></td><td>Backup servers needing full file permissions</td><td>Higher risk, use only on trusted internal networks</td></tr><tr><td><code>sync</code></td><td>Financial/critical data</td><td>Safer, slightly slower writes</td></tr><tr><td><code>async</code></td><td>Temporary/scratch data</td><td>Faster, risk of data loss on crash</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">15. Best Practices</h2>



<ul class="wp-block-list">
<li><strong>Always restrict exports to specific subnets or IPs</strong> — never use <code>*</code> in production environments.</li>



<li><strong>Prefer <code>root_squash</code></strong> unless you have a specific, well-understood reason to disable it.</li>



<li><strong>Use NFSv4</strong> where possible for simplified firewall rules and better security (Kerberos support).</li>



<li><strong>Combine NFS with proper firewall rules</strong>, restricting access to only the necessary client subnet.</li>



<li><strong>Regularly back up <code>/etc/exports</code></strong> and version-control it if managing multiple NFS servers.</li>



<li><strong>Monitor NFS server load</strong> using tools like <code>nfsstat</code> to catch performance bottlenecks early.</li>
</ul>



<h2 class="wp-block-heading">16. Troubleshooting Common Issues</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Issue</th><th>Cause</th><th>Fix</th></tr></thead><tbody><tr><td><code>mount.nfs: Connection timed out</code></td><td>Firewall blocking port 2049 or server not running</td><td>Check <code>systemctl status nfs-server</code>, verify firewall rules</td></tr><tr><td><code>mount.nfs: access denied by server</code></td><td>Client IP not included in <code>/etc/exports</code></td><td>Add correct client/subnet to the export entry, run <code>exportfs -ra</code></td></tr><tr><td>Changes to <code>/etc/exports</code> not taking effect</td><td>Forgot to re-export</td><td>Run <code>sudo exportfs -ra</code> after every edit</td></tr><tr><td>Slow NFS performance</td><td>Using <code>sync</code> on high-write workloads, or network congestion</td><td>Consider <code>async</code> for non-critical data, check network QoS</td></tr><tr><td>&#8220;No such file or directory&#8221; on client mount</td><td>Exported path doesn&#8217;t exist or was mistyped</td><td>Verify directory exists with <code>ls -ld /srv/nfs/shared</code> on the server</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Quick diagnostic commands:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo exportfs -v                  # List all current exports
sudo systemctl status nfs-server  # Check NFS service status
rpcinfo -p localhost              # Check registered RPC services (NFSv3)
showmount -e localhost            # Show exports as seen locally</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">exportfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-v</span><span style="color: #D8DEE9FF">                  </span><span style="color: #616E88"># List all current exports</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">systemctl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">status</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-server</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88"># Check NFS service status</span></span>
<span class="line"><span style="color: #88C0D0">rpcinfo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">localhost</span><span style="color: #D8DEE9FF">              </span><span style="color: #616E88"># Check registered RPC services (NFSv3)</span></span>
<span class="line"><span style="color: #88C0D0">showmount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">localhost</span><span style="color: #D8DEE9FF">            </span><span style="color: #616E88"># Show exports as seen locally</span></span></code></pre></div>



<h2 class="wp-block-heading">17. Advanced Concepts: NFS Security Hardening</h2>



<p class="wp-block-paragraph">Beyond basic export configuration, production NFS deployments benefit from additional security layers that go further than the default <code>root_squash</code> and subnet restrictions covered earlier.</p>



<h3 class="wp-block-heading">Using Kerberos with NFSv4 (sec=krb5)</h3>



<p class="wp-block-paragraph">By default, NFS authenticates clients purely based on their IP address (<code>sec=sys</code>), which offers no real user-level authentication or encryption — anyone who can spoof or gain access to a trusted IP can potentially access the export. <strong>NFSv4 with Kerberos</strong> (<code>sec=krb5</code>, <code>sec=krb5i</code> for integrity checking, or <code>sec=krb5p</code> for full encryption) adds proper cryptographic authentication of individual users, not just client machines.</p>



<p class="wp-block-paragraph"><strong>Example export line using Kerberos-based security:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/srv/nfs/secure    192.168.1.0/24(rw,sec=krb5p,no_subtree_check)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">/srv/nfs/secure</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.0/24</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">rw,sec</span><span style="color: #D8DEE9FF">=krb5p,no_subtree_check</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph">This configuration requires clients to authenticate via a Kerberos ticket and encrypts all NFS traffic (<code>krb5p</code>), providing both authentication and confidentiality — a significant security upgrade over the default IP-based trust model.</p>



<h3 class="wp-block-heading">Restricting Exports with TCP Wrappers and Firewalls</h3>



<p class="wp-block-paragraph">In addition to the access rules defined directly in <code>/etc/exports</code>, administrators should layer host-based firewall rules (via <code>iptables</code>, <code>nftables</code>, or <code>firewalld</code>) to ensure that even if <code>/etc/exports</code> is ever misconfigured, unauthorized networks cannot reach the NFS ports at all. Defense in depth — combining application-level (<code>/etc/exports</code>) and network-level (firewall) restrictions — is a core security best practice.</p>



<h3 class="wp-block-heading">Read-Only Root Exports for Immutable Data</h3>



<p class="wp-block-paragraph">For directories containing reference data, installation media, or compliance archives that should never change, exporting with <code>ro</code> (read-only) at the NFS level, combined with filesystem-level immutability (<code>chattr +i</code> on Linux), provides two independent layers of protection against accidental or malicious modification.</p>



<h2 class="wp-block-heading">18. NFS vs. Other File Sharing Protocols</h2>



<p class="wp-block-paragraph">It&#8217;s useful to understand how NFS compares to alternative file-sharing protocols, since the right choice depends heavily on your operating system mix and use case.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Protocol</th><th>Best For</th><th>Native OS Support</th></tr></thead><tbody><tr><td>NFS</td><td>Linux/Unix-to-Linux/Unix file sharing</td><td>Native on Linux/Unix, requires additional software on Windows</td></tr><tr><td>SMB/CIFS</td><td>Mixed Windows/Linux/macOS environments</td><td>Native on Windows, well-supported everywhere else</td></tr><tr><td>SSHFS</td><td>Quick, ad-hoc secure mounts over SSH</td><td>Works anywhere SSH is available, no dedicated server needed</td></tr><tr><td>iSCSI</td><td>Block-level storage (acts like a local disk, not a shared folder)</td><td>Requires an initiator on the client and a target on the server</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">NFS remains the preferred choice in Linux-heavy environments — data centers, research clusters, and container storage backends — due to its maturity, performance, and tight integration with Unix-style permissions.</p>



<h2 class="wp-block-heading">19. Monitoring and Auditing NFS Exports Over Time</h2>



<p class="wp-block-paragraph">Once an NFS export is live in production, ongoing monitoring is essential to catch performance degradation, unauthorized access attempts, or configuration drift before they become serious problems.</p>



<p class="wp-block-paragraph"><strong>Monitor active NFS connections and operation counts:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo nfsstat -s</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfsstat</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span></span></code></pre></div>



<p class="wp-block-paragraph">This command displays server-side statistics, including counts of read/write calls, and can help identify unusually high load from a specific client subnet.</p>



<p class="wp-block-paragraph"><strong>Audit who is currently connected to your NFS exports:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo ss -tn | grep :2049</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ss</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-tn</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">grep</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">:2049</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Log NFS mount and unmount events for auditing purposes</strong> by enabling verbose logging in <code>rpc.mountd</code> (part of the <code>nfs-utils</code> package), which records every client that mounts an export, along with the timestamp — valuable for security audits in regulated environments.</p>



<p class="wp-block-paragraph"><strong>Periodically review <code>/etc/exports</code> for drift:</strong></p>



<p class="wp-block-paragraph">Configuration drift — where the live export rules on a server slowly diverge from documented policy due to ad-hoc changes — is a common issue in long-running infrastructure. Storing <code>/etc/exports</code> in a version-controlled configuration management system (Ansible, Puppet, or even a simple Git repository) ensures every change is tracked, reviewed, and reversible.</p>



<h2 class="wp-block-heading">20. Frequently Asked Questions</h2>



<p class="wp-block-paragraph"><strong>Can I export the same directory to different clients with different permissions?</strong></p>



<p class="wp-block-paragraph">Yes. You can add multiple lines in <code>/etc/exports</code> for the same directory, each specifying a different client or subnet with its own options. For example, you might grant <code>rw</code> access to your internal admin subnet while granting only <code>ro</code> access to a broader internal network.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/srv/nfs/shared    192.168.1.0/24(ro,sync,no_subtree_check)
/srv/nfs/shared    192.168.1.50(rw,sync,no_subtree_check)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">/srv/nfs/shared</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.0/24</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">ro,sync,no_subtree_check</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #88C0D0">/srv/nfs/shared</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.50</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">rw,sync,no_subtree_check</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>What happens if the NFS server goes offline while clients have it mounted?</strong></p>



<p class="wp-block-paragraph">Depending on the mount options used, client applications accessing the share may hang indefinitely (<code>hard</code> mount, the default) until the server returns, or fail immediately with an I/O error (<code>soft</code> mount). For most production use cases, <code>hard</code> mounts are preferred despite the temporary hang, because <code>soft</code> mounts risk silent data corruption if a write operation is interrupted mid-transfer.</p>



<p class="wp-block-paragraph"><strong>Is NFS suitable for storing a live database&#8217;s data files?</strong></p>



<p class="wp-block-paragraph">Generally, no. Databases like MySQL or PostgreSQL typically expect strict, immediate file-locking guarantees that NFS — especially older versions or misconfigured setups — may not reliably provide, risking data corruption. Most database vendors explicitly recommend local or block-level storage (like iSCSI) over NFS for primary database files, reserving NFS for backups, logs, or shared application data instead.</p>



<p class="wp-block-paragraph"><strong>How many clients can mount the same NFS export simultaneously?</strong></p>



<p class="wp-block-paragraph">There&#8217;s no hard protocol-level limit built into NFS itself; the practical ceiling depends on the server&#8217;s CPU, memory, disk I/O throughput, and network bandwidth. Large-scale deployments in research and enterprise environments routinely support hundreds of simultaneous client connections to a single, well-provisioned NFS server, often backed by high-performance storage arrays and 10 Gbps or faster network links.</p>



<h2 class="wp-block-heading">21. Conclusion</h2>



<p class="wp-block-paragraph">Exporting a file system with NFS in Linux is a foundational, practical skill for anyone managing shared storage in a networked environment. By installing the NFS server package, defining directories and access rules in <code>/etc/exports</code>, applying the export with <code>exportfs -ra</code>, and properly configuring your firewall, you can securely share files across your network — whether that&#8217;s a small home lab or a university research cluster. In the next article, we&#8217;ll cover the client side of this process: how to actually mount and use these NFS exports from remote machines.</p>



<p class="wp-block-paragraph">Whether you&#8217;re setting up a small home lab for shared media storage or architecting a multi-terabyte research data platform for a university department, the same core principles apply: carefully scope your export&#8217;s client access, choose sensible read/write and squash options, validate your configuration before restarting services, and layer network-level firewall rules on top of the application-level rules defined in <code>/etc/exports</code>. Mastering the export side of NFS is the foundation upon which all remote file access is built. Once you&#8217;re comfortable defining directories, access rules, and security options in <code>/etc/exports</code>, the natural next step — covered in depth in the following article — is understanding how client machines discover, mount, and interact with these exports in day-to-day use, completing the full picture of NFS-based file sharing across a network.</p>



<h2 class="wp-block-heading">Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://man7.org/linux/man-pages/man5/exports.5.html">Linux <code>exports</code> Man Page</a></li>



<li><a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/managing_file_systems/exporting-nfs-shares_managing-file-systems">Red Hat — Configuring an NFS Server</a></li>



<li><a href="https://ubuntu.com/server/docs/service-nfs">Ubuntu Server Documentation — NFS</a></li>



<li><a href="https://datatracker.ietf.org/doc/html/rfc8881">IETF RFC 8881 — NFSv4.1 Protocol Specification</a></li>



<li><a href="https://www.cisco.com/c/en/us/support/docs/quality-of-service-qos/qos-policing/23408-qos-faq.html">Cisco QoS Configuration Guide</a></li>



<li><a href="https://firewalld.org/documentation/">Linux <code>firewalld</code> Documentation</a></li>



<li><a href="https://web.mit.edu/kerberos/krb5-latest/doc/admin/nfs.html">MIT Kerberos Documentation — Securing NFSv4 with Strong Authentication</a></li>



<li><a href="https://wiki.archlinux.org/title/NFS">Arch Linux Wiki — NFS/Troubleshooting</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/networking/how-to-export-file-system-with-nfs-in-linux/">How to Export a File System with NFS in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/networking/how-to-export-file-system-with-nfs-in-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3456</post-id>	</item>
		<item>
		<title>How to Share Files with NFS in Linux</title>
		<link>https://awjunaid.com/networking/how-share-files-with-nfs-in-linux/</link>
					<comments>https://awjunaid.com/networking/how-share-files-with-nfs-in-linux/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Mon, 24 Jul 2023 02:15:44 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=3453</guid>

					<description><![CDATA[<p>I covered how to export a file system on the NFS server side. But exporting a directory is&#8230;</p>
<p>The post <a href="https://awjunaid.com/networking/how-share-files-with-nfs-in-linux/">How to Share Files with NFS in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I covered how to <strong>export</strong> a file system on the NFS server side. But exporting a directory is only half the story — the real value of NFS comes from <strong>client machines mounting that export</strong> and accessing the shared files as if they were local. This article focuses on the complete, practical process of sharing files with NFS from both the server and client perspective, with an emphasis on real-world usage, mounting strategies, and troubleshooting.</p>



<h2 class="wp-block-heading">Table of Contents</h2>



<ol class="wp-block-list">
<li>Recap: What Is NFS File Sharing?</li>



<li>The Complete NFS Sharing Workflow</li>



<li>Server-Side Quick Setup</li>



<li>Client-Side: Installing NFS Utilities</li>



<li>Manually Mounting an NFS Share</li>



<li>Making the Mount Persistent with /etc/fstab</li>



<li>Auto-Mounting with autofs</li>



<li>Verifying and Testing File Sharing</li>



<li>Permissions and User Mapping Challenges</li>



<li>Real-World Example: Shared Team Directory</li>



<li>Cisco/Network Considerations for Multi-Site Sharing</li>



<li>Python Example: Automating Mount Verification</li>



<li>Comparison Table: Mounting Methods</li>



<li>Best Practices</li>



<li>Troubleshooting Common Issues</li>



<li>Conclusion</li>
</ol>



<h2 class="wp-block-heading">1. Recap: What Is NFS File Sharing?</h2>



<p class="wp-block-paragraph"><strong>NFS (Network File System)</strong> allows one Linux machine (the server) to make a directory available over the network, and other machines (clients) to <strong>mount</strong> that directory into their own file system tree. Once mounted, users on the client machine can read, write, create, and delete files in that shared directory exactly as if it were a local folder — all changes are instantly reflected for every other client with the same directory mounted.</p>



<h2 class="wp-block-heading">2. The Complete NFS Sharing Workflow</h2>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">graph LR
    A[1. Server: Install nfs-kernel-server] --> B[2. Server: Create shared directory]
    B --> C[3. Server: Add entry to /etc/exports]
    C --> D[4. Server: Run exportfs -ra]
    D --> E[5. Client: Install nfs-common]
    E --> F[6. Client: Create mount point directory]
    F --> G[7. Client: Mount the NFS share]
    G --> H[8. Users on client read/write files]</pre></div>



<p class="wp-block-paragraph">This diagram represents the complete end-to-end process — from setting up the server export (covered in the previous article) through to actually mounting and using the share on a client machine, which is our focus here.</p>



<h2 class="wp-block-heading">3. Server-Side Quick Setup</h2>



<p class="wp-block-paragraph">For completeness, here&#8217;s a condensed version of the server-side steps (covered in detail in the previous article):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo apt update
sudo apt install nfs-kernel-server -y
sudo mkdir -p /srv/nfs/teamshare
sudo chown nobody:nogroup /srv/nfs/teamshare
sudo chmod 2775 /srv/nfs/teamshare
echo "/srv/nfs/teamshare  192.168.1.0/24(rw,sync,no_subtree_check)" | sudo tee -a /etc/exports
sudo exportfs -ra
sudo systemctl enable --now nfs-server</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">update</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-kernel-server</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/srv/nfs/teamshare</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">chown</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nobody:nogroup</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/srv/nfs/teamshare</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">chmod</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2775</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/srv/nfs/teamshare</span></span>
<span class="line"><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/srv/nfs/teamshare  192.168.1.0/24(rw,sync,no_subtree_check)</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tee</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-a</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/etc/exports</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">exportfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-ra</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">systemctl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">enable</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--now</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-server</span></span></code></pre></div>



<h2 class="wp-block-heading">4. Client-Side: Installing NFS Utilities</h2>



<p class="wp-block-paragraph">On the client machine, you need the NFS client package, which is separate from the server package.</p>



<p class="wp-block-paragraph"><strong>On Ubuntu/Debian:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo apt update
sudo apt install nfs-common -y</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">update</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-common</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>On CentOS/RHEL/Fedora:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo dnf install nfs-utils -y</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dnf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs-utils</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span></span></code></pre></div>



<h2 class="wp-block-heading">5. Manually Mounting an NFS Share</h2>



<p class="wp-block-paragraph"><strong>Step 1: Create a local mount point (an empty directory that will act as the access point).</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo mkdir -p /mnt/teamshare</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/teamshare</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Step 2: Mount the remote NFS export.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo mount -t nfs 192.168.1.100:/srv/nfs/teamshare /mnt/teamshare</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.100:/srv/nfs/teamshare</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/teamshare</span></span></code></pre></div>



<p class="wp-block-paragraph">Here, <code>192.168.1.100</code> is the NFS server&#8217;s IP address, <code>/srv/nfs/teamshare</code> is the exported directory on the server, and <code>/mnt/teamshare</code> is the local mount point on the client.</p>



<p class="wp-block-paragraph"><strong>Step 3: Verify the mount was successful.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>df -h | grep teamshare</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">df</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-h</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">grep</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">teamshare</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Sample output:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>192.168.1.100:/srv/nfs/teamshare   50G   12G   38G   24%  /mnt/teamshare</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">192.168.1.100:/srv/nfs/teamshare</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">50</span><span style="color: #A3BE8C">G</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">12</span><span style="color: #A3BE8C">G</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">38</span><span style="color: #A3BE8C">G</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">24</span><span style="color: #A3BE8C">%</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">/mnt/teamshare</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Step 4: Test file sharing by creating a file.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>echo "Hello from client!" > /mnt/teamshare/test.txt
cat /mnt/teamshare/test.txt</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Hello from client!</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/teamshare/test.txt</span></span>
<span class="line"><span style="color: #88C0D0">cat</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/teamshare/test.txt</span></span></code></pre></div>



<p class="wp-block-paragraph">If another client also has this same share mounted, they will immediately see <code>test.txt</code> appear in their <code>/mnt/teamshare</code> directory too.</p>



<h2 class="wp-block-heading">6. Making the Mount Persistent with /etc/fstab</h2>



<p class="wp-block-paragraph">A manual mount using the <code>mount</code> command will disappear after a reboot. To make it persistent, add an entry to <code>/etc/fstab</code>.</p>



<p class="wp-block-paragraph"><strong>Edit the fstab file:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo nano /etc/fstab</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nano</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/etc/fstab</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Add this line:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>192.168.1.100:/srv/nfs/teamshare   /mnt/teamshare   nfs   defaults,_netdev   0   0</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">192.168.1.100:/srv/nfs/teamshare</span><span style="color: #D8DEE9FF">   </span><span style="color: #A3BE8C">/mnt/teamshare</span><span style="color: #D8DEE9FF">   </span><span style="color: #A3BE8C">nfs</span><span style="color: #D8DEE9FF">   </span><span style="color: #A3BE8C">defaults,_netdev</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">0</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>_netdev</code> option is important — it tells the system to wait until the network is up before attempting to mount, preventing boot failures.</p>



<p class="wp-block-paragraph"><strong>Test the fstab entry without rebooting:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo mount -a</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-a</span></span></code></pre></div>



<h2 class="wp-block-heading">7. Auto-Mounting with autofs</h2>



<p class="wp-block-paragraph">For environments where you don&#8217;t want the NFS share mounted permanently (to save resources or avoid boot delays if the server is temporarily unreachable), <strong>autofs</strong> mounts the share on-demand when accessed, and automatically unmounts it after a period of inactivity.</p>



<p class="wp-block-paragraph"><strong>Install autofs:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo apt install autofs -y</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">autofs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Configure the master map file:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>echo "/mnt/auto  /etc/auto.nfs" | sudo tee -a /etc/auto.master</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/mnt/auto  /etc/auto.nfs</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tee</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-a</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/etc/auto.master</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Create the map file <code>/etc/auto.nfs</code>:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>teamshare    -rw,sync    192.168.1.100:/srv/nfs/teamshare</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">teamshare</span><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">-rw,sync</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.100:/srv/nfs/teamshare</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Restart autofs:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo systemctl restart autofs</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">systemctl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">restart</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">autofs</span></span></code></pre></div>



<p class="wp-block-paragraph">Now, accessing <code>/mnt/auto/teamshare</code> for the first time will automatically trigger the mount, and it will unmount itself after being idle.</p>



<h2 class="wp-block-heading">8. Verifying and Testing File Sharing</h2>



<p class="wp-block-paragraph"><strong>Check active NFS mounts on a client:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>mount | grep nfs</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">mount</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">grep</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>View NFS statistics (read/write operations, retransmissions):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>nfsstat -c</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">nfsstat</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-c</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Check what a server is exporting from the client side, before mounting:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>showmount -e 192.168.1.100</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">showmount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.100</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Sample output:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Export list for 192.168.1.100:
/srv/nfs/teamshare 192.168.1.0/24</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">Export</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.100:</span></span>
<span class="line"><span style="color: #88C0D0">/srv/nfs/teamshare</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.0/24</span></span></code></pre></div>



<h2 class="wp-block-heading">9. Permissions and User Mapping Challenges</h2>



<p class="wp-block-paragraph">One of the trickiest parts of NFS file sharing is that <strong>user and group IDs (UID/GID) are shared by number, not by name</strong>, across client and server. If a user &#8220;alice&#8221; has UID 1001 on the server but UID 1005 on the client, file ownership will appear incorrect or inaccessible on one side.</p>



<p class="wp-block-paragraph"><strong>Best solutions to this problem:</strong></p>



<ul class="wp-block-list">
<li><strong>Use a centralized identity system</strong> like LDAP or FreeIPA so UIDs/GIDs are consistent across all machines.</li>



<li><strong>Use NFSv4 with idmapping</strong> (<code>/etc/idmapd.conf</code>), which maps users by name rather than raw UID number, provided both server and client have matching domain settings.</li>



<li><strong>Manually align UIDs/GIDs</strong> when creating users on server and client machines in smaller environments.</li>
</ul>



<p class="wp-block-paragraph"><strong>Example <code>/etc/idmapd.conf</code> domain setting (must match on server and client):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&#91;General&#93;
Domain = example.com</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9FF">General</span><span style="color: #ECEFF4">&#93;</span></span>
<span class="line"><span style="color: #88C0D0">Domain</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">example.com</span></span></code></pre></div>



<h2 class="wp-block-heading">10. Real-World Example: Shared Team Directory</h2>



<p class="wp-block-paragraph">A small software development team has five developers working from five different Linux workstations. Instead of using Git alone for everything (some large binary assets aren&#8217;t well-suited to version control), the team sets up a shared NFS directory for design assets:</p>



<ul class="wp-block-list">
<li><strong>Server:</strong> <code>fileserver.internal</code> exports <code>/srv/nfs/design-assets</code> with <code>rw</code> access to the <code>192.168.1.0/24</code> subnet.</li>



<li><strong>Clients:</strong> Each developer&#8217;s workstation mounts this at <code>/mnt/design-assets</code> via <code>/etc/fstab</code>.</li>



<li><strong>Result:</strong> Any designer or developer can drop a new asset into the shared folder, and it&#8217;s instantly visible and editable by the rest of the team — no manual file transfers, no version conflicts on binary assets.</li>
</ul>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">graph TD
    S[File Server: /srv/nfs/design-assets] --> C1[Developer 1: /mnt/design-assets]
    S --> C2[Developer 2: /mnt/design-assets]
    S --> C3[Developer 3: /mnt/design-assets]
    S --> C4[Developer 4: /mnt/design-assets]</pre></div>



<h2 class="wp-block-heading">11. Cisco/Network Considerations for Multi-Site Sharing</h2>



<p class="wp-block-paragraph">If clients and the NFS server are on different sites connected via a WAN (as discussed in our LAN/MAN/WAN article), NFS performance can degrade significantly due to latency, since NFS was originally designed for fast local networks. Considerations include:</p>



<ul class="wp-block-list">
<li><strong>Avoid NFS over high-latency WAN links</strong> for interactive workloads; consider a caching file system or a sync tool (like <code>rsync</code>) instead.</li>



<li><strong>If NFS over WAN is unavoidable</strong>, use NFSv4.1+ with features like <code>pNFS</code> and increase read/write buffer sizes (<code>rsize</code>/<code>wsize</code> mount options) to reduce round trips.</li>



<li><strong>Configure QoS on Cisco routers/switches</strong> to prioritize NFS traffic (port 2049) across the WAN link, similar to the example shown in the previous article.</li>
</ul>



<p class="wp-block-paragraph"><strong>Example: increasing NFS buffer sizes on a slower link:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo mount -t nfs -o rsize=32768,wsize=32768,timeo=30 192.168.1.100:/srv/nfs/teamshare /mnt/teamshare</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rsize=</span><span style="color: #B48EAD">32768</span><span style="color: #A3BE8C">,wsize=</span><span style="color: #B48EAD">32768</span><span style="color: #A3BE8C">,timeo=</span><span style="color: #B48EAD">30</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.100:/srv/nfs/teamshare</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/teamshare</span></span></code></pre></div>



<h2 class="wp-block-heading">12. Python Example: Automating Mount Verification</h2>



<p class="wp-block-paragraph">This Python script checks whether a list of expected NFS mounts are actually active on a client machine — useful for automated health checks across a fleet of workstations.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import subprocess

expected_mounts = &#91;"/mnt/teamshare", "/mnt/design-assets"&#93;

def get_active_nfs_mounts():
    result = subprocess.run(&#91;"mount", "-t", "nfs,nfs4"&#93;, capture_output=True, text=True)
    return result.stdout

active_output = get_active_nfs_mounts()

for mount_point in expected_mounts:
    if mount_point in active_output:
        print(f"&#91;OK&#93;      {mount_point} is mounted.")
    else:
        print(f"&#91;MISSING&#93; {mount_point} is NOT mounted!")</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> subprocess</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">expected_mounts </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/mnt/teamshare</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/mnt/design-assets</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">&#93;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">get_active_nfs_mounts</span><span style="color: #ECEFF4">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    result </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> subprocess</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">run</span><span style="color: #ECEFF4">(&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">mount</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-t</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">nfs,nfs4</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">&#93;,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">capture_output</span><span style="color: #81A1C1">=True</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">text</span><span style="color: #81A1C1">=True</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> result</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">stdout</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">active_output </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">get_active_nfs_mounts</span><span style="color: #ECEFF4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> mount_point </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> expected_mounts</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> mount_point </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> active_output</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">print</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;&#91;OK&#93;      </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">mount_point</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C"> is mounted.&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">else</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">print</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;&#91;MISSING&#93; </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">mount_point</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C"> is NOT mounted!&quot;</span><span style="color: #ECEFF4">)</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Sample Output:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&#91;OK&#93;      /mnt/teamshare is mounted.
&#91;MISSING&#93; /mnt/design-assets is NOT mounted!</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9FF">OK</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF">      /mnt/teamshare is mounted.</span></span>
<span class="line"><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9FF">MISSING</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> /mnt/design-assets is NOT mounted</span><span style="color: #81A1C1">!</span></span></code></pre></div>



<p class="wp-block-paragraph">This kind of script can be scheduled with <code>cron</code> to alert administrators when an expected NFS mount has silently failed or been unmounted.</p>



<h2 class="wp-block-heading">13. Comparison Table: Mounting Methods</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Method</th><th>Persistence</th><th>Best Use Case</th></tr></thead><tbody><tr><td>Manual <code>mount</code> command</td><td>Temporary (lost on reboot)</td><td>Quick testing, one-off access</td></tr><tr><td><code>/etc/fstab</code> entry</td><td>Permanent, mounts on every boot</td><td>Servers/workstations that always need the share</td></tr><tr><td><code>autofs</code></td><td>On-demand, auto-unmounts when idle</td><td>Shares used occasionally, laptops, saving resources</td></tr><tr><td>Systemd <code>.mount</code> unit</td><td>Permanent, more granular control</td><td>Advanced setups needing dependency ordering</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">14. Best Practices</h2>



<ul class="wp-block-list">
<li><strong>Always test mounts manually before adding them to <code>/etc/fstab</code></strong> to avoid boot failures from typos.</li>



<li><strong>Use the <code>_netdev</code> option</strong> in <code>/etc/fstab</code> for any NFS mount to prevent boot delays or failures when the network isn&#8217;t ready yet.</li>



<li><strong>Standardize UID/GID mapping</strong> across your organization using LDAP, FreeIPA, or NFSv4 idmapping to avoid permission headaches.</li>



<li><strong>Use <code>autofs</code> for laptops or intermittently connected clients</strong> to avoid hanging boot processes when the NFS server is unreachable.</li>



<li><strong>Monitor NFS mounts with automated health checks</strong> (like the Python script above) to catch silent failures early.</li>



<li><strong>Avoid NFS for latency-sensitive workloads over WAN links</strong>; prefer it for LAN/CAN environments where it performs best.</li>
</ul>



<h2 class="wp-block-heading">15. Troubleshooting Common Issues</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Issue</th><th>Cause</th><th>Fix</th></tr></thead><tbody><tr><td><code>mount.nfs: Connection timed out</code></td><td>Firewall blocking, or wrong server IP</td><td>Verify with <code>showmount -e &lt;server_ip&gt;</code>, check firewall</td></tr><tr><td>Files show as owned by &#8220;nobody&#8221;</td><td>UID/GID mismatch between client and server</td><td>Align UIDs/GIDs or configure NFSv4 idmapping</td></tr><tr><td>System hangs on boot waiting for NFS</td><td>Missing <code>_netdev</code> option, or server unreachable</td><td>Add <code>_netdev</code>, or switch to <code>autofs</code></td></tr><tr><td>&#8220;Stale file handle&#8221; error</td><td>Server export was changed/restarted while client had it mounted</td><td>Unmount and remount: <code>sudo umount -l /mnt/teamshare &amp;&amp; sudo mount -a</code></td></tr><tr><td>Slow file transfers over the share</td><td>Small buffer sizes, or high network latency</td><td>Increase <code>rsize</code>/<code>wsize</code> mount options, check network path</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Quick fix for a stale NFS mount:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo umount -f /mnt/teamshare
sudo mount -a</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">umount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/teamshare</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-a</span></span></code></pre></div>



<h2 class="wp-block-heading">16. Advanced Concepts: NFS Locking and Concurrent Access</h2>



<p class="wp-block-paragraph">One of the trickiest aspects of sharing files with NFS is understanding how the protocol handles <strong>file locking</strong> when multiple clients attempt to read or write the same file simultaneously.</p>



<h3 class="wp-block-heading">Network Lock Manager (NLM) in NFSv3</h3>



<p class="wp-block-paragraph">NFSv3 relies on a separate protocol called <strong>NLM (Network Lock Manager)</strong>, running alongside NFS itself, to coordinate file locks between clients. This historically caused issues, since NLM state could be lost if the server rebooted, requiring clients to detect the failure and re-acquire locks — a process that isn&#8217;t always seamless.</p>



<h3 class="wp-block-heading">Integrated Locking in NFSv4</h3>



<p class="wp-block-paragraph"><strong>NFSv4</strong> solves this by integrating locking directly into the core protocol (no separate NLM service required), and by introducing the concept of a <strong>lease</strong> — a time-bounded grant of access that a client must periodically renew. If a client fails to renew its lease (for example, due to a crash or network partition), the server automatically releases the lock, preventing indefinite blocking of other clients.</p>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">sequenceDiagram
    participant C1 as Client 1
    participant Server as NFSv4 Server
    participant C2 as Client 2

    C1->>Server: Request lock on file.txt
    Server->>C1: Lock granted (lease started)
    C2->>Server: Request lock on file.txt
    Server->>C2: Lock denied - already held
    C1->>Server: Release lock / lease expires
    Server->>C2: Lock now available
    C2->>Server: Request lock on file.txt
    Server->>C2: Lock granted</pre></div>



<h3 class="wp-block-heading">Practical Implications for Shared Teams</h3>



<p class="wp-block-paragraph">When multiple users on different client machines are actively editing files in a shared NFS directory, application-level locking behavior matters as much as NFS&#8217;s own lock handling. Text editors and office applications that respect <code>flock()</code>/<code>fcntl()</code> locking will correctly prevent simultaneous conflicting writes, while poorly behaved applications that ignore locks entirely can still cause silent overwrites regardless of what NFS itself supports. This is why many teams pair NFS shared storage with version control (for code) or dedicated collaborative editing tools (for documents), rather than relying solely on file-level locking for critical concurrent work.</p>



<h2 class="wp-block-heading">17. NFS Performance Tuning Tips</h2>



<p class="wp-block-paragraph">Beyond correct configuration, several tuning options can meaningfully improve NFS performance in demanding environments:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tuning Option</th><th>Effect</th></tr></thead><tbody><tr><td>Increasing <code>rsize</code>/<code>wsize</code></td><td>Larger read/write buffer sizes reduce the number of round trips needed for large file transfers</td></tr><tr><td>Using <code>nconnect</code> (NFSv4.1+)</td><td>Allows multiple TCP connections per mount, better utilizing available network bandwidth</td></tr><tr><td>Enabling <code>noatime</code> on client mounts</td><td>Avoids unnecessary metadata writes every time a file is merely read, reducing overhead</td></tr><tr><td>Using 10 Gbps+ networking</td><td>For heavy multi-client workloads, network bandwidth is often the real bottleneck, not NFS itself</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Example mount command combining several performance tuning options:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo mount -t nfs4 -o rsize=131072,wsize=131072,noatime,nconnect=4 192.168.1.100:/srv/nfs/teamshare /mnt/teamshare</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nfs4</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rsize=</span><span style="color: #B48EAD">131072</span><span style="color: #A3BE8C">,wsize=</span><span style="color: #B48EAD">131072</span><span style="color: #A3BE8C">,noatime,nconnect=</span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #A3BE8C">.1.100:/srv/nfs/teamshare</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/teamshare</span></span></code></pre></div>



<h2 class="wp-block-heading">18. Frequently Asked Questions</h2>



<p class="wp-block-paragraph"><strong>Can Windows machines mount a Linux NFS export?</strong></p>



<p class="wp-block-paragraph">Yes, though it requires enabling the &#8220;NFS Client&#8221; feature on Windows (available in Windows 10/11 Pro and Enterprise editions, and Windows Server), or using third-party NFS client software. That said, in mixed Windows/Linux environments, many organizations prefer SMB/CIFS for Windows clients and reserve NFS specifically for Linux-to-Linux sharing, to avoid UID/GID mapping complications between the two very different permission models.</p>



<p class="wp-block-paragraph"><strong>What happens if two clients edit the same file at the exact same time?</strong></p>



<p class="wp-block-paragraph">Without proper application-level locking, the last write to complete typically &#8220;wins,&#8221; silently overwriting the other client&#8217;s changes — a classic race condition. This is why collaborative editing of the same file by multiple simultaneous users is generally discouraged over plain NFS shares unless the applications involved implement robust locking or conflict resolution themselves.</p>



<p class="wp-block-paragraph"><strong>Is it safe to run NFS shares over an untrusted public network?</strong></p>



<p class="wp-block-paragraph">Not without additional protection. Traditional NFS (<code>sec=sys</code>) trusts client IP addresses without strong authentication or encryption, making it unsuitable for use directly over the public internet. If NFS access is genuinely needed across untrusted networks, tunnel it through a VPN or use NFSv4 with Kerberos-based security (<code>sec=krb5p</code>) as covered in the previous article, rather than exposing NFS ports directly to the internet.</p>



<h2 class="wp-block-heading">19. Scaling NFS Sharing Beyond a Single Server</h2>



<p class="wp-block-paragraph">As an organization grows, a single NFS server eventually becomes a bottleneck or a single point of failure. Several architectural approaches address this at scale:</p>



<ul class="wp-block-list">
<li><strong>NFS with High Availability (HA) clustering:</strong> Tools like <code>Pacemaker</code> and <code>Corosync</code> on Linux allow two or more servers to share a virtual IP address and storage backend, so if the primary NFS server fails, a standby server takes over transparently, and clients experience only a brief pause rather than a full outage.</li>



<li><strong>Distributed file systems as an NFS alternative:</strong> For very large-scale deployments, systems like <strong>GlusterFS</strong>, <strong>CephFS</strong>, or <strong>Amazon EFS</strong> (in cloud environments) provide NFS-compatible interfaces backed by distributed, redundant storage across many physical nodes, rather than a single server.</li>



<li><strong>Read replicas for read-heavy workloads:</strong> In scenarios where most clients only need read access (like the raw footage example from the previous article), replicating data to multiple read-only NFS servers and distributing clients across them using DNS round-robin or a load balancer can significantly reduce load on any single machine.</li>
</ul>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">graph TD
    VIP[Virtual IP: nfs.internal.company.local] --> Active[Active NFS Server]
    VIP -.->|Failover| Standby[Standby NFS Server]
    Active --- SharedStorage[(Shared/Replicated Storage)]
    Standby --- SharedStorage</pre></div>



<h2 class="wp-block-heading">20. Conclusion</h2>



<p class="wp-block-paragraph">Sharing files with NFS in Linux is a two-sided process: the server exports a directory with defined access rules, and clients mount that export locally, either manually, persistently via <code>/etc/fstab</code>, or on-demand via <code>autofs</code>. Once mounted, NFS creates a seamless, shared file system experience across multiple machines — ideal for team collaboration, centralized storage, and shared datasets within a LAN or CAN environment. Understanding UID/GID mapping and choosing the right mount strategy for your use case are the keys to a reliable, trouble-free NFS deployment.</p>



<h2 class="wp-block-heading">Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://man7.org/linux/man-pages/man8/mount.8.html">Linux <code>mount</code> Man Page</a></li>



<li><a href="https://man7.org/linux/man-pages/man5/nfs.5.html">Linux <code>nfs</code> Man Page</a></li>



<li><a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/managing_file_systems/mounting-nfs-shares_managing-file-systems">Red Hat — Mounting NFS Shares</a></li>



<li><a href="https://ubuntu.com/server/docs/service-nfs">Ubuntu Server Documentation — NFS Client Configuration</a></li>



<li><a href="https://man7.org/linux/man-pages/man5/autofs.5.html">Linux <code>autofs</code> Documentation</a></li>



<li><a href="https://datatracker.ietf.org/doc/html/rfc8881">IETF RFC 8881 — NFSv4.1 Protocol Specification</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/networking/how-share-files-with-nfs-in-linux/">How to Share Files with NFS in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/networking/how-share-files-with-nfs-in-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3453</post-id>	</item>
		<item>
		<title>How to Perform Automated Backups in Linux</title>
		<link>https://awjunaid.com/networking/how-to-perform-automated-backups-in-linux/</link>
					<comments>https://awjunaid.com/networking/how-to-perform-automated-backups-in-linux/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Sun, 23 Jul 2023 06:22:43 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=3336</guid>

					<description><![CDATA[<p>There are two kinds of system administrators: those who have lost important data, and those who will. The&#8230;</p>
<p>The post <a href="https://awjunaid.com/networking/how-to-perform-automated-backups-in-linux/">How to Perform Automated Backups in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">There are two kinds of system administrators: those who have lost important data, and those who will. The difference between a minor inconvenience and a catastrophic disaster almost always comes down to one thing — whether reliable, automated backups were in place.</p>



<p class="wp-block-paragraph">Manual backups fail because humans forget, get busy, or simply assume &#8220;someone else is handling it.&#8221; <strong>Automated backups</strong> remove human memory from the equation entirely — the system backs itself up on a schedule, without anyone needing to remember to do it.</p>



<p class="wp-block-paragraph">This article covers how to design and implement automated backup systems on Linux from first principles: what to back up, where to store it, how to schedule it, and how to verify it&#8217;s actually working — because a backup you&#8217;ve never tested is really just a hope, not a backup.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Why Automated (Not Manual) Backups?</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Manual Backups</th><th>Automated Backups</th></tr></thead><tbody><tr><td>Relies on someone remembering</td><td>Runs on a fixed schedule automatically</td></tr><tr><td>Prone to human error and inconsistency</td><td>Consistent, repeatable process every time</td></tr><tr><td>Easy to skip during busy periods</td><td>Runs regardless of how busy the team is</td></tr><tr><td>Hard to audit historically</td><td>Logs every run, easy to review history</td></tr><tr><td>Doesn&#8217;t scale past a handful of systems</td><td>Scales to hundreds/thousands of systems easily</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">The 3-2-1 Backup Rule</h2>



<p class="wp-block-paragraph">Before any technical implementation, it&#8217;s worth understanding the industry-standard guiding principle for backup strategy:</p>



<ul class="wp-block-list">
<li><strong>3</strong> copies of your data (the original plus two backups)</li>



<li><strong>2</strong> different storage media types (e.g., local disk + cloud, or disk + tape)</li>



<li><strong>1</strong> copy stored offsite (so a fire, flood, or theft doesn&#8217;t destroy everything at once)</li>
</ul>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart TD
    A[Production Data] --> B[Local Backup Copy]
    A --> C[Offsite/Cloud Backup Copy]
    B -.->|Different Media Type| D[e.g. External Disk]
    C -.->|Different Location| E[e.g. Cloud Storage / Remote Site]</pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 1: Decide What to Back Up</h2>



<p class="wp-block-paragraph">Not everything on a server needs backing up. Focus on:</p>



<ul class="wp-block-list">
<li><strong>Configuration files</strong> (<code>/etc/</code>)</li>



<li><strong>Application data</strong> (databases, uploaded files, application state)</li>



<li><strong>User data</strong> (<code>/home/</code>)</li>



<li><strong>Web content</strong> (<code>/var/www/</code>)</li>



<li><strong>Databases</strong> (dumped in proper format, not just copied as raw files while running)</li>
</ul>



<p class="wp-block-paragraph">You generally do <strong>not</strong> need to back up:</p>



<ul class="wp-block-list">
<li>Operating system binaries (easily reinstalled)</li>



<li>Temporary files (<code>/tmp/</code>)</li>



<li>Cache directories</li>



<li>Log files (unless required for compliance/auditing)</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 2: Choose a Backup Tool</h2>



<h3 class="wp-block-heading"><code>rsync</code> — The Workhorse of Linux Backups</h3>



<p class="wp-block-paragraph"><code>rsync</code> efficiently copies only the parts of files that have changed, making it fast even for large datasets on repeat runs.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>rsync -avz --delete /var/www/ /backup/www/</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">rsync</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-avz</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--delete</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/www/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/www/</span></span></code></pre></div>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Flag</th><th>Meaning</th></tr></thead><tbody><tr><td><code>-a</code></td><td>Archive mode — preserves permissions, timestamps, symlinks</td></tr><tr><td><code>-v</code></td><td>Verbose output</td></tr><tr><td><code>-z</code></td><td>Compress data during transfer</td></tr><tr><td><code>--delete</code></td><td>Remove files in destination that no longer exist in source (mirror mode)</td></tr></tbody></table></figure>



<h3 class="wp-block-heading"><code>tar</code> — Simple Archive Creation</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -czvf /backup/website-backup-$(date +%F).tar.gz /var/www/</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-czvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/website-backup-</span><span style="color: #ECEFF4">$(</span><span style="color: #88C0D0">date</span><span style="color: #A3BE8C"> +%F</span><span style="color: #ECEFF4">)</span><span style="color: #A3BE8C">.tar.gz</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/www/</span></span></code></pre></div>



<h3 class="wp-block-heading"><code>rclone</code> — For Cloud Storage Backups</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>rclone sync /var/www/ remote:my-backup-bucket/www/</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">rclone</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sync</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/www/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">remote:my-backup-bucket/www/</span></span></code></pre></div>



<p class="wp-block-paragraph"><code>rclone</code> supports dozens of cloud providers (AWS S3, Google Drive, Backblaze B2, and more) with the same simple syntax.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 3: Automate with <code>cron</code></h2>



<p class="wp-block-paragraph"><code>cron</code> is the classic Linux job scheduler — perfect for running backup scripts on a recurring schedule without any manual intervention.</p>



<h3 class="wp-block-heading">Writing a Backup Script</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo nano /usr/local/bin/backup.sh</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nano</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/usr/local/bin/backup.sh</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#!/bin/bash
# Simple automated backup script

BACKUP_DIR="/backup"
SOURCE_DIR="/var/www"
DATE=$(date +%F)
LOGFILE="/var/log/backup.log"

echo "&#91;$(date)&#93; Starting backup..." >> "$LOGFILE"

mkdir -p "$BACKUP_DIR"

tar -czf "$BACKUP_DIR/backup-$DATE.tar.gz" "$SOURCE_DIR"

if &#91; $? -eq 0 &#93;; then
    echo "&#91;$(date)&#93; Backup completed successfully: backup-$DATE.tar.gz" >> "$LOGFILE"
else
    echo "&#91;$(date)&#93; BACKUP FAILED!" >> "$LOGFILE"
fi

# Remove backups older than 14 days
find "$BACKUP_DIR" -name "backup-*.tar.gz" -mtime +14 -delete
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">#!/bin/bash</span></span>
<span class="line"><span style="color: #616E88"># Simple automated backup script</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">BACKUP_DIR</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/backup</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">SOURCE_DIR</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/var/www</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">DATE</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">$(</span><span style="color: #88C0D0">date</span><span style="color: #A3BE8C"> +%F</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9">LOGFILE</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/var/log/backup.log</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&#91;</span><span style="color: #ECEFF4">$(</span><span style="color: #88C0D0">date</span><span style="color: #ECEFF4">)</span><span style="color: #A3BE8C">&#93; Starting backup...</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$LOGFILE</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$BACKUP_DIR</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-czf</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$BACKUP_DIR</span><span style="color: #A3BE8C">/backup-</span><span style="color: #D8DEE9">$DATE</span><span style="color: #A3BE8C">.tar.gz</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$SOURCE_DIR</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">$?</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-eq</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">then</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&#91;</span><span style="color: #ECEFF4">$(</span><span style="color: #88C0D0">date</span><span style="color: #ECEFF4">)</span><span style="color: #A3BE8C">&#93; Backup completed successfully: backup-</span><span style="color: #D8DEE9">$DATE</span><span style="color: #A3BE8C">.tar.gz</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$LOGFILE</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #81A1C1">else</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&#91;</span><span style="color: #ECEFF4">$(</span><span style="color: #88C0D0">date</span><span style="color: #ECEFF4">)</span><span style="color: #A3BE8C">&#93; BACKUP FAILED!</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$LOGFILE</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #81A1C1">fi</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Remove backups older than 14 days</span></span>
<span class="line"><span style="color: #88C0D0">find</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$BACKUP_DIR</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-name</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">backup-*.tar.gz</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-mtime</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+14</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-delete</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Make it executable:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo chmod +x /usr/local/bin/backup.sh</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">chmod</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+x</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/usr/local/bin/backup.sh</span></span></code></pre></div>



<h3 class="wp-block-heading">Scheduling with Cron</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo crontab -e</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">crontab</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-e</span></span></code></pre></div>



<p class="wp-block-paragraph">Add a line to run the backup every night at 2:00 AM:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>0 2 * * * /usr/local/bin/backup.sh</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/usr/local/bin/backup.sh</span></span></code></pre></div>



<h3 class="wp-block-heading">Understanding Cron Syntax</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>* * * * *  command
│ │ │ │ │
│ │ │ │ └── Day of week (0-6, Sunday=0)
│ │ │ └──── Month (1-12)
│ │ └────── Day of month (1-31)
│ └──────── Hour (0-23)
└────────── Minute (0-59)
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">  command</span></span>
<span class="line"><span style="color: #88C0D0">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span></span>
<span class="line"><span style="color: #88C0D0">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Day</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">of</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">week</span><span style="color: #D8DEE9FF"> (0-6, </span><span style="color: #A3BE8C">Sunday=</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">└────</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Month</span><span style="color: #D8DEE9FF"> (1-12)</span></span>
<span class="line"><span style="color: #88C0D0">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">└──────</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Day</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">of</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">month</span><span style="color: #D8DEE9FF"> (1-31)</span></span>
<span class="line"><span style="color: #88C0D0">│</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">└────────</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Hour</span><span style="color: #D8DEE9FF"> (0-23)</span></span>
<span class="line"><span style="color: #88C0D0">└──────────</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Minute</span><span style="color: #D8DEE9FF"> (0-59)</span></span>
<span class="line"></span></code></pre></div>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Schedule</th><th>Cron Expression</th></tr></thead><tbody><tr><td>Every day at 2 AM</td><td><code>0 2 * * *</code></td></tr><tr><td>Every Sunday at midnight</td><td><code>0 0 * * 0</code></td></tr><tr><td>Every 6 hours</td><td><code>0 */6 * * *</code></td></tr><tr><td>First day of every month</td><td><code>0 0 1 * *</code></td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 4: Automate Database Backups</h2>



<p class="wp-block-paragraph">Databases need special handling — copying raw database files while the database is running can produce corrupted, unusable backups. Always use the proper dump tool.</p>



<h3 class="wp-block-heading">MySQL/MariaDB</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>mysqldump -u root -p'password' --all-databases | gzip > /backup/db-$(date +%F).sql.gz</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">mysqldump</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">root</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--all-databases</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">gzip</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/db-</span><span style="color: #ECEFF4">$(</span><span style="color: #88C0D0">date</span><span style="color: #A3BE8C"> +%F</span><span style="color: #ECEFF4">)</span><span style="color: #A3BE8C">.sql.gz</span></span></code></pre></div>



<h3 class="wp-block-heading">PostgreSQL</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>pg_dumpall -U postgres | gzip > /backup/pgdb-$(date +%F).sql.gz</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">pg_dumpall</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-U</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postgres</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">gzip</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/pgdb-</span><span style="color: #ECEFF4">$(</span><span style="color: #88C0D0">date</span><span style="color: #A3BE8C"> +%F</span><span style="color: #ECEFF4">)</span><span style="color: #A3BE8C">.sql.gz</span></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 5: Send Backups Offsite</h2>



<p class="wp-block-paragraph">A local-only backup doesn&#8217;t protect against site-wide disasters (fire, theft, ransomware encrypting everything it can reach, including local backups!).</p>



<h3 class="wp-block-heading">Using <code>rsync</code> to a Remote Server</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>rsync -avz -e ssh /backup/ user@remote-backup-server:/backups/server1/</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">rsync</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-avz</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ssh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">user@remote-backup-server:/backups/server1/</span></span></code></pre></div>



<h3 class="wp-block-heading">Using <code>rclone</code> to Cloud Storage</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>rclone copy /backup/ remote:company-backups/server1/</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">rclone</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">copy</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">remote:company-backups/server1/</span></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Architecture Diagram: A Complete Automated Backup Flow</h2>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart LR
    A[Cron Trigger 2 AM Daily] --> B[Backup Script Runs]
    B --> C[Dump Databases]
    B --> D[Archive Files with tar]
    C --> E[Local Backup Storage]
    D --> E
    E --> F[Sync Offsite via rsync/rclone]
    E --> G[Rotate: Delete Backups Older Than 14 Days]
    B --> H[Write Log Entry]
    H --> I[Alert on Failure via Email/Monitoring]</pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Real-World Example: E-Commerce Website Backup Strategy</h2>



<p class="wp-block-paragraph">A small online store running on a single Linux VPS might implement this layered strategy:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Data Type</th><th>Backup Method</th><th>Frequency</th><th>Retention</th></tr></thead><tbody><tr><td>MySQL order database</td><td><code>mysqldump</code> + gzip</td><td>Every 6 hours</td><td>30 days</td></tr><tr><td>Product images/uploads</td><td><code>rsync</code></td><td>Daily</td><td>14 days</td></tr><tr><td>Application config</td><td><code>tar</code> archive</td><td>Weekly</td><td>8 weeks</td></tr><tr><td>Full offsite copy</td><td><code>rclone</code> to cloud storage</td><td>Daily</td><td>90 days</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">This layered approach means: if a bad deployment corrupts data at 3 PM, the store can restore from a 6-hour-old database snapshot rather than losing an entire day (or week) of orders.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Cisco Example: Backing Up Network Device Configurations</h2>



<p class="wp-block-paragraph">Automated backups aren&#8217;t just for servers — network device configurations should be backed up too. Cisco devices support automatic configuration backup via TFTP/SCP triggered from a script:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>copy running-config tftp://192.168.1.100/backups/router1-config.txt
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">copy</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">running-config</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tftp://192.168.1.100/backups/router1-config.txt</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">This can be automated from a Linux server using a scheduled script that connects via SSH and issues backup commands to multiple devices in sequence — often built with tools like Python&#8217;s <code>netmiko</code> library or Ansible.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Python Example: A More Robust Backup Script</h2>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import subprocess
import datetime
import os
import logging

logging.basicConfig(filename='/var/log/backup.log', level=logging.INFO,
                     format='%(asctime)s %(message)s')

BACKUP_DIR = "/backup"
SOURCE_DIR = "/var/www"
RETENTION_DAYS = 14

def run_backup():
    os.makedirs(BACKUP_DIR, exist_ok=True)
    date_str = datetime.date.today().isoformat()
    archive_path = f"{BACKUP_DIR}/backup-{date_str}.tar.gz"

    try:
        subprocess.run(
            &#91;"tar", "-czf", archive_path, SOURCE_DIR&#93;,
            check=True
        )
        logging.info(f"Backup succeeded: {archive_path}")
    except subprocess.CalledProcessError as e:
        logging.error(f"Backup FAILED: {e}")
        return

    cleanup_old_backups()

def cleanup_old_backups():
    cutoff = datetime.datetime.now().timestamp() - (RETENTION_DAYS * 86400)
    for filename in os.listdir(BACKUP_DIR):
        filepath = os.path.join(BACKUP_DIR, filename)
        if os.path.getmtime(filepath) &lt; cutoff:
            os.remove(filepath)
            logging.info(f"Removed old backup: {filename}")

if __name__ == "__main__":
    run_backup()
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> subprocess</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> datetime</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> os</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> logging</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">logging</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">basicConfig</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">filename</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">/var/log/backup.log</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">level</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">logging</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">INFO</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                     </span><span style="color: #D8DEE9">format</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">%(asctime)s</span><span style="color: #A3BE8C"> </span><span style="color: #EBCB8B">%(message)s</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">BACKUP_DIR </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/backup</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">SOURCE_DIR </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/var/www</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">RETENTION_DAYS </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">14</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">run_backup</span><span style="color: #ECEFF4">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    os</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">makedirs</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">BACKUP_DIR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">exist_ok</span><span style="color: #81A1C1">=True</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    date_str </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> datetime</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">date</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">today</span><span style="color: #ECEFF4">().</span><span style="color: #88C0D0">isoformat</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    archive_path </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;</span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">BACKUP_DIR</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">/backup-</span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">date_str</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">.tar.gz&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">try</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        subprocess</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">run</span><span style="color: #ECEFF4">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">tar</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-czf</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> archive_path</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> SOURCE_DIR</span><span style="color: #ECEFF4">&#93;,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">check</span><span style="color: #81A1C1">=True</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        logging</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">info</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;Backup succeeded: </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">archive_path</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">except</span><span style="color: #D8DEE9FF"> subprocess</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">CalledProcessError </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> e</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        logging</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">error</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;Backup FAILED: </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">e</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">cleanup_old_backups</span><span style="color: #ECEFF4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">cleanup_old_backups</span><span style="color: #ECEFF4">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    cutoff </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> datetime</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">datetime</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">now</span><span style="color: #ECEFF4">().</span><span style="color: #88C0D0">timestamp</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">RETENTION_DAYS </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">86400</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> filename </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">listdir</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">BACKUP_DIR</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">        filepath </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">join</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">BACKUP_DIR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> filename</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">getmtime</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">filepath</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> cutoff</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">            os</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">remove</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">filepath</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">            logging</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">info</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;Removed old backup: </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">filename</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> __name__ </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">__main__</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">run_backup</span><span style="color: #ECEFF4">()</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Schedule this with cron just like the Bash version:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>0 2 * * * /usr/bin/python3 /usr/local/bin/backup.py
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/usr/bin/python3</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/usr/local/bin/backup.py</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Comparison Table: Backup Tool Options</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tool</th><th>Best For</th><th>Incremental Support</th><th>Cloud Support</th></tr></thead><tbody><tr><td><code>tar</code></td><td>Simple full archives</td><td>No (manual scripting needed)</td><td>No (needs pairing with rclone/rsync)</td></tr><tr><td><code>rsync</code></td><td>Efficient file syncing</td><td>Yes (via <code>--link-dest</code>)</td><td>Only to rsync-compatible remotes</td></tr><tr><td><code>rclone</code></td><td>Cloud storage sync</td><td>Yes</td><td>Yes (30+ providers)</td></tr><tr><td><code>restic</code></td><td>Modern encrypted, deduplicated backups</td><td>Yes</td><td>Yes</td></tr><tr><td><code>borgbackup</code></td><td>Deduplicated, compressed backups</td><td>Yes</td><td>Via SSH-based remotes</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Best Practices</h2>



<ul class="wp-block-list">
<li><strong>Follow the 3-2-1 rule</strong> — multiple copies, multiple media types, at least one offsite.</li>



<li><strong>Automate everything</strong> — never rely on a human remembering to run a backup.</li>



<li><strong>Test restores regularly</strong> — a backup that&#8217;s never been restored is unverified and untrustworthy.</li>



<li><strong>Log every backup run</strong>, and alert on failures — a silent failure is worse than an obvious one.</li>



<li><strong>Encrypt backups</strong>, especially offsite/cloud copies, to protect sensitive data.</li>



<li><strong>Rotate old backups</strong> to avoid unbounded storage growth.</li>



<li><strong>Dump databases properly</strong> — never just copy live database files directly.</li>



<li><strong>Document your backup and restore procedures</strong> so anyone on the team can execute a recovery, not just the person who built it.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Troubleshooting</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Symptom</th><th>Likely Cause</th><th>Fix</th></tr></thead><tbody><tr><td>Cron job doesn&#8217;t run</td><td>Wrong cron syntax, or script not executable</td><td>Check <code>crontab -l</code>; verify <code>chmod +x</code> on script</td></tr><tr><td>Backup script runs but produces empty archive</td><td>Wrong source path, or permissions issue</td><td>Verify path exists; run script manually with <code>sudo</code> to test</td></tr><tr><td>Disk fills up over time</td><td>No rotation/cleanup of old backups</td><td>Add retention/cleanup logic (see script examples above)</td></tr><tr><td>Database backup fails silently</td><td>Wrong credentials, or DB service down</td><td>Test <code>mysqldump</code>/<code>pg_dump</code> manually; check DB service status</td></tr><tr><td>Offsite sync fails</td><td>Network/SSH key issues</td><td>Test <code>rsync</code>/<code>rclone</code> manually; verify SSH keys and connectivity</td></tr><tr><td>Backup completes but restore fails</td><td>Backup was never tested</td><td>Schedule regular test restores to a sandbox environment</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Useful Diagnostic Commands</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># View recent cron job logs
grep CRON /var/log/syslog

# Manually test a backup script
sudo /usr/local/bin/backup.sh

# Verify archive integrity
tar -tzf /backup/backup-2026-07-24.tar.gz > /dev/null &amp;&amp; echo "Archive OK"
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># View recent cron job logs</span></span>
<span class="line"><span style="color: #88C0D0">grep</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CRON</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/log/syslog</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Manually test a backup script</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/usr/local/bin/backup.sh</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Verify archive integrity</span></span>
<span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-tzf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/backup-2026-07-24.tar.gz</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/null</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Archive OK</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Automated backups turn data protection from a fragile, human-dependent hope into a reliable, repeatable system. By combining simple, well-understood Linux tools — <code>tar</code>, <code>rsync</code>, <code>rclone</code>, database dump utilities, and <code>cron</code> scheduling — with sound principles like the 3-2-1 rule, proper logging, and regular restore testing, you can build a backup system that will actually save you when disaster strikes, not just when everything is already going fine.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://rsync.samba.org/documentation.html">rsync Official Documentation</a></li>



<li><a href="https://rclone.org/docs/">rclone Documentation</a></li>



<li><a href="https://borgbackup.readthedocs.io/">BorgBackup Documentation</a></li>



<li><a href="https://restic.readthedocs.io/">restic Documentation</a></li>



<li><a href="https://man7.org/linux/man-pages/man5/crontab.5.html">Cron man page</a></li>



<li><a href="https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html">MySQL mysqldump Reference</a></li>



<li><a href="https://www.postgresql.org/docs/current/backup.html">PostgreSQL Backup and Restore Documentation</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/networking/how-to-perform-automated-backups-in-linux/">How to Perform Automated Backups in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/networking/how-to-perform-automated-backups-in-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3336</post-id>	</item>
		<item>
		<title>How to Perform Incremental Backups in Linux</title>
		<link>https://awjunaid.com/networking/how-to-perform-incremental-backups-in-linux/</link>
					<comments>https://awjunaid.com/networking/how-to-perform-incremental-backups-in-linux/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Sun, 23 Jul 2023 06:18:21 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=3333</guid>

					<description><![CDATA[<p>Imagine backing up a 500 GB file server every single night, in full, forever. Not only would that&#8230;</p>
<p>The post <a href="https://awjunaid.com/networking/how-to-perform-incremental-backups-in-linux/">How to Perform Incremental Backups in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Imagine backing up a 500 GB file server every single night, in full, forever. Not only would that consume enormous amounts of storage, it would also take hours to complete each time — most of which is spent re-copying files that haven&#8217;t changed since yesterday. There&#8217;s a smarter way: <strong>incremental backups</strong>, which only copy the data that has actually changed since the last backup.</p>



<p class="wp-block-paragraph">This article explains incremental backups from first principles — how they differ from full and differential backups, how to implement them on Linux using <code>rsync</code>, <code>tar</code>, and modern tools like <code>restic</code> and <code>borgbackup</code>, and how to structure a real backup rotation strategy around them.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Full vs. Incremental vs. Differential Backups</h2>



<p class="wp-block-paragraph">Understanding these three backup types — and the tradeoffs between them — is essential before implementing any backup strategy.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Backup Type</th><th>What It Copies</th><th>Storage Use</th><th>Restore Speed</th><th>Backup Speed</th></tr></thead><tbody><tr><td><strong>Full</strong></td><td>Everything, every time</td><td>Highest</td><td>Fastest (single restore point)</td><td>Slowest</td></tr><tr><td><strong>Incremental</strong></td><td>Only changes since the <em>last backup</em> (full or incremental)</td><td>Lowest</td><td>Slowest (must replay full + every increment)</td><td>Fastest</td></tr><tr><td><strong>Differential</strong></td><td>Only changes since the <em>last full backup</em></td><td>Medium</td><td>Medium (full + one differential)</td><td>Medium</td></tr></tbody></table></figure>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart LR
    subgraph Full Backup Strategy
    F1[Full: Sun] --> F2[Full: Mon] --> F3[Full: Tue]
    end
</pre></div>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart LR
    subgraph Incremental Backup Strategy
    I1[Full: Sun] --> I2[Incremental: Mon changes only] --> I3[Incremental: Tue changes only] --> I4[Incremental: Wed changes only]
    end</pre></div>



<p class="wp-block-paragraph">With incremental backups, <strong>Monday&#8217;s backup</strong> only contains what changed between Sunday and Monday. <strong>Tuesday&#8217;s backup</strong> only contains what changed between Monday and Tuesday — and so on. To fully restore Wednesday&#8217;s state, you need the original full backup <strong>plus every incremental backup in the chain</strong>, applied in order.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Why Choose Incremental Backups?</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Benefit</th><th>Explanation</th></tr></thead><tbody><tr><td><strong>Massive storage savings</strong></td><td>Only changed data is stored after the initial full backup</td></tr><tr><td><strong>Much faster backup runs</strong></td><td>Less data to copy each time means shorter backup windows</td></tr><tr><td><strong>Lower bandwidth usage</strong></td><td>Critical when backing up to remote/offsite/cloud storage</td></tr><tr><td><strong>More frequent backups possible</strong></td><td>Since each run is fast and cheap, you can back up more often (e.g., hourly)</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">The Tradeoff</h3>



<p class="wp-block-paragraph">The main downside is <strong>restore complexity and speed</strong> — recovering data means restoring the last full backup, then replaying every subsequent incremental backup in the correct order. A broken link anywhere in that chain can make later backups unusable.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Method 1: Incremental Backups with <code>rsync</code> and Hard Links</h2>



<p class="wp-block-paragraph">A classic and elegant technique uses <code>rsync</code>&#8216;s <code>--link-dest</code> option combined with hard links, popularized by tools like <code>rsnapshot</code>. Each backup looks like a <strong>complete</strong> snapshot from the outside, but unchanged files are actually just hard links to the previous backup — using almost no extra disk space for unchanged data.</p>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart TD
    A[backup.2026-07-22 Full snapshot] -->|Hard links for unchanged files| B[backup.2026-07-23]
    B -->|Hard links for unchanged files| C[backup.2026-07-24]
    C -->|Only new/changed files use real disk space| D[Result: Each folder looks complete, but disk usage stays low]
</pre></div>



<h3 class="wp-block-heading">Example Script</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#!/bin/bash
SOURCE="/var/www"
BACKUP_ROOT="/backup/snapshots"
DATE=$(date +%F)
LATEST_LINK="$BACKUP_ROOT/latest"

mkdir -p "$BACKUP_ROOT"

rsync -av --delete \
  --link-dest="$LATEST_LINK" \
  "$SOURCE/" "$BACKUP_ROOT/$DATE/"

# Update the "latest" pointer for next time
rm -f "$LATEST_LINK"
ln -s "$BACKUP_ROOT/$DATE" "$LATEST_LINK"
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">#!/bin/bash</span></span>
<span class="line"><span style="color: #D8DEE9">SOURCE</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/var/www</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">BACKUP_ROOT</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/backup/snapshots</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">DATE</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">$(</span><span style="color: #88C0D0">date</span><span style="color: #A3BE8C"> +%F</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9">LATEST_LINK</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$BACKUP_ROOT</span><span style="color: #A3BE8C">/latest</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$BACKUP_ROOT</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">rsync</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-av</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--delete</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">--link-dest=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$LATEST_LINK</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$SOURCE</span><span style="color: #A3BE8C">/</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$BACKUP_ROOT</span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9">$DATE</span><span style="color: #A3BE8C">/</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Update the &quot;latest&quot; pointer for next time</span></span>
<span class="line"><span style="color: #88C0D0">rm</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$LATEST_LINK</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #88C0D0">ln</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$BACKUP_ROOT</span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9">$DATE</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9">$LATEST_LINK</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Each day&#8217;s folder (<code>$BACKUP_ROOT/2026-07-24/</code>) appears to contain a <strong>full</strong> copy of the source directory — you can <code>cd</code> into it and browse it like any normal folder — but unchanged files are hard-linked to yesterday&#8217;s backup, so they consume zero additional disk space.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Method 2: Incremental Backups with <code>tar</code></h2>



<p class="wp-block-paragraph"><code>tar</code> has native support for incremental backups using a &#8220;snapshot file&#8221; that tracks file metadata between runs.</p>



<h3 class="wp-block-heading">First Backup (Full)</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar --create \
    --file=/backup/full-2026-07-20.tar \
    --listed-incremental=/backup/snapshot.snar \
    /var/www
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--create</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--file=/backup/full-2026-07-20.tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--listed-incremental=/backup/snapshot.snar</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">/var/www</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Subsequent Backups (Incremental)</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar --create \
    --file=/backup/incr-2026-07-21.tar \
    --listed-incremental=/backup/snapshot.snar \
    /var/www
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--create</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--file=/backup/incr-2026-07-21.tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--listed-incremental=/backup/snapshot.snar</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">/var/www</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">The <code>--listed-incremental</code> snapshot file (<code>snapshot.snar</code>) remembers exactly what was backed up last time — each subsequent run only includes files that are new or modified since the last snapshot update.</p>



<h3 class="wp-block-heading">Restoring a Full Chain</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>cd /restore-target
tar --extract --listed-incremental=/dev/null --file=/backup/full-2026-07-20.tar
tar --extract --listed-incremental=/dev/null --file=/backup/incr-2026-07-21.tar
tar --extract --listed-incremental=/dev/null --file=/backup/incr-2026-07-22.tar
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">cd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/restore-target</span></span>
<span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--extract</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--listed-incremental=/dev/null</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--file=/backup/full-2026-07-20.tar</span></span>
<span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--extract</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--listed-incremental=/dev/null</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--file=/backup/incr-2026-07-21.tar</span></span>
<span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--extract</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--listed-incremental=/dev/null</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--file=/backup/incr-2026-07-22.tar</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Notice the extracts must happen <strong>in order</strong> — full, then each incremental in sequence.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Method 3: Modern Tools — <code>restic</code> and <code>borgbackup</code></h2>



<p class="wp-block-paragraph">Modern backup tools like <code>restic</code> and <code>borgbackup</code> handle incremental logic automatically, with added benefits like deduplication and encryption built in — no manual snapshot management required.</p>



<h3 class="wp-block-heading"><code>restic</code> Example</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Initialize a backup repository (once)
restic init --repo /backup/restic-repo

# Run a backup (restic automatically only stores new/changed data)
restic backup /var/www --repo /backup/restic-repo

# List all snapshots
restic snapshots --repo /backup/restic-repo

# Restore a specific snapshot
restic restore latest --target /restore --repo /backup/restic-repo
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Initialize a backup repository (once)</span></span>
<span class="line"><span style="color: #88C0D0">restic</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">init</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--repo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/restic-repo</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Run a backup (restic automatically only stores new/changed data)</span></span>
<span class="line"><span style="color: #88C0D0">restic</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">backup</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/www</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--repo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/restic-repo</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># List all snapshots</span></span>
<span class="line"><span style="color: #88C0D0">restic</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">snapshots</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--repo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/restic-repo</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Restore a specific snapshot</span></span>
<span class="line"><span style="color: #88C0D0">restic</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">restore</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">latest</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--target</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/restore</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--repo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/restic-repo</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><code>borgbackup</code> Example</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Initialize a repository
borg init --encryption=repokey /backup/borg-repo

# Create an incremental backup (borg deduplicates automatically)
borg create /backup/borg-repo::backup-{now} /var/www

# List all backups
borg list /backup/borg-repo

# Restore a specific archive
borg extract /backup/borg-repo::backup-2026-07-24
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Initialize a repository</span></span>
<span class="line"><span style="color: #88C0D0">borg</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">init</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--encryption=repokey</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/borg-repo</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Create an incremental backup (borg deduplicates automatically)</span></span>
<span class="line"><span style="color: #88C0D0">borg</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">create</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/borg-repo::backup-{now}</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/www</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># List all backups</span></span>
<span class="line"><span style="color: #88C0D0">borg</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/borg-repo</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Restore a specific archive</span></span>
<span class="line"><span style="color: #88C0D0">borg</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">extract</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/borg-repo::backup-2026-07-24</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Both tools use <strong>content-based deduplication</strong> — meaning even if a large file is only partially modified, only the changed chunks are stored, not the entire file again. This is more efficient than traditional file-level incremental approaches.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Comparison Table: Incremental Backup Tools</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tool</th><th>Deduplication</th><th>Encryption Built In</th><th>Complexity</th><th>Best For</th></tr></thead><tbody><tr><td><code>rsync</code> + <code>--link-dest</code></td><td>File-level (via hard links)</td><td>No (add manually)</td><td>Medium</td><td>Simple snapshot-style backups</td></tr><tr><td><code>tar --listed-incremental</code></td><td>No</td><td>No</td><td>Medium-High</td><td>Environments requiring plain <code>tar</code> archives</td></tr><tr><td><code>restic</code></td><td>Block-level</td><td>Yes (built in)</td><td>Low</td><td>Modern, secure automated backups</td></tr><tr><td><code>borgbackup</code></td><td>Block-level</td><td>Yes (built in)</td><td>Low</td><td>Modern, space-efficient backups</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Real-World Example: Backing Up a Growing Log/Data Server</h2>



<p class="wp-block-paragraph"><strong>Scenario:</strong> A company has a data ingestion server accumulating about 50 GB of new data files per day, with a total dataset of 5 TB. A full backup every night would take hours and consume enormous storage.</p>



<p class="wp-block-paragraph"><strong>Solution using <code>restic</code>:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Weekly full-equivalent baseline handled automatically by restic's dedup engine
0 1 * * * restic backup /data --repo /backup/restic-repo --tag daily

# Prune old snapshots weekly, keeping a sensible retention policy
0 3 * * 0 restic forget --repo /backup/restic-repo --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Weekly full-equivalent baseline handled automatically by restic&#39;s dedup engine</span></span>
<span class="line"><span style="color: #88C0D0">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">restic</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">backup</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/data</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--repo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/restic-repo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--tag</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">daily</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Prune old snapshots weekly, keeping a sensible retention policy</span></span>
<span class="line"><span style="color: #88C0D0">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">restic</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">forget</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--repo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/backup/restic-repo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--keep-daily</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">14</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--keep-weekly</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--keep-monthly</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--prune</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Because <code>restic</code> deduplicates at the block level, even though 50 GB of <em>new</em> files are added daily, if those files share content with existing data (common in log formats, database exports, etc.), the actual stored increment can be far smaller than 50 GB — saving significant storage over time.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Cisco Example: Incremental Configuration Backups</h2>



<p class="wp-block-paragraph">While Cisco devices don&#8217;t have a native &#8220;incremental backup&#8221; concept for configs (configs are usually small enough for full backups), the same <em>principle</em> applies when managing large numbers of devices. A common pattern is to back up configs daily but only <strong>alert or store a new version</strong> if the configuration actually changed — effectively an application-level incremental strategy:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Simplified logic: only save a new config backup if it differs from the last one
import hashlib

def config_changed(new_config, last_backup_path):
    with open(last_backup_path, 'rb') as f:
        old_hash = hashlib.sha256(f.read()).hexdigest()
    new_hash = hashlib.sha256(new_config.encode()).hexdigest()
    return old_hash != new_hash
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Simplified logic: only save a new config backup if it differs from the last one</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> hashlib</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">config_changed</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">new_config</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">last_backup_path</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">open</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">last_backup_path</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">rb</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        old_hash </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> hashlib</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">sha256</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">f</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">read</span><span style="color: #ECEFF4">()).</span><span style="color: #88C0D0">hexdigest</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    new_hash </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> hashlib</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">sha256</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">new_config</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">encode</span><span style="color: #ECEFF4">()).</span><span style="color: #88C0D0">hexdigest</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> old_hash </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> new_hash</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">This pattern — hash comparison to detect actual changes — is the same underlying idea that makes incremental backups efficient: don&#8217;t store what hasn&#8217;t changed.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Python Example: A Custom Incremental Backup Script Using Hashes</h2>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import os
import hashlib
import shutil
import json
from datetime import date

SOURCE_DIR = "/var/www"
BACKUP_DIR = "/backup/incremental"
MANIFEST_FILE = os.path.join(BACKUP_DIR, "manifest.json")

def file_hash(path):
    h = hashlib.sha256()
    with open(path, 'rb') as f:
        while chunk := f.read(8192):
            h.update(chunk)
    return h.hexdigest()

def load_manifest():
    if os.path.exists(MANIFEST_FILE):
        with open(MANIFEST_FILE) as f:
            return json.load(f)
    return {}

def save_manifest(manifest):
    with open(MANIFEST_FILE, 'w') as f:
        json.dump(manifest, f)

def run_incremental_backup():
    manifest = load_manifest()
    today_dir = os.path.join(BACKUP_DIR, str(date.today()))
    os.makedirs(today_dir, exist_ok=True)

    changed_count = 0
    for root, _, files in os.walk(SOURCE_DIR):
        for name in files:
            full_path = os.path.join(root, name)
            rel_path = os.path.relpath(full_path, SOURCE_DIR)
            current_hash = file_hash(full_path)

            if manifest.get(rel_path) != current_hash:
                dest_path = os.path.join(today_dir, rel_path)
                os.makedirs(os.path.dirname(dest_path), exist_ok=True)
                shutil.copy2(full_path, dest_path)
                manifest&#91;rel_path&#93; = current_hash
                changed_count += 1

    save_manifest(manifest)
    print(f"Incremental backup complete: {changed_count} files changed")

run_incremental_backup()
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> os</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> hashlib</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> shutil</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> json</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> datetime </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> date</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">SOURCE_DIR </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/var/www</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">BACKUP_DIR </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/backup/incremental</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">MANIFEST_FILE </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">join</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">BACKUP_DIR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">manifest.json</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">file_hash</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">path</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    h </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> hashlib</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">sha256</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">open</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">rb</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> chunk </span><span style="color: #81A1C1">:=</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">read</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">8192</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">            h</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">update</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">chunk</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> h</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">hexdigest</span><span style="color: #ECEFF4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">load_manifest</span><span style="color: #ECEFF4">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">exists</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">MANIFEST_FILE</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">open</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">MANIFEST_FILE</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> json</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">load</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">f</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">save_manifest</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">manifest</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">open</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">MANIFEST_FILE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">w</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        json</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">dump</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">manifest</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">run_incremental_backup</span><span style="color: #ECEFF4">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    manifest </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">load_manifest</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    today_dir </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">join</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">BACKUP_DIR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">str</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">date</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">today</span><span style="color: #ECEFF4">()))</span></span>
<span class="line"><span style="color: #D8DEE9FF">    os</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">makedirs</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">today_dir</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">exist_ok</span><span style="color: #81A1C1">=True</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    changed_count </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> root</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> _</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> files </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">walk</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">SOURCE_DIR</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> name </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> files</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">            full_path </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">join</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">root</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">            rel_path </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">relpath</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">full_path</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> SOURCE_DIR</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">            current_hash </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">file_hash</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">full_path</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> manifest</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">get</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">rel_path</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> current_hash</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                dest_path </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">join</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">today_dir</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> rel_path</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">                os</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">makedirs</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">dirname</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">dest_path</span><span style="color: #ECEFF4">),</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">exist_ok</span><span style="color: #81A1C1">=True</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">                shutil</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">copy2</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">full_path</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> dest_path</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">                manifest</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9FF">rel_path</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> current_hash</span></span>
<span class="line"><span style="color: #D8DEE9FF">                changed_count </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">save_manifest</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">manifest</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">print</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;Incremental backup complete: </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">changed_count</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C"> files changed&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">run_incremental_backup</span><span style="color: #ECEFF4">()</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">This script only copies files whose SHA-256 hash has changed since the last run — the core principle behind every incremental backup tool, written from scratch to illustrate exactly how they work under the hood.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Designing a Retention Strategy (GFS: Grandfather-Father-Son)</h2>



<p class="wp-block-paragraph">A common industry-standard rotation scheme for incremental backups is <strong>GFS</strong>:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Level</th><th>Frequency</th><th>Retention</th></tr></thead><tbody><tr><td><strong>Son</strong> (daily)</td><td>Every day</td><td>Keep 7 daily backups</td></tr><tr><td><strong>Father</strong> (weekly)</td><td>Every Sunday</td><td>Keep 4 weekly backups</td></tr><tr><td><strong>Grandfather</strong> (monthly)</td><td>First of the month</td><td>Keep 12 monthly backups</td></tr></tbody></table></figure>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart TD
    A[Daily Incrementals - Son] --> B[Weekly Rollup - Father]
    B --> C[Monthly Rollup - Grandfather]</pre></div>



<p class="wp-block-paragraph">This gives you fine-grained recent recovery points (daily, for the last week) while still retaining longer-term history (monthly, for the last year) without keeping 365 individual daily backups forever.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Best Practices</h2>



<ul class="wp-block-list">
<li><strong>Always pair incrementals with periodic full backups</strong> — an unbroken chain of 200 incrementals with no recent full backup is fragile and slow to restore.</li>



<li><strong>Test the entire restore chain periodically</strong>, not just the latest incremental — a broken link anywhere breaks the whole chain.</li>



<li><strong>Use tools with built-in deduplication</strong> (<code>restic</code>, <code>borgbackup</code>) for the best balance of simplicity and efficiency.</li>



<li><strong>Automate retention/pruning</strong> so incremental chains don&#8217;t grow forever.</li>



<li><strong>Monitor backup job success/failure</strong> with alerts — a silently failing incremental chain can go unnoticed for weeks.</li>



<li><strong>Encrypt incremental backups</strong>, especially when stored offsite or in the cloud.</li>



<li><strong>Document the exact restore procedure</strong>, including the order of operations, so anyone on the team can execute a recovery under pressure.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Troubleshooting</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Symptom</th><th>Likely Cause</th><th>Fix</th></tr></thead><tbody><tr><td>Restore is missing recent files</td><td>An incremental in the chain was skipped or corrupted</td><td>Verify all incrementals were applied in the correct order</td></tr><tr><td>Backup chain keeps growing indefinitely</td><td>No periodic full backup / no pruning policy</td><td>Schedule regular full backups; configure retention/pruning</td></tr><tr><td><code>tar</code> incremental restore fails</td><td>Snapshot file (<code>.snar</code>) lost or corrupted</td><td>Rebuild backup chain starting from a new full backup</td></tr><tr><td><code>restic</code>/<code>borgbackup</code> restore is slow</td><td>Very deep history with excessive small snapshots</td><td>Prune old snapshots regularly per your retention policy</td></tr><tr><td>Disk space still growing fast despite incrementals</td><td>Source data has high change rate (not much overlap)</td><td>Consider differential or full+dedup strategy instead</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Incremental backups are the practical answer to the real-world constraints of storage, bandwidth, and time. By only capturing what has changed since the last backup — whether through <code>rsync</code> hard-linking, <code>tar</code>&#8216;s snapshot tracking, or modern deduplicating tools like <code>restic</code> and <code>borgbackup</code> — you can back up far more frequently, use dramatically less storage, and still maintain a complete, restorable history of your data. The key is pairing incrementals with a sound retention strategy and testing restores regularly, so the speed and efficiency gains never come at the cost of reliability.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://restic.readthedocs.io/">restic Documentation</a></li>



<li><a href="https://borgbackup.readthedocs.io/">BorgBackup Documentation</a></li>



<li><a href="https://www.gnu.org/software/tar/manual/html_node/Incremental-Dumps.html">GNU tar Incremental Backups Manual</a></li>



<li><a href="https://rsync.samba.org/documentation.html">rsync &#8211;link-dest Documentation</a></li>



<li><a href="https://rsnapshot.org/">rsnapshot Official Site</a></li>



<li><a href="https://en.wikipedia.org/wiki/Backup_rotation_scheme">Backup Rotation Schemes – GFS Explained</a></li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/networking/how-to-perform-incremental-backups-in-linux/">How to Perform Incremental Backups in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/networking/how-to-perform-incremental-backups-in-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3333</post-id>	</item>
		<item>
		<title>How to Back Up Data on Tapes in Linux</title>
		<link>https://awjunaid.com/networking/how-to-do-backup-on-tapes-in-linux/</link>
					<comments>https://awjunaid.com/networking/how-to-do-backup-on-tapes-in-linux/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Sun, 23 Jul 2023 06:14:58 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=3330</guid>

					<description><![CDATA[<p>In an era of cloud storage and solid-state drives, magnetic tape might sound like a relic of the&#8230;</p>
<p>The post <a href="https://awjunaid.com/networking/how-to-do-backup-on-tapes-in-linux/">How to Back Up Data on Tapes in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In an era of cloud storage and solid-state drives, magnetic tape might sound like a relic of the past — something out of a 1970s data center. But tape is very much alive, and for good reason: it remains one of the cheapest, most durable, and most secure ways to store massive amounts of data for long-term archival, especially for compliance, disaster recovery, and &#8220;cold storage&#8221; purposes.</p>



<p class="wp-block-paragraph">This article explains tape backups on Linux from the ground up — how tape drives work, the tools used to control them (<code>mt</code> and <code>tar</code>), how to build a rotation strategy, and how modern approaches like LTFS make tape almost as easy to browse as a regular hard drive.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Why Tape Still Matters</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Advantage</th><th>Explanation</th></tr></thead><tbody><tr><td><strong>Extremely low cost per terabyte</strong></td><td>Tape media is dramatically cheaper than SSD or even spinning disk at scale</td></tr><tr><td><strong>Long shelf life</strong></td><td>Quality tape media can reliably store data for 15–30 years if stored properly</td></tr><tr><td><strong>Air-gapped security</strong></td><td>A tape sitting on a shelf, physically disconnected, cannot be touched by ransomware or remote attackers</td></tr><tr><td><strong>High capacity</strong></td><td>Modern LTO tape cartridges hold many terabytes per cartridge</td></tr><tr><td><strong>Regulatory compliance</strong></td><td>Many industries require offline, immutable, long-term archival — tape fits this perfectly</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">The tradeoff, of course, is <strong>speed</strong> — tape is sequential-access media, meaning to read a file near the end of a tape, the drive must physically wind through everything before it. This makes tape unsuitable for frequently-accessed data, but ideal for long-term archives and disaster-recovery-of-last-resort backups.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">How Tape Storage Works</h2>



<p class="wp-block-paragraph">Unlike a hard drive or SSD, which can jump instantly to any location on the media (<strong>random access</strong>), tape is a <strong>sequential access</strong> medium — data is written and read in a straight line, like an old cassette tape.</p>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart LR
    A[Tape Start] --> B[File 1] --> C[File 2] --> D[File 3] --> E[...] --> F[Tape End]
</pre></div>



<p class="wp-block-paragraph">To read &#8220;File 3,&#8221; the drive must physically wind past File 1 and File 2 first (unless it uses an index, discussed later). This is the fundamental tradeoff of tape: incredible cost-efficiency and durability, at the cost of slow random access.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Linux Tape Devices</h2>



<p class="wp-block-paragraph">When a tape drive is connected to a Linux system (often via SAS, Fibre Channel, or USB for smaller autoloaders), it typically appears as a device like:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/dev/st0     # rewinding tape device
/dev/nst0    # non-rewinding tape device</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">/dev/st0</span><span style="color: #D8DEE9FF">     </span><span style="color: #616E88"># rewinding tape device</span></span>
<span class="line"><span style="color: #88C0D0">/dev/nst0</span><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># non-rewinding tape device</span></span></code></pre></div>



<h3 class="wp-block-heading">Rewinding vs. Non-Rewinding Devices</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Device</th><th>Behavior After Each Operation</th></tr></thead><tbody><tr><td><code>/dev/st0</code> (rewinding)</td><td>Automatically rewinds to the beginning after every operation</td></tr><tr><td><code>/dev/nst0</code> (non-rewinding)</td><td>Stays at its current position — essential for writing multiple archives to one tape</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">For backup work involving multiple files/archives on a single tape, you almost always want the <strong>non-rewinding</strong> device (<code>/dev/nst0</code>), so each write picks up where the last one left off instead of overwriting from the start.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 1: Install Tape Tools</h2>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo apt install mt-st tar -y        # Debian/Ubuntu
sudo dnf install mt-st tar -y        # RHEL/CentOS</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mt-st</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88"># Debian/Ubuntu</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dnf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mt-st</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88"># RHEL/CentOS</span></span></code></pre></div>



<p class="wp-block-paragraph"><code>mt</code> (&#8220;magnetic tape control&#8221;) is the primary tool for controlling tape drive operations — rewinding, ejecting, seeking, and erasing.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 2: Basic Tape Operations with <code>mt</code></h2>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Check tape drive status
mt -f /dev/nst0 status

# Rewind the tape to the beginning
mt -f /dev/st0 rewind

# Eject the tape
mt -f /dev/st0 offline

# Erase a tape completely
mt -f /dev/st0 erase

# Move forward by 2 file marks (skip past 2 archives)
mt -f /dev/nst0 fsf 2

# Move backward by 1 file mark
mt -f /dev/nst0 bsf 1
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Check tape drive status</span></span>
<span class="line"><span style="color: #88C0D0">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">status</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Rewind the tape to the beginning</span></span>
<span class="line"><span style="color: #88C0D0">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/st0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rewind</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Eject the tape</span></span>
<span class="line"><span style="color: #88C0D0">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/st0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">offline</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Erase a tape completely</span></span>
<span class="line"><span style="color: #88C0D0">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/st0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">erase</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Move forward by 2 file marks (skip past 2 archives)</span></span>
<span class="line"><span style="color: #88C0D0">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">fsf</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Move backward by 1 file mark</span></span>
<span class="line"><span style="color: #88C0D0">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">bsf</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 3: Writing a Backup to Tape with <code>tar</code></h2>



<p class="wp-block-paragraph"><code>tar</code> was originally designed for exactly this purpose — its name literally stands for <strong>T</strong>ape <strong>AR</strong>chive.</p>



<h3 class="wp-block-heading">Writing Data to Tape</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -cvf /dev/nst0 /var/www /etc</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-cvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/www</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/etc</span></span></code></pre></div>



<p class="wp-block-paragraph">This writes an archive of <code>/var/www</code> and <code>/etc</code> directly to the tape device, without creating an intermediate file on disk.</p>



<h3 class="wp-block-heading">Writing Multiple Archives to the Same Tape</h3>



<p class="wp-block-paragraph">Because we used the <strong>non-rewinding</strong> device, we can write a second archive right after the first without overwriting it:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -cvf /dev/nst0 /var/www
sudo tar -cvf /dev/nst0 /home
sudo tar -cvf /dev/nst0 /etc</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-cvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/www</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-cvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/home</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-cvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/etc</span></span></code></pre></div>



<p class="wp-block-paragraph">Each <code>tar</code> command writes one &#8220;file&#8221; onto the tape, separated by a file mark, one after another:</p>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart LR
    A[Tape Start] --> B["Archive 1: /var/www"] --> C["Archive 2: /home"] --> D["Archive 3: /etc"] --> E[Tape End]
</pre></div>



<h3 class="wp-block-heading">Reading Data Back from Tape</h3>



<p class="wp-block-paragraph">First, rewind to the beginning:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo mt -f /dev/st0 rewind</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/st0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rewind</span></span></code></pre></div>



<p class="wp-block-paragraph">Then extract the <strong>first</strong> archive:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -xvf /dev/nst0</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-xvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span></span></code></pre></div>



<p class="wp-block-paragraph">To get to the <strong>second</strong> archive (<code>/home</code>), skip forward past the first file mark, then extract:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo mt -f /dev/nst0 fsf 1
sudo tar -xvf /dev/nst0</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">fsf</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-xvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span></span></code></pre></div>



<h3 class="wp-block-heading">Listing Contents Without Extracting</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -tvf /dev/nst0</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-tvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Step 4: Compression Considerations</h2>



<p class="wp-block-paragraph">Unlike disk backups, it&#8217;s usually best to let the <strong>tape drive&#8217;s own hardware compression</strong> handle compression rather than software compression like <code>gzip</code>, because:</p>



<ul class="wp-block-list">
<li>Hardware compression is extremely fast (built into the drive controller)</li>



<li>Pre-compressed data (e.g., via <code>tar -z</code>) doesn&#8217;t compress further and may even slightly increase in size when passed through the drive&#8217;s compression engine</li>



<li>LTO drives typically achieve roughly 2:1 compression ratios on typical data</li>
</ul>



<p class="wp-block-paragraph">If you do want software compression for portability reasons, use it consistently and be aware it may reduce the tape drive&#8217;s own compression efficiency.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">LTFS: Making Tape Behave Like a Disk</h2>



<p class="wp-block-paragraph"><strong>LTFS (Linear Tape File System)</strong> is a modern standard that lets you mount a tape and browse it like a regular filesystem — with visible files and folders — instead of using raw sequential <code>tar</code> streams.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo apt install ltfs -y

# Format a tape with LTFS
sudo mkltfs -d /dev/nst0

# Mount it like a regular filesystem
sudo mkdir /mnt/tape
sudo ltfs -o devname=/dev/nst0 /mnt/tape

# Now you can use normal file commands!
cp -r /var/www /mnt/tape/
ls /mnt/tape/

# Unmount when finished
sudo umount /mnt/tape</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ltfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-y</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Format a tape with LTFS</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mkltfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-d</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Mount it like a regular filesystem</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/tape</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ltfs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">devname=/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/tape</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Now you can use normal file commands!</span></span>
<span class="line"><span style="color: #88C0D0">cp</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-r</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/var/www</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/tape/</span></span>
<span class="line"><span style="color: #88C0D0">ls</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/tape/</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Unmount when finished</span></span>
<span class="line"><span style="color: #88C0D0">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">umount</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/mnt/tape</span></span></code></pre></div>



<p class="wp-block-paragraph">LTFS trades away a small amount of the raw efficiency of <code>tar</code> streaming in exchange for dramatically improved usability — a huge win for organizations that need occasional random access to archived files without a full tape read-through.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Comparison Table: Tape Backup Approaches</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Method</th><th>Ease of Use</th><th>Random File Access</th><th>Efficiency</th><th>Best For</th></tr></thead><tbody><tr><td>Raw <code>tar</code> to <code>/dev/nst0</code></td><td>Moderate (CLI-based)</td><td>No (sequential only)</td><td>Highest</td><td>Large sequential archival backups</td></tr><tr><td>LTFS</td><td>High (mount like a drive)</td><td>Yes (within reason)</td><td>Slightly lower overhead</td><td>Organizations needing occasional file browsing</td></tr><tr><td>Enterprise backup software (Bacula, Amanda, Veeam)</td><td>High (GUI/managed)</td><td>Managed via catalog/index</td><td>High</td><td>Large-scale, multi-tape, multi-server environments</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Real-World Example: Compliance Archival for a Financial Company</h2>



<p class="wp-block-paragraph"><strong>Scenario:</strong> A financial services company is legally required to retain transaction records for 7 years, with data that must be stored offline (air-gapped) for security compliance.</p>



<p class="wp-block-paragraph"><strong>Solution:</strong></p>



<ol class="wp-block-list">
<li>Monthly, a full database export and document archive is created.</li>



<li>The archive is written to two LTO tape cartridges (<code>tar -cvf /dev/nst0 ...</code>), one kept onsite in a fireproof safe, one sent to an offsite secure storage facility — following the 3-2-1 principle from general backup strategy.</li>



<li>Each tape is labeled with the date and a checksum file is also written to the tape for later integrity verification.</li>



<li>Tapes older than 7 years are securely destroyed per company data retention policy.</li>
</ol>



<p class="wp-block-paragraph">Because the tapes are physically disconnected from any network after writing, they are <strong>completely immune</strong> to ransomware, remote attacks, or accidental deletion — a property no purely online backup system can fully match.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Cisco Example: Network Bandwidth Planning for Tape Libraries</h2>



<p class="wp-block-paragraph">While Cisco hardware doesn&#8217;t interact with tape directly, tape backup systems (especially large tape libraries/autoloaders) often sit on a dedicated backup network segment to avoid saturating production bandwidth during large backup windows. A typical Cisco QoS configuration prioritizes production traffic over scheduled backup traffic:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>class-map match-all BACKUP-TRAFFIC
 match access-group name BACKUP-ACL

policy-map WAN-QOS
 class BACKUP-TRAFFIC
  bandwidth percent 20
  set dscp af11
 class class-default
  bandwidth percent 80
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">class-map</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">match-all</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">BACKUP-TRAFFIC</span></span>
<span class="line"><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">match</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">access-group</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">name</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">BACKUP-ACL</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">policy-map</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">WAN-QOS</span></span>
<span class="line"><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">BACKUP-TRAFFIC</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">bandwidth</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">percent</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">20</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dscp</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">af11</span></span>
<span class="line"><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">class-default</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">bandwidth</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">percent</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">80</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">This ensures that when a large backup job saturates the network transferring data to a tape library, it doesn&#8217;t starve critical production traffic like VoIP or customer-facing applications.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Python Example: Automating Tape Backup Verification</h2>



<p class="wp-block-paragraph">Verifying tape backups is critical — you don&#8217;t want to discover a tape is unreadable only when you desperately need to restore from it. Here&#8217;s a script that automates writing a checksum manifest alongside a tape backup:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import subprocess
import hashlib
import os
import datetime

SOURCE_DIRS = &#91;"/var/www", "/etc"&#93;
TAPE_DEVICE = "/dev/nst0"
REWIND_DEVICE = "/dev/st0"
LOG_FILE = "/var/log/tape-backup.log"

def calculate_checksums(directories):
    manifest = {}
    for directory in directories:
        for root, _, files in os.walk(directory):
            for name in files:
                path = os.path.join(root, name)
                try:
                    h = hashlib.sha256()
                    with open(path, 'rb') as f:
                        while chunk := f.read(8192):
                            h.update(chunk)
                    manifest&#91;path&#93; = h.hexdigest()
                except (PermissionError, FileNotFoundError):
                    continue
    return manifest

def write_to_tape(directories, device):
    cmd = &#91;"tar", "-cvf", device&#93; + directories
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.returncode == 0

def log(message):
    with open(LOG_FILE, "a") as f:
        f.write(f"&#91;{datetime.datetime.now()}&#93; {message}\n")

def run_tape_backup():
    subprocess.run(&#91;"mt", "-f", REWIND_DEVICE, "rewind"&#93;)

    log("Calculating pre-backup checksums...")
    manifest = calculate_checksums(SOURCE_DIRS)
    log(f"Checksummed {len(manifest)} files")

    log("Writing archive to tape...")
    success = write_to_tape(SOURCE_DIRS, TAPE_DEVICE)

    if success:
        log("Tape backup completed successfully")
    else:
        log("TAPE BACKUP FAILED")

    subprocess.run(&#91;"mt", "-f", REWIND_DEVICE, "rewind"&#93;)

if __name__ == "__main__":
    run_tape_backup()
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> subprocess</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> hashlib</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> os</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> datetime</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">SOURCE_DIRS </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/var/www</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/etc</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">&#93;</span></span>
<span class="line"><span style="color: #D8DEE9FF">TAPE_DEVICE </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">REWIND_DEVICE </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/dev/st0</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">LOG_FILE </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/var/log/tape-backup.log</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">calculate_checksums</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">directories</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    manifest </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> directory </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> directories</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> root</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> _</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> files </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">walk</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">directory</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> name </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> files</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                path </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">join</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">root</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">try</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    h </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> hashlib</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">sha256</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">open</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">rb</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> chunk </span><span style="color: #81A1C1">:=</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">read</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">8192</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            h</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">update</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">chunk</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    manifest</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> h</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">hexdigest</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">except</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #8FBCBB">PermissionError</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">FileNotFoundError</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">continue</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> manifest</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">write_to_tape</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">directories</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">device</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    cmd </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">tar</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-cvf</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> device</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> directories</span></span>
<span class="line"><span style="color: #D8DEE9FF">    result </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> subprocess</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">run</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">cmd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">capture_output</span><span style="color: #81A1C1">=True</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">text</span><span style="color: #81A1C1">=True</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> result</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">returncode </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">log</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">message</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">open</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">LOG_FILE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">a</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> f</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        f</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">write</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;&#91;</span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">datetime</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">datetime</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">now</span><span style="color: #ECEFF4">()</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">&#93; </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">message</span><span style="color: #EBCB8B">}\n</span><span style="color: #A3BE8C">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">run_tape_backup</span><span style="color: #ECEFF4">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    subprocess</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">run</span><span style="color: #ECEFF4">(&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">mt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-f</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REWIND_DEVICE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">rewind</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">&#93;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">log</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Calculating pre-backup checksums...</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    manifest </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">calculate_checksums</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">SOURCE_DIRS</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">log</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;Checksummed </span><span style="color: #EBCB8B">{</span><span style="color: #88C0D0">len</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">manifest</span><span style="color: #ECEFF4">)</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C"> files&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">log</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Writing archive to tape...</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    success </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">write_to_tape</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">SOURCE_DIRS</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> TAPE_DEVICE</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> success</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">log</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tape backup completed successfully</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">else</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">log</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TAPE BACKUP FAILED</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    subprocess</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">run</span><span style="color: #ECEFF4">(&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">mt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-f</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REWIND_DEVICE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">rewind</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">&#93;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> __name__ </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">__main__</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">run_tape_backup</span><span style="color: #ECEFF4">()</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">The checksum manifest can later be compared against a restored copy to confirm data integrity — an essential step for any archival system meant to be trusted years down the line.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Best Practices</h2>



<ul class="wp-block-list">
<li><strong>Always use the non-rewinding device (<code>/dev/nst0</code>)</strong> when writing multiple archives to a single tape.</li>



<li><strong>Label every tape physically and digitally</strong> — with date, contents summary, and retention/expiry date.</li>



<li><strong>Store tapes properly</strong> — cool, dry, magnetically shielded environments extend tape lifespan significantly.</li>



<li><strong>Rotate tapes off-site</strong> for disaster recovery, following the 3-2-1 backup principle.</li>



<li><strong>Periodically test-read old tapes</strong> — media degrades, and drives eventually stop supporting very old formats.</li>



<li><strong>Use hardware compression</strong> on the drive rather than double-compressing with software tools.</li>



<li><strong>Keep a tape catalog/index</strong> (via LTFS, or dedicated backup software) so you don&#8217;t have to blindly search through tapes to find a specific file.</li>



<li><strong>Plan for drive obsolescence</strong> — LTO drives typically read back 1–2 generations and write 1 generation back; migrate old tapes to new formats periodically.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Troubleshooting</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Symptom</th><th>Likely Cause</th><th>Fix</th></tr></thead><tbody><tr><td><code>mt: /dev/st0: No such device</code></td><td>Tape drive not detected by the kernel</td><td>Check <code>dmesg</code>, verify SCSI/SAS cabling, confirm drive is powered on</td></tr><tr><td>Tape backup seems to overwrite previous data</td><td>Used rewinding device (<code>/dev/st0</code>) instead of non-rewinding (<code>/dev/nst0</code>)</td><td>Always use <code>/dev/nst0</code> for multi-archive tapes</td></tr><tr><td><code>tar: Cannot write: No space left on device</code> mid-backup</td><td>Tape physically full</td><td>Use a new/second tape cartridge; consider splitting large backups</td></tr><tr><td>Can&#8217;t find a specific archive on tape</td><td>No index maintained</td><td>Use LTFS for browsable tapes, or maintain a written/digital catalog</td></tr><tr><td>Old tape unreadable in new drive</td><td>Drive doesn&#8217;t support that many generations back</td><td>Check LTO generation compatibility chart; migrate data to newer media periodically</td></tr><tr><td>Backup is extremely slow</td><td>Software compression combined with hardware compression, or slow interface</td><td>Disable software compression; verify SAS/Fibre Channel link speed</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Useful Diagnostic Commands</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Check detected tape devices
lsscsi | grep tape

# Check current tape drive status
mt -f /dev/nst0 status

# Test read without extracting
tar -tvf /dev/nst0

# Check kernel messages for tape drive errors
dmesg | grep -i tape</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Check detected tape devices</span></span>
<span class="line"><span style="color: #88C0D0">lsscsi</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">grep</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tape</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Check current tape drive status</span></span>
<span class="line"><span style="color: #88C0D0">mt</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">status</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Test read without extracting</span></span>
<span class="line"><span style="color: #88C0D0">tar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-tvf</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/dev/nst0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Check kernel messages for tape drive errors</span></span>
<span class="line"><span style="color: #88C0D0">dmesg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">grep</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-i</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tape</span></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Tape storage may not be flashy, but it remains an irreplaceable part of a mature backup and archival strategy — offering unmatched cost efficiency, long-term durability, and true air-gapped security that no online backup can fully replicate. By understanding Linux tape device semantics (<code>/dev/st0</code> vs <code>/dev/nst0</code>), mastering <code>mt</code> and <code>tar</code> fundamentals, and optionally layering on LTFS for usability, you can build a tape backup system that will reliably protect your organization&#8217;s most critical long-term data for decades.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://www.gnu.org/software/tar/manual/html_node/Tapes.html">GNU tar Manual – Tape Backups</a></li>



<li><a href="https://linux.die.net/man/1/mt">mt(1) man page</a></li>



<li><a href="https://www.snia.org/tech_activities/standards/curr_standards/ltfs">LTFS Format Specification – SNIA</a></li>



<li><a href="https://www.lto.org/">LTO Ultrium Official Site</a></li>



<li><a href="https://www.bacula.org/">Bacula Open Source Backup Software</a></li>



<li><a href="https://www.amanda.org/">Amanda Network Backup</a></li>



<li><a href="https://www.cisa.gov/news-events/news/data-backup-options">3-2-1 Backup Strategy Explained – US-CERT</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/networking/how-to-do-backup-on-tapes-in-linux/">How to Back Up Data on Tapes in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/networking/how-to-do-backup-on-tapes-in-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3330</post-id>	</item>
		<item>
		<title>How to Back Up and Restore a Multi-Volume Archive in Linux</title>
		<link>https://awjunaid.com/networking/how-to-backup-and-restoring-a-multi-volume-archive-in-linux/</link>
					<comments>https://awjunaid.com/networking/how-to-backup-and-restoring-a-multi-volume-archive-in-linux/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Sun, 23 Jul 2023 06:12:42 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=3327</guid>

					<description><![CDATA[<p>Every Linux system administrator eventually runs into the same wall: you need to back up a huge amount&#8230;</p>
<p>The post <a href="https://awjunaid.com/networking/how-to-backup-and-restoring-a-multi-volume-archive-in-linux/">How to Back Up and Restore a Multi-Volume Archive in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Every Linux system administrator eventually runs into the same wall: you need to back up a huge amount of data — maybe hundreds of gigabytes of logs, databases, or user files — but the destination media can&#8217;t hold it all in one piece. Maybe you&#8217;re writing to a stack of DVDs, a set of USB flash drives, or old-school tape media with a fixed capacity. This is exactly the problem that <strong>multi-volume archives</strong> solve.</p>



<p class="wp-block-paragraph">In this article, we will explain, from first principles, what a multi-volume archive is, why it exists, how the Linux <code>tar</code> command supports it, and how to create and restore one step by step. We&#8217;ll use simple English, real command-line examples, diagrams, and a troubleshooting guide so that both beginners and experienced administrators can use this as a reference.</p>



<h2 class="wp-block-heading">What Is an Archive, Really?</h2>



<p class="wp-block-paragraph">Before we talk about &#8220;multi-volume&#8221; anything, let&#8217;s define an archive. An archive is a single file that contains many other files and directories, bundled together with their names, permissions, and directory structure preserved. On Linux, the classic tool for this is <code>tar</code> (short for <strong>T</strong>ape <strong>AR</strong>chiver — a name that hints at its origins in the days of magnetic tape backups).</p>



<p class="wp-block-paragraph">A normal archive command looks like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -cvf backup.tar /home/user/documents</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">cvf backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">home</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">user</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">documents</span></span></code></pre></div>



<p class="wp-block-paragraph">Here:</p>



<ul class="wp-block-list">
<li><code>-c</code> means <strong>create</strong> a new archive</li>



<li><code>-v</code> means <strong>verbose</strong> (show file names as they&#8217;re archived)</li>



<li><code>-f</code> means the next argument is the <strong>filename</strong> of the archive</li>
</ul>



<p class="wp-block-paragraph">This creates one single file, <code>backup.tar</code>, containing everything under <code>/home/user/documents</code>.</p>



<h2 class="wp-block-heading">The Problem: What If the Data Is Too Big?</h2>



<p class="wp-block-paragraph">Imagine you have 50 GB of data to back up, but your only available media is a set of 4.7 GB DVDs, or a series of 8 GB USB sticks. A single <code>.tar</code> file of 50 GB simply will not fit on any single piece of media. This is the exact problem tape archiving faced decades ago — tapes had fixed lengths, and a backup often needed more tape than one reel could hold.</p>



<p class="wp-block-paragraph">The solution is to <strong>split the single archive into multiple smaller pieces, called volumes</strong>, where each volume fits on one piece of media, and <code>tar</code> knows how to prompt you to insert or specify the next volume when the current one is full.</p>



<p class="wp-block-paragraph">This is different from simply splitting a file into random pieces using a tool like <code>split</code>. A multi-volume tar archive is <em>tar-aware</em> — meaning <code>tar</code> itself understands the volume boundaries, tracks file continuity across volumes (even if a single large file is cut in half between two volumes), and can reassemble everything correctly on restore.</p>



<h2 class="wp-block-heading">How Multi-Volume Archives Work (Conceptually)</h2>



<p class="wp-block-paragraph">Think of it like packing a very large shipment into several boxes because no single box is big enough. Each box (volume) is labeled with a sequence number. When you unpack, you must open the boxes <strong>in the correct order</strong> — box 1, then box 2, then box 3 — otherwise the contents won&#8217;t make sense, especially if one item was too big to fit in a single box and had to be split across two.</p>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart LR
    A[Original Data 50GB] --> B[tar --multi-volume]
    B --> C[Volume 1 - 4.7GB]
    B --> D[Volume 2 - 4.7GB]
    B --> E[Volume 3 - 4.7GB]
    B --> F[... more volumes ...]
    C --> G[Restore: tar -M]
    D --> G
    E --> G
    F --> G
    G --> H[Original Data Restored]</pre></div>



<h2 class="wp-block-heading">Creating a Multi-Volume Archive</h2>



<p class="wp-block-paragraph">The <code>tar</code> command supports multi-volume archiving using the <code>-M</code> (or <code>--multi-volume</code>) flag, combined with <code>-L</code> to specify the size limit per volume (in units of 1024 bytes, i.e., KB), or you can let <code>tar</code> prompt interactively when a volume boundary is reached.</p>



<h3 class="wp-block-heading">Basic Example</h3>



<p class="wp-block-paragraph">Suppose we want to back up <code>/data</code> into volumes of 100 MB each:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar --create --multi-volume --tape-length=102400 --file=backup.tar.vol1 /data</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">create </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">multi</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">volume </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">tape</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">length</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">102400</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">file</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">vol1 </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">data</span></span></code></pre></div>



<p class="wp-block-paragraph">Explanation:</p>



<ul class="wp-block-list">
<li><code>--create</code> – create a new archive</li>



<li><code>--multi-volume</code> (<code>-M</code>) – enable multi-volume mode</li>



<li><code>--tape-length=102400</code> (<code>-L</code>) – set the volume size to 102400 KB (100 MB); this name is a holdover from tape backup terminology</li>



<li><code>--file=backup.tar.vol1</code> – the name of the first volume</li>
</ul>



<p class="wp-block-paragraph">When <code>tar</code> reaches the size limit, it will pause and ask:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Prepare volume #2 for 'backup.tar.vol1' and hit return:</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">Prepare volume </span><span style="color: #616E88">#2 for &#39;backup.tar.vol1&#39; and hit return:</span></span></code></pre></div>



<p class="wp-block-paragraph">At this point, in the old tape-based world, you&#8217;d physically swap tapes. On a modern system writing to files (for example, if you&#8217;re staging backups on separate USB drives one at a time), you type a new filename when prompted, or use the <code>-F</code> (<code>--info-script</code>) option to run a script that handles the swap automatically.</p>



<h3 class="wp-block-heading">Non-Interactive Multi-Volume Backup Using a Naming Pattern</h3>



<p class="wp-block-paragraph">For unattended backups, it&#8217;s common to combine <code>-M</code> with a script, or to just create the volumes as separate named files without needing manual intervention, like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -M -L 102400 -cvf backup-vol-%d.tar /data</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">M </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">L </span><span style="color: #B48EAD">102400</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">cvf backup</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">vol</span><span style="color: #81A1C1">-%</span><span style="color: #D8DEE9FF">d</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">data</span></span></code></pre></div>



<p class="wp-block-paragraph">Here <code>%d</code> is replaced with the volume number automatically by <code>tar</code> in newer GNU tar versions, producing files like <code>backup-vol-1.tar</code>, <code>backup-vol-2.tar</code>, and so on.</p>



<h3 class="wp-block-heading">Practical Example: Backing Up to DVD-Sized Volumes</h3>



<p class="wp-block-paragraph">DVDs typically hold about 4.7 GB (4,700,000 KB, though the &#8220;real&#8221; formatted capacity is slightly less). A conservative volume size command:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar --create --multi-volume --tape-length=4500000 \
    --file=/mnt/dvd-staging/backup.tar /var/www /etc /home</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">create </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">multi</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">volume </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">tape</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">length</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">4500000</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">file</span><span style="color: #81A1C1">=/</span><span style="color: #D8DEE9FF">mnt</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">dvd</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">staging</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">var</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">www </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">etc </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">home</span></span></code></pre></div>



<p class="wp-block-paragraph">This creates volume files sized to comfortably fit on a 4.7 GB DVD, leaving a small safety margin for filesystem overhead.</p>



<h2 class="wp-block-heading">Restoring a Multi-Volume Archive</h2>



<p class="wp-block-paragraph">Restoring uses the same <code>-M</code> flag but with the <code>-x</code> (extract) option instead of <code>-c</code> (create):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar --extract --multi-volume --file=backup.tar.vol1</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">extract </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">multi</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">volume </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">file</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">vol1</span></span></code></pre></div>



<p class="wp-block-paragraph">When <code>tar</code> reaches the end of the first volume&#8217;s data, it will prompt:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Prepare volume #2 for 'backup.tar.vol1' and hit return:</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">Prepare volume </span><span style="color: #616E88">#2 for &#39;backup.tar.vol1&#39; and hit return:</span></span></code></pre></div>



<p class="wp-block-paragraph">If your volumes are named sequentially (<code>backup.tar.vol1</code>, <code>backup.tar.vol2</code>, &#8230;), you can type the next filename at the prompt, or better, use the <code>-F</code> info-script option to automate the process:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -Mx -f backup.tar.vol1 -F ./next-volume.sh</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">Mx </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">f backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">vol1 </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">F </span><span style="color: #ECEFF4">.</span><span style="color: #81A1C1">/</span><span style="color: #88C0D0">next</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">volume</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">sh</span></span></code></pre></div>



<p class="wp-block-paragraph">Where <code>next-volume.sh</code> is a small script that tells <code>tar</code> the name of the next volume automatically, based on the <code>TAR_VOLUME</code> environment variable that <code>tar</code> sets for the script.</p>



<h3 class="wp-block-heading">Example <code>next-volume.sh</code> Script</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#!/bin/bash
# tar calls this script when it needs the next volume
# It expects the script to echo the next volume's filename to stdout
echo "backup.tar.vol${TAR_VOLUME}"</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">#!/bin/bash</span></span>
<span class="line"><span style="color: #616E88"># tar calls this script when it needs the next volume</span></span>
<span class="line"><span style="color: #616E88"># It expects the script to echo the next volume&#39;s filename to stdout</span></span>
<span class="line"><span style="color: #D8DEE9FF">echo </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">backup.tar.vol$</span><span style="color: #EBCB8B">{TAR_VOLUME}</span><span style="color: #ECEFF4">&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">Make it executable:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>chmod +x next-volume.sh</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">chmod </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF">x </span><span style="color: #88C0D0">next</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">volume</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">sh</span></span></code></pre></div>



<h2 class="wp-block-heading">A Complete Walkthrough Example</h2>



<p class="wp-block-paragraph">Let&#8217;s walk through a full, realistic scenario: backing up a 10 GB directory into 2 GB volumes on a Linux server, then restoring it onto a different machine.</p>



<p class="wp-block-paragraph"><strong>Step 1: Create the archive</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar --create --multi-volume --tape-length=2097152 \
    --file=/backups/website-backup.tar /var/www/html</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">create </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">multi</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">volume </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">tape</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">length</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">2097152</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">file</span><span style="color: #81A1C1">=/</span><span style="color: #D8DEE9FF">backups</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">website</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">var</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">www</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">html</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Step 2: Respond to volume prompts (or automate with a script)</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Prepare volume #2 for '/backups/website-backup.tar' and hit return:
n website-backup.tar.2</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">Prepare volume </span><span style="color: #616E88">#2 for &#39;/backups/website-backup.tar&#39; and hit return:</span></span>
<span class="line"><span style="color: #D8DEE9FF">n website</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">2</span></span></code></pre></div>



<p class="wp-block-paragraph">Typing <code>n website-backup.tar.2</code> tells <code>tar</code> the new filename for volume 2.</p>



<p class="wp-block-paragraph"><strong>Step 3: Verify the volumes exist</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>ls -lh /backups/website-backup.tar*</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">ls </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">lh </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backups</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">website</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #81A1C1">*</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Step 4: Transfer volumes to the restore target</strong> (using <code>scp</code>, external drive, etc.)</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>scp /backups/website-backup.tar* admin@newserver:/restore/</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">scp </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backups</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">website</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> admin</span><span style="color: #81A1C1">@</span><span style="color: #D8DEE9FF">newserver</span><span style="color: #ECEFF4">:</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">restore</span><span style="color: #81A1C1">/</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Step 5: Restore on the new server</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>cd /restore
tar --extract --multi-volume --file=website-backup.tar</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">cd </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">restore</span></span>
<span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">extract </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">multi</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">volume </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">file</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">website</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span></span></code></pre></div>



<p class="wp-block-paragraph">Respond to volume prompts the same way as during creation.</p>



<p class="wp-block-paragraph"><strong>Step 6: Verify the restored data</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>diff -r /var/www/html /restore/var/www/html</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">diff </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">r </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">var</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">www</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">html </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">restore</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">var</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">www</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">html</span></span></code></pre></div>



<h2 class="wp-block-heading">Comparison: Single-Volume vs. Multi-Volume Archives</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Feature</th><th>Single-Volume Archive</th><th>Multi-Volume Archive</th></tr></thead><tbody><tr><td>Fits on one media device</td><td>Yes (if small enough)</td><td>No — spans several devices/files</td></tr><tr><td>Command flag</td><td>none needed (default)</td><td><code>-M</code> / <code>--multi-volume</code></td></tr><tr><td>Handles files larger than one volume</td><td>N/A</td><td>Yes, files are split across volumes</td></tr><tr><td>Restore complexity</td><td>Simple, one command</td><td>Requires volume prompts or scripting</td></tr><tr><td>Common use case</td><td>Small backups, config files</td><td>Large backups, legacy tape systems, offline media transport</td></tr><tr><td>Automation friendliness</td><td>Very easy</td><td>Needs <code>-F</code> info-scripts for smooth automation</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Real-World Use Cases</h2>



<ol class="wp-block-list">
<li><strong>Offline data transport</strong>: Transferring a large database dump to an air-gapped, secure network via a stack of USB drives, where no single drive is large enough.</li>



<li><strong>Legacy tape backup systems</strong>: Enterprises still running LTO tape drives for compliance-driven long-term archival often rely on multi-volume tar behavior baked into their backup software.</li>



<li><strong>DVD/Blu-ray archival</strong>: Small businesses without cloud backup budgets sometimes still archive project files to optical media in multi-volume sets.</li>



<li><strong>Bandwidth-limited cloud uploads</strong>: Splitting a huge archive into fixed-size chunks so each chunk can be retried independently if an upload fails, without re-uploading everything.</li>
</ol>



<h2 class="wp-block-heading">Best Practices</h2>



<ul class="wp-block-list">
<li><strong>Always verify your volumes after creation.</strong> Use <code>tar --list --multi-volume --file=vol1</code> to confirm the archive&#8217;s table of contents is intact before you rely on it.</li>



<li><strong>Keep volume naming consistent and sequential.</strong> Avoid renaming volumes after creation; <code>tar</code> expects to find them by the name pattern you used, or by prompt-response, in the correct order.</li>



<li><strong>Document your volume size choice.</strong> Write down the exact <code>--tape-length</code> value used, so future restores (possibly by a different administrator) know what to expect.</li>



<li><strong>Test restores regularly.</strong> A backup you have never restored is not a real backup. Periodically do a full multi-volume restore into a scratch directory to confirm every volume works.</li>



<li><strong>Use checksums.</strong> Generate an <code>sha256sum</code> for each volume file right after backup, and store the checksums separately, so you can detect corruption before attempting a restore.</li>



<li><strong>Automate volume swapping wherever possible</strong> using <code>-F</code> info-scripts to avoid human error during long unattended backup windows.</li>



<li><strong>Store volumes in the correct order</strong> if using physical media (label them clearly: Volume 1 of 5, Volume 2 of 5, etc.).</li>
</ul>



<h2 class="wp-block-heading">Troubleshooting</h2>



<p class="wp-block-paragraph"><strong>Problem: <code>tar: This does not look like a tar archive</code></strong></p>



<p class="wp-block-paragraph">This usually happens when you try to extract starting from the wrong volume, or a volume file got corrupted or truncated during transfer. Always start extraction from volume 1, and verify the file sizes match the source.</p>



<h3 class="wp-block-heading">Problem: <code>tar</code> doesn&#8217;t prompt for the next volume in a non-interactive script</h3>



<p class="wp-block-paragraph">If you&#8217;re running <code>tar</code> inside a script or cron job, an interactive prompt will hang forever waiting for input. Always use the <code>-F</code> info-script option for unattended multi-volume operations instead of relying on interactive prompts.</p>



<h3 class="wp-block-heading">Problem: Restored files are incomplete or truncated</h3>



<p class="wp-block-paragraph">This is almost always a sign that a volume was skipped, corrupted, or restored out of order. Re-check the sequence of volume files and re-verify their checksums against the ones generated at backup time.</p>



<h3 class="wp-block-heading">Problem: Volume sizes don&#8217;t match what you specified</h3>



<p class="wp-block-paragraph">Remember that <code>--tape-length</code> is measured in kilobytes (1024-byte units), and the <em>actual</em> final volume in a set will normally be smaller than the others, since it just contains the remaining data. This is expected behavior, not an error.</p>



<h3 class="wp-block-heading">Problem: Insufficient permissions when restoring system files</h3>



<p class="wp-block-paragraph">Multi-volume restores that include system directories like <code>/etc</code> typically need to run as root:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar --extract --multi-volume --file=backup.tar.vol1</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">sudo tar </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">extract </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">multi</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">volume </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">file</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">vol1</span></span></code></pre></div>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">Multi-volume archives solve a very old but still very real problem: how do you back up data that&#8217;s larger than any single piece of media you have available? By understanding how <code>tar</code>&#8216;s <code>-M</code> and <code>-L</code> options work, how volume prompts and info-scripts function, and how to verify and automate the process, you can confidently back up and restore datasets of any size — from a home server&#8217;s photo collection to an enterprise database spanning dozens of gigabytes.</p>



<p class="wp-block-paragraph">The key takeaways are: always test your restores, automate volume handling with scripts for unattended jobs, keep volumes in strict sequential order, and verify integrity with checksums. With these practices in place, multi-volume archiving becomes a reliable, professional-grade backup strategy rather than a source of anxiety.</p>



<h2 class="wp-block-heading">Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://www.gnu.org/software/tar/manual/html_node/Multi_002dVolume-Archives.html">GNU Tar Manual — Multi-Volume Archives</a></li>



<li><a href="https://www.gnu.org/software/tar/manual/tar.html">GNU Tar Manual — Full Reference</a></li>



<li><a href="https://man7.org/linux/man-pages/man1/tar.1.html">Linux man page for tar</a></li>



<li><a href="https://access.redhat.com/documentation">Red Hat: Backing up and restoring data</a></li>



<li><a href="https://wiki.archlinux.org/title/Tar">Arch Wiki: Tar</a></li>



<li><a href="https://debian-handbook.info/">Debian Administrator&#8217;s Handbook — Backup</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/networking/how-to-backup-and-restoring-a-multi-volume-archive-in-linux/">How to Back Up and Restore a Multi-Volume Archive in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/networking/how-to-backup-and-restoring-a-multi-volume-archive-in-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3327</post-id>	</item>
		<item>
		<title>How to Back Up and Restore a Single-Volume Archive in Linux</title>
		<link>https://awjunaid.com/networking/how-to-backup-and-restoring-a-single-volume-archive-in-linux/</link>
					<comments>https://awjunaid.com/networking/how-to-backup-and-restoring-a-single-volume-archive-in-linux/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Sun, 23 Jul 2023 06:09:43 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=3324</guid>

					<description><![CDATA[<p>Backing up data is one of the most fundamental responsibilities of any Linux user or system administrator. Before&#8230;</p>
<p>The post <a href="https://awjunaid.com/networking/how-to-backup-and-restoring-a-single-volume-archive-in-linux/">How to Back Up and Restore a Single-Volume Archive in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Backing up data is one of the most fundamental responsibilities of any Linux user or system administrator. Before diving into complex, multi-device backup strategies, every admin needs to master the simplest and most common case: the <strong>single-volume archive</strong> — one archive file that contains all of your backed-up data, small enough to fit entirely on one piece of media or in one file on disk.</p>



<p class="wp-block-paragraph">This article explains, from first principles, what an archive is, how the <code>tar</code> command works, how to create and restore a single-volume archive, how compression fits in, and how to troubleshoot common problems — all illustrated with practical, real-world examples.</p>



<h2 class="wp-block-heading">What Is a Single-Volume Archive?</h2>



<p class="wp-block-paragraph">A single-volume archive is exactly what it sounds like: <strong>one file</strong> that contains a bundle of other files and directories, with no need to split the data across multiple pieces. Compare this to a multi-volume archive (used when data is too large for one piece of media), which we cover in a separate article.</p>



<p class="wp-block-paragraph">For most everyday backup jobs — a home directory, a website&#8217;s files, a set of configuration files — a single-volume archive is all you need, because modern storage (hard drives, SSDs, cloud storage) can typically hold gigabytes or terabytes in a single file without any issue.</p>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart TD
    A[Source Files and Directories] -->|tar -cvf| B[Single Archive File: backup.tar]
    B -->|tar -xvf| A2[Restored Files and Directories]
</pre></div>



<h2 class="wp-block-heading">The <code>tar</code> Command: The Foundation</h2>



<p class="wp-block-paragraph">The <code>tar</code> utility (Tape Archiver) is the standard Linux tool for creating archives. Its basic syntax is:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar &#91;options&#93; -f archive-name.tar file-or-directory</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9FF">options</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">f archive</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">name</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar file</span><span style="color: #81A1C1">-or-</span><span style="color: #D8DEE9FF">directory</span></span></code></pre></div>



<h3 class="wp-block-heading">Creating an Archive</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -cvf home-backup.tar /home/username</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">cvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">home</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">username</span></span></code></pre></div>



<p class="wp-block-paragraph">Breaking this down:</p>



<ul class="wp-block-list">
<li><code>-c</code> = <strong>create</strong> a new archive</li>



<li><code>-v</code> = <strong>verbose</strong>, print each filename as it&#8217;s processed</li>



<li><code>-f</code> = specify the <strong>filename</strong> of the archive (must be followed immediately by the filename)</li>
</ul>



<p class="wp-block-paragraph">This command bundles everything under <code>/home/username</code> into a single file called <code>home-backup.tar</code>.</p>



<h3 class="wp-block-heading">Listing Contents Without Extracting</h3>



<p class="wp-block-paragraph">Before restoring, it&#8217;s good practice to check what&#8217;s inside an archive:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -tvf home-backup.tar</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">tvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>-t</code> flag lists the table of contents.</p>



<h3 class="wp-block-heading">Restoring (Extracting) an Archive</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -xvf home-backup.tar</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span></span></code></pre></div>



<ul class="wp-block-list">
<li><code>-x</code> = <strong>extract</strong></li>



<li>Files are restored relative to the current directory, preserving the original directory structure recorded in the archive.</li>
</ul>



<p class="wp-block-paragraph">To restore to a specific location:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -xvf home-backup.tar -C /restore/destination</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">C </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">restore</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">destination</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>-C</code> flag changes the extraction directory before extracting.</p>



<h2 class="wp-block-heading">Adding Compression</h2>



<p class="wp-block-paragraph">A plain <code>tar</code> file is not compressed — it&#8217;s just a bundle. To save space, you compress it, typically with <code>gzip</code> or <code>bzip2</code> or the newer <code>xz</code>.</p>



<h3 class="wp-block-heading">Creating a Compressed Archive</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -czvf home-backup.tar.gz /home/username</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">czvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">home</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">username</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>-z</code> flag tells <code>tar</code> to pipe the output through <code>gzip</code>.</p>



<p class="wp-block-paragraph">For better compression at the cost of speed:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -cjvf home-backup.tar.bz2 /home/username   # bzip2
tar -cJvf home-backup.tar.xz /home/username    # xz</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">cjvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">bz2 </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">home</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">username   </span><span style="color: #616E88"># bzip2</span></span>
<span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">cJvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">xz </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">home</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">username    </span><span style="color: #616E88"># xz</span></span></code></pre></div>



<h3 class="wp-block-heading">Restoring a Compressed Archive</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -xzvf home-backup.tar.gz
tar -xjvf home-backup.tar.bz2
tar -xJvf home-backup.tar.xz</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xzvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz</span></span>
<span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xjvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">bz2</span></span>
<span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xJvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">xz</span></span></code></pre></div>



<p class="wp-block-paragraph">Modern GNU <code>tar</code> can actually auto-detect the compression type even without the <code>-z</code>/<code>-j</code>/<code>-J</code> flag, so <code>tar -xvf home-backup.tar.gz</code> will often &#8220;just work&#8221; — but specifying the flag explicitly is still good practice for clarity and portability.</p>



<h2 class="wp-block-heading">Comparison Table: Compression Options</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Method</th><th>Flag</th><th>Speed</th><th>Compression Ratio</th><th>Typical Use Case</th></tr></thead><tbody><tr><td>None</td><td>(none)</td><td>Fastest</td><td>None</td><td>Archives that will be compressed later, or already-compressed data</td></tr><tr><td>gzip</td><td><code>-z</code></td><td>Fast</td><td>Moderate</td><td>General-purpose, most common default</td></tr><tr><td>bzip2</td><td><code>-j</code></td><td>Slower</td><td>Better than gzip</td><td>When storage space matters more than speed</td></tr><tr><td>xz</td><td><code>-J</code></td><td>Slowest</td><td>Best</td><td>Long-term archival, minimizing storage cost</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">A Practical, Real-World Example</h2>



<p class="wp-block-paragraph">Let&#8217;s back up an Nginx web server&#8217;s configuration and content directory before making risky changes.</p>



<p class="wp-block-paragraph"><strong>Step 1: Create the backup</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -czvf /backups/nginx-backup-$(date +%F).tar.gz /etc/nginx /var/www</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">sudo tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">czvf </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backups</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">nginx</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">date </span><span style="color: #81A1C1">+%</span><span style="color: #D8DEE9FF">F</span><span style="color: #ECEFF4">).</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">etc</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">nginx </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">var</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">www</span></span></code></pre></div>



<p class="wp-block-paragraph">This uses <code>$(date +%F)</code> to automatically insert today&#8217;s date (e.g., <code>2026-07-24</code>) into the filename, so backups don&#8217;t overwrite each other.</p>



<p class="wp-block-paragraph"><strong>Step 2: Confirm it worked</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>ls -lh /backups/
tar -tzvf /backups/nginx-backup-2026-07-24.tar.gz | head -20</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">ls </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">lh </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backups</span><span style="color: #81A1C1">/</span></span>
<span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">tzvf </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backups</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">nginx</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">2026</span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9">7</span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">24.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> head </span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">20</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Step 3: Simulate a disaster — restore it</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -xzvf /backups/nginx-backup-2026-07-24.tar.gz -C /</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">sudo tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xzvf </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backups</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">nginx</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">2026</span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9">7</span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">24.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">C </span><span style="color: #81A1C1">/</span></span></code></pre></div>



<p class="wp-block-paragraph">Because the archive was created with absolute paths (<code>/etc/nginx</code>, <code>/var/www</code>), extracting with <code>-C /</code> restores the files to their original locations.</p>



<h2 class="wp-block-heading">Preserving Permissions and Ownership</h2>



<p class="wp-block-paragraph">By default, <code>tar</code> preserves file permissions, ownership, and timestamps as recorded in the archive — but only if you&#8217;re extracting as <code>root</code>. If you extract as a normal user, ownership may be changed to that user instead.</p>



<p class="wp-block-paragraph">To force preservation of original ownership during extraction (as root):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -xpvf home-backup.tar</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">sudo tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xpvf home</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>-p</code> flag means <strong>preserve permissions</strong>.</p>



<h2 class="wp-block-heading">Excluding Files From a Backup</h2>



<p class="wp-block-paragraph">Often you don&#8217;t want everything in a directory — for example, you might want to skip cache files or log files:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -czvf project-backup.tar.gz --exclude='*.log' --exclude='node_modules' /srv/project</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">czvf project</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">exclude</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">*.log</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">--</span><span style="color: #D8DEE9FF">exclude</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">node_modules</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">srv</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">project</span></span></code></pre></div>



<p class="wp-block-paragraph">You can also use an exclude file listing multiple patterns:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -czvf project-backup.tar.gz -X excludes.txt /srv/project</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">czvf project</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">X excludes</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">txt </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">srv</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">project</span></span></code></pre></div>



<p class="wp-block-paragraph">Where <code>excludes.txt</code> contains:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>*.log
*.tmp
node_modules/
.git/</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">*</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">log</span></span>
<span class="line"><span style="color: #81A1C1">*</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tmp</span></span>
<span class="line"><span style="color: #D8DEE9FF">node_modules</span><span style="color: #81A1C1">/</span></span>
<span class="line"><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">git</span><span style="color: #81A1C1">/</span></span></code></pre></div>



<h2 class="wp-block-heading">Verifying Archive Integrity</h2>



<p class="wp-block-paragraph">Never trust a backup you haven&#8217;t verified. Two common approaches:</p>



<p class="wp-block-paragraph"><strong>1. Compare against source using <code>diff</code>:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>tar -xzvf backup.tar.gz -C /tmp/verify
diff -r /home/username /tmp/verify/home/username</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xzvf backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">C </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">tmp</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">verify</span></span>
<span class="line"><span style="color: #D8DEE9FF">diff </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">r </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">home</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">username </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">tmp</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">verify</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">home</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">username</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>2. Generate and check a checksum:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sha256sum backup.tar.gz > backup.tar.gz.sha256
sha256sum -c backup.tar.gz.sha256</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">sha256sum backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">sha256</span></span>
<span class="line"><span style="color: #D8DEE9FF">sha256sum </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">c backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">sha256</span></span></code></pre></div>



<h2 class="wp-block-heading">Automating Backups With <code>cron</code></h2>



<p class="wp-block-paragraph">A single-volume archive backup is a perfect candidate for automation. Here&#8217;s a cron job that backs up <code>/etc</code> every night at 2 AM:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>0 2 * * * /usr/bin/tar -czf /backups/etc-backup-$(date +\%F).tar.gz /etc</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">usr</span><span style="color: #81A1C1">/</span><span style="color: #88C0D0">bin</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">czf </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backups</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">etc</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">backup</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">date </span><span style="color: #81A1C1">+</span><span style="color: #ECEFF4">\</span><span style="color: #D8DEE9">%F).tar.gz /etc</span></span></code></pre></div>



<p class="wp-block-paragraph">Note the escaped <code>%</code> (<code>\%</code>) — cron interprets unescaped <code>%</code> characters as newlines, so they must be escaped inside crontab entries.</p>



<h2 class="wp-block-heading">Real-World Use Cases</h2>



<ol class="wp-block-list">
<li><strong>Website migrations</strong>: Archiving an entire web application directory before moving it to a new server.</li>



<li><strong>Configuration snapshots</strong>: Taking a <code>tar</code> snapshot of <code>/etc</code> before a major system upgrade, so changes can be rolled back if something breaks.</li>



<li><strong>Developer environment backups</strong>: Archiving a project directory (excluding build artifacts) before a risky refactor.</li>



<li><strong>User data migration</strong>: Backing up a single user&#8217;s home directory before reinstalling the OS.</li>
</ol>



<h2 class="wp-block-heading">Best Practices</h2>



<ul class="wp-block-list">
<li><strong>Always test extraction</strong> in a scratch directory before trusting a backup for disaster recovery.</li>



<li><strong>Use compression thoughtfully</strong> — <code>gzip</code> for speed, <code>xz</code> for maximum space savings on long-term cold storage.</li>



<li><strong>Include a timestamp in the filename</strong> so successive backups don&#8217;t silently overwrite each other.</li>



<li><strong>Exclude unnecessary files</strong> (caches, logs, build artifacts) to keep archives lean and restore times fast.</li>



<li><strong>Store backups off-machine.</strong> A backup stored only on the same disk as the original data offers no protection against disk failure.</li>



<li><strong>Automate with cron or systemd timers</strong>, and monitor for job failures (e.g., email alerts on non-zero exit codes).</li>



<li><strong>Document restore procedures</strong> so that anyone on the team, not just the person who created the backup, can perform a restore.</li>
</ul>



<h2 class="wp-block-heading">Troubleshooting</h2>



<h3 class="wp-block-heading">Problem: <code>tar: Cannot open: Permission denied</code></h3>



<p class="wp-block-paragraph">You likely need <code>sudo</code> to read protected system files, or to write to the destination directory. Re-run with elevated privileges:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -czvf backup.tar.gz /etc</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">sudo tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">czvf backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">etc</span></span></code></pre></div>



<h3 class="wp-block-heading">Problem: Archive is larger than expected</h3>



<p class="wp-block-paragraph">Check whether you&#8217;re accidentally including large, unnecessary directories like <code>node_modules</code>, <code>.git</code>, or log directories. Use <code>--exclude</code> to trim them out, or inspect with <code>tar -tzvf backup.tar.gz | wc -l</code> to count files.</p>



<h3 class="wp-block-heading">Problem: <code>gzip: stdin: not in gzip format</code></h3>



<p class="wp-block-paragraph">This means the file isn&#8217;t actually gzip-compressed, even though it might have a <code>.gz</code> extension — perhaps it&#8217;s a plain <code>.tar</code> that was renamed. Check with:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>file backup.tar.gz</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">file backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">gz</span></span></code></pre></div>



<h3 class="wp-block-heading">Problem: Restored files have the wrong owner</h3>



<p class="wp-block-paragraph">You likely extracted as a non-root user. Re-extract as root with <code>-p</code> to preserve original ownership:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>sudo tar -xpvf backup.tar</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">sudo tar </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">xpvf backup</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">tar</span></span></code></pre></div>



<h3 class="wp-block-heading">Problem: &#8220;Not enough space&#8221; during extraction</h3>



<p class="wp-block-paragraph">Check available disk space with <code>df -h</code> before extracting large archives, and extract to a partition with sufficient free space.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">The single-volume archive is the workhorse of Linux backups. With just a handful of <code>tar</code> flags — <code>-c</code>, <code>-x</code>, <code>-v</code>, <code>-f</code>, <code>-z</code>/<code>-j</code>/<code>-J</code>, and <code>-C</code> — you can confidently back up and restore anything from a single configuration file to an entire application directory. Combine this with compression, exclusion rules, integrity verification, and cron-based automation, and you have a simple, dependable, and completely free backup system built entirely from tools that ship with every Linux distribution.</p>



<h2 class="wp-block-heading">Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://www.gnu.org/software/tar/manual/tar.html">GNU Tar Manual</a></li>



<li><a href="https://man7.org/linux/man-pages/man1/tar.1.html">tar(1) man page</a></li>



<li><a href="https://man7.org/linux/man-pages/man1/gzip.1.html">gzip(1) man page</a></li>



<li><a href="https://wiki.archlinux.org/title/Tar">Arch Wiki: Tar</a></li>



<li><a href="https://man7.org/linux/man-pages/man5/crontab.5.html">Cron job syntax reference</a></li>



<li><a href="https://access.redhat.com/documentation">Red Hat System Administrator&#8217;s Guide — Backups</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/networking/how-to-backup-and-restoring-a-single-volume-archive-in-linux/">How to Back Up and Restore a Single-Volume Archive in Linux</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/networking/how-to-backup-and-restoring-a-single-volume-archive-in-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3324</post-id>	</item>
		<item>
		<title>Performance Metrics, Parameters, and Purposes of Storage/Host Tools: A Complete Guide</title>
		<link>https://awjunaid.com/storage/performance-metrics-parameters-and-purposes-of-storage-host-tools/</link>
					<comments>https://awjunaid.com/storage/performance-metrics-parameters-and-purposes-of-storage-host-tools/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Wed, 12 Jul 2023 02:48:52 +0000</pubDate>
				<category><![CDATA[Storage]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=2732</guid>

					<description><![CDATA[<p>I have spent a good chunk of my career staring at dashboards, log files, and command-line outputs trying&#8230;</p>
<p>The post <a href="https://awjunaid.com/storage/performance-metrics-parameters-and-purposes-of-storage-host-tools/">Performance Metrics, Parameters, and Purposes of Storage/Host Tools: A Complete Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I have spent a good chunk of my career staring at dashboards, log files, and command-line outputs trying to figure out why a database was crawling or why a virtual machine froze during a backup window. Every single time, the answer was hiding inside a performance metric I hadn&#8217;t paid enough attention to. In this article, I want to walk you through everything I know about storage and host performance tools — what they measure, why those measurements matter, and how I personally use them to keep systems healthy.</p>



<p class="wp-block-paragraph">This is a long read, but I have tried to structure it so a beginner can follow along from the basics and an experienced storage administrator can jump straight to the sections on tuning, troubleshooting, and enterprise deployment.</p>



<h2 class="wp-block-heading">Why Performance Metrics Matter in the First Place</h2>



<p class="wp-block-paragraph">Every storage system — whether it is a single NVMe drive in a laptop or a multi-petabyte SAN array — is a chain of components: application, operating system, host bus adapter (HBA) or network interface card (NIC), fabric or network, controller, cache, and physical media. A chain is only as fast as its weakest link, and metrics are how I find that weak link before it becomes an outage.</p>



<p class="wp-block-paragraph">Without metrics, storage administration is guesswork. With them, I can answer questions like:</p>



<ul class="wp-block-list">
<li>Is my storage array the bottleneck, or is it the network fabric?</li>



<li>Is the application generating too many small random I/Os?</li>



<li>Is my SSD wearing out faster than expected?</li>



<li>Will this workload still perform well if I double the number of virtual machines?</li>
</ul>



<h2 class="wp-block-heading">Core Performance Metrics I Track</h2>



<h3 class="wp-block-heading">1. IOPS (Input/Output Operations Per Second)</h3>



<p class="wp-block-paragraph">IOPS tells me how many read or write operations a device or system can handle every second. It is the single most quoted metric in storage sizing conversations, but it is also the most misunderstood because IOPS numbers change dramatically based on block size and read/write mix.</p>



<p class="wp-block-paragraph">A rough formula I use when estimating IOPS capability of spinning disks:</p>



<pre class="wp-block-code"><code>IOPS ≈ 1 / (Seek Time + Rotational Latency + Transfer Time)
</code></pre>



<p class="wp-block-paragraph">For a 15K RPM enterprise HDD:</p>



<ul class="wp-block-list">
<li>Average seek time: ~3.5 ms</li>



<li>Rotational latency: ~2 ms (half of 4ms per rotation at 15,000 RPM)</li>



<li>Transfer time: negligible for small blocks</li>
</ul>



<pre class="wp-block-code"><code>IOPS ≈ 1 / (0.0035 + 0.002) ≈ 180 IOPS per disk
</code></pre>



<p class="wp-block-paragraph">Compare that to an enterprise NVMe SSD, which can deliver anywhere from 100,000 to over 1,000,000 IOPS depending on queue depth and block size. This gap is exactly why I always ask &#8220;what block size and queue depth were used?&#8221; before trusting any vendor IOPS number.</p>



<h3 class="wp-block-heading">2. Throughput (MB/s or GB/s)</h3>



<p class="wp-block-paragraph">Throughput measures how much data moves per second. IOPS and throughput are related by block size:</p>



<pre class="wp-block-code"><code>Throughput = IOPS × Block Size
</code></pre>



<p class="wp-block-paragraph">Example: 10,000 IOPS at a 4KB block size gives roughly 39 MB/s, while the same 10,000 IOPS at a 256KB block size gives roughly 2.5 GB/s. This is why a system tuned for database transaction logs (small, random I/O) looks completely different from one tuned for video streaming or backup jobs (large, sequential I/O).</p>



<h3 class="wp-block-heading">3. Latency</h3>



<p class="wp-block-paragraph">Latency is the time between issuing an I/O request and receiving the acknowledgment. I consider this the most important metric of all, because users feel latency directly — nobody notices IOPS, but everybody notices a slow application.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Storage Type</th><th>Typical Latency</th></tr></thead><tbody><tr><td>NVMe SSD (enterprise)</td><td>20–100 microseconds</td></tr><tr><td>SATA/SAS SSD</td><td>100–500 microseconds</td></tr><tr><td>15K RPM HDD</td><td>3–5 milliseconds</td></tr><tr><td>7.2K RPM HDD</td><td>8–12 milliseconds</td></tr><tr><td>Cloud block storage (network-attached)</td><td>1–10 milliseconds</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">4. Queue Depth</h3>



<p class="wp-block-paragraph">Queue depth is the number of outstanding I/O requests waiting to be serviced. A higher queue depth generally increases throughput and IOPS up to a saturation point, after which latency spikes sharply. I always look at queue depth alongside latency, never in isolation.</p>



<h3 class="wp-block-heading">5. CPU Utilization on Storage Controllers and Hosts</h3>



<p class="wp-block-paragraph">Storage performance is not purely a disk problem. I have seen arrays with plenty of free IOPS capacity that were still slow because the storage controller&#8217;s CPU was pegged at 100% doing data reduction (deduplication/compression) or RAID parity calculations.</p>



<h3 class="wp-block-heading">6. Cache Hit Ratio</h3>



<p class="wp-block-paragraph">Most storage systems and hosts use some form of read/write caching (DRAM, NVDIMM, or flash-based). The cache hit ratio tells me what percentage of requests are served from fast cache versus slower backend media.</p>



<pre class="wp-block-code"><code>Cache Hit Ratio (%) = (Cache Hits / Total Requests) × 100
</code></pre>



<p class="wp-block-paragraph">A ratio above 90% for read-heavy workloads is generally considered healthy; anything lower and I start investigating working-set size versus cache size.</p>



<h2 class="wp-block-heading">Host-Side and Storage-Side Tools I Rely On</h2>



<h3 class="wp-block-heading">Linux Host Tools</h3>



<p class="wp-block-paragraph"><strong>iostat</strong> — my go-to for a quick health check:</p>



<pre class="wp-block-code"><code>iostat -xz 2 5
</code></pre>



<p class="wp-block-paragraph">This gives extended stats every 2 seconds, 5 times, showing <code>%util</code>, <code>await</code> (latency), <code>r/s</code>, <code>w/s</code>, and <code>avgqu-sz</code> (queue depth) per device.</p>



<p class="wp-block-paragraph"><strong>vmstat</strong> — useful for correlating storage waits with CPU and memory pressure:</p>



<pre class="wp-block-code"><code>vmstat 1 10
</code></pre>



<p class="wp-block-paragraph"><strong>sar</strong> — historical performance data collected by <code>sysstat</code>:</p>



<pre class="wp-block-code"><code>sar -d -f /var/log/sysstat/sa15
</code></pre>



<p class="wp-block-paragraph"><strong>nvme-cli</strong> — for NVMe-specific health and performance data:</p>



<pre class="wp-block-code"><code>nvme smart-log /dev/nvme0
</code></pre>



<p class="wp-block-paragraph">This shows temperature, percentage used (wear), and error counts directly from the drive&#8217;s SMART data.</p>



<h3 class="wp-block-heading">Windows Host Tools</h3>



<ul class="wp-block-list">
<li><strong>Performance Monitor (perfmon)</strong> — I add counters like <code>LogicalDisk\Avg. Disk sec/Read</code>, <code>LogicalDisk\Avg. Disk sec/Write</code>, and <code>LogicalDisk\Current Disk Queue Length</code>.</li>



<li><strong>PowerShell Get-Counter</strong>:</li>
</ul>



<pre class="wp-block-code"><code>Get-Counter '\LogicalDisk(*)\Avg. Disk sec/Transfer' -Continuous
</code></pre>



<h3 class="wp-block-heading">VMware / Virtualization Tools</h3>



<ul class="wp-block-list">
<li><strong>esxtop</strong> — the definitive tool for host-level storage stats in ESXi. I typically switch to the disk device view (<code>u</code>) and watch <code>DAVG/cmd</code> (device latency), <code>KAVG/cmd</code> (kernel latency), and <code>GAVG/cmd</code> (guest-perceived latency).</li>



<li><strong>vROps (vRealize Operations)</strong> — for trend analysis and capacity forecasting across clusters.</li>
</ul>



<h3 class="wp-block-heading">Storage Array Vendor Tools</h3>



<ul class="wp-block-list">
<li><strong>Dell EMC Unisphere / CloudIQ</strong> — array-level dashboards for latency, IOPS, and predictive analytics.</li>



<li><strong>NetApp Active IQ / OnCommand Unified Manager</strong> — performance advisor with QoS policy visibility.</li>



<li><strong>HPE InfoSight</strong> — AI-driven anomaly detection built into HPE Alletra/Nimble/3PAR arrays.</li>



<li><strong>IBM Storage Insights</strong> — cloud-based monitoring for IBM FlashSystem and DS8000.</li>



<li><strong>Cisco Nexus Dashboard / DCNM</strong> — SAN fabric health, port utilization, and zoning diagnostics for Fibre Channel environments.</li>
</ul>



<h3 class="wp-block-heading">SAN/Fabric-Level Tools</h3>



<ul class="wp-block-list">
<li><strong>Fibre Channel switch CLI</strong> (Brocade/Cisco MDS): <code>portperfshow</code> (Brocade) or <code>show interface counters</code> (Cisco) to check for CRC errors, link resets, and port congestion.</li>



<li><strong>SNIA SNMS (Storage Network Management)</strong> frameworks for cross-vendor visibility.</li>
</ul>



<h2 class="wp-block-heading">A Simple Architecture Diagram</h2>



<pre class="wp-block-code"><code>&#91;Application]
     |
&#91;Host OS / File System]
     |
&#91;HBA / NIC]  ---&gt;  &#91;SAN Fabric / Network]  ---&gt;  &#91;Storage Controller]
     |                                                   |
&#91;Multipathing]                                    &#91;Cache (DRAM/NVDIMM)]
                                                          |
                                                  &#91;RAID / Erasure Coding]
                                                          |
                                                    &#91;Physical Media]
</code></pre>



<p class="wp-block-paragraph">Every layer in this diagram has its own metrics, and a mature monitoring strategy captures data at each layer, not just at the array.</p>



<h2 class="wp-block-heading">Putting It All Together: A Troubleshooting Workflow</h2>



<p class="wp-block-paragraph">When I get a &#8220;storage is slow&#8221; ticket, I follow roughly this sequence:</p>



<ol class="wp-block-list">
<li>Check host-level latency (<code>iostat</code>, <code>esxtop</code>) to confirm the complaint is real and not application-side.</li>



<li>Check queue depth and <code>%util</code> to see if the host is saturating its path.</li>



<li>Check HBA/NIC error counters for retransmits, CRC errors, or link resets.</li>



<li>Check the SAN fabric for congestion or zoning issues.</li>



<li>Check the array-side controller CPU, cache hit ratio, and per-LUN latency.</li>



<li>Check for noisy-neighbor workloads sharing the same storage pool.</li>



<li>Correlate with recent changes: firmware updates, new VMs, backup jobs, replication schedules.</li>
</ol>



<h2 class="wp-block-heading">Common Mistakes I See</h2>



<ul class="wp-block-list">
<li>Relying only on average latency instead of looking at the 95th/99th percentile, where the real pain usually lives.</li>



<li>Sizing storage based on marketing IOPS numbers that assume 100% read, 4KB block, high queue depth — unrealistic for most production workloads.</li>



<li>Ignoring HBA/NIC-side errors because &#8220;the array dashboard looks fine.&#8221;</li>



<li>Forgetting that thin provisioning and deduplication add CPU overhead that can mask itself as a &#8220;disk problem.&#8221;</li>
</ul>



<h2 class="wp-block-heading">Scalability Considerations</h2>



<p class="wp-block-paragraph">As I scale a storage environment from a handful of hosts to hundreds, the metrics I care about don&#8217;t change, but the way I collect and interpret them does. At small scale, I can eyeball <code>iostat</code> output on a single host. At enterprise scale, I need centralized time-series collection — Prometheus with node_exporter, Grafana dashboards fed from array APIs, or vendor platforms like NetApp Active IQ Unified Manager — because manually checking dozens of arrays and thousands of LUNs simply doesn&#8217;t work. I also start caring about metric retention and trending: a single snapshot of IOPS tells me almost nothing, but 90 days of trend data tells me whether a workload is organically growing toward a capacity or performance cliff.</p>



<h2 class="wp-block-heading">Maintenance and Ongoing Health Checks</h2>



<p class="wp-block-paragraph">Performance monitoring isn&#8217;t a &#8220;set it up once&#8221; task. I build recurring maintenance activities around these tools:</p>



<ul class="wp-block-list">
<li><strong>Weekly</strong>: review top-N busiest LUNs/volumes by IOPS and latency; check for any host with abnormal queue depth.</li>



<li><strong>Monthly</strong>: review firmware/driver versions against vendor interoperability matrices, since outdated multipathing or HBA drivers are a surprisingly common cause of latency regressions.</li>



<li><strong>Quarterly</strong>: re-baseline performance after any significant workload change (new application onboarded, VM count doubled, etc.) using <code>fio</code> or vendor-native benchmarking tools.</li>



<li><strong>Annually</strong>: capacity and performance forecasting review, using historical trend data to predict when the array will need an upgrade or additional nodes.</li>
</ul>



<h2 class="wp-block-heading">Cloud and Hybrid Integration</h2>



<p class="wp-block-paragraph">When workloads move to the cloud, the same metrics still apply, but the tools change. AWS CloudWatch exposes <code>VolumeReadOps</code>, <code>VolumeWriteOps</code>, <code>VolumeQueueLength</code>, and <code>VolumeThroughputPercentage</code> for EBS volumes. Azure Monitor exposes similar metrics for Managed Disks, and Google Cloud&#8217;s Monitoring console does the same for Persistent Disks. In hybrid deployments — where on-prem arrays replicate to cloud storage or where cloud-based DR sites exist — I make a point of validating that monitoring tools on both sides use comparable metric definitions, since a &#8220;read latency&#8221; metric in one platform isn&#8217;t always calculated the same way as in another.</p>



<h2 class="wp-block-heading">Comparing Tool Approaches: Agent-Based vs. Agentless Monitoring</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Approach</th><th>Pros</th><th>Cons</th></tr></thead><tbody><tr><td>Agent-based (installed on host)</td><td>Deep OS-level visibility, granular per-process I/O stats</td><td>Deployment overhead, potential resource consumption</td></tr><tr><td>Agentless (array/API-based)</td><td>Easy to deploy, vendor-supported, less host overhead</td><td>Limited visibility into host-side queuing and application behavior</td></tr><tr><td>Hybrid (both combined)</td><td>Full-stack visibility from application to media</td><td>More complex to set up and correlate</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">I generally recommend a hybrid approach for any environment supporting business-critical applications, since neither agent-based nor agentless monitoring alone tells the complete story.</p>



<h2 class="wp-block-heading">FAQs</h2>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the difference between throughput and bandwidth?</strong> Throughput is the actual measured data transfer rate under a workload; bandwidth is the theoretical maximum a link or device can support (e.g., a 32Gb Fibre Channel port has 32Gb of bandwidth, but real throughput will always be somewhat lower).</p>



<p class="wp-block-paragraph"><strong>Q: Which metric should I prioritize — IOPS or latency?</strong> For most interactive and transactional workloads, I prioritize latency. IOPS matters more for batch or throughput-oriented workloads like backups and analytics.</p>



<p class="wp-block-paragraph"><strong>Q: Do these tools work the same way in cloud environments?</strong> The concepts are identical, but the tools differ. AWS CloudWatch, Azure Monitor, and Google Cloud Monitoring expose similar metrics (IOPS, throughput, latency) for EBS, Managed Disks, and Persistent Disks respectively.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Performance metrics are the language storage systems speak, and host/storage tools are how I translate that language into decisions. IOPS, throughput, latency, queue depth, and cache hit ratio form the foundation; the tools I described — from <code>iostat</code> to vendor platforms like NetApp Active IQ and HPE InfoSight — turn raw numbers into actionable insight. Mastering this combination is, in my experience, what separates a reactive storage admin from a proactive one.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>SNIA (Storage Networking Industry Association) — Dictionary of Storage Terms: https://www.snia.org/education/dictionary</li>



<li>Dell Technologies — Unisphere and CloudIQ Documentation: https://www.dell.com/support</li>



<li>NetApp — Active IQ Documentation: https://docs.netapp.com</li>



<li>HPE — InfoSight Documentation: https://infosight.hpe.com</li>



<li>IBM — Storage Insights Documentation: https://www.ibm.com/docs</li>



<li>VMware — esxtop Performance Guide: https://docs.vmware.com</li>



<li>Cisco — MDS 9000 Series Troubleshooting Guide: https://www.cisco.com/c/en/us/support</li>
</ul>
<p>The post <a href="https://awjunaid.com/storage/performance-metrics-parameters-and-purposes-of-storage-host-tools/">Performance Metrics, Parameters, and Purposes of Storage/Host Tools: A Complete Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/storage/performance-metrics-parameters-and-purposes-of-storage-host-tools/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2732</post-id>	</item>
		<item>
		<title>Storage Device Bandwidth: Properties, Functions, and Why It Shapes Every Storage Decision I Make</title>
		<link>https://awjunaid.com/storage/storage-device-bandwidth-properties-and-functions/</link>
					<comments>https://awjunaid.com/storage/storage-device-bandwidth-properties-and-functions/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Wed, 12 Jul 2023 02:43:23 +0000</pubDate>
				<category><![CDATA[Storage]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=2729</guid>

					<description><![CDATA[<p>Bandwidth is one of those words that gets thrown around loosely in storage conversations — &#8220;we need more&#8230;</p>
<p>The post <a href="https://awjunaid.com/storage/storage-device-bandwidth-properties-and-functions/">Storage Device Bandwidth: Properties, Functions, and Why It Shapes Every Storage Decision I Make</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Bandwidth is one of those words that gets thrown around loosely in storage conversations — &#8220;we need more bandwidth,&#8221; &#8220;the link is bandwidth-constrained&#8221; — but when I actually sit down to design or troubleshoot a storage system, I need to understand exactly what bandwidth means at each layer: the drive itself, the bus connecting it, the network fabric, and the host adapter. This article is my attempt to lay all of that out clearly, from the fundamentals to the enterprise-scale implications.</p>



<h2 class="wp-block-heading">What Bandwidth Actually Means</h2>



<p class="wp-block-paragraph">Bandwidth is the maximum rate at which data can be transferred across a given interface or medium, usually expressed in megabytes per second (MB/s), gigabytes per second (GB/s), or gigabits per second (Gb/s). It is a theoretical ceiling — actual throughput is almost always somewhat lower due to protocol overhead, encoding schemes, and real-world inefficiencies.</p>



<p class="wp-block-paragraph">I like to think of bandwidth as the width of a highway and throughput as how many cars actually get through during rush hour. A wider highway helps, but traffic lights, accidents, and merging lanes (protocol overhead, latency, congestion) all reduce the real flow below the theoretical maximum.</p>



<h2 class="wp-block-heading">Bandwidth at the Drive Level</h2>



<h3 class="wp-block-heading">HDD Bandwidth</h3>



<p class="wp-block-paragraph">Hard disk drives are fundamentally sequential-access-friendly devices. Their sustained bandwidth is a function of areal density and rotational speed.</p>



<pre class="wp-block-code"><code>Sustained Bandwidth ≈ (Bits per Track / Rotation Time) × Efficiency Factor
</code></pre>



<p class="wp-block-paragraph">A modern 7.2K RPM enterprise HDD typically sustains 150–270 MB/s sequential, but drops to just a few MB/s under fully random small-block workloads because seek time dominates.</p>



<h3 class="wp-block-heading">SATA SSD Bandwidth</h3>



<p class="wp-block-paragraph">SATA III caps out at 6 Gb/s, which after 8b/10b encoding overhead yields a practical maximum around 550–600 MB/s. This ceiling exists regardless of how fast the underlying NAND flash actually is — the interface itself is the bottleneck.</p>



<h3 class="wp-block-heading">SAS SSD Bandwidth</h3>



<p class="wp-block-paragraph">SAS (Serial Attached SCSI) at 12 Gb/s per lane offers roughly 1,200 MB/s of usable bandwidth, and dual-port SAS drives can aggregate paths for redundancy and higher effective throughput in multipathed configurations.</p>



<h3 class="wp-block-heading">NVMe SSD Bandwidth</h3>



<p class="wp-block-paragraph">NVMe drives connect via PCIe lanes, and bandwidth scales directly with PCIe generation and lane count:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>PCIe Generation</th><th>Per-Lane Bandwidth</th><th>x4 Lane Bandwidth (typical NVMe)</th></tr></thead><tbody><tr><td>PCIe 3.0</td><td>~985 MB/s</td><td>~3.9 GB/s</td></tr><tr><td>PCIe 4.0</td><td>~1,969 MB/s</td><td>~7.8 GB/s</td></tr><tr><td>PCIe 5.0</td><td>~3,938 MB/s</td><td>~15.7 GB/s</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">This is why a single modern NVMe drive can outrun an entire shelf of SATA SSDs in raw bandwidth terms.</p>



<h2 class="wp-block-heading">Bandwidth at the Fabric and Network Level</h2>



<h3 class="wp-block-heading">Fibre Channel</h3>



<p class="wp-block-paragraph">Fibre Channel bandwidth has scaled generationally: 8Gb, 16Gb, 32Gb, and now 64Gb FC, each roughly doubling the previous generation while maintaining backward compatibility. In an FC SAN, I always check both the HBA speed and the switch port speed — the lower of the two dictates the actual link rate.</p>



<h3 class="wp-block-heading">iSCSI / Ethernet-based Storage</h3>



<p class="wp-block-paragraph">iSCSI rides on standard Ethernet, so bandwidth is tied to the NIC and switch capability: 1GbE, 10GbE, 25GbE, 40GbE, 100GbE, and now 400GbE in hyperscale data centers. TCP/IP overhead, however, means practical throughput on iSCSI is typically 85–95% of line rate under good conditions, and much lower if jumbo frames aren&#8217;t configured correctly.</p>



<h3 class="wp-block-heading">NVMe-oF (NVMe over Fabrics)</h3>



<p class="wp-block-paragraph">NVMe-oF extends the low-latency, high-bandwidth NVMe protocol across a network using RDMA (RoCE, iWARP) or Fibre Channel (FC-NVMe), largely eliminating the SCSI translation overhead that iSCSI and traditional FC carry. This is the direction most enterprise all-flash arrays are moving.</p>



<h2 class="wp-block-heading">Aggregate Bandwidth: RAID and Erasure Coding</h2>



<p class="wp-block-paragraph">Individual drive bandwidth rarely tells the whole story — RAID and erasure coding schemes change the effective bandwidth seen by the host.</p>



<pre class="wp-block-code"><code>Effective Write Bandwidth (RAID 5) ≈ (N - 1) × Single Drive Bandwidth ÷ (Write Penalty)
</code></pre>



<p class="wp-block-paragraph">RAID 5 has a write penalty of 4 (one read of data, one read of parity, one write of data, one write of parity, per small random write), while RAID 10 has a write penalty of only 2. This is why I steer latency-sensitive, write-heavy workloads toward RAID 10 despite its lower usable capacity.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>RAID Level</th><th>Write Penalty</th><th>Usable Capacity</th><th>Typical Use Case</th></tr></thead><tbody><tr><td>RAID 0</td><td>1</td><td>100%</td><td>Scratch/temp data, no redundancy</td></tr><tr><td>RAID 1</td><td>2</td><td>50%</td><td>Boot volumes, small critical data</td></tr><tr><td>RAID 5</td><td>4</td><td>(N-1)/N</td><td>Read-heavy workloads</td></tr><tr><td>RAID 6</td><td>6</td><td>(N-2)/N</td><td>Large capacity drives, double fault tolerance</td></tr><tr><td>RAID 10</td><td>2</td><td>50%</td><td>Databases, high-write workloads</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Functions Bandwidth Serves in a Storage System</h2>



<ol class="wp-block-list">
<li><strong>Sizing for peak workloads</strong> — I calculate aggregate bandwidth needs by summing peak sequential throughput demands across all workloads sharing a resource, then adding headroom (usually 20–30%) for growth and burst activity.</li>



<li><strong>Determining backup and replication windows</strong> — a 10TB dataset over a 10GbE link (theoretical ~1.25 GB/s, practically closer to 1 GB/s) takes roughly 2.8 hours minimum, before accounting for source/target bottlenecks.</li>



<li><strong>Supporting multipathing and load balancing</strong> — bandwidth from multiple paths (via MPIO) can be aggregated for higher effective throughput and failover protection.</li>



<li><strong>Enabling tiering decisions</strong> — high-bandwidth flash tiers handle hot data while high-capacity, lower-bandwidth HDD tiers handle cold data economically.</li>
</ol>



<h2 class="wp-block-heading">Calculating Bandwidth Requirements — A Worked Example</h2>



<p class="wp-block-paragraph">Let&#8217;s say I&#8217;m sizing storage for a video surveillance system with 50 cameras, each streaming at 8 Mbps continuously.</p>



<pre class="wp-block-code"><code>Total ingest bandwidth = 50 × 8 Mbps = 400 Mbps ≈ 50 MB/s
</code></pre>



<p class="wp-block-paragraph">A single 7.2K RPM HDD sustaining 150 MB/s sequential write could technically handle this, but I would never design it that way — I&#8217;d add RAID overhead, retention/replay read load, and redundancy, easily justifying a small all-flash or hybrid array with a 1GbE or 10GbE network back-end.</p>



<h2 class="wp-block-heading">Monitoring Bandwidth in Practice</h2>



<pre class="wp-block-code"><code># Linux: check real-time network throughput per interface
sar -n DEV 1 10

# Linux: check disk throughput
iostat -xm 2 5

# Check Fibre Channel port throughput (Cisco MDS)
show interface fc1/1 counters

# Check NVMe drive bandwidth utilization
nvme smart-log /dev/nvme0
</code></pre>



<h2 class="wp-block-heading">Real-World Enterprise Context</h2>



<p class="wp-block-paragraph">In SAN environments, I have seen 16Gb FC fabrics get &#8220;bandwidth-starved&#8221; purely because of poor zoning practices funneling too many hosts through too few ISLs (inter-switch links). In NAS environments, I&#8217;ve seen 10GbE links saturated by backup jobs during business hours because QoS wasn&#8217;t configured to throttle non-critical traffic. In virtualized environments, vSAN or Storage vMotion traffic sharing the same physical NICs as production traffic is a classic cause of unexplained bandwidth contention — the fix is almost always dedicated VMkernel ports or VLANs with proper traffic shaping.</p>



<p class="wp-block-paragraph">Cloud storage adds another dimension: AWS EBS volumes, Azure Managed Disks, and Google Persistent Disks all have provisioned bandwidth limits tied to the volume type and size, separate from IOPS limits — a detail that catches a lot of people off guard when they assume &#8220;more IOPS&#8221; automatically means &#8220;more throughput.&#8221;</p>



<h2 class="wp-block-heading">Scalability: How Bandwidth Needs Grow With the Environment</h2>



<p class="wp-block-paragraph">Bandwidth planning isn&#8217;t a one-time calculation — it has to account for growth. When I size a new SAN or NAS deployment, I don&#8217;t just size for today&#8217;s peak; I model for at least 18–24 months of expected growth, because re-cabling a fabric or upgrading switch line cards later is far more disruptive than provisioning slightly ahead of need. A few scaling patterns I watch for:</p>



<ul class="wp-block-list">
<li><strong>Host count growth</strong>: each additional host added to a shared fabric or network reduces the effective bandwidth available per host unless the fabric itself is upgraded in parallel.</li>



<li><strong>VM density growth</strong>: as virtualization hosts get denser (more VMs per physical server), aggregate bandwidth demand per physical NIC/HBA increases even though the underlying hardware hasn&#8217;t changed.</li>



<li><strong>Data growth driving backup windows</strong>: backup bandwidth requirements grow roughly in proportion to dataset size, which is why many organizations move from traditional full backups to incremental-forever or snapshot-based replication strategies specifically to keep bandwidth requirements manageable.</li>
</ul>



<h2 class="wp-block-heading">Troubleshooting Bandwidth Bottlenecks</h2>



<p class="wp-block-paragraph">When someone reports &#8220;storage is slow&#8221; and my metrics show latency is fine but throughput is capped, I work through this checklist:</p>



<ol class="wp-block-list">
<li>Confirm the physical link speed matches expectations (<code>ethtool eth0</code> on Linux, or checking negotiated FC port speed on the switch).</li>



<li>Check for duplex mismatches or auto-negotiation failures, which silently cap Ethernet links far below their rated speed.</li>



<li>Check for oversubscription — too many hosts sharing too few uplinks or ISLs.</li>



<li>Check jumbo frame configuration consistency end-to-end for iSCSI/NFS; a single hop without jumbo frames enabled forces fragmentation and kills throughput.</li>



<li>Check for a RAID rebuild or scrub running in the background, which consumes a meaningful share of available drive and controller bandwidth.</li>
</ol>



<pre class="wp-block-code"><code># Check negotiated Ethernet link speed and duplex
ethtool eth0

# Check for interface errors that silently cap throughput
ip -s link show eth0
</code></pre>



<h2 class="wp-block-heading">Maintenance Practices That Protect Bandwidth Over Time</h2>



<ul class="wp-block-list">
<li>Periodically re-validate multipathing configuration after firmware upgrades, since I&#8217;ve seen upgrades silently reset path policies back to a single-active-path default, halving effective bandwidth.</li>



<li>Monitor drive-level bandwidth degradation as SSDs age — write amplification and garbage collection overhead can reduce sustained bandwidth on heavily used flash over time.</li>



<li>Keep switch firmware and HBA drivers current, since interoperability bugs between mismatched firmware versions are a common, under-diagnosed cause of throughput ceilings well below rated link speed.</li>
</ul>



<h2 class="wp-block-heading">Common Mistakes</h2>



<ul class="wp-block-list">
<li>Assuming interface bandwidth (e.g., 10GbE) equals achievable throughput without accounting for protocol overhead.</li>



<li>Ignoring RAID write penalty when calculating effective bandwidth for write-heavy workloads.</li>



<li>Not separating bandwidth requirements for backup/replication traffic from production traffic.</li>



<li>Overlooking that cloud block storage often has separate, sometimes lower, bandwidth caps compared to on-prem equivalents.</li>
</ul>



<h2 class="wp-block-heading">FAQs</h2>



<p class="wp-block-paragraph"><strong>Q: Is higher bandwidth always better?</strong> Not necessarily — if your workload is dominated by small random I/O, latency and IOPS matter more than raw bandwidth. Bandwidth mostly benefits sequential, large-block workloads like backups, video, and analytics.</p>



<p class="wp-block-paragraph"><strong>Q: How is bandwidth different from IOPS?</strong> Bandwidth measures data volume per second; IOPS measures the number of operations per second. They are related through block size but optimize for different workload types.</p>



<p class="wp-block-paragraph"><strong>Q: Does RAID reduce bandwidth?</strong> Read bandwidth generally scales up with more drives in RAID 0/5/6/10. Write bandwidth is reduced by the write penalty inherent to parity-based RAID levels.</p>



<p class="wp-block-paragraph"><strong>Q: How do I know if I&#8217;m bandwidth-constrained versus latency-constrained?</strong> I look at utilization first: if a link or device is running near its rated maximum throughput while latency is only mildly elevated, that&#8217;s a bandwidth ceiling. If throughput is well below the rated maximum but latency is high, the bottleneck is elsewhere — usually controller CPU, cache misses, or fabric congestion rather than raw bandwidth capacity.</p>



<p class="wp-block-paragraph"><strong>Q: Does link aggregation (LACP) double my bandwidth?</strong> Not automatically. LACP aggregates capacity across links, but traffic distribution depends on the hashing algorithm used (source/destination IP, MAC, or port). A single high-throughput flow between two endpoints may still be pinned to one physical link unless the hash and traffic pattern spread it across multiple links.</p>



<h2 class="wp-block-heading">A Final Thought on Bandwidth Planning</h2>



<p class="wp-block-paragraph">Whenever I&#8217;m asked to justify a bandwidth upgrade, I try to translate the raw numbers into business terms: not &#8220;we need a faster switch&#8221; but &#8220;our backup window is currently 9 hours and shrinking it to 4 hours requires doubling our effective throughput.&#8221; Framing bandwidth decisions around business outcomes — recovery time objectives, batch job completion windows, user-perceived responsiveness — makes the investment case far clearer than quoting Gb/s figures on their own, and it&#8217;s a habit I&#8217;d recommend to anyone managing storage budgets.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Bandwidth is the raw capacity of a storage path, but its real-world impact depends heavily on protocol overhead, RAID/erasure coding penalties, and network conditions. Understanding bandwidth at every layer — drive, bus, fabric, and network — lets me size systems correctly and diagnose bottlenecks quickly instead of blaming &#8220;slow storage&#8221; without evidence.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>SNIA — Storage Performance and Benchmarking resources: https://www.snia.org</li>



<li>Dell EMC — PowerStore and PowerMax Architecture Guides: https://www.dell.com/support</li>



<li>NetApp — ONTAP Performance and Bandwidth Documentation: https://docs.netapp.com</li>



<li>HPE — Storage Networking Best Practices: https://support.hpe.com</li>



<li>Cisco — MDS 9000 and Nexus Configuration Guides: https://www.cisco.com/c/en/us/support</li>



<li>VMware — vSAN Network Design Guide: https://docs.vmware.com</li>
</ul>
<p>The post <a href="https://awjunaid.com/storage/storage-device-bandwidth-properties-and-functions/">Storage Device Bandwidth: Properties, Functions, and Why It Shapes Every Storage Decision I Make</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/storage/storage-device-bandwidth-properties-and-functions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2729</post-id>	</item>
		<item>
		<title>Tuning and Workload Balance Concepts: How I Keep Storage Systems Running Smoothly Under Real Load</title>
		<link>https://awjunaid.com/storage/tuning-and-workload-balance-concepts/</link>
					<comments>https://awjunaid.com/storage/tuning-and-workload-balance-concepts/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Wed, 12 Jul 2023 02:39:44 +0000</pubDate>
				<category><![CDATA[Storage]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[storage devices]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=2726</guid>

					<description><![CDATA[<p>Every storage system I have ever worked with starts fast on day one and slowly develops performance quirks&#8230;</p>
<p>The post <a href="https://awjunaid.com/storage/tuning-and-workload-balance-concepts/">Tuning and Workload Balance Concepts: How I Keep Storage Systems Running Smoothly Under Real Load</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Every storage system I have ever worked with starts fast on day one and slowly develops performance quirks as workloads grow, change shape, and start competing for the same resources. Tuning and workload balancing are how I keep that drift under control. This article covers what I actually do — the concepts, the tools, and the trade-offs — to keep storage performance predictable as environments scale.</p>



<h2 class="wp-block-heading">What Tuning Really Means</h2>



<p class="wp-block-paragraph">Tuning is the process of adjusting configuration parameters — at the host, network, and storage layers — so that the system matches the actual characteristics of the workload running on it, rather than relying on generic defaults. Default settings are built for the average case; production workloads are rarely average.</p>



<h2 class="wp-block-heading">Understanding Workload Characteristics Before Tuning Anything</h2>



<p class="wp-block-paragraph">Before I touch a single setting, I profile the workload along these dimensions:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Dimension</th><th>Question I Ask</th></tr></thead><tbody><tr><td>I/O size</td><td>Are requests small (4K–8K, typical of databases) or large (256K+, typical of backups/media)?</td></tr><tr><td>Read/write ratio</td><td>Is it read-heavy (e.g., 80/20 for OLTP reads) or write-heavy (e.g., logging, journaling)?</td></tr><tr><td>Access pattern</td><td>Sequential (video, backup) or random (databases, VDI)?</td></tr><tr><td>Concurrency</td><td>How many simultaneous threads/queues generate I/O?</td></tr><tr><td>Burstiness</td><td>Is load steady, or does it spike at specific times (month-end batch jobs, backup windows)?</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Tools I use to gather this profile:</p>



<pre class="wp-block-code"><code># Linux block-level trace and histogram of I/O sizes
blktrace -d /dev/sdb -o - | blkparse -i -

# fio - synthetic but highly configurable workload generator
fio --name=randread --ioengine=libaio --rw=randread --bs=4k \
    --numjobs=4 --iodepth=32 --size=1G --runtime=60 --time_based
</code></pre>



<p class="wp-block-paragraph"><code>fio</code> is, in my experience, the single most valuable tool for both benchmarking and validating tuning changes because I can simulate the exact I/O pattern of a production workload before making changes to the real thing.</p>



<h2 class="wp-block-heading">Core Tuning Levers</h2>



<h3 class="wp-block-heading">1. I/O Scheduler (Linux)</h3>



<p class="wp-block-paragraph">Linux offers multiple I/O schedulers, and picking the right one matters more than people expect:</p>



<ul class="wp-block-list">
<li><strong>noop / none</strong> — best for NVMe/SSD where the device itself handles queuing efficiently; avoids unnecessary CPU overhead from re-ordering.</li>



<li><strong>deadline / mq-deadline</strong> — good general-purpose choice, prioritizes read latency.</li>



<li><strong>cfq / bfq</strong> — fair-share scheduling, useful for multi-tenant hosts with mixed workloads but adds overhead on fast flash devices.</li>
</ul>



<pre class="wp-block-code"><code># Check current scheduler
cat /sys/block/sdb/queue/scheduler

# Set scheduler to none for an NVMe-backed device
echo none &gt; /sys/block/nvme0n1/queue/scheduler
</code></pre>



<h3 class="wp-block-heading">2. Queue Depth and Multipathing</h3>



<p class="wp-block-paragraph">Queue depth tuning balances throughput against latency. Too shallow a queue underutilizes fast storage; too deep a queue causes latency spikes as requests pile up.</p>



<pre class="wp-block-code"><code># Check queue depth for a LUN
cat /sys/block/sdb/device/queue_depth

# multipath.conf snippet for round-robin path balancing
device {
    vendor "NETAPP"
    product "LUN"
    path_grouping_policy multibus
    path_selector "round-robin 0"
    rr_min_io 100
}
</code></pre>



<h3 class="wp-block-heading">3. Block Size Alignment</h3>



<p class="wp-block-paragraph">Misaligned I/O (where the application&#8217;s block size doesn&#8217;t align with the underlying storage&#8217;s stripe size or physical sector boundaries) causes read-modify-write penalties. I always verify alignment when provisioning new LUNs, especially in virtualized environments where multiple layers of abstraction (guest filesystem, VMDK, datastore, array LUN) each have their own block boundaries.</p>



<pre class="wp-block-code"><code># Check partition alignment on Linux
parted /dev/sdb align-check optimal 1
</code></pre>



<h3 class="wp-block-heading">4. Cache Tuning</h3>



<p class="wp-block-paragraph">Read-ahead and write-back cache settings dramatically affect perceived performance:</p>



<pre class="wp-block-code"><code># Set read-ahead size (in 512-byte sectors) - 8192 = 4MB
blockdev --setra 8192 /dev/sdb
</code></pre>



<p class="wp-block-paragraph">Write-back caching improves write latency but introduces data-loss risk on power failure unless backed by battery/flash-backed cache (common in RAID controllers) — I never enable write-back without confirming the cache is protected.</p>



<h3 class="wp-block-heading">5. Filesystem and Database-Level Tuning</h3>



<ul class="wp-block-list">
<li><strong>XFS/ext4 mount options</strong>: <code>noatime</code>, appropriate <code>stripe_width</code>/<code>stripe_unit</code> matching underlying RAID geometry.</li>



<li><strong>Database tuning</strong>: separating redo/transaction logs (sequential, latency-sensitive) from data files (random, throughput-oriented) onto different storage tiers or LUNs — a classic and still very effective practice.</li>
</ul>



<h2 class="wp-block-heading">Workload Balance Concepts</h2>



<h3 class="wp-block-heading">Load Balancing Across Controllers and Paths</h3>



<p class="wp-block-paragraph">Storage arrays typically have dual (or more) controllers/nodes. I balance LUNs/volumes so that no single controller becomes a hotspot while others sit idle. Active-active arrays (most modern NVMe-based platforms) make this easier than legacy active-passive designs.</p>



<h3 class="wp-block-heading">QoS (Quality of Service) Policies</h3>



<p class="wp-block-paragraph">Most enterprise arrays let me set IOPS/throughput ceilings or floors per volume:</p>



<pre class="wp-block-code"><code>NetApp ONTAP example:
qos policy-group create -policy-group vm-critical -vserver svm1 -max-throughput 5000IOPS
qos policy-group create -policy-group vm-background -vserver svm1 -max-throughput 500IOPS
</code></pre>



<p class="wp-block-paragraph">This prevents a single noisy workload (e.g., a runaway batch job or a misbehaving VM) from starving latency-sensitive workloads sharing the same pool — a pattern known as the &#8220;noisy neighbor&#8221; problem.</p>



<h3 class="wp-block-heading">Storage Tiering</h3>



<p class="wp-block-paragraph">Automated tiering (e.g., NetApp FabricPool, Dell EMC FAST, HPE Adaptive Optimization) moves hot data to flash and cold data to cheaper capacity tiers based on access frequency, balancing cost against performance without manual intervention.</p>



<h3 class="wp-block-heading">Distributed/Scale-Out Balance</h3>



<p class="wp-block-paragraph">In scale-out systems (Ceph, VMware vSAN, NetApp SolidFire/Element, Dell PowerScale), workload balance also means ensuring data and metadata are evenly distributed across nodes so no single node becomes a bottleneck. Rebalancing operations themselves consume bandwidth and IOPS, so I schedule them carefully around business-critical windows.</p>



<pre class="wp-block-code"><code># Ceph - check placement group balance across OSDs
ceph osd df tree
</code></pre>



<h2 class="wp-block-heading">A Tuning Workflow I Follow</h2>



<ol class="wp-block-list">
<li>Baseline the current performance with real or synthetic (fio) workloads.</li>



<li>Identify the bottleneck layer (host queue, HBA, fabric, controller CPU, cache, media).</li>



<li>Change one variable at a time (scheduler, queue depth, alignment, QoS).</li>



<li>Re-run the same benchmark and compare against baseline.</li>



<li>Document the change and roll out gradually, monitoring for regressions.</li>
</ol>



<h2 class="wp-block-heading">Real-World Enterprise Example</h2>



<p class="wp-block-paragraph">I once worked on a VMware environment where VDI boot storms (hundreds of desktops booting simultaneously) were overwhelming a hybrid array&#8217;s spinning-disk tier. The fix combined several tuning and balancing concepts at once: enabling read cache pre-warming, setting a QoS floor for VDI datastores so boot storms couldn&#8217;t be starved by backup jobs, and migrating the VDI golden image and linked clones to an all-flash tier while leaving file shares on the capacity tier. Boot storm completion time dropped from 45 minutes to under 8 minutes.</p>



<h2 class="wp-block-heading">Monitoring Tuning Effectiveness Over Time</h2>



<p class="wp-block-paragraph">Tuning a system once and walking away rarely holds up over the long run, because workloads drift. I set up ongoing monitoring specifically to catch tuning drift:</p>



<ul class="wp-block-list">
<li><strong>Latency percentile tracking (p50/p95/p99)</strong> trended over weeks, so I can catch a slow creep before it becomes a user-visible complaint.</li>



<li><strong>Queue depth trending</strong> per LUN/volume to catch workloads that have organically outgrown their original sizing.</li>



<li><strong>QoS policy hit rate</strong> — how often a workload is actually being throttled by its assigned ceiling, which tells me whether the policy needs adjusting.</li>
</ul>



<pre class="wp-block-code"><code># Ceph - monitor OSD latency distribution
ceph osd perf

# NetApp - check QoS policy statistics
qos statistics workload show
</code></pre>



<h2 class="wp-block-heading">Scalability of Tuning Practices in Larger Environments</h2>



<p class="wp-block-paragraph">Tuning a single host is straightforward; tuning a cluster of 50 ESXi hosts sharing a handful of storage pools is a different problem entirely, because a change that helps one workload can hurt another sharing the same physical resources. In large environments, I lean heavily on:</p>



<ul class="wp-block-list">
<li><strong>Storage policies in VMware (SPBM)</strong> to apply consistent QoS and placement rules across large numbers of VMs without manual per-VM tuning.</li>



<li><strong>Automated tiering</strong> so that hot/cold data placement adjusts itself as workload patterns shift across hundreds or thousands of volumes.</li>



<li><strong>Cluster-wide rebalance scheduling</strong> in scale-out systems, ensuring rebalancing operations (which themselves consume I/O bandwidth) run during low-activity windows rather than competing with production traffic.</li>
</ul>



<h2 class="wp-block-heading">Comparing Manual Tuning vs. AI-Driven Automated Tuning</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Approach</th><th>Strengths</th><th>Limitations</th></tr></thead><tbody><tr><td>Manual tuning</td><td>Precise, workload-specific, fully explainable</td><td>Time-consuming, requires deep expertise, doesn&#8217;t scale to hundreds of systems</td></tr><tr><td>AI-driven (HPE InfoSight, NetApp Active IQ)</td><td>Continuously learns from telemetry across thousands of systems, catches subtle patterns</td><td>Recommendations still need human validation; less effective for highly unusual or brand-new workload types</td></tr><tr><td>Hybrid</td><td>Combines automated baseline tuning with human oversight for exceptions</td><td>Requires process discipline to avoid conflicting manual overrides</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">In practice, I use AI-driven platforms as a first-pass filter that surfaces candidates for tuning, then apply manual judgment before making production changes — the automation speeds up discovery, but I still own the decision.</p>



<h2 class="wp-block-heading">Common Mistakes</h2>



<ul class="wp-block-list">
<li>Changing multiple tuning parameters simultaneously, making it impossible to know which change helped or hurt.</li>



<li>Applying &#8220;generic best practice&#8221; settings without profiling the actual workload first.</li>



<li>Ignoring controller CPU and cache as tuning targets and only focusing on the disks themselves.</li>



<li>Setting QoS limits too aggressively, unintentionally throttling legitimate business workloads.</li>



<li>Forgetting to re-baseline after tuning changes to confirm the expected improvement actually happened.</li>
</ul>



<h2 class="wp-block-heading">FAQs</h2>



<p class="wp-block-paragraph"><strong>Q: How often should I re-tune a storage system?</strong> I revisit tuning whenever workload characteristics change significantly — new applications onboarded, major version upgrades, or noticeable performance complaints — rather than on a fixed schedule.</p>



<p class="wp-block-paragraph"><strong>Q: Is manual tuning still necessary with AI-driven platforms like HPE InfoSight or NetApp Active IQ?</strong> These platforms handle a lot of the heavy lifting through recommendations and predictive analytics, but I still validate and apply changes manually, especially for workload-specific QoS and application-level settings that the platform can&#8217;t fully see.</p>



<p class="wp-block-paragraph"><strong>Q: What&#8217;s the single highest-impact tuning change for databases?</strong> In my experience, separating log/journal I/O from data I/O onto different performance tiers consistently delivers the biggest and most reliable improvement.</p>



<p class="wp-block-paragraph"><strong>Q: Should I tune at the host level or the array level first?</strong> I generally start at the host level, since misconfigured schedulers, misaligned partitions, or shallow queue depths are cheap to fix and often explain a large share of the problem before I even need to touch array-side settings.</p>



<p class="wp-block-paragraph"><strong>Q: How do I balance competing workloads that all claim to be &#8220;critical&#8221;?</strong> This is more of a governance problem than a technical one. I push for a documented workload prioritization policy signed off by application owners, so that QoS floors and ceilings reflect actual business priority rather than whoever complains loudest gets more resources.</p>



<h2 class="wp-block-heading">Workload Balance in Multi-Tenant Environments</h2>



<p class="wp-block-paragraph">Multi-tenant storage — whether it&#8217;s a service provider platform or simply a shared internal array serving multiple business units — adds an extra layer of complexity to workload balancing. I rely on per-tenant QoS limits, strict LUN/volume isolation, and chargeback/showback reporting so that tenants can see their own consumption trends and plan capacity requests accordingly, rather than everyone assuming the shared pool has infinite headroom.</p>



<h2 class="wp-block-heading">Documenting Tuning Decisions</h2>



<p class="wp-block-paragraph">I keep a simple running log for every tuning change I make: date, system affected, parameter changed, old value, new value, reason, and measured before/after result. This might sound like overhead, but it has saved me countless hours during later troubleshooting sessions when a &#8220;mystery&#8221; performance shift turned out to be a tuning change made months earlier that nobody remembered. It also makes onboarding new team members far easier, since they can see the reasoning behind current settings instead of inheriting a black box of unexplained configuration.</p>



<h2 class="wp-block-heading">Final Thoughts on Building a Tuning Culture</h2>



<p class="wp-block-paragraph">The best storage teams I&#8217;ve worked with treat tuning as a habit rather than a project — small, incremental, well-documented adjustments made continuously as workloads evolve, rather than a big disruptive overhaul once a year. Building that habit means investing in good baseline data, keeping a change log of every tuning adjustment (so regressions can be traced back to a specific change), and being willing to revert a change quickly if it doesn&#8217;t deliver the expected improvement. That discipline, more than any single scheduler setting or QoS policy, is what keeps a storage environment performing well as it grows.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Tuning and workload balancing are ongoing disciplines, not one-time projects. By profiling workloads accurately, adjusting the right levers — schedulers, queue depth, alignment, caching, QoS, and tiering — and validating each change methodically, I keep storage systems performing consistently even as demands on them evolve.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>SNIA — Storage Performance Benchmarking Best Practices: https://www.snia.org</li>



<li>NetApp — ONTAP QoS and Performance Management Guide: https://docs.netapp.com</li>



<li>Dell EMC — PowerMax and PowerStore Performance Best Practices: https://www.dell.com/support</li>



<li>VMware — vSAN Performance and Troubleshooting Guide: https://docs.vmware.com</li>



<li>Red Hat — Linux Performance Tuning Guide: https://access.redhat.com/documentation</li>



<li>Ceph Documentation — Placement Groups and Balancing: https://docs.ceph.com</li>
</ul>
<p>The post <a href="https://awjunaid.com/storage/tuning-and-workload-balance-concepts/">Tuning and Workload Balance Concepts: How I Keep Storage Systems Running Smoothly Under Real Load</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/storage/tuning-and-workload-balance-concepts/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2726</post-id>	</item>
	</channel>
</rss>
