<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Documentation on Shelltrap</title><link>https://shelltrap.com/docs/</link><description>Recent content in Documentation on Shelltrap</description><generator>Hugo</generator><language>en-GB</language><atom:link href="https://shelltrap.com/docs/index.xml" rel="self" type="application/rss+xml"/><item><title>Installation and first run</title><link>https://shelltrap.com/docs/installation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://shelltrap.com/docs/installation/</guid><description>&lt;h2 id="requirements">Requirements&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Root access&lt;/strong>, or a package service account with full installation rights. The broker
&lt;code>shelltrapd&lt;/code> runs as root; the worker runs as &lt;code>shelltrap-scan&lt;/code>, a system user without a login
shell and without a home directory.&lt;/li>
&lt;li>&lt;strong>A supported CyberPanel operating system:&lt;/strong> Ubuntu 20.04, 22.04 or 24.04; AlmaLinux,
RockyLinux or RHEL 8, 9 or 10; CloudLinux 8; CentOS 9. Debian is only third-party supported by
CyberPanel and is not promised.&lt;/li>
&lt;li>&lt;strong>A Linux filesystem under the configured customer roots&lt;/strong> (&lt;code>/home&lt;/code> by default), enough
memory, and a kernel on which the installer can actually probe the fanotify and file-handle
capabilities.&lt;/li>
&lt;li>&lt;strong>For the Full profile:&lt;/strong> at least 1.5 GiB of &lt;code>MemAvailable&lt;/code> remaining &lt;em>after&lt;/em> the measured
reload reserve, which includes the observed clamd footprint plus a fixed safety margin. This
measurement must not be replaced by a global sysctl change.&lt;/li>
&lt;li>&lt;strong>For ClamAV in the Full profile:&lt;/strong> a running or installable &lt;code>clamd&lt;/code> and a Unix socket
reachable by the &lt;code>shelltrap-scan&lt;/code> user, &lt;code>/run/clamav/clamd.ctl&lt;/code> by default. A socket readable
only by root is not enough. If the service or the worker&amp;rsquo;s access is unavailable, the state
becomes &lt;code>degraded&lt;/code> and never &lt;code>clean&lt;/code>.&lt;/li>
&lt;li>&lt;strong>For the PHP upload adapter:&lt;/strong> a supported lsphp/LSWS installation. The adapter needs only the
local socket &lt;code>/run/shelltrap/upload.sock&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Tools:&lt;/strong> &lt;code>sha256sum&lt;/code>, GnuPG and either &lt;code>curl&lt;/code> or &lt;code>wget&lt;/code> for the host installer; &lt;code>unzip&lt;/code> in
addition for the CyberPanel package. The native package manager resolves dependencies.&lt;/li>
&lt;/ul>
&lt;h2 id="host-preflight">Host preflight&lt;/h2>
&lt;p>Before any download, the host installer prints read-only facts about the machine and changes
nothing:&lt;/p></description></item><item><title>Configuration and policies</title><link>https://shelltrap.com/docs/configuration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://shelltrap.com/docs/configuration/</guid><description>&lt;h2 id="the-policy-model">The policy model&lt;/h2>
&lt;p>Every setting that steers behaviour is a policy on three levels:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>global&lt;/strong> — the whole host&lt;/li>
&lt;li>&lt;strong>account&lt;/strong> — one CyberPanel user&lt;/li>
&lt;li>&lt;strong>domain&lt;/strong> — one website or child domain&lt;/li>
&lt;/ol>
&lt;p>The more specific level wins, and each level may inherit or override individual keys. Inside a
domain there can also be path rules using globs relative to the document root.&lt;/p>
&lt;p>Assignment works through a document-root index the broker keeps from the CyberPanel database
(website, child domain, document root, owner), refreshed on a timer and on panel changes.
fanotify events are mapped to an account and a domain by the longest matching document-root
prefix. The PHP adapter passes &lt;code>DOCUMENT_ROOT&lt;/code> and &lt;code>SERVER_NAME&lt;/code>; the document root decides and
the server name is only used as a plausibility check. Files outside every document root — mail,
backups, the home root — fall under the account policy.&lt;/p></description></item><item><title>The CyberPanel plugin</title><link>https://shelltrap.com/docs/plugin/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://shelltrap.com/docs/plugin/</guid><description>&lt;h2 id="before-you-install">Before you install&lt;/h2>
&lt;p>The Shelltrap broker must be running, &lt;code>/run/shelltrap/api.sock&lt;/code> must exist, and CyberPanel must
be installed. The plugin archive is built reproducibly and contains a single top-level directory
&lt;code>shelltrap/&lt;/code>, without caches or Python bytecode.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">cd /usr/local/CyberCP
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">/usr/local/CyberCP/bin/python /usr/local/CyberCP/pluginInstaller/pluginInstaller.py \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> install --pluginName shelltrap
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="why-the-install-is-so-careful">Why the install is so careful&lt;/h2>
&lt;p>The CyberPanel installer patches core files — &lt;code>CyberCP/settings.py&lt;/code>, &lt;code>CyberCP/urls.py&lt;/code> and the
sidebar template — by inserting lines, and its hook calls use &lt;code>subprocess.call&lt;/code> and &lt;strong>ignore
exit codes&lt;/strong>. A failed preflight therefore cannot stop the installation from claiming success.&lt;/p></description></item><item><title>Signature feeds</title><link>https://shelltrap.com/docs/feeds/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://shelltrap.com/docs/feeds/</guid><description>&lt;figure class="figure">&lt;svg viewBox="0 0 900 400" role="img" aria-labelledby="feedTitle feedDesc">
 &lt;title id="feedTitle">The path of a signature generation from source to activation&lt;/title>
 &lt;desc id="feedDesc">Sources are filtered by licence, given provenance and built into an Ed25519-signed generation. The client verifies digest and signature, the corpus gate checks against known-good and known-bad sets, and only then is the switch made atomically. A quarantine storm across several accounts triggers an automatic rollback.&lt;/desc>
 &lt;defs>
 &lt;marker id="fdArrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
 &lt;path d="M0 1l8 4-8 4z" fill="var(--border-strong)"/>
 &lt;/marker>
 &lt;marker id="fdArrowD" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
 &lt;path d="M0 1l8 4-8 4z" fill="var(--danger)"/>
 &lt;/marker>
 &lt;/defs>&lt;text x="24" y="26" class="svg-label" fill="var(--accent)">BUILD AT PANOMITY&lt;/text>
 &lt;text x="470" y="26" class="svg-label" fill="var(--accent)">ON YOUR SERVER&lt;/text>
 &lt;line x1="452" y1="18" x2="452" y2="300" stroke="var(--border)" stroke-width="1" stroke-dasharray="4 5"/>
 &lt;rect x="24" y="40" width="196" height="92" rx="5" class="svg-panel-raised"/>
 &lt;text x="38" y="66" class="svg-label" fill="var(--accent)">01&lt;/text>
 &lt;text x="38" y="90" class="svg-title">Sources&lt;/text>
 &lt;text x="38" y="112" class="svg-label svg-label--sm">own rules · curated third-party rules&lt;/text>
 &lt;path d="M220 86h12" stroke="var(--border-strong)" stroke-width="1.4" marker-end="url(#fdArrow)" fill="none"/>
 &lt;rect x="238" y="40" width="196" height="92" rx="5" class="svg-panel-raised"/>
 &lt;text x="252" y="66" class="svg-label" fill="var(--accent)">02&lt;/text>
 &lt;text x="252" y="90" class="svg-title">Licence filter&lt;/text>
 &lt;text x="252" y="112" class="svg-label svg-label--sm">only DRL-1.1, BSD-3, Apache-2.0, MIT&lt;/text>
 &lt;path d="M434 86h12" stroke="var(--border-strong)" stroke-width="1.4" marker-end="url(#fdArrow)" fill="none"/>
 &lt;rect x="452" y="40" width="196" height="92" rx="5" class="svg-panel-raised"/>
 &lt;text x="466" y="66" class="svg-label" fill="var(--accent)">03&lt;/text>
 &lt;text x="466" y="90" class="svg-title">Provenance&lt;/text>
 &lt;text x="466" y="112" class="svg-label svg-label--sm">source, author, commit, licence per rule&lt;/text>
 &lt;path d="M648 86h12" stroke="var(--border-strong)" stroke-width="1.4" marker-end="url(#fdArrow)" fill="none"/>
 &lt;rect x="666" y="40" width="196" height="92" rx="5" class="svg-panel-raised"/>
 &lt;text x="680" y="66" class="svg-label" fill="var(--accent)">04&lt;/text>
 &lt;text x="680" y="90" class="svg-title">Signature&lt;/text>
 &lt;text x="680" y="112" class="svg-label svg-label--sm">Ed25519 · manifest.json &amp;#43; manifest.sig&lt;/text>
 &lt;rect x="24" y="156" width="196" height="92" rx="5" class="svg-panel-raised"/>
 &lt;text x="38" y="182" class="svg-label" fill="var(--accent)">05&lt;/text>
 &lt;text x="38" y="206" class="svg-title">Verification&lt;/text>
 &lt;text x="38" y="228" class="svg-label svg-label--sm">digest before signature, expiry, denylist&lt;/text>
 &lt;path d="M220 202h12" stroke="var(--border-strong)" stroke-width="1.4" marker-end="url(#fdArrow)" fill="none"/>
 &lt;rect x="238" y="156" width="196" height="92" rx="5" class="svg-panel-raised"/>
 &lt;text x="252" y="182" class="svg-label" fill="var(--accent)">06&lt;/text>
 &lt;text x="252" y="206" class="svg-title">Corpus gate&lt;/text>
 &lt;text x="252" y="228" class="svg-label svg-label--sm">known-good is hard, known-bad is a ratio&lt;/text>
 &lt;path d="M434 202h12" stroke="var(--border-strong)" stroke-width="1.4" marker-end="url(#fdArrow)" fill="none"/>
 &lt;rect x="452" y="156" width="196" height="92" rx="5" class="svg-panel-raised"/>
 &lt;text x="466" y="182" class="svg-label" fill="var(--accent)">07&lt;/text>
 &lt;text x="466" y="206" class="svg-title">Activation&lt;/text>
 &lt;text x="466" y="228" class="svg-label svg-label--sm">atomic symlink swap, cache invalidated&lt;/text>
 &lt;path d="M648 202h12" stroke="var(--border-strong)" stroke-width="1.4" marker-end="url(#fdArrow)" fill="none"/>
 &lt;path d="M866 86v46H98v18" stroke="var(--border-strong)" stroke-width="1.4" marker-end="url(#fdArrow)" fill="none"/>

 
 &lt;rect x="24" y="288" width="852" height="88" rx="5" class="svg-panel"/>
 &lt;rect x="24" y="288" width="4" height="88" fill="var(--danger)"/>
 &lt;text x="48" y="314" class="svg-title" fill="var(--danger)">Circuit breaker&lt;/text>
 &lt;text x="48" y="336" class="svg-label">last hour against the 24-hour mean: at least 50 quarantines and more than ten times the mean&lt;/text>
 &lt;text x="48" y="356" class="svg-label">and at least three accounts and at least 20 % of active accounts — a single account can never trigger a server-wide rollback&lt;/text>
 &lt;path d="M760 288v-24" stroke="var(--danger)" stroke-width="1.4" marker-end="url(#fdArrowD)" fill="none"/>
 &lt;text x="612" y="282" class="svg-label svg-label--sm" fill="var(--danger)">automatic rollback&lt;/text>
