<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Cryptsetup on inetshell</title><link>https://inet.sh/en/tags/cryptsetup/</link><description>Recent content in Cryptsetup on inetshell</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 25 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/en/tags/cryptsetup/index.xml" rel="self" type="application/rss+xml"/><item><title>LUKS: back up and restore the header, and add, change or remove keys</title><link>https://inet.sh/en/posts/linux/luks-header-backup-keys/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/linux/luks-header-backup-keys/</guid><description>The cryptsetup commands that keep you from losing a LUKS-encrypted disk: luksHeaderBackup and luksHeaderRestore, luksAddKey, luksChangeKey, luksRemoveKey and luksKillSlot, luksDump to see the slots, keyfiles in crypttab. And the warning almost nobody reads: a header backup brings back the passphrases you already removed.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Header backup (the volume does not need to be open)</span>
</span></span><span class="line"><span class="cl">cryptsetup luksHeaderBackup /dev/sdb --header-backup-file /root/sdb-luks-header.img
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Slots in use</span>
</span></span><span class="line"><span class="cl">cryptsetup luksDump /dev/sdb
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Keys</span>
</span></span><span class="line"><span class="cl">cryptsetup luksAddKey /dev/sdb                      <span class="c1"># another passphrase (asks for an existing one)</span>
</span></span><span class="line"><span class="cl">cryptsetup luksAddKey /dev/sdb /root/keyfile.bin    <span class="c1"># a keyfile in a new slot</span>
</span></span><span class="line"><span class="cl">cryptsetup luksChangeKey /dev/sdb                   <span class="c1"># swap one passphrase for another, same slot</span>
</span></span><span class="line"><span class="cl">cryptsetup luksRemoveKey /dev/sdb                   <span class="c1"># remove the passphrase you type</span>
</span></span><span class="line"><span class="cl">cryptsetup luksKillSlot /dev/sdb <span class="m">2</span>                  <span class="c1"># remove slot 2 without knowing its passphrase (asks for another)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Restore the header</span>
</span></span><span class="line"><span class="cl">cryptsetup luksHeaderRestore /dev/sdb --header-backup-file /root/sdb-luks-header.img
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>After any key change, back up the header again and destroy the previous backup.</strong> Restoring an old backup reactivates every passphrase it held at the time, including the ones you removed.</p>
<h2 id="why-the-header-is-everything">Why the header is everything</h2>
<p>LUKS does not encrypt your data with your passphrase: it encrypts it with a random <strong>master key</strong>, and that master key sits encrypted inside the header, one copy per slot, each protected by a passphrase or keyfile. The header takes the first <strong>16 MiB</strong> of the device on LUKS2 (2 MiB on LUKS1).</p>
<p>If those megabytes get damaged (a wrong <code>dd</code>, a <code>mkfs</code> on the raw disk, dead sectors right there), the master key is gone and the data becomes unrecoverable noise, even if you know the passphrase. A header backup, stored somewhere else, is the only insurance. The file is the size of the header and <strong>contains no data</strong>, only the encrypted master key.</p>
<h2 id="backing-up-and-restoring">Backing up and restoring</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">cryptsetup luksHeaderBackup /dev/sdb --header-backup-file /root/sdb-luks-header.img
</span></span><span class="line"><span class="cl">cryptsetup luksDump /root/sdb-luks-header.img         <span class="c1"># the backup can be inspected like a device</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Keep it off the machine, encrypted (a <code>gpg -c</code> is enough), with a name that says which disk it belongs to. Restoring:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">cryptsetup luksHeaderRestore /dev/sdb --header-backup-file /root/sdb-luks-header.img
</span></span></code></pre></td></tr></table>
</div>
</div><p>It only repairs the header. If the accident went past the first 16 MiB, whatever was there stays lost.</p>
<h2 id="slots-and-keys">Slots and keys</h2>
<p>LUKS2 has 32 slots (0–31); LUKS1, 8. All of them unlock the same master key, so it does not matter which one you come in through:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">cryptsetup luksDump /dev/sdb <span class="p">|</span> sed -n <span class="s1">&#39;/^Keyslots:/,/^Tokens:/p&#39;</span>
</span></span><span class="line"><span class="cl">cryptsetup open --test-passphrase -v /dev/sdb         <span class="c1"># &#34;Key slot 0 unlocked&#34;: which slot your passphrase uses</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Keyfile to open without typing (typical for a data disk that comes up with the system):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">dd <span class="k">if</span><span class="o">=</span>/dev/urandom <span class="nv">bs</span><span class="o">=</span><span class="m">32</span> <span class="nv">count</span><span class="o">=</span><span class="m">1</span> <span class="nv">of</span><span class="o">=</span>/root/keyfile.bin
</span></span><span class="line"><span class="cl">chmod <span class="m">0400</span> /root/keyfile.bin
</span></span><span class="line"><span class="cl">cryptsetup luksAddKey /dev/sdb /root/keyfile.bin
</span></span></code></pre></td></tr></table>
</div>
</div><p>And in <code>/etc/crypttab</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">data  UUID=&lt;luks-uuid&gt;  /root/keyfile.bin  luks
</span></span></code></pre></td></tr></table>
</div>
</div><p>Test without rebooting: <code>systemctl daemon-reload &amp;&amp; systemctl start systemd-cryptsetup@data.service</code>. A keyfile under <code>/root</code> only makes sense if <code>/</code> is encrypted too or the disk belongs to a machine you trust physically.</p>
<p>Removing keys:</p>
<ul>
<li><code>luksRemoveKey</code> asks for the passphrase you want gone.</li>
<li><code>luksKillSlot &lt;n&gt;</code> removes a specific slot and asks for <strong>another</strong> valid passphrase; useful when nobody remembers the slot&rsquo;s own.</li>
<li><code>luksChangeKey</code> swaps one passphrase for another in the same slot.</li>
</ul>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>The header backup keeps the old keys.</strong> You removed a former colleague&rsquo;s passphrase and the earlier backup is still on a USB stick: that stick opens the disk. Re-back up after every change and destroy the previous ones (<code>shred -u</code>).</li>
<li><strong><code>luksErase</code> is not secure erasure if a header backup exists.</strong> It destroys every slot on the disk, but a <code>luksHeaderRestore</code> brings them back. For a final wipe, destroy the backups too.</li>
<li><strong>Do not kill the last slot.</strong> <code>cryptsetup</code> warns the device will become unusable; if you accept, that is it.</li>
<li><strong>A backup on the same disk is not a backup.</strong> Nor on the same server if losing the server is what you fear.</li>
<li><strong>Detached header</strong> (<code>--header /path/header.img</code> when formatting and opening) moves the header off the disk entirely; then the &ldquo;backup&rdquo; is the header itself and losing it equals losing the data.</li>
<li><strong>LUKS1 vs LUKS2</strong>: the commands are the same; <code>cryptsetup convert --type luks2</code> migrates a LUKS1 (with a backup first, of course).</li>
</ul>
<p>Reference: <code>man 8 cryptsetup</code>, sections <em>luksHeaderBackup</em>, <em>luksHeaderRestore</em>, and <em>luksKillSlot</em>.</p>
]]></content:encoded></item></channel></rss>