mirror of https://github.com/mautrix/docs.git
292 lines
12 KiB
Markdown
292 lines
12 KiB
Markdown
# Direct media access (v2)
|
|
_New in version 0.7.0_
|
|
|
|
To avoid spamming your homeserver's media repository with all files from
|
|
Discord, the bridge has an option to generate fake `mxc://` URIs that contain
|
|
the Discord message ID and some other info. To make the URIs work, the bridge
|
|
effectively turns into a media-only homeserver.
|
|
|
|
For example, if your main Matrix server is `example.com`, you could set up
|
|
`discord-media.example.com` as the bridge's server name. The way to do that
|
|
is to either proxy the subdomain to the bridge entirely, or create a
|
|
`.well-known/matrix/server` file (just like normal homeserver setups) pointing
|
|
somewhere else where the bridge is listening.
|
|
|
|
When proxying the subdomain entirely, port 443 is enough, the bridge will
|
|
automatically serve a .well-known to redirect from port 8448 to 443.
|
|
|
|
Endpoints that the bridge can handle with direct media access:
|
|
|
|
* `/_matrix/media/*`
|
|
* `/_matrix/key/*`
|
|
* `/_matrix/federation/v1/version`
|
|
* `/.well-known/matrix/server`
|
|
|
|
To enable direct media access:
|
|
|
|
* Set `bridge` -> `direct_media` -> `enabled` to `true`.
|
|
* Change the `server_name` field to a (sub)domain where the aforementioned
|
|
endpoints are proxied to the bridge.
|
|
* Ensure `server_key` is set.
|
|
* The bridge generates one automatically on startup and writes it back to the
|
|
config. If you prevented the bridge from writing the config, you'll have to
|
|
set it yourself so it wouldn't generate a new one on every restart.
|
|
|
|
## Legacy direct media access
|
|
In the past, the bridge supported specifying templates that a simple reverse
|
|
proxy could parse to redirect the request to Discord's CDN. However, that
|
|
method no longer works since Discord started requiring signed URLs that expire.
|
|
|
|
<details>
|
|
<summary>Old docs</summary>
|
|
|
|
_New in version 0.4.0_
|
|
|
|
To avoid spamming your homeserver's media repository with all files from
|
|
Discord, the bridge has an option to generate fake `mxc://` URIs that contain
|
|
the Discord media ID. The media repo or your reverse proxy can then handle
|
|
those URIs specially to fetch content directly from the Discord CDN.
|
|
|
|
To enable this mode, set `bridge` -> `media_patterns` -> `enabled` to `true`
|
|
in the bridge config. You can then configure each of the patterns or leave the
|
|
defaults.
|
|
|
|
## Ways to use patterns
|
|
|
|
### Default pattern and MSC3860-compatible media repo
|
|
If your media repo supports [MSC3860], you can use the default patterns out of
|
|
the box with no modifications. Your media repo will act like discord-media.mau.dev
|
|
is a federated Matrix server, so when your client requests Discord media, your
|
|
media repo will ask discord-media.mau.dev, which redirects to cdn.discordapp.com.
|
|
Your media repo then downloads the media and caches it as remote media (like it
|
|
does for all federated media).
|
|
|
|
MSC3860 is supported as of Synapse v1.98.0 and matrix-media-repo v1.4.0.
|
|
Additionally, while Conduit doesn't opt into redirects, it does follow them,
|
|
so it should work with the default config.
|
|
|
|
The software on discord-media.mau.dev is just a Caddy instance with the first
|
|
example config below, plus a static .well-known file to redirect federation to
|
|
443. You can find the raw config at [mau.dev/maunium/caddy].
|
|
|
|
[mau.dev/maunium/caddy]: https://mau.dev/maunium/caddy/-/blob/master/vhosts/discord-media.mau.dev
|
|
[MSC3860]: https://github.com/matrix-org/matrix-spec-proposals/pull/3860
|
|
|
|
### Redirect in reverse proxy
|
|
You can also configure your reverse proxy to redirect `mxc://discord-media.mau.dev/*`
|
|
downloads directly to cdn.discordapp.com. This method doesn't involve your
|
|
media repo at all, so it already works with most clients. However, it won't
|
|
work with servers that don't support MSC3860, as they'd still try to connect to
|
|
discord-media.mau.dev, which may be a problem if you want to use your bridge in
|
|
federated rooms. Additionally, you may encounter some CORS issues with this
|
|
method as cdn.discordapp.com doesn't provide CORS headers for all files (like
|
|
webp images and non-inline documents)
|
|
|
|
<details>
|
|
<summary>Caddy config example</summary>
|
|
|
|
```Caddyfile
|
|
matrix.example.com {
|
|
handle /_matrix/media/*/download/discord-media.mau.dev/* {
|
|
# The redirect must have CORS headers to let web clients follow it.
|
|
header Access-Control-Allow-Origin *
|
|
# Need to use a route directive to make the uri mutations apply before redir
|
|
route {
|
|
# Remove path prefix
|
|
uri path_regexp ^/_matrix/media/.+/download/discord-media\.mau\.dev/ /
|
|
# The mxc patterns use | instead of /, so replace it first turning the path into attachments/1234/5678/filename.png
|
|
uri replace "%7C" /
|
|
# Then redirect to cdn.discordapp.com/attachments/1234/5678/filename.png with HTTP 307
|
|
redir https://cdn.discordapp.com{uri} 307
|
|
}
|
|
}
|
|
# Special-case stickers because they don't have CORS headers on cdn.discordapp.com for some reason
|
|
handle /_matrix/media/*/download/discord-media.mau.dev/stickers|* {
|
|
header Access-Control-Allow-Origin *
|
|
route {
|
|
uri path_regexp ^/_matrix/media/.+/download/discord-media\.mau\.dev/ /
|
|
uri replace "%7C" /
|
|
redir https://media.discordapp.net{uri} 307
|
|
}
|
|
}
|
|
# Do the same for thumbnails, but redirect to media.discordapp.net (which is Discord's thumbnailing server, and happens to use similar width/height params as Matrix)
|
|
# Alternatively, you can point this at cdn.discordapp.com too. Clients shouldn't mind even if they get a bigger image than they asked for.
|
|
handle /_matrix/media/*/thumbnail/discord-media.mau.dev/* {
|
|
header Access-Control-Allow-Origin *
|
|
route {
|
|
uri path_regexp ^/_matrix/media/.+/thumbnail/discord-media\.mau\.dev/ /
|
|
uri replace "%7C" /
|
|
redir https://media.discordapp.net{uri} 307
|
|
}
|
|
}
|
|
# The usual proxying to your homeserver
|
|
handle /_matrix/* {
|
|
reverse_proxy http://localhost:8008
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Nginx config example</summary>
|
|
|
|
```nginx
|
|
server {
|
|
listen 443;
|
|
server_name matrix.example.com;
|
|
# ... usual /_matrix location block and other stuff ...
|
|
# N.B. If you use a regex pattern for the /_matrix block, it must be below these locations
|
|
|
|
location ~ ^/_matrix/media/(?:v3|r0)/download/discord-media.mau.dev/attachments\|([0-9]+)\|([0-9]+)\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 307 https://cdn.discordapp.com/attachments/$1/$2/$3;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/download/discord-media.mau.dev/emojis\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 307 https://cdn.discordapp.com/emojis/$1;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/download/discord-media.mau.dev/stickers\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
# Stickers don't have CORS headers on cdn.discordapp.com for some reason, so always use media.
|
|
return 307 https://media.discordapp.net/stickers/$1;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/download/discord-media.mau.dev/avatars\|([0-9]+)\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 307 https://cdn.discordapp.com/avatars/$1/$2;
|
|
}
|
|
|
|
# Thumbnails (optional-ish)
|
|
location ~ ^/_matrix/media/(?:v3|r0)/thumbnail/discord-media.mau.dev/attachments\|([0-9]+)\|([0-9]+)\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 307 https://media.discordapp.net/attachments/$1/$2/$3?$args;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/thumbnail/discord-media.mau.dev/emojis\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 307 https://media.discordapp.net/emojis/$1?$args;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/thumbnail/discord-media.mau.dev/stickers\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 307 https://media.discordapp.net/stickers/$1?$args;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/thumbnail/discord-media.mau.dev/avatars\|([0-9]+)\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 307 https://media.discordapp.net/avatars/$1/$2?$args;
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
|
|
### Proxy in reverse proxy
|
|
If you want bridged media to work over federation without MSC3860, you can
|
|
change discord-media.mau.dev to your own server name, and have your reverse proxy
|
|
actually proxy the downloads instead of just redirecting to cdn.discordapp.com.
|
|
That way it'll work with all existing servers and clients. The downside of this
|
|
method is the higher bandwidth use compared to redirecting, and theoretical
|
|
abuse vectors for spamming the Discord CDN through your server.
|
|
|
|
When using this example, change `discord-media.mau.dev/` in the patterns to
|
|
`example.com/discord_` (replacing `example.com` with your own domain). The
|
|
`discord_` prefix is there so that other media on your domain will still work
|
|
normally.
|
|
|
|
<details>
|
|
<summary>Caddy config example</summary>
|
|
|
|
```Caddyfile
|
|
matrix.example.com {
|
|
handle /_matrix/media/*/download/example.com/discord_* {
|
|
header Access-Control-Allow-Origin *
|
|
# Remove path prefix
|
|
uri path_regexp ^/_matrix/media/.+/download/example\.com/discord_ /
|
|
# The mxc patterns use | instead of /, so replace it first turning it into attachments/1234/5678/filename.png
|
|
uri replace "%7C" /
|
|
reverse_proxy {
|
|
# reverse_proxy automatically includes the uri, so no {uri} at the end
|
|
to https://cdn.discordapp.com
|
|
# Caddy doesn't set the Host header automatically when reverse proxying
|
|
# (because usually reverse proxies are local and don't care about Host headers)
|
|
header_up Host cdn.discordapp.com
|
|
}
|
|
}
|
|
# Do the same for thumbnails, but redirect to media.discordapp.net (which is Discord's thumbnailing server, and happens to use similar width/height params as Matrix)
|
|
# Alternatively, you can point this at cdn.discordapp.com too. Clients shouldn't mind even if they get a bigger image than they asked for.
|
|
handle /_matrix/media/*/thumbnail/example.com/discord_* {
|
|
header Access-Control-Allow-Origin *
|
|
uri path_regexp ^/_matrix/media/.+/thumbnail/example\.com/discord_ /
|
|
uri replace "%7C" /
|
|
reverse_proxy {
|
|
to https://media.discordapp.net
|
|
header_up Host media.discordapp.net
|
|
}
|
|
}
|
|
handle /_matrix/* {
|
|
reverse_proxy http://localhost:8008
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Nginx config example</summary>
|
|
|
|
```nginx
|
|
server {
|
|
listen 443;
|
|
server_name matrix.example.com;
|
|
# ... usual /_matrix location block and other stuff ...
|
|
# N.B. If you use a regex pattern for the /_matrix block, it must be below these locations
|
|
|
|
# You may need to configure a resolver for nginx to be able to resolve cdn.discordapp.com
|
|
#resolver 8.8.8.8;
|
|
|
|
location ~ ^/_matrix/media/(?:v3|r0)/download/example.com/discord_attachments\|([0-9]+)\|([0-9]+)\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
proxy_set_header Host cdn.discordapp.com;
|
|
proxy_pass https://cdn.discordapp.com/attachments/$1/$2/$3;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/download/example.com/discord_emojis\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
proxy_set_header Host cdn.discordapp.com;
|
|
proxy_pass https://cdn.discordapp.com/emojis/$1;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/download/example.com/discord_stickers\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
proxy_set_header Host cdn.discordapp.com;
|
|
proxy_pass https://cdn.discordapp.com/stickers/$1;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/download/example.com/discord_avatars\|([0-9]+)\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
proxy_set_header Host cdn.discordapp.com;
|
|
proxy_pass https://cdn.discordapp.com/avatars/$1/$2;
|
|
}
|
|
|
|
# Thumbnails (optional-ish)
|
|
location ~ ^/_matrix/media/(?:v3|r0)/thumbnail/example.com/discord_attachments\|([0-9]+)\|([0-9]+)\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
proxy_set_header Host media.discordapp.net;
|
|
proxy_pass https://media.discordapp.net/attachments/$1/$2/$3?$args;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/thumbnail/example.com/discord_emojis\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
proxy_set_header Host media.discordapp.net;
|
|
proxy_pass https://media.discordapp.net/emojis/$1?$args;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/thumbnail/example.com/discord_stickers\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
proxy_set_header Host media.discordapp.net;
|
|
proxy_pass https://media.discordapp.net/stickers/$1?$args;
|
|
}
|
|
location ~ ^/_matrix/media/(?:v3|r0)/thumbnail/example.com/discord_avatars\|([0-9]+)\|(.+)$ {
|
|
add_header Access-Control-Allow-Origin *;
|
|
proxy_set_header Host media.discordapp.net;
|
|
proxy_pass https://media.discordapp.net/avatars/$1/$2?$args;
|
|
}
|
|
}
|
|
```
|
|
|
|
</details>
|
|
</details>
|