Configuration
S3 Lens reads YAML configuration. The standalone process automatically loads s3lens.yaml from its current directory when the file exists, or you can select one or more files with --config.
Minimal configuration
Section titled “Minimal configuration”workspace: id: local display_name: Local storage providers: - id: garage display_name: Garage type: generic endpoint: http://127.0.0.1:3900 region: garage force_path_style: true credentials: access_key_id: ${GARAGE_ACCESS_KEY} secret_access_key: ${GARAGE_SECRET_KEY}
server: listen: http://127.0.0.1:8085 allow_insecure_remote: false max_object_body_bytes: 16777216
logging: level: info
ui: enabled: false # title: Local storage | S3 LensProvider type defaults to generic when omitted. See Storage providers for the supported types.
Unknown fields are rejected. Configuration validation is local: it checks YAML shape, identifiers, endpoints, credentials, and cross-field invariants without contacting a Provider.
Sections
Section titled “Sections”| Section | Purpose |
|---|---|
workspace |
Stable Workspace identity and its configured Providers. |
server |
Listener safety and the maximum Object body permitted in bounded RPC operations. |
logging |
Standalone process verbosity: error, warn, info, debug, or trace. |
ui |
Serve the bundled browser application and set its optional browser title. |
auth |
Optional OIDC authentication, policies, bindings, and durable API Keys. |
When workspace is omitted, the server uses the development identity default / Default Workspace with no Providers. The default listener is http://127.0.0.1:8085.
Bundled web UI
Section titled “Bundled web UI”ui.enabled defaults to false. When enabled, a binary built with the
embed-ui Cargo feature serves the browser application at /, alongside the
RPC and authentication endpoints. Static assets are public so the sign-in page
can load before authentication. Existing API authentication still applies.
Run pnpm run build from the repository root to build
target/release/s3lens with fresh production assets. The Docker image also
includes the assets. Neither needs Node.js or frontend files at runtime.
Ordinary Cargo builds omit the assets. Starting one with ui.enabled: true or
--ui fails with an error before opening the state database. The bundled UI
uses the server’s origin, ignores VITE_RPC_URL, and is served at the origin
root rather than a configurable URL prefix.
HTML, fonts, and favicons revalidate through ETags. Fingerprinted files under
/assets/ use immutable caching. Browser navigation under /providers and
/settings receives the application HTML, including Object paths containing
dots. Missing assets and unknown API paths return errors instead of HTML.
GET /v1/instance is always available, including when the bundled UI is
disabled. It returns the public Workspace display name as name and the
configured ui.title as title. If ui.title is omitted, title uses the
Workspace display name. The endpoint contains no authentication or Provider
configuration.
Configuration precedence
Section titled “Configuration precedence”The standalone process resolves values from lowest to highest precedence:
- Built-in defaults
- Configuration files from left to right
- Command-line options such as
--listen,--log-level,--ui, and--allow-insecure-remote
cargo run -- serve \ --config ./base.yaml \ --config ./deployment.yaml \ --config ./local-secrets.yamlLater mapping values override earlier ones. Provider lists merge by stable Provider ID: a later Provider with the same ID replaces the complete earlier entry while keeping its position. Other YAML sequences, including authentication policies and bindings, replace the earlier sequence as a whole.
Environment references
Section titled “Environment references”Selected operational string fields support environment references:
${NAME}requires a non-empty environment variable.${NAME:-}uses an empty-string fallback.${NAME:-value}usesvaluewhen the variable is absent or empty.
Expansion is supported in server.listen; Provider region, endpoint, and credential fields; auth.public_origin; Redis auth.session.url; and OIDC issuer, client_id, client_secret, redirect_uri, and post_logout_redirect_uri. Identity fields, display names, policy documents, bindings, OIDC scopes, and claim selectors remain literal.
credentials: access_key_id: ${S3_ACCESS_KEY_ID} secret_access_key: ${S3_SECRET_ACCESS_KEY} session_token: ${S3_SESSION_TOKEN:-}Listener safety
Section titled “Listener safety”The server accepts plain HTTP because local and embedded hosts commonly terminate TLS elsewhere. Non-loopback listeners are rejected unless server.allow_insecure_remote or --allow-insecure-remote is explicitly enabled. That switch only relaxes the listener check; it does not add TLS, authentication, authorization, or origin restrictions.
Validate before serving
Section titled “Validate before serving”cargo run -- config validatecargo run -- config validate --config ./deployment.yamlInspect the effective configuration
Section titled “Inspect the effective configuration”config show loads, merges, expands, and canonicalizes the same document the
server would use. Provider credentials and OIDC client secrets are replaced by a
visible [REDACTED] marker before the YAML is printed.
cargo run -- config show --config ./base.yaml --config ./deployment.yamlFor complete examples, see the configurations under examples/ and Storage providers.