Silo is configured through a layered system. From highest priority to lowest: CLI flags overrideDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/org-quicko/silo/llms.txt
Use this file to discover all available pages before exploring further.
SILO_* environment variables, which override the silo.toml file, which falls back to built-in defaults. Every key is optional — an empty or absent silo.toml is perfectly valid. Run silo init to generate a fully-annotated template at the defaults.
Annotated silo.toml
The file below is exactly whatsilo init writes. Every setting is at its default value, with alternatives and S3 keys commented inline.
Environment variables
Everysilo.toml key has a corresponding SILO_* variable. Set these in your container environment, systemd unit, or .env file to override the file without editing it.
| Environment variable | Overrides |
|---|---|
SILO_CONFIG | Which file this table is read from and written to, below --config |
SILO_LISTEN | listen |
SILO_HTTP_IDLE_TIMEOUT | [http] idle_timeout |
SILO_HTTP_MAX_BODY_SIZE_MB, SILO_HTTP_MAX_JSON_BODY_SIZE_MB | [http] max_body_size_mb, [http] max_json_body_size_mb |
SILO_TRANSFER_MAX_ARCHIVE_SIZE_MB, SILO_TRANSFER_MAX_EXTRACTED_SIZE_MB | [transfer] max_archive_size_mb, [transfer] max_extracted_size_mb |
SILO_READ_THREAD | on or off: whether entry lists and searches on SQLite run on a separate storage thread. On by default; off under the test runner. Not present in the file |
SILO_DEFAULT_PROJECT, SILO_DEFAULT_ENV | default_project, default_env |
SILO_STORAGE_DRIVER, SILO_STORAGE_PATH | [storage] driver, [storage] path |
SILO_BLOB_DRIVER, SILO_BLOB_PATH | [blob_storage] driver, [blob_storage] path |
SILO_BLOB_S3_BUCKET, SILO_BLOB_S3_REGION, SILO_BLOB_S3_ENDPOINT | [blob_storage] bucket, region, endpoint |
SILO_BLOB_S3_ACCESS_KEY_ID, SILO_BLOB_S3_SECRET_ACCESS_KEY | [blob_storage] access_key_id, secret_access_key |
SILO_BLOB_S3_FORCE_PATH_STYLE | [blob_storage] force_path_style |
SILO_BLOB_S3_PUBLIC_READ | [blob_storage] public_read |
SILO_AUTH_DISABLED | [auth] disabled |
SILO_SCHEMA_ALLOW_REMOTE_REFS | [schema] allow_remote_refs |
SILO_SEARCH_ENABLED, SILO_SEARCH_TOKENIZER | [search] enabled, [search] tokenizer |
SILO_LOG_LEVEL, SILO_LOG_FILE, SILO_LOG_FORMAT | [log] level, [log] file, [log] format |
SILO_LOG_REQUESTS, SILO_LOG_MAX_SIZE_MB, SILO_LOG_MAX_FILES | [log] requests, [log] max_size_mb, [log] max_files |
SILO_MEDIA_BASE_URL, SILO_MEDIA_BASE_URL_TARGET | [media] base_url and its target |
SILO_MEDIA_EXTENSIONS | [media] extensions, comma-separated |
SILO_VERSION | The version silo reports. Not configuration and not in the file. The release sets it in the container image. A binary ignores it. If you set it, silo will report a version that it is not |
Storage drivers
Silo ships two storage drivers. Choose one per deployment; switching later requires an export and import.sqlite (default)
Stores all data at
<path>/silo.db. A single file, zero external dependencies, and the right choice for the vast majority of deployments. Writes are serialised inside the process, which is what makes optimistic concurrency (If-Match) sound.fs
Writes one JSON file per entry as a flat directory tree. The on-disk layout is the export format, making it ideal for reviewing changes with
git diff and backing up with rsync. No binary blob to inspect.[storage] is reported by the settings API but never written. Changing the storage driver means pointing at a different instance, not reconfiguring this one. Use silo export and silo import to move data between drivers.Blob storage
Media files (uploads) are stored separately from structured data. Two blob drivers are available.fs (default)
Files are stored at
<data dir>/media, or at the path you set via [blob_storage] path, SILO_BLOB_PATH, or --blob-path. Moving the data directory moves media with it unless you pin the path explicitly.s3
Any S3-compatible bucket: AWS S3, MinIO, Cloudflare R2, DigitalOcean Spaces. Requires
bucket and region. Set endpoint for non-AWS providers. Credentials go in access_key_id and secret_access_key, or the standard AWS environment variables.public_read defaults to true for S3 buckets: media URLs point directly at the bucket, which requires a bucket policy granting anonymous s3:GetObject. Set public_read = false for a private bucket — silo then streams each file from storage at /media/<id> instead, using the credentials you configured. Nothing else changes and no URL breaks.Media URLs
How a media URL is formed depends on two settings: whether you have abase_url, and who is serving the file.
When base_url is set, every media link is rooted at that address:
base_url value | A media URL looks like |
|---|---|
https://api.example.com | https://api.example.com/media/<id> |
https://example.com/silo | https://example.com/silo/media/<id> |
base_url is not set, the URL depends on the blob provider:
Provider, no base_url | A media URL looks like |
|---|---|
| Local directory | <your server's address>/media/<id> |
| Bucket | <the bucket's own address>/<blob key> |
Bucket with public_read = false | <your server's address>/media/<id> |
base_url addresses each file directly at the bucket, with silo out of the read path. That is the shape an email client needs, because it cannot authenticate.
Public S3 bucket policy
If you use an S3 bucket and want silo to hand out direct bucket URLs (i.e.public_read is on), you must apply a bucket policy that allows anonymous reads. Turning off Block Public Access alone is not enough — without a policy, S3 answers AccessDenied for every file and each media URL breaks.
public_read = false instead.
Authentication
[auth] disabled = true is a development escape hatch: every request is treated as root with no key required. It is settable to false via the settings API, but never to true — an API that can switch off its own authentication is a lock whose key opens itself. Use the CLI or the config file to enable it.
Log file
Silo’s logging behaviour is intentionally simple.With no
[log] file set, silo logs to the console regardless of whether a terminal is attached. This is the correct behavior under Docker and systemd — let the supervisor own the output stream.- No
fileset: all output goes to stdout (correct for containers and process supervisors). fileset: silo writes to that file and to the console when stdout is a terminal. A foreground server you are watching still shows itself.--detach: automatically picks<data dir>/silo.logas the log file. This is the only case where silo chooses a path for you.
Schema references
A schema can reference another schema with standard JSON Schema$ref. Silo supports two kinds of reference, with different trust levels.
silo://collections/<name>
Always allowed. Resolved locally against another collection in the same project and environment. No network involved. The schema builder offers these as Reference fields; entry forms render the referenced collection’s fields inline.
https:// remote refs
Rejected by default. Fetching a schema over the network during validation makes writes non-deterministic, adds an availability dependency, and lets any schema editor trigger outbound fetches. Set
allow_remote_refs = true to opt in. Fetched schemas are cached in memory until a schema changes.Search tokenizer
The search index uses SQLite FTS5 under the hood. Two tokenizer modes are available.| Tokenizer | Behavior | Best for |
|---|---|---|
unicode61 (default) | Word-based tokenization | Latin scripts and most European languages |
trigram | Substring search on character trigrams | CJK languages; also enables mid-word search in any language |
Plugin configuration block
Plugins are declared as an ordered[[plugins]] array in silo.toml. The order matters: hook dispatch runs top-to-bottom through this list.
| Key | Meaning |
|---|---|
name | Directory name under <data dir>/plugins/. Required |
claims | A declarative list of claims to grant this plugin. A second way to say what silo plugin grant stores |
timeout_ms | Milliseconds a hook call may run. The plugin is terminated and the call fails if it exceeds this |
on_error | fail (default): a plugin error fails the request. skip: log the error and continue |
[plugins.config] | Arbitrary plugin-specific configuration, passed to the plugin at load time |
There is no
SILO_PLUGINS environment variable by design. Which code runs on your server is not something the environment should be able to change. Plugin configuration is always explicit in silo.toml.