<?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>Ceph on inetshell</title><link>https://inet.sh/en/tags/ceph/</link><description>Recent content in Ceph 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/ceph/index.xml" rel="self" type="application/rss+xml"/><item><title>Ceph on Proxmox: clearing the 'daemons have recently crashed' HEALTH_WARN and deleting orphaned VM disks in RBD</title><link>https://inet.sh/en/posts/proxmox/ceph-crash-archive-orphaned-rbd/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/proxmox/ceph-crash-archive-orphaned-rbd/</guid><description>Two routine clean-ups on a Ceph managed by Proxmox VE: archiving crashes you have already reviewed to get back to HEALTH_OK (ceph crash ls-new, info, archive-all) and finding and deleting RBD images that no longer belong to any VM (pvesm free, rbd rm, and the watchers and snapshots that block it).</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></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"># HEALTH_WARN: N daemons have recently crashed</span>
</span></span><span class="line"><span class="cl">ceph crash ls-new
</span></span><span class="line"><span class="cl">ceph crash info &lt;id&gt;          <span class="c1"># which daemon, when, and the backtrace</span>
</span></span><span class="line"><span class="cl">ceph crash archive-all        <span class="c1"># the warning goes away; the crash stays in `ceph crash ls`</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Disks of a VM that no longer exists</span>
</span></span><span class="line"><span class="cl">rbd ls -l cephpool
</span></span><span class="line"><span class="cl">pvesm free cephpool:vm-124-disk-1     <span class="c1"># through the Proxmox storage layer</span>
</span></span><span class="line"><span class="cl">rbd rm cephpool/vm-124-disk-1         <span class="c1"># or straight in Ceph</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="health_warn-daemons-have-recently-crashed">HEALTH_WARN: daemons have recently crashed</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">HEALTH_WARN 1 daemons have recently crashed
</span></span><span class="line"><span class="cl">[WRN] RECENT_CRASH: 1 daemons have recently crashed
</span></span><span class="line"><span class="cl">    osd.5 crashed on host pve-node2 at 2026-09-20T03:14:07.123456Z
</span></span></code></pre></td></tr></table>
</div>
</div><p>It is the <code>RECENT_CRASH</code> check from the manager&rsquo;s <code>crash</code> module: a daemon fell over, left a report, and the warning stays until an administrator <strong>archives</strong> it, or until two weeks pass (<code>mgr/crash/warn_recent_interval</code>). The daemon has almost always come back on its own; the warning does not say it is still down.</p>
<p>Before archiving, look at what it was:</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">ceph crash ls-new
</span></span><span class="line"><span class="cl">ceph crash info 2026-09-20T03:14:07.123456Z_9f1c...
</span></span></code></pre></td></tr></table>
</div>
</div><p>What matters from <code>info</code> is <code>entity_name</code> (which daemon), <code>utc_timestamp</code>, <code>assert_msg</code> or <code>backtrace</code>, and <code>ceph_version</code>. Then:</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">ceph osd stat                          <span class="c1"># are they all still up/in?</span>
</span></span><span class="line"><span class="cl">systemctl status ceph-osd@5            <span class="c1"># on the OSD&#39;s node</span>
</span></span><span class="line"><span class="cl">journalctl -u ceph-osd@5 --since <span class="s1">&#39;-1h&#39;</span>
</span></span><span class="line"><span class="cl">dmesg -T <span class="p">|</span> grep -iE <span class="s1">&#39;sd[a-z]|nvme|i/o error&#39;</span>
</span></span><span class="line"><span class="cl">smartctl -a /dev/sdX                   <span class="c1"># if the crash lines up with disk errors</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>With that settled, archive:</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">ceph crash archive &lt;id&gt;
</span></span><span class="line"><span class="cl">ceph crash archive-all
</span></span><span class="line"><span class="cl">ceph -s                                <span class="c1"># HEALTH_OK if nothing else is going on</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Archiving fixes nothing; it only acknowledges you saw it. If the same OSD shows up in <code>ls-new</code> every few days, it is a disk or a controller, not an annoying notice: take it out of the cluster and replace it.</p>
<p>To clean the history: <code>ceph crash rm &lt;id&gt;</code> or <code>ceph crash prune &lt;days&gt;</code>. The warning can be turned off entirely with <code>ceph config set mgr mgr/crash/warn_recent_interval 0</code>, which is exactly what you do not want in production.</p>
<h2 id="orphaned-vm-disks-in-rbd">Orphaned VM disks in RBD</h2>
<p>They appear when a VM is deleted while the storage is unreachable, a clone or migration fails halfway, someone deletes the <code>.conf</code> by hand, or a restore is left incomplete. They take space and do not show in the GUI because no <code>.conf</code> mentions them.</p>
<h3 id="finding-them">Finding them</h3>
<p>Compare the pool&rsquo;s images with the <code>.conf</code> files of <strong>every</strong> node (<code>/etc/pve/nodes/</code> holds each node&rsquo;s copy):</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="k">for</span> img in <span class="k">$(</span>rbd ls cephpool<span class="k">)</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  grep -rqs <span class="s2">&#34;cephpool:</span><span class="nv">$img</span><span class="s2">&#34;</span> /etc/pve/nodes/*/qemu-server /etc/pve/nodes/*/lxc <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    <span class="o">||</span> <span class="nb">echo</span> <span class="s2">&#34;no owner: </span><span class="nv">$img</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="cl">rbd ls -l cephpool          <span class="c1"># sizes</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>pvesm list cephpool</code> gives the same list with the VMID Proxmox infers from the name; handy to cross-check against <code>qm list</code> and <code>pct list</code> on each node.</p>
<h3 id="if-the-vm-still-exists">If the VM still exists</h3>
<p>Let Proxmox see it again and delete it from there:</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">qm rescan --vmid <span class="m">124</span>        <span class="c1"># shows up as unused0 in the .conf</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Then GUI → Hardware → the <em>Unused</em> disk → <strong>Remove</strong>, which does delete the image, or <code>pvesm free cephpool:vm-124-disk-1</code>. Careful: <code>qm set 124 --delete unused0</code> only drops it from the <code>.conf</code>, it deletes no data.</p>
<h3 id="if-the-vm-no-longer-exists">If the VM no longer exists</h3>
<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">pvesm free cephpool:vm-124-disk-1
</span></span><span class="line"><span class="cl"><span class="c1"># direct Ceph equivalent:</span>
</span></span><span class="line"><span class="cl">rbd rm cephpool/vm-124-disk-1
</span></span></code></pre></td></tr></table>
</div>
</div><p>When <code>rbd rm</code> refuses:</p>
<table>
  <thead>
      <tr>
          <th>Message</th>
          <th>Cause</th>
          <th>Way out</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>image still has watchers</code></td>
          <td>Some process has it open (a VM running on another node, an <code>rbd map</code>)</td>
          <td><code>rbd status cephpool/vm-124-disk-1</code> says who; stop that VM or <code>rbd unmap</code></td>
      </tr>
      <tr>
          <td><code>image has snapshots</code></td>
          <td>Snapshots remain</td>
          <td><code>rbd snap purge cephpool/vm-124-disk-1</code> and retry</td>
      </tr>
      <tr>
          <td><code>cannot remove a protected snapshot</code></td>
          <td>It is a template <code>base-*</code> with clones</td>
          <td><code>rbd children cephpool/base-9000-disk-0@__base__</code>; the clones depend on it, do not delete it</td>
      </tr>
  </tbody>
