increased configurability
This commit is contained in:
@@ -189,15 +189,6 @@ impl<'a> TryFrom<&'a DescribedGateway> for Node {
|
||||
});
|
||||
}
|
||||
|
||||
let ips = ips
|
||||
.iter()
|
||||
.map(|ip| ip.parse())
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|err| GatewayConversionError::MalformedIpAddress {
|
||||
gateway: value.bond.gateway.identity_key.clone(),
|
||||
err,
|
||||
})?;
|
||||
|
||||
let host = match &self_described.host_information.hostname {
|
||||
None => NetworkAddress::IpAddr(ips[0]),
|
||||
Some(hostname) => NetworkAddress::Hostname(hostname.clone()),
|
||||
|
||||
@@ -41,7 +41,7 @@ pub(crate) struct OverrideConfig {
|
||||
impl OverrideConfig {
|
||||
pub(crate) fn do_override(self, mut config: Config) -> Result<Config, GatewayError> {
|
||||
config = config
|
||||
.with_optional(Config::with_listening_address, self.host)
|
||||
.with_optional(Config::with_host, self.host)
|
||||
.with_optional(Config::with_mix_port, self.mix_port)
|
||||
.with_optional(Config::with_clients_port, self.clients_port)
|
||||
.with_optional_custom_env(
|
||||
|
||||
@@ -13,9 +13,9 @@ use nym_config::{
|
||||
};
|
||||
use nym_network_defaults::mainnet;
|
||||
use nym_node::config;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use std::io;
|
||||
use std::net::IpAddr;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
@@ -40,6 +40,18 @@ const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000;
|
||||
const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16;
|
||||
const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100;
|
||||
|
||||
fn de_maybe_port<'de, D>(deserializer: D) -> Result<Option<u16>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let port = u16::deserialize(deserializer)?;
|
||||
if port == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(port))
|
||||
}
|
||||
}
|
||||
|
||||
/// Derive default path to gateway's config directory.
|
||||
/// It should get resolved to `$HOME/.nym/gateways/<id>/config`
|
||||
pub fn default_config_directory<P: AsRef<Path>>(id: P) -> PathBuf {
|
||||
@@ -73,11 +85,17 @@ pub struct Config {
|
||||
#[serde(skip)]
|
||||
pub(crate) save_path: Option<PathBuf>,
|
||||
|
||||
pub host: config::Host,
|
||||
|
||||
#[serde(default)]
|
||||
pub http: config::Http,
|
||||
|
||||
pub gateway: Gateway,
|
||||
|
||||
#[serde(default)]
|
||||
// currently not really used for anything useful
|
||||
pub wireguard: config::Wireguard,
|
||||
|
||||
pub storage_paths: GatewayPaths,
|
||||
|
||||
pub network_requester: NetworkRequester,
|
||||
@@ -97,10 +115,16 @@ impl NymConfigTemplate for Config {
|
||||
|
||||
impl Config {
|
||||
pub fn new<S: AsRef<str>>(id: S) -> Self {
|
||||
let default_gateway = Gateway::new_default(id.as_ref());
|
||||
Config {
|
||||
save_path: None,
|
||||
host: config::Host {
|
||||
public_ips: vec![default_gateway.listening_address],
|
||||
..Default::default()
|
||||
},
|
||||
http: Default::default(),
|
||||
gateway: Gateway::new_default(id.as_ref()),
|
||||
gateway: default_gateway,
|
||||
wireguard: Default::default(),
|
||||
storage_paths: GatewayPaths::new_default(id.as_ref()),
|
||||
network_requester: Default::default(),
|
||||
logging: Default::default(),
|
||||
@@ -188,8 +212,16 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_listening_address(mut self, listening_address: IpAddr) -> Self {
|
||||
pub fn with_host(mut self, listening_address: IpAddr) -> Self {
|
||||
self.gateway.listening_address = listening_address;
|
||||
|
||||
// temporary workaround
|
||||
self.host.public_ips = vec![listening_address];
|
||||
let http_port = self.http.bind_address.port();
|
||||
self.http.bind_address = SocketAddr::new(listening_address, http_port);
|
||||
let wg_port = self.wireguard.bind_address.port();
|
||||
self.wireguard.bind_address = SocketAddr::new(listening_address, wg_port);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
@@ -251,6 +283,11 @@ pub struct Gateway {
|
||||
/// (default: 9000)
|
||||
pub clients_port: u16,
|
||||
|
||||
/// If applicable, announced port for listening for secure websocket client traffic.
|
||||
/// (default: None)
|
||||
#[serde(deserialize_with = "de_maybe_port")]
|
||||
pub clients_wss_port: Option<u16>,
|
||||
|
||||
/// Whether gateway collects and sends anonymized statistics
|
||||
pub enabled_statistics: bool,
|
||||
|
||||
@@ -285,6 +322,7 @@ impl Gateway {
|
||||
listening_address: inaddr_any(),
|
||||
mix_port: DEFAULT_MIX_LISTENING_PORT,
|
||||
clients_port: DEFAULT_CLIENT_LISTENING_PORT,
|
||||
clients_wss_port: None,
|
||||
enabled_statistics: false,
|
||||
statistics_service_url: mainnet::STATISTICS_SERVICE_DOMAIN_ADDRESS
|
||||
.parse()
|
||||
|
||||
@@ -110,6 +110,13 @@ impl From<ConfigV1_1_29> for Config {
|
||||
Config {
|
||||
save_path: value.save_path,
|
||||
|
||||
// \/ ADDED
|
||||
host: nym_node::config::Host {
|
||||
public_ips: vec![value.gateway.listening_address],
|
||||
..Default::default()
|
||||
},
|
||||
// /\ ADDED
|
||||
|
||||
// \/ ADDED
|
||||
http: Default::default(),
|
||||
// /\ ADDED
|
||||
@@ -120,12 +127,19 @@ impl From<ConfigV1_1_29> for Config {
|
||||
listening_address: value.gateway.listening_address,
|
||||
mix_port: value.gateway.mix_port,
|
||||
clients_port: value.gateway.clients_port,
|
||||
|
||||
// \/ ADDED
|
||||
clients_wss_port: None,
|
||||
// /\ ADDED
|
||||
enabled_statistics: value.gateway.enabled_statistics,
|
||||
nym_api_urls: value.gateway.nym_api_urls,
|
||||
nyxd_urls: value.gateway.nyxd_urls,
|
||||
statistics_service_url: value.gateway.statistics_service_url,
|
||||
cosmos_mnemonic: value.gateway.cosmos_mnemonic,
|
||||
},
|
||||
// \/ ADDED
|
||||
wireguard: Default::default(),
|
||||
// /\ ADDED
|
||||
storage_paths: GatewayPaths {
|
||||
keys: KeysPaths {
|
||||
private_identity_key_file: value.storage_paths.keys.private_identity_key_file,
|
||||
|
||||
@@ -9,7 +9,18 @@ pub(crate) const CONFIG_TEMPLATE: &str = r#"
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
##### main base mixnode config options #####
|
||||
##### main base gateway config options #####
|
||||
|
||||
[host]
|
||||
# Ip address(es) of this host, such as 1.1.1.1 that external clients will use for connections.
|
||||
public_ips = [
|
||||
{{#each host.public_ips }}
|
||||
'{{this}}',
|
||||
{{/each}}
|
||||
]
|
||||
|
||||
# (temporary) Optional hostname of this node, for example nymtech.net.
|
||||
hostname = '{{ host.hostname }}'
|
||||
|
||||
[gateway]
|
||||
# Version of the gateway for which this configuration was created.
|
||||
@@ -33,6 +44,10 @@ mix_port = {{ gateway.mix_port }}
|
||||
# (default: 9000)
|
||||
clients_port = {{ gateway.clients_port }}
|
||||
|
||||
# If applicable, announced port for listening for secure websocket client traffic.
|
||||
# (default: 0 - disabled)
|
||||
clients_wss_port ={{#if gateway.clients_wss_port }} {{ gateway.clients_wss_port }} {{else}} 0 {{/if}}
|
||||
|
||||
# Wheather gateway collects and sends anonymized statistics
|
||||
enabled_statistics = {{ gateway.enabled_statistics }}
|
||||
|
||||
|
||||
+13
-4
@@ -19,12 +19,21 @@ use tokio::sync::RwLock;
|
||||
fn load_gateway_details(
|
||||
config: &Config,
|
||||
) -> Result<api_requests::v1::gateway::models::Gateway, GatewayError> {
|
||||
let wireguard = if config.wireguard.enabled {
|
||||
Some(api_requests::v1::gateway::models::Wireguard {
|
||||
port: config.wireguard.announced_port,
|
||||
public_key: "placeholder key value".to_string(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(api_requests::v1::gateway::models::Gateway {
|
||||
client_interfaces: api_requests::v1::gateway::models::ClientInterfaces {
|
||||
wireguard: None,
|
||||
wireguard,
|
||||
mixnet_websockets: Some(api_requests::v1::gateway::models::WebSockets {
|
||||
ws_port: config.gateway.clients_port,
|
||||
wss_port: None,
|
||||
wss_port: config.gateway.clients_wss_port,
|
||||
}),
|
||||
},
|
||||
})
|
||||
@@ -37,8 +46,8 @@ fn load_host_details(
|
||||
) -> Result<api_requests::v1::node::models::SignedHostInformation, GatewayError> {
|
||||
let host_info = api_requests::v1::node::models::HostInformation {
|
||||
// TODO: this should be extracted differently, i.e. it's the issue of the public/private address
|
||||
ip_address: vec![config.gateway.listening_address.to_string()],
|
||||
hostname: None,
|
||||
ip_address: config.host.public_ips.clone(),
|
||||
hostname: config.host.hostname.clone(),
|
||||
keys: api_requests::v1::node::models::HostKeys {
|
||||
ed25519: identity_keypair.public_key().to_base58_string(),
|
||||
x25519: sphinx_key.to_base58_string(),
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::IpAddr;
|
||||
|
||||
pub use crate::api::SignedHostInformation;
|
||||
pub use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
@@ -19,9 +20,11 @@ pub struct NodeRoles {
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct HostInformation {
|
||||
/// Ip address(es) of this host, such as `1.1.1.1`.
|
||||
pub ip_address: Vec<String>,
|
||||
#[cfg_attr(feature = "openapi", schema(value_type = Vec<String>, format = Byte, example = json!(["1.1.1.1"])))]
|
||||
pub ip_address: Vec<IpAddr>,
|
||||
|
||||
/// Optional hostname of this node, for example `nymtech.net`.
|
||||
#[cfg_attr(feature = "openapi", schema(example = "nymtech.net"))]
|
||||
pub hostname: Option<String>,
|
||||
|
||||
/// Public keys associated with this node.
|
||||
|
||||
+62
-10
@@ -1,24 +1,43 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_helpers::*;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn de_maybe_path<'de, D>(deserializer: D) -> Result<Option<PathBuf>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let path = PathBuf::deserialize(deserializer)?;
|
||||
if path.as_os_str().is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(path))
|
||||
pub mod persistence;
|
||||
mod serde_helpers;
|
||||
|
||||
pub const DEFAULT_WIREGUARD_PORT: u16 = 51820;
|
||||
|
||||
// TODO: this is very much a WIP. we need proper ssl certificate support here
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Host {
|
||||
/// Ip address(es) of this host, such as 1.1.1.1 that external clients will use for connections.
|
||||
pub public_ips: Vec<IpAddr>,
|
||||
|
||||
/// Optional hostname of this node, for example nymtech.net.
|
||||
// TODO: this is temporary. to be replaced by pulling the data directly from the certs.
|
||||
#[serde(deserialize_with = "de_maybe_string")]
|
||||
pub hostname: Option<String>,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for Host {
|
||||
fn default() -> Self {
|
||||
Host {
|
||||
public_ips: vec![],
|
||||
hostname: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Http {
|
||||
/// Socket address this node will use for binding its http API.
|
||||
/// default: `0.0.0.0:80`
|
||||
@@ -37,3 +56,36 @@ impl Default for Http {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Wireguard {
|
||||
/// Specifies whether the wireguard service is enabled on this node.
|
||||
pub enabled: bool,
|
||||
|
||||
/// Socket address this node will use for binding its wireguard interface.
|
||||
/// default: `0.0.0.0:51820`
|
||||
pub bind_address: SocketAddr,
|
||||
|
||||
/// Port announced to external clients wishing to connect to the wireguard interface.
|
||||
/// Useful in the instances where the node is behind a proxy.
|
||||
pub announced_port: u16,
|
||||
|
||||
/// Paths for wireguard keys, client registries, etc.
|
||||
pub storage_paths: persistence::WireguardPaths,
|
||||
}
|
||||
|
||||
impl Default for Wireguard {
|
||||
fn default() -> Self {
|
||||
Wireguard {
|
||||
enabled: false,
|
||||
bind_address: SocketAddr::new(
|
||||
IpAddr::V4(Ipv4Addr::UNSPECIFIED),
|
||||
DEFAULT_WIREGUARD_PORT,
|
||||
),
|
||||
announced_port: DEFAULT_WIREGUARD_PORT,
|
||||
storage_paths: persistence::WireguardPaths {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WireguardPaths {
|
||||
// pub keys:
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(super) fn de_maybe_path<'de, D>(deserializer: D) -> Result<Option<PathBuf>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let path = PathBuf::deserialize(deserializer)?;
|
||||
if path.as_os_str().is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(path))
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn de_maybe_string<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let path = String::deserialize(deserializer)?;
|
||||
if path.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(path))
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ use crate::http::middleware::logging;
|
||||
use crate::http::state::AppState;
|
||||
use crate::http::NymNodeHTTPServer;
|
||||
use axum::Router;
|
||||
use nym_node_requests::api::v1::gateway::models::Gateway;
|
||||
use nym_node_requests::api::v1::gateway::models::{Gateway, Wireguard};
|
||||
use nym_node_requests::api::v1::mixnode::models::Mixnode;
|
||||
use nym_node_requests::api::v1::network_requester::models::NetworkRequester;
|
||||
use nym_node_requests::api::v1::node::models;
|
||||
@@ -15,6 +15,7 @@ use nym_node_requests::api::SignedHostInformation;
|
||||
use nym_node_requests::routes;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
use tracing::warn;
|
||||
|
||||
pub mod api;
|
||||
pub mod landing_page;
|
||||
@@ -48,6 +49,18 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_wireguard_interface(mut self, wireguard: Wireguard) -> Self {
|
||||
match &mut self.api.v1_config.gateway.details {
|
||||
Some(gw) => gw.client_interfaces.wireguard = Some(wireguard),
|
||||
None => {
|
||||
warn!(
|
||||
"can't add wireguard interface information as the gateway role is not enabled."
|
||||
);
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_landing_page_assets<P: AsRef<Path>>(mut self, assets_path: Option<P>) -> Self {
|
||||
self.landing.assets_path = assets_path.map(|p| p.as_ref().to_path_buf());
|
||||
|
||||
Reference in New Issue
Block a user