Features
Everything ravyn does, one page, grouped by area. All of it is
configured from /settings (your own account) or
/admin (instance-wide, admin only).
Accounts and access
The first account ever created, through /register or
the CLI, automatically becomes the instance's admin. Everyone
after that is gated by a registration mode an admin sets from
/admin: closed (default, accounts
only via the CLI or an invite), open (anyone can
sign up), or invite (a single-use code, generated
by an admin).
cargo run -p ravyn-api -- create-user alice hunter2
That command always creates an admin regardless of the current
registration mode, useful for a headless setup or adding a second
admin later. An API token (/settings) is what ShareX
or a script authenticates with instead of a session cookie, and
the settings page has a one-click "download ShareX config" button
that fills in the token and this instance's URL already.
Two-factor authentication
Optional, per user, off by default. Standard TOTP, compatible with any authenticator app: setup shows a QR code and confirms with a real code before it's actually turned on, so an abandoned setup never leaves an account half-protected. Confirming mints eight single-use recovery codes, shown once. Once enabled, login becomes two steps (password, then a code), and turning it back off needs both the password and a valid code, so a stolen session cookie alone can't touch it either way.
Per-user storage quotas
An admin sets a cap in MB per account from /admin,
or leaves it unlimited. An upload that would push someone over
their cap is rejected outright rather than partially saved.
Deleting an account
An admin can remove a user entirely from /admin,
behind an inline confirmation since it's irreversible. This
deletes their file bytes from storage, any in-progress upload's
leftover chunks, and the account itself, which cascades
everything else that belonged to them (folders, sessions,
tokens, short links). Activity log entries survive, since those
already store a snapshot of the username rather than a live
reference. An admin can't delete their own account this way, so
an instance never ends up with nobody able to manage it.
Rate limiting
Login, two-factor codes, registration, and uploads are all protected against brute-forcing with a simple limiter keyed by IP (or by account, for uploads): 10 login attempts per 5 minutes, 10 two-factor attempts per 5 minutes (a 6-digit code only has a million possibilities, so this one matters more than the password check), 5 registrations per hour, 60 uploads per minute. A rejected request gets a plain "too many attempts, try again later." This lives in memory and resets on a restart; it's meant to blunt casual abuse on a self-hosted instance, not stand up to a determined, distributed attacker.
Uploading
Large files
At or above 32 MB, an upload automatically switches from a single request to 8 MB chunks sent one at a time. A chunk that fails is retried on its own, up to three times, so a network blip partway through a multi-gigabyte upload costs a few seconds of retrying that one chunk, not starting over. Reloading the page mid-upload does lose progress today; there's no resume-after-reload yet, though the server already tracks enough to build that later.
ShareX and scripts
Dropping (or selecting) several files at once sends them as one
request with multiple parts. A single file upload gets back the
plain {"id": ...} shape ShareX expects; more than
one gets an array instead, so one bad file in a batch doesn't
silently drop the ones that succeeded next to it.
Text snippets
The upload page's "paste text" tab turns pasted text into a file and sends it through the exact same upload path as a real file, so naming, quotas, and auto-delete all apply the same way. Any text file under 2 MB (not just ones made this way) renders as a proper in-page text view instead of a raw download when opened.
URL shortener
A third upload-page tab: paste a destination, get back a short link. Deliberately minimal, just a slug, a destination, and a click counter, since the file side already covers passwords, expiry, and tags for anything actually hosted here. Each account only ever sees and manages its own links.
Organizing files
Folders
Flat labels (no nesting) a file can belong to, each with its own optional password. A folder's contents are viewable at its own public link without logging in, gated by the password if it has one, the same sharing model as a single file.
Passwords
A file can also be password-protected on its own, independent of any folder. A direct link to a protected file shows a small password prompt instead of the raw bytes. The owner always sees their own file regardless, whether through a session or an API token.
Tags
Simple, free-text, per-file tags, no shared registry to manage. The browse page's search matches both filenames and tags, and clicking a tag on a file card drops it straight into the search box.
Bulk actions
The browse page's "select" button turns every card into a checkbox. With one or more selected, a bar above the grid moves or deletes all of them at once.
File naming and lifecycle
Naming scheme
By default a file keeps whatever name it was uploaded with. An admin can switch the instance-wide default to a random string (length configurable), a UUID, or a timestamp, all of which keep the original file extension. This only changes the display name, not the link, and anyone can rename their own file afterward regardless of the default.
Auto-delete
An admin sets an instance-wide default expiry (from 5 minutes up to a year, or never) applied at upload time. Anyone can override their own file's expiry afterward, including turning it off entirely. A background sweep checks every 5 minutes and deletes anything past its expiry, storage and database record together.
EXIF stripping
On by default, instance-wide: removes camera model, GPS coordinates, and timestamps from an uploaded image before it's ever written to storage. Only affects JPEG, PNG, and WebP; other formats upload untouched rather than failing over a privacy nice-to-have. The image container is rewritten in place, not recompressed, so a stripped file is byte-identical to the original apart from the removed metadata.
Sharing and embeds
Every share link already works as a direct image or video link,
Discord previews it natively either way. Turning embeds on (per
account, from /settings) additionally sets a custom
title, description, and accent color that Discord, Slack, and
Twitter read from the link, with template variables for the
file's name, size, type, and the uploader's username.
Upload webhooks
Per account, off by default: every successful upload posts a notification (filename and link) to a URL you provide. Works for both Discord and Slack's webhook formats without needing to say which one it is. Sent in the background so a slow or unreachable target never delays the upload itself.
Visibility
Your own stats
Storage used against your quota, file count, and a breakdown by
type, in /settings.
Instance stats
The same shape summed across every account, plus registration
mode and invite management, in /admin.
Cost estimate
A fun, not-a-bill number on /admin: fill in a
currency and a price per GB per month, and it's multiplied
against the instance's real total storage on every load. Left
unconfigured by default, since there's no sensible price to
guess at, which hides the number entirely rather than showing a
misleading zero. Storage only, no request or bandwidth cost,
since this app doesn't track either.
Activity log
An admin-only tab showing the most recent 200 events on the instance: uploads, deletes, logins, registrations, password and 2FA changes, and anything an admin changed. Each entry keeps a snapshot of the acting username, so the log stays readable even for an account since renamed or deleted.