Compare commits

...

8 Commits

Author SHA1 Message Date
Charles Hall 2993097715 Merge branch 'refactor-main' into 'next'
return ExitCode instead of using panic or exit

See merge request famedly/conduit!639
2 weeks ago
Matthias Ahouansou cd4e4fe7ac Merge branch 'Daniel15au-next-patch-38459' into 'next'
[docs] Remove references to legacy Docker Compose v1

See merge request famedly/conduit!642
2 weeks ago
Matthias Ahouansou 0a7ac058a0 Merge branch 'docs-migrate-faq-fix' into 'next'
docs(faq): correct answer about migration

See merge request famedly/conduit!654
2 weeks ago
Daniel Lo Nigro c90e4816b7
[docs] Update docker-compose commands 2 weeks ago
Matthias Ahouansou 2b5295aa29
docs(faq): correct answer about migration 2 weeks ago
Charles Hall 10e3adc83c
return a concrete error type from `try_main`
Also adds a utility for printing out an error message in addition to all
of its sources, i.e. errors that came before it that led to the current
error.

This helps us to provide better error messages to users by including
more information: both our own error message and all of the underlying
error messages, if any, instead of only one or the other.
3 weeks ago
Charles Hall 630a53934a
reword error message about `CONDUIT_CONFIG`
The new message more accurately reflects the purpose and behaviors of
the environment variable.
3 weeks ago
Charles Hall 90f9681d90
return ExitCode instead of using panic or exit
`panic!()` (and things that invoke it, such as `expect` and `unwrap`)
produces terrible looking error messages and `std::process::exit()`
doesn't run destructors. Instead, we'll make a `try_main` that can
return a `Result` with a structured error type, but for now I'm going to
be lazy and just use `Box<dyn Error>`. Then, `main` will call it and
return the appropriate `ExitCode` value based on `try_main`'s `Result`.
This gives us the opportunity to produce good error messages and doesn't
violently terminate the program.
3 weeks ago

@ -7,8 +7,8 @@ services:
### then you are ready to go.
image: matrixconduit/matrix-conduit:latest
### If you want to build a fresh image from the sources, then comment the image line and uncomment the
### build lines. If you want meaningful labels in your built Conduit image, you should run docker-compose like this:
### CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml) docker-compose up -d
### build lines. If you want meaningful labels in your built Conduit image, you should run docker compose like this:
### CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml) docker compose up -d
# build:
# context: .
# args:
@ -38,7 +38,7 @@ services:
# We need some way to server the client and server .well-known json. The simplest way is to use a nginx container
# to serve those two as static files. If you want to use a different way, delete or comment the below service, here
# and in the docker-compose override file.
# and in the docker compose override file.
well-known:
image: nginx:latest
restart: unless-stopped

@ -18,7 +18,7 @@ services:
# We need some way to server the client and server .well-known json. The simplest way is to use a nginx container
# to serve those two as static files. If you want to use a different way, delete or comment the below service, here
# and in the docker-compose file.
# and in the docker compose file.
well-known:
labels:
- "traefik.enable=true"

@ -7,8 +7,8 @@ services:
### then you are ready to go.
image: matrixconduit/matrix-conduit:latest
### If you want to build a fresh image from the sources, then comment the image line and uncomment the
### build lines. If you want meaningful labels in your built Conduit image, you should run docker-compose like this:
### CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml) docker-compose up -d
### build lines. If you want meaningful labels in your built Conduit image, you should run docker compose like this:
### CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml) docker compose up -d
# build:
# context: .
# args:
@ -42,7 +42,7 @@ services:
# We need some way to server the client and server .well-known json. The simplest way is to use a nginx container
# to serve those two as static files. If you want to use a different way, delete or comment the below service, here
# and in the docker-compose override file.
# and in the docker compose override file.
well-known:
image: nginx:latest
restart: unless-stopped

@ -7,8 +7,8 @@ services:
### then you are ready to go.
image: matrixconduit/matrix-conduit:latest
### If you want to build a fresh image from the sources, then comment the image line and uncomment the
### build lines. If you want meaningful labels in your built Conduit image, you should run docker-compose like this:
### CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml) docker-compose up -d
### build lines. If you want meaningful labels in your built Conduit image, you should run docker compose like this:
### CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml) docker compose up -d
# build:
# context: .
# args:

