"Should X be a registry too?" gets re-asked every few months, and the answer is usually no. This records the rule and the per-catalog verdicts so the assessment does not get redone from scratch. A catalog earns a registry only when all three hold: it changes faster than the panel releases, it is data rather than code (a new entry must work on an existing panel with no code change), and someone outside the release cycle would contribute to it. Extensions, themes and app templates pass. Seven other catalogs were assessed and rejected, each with the reason -- server templates, notification events, AI providers, DB tuning settings, sanitization profiles, agent survey probes and build packs. Also names the failure mode that makes a bad extraction expensive: panels that have not upgraded read the registry forever, so an entry that needs new panel code either gets ignored or renders as a broken item. That is what forces a min_panel_version gate, and why serverkit-extensions has one and the other two do not need one. Records one open candidate rather than leaving it implicit. YARA rules pass all three tests and have no update path -- 16 curated rules frozen at release time. That got sharper this session: the image now builds without ClamAV by default, and ClamAV was the component with a self-updating feed via freshclam, so YARA is now the only malware detection in a default container. Operators can already drop custom .yar files in CUSTOM_RULES_DIR; what is missing is a curated upstream. Not built -- noted so the gap is deliberate. Adds the templates registry and this doc to the README documentation table. Every claim was checked against the code rather than written from memory: rule counts (16 in both BUILTIN_RULES and webshells.yar), the CUSTOM_RULES_DIR default, ARG INSTALL_CLAMAV=false, and that ServerTemplateService already exposes create_template so its 12-entry library is a seed, not a catalog. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5.5 KiB
Registries
ServerKit publishes some of its catalogs as standalone repositories that panels read over the network, so entries can ship without a panel release. Three exist today:
| Registry | Repo | Bundled in the panel? |
|---|---|---|
| Extensions | serverkit-extensions |
builtins only; the rest install on demand |
| Themes | serverkit-themes |
17 bundled, gallery adds more |
| App templates | serverkit-templates |
all 106 bundled, registry adds/updates |
This document exists because "should X be a registry too?" is a question that otherwise gets re-asked every few months. Most of the time the answer is no.
The test
A catalog earns a registry only when all three hold:
- It changes faster than the panel releases. If new entries naturally arrive with the feature work that consumes them, a registry buys nothing.
- It is data, not code. A new entry must work on an existing panel with no code change. If using it requires a new service method, a new job kind, or a new UI surface, it is code wearing a catalog's clothes.
- Someone outside the release cycle would contribute. If only the maintainers will ever add entries, a directory in this repo is simpler and reviews the same way.
Fail any one, and extraction adds a network dependency, a second release process, and a version-skew surface in exchange for nothing.
The failure mode to avoid
The expensive mistake is extracting a catalog that fails test 2. Panels that
have not upgraded keep reading the registry forever. Publish an entry that needs
new panel code, and every old panel either ignores it (best case) or shows a
broken item it cannot install (worst). At that point the registry needs its own
min_panel_version gate — which is exactly why serverkit-extensions has one,
and exactly the complexity you do not want unless the catalog earns it.
Why the three qualified
- Extensions are independently versioned code artifacts with permissions and
a
min_panel_versiongate. They are the archetype: third-party authored, released on their own cadence, installed at runtime. - Themes are pure token maps — data by construction, contributed by people who will never open a panel PR, and worthless if shipping one requires a release.
- App templates are declarative Compose specs. New self-hosted apps appear
constantly and each is ~2 KB of YAML that an existing panel already knows how
to install.
TemplateServicehas always resolved<repo_url>/index.json+<repo_url>/templates/<id>.yaml; the registry is just the other end of a contract the panel already had.
Note the pattern: bundled and registry are not exclusive. Templates and themes ship inside the panel and have a registry. The bundle is the offline floor — air-gapped installs, fresh installs with no network, and any day GitHub is unreachable — while the registry is the growth path. Only extensions lean on the registry as the primary source, because they are large and optional by nature.
What was assessed and rejected
| Catalog | Where | Verdict |
|---|---|---|
| Server templates | ServerTemplateService.TEMPLATE_LIBRARY |
No. 12 entries, stable, and operators already create their own via create_template() into the DB. The library is a seed, not a catalog. |
| Notification events | app/notifications/catalog.py |
No. Fails test 2 — an event type is only real if panel code emits it. A registry entry with no emitter is a dead row. |
| AI providers | ai_service.CURATED_PROVIDERS |
No. Each entry is bound to a Prompture driver; adding one without the driver produces a provider that cannot connect. |
| DB tuning settings | db_config_tuner_service.CURATED_SETTINGS |
No. Fails test 3 — tuning knobs track the engines the panel supports, and only maintainers will touch them. |
| Sanitization profiles | models/sanitization_profile.BUILTIN_PROFILES |
No. Consumed by code paths that must understand each profile. |
| Agent survey probes | app/data/survey_probe_catalog.yaml |
No. A probe is only meaningful if the agent implements its kind, so it is gated by the agent's release, not the panel's. |
| Build packs | buildpack_service |
No. Not a catalog at all — it generates Dockerfiles and compose from a build plan. That is code. |
Open candidate: malware signatures
YARA rules are the one remaining catalog that passes all three tests, and they have no update path today.
YaraScanService.BUILTIN_RULES (16 curated rules, mirrored in
yara_rules/webshells.yar) ships inside the panel and changes only when the
panel is released. Webshell signatures are the textbook case for out-of-band
updates — a new obfuscation family is worth pushing the day it is seen, not the
next release.
This matters more than it used to. The container image now builds without
ClamAV by default (ARG INSTALL_CLAMAV=false — see the Dockerfile), and
ClamAV was the component with a self-updating signature feed via freshclam.
In a default container, YARA is the only malware detection, and its rules are
frozen at release time.
Operators can already drop custom .yar files into
YaraScanService.CUSTOM_RULES_DIR (/var/serverkit/security/yara-custom, real
yara CLI required), so the local extension point exists. What is missing is a
curated upstream feed that updates itself.
Not built. Noted here so the decision is deliberate rather than forgotten.