Skip to content
SkyKeephelp

Admin console settings

This table is generated from the vault's closed settings registry — the same enumeration the console enforces, so it is complete by construction. A console value overrides the environment baseline until cleared; an unknown key or out-of-contract value is refused, never stored.

Some settings are set in the deployment's env file, never here

The Where it is set column says which. The malware scanner is the whole of that class today — the engine, its signatures, the external command and its timeout — and the reason is that each of those is a lever that can leave the ingest scan gate detecting nothing. The vault refuses to start a production installation on a scanner that scans nothing, and that refusal reads the environment the container was started with, not the database: a check that needed the database would refuse a vault whose database was merely slow. So a stored value would be a downgrade no guard could see, and one console session is a narrower thing to trust than the file an operator edits on the host.

Set SKYKEEP_SCANNER in the env file this deployment was started with and restart. It ships empty, and empty is a configured absence rather than an oversight: with no engine named every upload quarantines. That is the gate working. Nothing anywhere turns the two ingest scan gates off — there is no such setting, and the console listing one would not make one.

Four of these settings — the two model roles, the embedding model and the entity-extraction fallback — have a page of their own, because choosing one is a decision with consequences elsewhere: see Choosing the models.

SettingEnvironment baselineWhere it is setWhat it doesExample
model_providerSKYKEEP_MODEL_PROVIDERadmin console, over the environment baselineWhich model runtime serves every AI-driven step. 'ollama' serves embeddings and generation; 'openai' speaks the OpenAI-compatible chat API and generates only — its embeddings refuse rather than guess. An unrecognized provider refuses service; it never falls back.ollama
model_base_urlSKYKEEP_OLLAMA_BASE_URLadmin console, over the environment baselineThe model provider's endpoint (ADR-0002: connection details are configuration). Local-first: a non-local endpoint is refused unless the operator's explicit egress override is active.http://models:11434
embed_modelSKYKEEP_EMBED_MODELadmin console, over the environment baselineEmbedding model (ingestion step 7) — a different KIND of choice from the two chat roles, which is why ADR-0031 keeps it on its own control. Changing the answering model changes the next answer; changing this one invalidates every vector in the vault. A different-width model is refused by the engine; a same-width one is worse, because it succeeds and ranks new documents against old vectors from another space. In practice a kickoff-time decision (architecture doc, Model Configuration).all-minilm
think_modelSKYKEEP_THINK_MODELadmin console, over the environment baselineThe ANSWERING model: it writes the answer to a question (ADR-0009 — safety is structural, so this choice changes answer quality, never what an answer may be written from). Settings → Models lists what this deployment's runtime actually has, with what each one is good and bad at.granite4.1:3b
ingest_modelSKYKEEP_INGEST_MODELadmin console, over the environment baselineThe INGESTION model: it reads a document at upload to write its summary. Nobody waits on an upload, so a slower, more careful model is cheap here — but the cost is paid on every document. Empty means ingestion uses the answering model.granite4.1:3b
entity_fallback_modelSKYKEEP_ENTITY_FALLBACK_MODELadmin console, over the environment baselineEntity extraction's LLM fallback model (ingestion step 6). Empty disables the fallback: unresolved mentions honestly stay unresolved, never guessed (Gate IN.5).granite4.1:3b
model_context_tokensSKYKEEP_MODEL_CONTEXT_TOKENSadmin console, over the environment baselineHow many TOKENS of context the vault asks the model runtime for. Ollama's own default is 2048 and it silently truncates a longer prompt to its tail — which for this vault means the highest-ranked passages are discarded and the answer is built from the leftovers. Raising this costs memory on the model host; lowering it costs evidence, quietly.8192
embed_batch_max_textsSKYKEEP_EMBED_BATCH_MAX_TEXTSadmin console, over the environment baselineMaximum number of texts to embed in a single call to the model provider (PT-30). Ingestion and search batch embeddings in sub-calls if they exceed this limit. A large value (e.g. 512) is safe on a high-memory runtime; a small value (e.g. 8) is safe on a constrained one. Empty or out of range = 64.64
passages_per_documentSKYKEEP_PASSAGES_PER_DOCUMENTadmin console, over the environment baselineHow many passages ONE document may contribute to a single retrieval. Empty means 3. Raising it lets a document that answers a question in several places actually answer it; lowering it spreads the same k results across more documents. 1 is the historical behaviour: exactly one passage per document, which is why a résumé could be stored, matched and still not yield the phone number printed at the top of it. The per-request k is unchanged and still bounds the total.3
summary_max_wordsSKYKEEP_SUMMARY_MAX_WORDSadmin console, over the environment baselineHow long a document summary may be, in words. Empty means 200, the architecture's own bound. A document too long for the answering model's context window is read in PARTS and the part-summaries summarized together; the listing says when that happened, because a summary of summaries is a weaker claim than a summary and must not arrive looking like one.200
tags_max_countSKYKEEP_TAGS_MAX_COUNTadmin console, over the environment baselineHow many TAGS a document may carry. Empty means 8. Tags are read from the vault's own summary by the classification pass and published in the OKF frontmatter an agent reads, so this bounds what leaves the vault about one document. A model offering more than this is TRUNCATED, not refused, and the ingest's audit entry records that it was. Changing this reaches later uploads only: tagging happens once, at ingest.8
tags_max_lengthSKYKEEP_TAGS_MAX_LENGTHadmin console, over the environment baselineHow long ONE tag may be, in characters. Empty means 40. A longer candidate is DROPPED whole rather than trimmed to fit — trimming would manufacture a tag the model never offered — and this is a length bound only: a tag carrying a newline, a control character or a YAML `---` marker is dropped at any length, by a rule no setting can relax.40
chunk_window_wordsSKYKEEP_CHUNK_WINDOW_WORDSadmin console, over the environment baselineHow many WORDS of a document go into one chunk. It must fit the embedding model's input limit: a chunk longer than the embedder reads is indexed by its opening only, and the rest is stored, decryptable and citable but unreachable by meaning. A value the configured embedder cannot read is REFUSED here, with both numbers named, rather than silently indexing a prefix. Empty means 190, which fits the shipped embedder. **This does not apply to documents already ingested.** Chunking happens once, at upload; changing this re-chunks nothing already stored and reaches only later uploads.190
document_date_floor_yearSKYKEEP_DOCUMENT_DATE_FLOOR_YEARadmin console, over the environment baselineThe earliest year a document may claim to have been written. A document states its own creation date in bytes the uploader controls, so the vault records that claim separately from the moment it received the file — and refuses a claim that is in the future or older than this year, leaving the document's date UNKNOWN with the refusal recorded rather than letting an asserted date decide where the document sorts. Empty means 1900; there is no way to configure no floor at all. Changing it does not re-assess documents already ingested.1900
passage_expansion_max_wordsSKYKEEP_PASSAGE_EXPANSION_MAX_WORDSadmin console, over the environment baselineHow many WORDS a passage may reach the answering model as. A chunk that wins the ranking is expanded to its enclosing heading section, up to this bound, so the model reads a whole thought instead of the window the embedder's input limit forced. Citations still name the chunk that MATCHED, never the wider span. Empty means 600; 0 turns widening off and every passage arrives exactly as it was chunked. A bound the configured context window cannot hold is REFUSED here, with both numbers named. **This applies to documents already stored** — it changes which offsets are read, not what was written.600
second_hop_max_passagesSKYKEEP_SECOND_HOP_MAX_PASSAGESadmin console, over the environment baselineHow many EXTRA passages a second retrieval hop may add. When a first search surfaces a reference code the question did not contain, the vault searches again for that code and the answering model gets both halves — the essay and the register row that points at it. The second search runs as the same person under the same compartment predicates, so it can never reach a document the asker could not already read. A question that surfaces no new code costs nothing. Empty means 2; 0 turns the hop off and the prompt is exactly what it was before.2
auth_providerSKYKEEP_AUTH_PROVIDERadmin console, over the environment baselineHow this vault signs people in (ADR-0003). Two implementations ship. 'local' is the password+OTP provider whose credentials live in the vault's own database. 'directory' authenticates each sign-in as a simple bind against the configured LDAP/Active Directory server (SKYKEEP_DIRECTORY_*, ADR-0060) — the person must ALREADY hold an account here; this signs them in, it does not create anybody. The choice is exclusive and it is the whole vault's: under 'directory' a local-only account cannot sign in, INCLUDING the bootstrap administrator, and neither password rotation nor changing where sign-in codes go is offered, because SkyKeep only ever reads the directory and cannot write a new secret back into it. Unset, or any other value, refuses every sign-in (503) — there is no fallback to local.local
disable_window_secondsSKYKEEP_DISABLE_TERMINATION_SECONDSadmin console, over the environment baselineDisabling an account blocks new sessions immediately and ends an in-flight session within this window (Gate AU.4); ceiling-clamped to the human session ceiling.60
scannerSKYKEEP_SCANNERenv file only — not in the consoleENVIRONMENT ONLY (PT-4c): set in the deployment's env file, never in the console. Malware scanner engine for the ingest gate. Empty — the shipped default — means no scanner is configured, and an unconfigured scanner quarantines every upload: fail-closed, never fail-open. 'pattern' is the byte-signature double for dev/CI; 'command' runs an external ClamAV-convention command (SKYKEEP_SCANNER_COMMAND) and is what a real engagement uses. Neither choice can turn the gate OFF: there is no such setting.command
scanner_signaturesSKYKEEP_SCANNER_SIGNATURESenv file only — not in the consoleENVIRONMENT ONLY (PT-4c). Comma-separated signature list for the pattern scanner. A scanner with no signatures could never detect, so it counts as unconfigured (uploads quarantine) — which is why emptying it is the same lever as naming no engine at all.SKYKEEP-MALWARE-TEST-SIGNATURE
scanner_commandSKYKEEP_SCANNER_COMMANDenv file only — not in the consoleENVIRONMENT ONLY (PT-4c): a console that could edit this line could point the malware gate at /bin/true, which exits 0 on anything. The command the 'command' scanner runs, shell-word-split. The document's path is appended as the final argument (clamscan's own convention) and the exit status is the verdict: 0 clean, 1 infected, anything else an error that quarantines. Empty while the engine is 'command' counts as unconfigured, so every upload quarantines. The shipped default points at containers/scanner/clamscan-stub.sh, which ANSWERS CLEAN WITHOUT SCANNING — replace it with a real clamscan/clamdscan and no code changes./opt/skykeep/scanner/clamscan-stub.sh --no-summary
scanner_timeout_secondsSKYKEEP_SCANNER_TIMEOUT_SECONDSenv file only — not in the consoleENVIRONMENT ONLY (PT-4c), for the same reason as the engine and the command: a timeout small enough that every scan gives up is the gate stopped by another name. How long the 'command' scanner may take on one document before the gate gives up. A timeout is a QUARANTINE, never a pass — a scanner that did not answer has not answered 'clean'.60
mail_relaySKYKEEP_MAIL_RELAYadmin console, over the environment baselineOutbound mail relay kind for one-time sign-in codes (Gate AU.6). Empty means no relay is configured, and code delivery refuses fail-closed — sign-in is honestly unavailable, never a silently dropped code.smtp
smtp_hostSKYKEEP_SMTP_HOSTadmin console, over the environment baselineThe customer's SMTP relay host (ADR-0002: connection details are configuration). Required once mail_relay is 'smtp'.relay.example.internal
smtp_portSKYKEEP_SMTP_PORTadmin console, over the environment baselineThe SMTP relay's TCP port (1-65535). Required once mail_relay is 'smtp'.587
smtp_fromSKYKEEP_SMTP_FROMadmin console, over the environment baselineThe From address on outbound one-time-code mail. Required once mail_relay is 'smtp'.skykeep-vault@example.com
smtp_usernameSKYKEEP_SMTP_USERNAMEadmin console, over the environment baselineSMTP AUTH username. Empty (with an empty password) means an unauthenticated relay; setting one of username/password without the other refuses fail-closed.skykeep-mailer
smtp_passwordSKYKEEP_SMTP_PASSWORDadmin console, over the environment baselineSMTP AUTH password. A secret: it travels only in request bodies, is redacted in audit entries, and never appears in URLs or logs.change-me-dev-only
smtp_tlsSKYKEEP_SMTP_TLSadmin console, over the environment baselineSMTP transport security: 'starttls' (upgrade after connect), 'tls' (implicit TLS from the first byte), or 'plain' (cleartext — trusted networks only). Empty defaults to 'starttls'.starttls
require_all_mfaSKYKEEP_REQUIRE_ALL_MFAadmin console, over the environment baselineRequire the one-time sign-in code for EVERY account past its first login, whatever each person has chosen on their profile (ADR-0025). Empty or 'false' leaves the choice to each account. Turning this on overrides every stored preference and never overwrites one: turning it off again restores exactly what each person had chosen.false
purge_certificatesSKYKEEP_PURGE_CERTIFICATESadmin console, over the environment baselineIssue purge certificates: a signed statement, with the audit chain entries that prove it, that a named version was destroyed in this vault (ADR-0087). Empty or 'true' (the shipped default) offers the capability. 'false' refuses every request for one, names the reason, and records the refusal in the audit trail — it does NOT invalidate a certificate already issued, which goes on verifying offline for as long as its engagement key slot is installed.true
email_domain_restrictionSKYKEEP_EMAIL_DOMAIN_RESTRICTIONadmin console, over the environment baselineRestrict invitations to the allowed e-mail domains below. Empty or 'false' (the shipped default) invites ANY domain, which is what this vault does today. 'true' refuses an address whose domain is not listed — and, if the list is empty, refuses every address rather than allowing every address, because a restriction with nothing to compare against is an unfinished intention, not permission.false
allowed_email_domainsSKYKEEP_ALLOWED_EMAIL_DOMAINSadmin console, over the environment baselineThe e-mail domains an account may be invited at, separated by commas, semicolons or spaces. Matching is EXACT and case-insensitive: listing 'example.com' does NOT admit 'mail.example.com' — a sub-domain may be delegated to anybody, so it is listed on its own or not at all. The Users page shows which existing accounts fall outside this list, whether or not the restriction above is on.example.com, partner.example.org
email_domain_exceptionsSKYKEEP_EMAIL_DOMAIN_EXCEPTIONSadmin console, over the environment baselineIndividual addresses admitted whatever the allowed-domain list says — the contractor, the auditor, the one person the rule was not meant for. WHOLE ADDRESSES only: a bare domain is refused here, because a domain belongs in the allowed list and two settings that meant the same thing would drift apart.contractor@othercompany.example
near_duplicate_max_distanceSKYKEEP_NEAR_DUPLICATE_MAX_DISTANCEadmin console, over the environment baselineHow different two documents may be and still be reported as nearly duplicate, in bits of a 64-bit fingerprint. Measured on ordinary prose: a re-flowed copy is 0, a word or a sentence changed is 3-8, one paragraph of seven rewritten is 13, an unrelated document of the same kind is 34. Empty or out of range = 16. Raising it finds more pairs and more false ones; 0 reports only documents whose fingerprints are identical.16
near_duplicate_min_shinglesSKYKEEP_NEAR_DUPLICATE_MIN_SHINGLESadmin console, over the environment baselineHow much text a document must have before the vault will fingerprint it at all, counted in overlapping five-word windows. Below this the document gets NO fingerprint and can never be reported as a near duplicate of anything — without that rule every file the vault could not read would pair with every other one. Empty or out of range = 8.8
near_duplicate_min_length_percentSKYKEEP_NEAR_DUPLICATE_MIN_LENGTH_PERCENTadmin console, over the environment baselineThe shorter of two documents must be at least this percent of the longer one before they can be called near duplicates. The fingerprint is a fixed 64 bits however long a document is, so a page and a book that repeats it land close together; this is what stops the vault calling them the same file. Empty or out of range = 50.50
near_duplicate_max_candidatesSKYKEEP_NEAR_DUPLICATE_MAX_CANDIDATESadmin console, over the environment baselineHow many near-duplicate pairs one upload may record. A cap, because a corpus of near-identical forms would otherwise pair a new upload with hundreds of rows nobody will read. 0 turns detection off entirely — the same spelling SKYKEEP_SECOND_HOP_MAX_PASSAGES uses for the same meaning. Empty or out of range = 20.20
disk_space_threshold_bytesSKYKEEP_DISK_SPACE_THRESHOLD_BYTESadmin console, over the environment baselineFree disk space threshold in bytes below which uploads are refused (PT-7). The threshold applies only when a disk-space sample exists; a missing sample means 'unknown' and is not a refusal. A refused upload is given an honest reason naming both the current free space and the threshold, so an operator can tune either. Empty or out of range = 104857600 (100 MB).104857600
merge_confirmation_ttl_secondsSKYKEEP_MERGE_CONFIRMATION_TTL_SECONDSadmin console, over the environment baselineHow long a compartment-merge confirmation stays spendable, in seconds. Merging is the vault's only clean-up verb and has no unmerge, so it is confirmed against a preview: the preview counts what moves, the merge re-counts and refuses if the numbers have changed, and this bounds the gap between the two. Lower is safer and more annoying; a long window is a confirmation of what the vault looked like some time ago. Empty = 300.300
hold_default_review_daysSKYKEEP_HOLD_DEFAULT_REVIEW_DAYSadmin console, over the environment baselineHow long after a legal hold is placed somebody should ask whether it still needs to stand, in days. THIS IS NOT AN EXPIRY: a hold past its review date is still a hold, it still refuses a purge, and no setting, timer or job anywhere in this vault lifts one — the only way out is an administrator typing the acknowledgment phrase and a reason. What the date does is put the hold on the holds-needing-review panel, answer the stale listing, and make a refused purge say in the trail that a stale hold is what refused it. Changing this moves the date stamped on holds placed from now on; it never moves the date on a hold already placed. Empty = 180.180
grant_expiry_warn_daysSKYKEEP_GRANT_EXPIRY_WARN_DAYSadmin console, over the environment baselineHow many days ahead the admin console's recertification list looks when it names the grants that are about to expire (PT-26). A grant with no expiry never appears in that list at whatever window — it is not going to lapse. This dial reports; it never grants, extends or revokes anything. Empty or out of range = 30.30
base_max_inflightSKYKEEP_BASE_MAX_INFLIGHTenv file only — not in the consoleENVIRONMENT ONLY (ADR-0094): how many model calls this PROCESS may have open at once against the BASE endpoint — every chunk of every document, as embeddings, and every generation on a deployment that has not split one off. The largest cap of the six because an embed is milliseconds where a generation is seconds, so this is the seam a queue actually drains. A cap is a property of this process's own sockets, so N replicas are N caps; it is deployment configuration and a console that could raise it could raise it past what the runtime can serve. Past the cap a request waits SKYKEEP_ADMISSION_WAIT_SECONDS and is then refused 429 with Retry-After; an ingest call waits instead, because it has nobody to refuse to. 0 IS REFUSED AT START-UP by name — it is not 'no limit', it is a vault that can never think. Empty = 8.8
generation_max_inflightSKYKEEP_GENERATION_MAX_INFLIGHTenv file only — not in the consoleENVIRONMENT ONLY (ADR-0094): how many model calls this PROCESS may have open at once against the GENERATION endpoint — ingest summaries, entity fallback, the auditor screen, translation. UNSET GENERATION SHARES THE BASE CAP: if no separate generation endpoint is configured, generation runs on the base runtime and is metered by SKYKEEP_BASE_MAX_INFLIGHT, because two numbers over one machine would mean neither of them was the real limit. A cap is a property of this process's own sockets, so N replicas are N caps; it is deployment configuration and a console that could raise it could raise it past what the runtime can serve. Past the cap a request waits SKYKEEP_ADMISSION_WAIT_SECONDS and is then refused 429 with Retry-After; an ingest call waits instead, because it has nobody to refuse to. 0 IS REFUSED AT START-UP by name — it is not 'no limit', it is a vault that can never think. Empty = 4.4
answer_max_inflightSKYKEEP_ANSWER_MAX_INFLIGHTenv file only — not in the consoleENVIRONMENT ONLY (ADR-0094): how many model calls this PROCESS may have open at once against the ANSWER endpoint — the final synthesis call alone. Shares the GENERATION cap (and through it the BASE cap) unless SKYKEEP_ANSWER_MODEL_URL routes it somewhere of its own. A cap is a property of this process's own sockets, so N replicas are N caps; it is deployment configuration and a console that could raise it could raise it past what the runtime can serve. Past the cap a request waits SKYKEEP_ADMISSION_WAIT_SECONDS and is then refused 429 with Retry-After; an ingest call waits instead, because it has nobody to refuse to. 0 IS REFUSED AT START-UP by name — it is not 'no limit', it is a vault that can never think. Empty = 4.4
vision_max_inflightSKYKEEP_VISION_MAX_INFLIGHTenv file only — not in the consoleENVIRONMENT ONLY (ADR-0094): how many model calls this PROCESS may have open at once against the VISION engine — image bytes. Small because a reading carries a whole file and its concurrency costs memory as well as runtime. Shares the BASE cap when SKYKEEP_VISION_BASE_URL is unset. A cap is a property of this process's own sockets, so N replicas are N caps; it is deployment configuration and a console that could raise it could raise it past what the runtime can serve. Past the cap a request waits SKYKEEP_ADMISSION_WAIT_SECONDS and is then refused 429 with Retry-After; an ingest call waits instead, because it has nobody to refuse to. 0 IS REFUSED AT START-UP by name — it is not 'no limit', it is a vault that can never think. Empty = 2.2
transcribe_max_inflightSKYKEEP_TRANSCRIBE_MAX_INFLIGHTenv file only — not in the consoleENVIRONMENT ONLY (ADR-0094): how many model calls this PROCESS may have open at once against the TRANSCRIBE engine — audio bytes. Its own cap always: an unset transcription URL is a vault that does not transcribe, not one that transcribes somewhere else. A cap is a property of this process's own sockets, so N replicas are N caps; it is deployment configuration and a console that could raise it could raise it past what the runtime can serve. Past the cap a request waits SKYKEEP_ADMISSION_WAIT_SECONDS and is then refused 429 with Retry-After; an ingest call waits instead, because it has nobody to refuse to. 0 IS REFUSED AT START-UP by name — it is not 'no limit', it is a vault that can never think. Empty = 2.2
page_render_max_inflightSKYKEEP_PAGE_RENDER_MAX_INFLIGHTenv file only — not in the consoleENVIRONMENT ONLY (ADR-0094): how many model calls this PROCESS may have open at once against the PAGE RENDER engine (ADR-0091) — PDF bytes drawn into pictures. Its own cap always, for the reason transcription's is its own. A cap is a property of this process's own sockets, so N replicas are N caps; it is deployment configuration and a console that could raise it could raise it past what the runtime can serve. Past the cap a request waits SKYKEEP_ADMISSION_WAIT_SECONDS and is then refused 429 with Retry-After; an ingest call waits instead, because it has nobody to refuse to. 0 IS REFUSED AT START-UP by name — it is not 'no limit', it is a vault that can never think. Empty = 4.4
admission_wait_secondsSKYKEEP_ADMISSION_WAIT_SECONDSenv file only — not in the consoleENVIRONMENT ONLY (ADR-0094): how long a request-path model call waits for room on its seam before it is refused 429. SECONDS, and NOT the model timeout — a caller waiting here holds a request thread and a socket while producing nothing, so the wait exists to absorb a burst that is already draining, never to queue. The number is also what a refused caller is told to wait, because the seam was full for the whole of it. An ingest call ignores this and waits up to its seam's own model timeout instead. Empty = 5.5