photoncloud-monorepo/lightningstor/crates/lightningstor-server/src/config.rs

258 lines
6.8 KiB
Rust

//! Server configuration
use lightningstor_distributed::DistributedConfig;
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
/// TLS configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TlsConfig {
/// Path to certificate file (PEM)
pub cert_file: String,
/// Path to private key file (PEM)
pub key_file: String,
/// Path to CA certificate for client verification (optional, for mTLS)
pub ca_file: Option<String>,
/// Require client certificates (mTLS)
#[serde(default)]
pub require_client_cert: bool,
}
/// Metadata storage backend
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum MetadataBackend {
/// FlareDB distributed metadata database
FlareDb,
/// PostgreSQL metadata database
Postgres,
/// SQLite metadata database (single-node only)
Sqlite,
}
impl Default for MetadataBackend {
fn default() -> Self {
Self::FlareDb
}
}
/// Object data storage backend
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "snake_case")]
pub enum ObjectStorageBackend {
/// Store object data directly on the local filesystem.
#[default]
LocalFs,
/// Coordinate object data across LightningStor storage nodes.
Distributed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct S3AuthConfig {
#[serde(default = "default_s3_auth_enabled")]
pub enabled: bool,
#[serde(default = "default_s3_aws_region")]
pub aws_region: String,
#[serde(default = "default_s3_iam_cache_ttl_secs")]
pub iam_cache_ttl_secs: u64,
#[serde(default = "default_s3_default_org_id")]
pub default_org_id: Option<String>,
#[serde(default = "default_s3_default_project_id")]
pub default_project_id: Option<String>,
#[serde(default = "default_s3_max_auth_body_bytes")]
pub max_auth_body_bytes: usize,
}
impl Default for S3AuthConfig {
fn default() -> Self {
Self {
enabled: default_s3_auth_enabled(),
aws_region: default_s3_aws_region(),
iam_cache_ttl_secs: default_s3_iam_cache_ttl_secs(),
default_org_id: default_s3_default_org_id(),
default_project_id: default_s3_default_project_id(),
max_auth_body_bytes: default_s3_max_auth_body_bytes(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct S3PerformanceConfig {
#[serde(default = "default_s3_streaming_put_threshold_bytes")]
pub streaming_put_threshold_bytes: usize,
#[serde(default = "default_s3_inline_put_max_bytes")]
pub inline_put_max_bytes: usize,
#[serde(default = "default_s3_multipart_put_concurrency")]
pub multipart_put_concurrency: usize,
#[serde(default = "default_s3_multipart_fetch_concurrency")]
pub multipart_fetch_concurrency: usize,
}
impl Default for S3PerformanceConfig {
fn default() -> Self {
Self {
streaming_put_threshold_bytes: default_s3_streaming_put_threshold_bytes(),
inline_put_max_bytes: default_s3_inline_put_max_bytes(),
multipart_put_concurrency: default_s3_multipart_put_concurrency(),
multipart_fetch_concurrency: default_s3_multipart_fetch_concurrency(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct S3Config {
#[serde(default)]
pub auth: S3AuthConfig,
#[serde(default)]
pub performance: S3PerformanceConfig,
}
/// Server configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
/// gRPC address to listen on
pub grpc_addr: SocketAddr,
/// S3 HTTP API address to listen on
pub s3_addr: SocketAddr,
/// Log level
pub log_level: String,
/// ChainFire endpoint for cluster coordination only
pub chainfire_endpoint: Option<String>,
/// FlareDB endpoint for metadata and tenant data storage
pub flaredb_endpoint: Option<String>,
/// Metadata backend selection (flaredb, postgres, sqlite)
#[serde(default)]
pub metadata_backend: MetadataBackend,
/// SQL database URL for metadata when backend is postgres or sqlite
pub metadata_database_url: Option<String>,
/// Allow single-node mode (required for SQLite)
#[serde(default)]
pub single_node: bool,
/// Data directory for object storage
pub data_dir: String,
/// Object data storage backend selection
#[serde(default)]
pub object_storage_backend: ObjectStorageBackend,
/// Distributed object storage settings (used when backend=distributed)
#[serde(default)]
pub distributed: DistributedConfig,
/// Whether local filesystem writes should be flushed before success is returned.
#[serde(default)]
pub sync_on_write: bool,
/// TLS configuration (optional)
pub tls: Option<TlsConfig>,
/// Authentication configuration
#[serde(default)]
pub auth: AuthConfig,
/// S3 API runtime settings
#[serde(default)]
pub s3: S3Config,
}
/// Authentication configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthConfig {
/// IAM server endpoint
#[serde(default = "default_iam_server_addr")]
pub iam_server_addr: String,
}
fn default_iam_server_addr() -> String {
"127.0.0.1:50051".to_string()
}
fn default_s3_auth_enabled() -> bool {
true
}
fn default_s3_aws_region() -> String {
"us-east-1".to_string()
}
fn default_s3_iam_cache_ttl_secs() -> u64 {
30
}
fn default_s3_default_org_id() -> Option<String> {
Some("default".to_string())
}
fn default_s3_default_project_id() -> Option<String> {
Some("default".to_string())
}
fn default_s3_max_auth_body_bytes() -> usize {
1024 * 1024 * 1024
}
fn default_s3_streaming_put_threshold_bytes() -> usize {
16 * 1024 * 1024
}
fn default_s3_inline_put_max_bytes() -> usize {
128 * 1024 * 1024
}
fn default_s3_multipart_put_concurrency() -> usize {
4
}
fn default_s3_multipart_fetch_concurrency() -> usize {
4
}
impl Default for AuthConfig {
fn default() -> Self {
Self {
iam_server_addr: default_iam_server_addr(),
}
}
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
grpc_addr: "0.0.0.0:9000".parse().unwrap(),
s3_addr: "0.0.0.0:9001".parse().unwrap(),
log_level: "info".to_string(),
chainfire_endpoint: None,
flaredb_endpoint: None,
metadata_backend: MetadataBackend::FlareDb,
metadata_database_url: None,
single_node: false,
data_dir: "/var/lib/lightningstor/data".to_string(),
object_storage_backend: ObjectStorageBackend::LocalFs,
distributed: DistributedConfig::default(),
sync_on_write: false,
tls: None,
auth: AuthConfig::default(),
s3: S3Config::default(),
}
}
}