&lt;/svg>
&lt;figcaption>Nothing is activated that has not been signed, verified twice, gated against a known-good and a known-bad corpus, and made revocable.&lt;/figcaption>
&lt;/figure>

&lt;h2 id="generations-not-updates">Generations, not updates&lt;/h2>
&lt;p>A rule set is not a stream of edits; it is a &lt;strong>generation&lt;/strong>: an immutable, signed directory.
Vendor generation IDs are exactly &lt;code>YYYYMMDDTHHMMSSZ-NNNN&lt;/code>, for example
&lt;code>20260903T120000Z-0001&lt;/code>. Local overlays use &lt;code>local-&amp;lt;64 hex characters&amp;gt;&lt;/code>.&lt;/p></description></item><item><title>Licensing and activation</title><link>https://shelltrap.com/docs/licensing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://shelltrap.com/docs/licensing/</guid><description>&lt;h2 id="the-pieces">The pieces&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Term&lt;/th>
 &lt;th>Meaning&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;strong>Licence key&lt;/strong>&lt;/td>
 &lt;td>&lt;code>STL-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;/code> — Crockford Base32, 25 payload characters including two check characters. Generated when the licence is created and returned in clear text exactly once; the service stores only &lt;code>sha256(key)&lt;/code> plus the first nine characters as a display prefix.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Licence&lt;/strong>&lt;/td>
 &lt;td>The record: plan, maximum servers (1 by default), status (&lt;code>active&lt;/code>, &lt;code>suspended&lt;/code>, &lt;code>terminated&lt;/code>), expiry, and the link to your account.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Activation&lt;/strong>&lt;/td>
 &lt;td>Binding a licence to a server fingerprint. At most &lt;code>max_servers&lt;/code> at a time; &lt;code>deactivate&lt;/code> frees a slot.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Licence token&lt;/strong>&lt;/td>
 &lt;td>An Ed25519-signed document the daemon verifies &lt;strong>offline&lt;/strong>.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Server fingerprint&lt;/strong>&lt;/td>
 &lt;td>&lt;code>sha256&lt;/code> over a fixed prefix and the contents of &lt;code>/etc/machine-id&lt;/code>. The hostname is sent for information only.&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="activation">Activation&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">shelltrap license activate STL-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">shelltrap license status
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">shelltrap license renew
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">shelltrap license deactivate
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The token lands in &lt;code>/etc/shelltrap/license.token&lt;/code>, root, mode &lt;code>0600&lt;/code>. The key itself is stored
only as a prefix in &lt;code>/etc/shelltrap/license.key&lt;/code>, also &lt;code>0600&lt;/code>, so renewals do not need you to
type it again. If you would rather not have the key on the server at all, delete that file and
renew manually.&lt;/p></description></item></channel></rss>