omni-stream 0.10.0

Single-binary streaming storage proxy: axum + tokio + aws-sdk-s3 backend with an embedded React SPA, serving local FS or S3-compatible object storage behind one port.
# OmniStream configuration template.
# Place at $XDG_CONFIG_HOME/omni-stream/config.toml, or set
# OMNI_CONFIG=/path/to/config.toml. Regenerate with `omni-stream config init`.
#
# Convention:
#   key = val               you must set this (deployment-specific, no default)
#   # key = val  # default  code default shown — uncomment to override
#   # key = val  # optional no default; uncomment only if you need it
#
# Env overrides (prefix OMNI_, separator _):
#   OMNI_SERVER_HOST, OMNI_SERVER_PORT, OMNI_AUTH_TOKEN

[server]
# host = "127.0.0.1"  # default; use "0.0.0.0" to allow external access
# port = 28080        # default

[auth]
# Optional bearer-token gate. Disabled = API open to anyone who can reach the
# port. Enable for internal-tool deployments.
# enabled = false                               # default
# token = "replace-with-a-long-random-string"  # required when enabled = true (or OMNI_AUTH_TOKEN)
#
# Read/write granularity (only applies when enabled = true):
#   public_read = true   # DEFAULT — browsing / preview / download stay open;
#                        # only writes (SQL queries, JSONL->Parquet convert,
#                        # plus any future upload / delete) require the token.
#   public_read = false  # full lockdown — every request requires the token.
#                        # NOTE: the /raw file mount relies on bearer-header
#                        # auth; browsers can't inject bearer headers on
#                        # navigation/fetch, so /raw is not practically usable
#                        # in full-lockdown mode. Use public_read = true (the
#                        # default) when you need /raw.
# NOTE: enabling auth no longer locks down reads by default. For the old
# "everything needs the token" behavior, set public_read = false.
# public_read = true                            # default

# ---- Storage backends -----------------------------------------------------
# At least one [[storages]] entry is REQUIRED. active = true is served by
# default; if none is active, the first entry wins.

# S3-compatible (AWS S3 / MinIO / Ceph / AOSS / OSS / COS)
[[storages]]
name = "production-s3"  # required; shown in UI, used as ?storage=<name>
type = "s3"             # required

[storages.s3]
access_key = "minioadmin"              # required for static creds (omit for IAM role / anonymous)
secret_key = "minioadmin"              # required for static creds
# endpoint = "http://localhost:9000"   # optional; omit for real AWS, set for self-hosted gateways
# bucket = "my-bucket"                 # optional; omit or "*" → multi-bucket (needs s3:ListAllMyBuckets)
# region = "us-east-1"                 # default; set to the bucket's real region for AWS outside us-east-1
# force_path_style = true              # default; set false for virtual-host gateways (some AOSS/OSS)

# Local filesystem
[[storages]]
name = "local-data"  # required
type = "local"       # required
# active = false     # default

[storages.local]
root_path = "/var/lib/omni-stream"  # required; absolute or ~-prefixed, no ".." traversal
# follow_symlinks = true            # default; false → symlinks surfaced as entries, reads Forbidden

# ---- Thumbnails (on-demand WebP cache; disabled by default) ---------------
# When off, the grid falls back to /api/proxy originals and /api/thumb returns
# 404 "thumbnails disabled". Uncomment enabled = true below to opt in.

[thumbnails]
# enabled = true                              # opt in (default: false)
# cache_path = "~/.cache/omni-stream/thumbs"  # default; else XDG / ProjectDirs-derived
# quality = 70                                # default; WebP quality 1-100
# max_source_bytes = 52428800                 # default 50 MiB; larger sources are rejected
# sizes = [160, 320, 640]                     # default width ladder (px)
# default_size = 320                          # default; snapped into `sizes` if not a member
# max_cache_bytes = 1073741824                # default 1 GiB; LRU sweep trims above this
# max_age_days = 90                           # default; 0 disables the age cap
# sweep_interval_secs = 3600                  # default; floored to 60s at runtime

# ---- SQL query endpoint (DuckDB; needs a `--features duckdb` build) --------
# POST /api/query runs read-only SQL (SELECT / DESCRIBE / EXPLAIN / etc.)
# against the selected storage via an embedded DuckDB. COPY and all mutating
# statements are rejected. The endpoint only activates
# when the binary was built with the `duckdb` cargo feature AND auth.enabled =
# true above — it never runs on an open API. PyPI wheels ship with the
# feature; `cargo install omni-stream` does not.
#
# Local storages with follow_symlinks = false refuse SQL entirely: DuckDB's
# directory sandbox follows symlinks, so it cannot honour that setting.

[sql]
# enabled = true            # default; kill-switch independent of the build feature
# memory_limit = "512MB"    # default; DuckDB memory_limit per query connection
# threads = 2               # default; DuckDB threads per query connection
# query_timeout_secs = 300  # default (5 min); query is interrupted past this, HTTP 408
# max_rows = 10000          # default; result rows beyond this are dropped (truncated = true)