mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-16 15:21:24 +01:00
Reload TLS config on SIGHUP
This commit is contained in:
parent
39880cc6ac
commit
94d523ebcb
4 changed files with 78 additions and 15 deletions
|
|
@ -144,7 +144,7 @@ trust-dns-resolver = "0.23.2"
|
|||
xdg = "2.5.2"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = { version = "0.29", features = ["resource"] }
|
||||
nix = { version = "0.29", features = ["resource", "time"] }
|
||||
|
||||
[features]
|
||||
default = ["rocksdb", "sqlite", "systemd"]
|
||||
|
|
|
|||
|
|
@ -251,3 +251,6 @@ This will be the first release of Grapevine since it was forked from Conduit
|
|||
20. Include the [`traceresponse` header](https://w3c.github.io/trace-context/#traceresponse-header)
|
||||
if OpenTelemetry Tracing is in use.
|
||||
([!112](https://gitlab.computer.surgery/matrix/grapevine/-/merge_requests/112))
|
||||
21. Sending SIGHUP to the grapevine process now reloads TLS certificates from
|
||||
disk.
|
||||
([!97](https://gitlab.computer.surgery/matrix/grapevine-fork/-/merge_requests/97))
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ async fn run_server() -> Result<(), error::Serve> {
|
|||
|
||||
set_application_state(ApplicationState::Ready);
|
||||
|
||||
tokio::spawn(shutdown_signal(handles));
|
||||
tokio::spawn(handle_signals(tls_config, handles));
|
||||
|
||||
while let Some(result) = servers.join_next().await {
|
||||
let (listen, result) =
|
||||
|
|
@ -540,28 +540,72 @@ fn routes(config: &Config, components: &HashSet<ListenComponent>) -> Router {
|
|||
router.route("/", get(it_works)).fallback(not_found)
|
||||
}
|
||||
|
||||
async fn shutdown_signal(handles: Vec<ServerHandle>) {
|
||||
let ctrl_c = async {
|
||||
signal::ctrl_c().await.expect("failed to install Ctrl+C handler");
|
||||
};
|
||||
async fn reload_tls_config(
|
||||
tls_config: &RustlsConfig,
|
||||
) -> Result<(), error::Serve> {
|
||||
let config = services()
|
||||
.globals
|
||||
.config
|
||||
.tls
|
||||
.as_ref()
|
||||
.expect("TLS config should exist if TLS listener exists");
|
||||
|
||||
tls_config.reload_from_pem_file(&config.certs, &config.key).await.map_err(
|
||||
|err| error::Serve::LoadCerts {
|
||||
certs: config.certs.clone(),
|
||||
key: config.key.clone(),
|
||||
err,
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_signals(
|
||||
tls_config: Option<RustlsConfig>,
|
||||
handles: Vec<ServerHandle>,
|
||||
) {
|
||||
#[cfg(unix)]
|
||||
let terminate = async {
|
||||
signal::unix::signal(signal::unix::SignalKind::terminate())
|
||||
async fn wait_signal(sig: signal::unix::SignalKind) {
|
||||
signal::unix::signal(sig)
|
||||
.expect("failed to install signal handler")
|
||||
.recv()
|
||||
.await;
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
let terminate = || wait_signal(signal::unix::SignalKind::terminate());
|
||||
#[cfg(not(unix))]
|
||||
let terminate = || std::future::pending::<()>();
|
||||
|
||||
#[cfg(unix)]
|
||||
let sighup = || wait_signal(signal::unix::SignalKind::hangup());
|
||||
#[cfg(not(unix))]
|
||||
let sighup = || std::future::pending::<()>();
|
||||
|
||||
let ctrl_c = || async {
|
||||
signal::ctrl_c().await.expect("failed to install Ctrl+C handler");
|
||||
};
|
||||
|
||||
#[cfg(not(unix))]
|
||||
let terminate = std::future::pending::<()>();
|
||||
let sig = loop {
|
||||
tokio::select! {
|
||||
() = sighup() => {
|
||||
info!("Received reload request");
|
||||
|
||||
let sig: &str;
|
||||
set_application_state(ApplicationState::Reloading);
|
||||
|
||||
tokio::select! {
|
||||
() = ctrl_c => { sig = "Ctrl+C"; },
|
||||
() = terminate => { sig = "SIGTERM"; },
|
||||
}
|
||||
if let Some(tls_config) = tls_config.as_ref() {
|
||||
if let Err(error) = reload_tls_config(tls_config).await {
|
||||
error!(?error, "Failed to reload TLS config");
|
||||
}
|
||||
}
|
||||
|
||||
set_application_state(ApplicationState::Ready);
|
||||
},
|
||||
() = terminate() => { break "SIGTERM"; },
|
||||
() = ctrl_c() => { break "Ctrl+C"; },
|
||||
}
|
||||
};
|
||||
|
||||
warn!(signal = %sig, "Shutting down due to signal");
|
||||
|
||||
|
|
|
|||
16
src/main.rs
16
src/main.rs
|
|
@ -44,6 +44,7 @@ fn version() -> String {
|
|||
#[derive(Debug, Clone, Copy)]
|
||||
enum ApplicationState {
|
||||
Ready,
|
||||
Reloading,
|
||||
Stopping,
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +62,21 @@ fn set_application_state(state: ApplicationState) {
|
|||
|
||||
match state {
|
||||
ApplicationState::Ready => notify(&[NotifyState::Ready]),
|
||||
ApplicationState::Reloading => {
|
||||
let timespec = nix::time::clock_gettime(
|
||||
nix::time::ClockId::CLOCK_MONOTONIC,
|
||||
)
|
||||
.expect("CLOCK_MONOTONIC should be usable");
|
||||
let monotonic_usec =
|
||||
timespec.tv_sec() * 1_000_000 + timespec.tv_nsec() / 1000;
|
||||
|
||||
notify(&[
|
||||
NotifyState::Reloading,
|
||||
NotifyState::Custom(&format!(
|
||||
"MONOTONIC_USEC={monotonic_usec}",
|
||||
)),
|
||||
]);
|
||||
}
|
||||
ApplicationState::Stopping => notify(&[NotifyState::Stopping]),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue