Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ clickhousectl local server start --name dev # Named "dev"
clickhousectl local server start --version stable # Use a specific version (installs if needed, doesn't change default)
clickhousectl local server start --foreground # Run in foreground (-F / --fg)
clickhousectl local server start --http-port 8124 --tcp-port 9001 # Explicit ports
clickhousectl local server start --config-file analytics # Apply a custom config (see "Custom config files" below)
clickhousectl local server start --config analytics # Apply a custom config (see "Custom config files" below)

# List custom config files available to --config-file
# List custom config files available to --config
clickhousectl local server configs

# List all servers (running and stopped)
Expand Down Expand Up @@ -217,12 +217,12 @@ cat > ~/.clickhouse/configs/analytics.xml <<'EOF'
</clickhouse>
EOF
clickhousectl local server configs # List available config files
clickhousectl local server start --config-file analytics # Start a server with it
clickhousectl local server start --config analytics # Start a server with it
```

The named file is **overlaid on top of ClickHouse's built-in defaults** (it is staged into the server's `config.d/` directory), so it only needs to contain the settings you want to change — you don't have to reproduce a full config. Files may be `.xml`, `.yaml`, or `.yml`; reference them by name with or without the extension (e.g. `--config-file analytics` or `--config-file analytics.xml`). `--config-file` takes a name within `~/.clickhouse/configs/` **not a path**.
The named file is **overlaid on top of ClickHouse's built-in defaults** (it is staged into the server's `config.d/` directory), so it only needs to contain the settings you want to change — you don't have to reproduce a full config. Files may be `.xml`, `.yaml`, or `.yml`; reference them by name with or without the extension (e.g. `--config analytics` or `--config analytics.xml`). `--config` takes a name within `~/.clickhouse/configs/` **not a path**. (`--config-file` remains supported as a legacy alias.)

The managed data directory (`.clickhouse/servers/<name>/data/`) and the HTTP/TCP ports are always forced as command-line overrides, which take precedence over the config file. This means a custom config can never break the managed server lifecycle (`list`, `stop`, `remove`, `dotenv`) regardless of its contents. Starting a server again without `--config-file` reverts it to plain defaults.
The managed data directory (`.clickhouse/servers/<name>/data/`) and the HTTP/TCP ports are always forced as command-line overrides, which take precedence over the config file. This means a custom config can never break the managed server lifecycle (`list`, `stop`, `remove`, `dotenv`) regardless of its contents. Starting a server again without `--config` reverts it to plain defaults.

#### Local Postgres (Docker-backed)

Expand Down
23 changes: 17 additions & 6 deletions crates/clickhousectl/src/local/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ CONTEXT FOR AGENTS:
Runs in background by default. Use --foreground (-F / --fg) to run in foreground.
If --name is given and that server is already running, the command will error.
Shows count of already-running servers before starting.
Use --config-file <NAME> to apply a custom ClickHouse config file from ~/.clickhouse/configs/
Use --config <NAME> to apply a custom ClickHouse config file from ~/.clickhouse/configs/
(see `clickhousectl local server configs`). The file is merged as an overlay on top of
ClickHouse's built-in defaults (via config.d), so it can contain just the settings you want
to change (e.g. <query_log>). The data directory and ports stay managed regardless of the
Expand Down Expand Up @@ -200,24 +200,24 @@ CONTEXT FOR AGENTS:
foreground: bool,

/// Overlay a named config file from ~/.clickhouse/configs/ on top of the defaults (see `server configs`)
#[arg(long, value_name = "NAME")]
#[arg(long = "config", alias = "config-file", value_name = "NAME")]
config_file: Option<String>,

/// Arguments to pass to clickhouse-server
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},

/// List custom config files available to `server start --config-file`
/// List custom config files available to `server start --config`
#[command(after_help = "\
CONTEXT FOR AGENTS:
Lists ClickHouse config files in ~/.clickhouse/configs/ and prints that directory's path.
Drop a config file there (e.g. analytics.xml) and start a server with it via
`clickhousectl local server start --config-file analytics`. The file is overlaid on top of
`clickhousectl local server start --config analytics`. The file is overlaid on top of
ClickHouse's built-in defaults (config.d merge), so it only needs the settings you want to
change. Files may be .xml, .yaml, or .yml; reference them by name with or without the
extension.
Related: `clickhousectl local server start --config-file <NAME>`.")]
Related: `clickhousectl local server start --config <NAME>`.")]
Configs,

/// List all server instances (running and stopped)
Expand Down Expand Up @@ -480,7 +480,18 @@ mod tests {
}

#[test]
fn parses_server_start_config_file() {
fn parses_server_start_config() {
let LocalCommands::Server {
command: ServerCommands::Start { config_file, .. },
} = local_command(&["server", "start", "--config", "analytics"])
else {
panic!("expected server start");
};
assert_eq!(config_file.as_deref(), Some("analytics"));
}

#[test]
fn parses_server_start_config_file_legacy_alias() {
let LocalCommands::Server {
command: ServerCommands::Start { config_file, .. },
} = local_command(&["server", "start", "--config-file", "analytics"])
Expand Down
4 changes: 2 additions & 2 deletions crates/clickhousectl/src/local/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Resolution and listing of custom server config files.
//!
//! Users drop named ClickHouse config files into `~/.clickhouse/configs/` and
//! reference them by name with `clickhousectl local server start --config-file
//! reference them by name with `clickhousectl local server start --config
//! <NAME>`. The file is passed to ClickHouse as `--config-file`; the launcher
//! still forces `--path=./` and the ports as command-line overrides (which beat
//! config-file values), so the managed server lifecycle is preserved regardless
Expand Down Expand Up @@ -140,7 +140,7 @@ pub fn list_configs() -> Result<Vec<String>> {
/// directory with its built-in defaults, so a partial override file takes
/// effect without replacing the whole config. We own a single file there named
/// `chctl-config.<ext>`; any previously staged overlay (in any recognized
/// extension) is removed first, so restarting a server without `--config-file`
/// extension) is removed first, so restarting a server without `--config`
/// reverts cleanly to plain defaults.
pub fn apply_config_overlay(data_dir: &Path, source: Option<&Path>) -> Result<()> {
let config_d = data_dir.join("config.d");
Expand Down
13 changes: 7 additions & 6 deletions crates/clickhousectl/src/local/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,19 +346,20 @@ async fn start_server(
http_port, tcp_port
);
}
// Reject --config-file / -C in passthrough args. Passing a raw config path
// here would bypass the managed `--config-file` handling below and could
// redirect where ClickHouse stores data, breaking the managed server
// Reject --config / --config-file / -C in passthrough args. Passing a raw
// config path here would bypass the managed `--config` handling below and
// could redirect where ClickHouse stores data, breaking the managed server
// lifecycle (list, stop, remove, dotenv all rely on the data directory
// living under .clickhouse/servers/<name>/). Individual --setting=value
// flags are fine — they don't change the data directory.
// `--config` also matches `--config-file` as a prefix.
if args
.iter()
.any(|a| a.starts_with("--config-file") || a.starts_with("-C"))
.any(|a| a.starts_with("--config") || a.starts_with("-C"))
{
return Err(Error::Exec(
"--config-file / -C cannot be passed through in trailing args. \
Use `--config-file <NAME>` with a file in ~/.clickhouse/configs/ \
"--config / --config-file / -C cannot be passed through in trailing args. \
Use `--config <NAME>` with a file in ~/.clickhouse/configs/ \
(see `clickhousectl local server configs`). \
Individual --setting=value flags are supported."
.into(),
Expand Down
6 changes: 3 additions & 3 deletions crates/clickhousectl/src/local/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ impl fmt::Display for ServerConfigsOutput {
write!(
f,
"Drop a ClickHouse config file there, then start with: \
clickhousectl local server start --config-file <NAME>"
clickhousectl local server start --config <NAME>"
)?;
return Ok(());
}
Expand All @@ -198,7 +198,7 @@ impl fmt::Display for ServerConfigsOutput {
}
write!(
f,
"Use with: clickhousectl local server start --config-file <NAME>"
"Use with: clickhousectl local server start --config <NAME>"
)
}
}
Expand Down Expand Up @@ -859,7 +859,7 @@ mod tests {
};
let text = output.to_string();
assert!(text.contains("No config files"));
assert!(text.contains("--config-file"));
assert!(text.contains("--config <NAME>"));
}

#[test]
Expand Down