<?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>Self-Hosted on inetshell</title><link>https://inet.sh/en/tags/self-hosted/</link><description>Recent content in Self-Hosted 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/self-hosted/index.xml" rel="self" type="application/rss+xml"/><item><title>Seafile: reclaim disk space with seaf-gc (the garbage collector)</title><link>https://inet.sh/en/posts/seafile/reclaim-disk-space-seaf-gc/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/seafile/reclaim-disk-space-seaf-gc/</guid><description>You deleted libraries and files in Seafile and the disk stays the same: blocks are only freed by seaf-gc. How to run it on the official Docker image (/scripts/gc.sh), on a binary install or on Kubernetes (seafile.sh stop, seaf-gc.sh, seafile.sh start), which options it has (--dry-run, -r, --rm-fs, -t), and why the admin&amp;#39;s library trash must be emptied first.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>Official Docker image (Community Edition):</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">docker <span class="nb">exec</span> seafile /scripts/gc.sh        <span class="c1"># stops Seafile, runs the GC, starts it again</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Binary install, or a container with the manual sequence:</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><span class="lnt">4
</span><span class="lnt">5
</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="nb">cd</span> /opt/seafile/seafile-server-latest
</span></span><span class="line"><span class="cl">./seafile.sh stop
</span></span><span class="line"><span class="cl">./seaf-gc.sh --dry-run        <span class="c1"># how many blocks would go, deleting nothing</span>
</span></span><span class="line"><span class="cl">./seaf-gc.sh                  <span class="c1"># delete</span>
</span></span><span class="line"><span class="cl">./seafile.sh start
</span></span></code></pre></td></tr></table>
</div>
</div><p>On Kubernetes, the same inside the pod: <code>kubectl -n seafile exec -it deploy/seafile -- bash</code> and the sequence above (or <code>/scripts/gc.sh</code> if it is the official image).</p>
<p>Before anything else: <strong>System Admin → Libraries → Trash → clean</strong>. A library sitting in the trash keeps all of its blocks and the GC will not touch it.</p>
<h2 id="why-the-disk-does-not-shrink-by-itself">Why the disk does not shrink by itself</h2>
<p>Seafile stores files chunked into content-addressed <strong>blocks</strong> under <code>seafile-data/storage/</code> (<code>blocks/</code>, <code>fs/</code>, <code>commits/</code>). Deleting a file or a library only writes a new commit; the blocks stay because the library&rsquo;s history still references them, and because another library or an older version might use them. The only thing that removes them is <code>seaf-gc</code>, which walks the live commits and deletes everything nobody references anymore.</p>
<p>Two things decide what &ldquo;nobody&rdquo; means:</p>
<ul>
<li><strong>The library trash</strong> in the admin panel: a library deleted by a user is not removed, it is moved there. Until you clean it, its blocks count as alive.</li>
<li><strong>Each library&rsquo;s history</strong> (<em>History settings</em>: days to keep). The GC honors that window; with unlimited history, blocks from old versions are never freed.</li>
</ul>
<h2 id="requirements">Requirements</h2>
<ul>
<li><strong>Community Edition: Seafile stopped.</strong> Blocks written while the GC runs could be deleted by mistake. The official image&rsquo;s <code>/scripts/gc.sh</code> stops and starts it for you; by hand, <code>seafile.sh stop</code> before and <code>seafile.sh start</code> after. Pro has online GC.</li>
<li><strong>Maintenance window.</strong> Runtime grows with storage size; on big installs it is hours.</li>
<li><strong>Backup or snapshot</strong> of <code>seafile-data</code> (on ZFS, a <code>zfs snapshot</code> is instant). It is the first time something will actually delete blocks.</li>
</ul>
<h2 id="seaf-gcsh-options">seaf-gc.sh options</h2>
<table>
  <thead>
      <tr>
          <th>Option</th>
          <th>What it does</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>--dry-run</code></td>
          <td>Counts what would be deleted and deletes nothing. Always start here</td>
      </tr>
      <tr>
          <td><code>-r</code></td>
          <td>Only blocks from deleted libraries (the ones already purged from the trash), without checking history. The fastest for &ldquo;I deleted a 500 GB library&rdquo;</td>
      </tr>
      <tr>
          <td><code>--rm-fs</code></td>
          <td>Also deletes orphaned <code>fs</code> objects. Buggy before CE 11.0.7 / Pro 10.0.15; upgrade before using it</td>
      </tr>
      <tr>
          <td><code>-t N</code></td>
          <td>Threads. Only helps with object backends (S3, etc.); with a local filesystem leave it at 1</td>
      </tr>
      <tr>
          <td><code>--id-prefix ab</code></td>
          <td>Only libraries whose ID starts with that prefix (to split a long pass)</td>
      </tr>
      <tr>
          <td><code>&lt;id&gt; [&lt;id&gt;…]</code></td>
          <td>Only those libraries</td>
      </tr>
  </tbody>
</table>
<p>Single-library dry run:</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">./seaf-gc.sh --dry-run 3f5a1c2e-7b9d-4e21-8c44-0a6d9e7f1b23
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="full-procedure">Full procedure</h2>
<ol>
<li>Admin panel → <strong>Libraries → Trash</strong> → clean (or <em>Clean</em> per library). Without this step the GC reports zero blocks and you wonder why.</li>
<li>Review the history of the big libraries (<em>History settings</em>); if they keep everything forever, decide on a number of days.</li>
<li>Snapshot or backup of <code>seafile-data</code>.</li>
<li><code>docker exec seafile /scripts/gc.sh</code>, or the manual sequence with <code>--dry-run</code> first. The output ends with the per-library block summary.</li>
<li>Check: <code>du -sh /opt/seafile-data/seafile/storage/blocks</code> and <code>df -h</code>.</li>
</ol>
<p>To avoid doing it by hand, a weekly overnight cron with the same <code>docker exec</code> is enough on CE.</p>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>&ldquo;GC frees nothing&rdquo;</strong>: trash not emptied, unlimited history, or blocks held by filesystem snapshots (on ZFS, <code>zfs list -t snapshot</code> and its <code>USED</code>).</li>
<li><strong>Never with Seafile up on CE.</strong> If the container runs <code>seafile-server</code> as its main process, <code>seafile.sh stop</code> inside can take the container down; with the official image use <code>/scripts/gc.sh</code>, which accounts for it.</li>
<li><strong><code>--rm-fs</code> on old versions</strong> can delete objects that are in use; only from CE 11.0.7.</li>
<li><strong>Nginx in front</strong> and clients showing <em>Server error</em> when syncing after the GC: it is usually <code>client_max_body_size</code> too low, not the GC; set it to <code>0</code> in Seafile&rsquo;s <code>server</code> block.</li>
<li><strong>Encrypted libraries</strong> are collected the same way; the GC does not need the password.</li>
</ul>
<p>Reference: <a href="https://manual.seafile.com/latest/administration/seafile_gc/">Seafile GC</a> in the admin manual.</p>
]]></content:encoded></item></channel></rss>