Core Concepts
Before diving into individual features, it helps to have the right mental model for what s3BEAR actually is and how its pieces fit together.
The single gated door
s3BEAR sits in front of any backend that exposes an S3-compatible API. AWS S3, MinIO,
Ceph, and Wasabi are examples rather than an exhaustive provider list. s3BEAR acts as
the single gated access path to it. Nothing — not a
browser, not an LLM provider, not an external partner — talks to the
underlying storage directly. Every request, whether it comes from your own
frontend or an unauthenticated GET from a share link, passes through
s3BEAR's permission checks first.
Why it matters: instead of every service re-implementing auth, MIME checking, and presigned-URL logic against S3 directly, you get one consistent enforcement point for the whole organization.
Private by default
The S3 bucket itself is never made public. There are no bucket ACL changes, no public-read policies. s3BEAR decides access at the application layer — per user, per share link, per request — while the bucket stays private at the storage level. Even a tokenized public share link doesn't change anything on the S3 side; s3BEAR validates the token and streams the object through itself.
Three roles
s3BEAR's capabilities fall into three roles:
- LLM-ready public hosting — expose private objects as expiring, revocable HTTPS URLs suitable for multimodal LLM inputs (Claude, GPT-4o, Gemini). See LLM Integration.
- Authenticated image serving — serve images from private buckets to the browser, with per-user permission checks and on-the-fly transforms (resize, re-encode). See Image Serving.
- S3 management console — manage buckets, objects, permissions, quotas, and cleanup policies from the web UI or API.
Share tokens
A share token turns one object into a tokenized, expiring, revocable HTTPS URL without touching the S3 bucket's ACLs. Tokens are:
- Expiring — choose
1h/24h/7d/30d, a custom duration, ornever(permanent until revoked). - Revocable — an admin or the creator can revoke a link at any time.
- Hashed at rest — the raw token is stored as a SHA-256 hash; the raw value is shown only once, at creation.
An expired, revoked, or unknown token always returns 410 Gone — the response never reveals whether the underlying object exists. See Share Links for the full API and use cases.
Groups & permissions
Users belong to one or more groups. Each group holds a list of bucket
permissions, where each permission pairs a glob bucket pattern (matched
with *, ?, [seq]) with four boolean flags: can_list, can_read,
can_write, can_delete.
A user's effective permission for a given bucket is the union of every
matching permission across all of their groups — if any group grants
write on a matching pattern, the user has write. Admin users bypass all
permission checks entirely.
Why it matters: naming buckets by convention (
<team>-*) means new buckets created inside a team's namespace are automatically covered by existing group permissions — no manual grant per bucket.
See Permissions for the full model and worked examples.
Image proxy vs. share links
s3BEAR exposes images to the outside world through two distinct paths:
| Image proxy | Share link | |
|---|---|---|
| Auth | JWT (authenticated) | Tokenized, no auth |
| Audience | Your logged-in users / frontend | Anyone with the URL (LLM providers, partners) |
| Lifetime | Until permissions change | Expires / revocable |
| Use case | In-app previews, dashboards | LLM image inputs, external embeds |
Both support the same on-the-fly transform query params (w, h, format,
q, fit). See Image Serving and
Share Links for details.
Data plane
Two stores back everything above:
- S3-compatible storage — holds the actual objects. s3BEAR never buffers large uploads through itself; big files move browser-to-storage directly via presigned URLs.
- PostgreSQL — holds everything that isn't an object: users, groups, permission policies, audit log entries, share links, and webhook configuration/delivery history.
Next steps
- Architecture — how the client, backend, and data plane fit together, request-by-request.
- Quick Start — run s3BEAR locally in about a minute.
