docs(maestro): unified-config rollover in installer + INSTALL + spec (NAP-233)
- Installer: check for a `[daemon]` section in the unified file (rather than the existence of the now-defunct `~/.config/maestrod/config.toml`) to decide whether to skip the configure prompt on re-runs. The configure prompt + maestrod_config_path() helper now reference `~/.config/maestro/config.toml`. - docs/INSTALL.md: mention the unified file and the single-TOML shape. - spec: update §Registry / §Daemon / §Auth to call out `[registry].bind_addr`, `[daemon].bind_addr`, `[shared].registry_url`, and `[shared].token` instead of the old per-app files.
This commit is contained in:
@@ -96,14 +96,15 @@ fn run(args: Args) -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// 2. Offer to run `maestrod configure` now (must happen before systemd
|
||||
// start, since the daemon refuses to run without registry_url / token).
|
||||
// Re-runs of the wizard auto-skip when the config already exists; that's
|
||||
// what makes "re-run to update" pleasant. In non-interactive mode (--yes /
|
||||
// no TTY) we also skip — `maestrod configure` would prompt for required
|
||||
// fields and we don't want to surprise scripts.
|
||||
let configured = if let Some(path) = maestrod_config_path() {
|
||||
if path.exists() {
|
||||
// Re-runs of the wizard auto-skip when the unified config already has a
|
||||
// [daemon] section; that's what makes "re-run to update" pleasant. In
|
||||
// non-interactive mode (--yes / no TTY) we also skip — `maestrod
|
||||
// configure` would prompt for required fields and we don't want to
|
||||
// surprise scripts.
|
||||
let configured = if let Some(path) = maestro_config_path() {
|
||||
if daemon_section_present(&path) {
|
||||
eprintln!(
|
||||
"\nconfig already exists at {} — skipping configure step.",
|
||||
"\n[daemon] section already present in {} — skipping configure step.",
|
||||
path.display()
|
||||
);
|
||||
eprintln!("(run `maestrod configure --force` to rewrite it.)");
|
||||
@@ -175,15 +176,28 @@ fn install_crate(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn maestrod_config_path() -> Option<PathBuf> {
|
||||
Some(dirs::config_dir()?.join("maestrod").join("config.toml"))
|
||||
fn maestro_config_path() -> Option<PathBuf> {
|
||||
Some(dirs::config_dir()?.join("maestro").join("config.toml"))
|
||||
}
|
||||
|
||||
/// True iff the unified file exists and already has a `[daemon]` section.
|
||||
/// Used to skip the configure prompt on re-runs without forcing the user
|
||||
/// to manually delete a co-located `[registry]` / `[cli]` section first.
|
||||
fn daemon_section_present(path: &Path) -> bool {
|
||||
if !path.exists() {
|
||||
return false;
|
||||
}
|
||||
let Ok(body) = std::fs::read_to_string(path) else {
|
||||
return false;
|
||||
};
|
||||
body.lines().any(|l| l.trim_start().starts_with("[daemon]"))
|
||||
}
|
||||
|
||||
fn run_configure_step(args: &Args, interactive: bool) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
let want = interactive
|
||||
&& !args.no_configure
|
||||
&& confirm(
|
||||
"Run `maestrod configure` now (writes ~/.config/maestrod/config.toml)?",
|
||||
"Run `maestrod configure` now (writes ~/.config/maestro/config.toml)?",
|
||||
true,
|
||||
)?;
|
||||
if want {
|
||||
|
||||
+6
-4
@@ -17,9 +17,10 @@ wizard, and cleans up — only `maestrod` and `maestro` end up persisted in
|
||||
`~/.cargo/bin`.
|
||||
|
||||
**Updating is the same command.** Re-running `./install.sh` detects an
|
||||
existing `~/.config/maestrod/config.toml` and existing systemd unit, skips the
|
||||
configure prompt, refreshes the unit, and runs `systemctl --user restart
|
||||
maestrod` instead of `start`. No `--update` flag needed.
|
||||
existing `[daemon]` section in `~/.config/maestro/config.toml` and an
|
||||
existing systemd unit, skips the configure prompt, refreshes the unit, and
|
||||
runs `systemctl --user restart maestrod` instead of `start`. No `--update`
|
||||
flag needed.
|
||||
|
||||
Inside the script, `cargo install --git https://git.naps.pt/naps62/maestro …`
|
||||
uses your already-configured git credentials for this host (HTTPS helper or
|
||||
@@ -39,7 +40,8 @@ The wizard:
|
||||
|
||||
1. Runs `cargo install` for `maestro-daemon` and `maestro-cli` (pinned to the
|
||||
committed `Cargo.lock` via `--locked`).
|
||||
2. Optionally runs `maestrod configure` to drop a `~/.config/maestrod/config.toml`.
|
||||
2. Optionally runs `maestrod configure` to populate `~/.config/maestro/config.toml`
|
||||
(one shared TOML for `maestrod`, `maestro-registry`, and the `maestro` CLI).
|
||||
3. On systemd hosts, optionally writes a user unit at
|
||||
`~/.config/systemd/user/maestrod.service`, reloads systemd, and offers to
|
||||
enable + start it.
|
||||
|
||||
@@ -83,7 +83,7 @@ Non-responsibilities:
|
||||
- No persistent storage in the prototype. State is in-memory; daemons re-register on reconnect.
|
||||
- No multi-user model. One shared secret, one effective user.
|
||||
|
||||
Runs as a single Rust binary on a designated VM. Listens on a configured `bind_addr` (default `127.0.0.1:8080`; operator sets the actual reachable address — e.g. a Wireguard interface IP — in `~/.config/maestro/registry.toml`).
|
||||
Runs as a single Rust binary on a designated VM. Listens on a configured `bind_addr` (default `127.0.0.1:8080`; operator sets the actual reachable address — e.g. a Wireguard interface IP — in `[registry].bind_addr` of the unified config at `~/.config/maestro/config.toml`).
|
||||
|
||||
### Daemon (`maestrod`)
|
||||
|
||||
@@ -101,7 +101,7 @@ Non-responsibilities:
|
||||
- Doesn't relay to other daemons. It only knows about local tmux.
|
||||
- Doesn't manage its own auth tokens; the registry issues them.
|
||||
|
||||
Runs as a single Rust binary on every host that holds sessions. Small footprint matters because some hosts are LXC containers. Listens on a configured `bind_addr` (default `127.0.0.1:8081`; operator sets the actual reachable address in `~/.config/maestrod/config.toml`). Also requires `registry_url` so it knows where to register on startup.
|
||||
Runs as a single Rust binary on every host that holds sessions. Small footprint matters because some hosts are LXC containers. Listens on a configured `bind_addr` (default `127.0.0.1:8081`; operator sets the actual reachable address in `[daemon].bind_addr` of the unified config at `~/.config/maestro/config.toml`). Also requires `[shared].registry_url` so it knows where to register on startup.
|
||||
|
||||
### Web client
|
||||
|
||||
@@ -244,7 +244,7 @@ struct Session {
|
||||
|
||||
## Auth
|
||||
|
||||
- Registry generates `MAESTRO_TOKEN` at first run, printed once, stored in `~/.config/maestro/registry.toml`.
|
||||
- Registry generates the shared token at first run, printed once, stored as `[shared].token` in `~/.config/maestro/config.toml` (env var name: `MAESTRO_SHARED_TOKEN`).
|
||||
- Same token deployed to each daemon (config file or env var) and used in `Hello`.
|
||||
- Web client gets a cookie from the registry on first visit. All registry API calls use it.
|
||||
- Per-attach JWT issued by registry, signed with the shared secret, validated locally by the daemon. ~5 min expiry; client refreshes by re-requesting `GET /api/sessions/:id/connect-info`.
|
||||
|
||||
Reference in New Issue
Block a user