This commit is contained in:
Mateusz Gruszczyński committed 2026-10-19 11:09:48 +02:00
1 parent 4afa88a65e
commit 2ab44c4c62
49 files changed
+1523 -176

No files matched your search

+15
View File
@@ -2,6 +2,7 @@ async fn run(
data_dir: PathBuf,
startup_admin_addr: SocketAddr,
options: ServeOptions,
file_config: Option<PathBuf>,
startup_locks: rust_proxy::settings::StartupLocks,
update_check: rust_proxy::update_check::Config,
) -> Result<()> {
@@ -74,7 +75,15 @@ async fn run(
};
let store = Store::open(&data_dir.join("config.sqlite3"), &initial).await?;
let mut saved = store.load().await?;
let external = if let Some(path) = file_config {
Some((path.clone(), rust_proxy::runtime::external_config::read(&path)?))
} else { None };
let saved_revision = saved.revision;
let stored_document = serde_json::to_value(&saved.config)?;
if let Some((_, (config, _))) = &external { saved.config = config.clone(); }
startup_locks.ensure_config(&mut saved.config);
let changed_on_disk = external.is_some() && serde_json::to_value(&saved.config)? != stored_document;
if changed_on_disk { saved.revision = saved.revision.checked_add(1).context("revision overflow")?; }
startup_locks
.validate(&saved.config, startup_admin_addr)
.context("stored configuration conflicts with a listener fixed by systemd/startup")?;
@@ -129,6 +138,10 @@ async fn run(
})
.await?
.context("stored configuration is invalid; no automatic reset was performed")?;
if changed_on_disk {
ensure!(store.replace_as(saved_revision, &snapshot.envelope.config, "file-startup").await?,
"configuration history changed while loading --config");
}
rust_proxy::logging::configure_error_log(snapshot.envelope.config.error_log.clone());
let admin_tls_config = {
let tls = snapshot.envelope.config.tls.clone();
@@ -166,6 +179,8 @@ async fn run(
startup_locks,
geoip,
);
if let Some((path, (_, hash))) = external { state.set_config_file(path, hash).await; }
state.prometheus_token_hash.store(store.prometheus_token_hash().await?.map(Arc::new));
state.acme.restore_renewals(renewal_observations);
// Bind EVERY listener before spawning servers: a missing private IP or
// occupied port fails startup atomically, never falling back to 0.0.0.0.
+9
View File
@@ -51,6 +51,9 @@ struct Cli {
default_value = "/var/lib/rustproxy"
)]
data_dir: PathBuf,
/// Use an existing JSON file as canonical desired configuration.
#[arg(long, global = true, env = "RUST_PROXY_CONFIG")]
config: Option<PathBuf>,
#[arg(
long,
global = true,
@@ -78,6 +81,8 @@ struct Cli {
enum Command {
/// Start proxy and local administration listener.
Serve(ServeOptions),
/// Soft reload configuration and certificate files in the running service.
Reload,
/// Compatibility alias for `admin setup-token`; never an API access token.
Token,
/// Local administrator setup, password recovery and session management.
@@ -349,6 +354,9 @@ async fn application() -> Result<()> {
.command
.context("a subcommand is required (or use --livelogs)")?;
match command {
Command::Reload => {
config_command(resolve_installed_data_dir(cli.data_dir, data_dir_explicit), cli.admin_listen, ConfigCommand::Reload).await
}
Command::Token => {
admin_command(
resolve_installed_data_dir(cli.data_dir, data_dir_explicit),
@@ -398,6 +406,7 @@ async fn application() -> Result<()> {
cli.data_dir,
cli.admin_listen,
options,
cli.config,
startup_locks,
update_check,
)
+2 -2
View File
@@ -86,8 +86,8 @@ async fn config_command(dir: PathBuf, addr: SocketAddr, action: ConfigCommand) -
match action {
ConfigCommand::Get => println!("{}", serde_json::to_string_pretty(&current.config)?),
ConfigCommand::Reload => {
let body = serde_json::json!({"expected_revision":current.revision,"config":current.config}).to_string();
let updated: Envelope = serde_json::from_str(&api(&admin, &session, Method::PUT, "/api/config", Some(body)).await?)?;
let body = serde_json::json!({"expected_revision":current.revision}).to_string();
let updated: Envelope = serde_json::from_str(&api(&admin, &session, Method::POST, "/api/config/reload", Some(body)).await?)?;
println!("Reloaded configuration and certificates at revision {}.", updated.revision);
},
ConfigCommand::Apply { file } => {