mirror of
https://github.com/mikedilger/chorus.git
synced 2026-05-03 06:51:42 +00:00
Reload config on HUP signal; change and synchronize default config
This commit is contained in:
parent
a701da6dda
commit
54bb5450f6
@ -6,9 +6,10 @@ use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::OnceLock;
|
||||
use tokio::sync::broadcast::Sender as BroadcastSender;
|
||||
use tokio::sync::watch::Sender as WatchSender;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
pub struct Globals {
|
||||
pub config: OnceLock<Config>,
|
||||
pub config: RwLock<Config>,
|
||||
pub store: OnceLock<Store>,
|
||||
pub http_server: Http,
|
||||
pub rid: OnceLock<String>,
|
||||
@ -33,7 +34,7 @@ lazy_static! {
|
||||
let (shutting_down, _) = tokio::sync::watch::channel(false);
|
||||
|
||||
Globals {
|
||||
config: OnceLock::new(),
|
||||
config: RwLock::new(Default::default()),
|
||||
store: OnceLock::new(),
|
||||
http_server,
|
||||
rid: OnceLock::new(),
|
||||
|
||||
@ -45,7 +45,7 @@ async fn main() -> Result<(), Error> {
|
||||
let config_path = args.next().unwrap();
|
||||
|
||||
// Read config file
|
||||
let mut file = OpenOptions::new().read(true).open(config_path)?;
|
||||
let mut file = OpenOptions::new().read(true).open(config_path.clone())?;
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents)?;
|
||||
let friendly_config: FriendlyConfig = toml::from_str(&contents)?;
|
||||
@ -80,11 +80,12 @@ async fn main() -> Result<(), Error> {
|
||||
log::info!(target: "Server", "Running on {}:{}", config.ip_address, config.port);
|
||||
|
||||
// Store config into GLOBALS
|
||||
let _ = GLOBALS.config.set(config);
|
||||
*GLOBALS.config.write().await = config;
|
||||
|
||||
let mut interrupt_signal = signal(SignalKind::interrupt())?;
|
||||
let mut quit_signal = signal(SignalKind::quit())?;
|
||||
let mut terminate_signal = signal(SignalKind::terminate())?;
|
||||
let mut hup_signal = signal(SignalKind::hangup())?;
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
@ -102,6 +103,20 @@ async fn main() -> Result<(), Error> {
|
||||
break;
|
||||
},
|
||||
|
||||
// Reload config on HUP
|
||||
v = hup_signal.recv() => if v.is_some() {
|
||||
log::info!(target: "Server", "SIGHUP: Reloading configuration");
|
||||
|
||||
// Reload the config file
|
||||
let mut file = OpenOptions::new().read(true).open(config_path.clone())?;
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents)?;
|
||||
let friendly_config: FriendlyConfig = toml::from_str(&contents)?;
|
||||
let config: Config = friendly_config.into_config()?;
|
||||
|
||||
*GLOBALS.config.write().await = config;
|
||||
},
|
||||
|
||||
// Accepts network connections and spawn a task to serve each one
|
||||
v = listener.accept() => {
|
||||
let (tcp_stream, peer_addr) = v?;
|
||||
|
||||
@ -82,7 +82,7 @@ impl WebSocketService {
|
||||
if let Err(e) = self.req_inner(&subid, filters).await {
|
||||
let reply = match e.inner {
|
||||
ChorusError::TooManySubscriptions => {
|
||||
let max_subscriptions = GLOBALS.config.get().unwrap().max_subscriptions;
|
||||
let max_subscriptions = GLOBALS.config.read().await.max_subscriptions;
|
||||
NostrReply::Closed(
|
||||
&subid,
|
||||
NostrReplyPrefix::Blocked,
|
||||
@ -105,7 +105,7 @@ impl WebSocketService {
|
||||
}
|
||||
|
||||
async fn req_inner(&mut self, subid: &String, filters: Vec<OwnedFilter>) -> Result<(), Error> {
|
||||
let max_subscriptions = GLOBALS.config.get().unwrap().max_subscriptions;
|
||||
let max_subscriptions = GLOBALS.config.read().await.max_subscriptions;
|
||||
if self.subscriptions.len() >= max_subscriptions {
|
||||
return Err(ChorusError::TooManySubscriptions.into());
|
||||
}
|
||||
@ -233,8 +233,7 @@ impl WebSocketService {
|
||||
|
||||
let event_flags = event_flags(&event, &user);
|
||||
|
||||
if !event_flags.author_is_an_authorized_user || GLOBALS.config.get().unwrap().verify_events
|
||||
{
|
||||
if !event_flags.author_is_an_authorized_user || GLOBALS.config.read().await.verify_events {
|
||||
// Verify the event is valid (id is hash, signature is valid)
|
||||
if let Err(e) = event.verify() {
|
||||
return Err(ChorusError::EventIsInvalid(format!("{}", e)).into());
|
||||
@ -345,7 +344,7 @@ impl WebSocketService {
|
||||
};
|
||||
if let Some(h) = url.host() {
|
||||
let theirhost = h.to_owned();
|
||||
if theirhost == GLOBALS.config.get().unwrap().hostname {
|
||||
if theirhost == GLOBALS.config.read().await.hostname {
|
||||
relay_ok = true;
|
||||
}
|
||||
}
|
||||
@ -402,7 +401,7 @@ async fn screen_incoming_event(
|
||||
}
|
||||
|
||||
// Accept if an open relay
|
||||
if GLOBALS.config.get().unwrap().open_relay {
|
||||
if GLOBALS.config.read().await.open_relay {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
@ -412,20 +411,20 @@ async fn screen_incoming_event(
|
||||
}
|
||||
|
||||
// Accept relay lists from anybody
|
||||
if event.kind() == Kind(10002) && GLOBALS.config.get().unwrap().serve_relay_lists {
|
||||
if event.kind() == Kind(10002) && GLOBALS.config.read().await.serve_relay_lists {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// Allow if event kind ephemeral
|
||||
if event.kind().is_ephemeral() && GLOBALS.config.get().unwrap().serve_ephemeral {
|
||||
if event.kind().is_ephemeral() && GLOBALS.config.read().await.serve_ephemeral {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// If the author is one of our users, always accept it
|
||||
if GLOBALS
|
||||
.config
|
||||
.get()
|
||||
.unwrap()
|
||||
.read()
|
||||
.await
|
||||
.user_keys
|
||||
.contains(&event.pubkey())
|
||||
{
|
||||
@ -436,7 +435,7 @@ async fn screen_incoming_event(
|
||||
for mut tag in event.tags()?.iter() {
|
||||
if tag.next() == Some(b"p") {
|
||||
if let Some(value) = tag.next() {
|
||||
for ukhex in &GLOBALS.config.get().unwrap().user_hex_keys {
|
||||
for ukhex in &GLOBALS.config.read().await.user_hex_keys {
|
||||
if value == ukhex.as_bytes() {
|
||||
return Ok(true);
|
||||
}
|
||||
@ -460,17 +459,17 @@ pub fn screen_outgoing_event(
|
||||
}
|
||||
|
||||
// Allow if an open relay
|
||||
if GLOBALS.config.get().unwrap().open_relay {
|
||||
if GLOBALS.config.blocking_read().open_relay {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow Relay Lists
|
||||
if event.kind() == Kind(10002) && GLOBALS.config.get().unwrap().serve_relay_lists {
|
||||
if event.kind() == Kind(10002) && GLOBALS.config.blocking_read().serve_relay_lists {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow if event kind ephemeral
|
||||
if event.kind().is_ephemeral() && GLOBALS.config.get().unwrap().serve_ephemeral {
|
||||
if event.kind().is_ephemeral() && GLOBALS.config.blocking_read().serve_ephemeral {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -491,7 +490,7 @@ pub fn screen_outgoing_event(
|
||||
pub async fn authorized_user(user: &Option<Pubkey>) -> bool {
|
||||
match user {
|
||||
None => false,
|
||||
Some(pk) => GLOBALS.config.get().unwrap().user_keys.contains(pk),
|
||||
Some(pk) => GLOBALS.config.read().await.user_keys.contains(pk),
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,8 +504,7 @@ pub struct EventFlags {
|
||||
pub fn event_flags(event: &Event<'_>, user: &Option<Pubkey>) -> EventFlags {
|
||||
let author_is_an_authorized_user = GLOBALS
|
||||
.config
|
||||
.get()
|
||||
.unwrap()
|
||||
.blocking_read()
|
||||
.user_keys
|
||||
.contains(&event.pubkey());
|
||||
|
||||
@ -529,7 +527,12 @@ pub fn event_flags(event: &Event<'_>, user: &Option<Pubkey>) -> EventFlags {
|
||||
}
|
||||
}
|
||||
|
||||
if GLOBALS.config.get().unwrap().user_keys.contains(&tagged_pk) {
|
||||
if GLOBALS
|
||||
.config
|
||||
.blocking_read()
|
||||
.user_keys
|
||||
.contains(&tagged_pk)
|
||||
{
|
||||
tags_an_authorized_user = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ pub async fn serve_http(peer: SocketAddr, request: Request<Body>) -> Result<Resp
|
||||
pub async fn serve_nip11(peer: SocketAddr) -> Result<Response<Body>, Error> {
|
||||
log::debug!(target: "Client", "{}: sent NIP-11", peer);
|
||||
let rid = {
|
||||
let config = GLOBALS.config.get().unwrap();
|
||||
let config = &*GLOBALS.config.read().await;
|
||||
GLOBALS.rid.get_or_init(|| build_rid(config))
|
||||
};
|
||||
|
||||
|
||||
@ -35,15 +35,15 @@ pub struct FriendlyConfig {
|
||||
impl Default for FriendlyConfig {
|
||||
fn default() -> FriendlyConfig {
|
||||
FriendlyConfig {
|
||||
data_directory: "/tmp".to_string(),
|
||||
data_directory: "/opt/chorus/var/chorus".to_string(),
|
||||
ip_address: "127.0.0.1".to_string(),
|
||||
port: 80,
|
||||
port: 443,
|
||||
hostname: "localhost".to_string(),
|
||||
use_tls: false,
|
||||
certchain_pem_path: "./tls/fullchain.pem".to_string(),
|
||||
key_pem_path: "./tls/privkey.pem".to_string(),
|
||||
name: None,
|
||||
description: None,
|
||||
use_tls: true,
|
||||
certchain_pem_path: "/opt/chorus/etc/tls/fullchain.pem".to_string(),
|
||||
key_pem_path: "/opt/chorus/etc/tls/privkey.pem".to_string(),
|
||||
name: Some("Chorus Default".to_string()),
|
||||
description: Some("A default config of the Chorus relay".to_string()),
|
||||
contact: None,
|
||||
public_key_hex: None,
|
||||
open_relay: false,
|
||||
@ -56,8 +56,8 @@ impl Default for FriendlyConfig {
|
||||
serve_ephemeral: true,
|
||||
serve_relay_lists: true,
|
||||
server_log_level: "Info".to_string(),
|
||||
library_log_level: "Warn".to_string(),
|
||||
client_log_level: "Error".to_string(),
|
||||
library_log_level: "Info".to_string(),
|
||||
client_log_level: "Info".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,9 +103,9 @@ impl FriendlyConfig {
|
||||
let hostname = Host::parse(&hostname)?;
|
||||
|
||||
let server_log_level =
|
||||
log::LevelFilter::from_str(&server_log_level).unwrap_or(log::LevelFilter::Error);
|
||||
log::LevelFilter::from_str(&server_log_level).unwrap_or(log::LevelFilter::Info);
|
||||
let library_log_level =
|
||||
log::LevelFilter::from_str(&library_log_level).unwrap_or(log::LevelFilter::Warn);
|
||||
log::LevelFilter::from_str(&library_log_level).unwrap_or(log::LevelFilter::Info);
|
||||
let client_log_level =
|
||||
log::LevelFilter::from_str(&client_log_level).unwrap_or(log::LevelFilter::Info);
|
||||
|
||||
@ -165,3 +165,12 @@ pub struct Config {
|
||||
pub library_log_level: log::LevelFilter,
|
||||
pub client_log_level: log::LevelFilter,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Config {
|
||||
let friendly = FriendlyConfig::default();
|
||||
|
||||
// We know the default config passes into_config without error:
|
||||
friendly.into_config().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,16 +67,16 @@ certchain_pem_path = "/opt/chorus/etc/tls/fullchain.pem"
|
||||
key_pem_path = "/opt/chorus/etc/tls/privkey.pem"
|
||||
|
||||
|
||||
# This is an optional name for your relay, displayed in the NIP-11 response.
|
||||
# This is a name for your relay, displayed in the NIP-11 response.
|
||||
#
|
||||
# Default is not set
|
||||
# Default is "Chorus Default"
|
||||
#
|
||||
# name = "Chorus Default"
|
||||
|
||||
|
||||
# This is an optional description for your relay, displayed in the NIP-11 response.
|
||||
# This is a description for your relay, displayed in the NIP-11 response.
|
||||
#
|
||||
# Default is not set
|
||||
# Default is "A default config of the Chorus relay"
|
||||
#
|
||||
# description = "A default config of the Chorus relay"
|
||||
|
||||
@ -203,15 +203,15 @@ server_log_level = "Info"
|
||||
#
|
||||
# Possible values are: Trace, Debug, Info, Warn, Error
|
||||
#
|
||||
# Default is Warn
|
||||
# Default is Info
|
||||
#
|
||||
library_log_level = "Warn"
|
||||
library_log_level = "Info"
|
||||
|
||||
|
||||
# How verbose to log issues with client requests
|
||||
#
|
||||
# Possible values are: Trace, Debug, Info, Warn, Error
|
||||
#
|
||||
# Default is Error
|
||||
# Default is Info
|
||||
#
|
||||
client_log_level = "Error"
|
||||
client_log_level = "Info"
|
||||
|
||||
@ -10,7 +10,7 @@ The config file must be in TOML format. See the [TOML documentation](https://git
|
||||
|
||||
This is the directory where chorus stores data.
|
||||
|
||||
Default is "/tmp".
|
||||
Default is "/opt/chorus/var/chorus".
|
||||
|
||||
If deployed according to [docs/DEPLOYING.md](docs/DEPLOYING.md), is "/opt/chorus/var/chorus".
|
||||
|
||||
@ -34,6 +34,8 @@ Default is 443.
|
||||
This is the DNS hostname of your relay. This is used for verifying AUTH events, which specify
|
||||
your relay host name.
|
||||
|
||||
Default is localhost
|
||||
|
||||
### use_tls
|
||||
|
||||
If true, chorus will handle TLS, running over HTTPS. If false, chorus run over HTTP.
|
||||
@ -41,17 +43,18 @@ If true, chorus will handle TLS, running over HTTPS. If false, chorus run over
|
||||
If you are proxying via nginx, normally you will set this to false and allow nginx to handle
|
||||
TLS.
|
||||
|
||||
Default is true
|
||||
|
||||
### certchain_pem_path
|
||||
|
||||
This is the path to your TLS certificate chain file.
|
||||
|
||||
If `use_tls` is false, this value is irrelevant.
|
||||
|
||||
Default is "./tls/fullchain.pem".
|
||||
Default is "/opt/chorus/etc/tls/fullchain.pem"
|
||||
|
||||
If deployed according to [docs/DEPLOYING.md](docs/DEPLOYING.md) using the direct method,
|
||||
this is set to "/opt/chorus/etc/tls/fullchain.pem" and the systemd service copies letsencrypt
|
||||
TLS certificates into this position on start.
|
||||
systemd service copies letsencrypt TLS certificates into this position on start.
|
||||
|
||||
### key_pem_path
|
||||
|
||||
@ -59,23 +62,22 @@ This is the path to yoru TLS private key file.
|
||||
|
||||
If `use_tls` is false, this value is irrelevant.
|
||||
|
||||
Default is "./tls/privkey.pem".
|
||||
Default is "/opt/chorus/etc/tls/privkey.pem"
|
||||
|
||||
If deployed according to [docs/DEPLOYING.md](docs/DEPLOYING.md) using the direct method,
|
||||
this is set to "/opt/chorus/etc/tls/privkey.pem" and the systemd service copies letsencrypt
|
||||
TLS certificates into this position on start.
|
||||
systemd service copies letsencrypt TLS certificates into this position on start.
|
||||
|
||||
### name
|
||||
|
||||
This is an optional name for your relay, displayed in the NIP-11 response.
|
||||
|
||||
Default is None.
|
||||
Default is "Chorus Default"
|
||||
|
||||
### description
|
||||
|
||||
This is an optional description for your relay, displayed in the NIP-11 response.
|
||||
|
||||
Default is None.
|
||||
Default is "A default config of the Chorus relay".
|
||||
|
||||
### contact
|
||||
|
||||
@ -177,7 +179,7 @@ How verbose to log library issues and other general issues
|
||||
|
||||
Possible values are: Trace, Debug, Info, Warn, Error
|
||||
|
||||
Default is Warn
|
||||
Default is Info
|
||||
|
||||
### client_log_level
|
||||
|
||||
@ -185,5 +187,5 @@ How verbose to log issues with client requests
|
||||
|
||||
Possible values are: Trace, Debug, Info, Warn, Error
|
||||
|
||||
Default is Error
|
||||
Default is Info
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user