Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Multimedia and storage provision

Tuwunel handles media uploads, remote media fetching, thumbnail generation, URL previews, and blurhash generation. This chapter covers configuration for all of these features, as well as the storage backends that back them.

  • Storage providers — Local filesystem and S3-compatible object storage backends.

  • Media management — Commands for inspecting, deleting, and bulk-removing media, including spam response.

Upload limits

OptionDefaultDescription
max_request_size24 MiBMaximum size of a single media upload. Accepts SI/IEC units, e.g. "50 MiB".
max_pending_media_uploads5Maximum number of in-progress asynchronous uploads a single user can have at once.
media_create_unused_expiration_time86400Seconds before an unused pending MXC URI is expired and removed (default: 24 hours).
media_rc_create_per_second10Maximum media-create requests per second from a single user before rate limiting applies.
media_rc_create_burst_count50Maximum burst size for media-create rate limiting per user.

Legacy media endpoints

Matrix spec version 1.11 introduced authenticated media endpoints. The older unauthenticated endpoints are deprecated but some clients and servers still use them.

OptionDefaultDescription
allow_legacy_mediafalseServe the unauthenticated /_matrix/media/*/ endpoints locally. The authenticated equivalents are always enabled.
request_legacy_mediafalseFall back to unauthenticated requests when fetching media from remote servers. Unauthenticated remote media was removed around 2024Q3; enabling this adds federation traffic that is unlikely to succeed.

Blocking remote media

prevent_media_downloads_from is a list of regex patterns matched against server names. Tuwunel refuses to download media originating from any matching server.

prevent_media_downloads_from = [
  "badserver\\.tld$",
  "spammy-phrase",
]

This is useful as a reactive measure after a spam incident. See the Management page for bulk-deletion commands to pair with it.

URL previews

URL previews are disabled unless at least one allowlist is configured. All allowlist checks are evaluated before the denylist check.

OptionDefaultDescription
url_preview_domain_explicit_allowlist[]Exact domain matches allowed for previewing. "google.com" matches https://google.com but not https://subdomain.google.com. Set to ["*"] to allow all domains.
url_preview_domain_contains_allowlist[]Substring domain matches. "google.com" matches any URL whose domain contains that string — including unrelated domains. Set to ["*"] to allow all domains.
url_preview_url_contains_allowlist[]Substring match against the full URL (not just the domain). Set to ["*"] to allow all URLs.
url_preview_domain_explicit_denylist[]Exact domain matches explicitly blocked. The denylist is checked first. Setting to ["*"] has no effect.
url_preview_check_root_domainfalseWhen enabled, domain allowlist checks are applied to the root domain. Allows all subdomains of any allowed domain — e.g. allowing wikipedia.org also allows en.m.wikipedia.org.
url_preview_max_spider_size256000Maximum bytes fetched from a URL when generating a preview (default: 256 KB).
url_preview_max_media_size52428800Maximum size of a single media item fetched or relayed for a URL preview: the og:image measurement fetch and the lazy-media relay. Media larger than this is not registered, and an over-cap relay is refused (default: 50 MiB).
url_preview_bound_interfaceNetwork interface name or IP address to bind when making URL preview requests. Example: "eth0" or "1.2.3.4".
url_preview_user_agentUser-Agent header sent when fetching pages to extract their OpenGraph tags. Defaults to the versioned server User-Agent, e.g. "Tuwunel/1.8.1 preview".
url_preview_media_user_agentUser-Agent header sent when fetching and relaying preview media files themselves. Falls back to url_preview_user_agent.

Note

Setting any allowlist to ["*"] opens significant attack surface — a malicious client could cause the server to make requests to arbitrary URLs on the local network. Use explicit allowlists wherever possible.

og:image, og:video, and og:audio (and direct links to image, video, and audio files) resolve to an mxc:// URI on this server rather than the third-party URL, and none of the content is stored: requests for that mxc:// URI are relayed — the server fetches the source URL on the client’s behalf (subject to the same SSRF/CIDR checks as everything else on this page, and capped at max_response_size) and passes the content through, so the third party sees the server’s address rather than the client’s, and the server hosts nothing. Images are additionally downloaded once while generating the preview to measure og:image:width/og:image:height and matrix:image:size, then discarded. og:video:width/og:video:height are populated when the page declares them. Clients cache the results themselves per the immutable cache headers on media downloads. Because nothing is stored, a preview’s mxc:// URI is only as durable as its source URL: if the source expires or changes, later fetches reflect that, unlike uploaded media. Upstream error responses are never relayed as media.

Blurhash

Tuwunel can generate blurhashes for uploaded images, which clients use to show a blurred placeholder before the full image loads. This requires the blurhashing compile-time feature.

Blurhash settings live in a dedicated config section:

[global.blurhashing]
components_x = 4
components_y = 3
blurhash_max_raw_size = 33554432
OptionDefaultDescription
components_x4Horizontal detail components. Higher values produce more detailed hashes at the cost of a larger hash string.
components_y3Vertical detail components.
blurhash_max_raw_size33554432Maximum raw image size (after decoding to pixel data) that will be blurhashed, in bytes (default: ~32 MiB). Set to 0 to disable blurhashing entirely. Should be at or above max_request_size to avoid silently skipping large uploads.