diff --git a/book/src/server_configuration.md b/book/src/server_configuration.md index 388df0165..28fed4b53 100644 --- a/book/src/server_configuration.md +++ b/book/src/server_configuration.md @@ -5,6 +5,10 @@ You need a configuration file in the volume named `server.toml`. (Within the container it should be `/data/server.toml`) The following is a commented example configuration. +The full options and explanations are in the +[kanidmd_core::config::ServerConfig](https://kanidm.github.io/kanidm/master/rustdoc/kanidmd_core/config/struct.ServerConfig.html) +for your particular build. + ```toml {{#rustdoc_include ../../examples/server_container.toml}} ``` diff --git a/proto/src/internal.rs b/proto/src/internal.rs index 1f529f1cc..d99a147ae 100644 --- a/proto/src/internal.rs +++ b/proto/src/internal.rs @@ -128,3 +128,47 @@ impl ImageValue { } } } + +#[repr(u32)] +#[derive(Debug, Copy, Clone, Deserialize, Default, Eq, PartialEq)] +#[serde(rename_all = "lowercase")] +/// Filesystem type object, used for tuning database parameters. +pub enum FsType { + Zfs = 65536, + #[default] + #[serde(other)] + /// The default setting, if not set to "zfs" + Generic = 4096, +} + +impl FsType { + pub fn checkpoint_pages(&self) -> u32 { + match self { + FsType::Generic => 2048, + FsType::Zfs => 256, + } + } +} + +impl From for FsType { + fn from(s: String) -> Self { + s.as_str().into() + } +} + +impl From<&str> for FsType { + fn from(s: &str) -> Self { + match s { + "zfs" => FsType::Zfs, + _ => FsType::Generic, + } + } +} + +#[test] +fn test_fstype_deser() { + assert_eq!(FsType::from("zfs"), FsType::Zfs); + assert_eq!(FsType::from("generic"), FsType::Generic); + assert_eq!(FsType::from(" "), FsType::Generic); + assert_eq!(FsType::from("crab🦀"), FsType::Generic); +} diff --git a/server/core/src/config.rs b/server/core/src/config.rs index 87e344041..83dde87ef 100644 --- a/server/core/src/config.rs +++ b/server/core/src/config.rs @@ -13,6 +13,7 @@ use std::path::Path; use std::str::FromStr; use kanidm_proto::constants::DEFAULT_SERVER_ADDRESS; +use kanidm_proto::internal::FsType; use kanidm_proto::messages::ConsoleOutputMode; use kanidm_lib_crypto::prelude::X509; @@ -24,10 +25,29 @@ use url::Url; #[derive(Deserialize, Debug, Clone)] pub struct OnlineBackup { + /// The destination folder for your backups pub path: String, #[serde(default = "default_online_backup_schedule")] + /// The schedule to run online backups (see ) + /// + /// Examples: + /// + /// - every day at 22:00 UTC (default): `"00 22 * * *"` + /// - every 6th hours (four times a day) at 3 minutes past the hour, : + /// `"03 */6 * * *"` + /// + /// We also support non standard cron syntax, with the following format: + /// + /// ` ` + /// + /// eg: + /// - `1 2 3 5 12 * 2023` would only back up once on the 5th of December 2023 at 03:02:01am. + /// - `3 2 1 * * Mon *` backs up every Monday at 03:02:01am. + /// + /// (it's very similar to the standard cron syntax, it just allows to specify the seconds at the beginning and the year at the end) pub schedule: String, #[serde(default = "default_online_backup_versions")] + /// How many past backup versions to keep pub versions: usize, } @@ -82,32 +102,60 @@ pub struct ReplicationConfiguration { pub manual: BTreeMap, } -/// This is the Server Configuration as read from server.toml. Important to note -/// is that not all flags or values from Configuration are exposed via this structure +/// This is the Server Configuration as read from `server.toml`. +/// +/// NOTE: not all flags or values from the internal [Configuration] object are exposed via this structure /// to prevent certain settings being set (e.g. integration test modes) #[derive(Debug, Deserialize)] #[serde(deny_unknown_fields)] pub struct ServerConfig { - pub bindaddress: Option, - pub ldapbindaddress: Option, - pub adminbindpath: Option, - pub trust_x_forward_for: Option, - // pub threads: Option, - pub db_path: String, - pub db_fs_type: Option, - pub db_arc_size: Option, - pub tls_chain: Option, - pub tls_key: Option, - pub online_backup: Option, + /// Kanidm Domain, eg `kanidm.example.com`. pub domain: String, + /// The user-facing HTTPS URL for this server, eg // TODO -this should be URL pub origin: String, - pub log_level: Option, + /// File path of the database file + pub db_path: String, + /// The file path to the TLS Certificate Chain + pub tls_chain: Option, + /// The file path to the TLS Private Key + pub tls_key: Option, + + /// The listener address for the HTTPS server. + /// + /// eg. `[::]:8443` or `127.0.0.1:8443`. Defaults to [kanidm_proto::constants::DEFAULT_SERVER_ADDRESS] + pub bindaddress: Option, + /// The listener address for the LDAP server. + /// + /// eg. `[::]:3636` or `127.0.0.1:3636`. Defaults to [kanidm_proto::constants::DEFAULT_LDAP_ADDRESS] + pub ldapbindaddress: Option, + + /// The role of this server, one of write_replica, write_replica_no_ui, read_only_replica #[serde(default)] pub role: ServerRole, + /// The log level, one of info, debug, trace. Defaults to "info" if not set. + pub log_level: Option, + + /// Backup Configuration, see [OnlineBackup] for details on sub-keys. + pub online_backup: Option, + + /// Trust the X-Forwarded-For header for client IP address. Defaults to false if unset. + pub trust_x_forward_for: Option, + + /// The filesystem type, either "zfs" or "generic". Defaults to "generic" if unset. + pub db_fs_type: Option, + /// The path to the "admin" socket, used for local communication when performing cer ain server control tasks. + pub adminbindpath: Option, + + /// Don't touch this unless you know what you're doing! + #[allow(dead_code)] + db_arc_size: Option, #[serde(default)] + + /// Enable replication, this is a development feature and not yet ready for production use. pub i_acknowledge_that_replication_is_in_development: bool, #[serde(rename = "replication")] + /// Replication configuration, this is a development feature and not yet ready for production use. pub repl_config: Option, } @@ -133,6 +181,11 @@ impl ServerConfig { std::io::Error::new(std::io::ErrorKind::Other, e) }) } + + /// Return the ARC size for the database, it's something you really shouldn't touch unless you are doing extreme tuning. + pub fn get_db_arc_size(&self) -> Option { + self.db_arc_size + } } #[derive(Debug, Deserialize, Clone, Copy, Default, Eq, PartialEq)] @@ -225,6 +278,7 @@ pub struct IntegrationReplConfig { // events? Or a channel to submit with oneshot responses. } +/// The internal configuration of the server. User-facing configuration is in [ServerConfig], as the configuration file is parsed by that object. #[derive(Debug, Clone)] pub struct Configuration { pub address: String, @@ -233,7 +287,7 @@ pub struct Configuration { pub threads: usize, // db type later pub db_path: String, - pub db_fs_type: Option, + pub db_fs_type: Option, pub db_arc_size: Option, pub maximum_request: usize, pub trust_x_forward_for: bool, @@ -393,8 +447,8 @@ impl Configuration { self.db_arc_size = v } - pub fn update_db_fs_type(&mut self, p: &Option) { - self.db_fs_type = p.as_ref().map(|v| v.to_lowercase()); + pub fn update_db_fs_type(&mut self, p: &Option) { + self.db_fs_type = p.to_owned(); } pub fn update_bind(&mut self, b: &Option) { diff --git a/server/core/src/lib.rs b/server/core/src/lib.rs index c207c74b7..ff3e1ea25 100644 --- a/server/core/src/lib.rs +++ b/server/core/src/lib.rs @@ -42,7 +42,7 @@ use std::sync::Arc; use crate::utils::touch_file_or_quit; use compact_jwt::JwsSigner; use kanidm_proto::v1::OperationError; -use kanidmd_lib::be::{Backend, BackendConfig, BackendTransaction, FsType}; +use kanidmd_lib::be::{Backend, BackendConfig, BackendTransaction}; use kanidmd_lib::idm::ldap::LdapServer; use kanidmd_lib::prelude::*; use kanidmd_lib::schema::Schema; @@ -76,21 +76,11 @@ fn setup_backend_vacuum( let idxmeta = schema_txn.reload_idxmeta(); let pool_size: u32 = config.threads as u32; - let fstype: FsType = if config - .db_fs_type - .as_ref() - .map(|s| s == "zfs") - .unwrap_or(false) - { - FsType::Zfs - } else { - FsType::Generic - }; let cfg = BackendConfig::new( config.db_path.as_str(), pool_size, - fstype, + config.db_fs_type.unwrap_or_default(), config.db_arc_size, ); diff --git a/server/daemon/src/main.rs b/server/daemon/src/main.rs index 29b6fba27..5e6dd5837 100644 --- a/server/daemon/src/main.rs +++ b/server/daemon/src/main.rs @@ -389,7 +389,7 @@ async fn kanidm_main() -> ExitCode { config.update_db_fs_type(&sconfig.db_fs_type); config.update_origin(sconfig.origin.as_str()); config.update_domain(sconfig.domain.as_str()); - config.update_db_arc_size(sconfig.db_arc_size); + config.update_db_arc_size(sconfig.get_db_arc_size()); config.update_role(sconfig.role); config.update_output_mode(opt.commands.commonopt().output_mode.to_owned().into()); config.update_trust_x_forward_for(sconfig.trust_x_forward_for); diff --git a/server/lib/src/be/idl_sqlite.rs b/server/lib/src/be/idl_sqlite.rs index ba339bbed..a91a3bc13 100644 --- a/server/lib/src/be/idl_sqlite.rs +++ b/server/lib/src/be/idl_sqlite.rs @@ -40,22 +40,6 @@ pub(super) fn serde_json_error(e: serde_json::Error) -> OperationError { type ConnPool = Arc>>; -#[repr(u32)] -#[derive(Debug, Copy, Clone)] -pub enum FsType { - Generic = 4096, - Zfs = 65536, -} - -impl FsType { - pub fn checkpoint_pages(&self) -> u32 { - match self { - FsType::Generic => 2048, - FsType::Zfs => 256, - } - } -} - #[derive(Debug)] pub struct IdSqliteEntry { id: i64, diff --git a/server/lib/src/be/mod.rs b/server/lib/src/be/mod.rs index c11fb1027..6b89e94c0 100644 --- a/server/lib/src/be/mod.rs +++ b/server/lib/src/be/mod.rs @@ -46,8 +46,7 @@ use crate::be::idl_arc_sqlite::{ IdlArcSqlite, IdlArcSqliteReadTransaction, IdlArcSqliteTransaction, IdlArcSqliteWriteTransaction, }; -// Re-export this -pub use crate::be::idl_sqlite::FsType; +use kanidm_proto::internal::FsType; // Currently disabled due to improvements in idlset for intersection handling. const FILTER_SEARCH_TEST_THRESHOLD: usize = 0;