</table>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>Cross-check against every node</strong>, not the <code>qm list</code> of the node you are on; the disk of a VM living on another node is not an orphan.</li>
<li><strong><code>base-*</code> is not junk</strong>: those are the templates. Delete them only through <code>qm destroy</code> of the template.</li>
<li><strong>Space comes back slowly</strong>: <code>ceph df</code> takes a while to reflect the delete while the OSDs remove objects.</li>
<li><strong>A whole pool you no longer need</strong>: <code>pveceph pool destroy &lt;pool&gt; --force --remove_storages</code>; it takes everything inside with it.</li>
</ul>
<h2 id="see-also">See also</h2>
<ul>
<li><a href="/en/posts/proxmox/ceph-device-classes-crush-rules/">Ceph: device classes and CRUSH rules</a></li>
<li><a href="/en/posts/proxmox/vm-is-locked-snapshot-delete/">VM is locked (snapshot-delete)</a> — orphaned RBD snapshots show up there</li>
<li>Ceph documentation: <a href="https://docs.ceph.com/en/latest/rados/operations/health-checks/#recent-crash">Health checks — RECENT_CRASH</a></li>
</ul>
]]></content:encoded></item><item><title>Ceph on Proxmox: device classes and CRUSH rules to keep SAS, SSD and NVMe apart</title><link>https://inet.sh/en/posts/proxmox/ceph-device-classes-crush-rules/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/proxmox/ceph-device-classes-crush-rules/</guid><description>How to make a Ceph pool on Proxmox VE use only one kind of disk: assign device classes to OSDs (set-device-class, with rm-device-class first if they already had one), create a replicated CRUSH rule per class and point the pool at that rule with pveceph or ceph osd pool set. Includes custom classes such as sas.</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></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"># 1. OSD class. If it already has one (automatic hdd/ssd/nvme), remove it first: Ceph will not overwrite it</span>
</span></span><span class="line"><span class="cl">ceph osd crush rm-device-class osd.5
</span></span><span class="line"><span class="cl">ceph osd crush set-device-class sas osd.5
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 2. Rule that only places data on that class (root &#34;default&#34;, failure domain &#34;host&#34;)</span>
</span></span><span class="line"><span class="cl">ceph osd crush rule create-replicated replicated_sas default host sas
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 3. New pool on the rule, registered as Proxmox storage</span>
</span></span><span class="line"><span class="cl">pveceph pool create vm-sas --crush_rule replicated_sas --add_storages <span class="m">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ...or move an existing pool (rebalances all of its data)</span>
</span></span><span class="line"><span class="cl">pveceph pool <span class="nb">set</span> vm-fast --crush_rule replicated_sas
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="why">Why</h2>
<p>Ceph&rsquo;s default rule (<code>replicated_rule</code>) spreads objects across <strong>all</strong> OSDs without looking at the disk underneath. In a mixed cluster that means the &ldquo;fast&rdquo; pool also lands on the slow disks and performs like the worst of them.</p>
<p>Since Luminous every OSD carries a <strong>device class</strong>. Ceph detects it on its own at startup (<code>hdd</code>, <code>ssd</code>, or <code>nvme</code>) and a CRUSH rule can be restricted to one class: internally it builds a shadow hierarchy (<code>default~sas</code>) with only those OSDs and places the whole pool there. The class is a free label: besides the automatic ones you can use <code>sas</code>, <code>sata</code>, <code>archive</code>, or whatever helps you separate.</p>
<h2 id="checking-the-state">Checking the state</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">ceph osd tree                        <span class="c1"># CLASS column per OSD</span>
</span></span><span class="line"><span class="cl">ceph osd crush class ls              <span class="c1"># existing classes</span>
</span></span><span class="line"><span class="cl">ceph osd crush class ls-osd sas      <span class="c1"># OSDs in a class</span>
</span></span><span class="line"><span class="cl">ceph osd crush tree --show-shadow    <span class="c1"># the default~&lt;class&gt; shadow hierarchies</span>
</span></span><span class="line"><span class="cl">ceph osd crush rule ls
</span></span><span class="line"><span class="cl">ceph osd crush rule dump replicated_sas
</span></span><span class="line"><span class="cl">ceph osd pool ls detail              <span class="c1"># crush_rule &lt;id&gt; of each pool</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="changing-an-osds-class">Changing an OSD&rsquo;s class</h2>
<p>If the OSD already has a class, <code>set-device-class</code> does not overwrite it:</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-text" data-lang="text"><span class="line"><span class="cl">Error EBUSY: osd.5 has already bound to class &#39;hdd&#39;, can not reset class to &#39;sas&#39;;
</span></span><span class="line"><span class="cl">use &#39;ceph osd crush rm-device-class &lt;id&gt;&#39; to remove old class first
</span></span></code></pre></td></tr></table>
</div>
</div><p>Hence the <code>rm-device-class</code> first. Several OSDs at once:</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">ceph osd crush rm-device-class osd.5 osd.6 osd.7
</span></span><span class="line"><span class="cl">ceph osd crush set-device-class sas osd.5 osd.6 osd.7
</span></span></code></pre></td></tr></table>
</div>
</div><p>There is no &ldquo;create the class&rdquo; step: the <code>ceph osd crush class create</code> from the early Luminous builds was removed, and the class appears with the first OSD that gets it. To rename it cluster-wide, <code>ceph osd crush class rename sas sas-10k</code>.</p>
<p>A manually assigned class <strong>survives OSD restarts</strong>: on startup the OSD tries to set its automatic class and gets the same <code>EBUSY</code>. If you would rather have new OSDs come up with no class so you assign it yourself, <code>ceph config set osd osd_class_update_on_start false</code>; the price is that no new OSD gets an automatic class.</p>
<h2 id="the-rule">The rule</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">ceph osd crush rule create-replicated &lt;name&gt; &lt;root&gt; &lt;failure-domain&gt; &lt;class&gt;
</span></span><span class="line"><span class="cl">ceph osd crush rule create-replicated replicated_sas default host sas
</span></span><span class="line"><span class="cl">ceph osd crush rule create-replicated replicated_nvme default host nvme
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><code>root</code> is <code>default</code> unless you built your own CRUSH tree.</li>
<li><code>host</code> as the failure domain puts each replica on a different node. With <code>size 3</code> you need <strong>at least three nodes</strong> with OSDs of that class, or the PGs stay <code>undersized</code>.</li>
<li>For erasure-coded pools the class goes into the profile: <code>pveceph pool create ec-sas --erasure-coding k=4,m=2,device-class=sas</code>.</li>
</ul>
<h2 id="the-pool">The pool</h2>
<p>New, with the Proxmox storage included:</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">pveceph pool create vm-sas --crush_rule replicated_sas --size <span class="m">3</span> --min_size <span class="m">2</span> --add_storages <span class="m">1</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Existing: <code>pveceph pool set vm-fast --crush_rule replicated_sas</code>, or in the GUI <strong>Ceph → Pools → Edit → Crush Rule</strong>. It is the same as <code>ceph osd pool set vm-fast crush_rule replicated_sas</code>. The change triggers a <strong>backfill of the whole pool</strong> onto the class&rsquo;s OSDs; do it in a maintenance window and follow it with <code>ceph -s</code>.</p>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>Count the OSDs before the rule.</strong> Three nodes, <code>size 3</code>, and only two with <code>sas</code> disks: the pool never reaches <code>active+clean</code>.</li>
<li><strong>Automatic classes get it wrong</strong> with RAID/HBA controllers that present SSDs as rotational. Check <code>ceph osd tree</code> after adding disks and correct with <code>rm-device-class</code> + <code>set-device-class</code>.</li>
<li><strong>Moving a big pool to another rule moves all of its data.</strong> Raise <code>osd_max_backfills</code> only if you know what you are doing; it is slow by default on purpose.</li>
<li><strong>Deleting a pool that refuses to go</strong>: <code>pveceph pool destroy &lt;pool&gt; --force --remove_storages</code> (the data goes with it).</li>
</ul>
<h2 id="see-also">See also</h2>
<ul>
<li><a href="/en/posts/proxmox/ceph-crash-archive-orphaned-rbd/">Ceph on Proxmox: crashes and orphaned disks</a></li>
<li><a href="/en/posts/proxmox/no-subscription-repos/">No-subscription repositories</a> — includes the Ceph repo</li>
<li>Ceph documentation: <a href="https://docs.ceph.com/en/latest/rados/operations/crush-map/#device-classes">CRUSH Maps — Device classes</a></li>
</ul>
]]></content:encoded></item><item><title>Proxmox VE without a subscription: no-subscription repositories on PVE 9 (deb822) and PVE 8</title><link>https://inet.sh/en/posts/proxmox/no-subscription-repos/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/proxmox/no-subscription-repos/</guid><description>How to keep a Proxmox VE without a subscription updating with no 401 errors: disable pve-enterprise and enable pve-no-subscription (plus Ceph) on PVE 9 with deb822 .sources files and on PVE 8 with .list files. Includes apt modernize-sources and the Proxmox Backup Server equivalent.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<p><strong>PVE 9</strong> (Debian 13 <em>trixie</em>, deb822 format):</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><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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">cat &gt; /etc/apt/sources.list.d/proxmox.sources <span class="s">&lt;&lt;&#39;EOF&#39;
</span></span></span><span class="line"><span class="cl"><span class="s">Types: deb
</span></span></span><span class="line"><span class="cl"><span class="s">URIs: http://download.proxmox.com/debian/pve
</span></span></span><span class="line"><span class="cl"><span class="s">Suites: trixie
</span></span></span><span class="line"><span class="cl"><span class="s">Components: pve-no-subscription
</span></span></span><span class="line"><span class="cl"><span class="s">Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Disable enterprise (without a subscription it returns 401 on every apt update)</span>
</span></span><span class="line"><span class="cl">grep -q <span class="s1">&#39;^Enabled:&#39;</span> /etc/apt/sources.list.d/pve-enterprise.sources <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  <span class="o">||</span> <span class="nb">echo</span> <span class="s1">&#39;Enabled: false&#39;</span> &gt;&gt; /etc/apt/sources.list.d/pve-enterprise.sources
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">apt update <span class="o">&amp;&amp;</span> apt full-upgrade
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>PVE 8</strong> (Debian 12 <em>bookworm</em>, one-line format):</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">echo</span> <span class="s1">&#39;deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  &gt; /etc/apt/sources.list.d/pve-no-subscription.list
</span></span><span class="line"><span class="cl">sed -i <span class="s1">&#39;s/^deb /# deb /&#39;</span> /etc/apt/sources.list.d/pve-enterprise.list
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">apt update <span class="o">&amp;&amp;</span> apt full-upgrade
</span></span></code></pre></td></tr></table>
</div>
</div><p>If the host runs Ceph, the Ceph enterprise repo has to be disabled too and swapped for its <code>no-subscription</code> (<a href="/en/posts/proxmox/no-subscription-repos/#ceph">below</a>).</p>
<h2 id="what-each-repository-does">What each repository does</h2>
<table>
  <thead>
      <tr>
          <th>Repo</th>
          <th>Purpose</th>
          <th>Without a subscription</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>pve-enterprise</code></td>
          <td>Stable packages, the most tested. Needs a subscription key</td>
          <td><code>apt update</code> returns <strong>401 Unauthorized</strong></td>
      </tr>
      <tr>
          <td><code>pve-no-subscription</code></td>
          <td>Public. Same packages, a bit earlier and with less testing</td>
          <td>Works</td>
      </tr>
      <tr>
          <td><code>pve-test</code></td>
          <td>Bleeding edge, for testing</td>
          <td>Works</td>
      </tr>
  </tbody>