@ -67,7 +67,7 @@ docker run -d -p 8448:6167 \
--name conduit <link>
```
or you can use [docker-compose](#docker-compose).
or you can use [docker compose](#docker-compose).
The `-d` flag lets the container run in detached mode. You now need to supply a `conduit.toml` config file, an example can be found [here](../configuration.md).
You can pass in different env vars to change config values on the fly. You can even configure Conduit completely by using env vars, but for that you need
@ -75,9 +75,9 @@ to pass `-e CONDUIT_CONFIG=""` into your container. For an overview of possible
If you just want to test Conduit for a short time, you can use the `--rm` flag, which will clean up everything related to your container after you stop it.
### Docker-compose
### Docker compose
If the `docker run` command is not for you or your setup, you can also use one of the provided `docker-compose` files.
If the `docker run` command is not for you or your setup, you can also use one of the provided `docker compose` files.
Depending on your proxy setup, you can use one of the following files;
- If you already have a `traefik` instance set up, use [`docker-compose.for-traefik.yml`](docker-compose.for-traefik.yml)
@ -91,10 +91,10 @@ Additional info about deploying Conduit can be found [here](generic.md).
### Build
To build the Conduit image with docker-compose, you first need to open and modify the `docker-compose.yml` file. There you need to comment the `image:` option and uncomment the `build:` option. Then call docker-compose with:
To build the Conduit image with docker compose, you first need to open and modify the `docker-compose.yml` file. There you need to comment the `image:` option and uncomment the `build:` option. Then call docker compose with:
```bash
docker-compose up
docker compose up
```
This will also start the container right afterwards, so if want it to run in detached mode, you also should use the `-d` flag.
@ -104,7 +104,7 @@ This will also start the container right afterwards, so if want it to run in det
If you already have built the image or want to use one from the registries, you can just start the container and everything else in the compose file in detached mode with:
```bash
docker-compose up -d
docker compose up -d
```
> **Note:** Don't forget to modify and adjust the compose file to your needs.
@ -157,7 +157,7 @@ So...step by step:
}
```
6. Run `docker-compose up -d`
6. Run `docker compose up -d`
7. Connect to your homeserver with your preferred client and create a user. You should do this immediately after starting Conduit, because the first created user is the admin.
@ -196,8 +196,8 @@ Run the [Coturn](https://hub.docker.com/r/coturn/coturn) image using
docker run -d --network=host -v $(pwd)/coturn.conf:/etc/coturn/turnserver.conf coturn/coturn
```
or docker-compose. For the latter, paste the following section into a file called `docker-compose.yml`
and run `docker-compose up -d` in the same directory.
or docker compose. For the latter, paste the following section into a file called `docker-compose.yml`
and run `docker compose up -d` in the same directory.
```yml
version: 3

@ -22,4 +22,5 @@ You need to add a `org.matrix.msc3575.proxy` field to your `.well-known/matrix/c
## Can I migrate from Synapse to Conduit?
Not really. You can reuse the domain of your current server with Conduit, but you have to leave all federated rooms first.
Not really. You can reuse the domain of your current server with Conduit, but you will not be able to migrate accounts automatically.
Rooms that were federated can be re-joined via the other participating servers, however media and the like may be deleted from remote servers after some time, and hence might not be recoverable.

@ -0,0 +1,64 @@
//! Error handling facilities
use std::{fmt, iter};
use thiserror::Error;
/// Wraps any [`Error`][e] type so that [`Display`][d] includes its [sources][s]
///
/// [e]: std::error::Error
/// [d]: fmt::Display
/// [s]: std::error::Error::source
pub struct Chain<'a>(pub &'a dyn std::error::Error);
impl fmt::Display for Chain<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)?;
let mut source = self.0.source();
source
.into_iter()
.chain(iter::from_fn(|| {
source = source.and_then(std::error::Error::source);
source
}))
.try_for_each(|source| write!(f, ": {source}"))
}
}
/// Top-level errors
// Missing docs are allowed here since that kind of information should be
// encoded in the error messages themselves anyway.
#[allow(missing_docs)]
#[derive(Error, Debug)]
pub enum Main {
#[error(
"the `CONDUIT_CONFIG` environment variable must either be set to a configuration file path \
or set to the empty string to force configuration through environment variables"
)]
ConfigPathUnset,
#[error("invalid configuration")]
ConfigInvalid(#[from] figment::Error),
// Upstream's documentation on what this error means is very sparse
#[error("opentelemetry error")]
Otel(#[from] opentelemetry::trace::TraceError),
#[error("invalid log filter syntax")]
EnvFilter(#[from] tracing_subscriber::filter::ParseError),
#[error("failed to install global default tracing subscriber")]
SetSubscriber(#[from] tracing::subscriber::SetGlobalDefaultError),
// Upstream's documentation on what this error means is very sparse
#[error("tracing_flame error")]
TracingFlame(#[from] tracing_flame::Error),
#[error("failed to load or create the database")]
DatabaseError(#[source] crate::utils::error::Error),
#[error("failed to serve requests")]
Serve(#[source] std::io::Error),
}

@ -2,6 +2,7 @@ pub mod api;
pub mod clap;
mod config;
mod database;
pub mod error;
mod service;
mod utils;

@ -1,4 +1,4 @@
use std::{future::Future, io, net::SocketAddr, sync::atomic, time::Duration};
use std::{future::Future, io, net::SocketAddr, process::ExitCode, sync::atomic, time::Duration};
use axum::{
extract::{DefaultBodyLimit, FromRequestParts, MatchedPath},
@ -30,7 +30,7 @@ use tower_http::{
trace::TraceLayer,
ServiceBuilderExt as _,
};
use tracing::{debug, error, info, warn};
use tracing::{debug, info, warn};
use tracing_subscriber::{prelude::*, EnvFilter};
pub use conduit::*; // Re-export everything from the library crate
@ -43,27 +43,28 @@ use tikv_jemallocator::Jemalloc;
static GLOBAL: Jemalloc = Jemalloc;
#[tokio::main]
async fn main() {
async fn main() -> ExitCode {
let Err(e) = try_main().await else {
return ExitCode::SUCCESS;
};
eprintln!("error: {}", error::Chain(&e));
ExitCode::FAILURE
}
/// Fallible entrypoint
async fn try_main() -> Result<(), error::Main> {
use error::Main as Error;
clap::parse();
// Initialize config
let raw_config =
Figment::new()
.merge(
Toml::file(Env::var("CONDUIT_CONFIG").expect(
"The CONDUIT_CONFIG env var needs to be set. Example: /etc/conduit.toml",
))
.nested(),
)
.merge(Env::prefixed("CONDUIT_").global());
let raw_config = Figment::new()
.merge(Toml::file(Env::var("CONDUIT_CONFIG").ok_or(Error::ConfigPathUnset)?).nested())
.merge(Env::prefixed("CONDUIT_").global());
let config = match raw_config.extract::<Config>() {
Ok(s) => s,
Err(e) => {
eprintln!("It looks like your config is invalid. The following error occurred: {e}");
std::process::exit(1);
}
};
let config = raw_config.extract::<Config>()?;
config.warn_deprecated();
@ -72,47 +73,31 @@ async fn main() {
let tracer = opentelemetry_jaeger::new_agent_pipeline()
.with_auto_split_batch(true)
.with_service_name("conduit")
.install_batch(opentelemetry::runtime::Tokio)
.unwrap();
.install_batch(opentelemetry::runtime::Tokio)?;
let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
let filter_layer = match EnvFilter::try_new(&config.log) {
Ok(s) => s,
Err(e) => {
eprintln!(
"It looks like your log config is invalid. The following error occurred: {e}"
);
EnvFilter::try_new("warn").unwrap()
}
};
let filter_layer = EnvFilter::try_new(&config.log)?;
let subscriber = tracing_subscriber::Registry::default()
.with(filter_layer)
.with(telemetry);
tracing::subscriber::set_global_default(subscriber).unwrap();
tracing::subscriber::set_global_default(subscriber)?;
} else if config.tracing_flame {
let registry = tracing_subscriber::Registry::default();
let (flame_layer, _guard) =
tracing_flame::FlameLayer::with_file("./tracing.folded").unwrap();
let (flame_layer, _guard) = tracing_flame::FlameLayer::with_file("./tracing.folded")?;
let flame_layer = flame_layer.with_empty_samples(false);
let filter_layer = EnvFilter::new("trace,h2=off");
let subscriber = registry.with(filter_layer).with(flame_layer);
tracing::subscriber::set_global_default(subscriber).unwrap();
tracing::subscriber::set_global_default(subscriber)?;
} else {
let registry = tracing_subscriber::Registry::default();
let fmt_layer = tracing_subscriber::fmt::Layer::new();
let filter_layer = match EnvFilter::try_new(&config.log) {
Ok(s) => s,
Err(e) => {
eprintln!("It looks like your config is invalid. The following error occured while parsing it: {e}");
EnvFilter::try_new("warn").unwrap()
}
};
let filter_layer = EnvFilter::try_new(&config.log)?;
let subscriber = registry.with(filter_layer).with(fmt_layer);
tracing::subscriber::set_global_default(subscriber).unwrap();
tracing::subscriber::set_global_default(subscriber)?;
}
// This is needed for opening lots of file descriptors, which tends to
@ -126,19 +111,19 @@ async fn main() {
maximize_fd_limit().expect("should be able to increase the soft limit to the hard limit");
info!("Loading database");
if let Err(error) = KeyValueDatabase::load_or_create(config).await {
error!(?error, "The database couldn't be loaded or created");
std::process::exit(1);
};
KeyValueDatabase::load_or_create(config)
.await
.map_err(Error::DatabaseError)?;
let config = &services().globals.config;
info!("Starting server");
run_server().await.unwrap();
run_server().await.map_err(Error::Serve)?;
if config.allow_jaeger {
opentelemetry::global::shutdown_tracer_provider();
}
Ok(())
}
async fn run_server() -> io::Result<()> {

Loading…
Cancel
Save