Packaging: the binary and package are inbuxa, INBUXA_* settings with STALWART_* fallback
- crates/main: package and [[bin]] renamed to inbuxa; homepage inbuxa.org; license AGPL-3.0-only (upstream is dual; the fork takes the AGPL). - types::branding::env_var reads INBUXA_<name>, falling back to STALWART_<name> with a warning, for all nine server settings. STALWART_APP_ and STALWART_SPAM_* storage keys are unchanged. - New-install default paths /var/lib/inbuxa and /var/log/inbuxa. - Dockerfiles, systemd unit, launchd plist and AppArmor profile renamed. - Upstream's .github moved to .github-upstream so none of it runs. - install.sh stubbed: upstream's would install Stalwart. - Two missed brand strings: the SMTP Received header and the utils user agent.
This commit is contained in:
@@ -69,7 +69,7 @@ impl Listeners {
|
||||
bind: Map::new(vec![
|
||||
SocketAddr::from_str(&format!(
|
||||
"[::]:{}",
|
||||
std::env::var("STALWART_RECOVERY_MODE_PORT")
|
||||
types::branding::env_var("RECOVERY_MODE_PORT")
|
||||
.ok()
|
||||
.and_then(|p| p.parse::<u16>().ok())
|
||||
.unwrap_or(8080)
|
||||
|
||||
@@ -503,7 +503,7 @@ impl Tracers {
|
||||
}
|
||||
} else {
|
||||
// Add default tracer if none were found
|
||||
let level = std::env::var("STALWART_RECOVERY_MODE_LOG_LEVEL")
|
||||
let level = types::branding::env_var("RECOVERY_MODE_LOG_LEVEL")
|
||||
.ok()
|
||||
.and_then(|level| Level::from_str(&level).ok())
|
||||
.unwrap_or(Level::Info);
|
||||
|
||||
@@ -43,7 +43,7 @@ const HELP: &str = concat!(
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
r#"
|
||||
|
||||
Usage: stalwart [OPTIONS]
|
||||
Usage: inbuxa [OPTIONS]
|
||||
|
||||
Options:
|
||||
-c, --config <PATH> Start server with the specified configuration file
|
||||
|
||||
@@ -529,7 +529,7 @@ async fn insert_safe_defaults(bp: &mut Bootstrap) -> trc::Result<()> {
|
||||
ansi: false,
|
||||
prefix: "stalwart.log".into(),
|
||||
rotate: LogRotateFrequency::Daily,
|
||||
path: "/var/log/stalwart".into(),
|
||||
path: "/var/log/inbuxa".into(),
|
||||
..Default::default()
|
||||
})
|
||||
.into(),
|
||||
|
||||
@@ -657,7 +657,7 @@ fn map_dns_server(dns_server: &DnsServerBootstrap) -> Option<registry::schema::s
|
||||
const DEFAULT_DATA_PATH: &str = if cfg!(target_os = "freebsd") {
|
||||
"/var/db/stalwart/"
|
||||
} else {
|
||||
"/var/lib/stalwart/"
|
||||
"/var/lib/inbuxa/"
|
||||
};
|
||||
|
||||
fn build_default_bootstrap(server: &Server) -> Bootstrap {
|
||||
@@ -676,7 +676,7 @@ fn build_default_bootstrap(server: &Server) -> Bootstrap {
|
||||
in_memory_store: InMemoryStore::Default,
|
||||
directory: DirectoryBootstrap::Internal,
|
||||
tracer: Tracer::Log(TracerLog {
|
||||
path: "/var/log/stalwart/".to_string(),
|
||||
path: "/var/log/inbuxa/".to_string(),
|
||||
prefix: "stalwart".to_string(),
|
||||
ansi: true,
|
||||
enable: true,
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
[package]
|
||||
name = "stalwart"
|
||||
name = "inbuxa"
|
||||
description = "INBUXA Mail and Collaboration Server, a fork of Stalwart"
|
||||
authors = [ "Stalwart Labs LLC <[email protected]>"]
|
||||
repository = "https://github.com/stalwartlabs/stalwart"
|
||||
homepage = "https://stalw.art"
|
||||
homepage = "https://inbuxa.org"
|
||||
keywords = ["imap", "jmap", "smtp", "email", "mail", "webdav", "server"]
|
||||
categories = ["email"]
|
||||
license = "AGPL-3.0-only OR LicenseRef-SEL"
|
||||
# Upstream offers AGPL-3.0-only OR LicenseRef-SEL; INBUXA takes the AGPL only.
|
||||
license = "AGPL-3.0-only"
|
||||
version = "0.16.22"
|
||||
edition = "2024"
|
||||
|
||||
[[bin]]
|
||||
name = "stalwart"
|
||||
name = "inbuxa"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -4143,7 +4143,7 @@ impl Default for Bootstrap {
|
||||
request_tls_certificate: true,
|
||||
generate_dkim_keys: true,
|
||||
data_store: DataStore::RocksDb(RocksDbStore {
|
||||
path: "/var/lib/stalwart/".to_string(),
|
||||
path: "/var/lib/inbuxa/".to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
blob_store: BlobStore::Default,
|
||||
@@ -4151,7 +4151,7 @@ impl Default for Bootstrap {
|
||||
in_memory_store: InMemoryStore::Default,
|
||||
directory: DirectoryBootstrap::Internal,
|
||||
tracer: Tracer::Log(TracerLog {
|
||||
path: "/var/log/stalwart/".to_string(),
|
||||
path: "/var/log/inbuxa/".to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
dns_server: DnsServerBootstrap::Manual,
|
||||
|
||||
@@ -1051,7 +1051,7 @@ impl<T: SessionStream> Session<T> {
|
||||
}
|
||||
headers.extend_from_slice(b"by ");
|
||||
headers.extend_from_slice(self.hostname.as_bytes());
|
||||
headers.extend_from_slice(b" (Stalwart SMTP) with ");
|
||||
headers.extend_from_slice(concat!(" (", types::brand!(), " SMTP) with ").as_bytes());
|
||||
headers.extend_from_slice(match (self.stream.is_tls(), !self.is_authenticated()) {
|
||||
(true, true) => b"ESMTPS",
|
||||
(true, false) => b"ESMTPSA",
|
||||
|
||||
@@ -31,18 +31,18 @@ impl RegistryStore {
|
||||
.collect::<String>();
|
||||
eprintln!();
|
||||
eprintln!("════════════════════════════════════════════════════════════");
|
||||
eprintln!("🔑 Stalwart bootstrap mode - temporary administrator account");
|
||||
eprintln!("🔑 INBUXA bootstrap mode - temporary administrator account");
|
||||
eprintln!();
|
||||
eprintln!(" username: admin");
|
||||
eprintln!(" password: {password}");
|
||||
eprintln!();
|
||||
eprintln!("Use these credentials to complete the initial setup at the");
|
||||
eprintln!("/admin web UI. Once setup is done, Stalwart will provision a");
|
||||
eprintln!("/admin web UI. Once setup is done, the server will provision a");
|
||||
eprintln!("permanent administrator and this temporary account will no");
|
||||
eprintln!("longer apply.");
|
||||
eprintln!();
|
||||
eprintln!("This password is shown only once. To pin a credential");
|
||||
eprintln!("instead, set STALWART_RECOVERY_ADMIN=admin:<password> in the");
|
||||
eprintln!("instead, set INBUXA_RECOVERY_ADMIN=admin:<password> in the");
|
||||
eprintln!("env file.");
|
||||
eprintln!("════════════════════════════════════════════════════════════");
|
||||
eprintln!();
|
||||
|
||||
@@ -17,7 +17,7 @@ pub(crate) enum RegistryInit {
|
||||
|
||||
impl RegistryStoreInner {
|
||||
pub(crate) fn new(local_path: PathBuf) -> Self {
|
||||
let env_hostname = std::env::var("STALWART_HOSTNAME")
|
||||
let env_hostname = types::branding::env_var("HOSTNAME")
|
||||
.ok()
|
||||
.filter(|h| !h.is_empty())
|
||||
.unwrap_or_else(|| {
|
||||
@@ -35,30 +35,30 @@ impl RegistryStoreInner {
|
||||
store: Store::None,
|
||||
id_generator: SnowflakeIdGenerator::new(),
|
||||
node_id: 0,
|
||||
env_recovery_mode: std::env::var("STALWART_RECOVERY_MODE")
|
||||
env_recovery_mode: types::branding::env_var("RECOVERY_MODE")
|
||||
.ok()
|
||||
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
|
||||
.unwrap_or(false),
|
||||
env_recovery_admin: std::env::var("STALWART_RECOVERY_ADMIN")
|
||||
env_recovery_admin: types::branding::env_var("RECOVERY_ADMIN")
|
||||
.ok()
|
||||
.and_then(|v| {
|
||||
v.split_once(':')
|
||||
.map(|(a, p)| (a.trim().to_string(), p.trim().to_string()))
|
||||
})
|
||||
.filter(|(a, p)| !a.is_empty() && !p.is_empty()),
|
||||
env_cluster_role: std::env::var("STALWART_ROLE")
|
||||
env_cluster_role: types::branding::env_var("ROLE")
|
||||
.ok()
|
||||
.filter(|r| !r.is_empty()),
|
||||
env_push_shard_id: std::env::var("STALWART_PUSH_SHARD")
|
||||
env_push_shard_id: types::branding::env_var("PUSH_SHARD")
|
||||
.ok()
|
||||
.and_then(|id| id.parse::<u32>().ok().and_then(|v| v.checked_sub(1)))
|
||||
.unwrap_or(0),
|
||||
env_public_url: std::env::var("STALWART_PUBLIC_URL")
|
||||
env_public_url: types::branding::env_var("PUBLIC_URL")
|
||||
.ok()
|
||||
.map(|v| v.trim().trim_end_matches('/').to_string())
|
||||
.filter(|u| !u.is_empty())
|
||||
.or_else(|| {
|
||||
std::env::var("STALWART_HTTPS_PORT").ok().and_then(|p| {
|
||||
types::branding::env_var("HTTPS_PORT").ok().and_then(|p| {
|
||||
p.parse::<u16>()
|
||||
.ok()
|
||||
.map(|port| format!("https://{}:{}", env_hostname, port))
|
||||
|
||||
@@ -45,3 +45,22 @@ macro_rules! brand_url {
|
||||
"https://inbuxa.org"
|
||||
};
|
||||
}
|
||||
|
||||
/// Reads one of the server's environment variables by its unprefixed name,
|
||||
/// such as `RECOVERY_ADMIN`.
|
||||
///
|
||||
/// `INBUXA_<name>` wins. `STALWART_<name>` is still read when the new name
|
||||
/// isn't set, so an existing Stalwart install moves over without editing its
|
||||
/// environment, and a warning says which variable to rename.
|
||||
pub fn env_var(name: &str) -> Result<String, std::env::VarError> {
|
||||
match std::env::var(format!("INBUXA_{name}")) {
|
||||
Err(std::env::VarError::NotPresent) => {
|
||||
let legacy = std::env::var(format!("STALWART_{name}"));
|
||||
if legacy.is_ok() {
|
||||
eprintln!("Warning: STALWART_{name} is deprecated; set INBUXA_{name} instead.");
|
||||
}
|
||||
legacy
|
||||
}
|
||||
found => found,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ pub fn build_http_client(
|
||||
allow_invalid_certs: bool,
|
||||
) -> Result<Client, String> {
|
||||
let mut headers = build_http_headers(raw_headers, username, password, token, content_type)?;
|
||||
headers.insert(USER_AGENT, "Stalwart/1.0.0".parse().unwrap());
|
||||
headers.insert(USER_AGENT, "INBUXA/1.0.0".parse().unwrap()); // types::brand!(); utils does not depend on types
|
||||
|
||||
match http_client_builder(allow_invalid_certs)
|
||||
.connect_timeout(timeout)
|
||||
|
||||
Reference in New Issue
Block a user