</table>
<p>Proxmox is clear about it: <code>pve-no-subscription</code> is for <strong>testing and non-production use</strong>; in production they want you to pay for a subscription and use enterprise. For a lab or a homelab it is the normal repo.</p>
<p>The enterprise 401 does not break anything by itself, but every <code>apt update</code> ends in an error and the other repos are left half refreshed. Disabling it is the fix; there is no need to delete it.</p>
<h2 id="pve-9-sources-files-deb822">PVE 9: .sources files (deb822)</h2>
<p>Since PVE 9 the installer already writes <code>/etc/apt/sources.list.d/pve-enterprise.sources</code> in deb822 format. A <code>.sources</code> file is a block of keys:</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><span class="lnt">6
</span><span class="lnt">7
</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"># /etc/apt/sources.list.d/pve-enterprise.sources
</span></span><span class="line"><span class="cl">Types: deb
</span></span><span class="line"><span class="cl">URIs: https://enterprise.proxmox.com/debian/pve
</span></span><span class="line"><span class="cl">Suites: trixie
</span></span><span class="line"><span class="cl">Components: pve-enterprise
</span></span><span class="line"><span class="cl">Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
</span></span><span class="line"><span class="cl">Enabled: false
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>Enabled: false</code> keeps it written but inactive. The no-subscription block is the one in the <a href="/en/posts/proxmox/no-subscription-repos/#tldr">TL;DR</a>; the test one is the same with <code>Components: pve-test</code>.</p>
<p>If you carry <code>.list</code> files from an upgrade off PVE 8, apt 3 converts them for you:</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">apt modernize-sources
</span></span></code></pre></td></tr></table>
</div>
</div><p>It rewrites each <code>.list</code> as <code>.sources</code> and leaves the original as <code>.list.bak</code>.</p>
<h2 id="pve-8-list-files">PVE 8: .list files</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># /etc/apt/sources.list.d/pve-enterprise.list
</span></span><span class="line"><span class="cl"># deb https://enterprise.proxmox.com/debian/pve bookworm pve-enterprise
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># /etc/apt/sources.list.d/pve-no-subscription.list
</span></span><span class="line"><span class="cl">deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
</span></span></code></pre></td></tr></table>
</div>
</div><p>Commenting the enterprise line with <code>#</code> is the deb822 <code>Enabled: false</code> equivalent.</p>
<h2 id="ceph">Ceph</h2>
<p>The installer also leaves the Ceph <strong>enterprise</strong> repo. Same treatment; the repo name carries the Ceph release the cluster runs (<code>ceph -v</code>):</p>
<p>PVE 9:</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><span class="lnt">6
</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"># /etc/apt/sources.list.d/ceph.sources
</span></span><span class="line"><span class="cl">Types: deb
</span></span><span class="line"><span class="cl">URIs: http://download.proxmox.com/debian/ceph-tentacle
</span></span><span class="line"><span class="cl">Suites: trixie
</span></span><span class="line"><span class="cl">Components: no-subscription
</span></span><span class="line"><span class="cl">Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
</span></span></code></pre></td></tr></table>
</div>
</div><p>Swap <code>ceph-tentacle</code> for <code>ceph-squid</code> if you are still on Squid. If the original file had <code>Components: enterprise</code>, replace the whole file with this one.</p>
<p>PVE 8:</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-text" data-lang="text"><span class="line"><span class="cl"># /etc/apt/sources.list.d/ceph.list
</span></span><span class="line"><span class="cl"># deb https://enterprise.proxmox.com/debian/ceph-squid bookworm enterprise
</span></span><span class="line"><span class="cl">deb http://download.proxmox.com/debian/ceph-squid bookworm no-subscription
</span></span></code></pre></td></tr></table>
</div>
</div><p>On bookworm there are <code>ceph-quincy</code>, <code>ceph-reef</code>, and <code>ceph-squid</code>; use the one matching your cluster, not the newest.</p>
<h2 id="proxmox-backup-server">Proxmox Backup Server</h2>
<p>Identical pattern with <code>pbs</code> in the URI and <code>pbs-no-subscription</code> as the component:</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><span class="lnt">6
</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"># /etc/apt/sources.list.d/proxmox.sources (PBS 4, trixie)
</span></span><span class="line"><span class="cl">Types: deb
</span></span><span class="line"><span class="cl">URIs: http://download.proxmox.com/debian/pbs
</span></span><span class="line"><span class="cl">Suites: trixie
</span></span><span class="line"><span class="cl">Components: pbs-no-subscription
</span></span><span class="line"><span class="cl">Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
</span></span></code></pre></td></tr></table>
</div>
</div><p>And <code>Enabled: false</code> in <code>pbs-enterprise.sources</code>.</p>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>Do not mix suites.</strong> <code>bookworm</code> on PVE 8, <code>trixie</code> on PVE 9. One line with the wrong suite breaks the next <code>full-upgrade</code>.</li>
<li><strong>The keyring is already there.</strong> <code>/usr/share/keyrings/proxmox-archive-keyring.gpg</code> ships with any ISO install. You only need to download it when installing Proxmox on top of a clean Debian (the official guide for that path covers it).</li>
<li><strong><code>Signed-By</code> is mandatory in deb822</strong>; without that line apt ignores the repo with a warning.</li>
<li><strong>If apt fails with <code>pve-apt-hook: not found</code></strong>, that is not a repo problem: <a href="/en/posts/proxmox/pve-apt-hook-not-found/">separate post</a>.</li>
<li><strong>The GUI&rsquo;s &ldquo;no valid subscription&rdquo; notice</strong> is independent of the repos and is not fixed here; a Community subscription removes it and gives you the enterprise repo as a bonus.</li>
</ul>
<p>Reference: <a href="https://pve.proxmox.com/wiki/Package_Repositories">Package Repositories</a> on the Proxmox wiki.</p>
]]></content:encoded></item></channel></rss>