Configuration Reference
Two surfaces configure SWIRL for Backstage. The Backstage side is the search.swirl block in app-config.yaml. The SWIRL side is environment variables on the container.
app-config.yaml: search.swirl
The whole block carries @visibility backend. None of it reaches the browser. baseUrl is the only required key.
search:
swirl:
baseUrl: http://swirl-backstage:8000
audience: search
indexerBatchSize: 500
queryTimeoutMs: 8000
federated:
enabled: true
providerTags: [backstage]
timeoutMs: 5000
tuning:
fieldBoosts:
titleExact: 3.0
titleNgram: 1.0
text: 1.0
ngram:
min: 4
max: 8
stemmer: english
fuzzy:
enabled: false
distance: 1
highlight:
enabled: true
maxChars: 200
startMarker: <em>
endMarker: </em>
Key reference
| Key | Type | Default | Meaning |
|---|---|---|---|
baseUrl |
string | required | Base URL of the SWIRL service, as the Backstage backend reaches it. |
audience |
string | search |
Backstage plugin id the module mints its tokens for. Must match SWIRL_BACKSTAGE_AUDIENCE. |
indexerBatchSize |
number | 500 |
Documents per ingest request. SWIRL rejects a batch larger than 1,000. |
queryTimeoutMs |
number | 8000 |
HTTP timeout the module applies to a query call to SWIRL. |
federated.enabled |
boolean | true |
Register the swirl-federated document type. Set to false to run the indexed lane only. |
federated.providerTags |
string[] | ["backstage"] |
SWIRL SearchProvider tags to fan out to. A source joins the federated lane by carrying one of these tags. |
federated.timeoutMs |
number | 5000 |
Federation timeout for one query, sent to SWIRL as backstage_timeout_ms. SWIRL rounds it to whole seconds and clamps it between 1 and 180. |
tuning |
object | empty | Relevance tuning, sent to SWIRL on startup. See below. |
highlight.enabled |
boolean | true |
Ask for snippets with the hit terms marked. |
highlight.maxChars |
number | 200 |
Longest snippet per field, counted in visible characters rather than markup. |
highlight.startMarker |
string | <em> |
The opening marker SWIRL uses, from its SWIRL_HIGHLIGHT_START_CHAR setting. Override both markers together. |
highlight.endMarker |
string | </em> |
The closing marker, from SWIRL_HIGHLIGHT_END_CHAR. |
Relevance tuning
The tuning block is posted to SWIRL at POST /swirl/index/config/ when the backend starts. SWIRL stores it and applies it on the next indexing run, because changing the n-gram bounds or the stemmer requires a rebuilt index. A tuning block SWIRL cannot read is logged and ignored, and SWIRL keeps its current tuning.
Write the tuning block with the nested, camelCase names in the table below. They are the ones the package declares in its config schema. The flat names SWIRL uses internally, such as title_exact_boost, are rejected by yarn backstage-cli config:check --strict, which most Backstage repositories run in CI. After a restart, confirm what SWIRL actually stored with GET /swirl/index/config/.
| Key | Type | Default | Meaning |
|---|---|---|---|
fieldBoosts.titleExact |
number | 3.0 |
Weight of the stemmed, ASCII-folded title field. |
fieldBoosts.titleNgram |
number | 1.0 |
Weight of the n-gram title field, which is what matches partial words. |
fieldBoosts.text |
number | 1.0 |
Weight of the body text field. |
ngram.min |
integer | 4 |
Shortest n-gram indexed on titles. |
ngram.max |
integer | 8 |
Longest n-gram indexed on titles. Maximum 32. |
stemmer |
string | english |
Stemmer language name. |
stopwords |
string or string[] | english |
A string names the stop word language for the body text field. A list adds extra stop words, lowercased on save. |
fuzzy.enabled |
boolean | false |
Typo tolerance on titles. Off by default. |
fuzzy.distance |
integer | 1 |
Edit distance when typo tolerance is on. 0, 1, or 2. |
The schema also declares bm25.k1 and bm25.b. SWIRL accepts and stores both and then reports them as not applied by this engine version, because the Tantivy binding exposes no way to set them. They change nothing about ranking today, so the example above leaves them out.
SWIRL's own config endpoint takes a few more knobs than the package declares, among them fieldBoosts.phraseMultiplier, removeLong, and its snippet settings. Those are not in the package schema, so putting them in app-config.yaml fails config:check --strict. Set them with a direct POST /swirl/index/config/ if you need them.
SWIRL environment variables
These are the defaults the Backstage image ships, from .env.backstage.dist in the SWIRL repository. Override any of them with environment: in compose or env: in the Kubernetes manifest.
| Variable | Default in the image | Meaning |
|---|---|---|
SECRET_KEY |
a development placeholder | Django secret key. Replace it on anything another person can reach. |
ALLOWED_HOSTS |
localhost,127.0.0.1,swirl |
Host names SWIRL will answer on. |
CSRF_TRUSTED_ORIGINS |
http://localhost:8000 |
Origins trusted for form posts to the admin. |
PROTOCOL |
http |
Scheme SWIRL builds its own URLs with. |
SWIRL_EXPLAIN |
True |
Include relevancy explanations in results. |
SQL_ENGINE |
django.db.backends.sqlite3 |
Database backend. The Backstage image uses SQLite. |
SQL_DATABASE |
/data/db.sqlite3 |
Database file on the volume. |
SQL_USER, SQL_PASSWORD, SQL_HOST, SQL_PORT |
placeholders | Unused with SQLite. Set them only if you point SWIRL at PostgreSQL. |
CELERY_BROKER_URL |
redis://127.0.0.1:6379/0 |
Redis broker. A local address makes the entrypoint start Redis inside the container. |
CELERY_RESULT_BACKEND |
redis://127.0.0.1:6379/0 |
Redis result backend. |
SWIRL_TANTIVY_DATA_DIR |
/data/tantivy |
Directory holding one subdirectory per document type. |
SWIRL_TANTIVY_WRITER_HEAP_MB |
64 |
Index writer heap. The SWIRL default outside the image is 128. |
SWIRL_TANTIVY_BEGIN_TTL |
7200 |
Seconds before an open generation is treated as stale, so a new begin is allowed. |
SWIRL_SPACY_MODEL_EN |
en_core_web_sm |
The one spaCy model the Backstage profile installs. |
SWIRL_BACKSTAGE_JWKS_URL |
empty | JWKS URL of the Backstage backend. Empty disables Backstage token verification. |
SWIRL_BACKSTAGE_AUDIENCE |
search |
Expected aud claim. Must match search.swirl.audience. |
SWIRL_TIMEOUT |
10 |
Seconds SWIRL waits for all federated sources. A query can override it with backstage_timeout_ms. |
SWIRL_HIGHLIGHT_START_CHAR, SWIRL_HIGHLIGHT_END_CHAR |
<em>, </em> |
Markers SWIRL wraps hit terms in. Change these together with the highlight markers in app-config. |
SWIRL_ADMIN_PASSWORD |
unset | Sets the admin password on start. Left alone when unset. |
SWIRL_PRINT_ADMIN_TOKEN |
unset | Set to true to print the admin API token to the container log on start. |
MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, MICROSOFT_REDIRECT_URI |
empty | Microsoft sign-in for the SWIRL Galaxy UI. Not used by Backstage. |
Checking what is in effect
Both calls need the admin API token or a Backstage service token.
# the tuning SWIRL actually stored
curl -s -H "Authorization: Token <admin-api-token>" \
http://localhost:8000/swirl/index/config/
# the live index per document type
curl -s -H "Authorization: Token <admin-api-token>" \
http://localhost:8000/swirl/index/