mirror of
https://gitlab.com/famedly/conduit.git
synced 2024-12-26 20:43:48 +03:00
Merge branch '244-support-well-known' into 'next'
feat: add .well-known support Closes #244 and #378 See merge request famedly/conduit!332
This commit is contained in:
commit
0074aca0ef
15 changed files with 184 additions and 27 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -432,6 +432,8 @@ dependencies = [
|
|||
"tracing-flame",
|
||||
"tracing-opentelemetry",
|
||||
"tracing-subscriber",
|
||||
"trust-dns-resolver",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3124,6 +3126,7 @@ dependencies = [
|
|||
"form_urlencoded",
|
||||
"idna 0.5.0",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -107,6 +107,9 @@ futures-util = { version = "0.3.28", default-features = false }
|
|||
# Used for reading the configuration from conduit.toml & environment variables
|
||||
figment = { version = "0.10.8", features = ["env", "toml"] }
|
||||
|
||||
# Validating urls in config
|
||||
url = { version = "2", features = ["serde"] }
|
||||
|
||||
tikv-jemallocator = { version = "0.5.0", features = ["unprefixed_malloc_on_supported_platforms"], optional = true }
|
||||
async-trait = "0.1.68"
|
||||
|
||||
|
|
|
@ -16,3 +16,7 @@ git-repository-icon = "fa-git-square"
|
|||
|
||||
[output.html.search]
|
||||
limit-results = 15
|
||||
|
||||
[output.html.code.hidelines]
|
||||
json = "~"
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
# https://matrix.org/docs/spec/client_server/latest#get-well-known-matrix-client
|
||||
# and
|
||||
# https://matrix.org/docs/spec/server_server/r0.1.4#get-well-known-matrix-server
|
||||
# for more information
|
||||
# for more information, or continue below to see how conduit can do this for you.
|
||||
|
||||
# YOU NEED TO EDIT THIS
|
||||
#server_name = "your.server.name"
|
||||
|
@ -65,3 +65,10 @@ trusted_servers = ["matrix.org"]
|
|||
|
||||
address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy
|
||||
#address = "0.0.0.0" # If Conduit is running in a container, make sure the reverse proxy (ie. Traefik) can reach it.
|
||||
|
||||
[global.well_known]
|
||||
# Conduit handles the /.well-known/matrix/* endpoints, making both clients and servers try to access conduit with the host
|
||||
# server_name and port 443 by default.
|
||||
# If you want to override these defaults, uncomment and edit the following lines accordingly:
|
||||
#server = your.server.name:443
|
||||
#client = https://your.server.name
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
- [Introduction](introduction.md)
|
||||
|
||||
- [Configuration](configuration.md)
|
||||
- [Delegation](delegation.md)
|
||||
- [Deploying](deploying.md)
|
||||
- [Generic](deploying/generic.md)
|
||||
- [Debian](deploying/debian.md)
|
||||
|
|
|
@ -56,6 +56,7 @@ The `global` section contains the following fields:
|
|||
| `turn_secret` | `string` | The TURN secret | `""` |
|
||||
| `turn_ttl` | `integer` | The TURN TTL in seconds | `86400` |
|
||||
| `emergency_password` | `string` | Set a password to login as the `conduit` user in case of emergency | N/A |
|
||||
| `well_known` | `table` | Used for [delegation](delegation.md) | See [delegation](delegation.md) |
|
||||
|
||||
|
||||
### TLS
|
||||
|
|
69
docs/delegation.md
Normal file
69
docs/delegation.md
Normal file
|
@ -0,0 +1,69 @@
|
|||
# Delegation
|
||||
|
||||
You can run Conduit on a separate domain than the actual server name (what shows up in user ids, aliases, etc.).
|
||||
For example you can have your users have IDs such as `@foo:example.org` and have aliases like `#bar:example.org`,
|
||||
while actually having Conduit hosted on the `matrix.example.org` domain. This is called delegation.
|
||||
|
||||
## Automatic (recommended)
|
||||
|
||||
Conduit has support for hosting delegation files by itself, and by default uses it to serve federation traffic on port 443.
|
||||
|
||||
With this method, you need to direct requests to `/.well-known/matrix/*` to Conduit in your reverse proxy.
|
||||
|
||||
This is only recommended if Conduit is on the same physical server as the server which serves your server name (e.g. example.org)
|
||||
as servers don't always seem to cache the response, leading to slower response times otherwise, but it should also work if you
|
||||
are connected to the server running Conduit using something like a VPN.
|
||||
|
||||
> **Note**: this will automatically allow you to use [sliding sync][0] without any extra configuration
|
||||
|
||||
To configure it, use the following options in the `global.well_known` table:
|
||||
| Field | Type | Description | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| `client` | `String` | The URL that clients should use to connect to Conduit | `https://<server_name>` |
|
||||
| `server` | `String` | The hostname and port servers should use to connect to Conduit | `<server_name>:443` |
|
||||
|
||||
### Example
|
||||
|
||||
```toml
|
||||
[global.well_known]
|
||||
client = "https://matrix.example.org"
|
||||
server = "matrix.example.org:443"
|
||||
```
|
||||
|
||||
## Manual
|
||||
|
||||
Alternatively you can serve static JSON files to inform clients and servers how to connect to Conduit.
|
||||
|
||||
### Servers
|
||||
|
||||
For servers to discover how to access your domain, serve a response in the following format for `/.well-known/matrix/server`:
|
||||
|
||||
```json
|
||||
{
|
||||
"m.server": "matrix.example.org:443"
|
||||
}
|
||||
```
|
||||
Where `matrix.example.org` is the domain and `443` is the port Conduit is accessible at.
|
||||
|
||||
### Clients
|
||||
|
||||
For clients to discover how to access your domain, serve a response in the following format for `/.well-known/matrix/client`:
|
||||
```json
|
||||
{
|
||||
"m.homeserver": {
|
||||
"base_url": "https://matrix.example.org"
|
||||
}
|
||||
}
|
||||
```
|
||||
Where `matrix.example.org` is the URL Conduit is accessible at.
|
||||
|
||||
To ensure that all clients can access this endpoint, it is recommended you set the following headers for this endpoint:
|
||||
```
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
|
||||
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Authorization
|
||||
```
|
||||
|
||||
If you also want to be able to use [sliding sync][0], look [here](faq.md#how-do-i-setup-sliding-sync).
|
||||
|
||||
[0]: https://matrix.org/blog/2023/09/matrix-2-0/#sliding-sync
|
12
docs/faq.md
12
docs/faq.md
|
@ -15,12 +15,16 @@ You can simply stop Conduit, make a copy or file system snapshot of the database
|
|||
|
||||
## How do I setup sliding sync?
|
||||
|
||||
You need to add a `org.matrix.msc3575.proxy` field to your `.well-known/matrix/client` response which points to Conduit. Here is an example:
|
||||
If you use the [automatic method for delegation](delegation.md#automatic-recommended) or just proxy `.well-known/matrix/client` to Conduit, sliding sync should work with no extra configuration.
|
||||
If you don't, continue below.
|
||||
|
||||
You need to add a `org.matrix.msc3575.proxy` field to your `.well-known/matrix/client` response which contains a url which Conduit is accessible behind.
|
||||
Here is an example:
|
||||
```json
|
||||
{
|
||||
"m.homeserver": {
|
||||
"base_url": "https://matrix.example.org"
|
||||
},
|
||||
~ "m.homeserver": {
|
||||
~ "base_url": "https://matrix.example.org"
|
||||
~ },
|
||||
"org.matrix.msc3575.proxy": {
|
||||
"url": "https://matrix.example.org"
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ mod typing;
|
|||
mod unversioned;
|
||||
mod user_directory;
|
||||
mod voip;
|
||||
mod well_known;
|
||||
|
||||
pub use account::*;
|
||||
pub use alias::*;
|
||||
|
@ -67,6 +68,7 @@ pub use typing::*;
|
|||
pub use unversioned::*;
|
||||
pub use user_directory::*;
|
||||
pub use voip::*;
|
||||
pub use well_known::*;
|
||||
|
||||
pub const DEVICE_ID_LENGTH: usize = 10;
|
||||
pub const TOKEN_LENGTH: usize = 32;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use std::{collections::BTreeMap, iter::FromIterator};
|
||||
|
||||
use axum::{response::IntoResponse, Json};
|
||||
use ruma::api::client::{discovery::get_supported_versions, error::ErrorKind};
|
||||
use ruma::api::client::discovery::get_supported_versions;
|
||||
|
||||
use crate::{services, Error, Result, Ruma};
|
||||
use crate::{Result, Ruma};
|
||||
|
||||
/// # `GET /_matrix/client/versions`
|
||||
///
|
||||
|
@ -33,18 +32,3 @@ pub async fn get_supported_versions_route(
|
|||
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
/// # `GET /.well-known/matrix/client`
|
||||
pub async fn well_known_client_route(
|
||||
_body: Ruma<get_supported_versions::Request>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
let client_url = match services().globals.well_known_client() {
|
||||
Some(url) => url.clone(),
|
||||
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
||||
};
|
||||
|
||||
Ok(Json(serde_json::json!({
|
||||
"m.homeserver": {"base_url": client_url},
|
||||
"org.matrix.msc3575.proxy": {"url": client_url}
|
||||
})))
|
||||
}
|
||||
|
|
22
src/api/client_server/well_known.rs
Normal file
22
src/api/client_server/well_known.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use ruma::api::client::discovery::discover_homeserver::{
|
||||
self, HomeserverInfo, SlidingSyncProxyInfo,
|
||||
};
|
||||
|
||||
use crate::{services, Result, Ruma};
|
||||
|
||||
/// # `GET /.well-known/matrix/client`
|
||||
///
|
||||
/// Returns the client server discovery information.
|
||||
pub async fn well_known_client(
|
||||
_body: Ruma<discover_homeserver::Request>,
|
||||
) -> Result<discover_homeserver::Response> {
|
||||
let client_url = services().globals.well_known_client();
|
||||
|
||||
Ok(discover_homeserver::Response {
|
||||
homeserver: HomeserverInfo {
|
||||
base_url: client_url.clone(),
|
||||
},
|
||||
identity_server: None,
|
||||
sliding_sync_proxy: Some(SlidingSyncProxyInfo { url: client_url }),
|
||||
})
|
||||
}
|
|
@ -17,7 +17,10 @@ use ruma::{
|
|||
backfill::get_backfill,
|
||||
device::get_devices::{self, v1::UserDevice},
|
||||
directory::{get_public_rooms, get_public_rooms_filtered},
|
||||
discovery::{get_server_keys, get_server_version, ServerSigningKeys, VerifyKey},
|
||||
discovery::{
|
||||
discover_homeserver, get_server_keys, get_server_version, ServerSigningKeys,
|
||||
VerifyKey,
|
||||
},
|
||||
event::{get_event, get_missing_events, get_room_state, get_room_state_ids},
|
||||
keys::{claim_keys, get_keys},
|
||||
membership::{create_invite, create_join_event, prepare_join_event},
|
||||
|
@ -1911,6 +1914,17 @@ pub async fn claim_keys_route(
|
|||
})
|
||||
}
|
||||
|
||||
/// # `GET /.well-known/matrix/server`
|
||||
///
|
||||
/// Returns the federation server discovery information.
|
||||
pub async fn well_known_server(
|
||||
_body: Ruma<discover_homeserver::Request>,
|
||||
) -> Result<discover_homeserver::Response> {
|
||||
Ok(discover_homeserver::Response {
|
||||
server: services().globals.well_known_server(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{add_port_to_hostname, get_ip_with_port, FedDest};
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::{
|
|||
use ruma::{OwnedServerName, RoomVersionId};
|
||||
use serde::{de::IgnoredAny, Deserialize};
|
||||
use tracing::warn;
|
||||
use url::Url;
|
||||
|
||||
mod proxy;
|
||||
|
||||
|
@ -56,7 +57,8 @@ pub struct Config {
|
|||
pub allow_unstable_room_versions: bool,
|
||||
#[serde(default = "default_default_room_version")]
|
||||
pub default_room_version: RoomVersionId,
|
||||
pub well_known_client: Option<String>,
|
||||
#[serde(default)]
|
||||
pub well_known: WellKnownConfig,
|
||||
#[serde(default = "false_fn")]
|
||||
pub allow_jaeger: bool,
|
||||
#[serde(default = "false_fn")]
|
||||
|
@ -91,6 +93,12 @@ pub struct TlsConfig {
|
|||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Default)]
|
||||
pub struct WellKnownConfig {
|
||||
pub client: Option<Url>,
|
||||
pub server: Option<OwnedServerName>,
|
||||
}
|
||||
|
||||
const DEPRECATED_KEYS: &[&str] = &["cache_capacity"];
|
||||
|
||||
impl Config {
|
||||
|
@ -111,9 +119,35 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn well_known_client(&self) -> String {
|
||||
if let Some(url) = &self.well_known.client {
|
||||
url.to_string()
|
||||
} else {
|
||||
format!("https://{}", self.server_name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn well_known_server(&self) -> OwnedServerName {
|
||||
match &self.well_known.server {
|
||||
Some(server_name) => server_name.to_owned(),
|
||||
None => {
|
||||
if self.server_name.port().is_some() {
|
||||
self.server_name.to_owned()
|
||||
} else {
|
||||
format!("{}:443", self.server_name.host())
|
||||
.try_into()
|
||||
.expect("Host from valid hostname + :443 must be valid")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Config {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Prepare a list of config values to show
|
||||
let well_known_server = self.well_known_server();
|
||||
let lines = [
|
||||
("Server name", self.server_name.host()),
|
||||
("Database backend", &self.database_backend),
|
||||
|
@ -194,6 +228,8 @@ impl fmt::Display for Config {
|
|||
}
|
||||
&lst.join(", ")
|
||||
}),
|
||||
("Well-known server name", well_known_server.as_str()),
|
||||
("Well-known client URL", &self.well_known_client()),
|
||||
];
|
||||
|
||||
let mut msg: String = "Active config values:\n\n".to_owned();
|
||||
|
|
|
@ -390,6 +390,7 @@ fn routes(config: &Config) -> Router {
|
|||
.ruma_route(client_server::get_relating_events_with_rel_type_route)
|
||||
.ruma_route(client_server::get_relating_events_route)
|
||||
.ruma_route(client_server::get_hierarchy_route)
|
||||
.ruma_route(client_server::well_known_client)
|
||||
.route(
|
||||
"/_matrix/client/r0/rooms/:room_id/initialSync",
|
||||
get(initial_sync),
|
||||
|
@ -430,10 +431,12 @@ fn routes(config: &Config) -> Router {
|
|||
.ruma_route(server_server::get_profile_information_route)
|
||||
.ruma_route(server_server::get_keys_route)
|
||||
.ruma_route(server_server::claim_keys_route)
|
||||
.ruma_route(server_server::well_known_server)
|
||||
} else {
|
||||
router
|
||||
.route("/_matrix/federation/*path", any(federation_disabled))
|
||||
.route("/_matrix/key/*path", any(federation_disabled))
|
||||
.route("/.well-known/matrix/server", any(federation_disabled))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -417,8 +417,12 @@ impl Service {
|
|||
r
|
||||
}
|
||||
|
||||
pub fn well_known_client(&self) -> &Option<String> {
|
||||
&self.config.well_known_client
|
||||
pub fn well_known_server(&self) -> OwnedServerName {
|
||||
self.config.well_known_server()
|
||||
}
|
||||
|
||||
pub fn well_known_client(&self) -> String {
|
||||
self.config.well_known_client()
|
||||
}
|
||||
|
||||
pub fn shutdown(&self) {
|
||||
|
|
Loading…
Reference in a new issue