This repository has been archived on 2026-10-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
maestro/docs/INSTALL.md
T
naps62-yolo 3b6dd50c1d
ci / rust (push) Successful in 4m36s
fix(maestro): maestro-web is now a proxy, not a local registry (NAP-231)
Earlier today I picked option 1 from NAP-231's open question (run
`maestro-registry` locally on a different port). That was wrong: the
user-facing framing is "local web UI", and option 2 — a thin front-end
that serves the web bundle and reverse-proxies `/api/*` to whatever
registry the daemon is already registered with — is what actually
delivers that.

What the new crate does:

- `crates/maestro-web` ships a single binary `maestro-web`.
- It embeds the web bundle the same way `maestro-registry` does
  (rust-embed against `web/dist/`).
- Mounts the bundle at `/` and a reverse proxy at `/api/*` (catch-all).
- HTTP proxy via `reqwest` — forwards method, headers (minus
  hop-by-hop), body, and passes upstream response headers (including
  `Set-Cookie`) back to the browser.
- WS proxy upgrades both sides and shuttles frames with
  `tokio::select!`. Cookies on the initial `WebSocket` upgrade headers
  are forwarded so the registry sees the same browser session.
- Reads `MAESTRO_REGISTRY` (upstream URL) and `MAESTRO_WEB_BIND_ADDR`
  (default `127.0.0.1:8888`) from env.
- An integration test (`tests/proxy.rs`) stands up a mock upstream,
  proxies an HTTP request with cookies through, and round-trips a text
  WebSocket frame to verify the WS path.

Installer changes:

- Wizard now `cargo install`s `maestro-web` (not `maestro-registry`)
  when the user opts into the web service.
- Unit template switched: `ExecStart=%h/.cargo/bin/maestro-web` plus
  `Environment=MAESTRO_REGISTRY=<upstream>` +
  `Environment=MAESTRO_WEB_BIND_ADDR=<bind>`.
- New `--web-registry <URL>` flag. Default in interactive mode: read
  `registry_url` straight out of `~/.config/maestrod/config.toml`, so
  the proxy lines up with what the daemon is using without further
  prompting. Non-interactive runs without either of those error out
  rather than guess.

Docs:

- `docs/INSTALL.md` updated unit body + flag table.
- `CLAUDE.md` repo-layout block now lists `maestro-web`.

148 tests pass workspace-wide (9 new in maestro-web, including the
proxy integration test; 15 in installer).
2026-05-26 08:59:27 +00:00

5.7 KiB

Installing Maestro

The repo is private, so grab install.sh while signed in to gitea, then run it:

  1. Open https://git.naps.pt/naps62/maestro/src/branch/main/install.sh, click Raw, save as install.sh. Or from any existing clone:
    git show origin/main:install.sh > install.sh
    
  2. Run it:
    chmod +x install.sh && ./install.sh
    

The bootstrap script builds maestro-installer into a temp directory, runs the 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.

Inside the script, cargo install --git https://git.naps.pt/naps62/maestro … uses your already-configured git credentials for this host (HTTPS helper or SSH agent). If only SSH is set up:

MAESTRO_REPO_URL=ssh://git@git.naps.pt/naps62/maestro ./install.sh

Pass flags through to the wizard after ./install.sh:

./install.sh --yes --no-systemd

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.
  3. On systemd hosts, optionally writes a user unit at ~/.config/systemd/user/maestrod.service, reloads systemd, and offers to enable + start it.
  4. On systemd hosts, also offers a local web UI unit (~/.config/systemd/user/maestro-web.service). When accepted, this also cargo installs maestro-web — a thin front-end that serves the bundled UI on 127.0.0.1:8888 (override with --web-bind) and reverse-proxies /api to your existing registry. Skip with --no-web (or answer "n"); you can always just open the registry's own URL in a browser instead.

Binaries land in ~/.cargo/bin — make sure that's on your $PATH.

Flags

Flag Purpose
--git <url> Install from a different git repo (default: this one).
--branch <name> Pin a branch with --git.
--path <dir> Install from a local workspace checkout (--path + -p <crate>).
--no-locked Drop --locked from cargo install (resolves a fresh dep tree).
--exec-start <path> Override the systemd unit's ExecStart (default ~/.cargo/bin/maestrod).
--no-systemd Skip the systemd step even if detected.
--no-configure Skip the maestrod configure step.
--no-web Skip the optional local web-UI unit + maestro-web install.
--web-bind <addr> Loopback bind for the web UI (default 127.0.0.1:8888).
--web-registry <url> Upstream registry the proxy forwards /api to (default: read from ~/.config/maestrod/config.toml).
--web-exec-start <path> Override the web unit's ExecStart (default ~/.cargo/bin/maestro-web).
-y, --yes Non-interactive: install binaries + drop systemd unit + reload + enable, but don't auto-run configure or auto-start the unit (those need real config).

What the systemd unit looks like

The wizard writes a user unit (systemctl --user), since maestrod runs per-user and uses tmux sockets under $XDG_RUNTIME_DIR. Body:

[Unit]
Description=Maestro per-host daemon (maestrod)
Documentation=https://git.naps.pt/naps62/maestro
After=network-online.target

[Service]
Type=simple
ExecStart=%h/.cargo/bin/maestrod
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target

Check status / logs:

systemctl --user status maestrod
journalctl --user -u maestrod -f

The optional maestro-web.service runs a thin front-end that serves the embedded web bundle and reverse-proxies /api (HTTP + WS) to a configured upstream registry — so you can hit the UI on localhost while the daemon keeps talking to whichever registry it was registered with:

[Unit]
Description=Maestro local web UI (maestro-web on 127.0.0.1:8888, proxying https://maestro-registry.example.com)
Documentation=https://git.naps.pt/naps62/maestro
After=network-online.target maestrod.service
Wants=maestrod.service

[Service]
Type=simple
Environment=MAESTRO_WEB_BIND_ADDR=127.0.0.1:8888
Environment=MAESTRO_REGISTRY=https://maestro-registry.example.com
ExecStart=%h/.cargo/bin/maestro-web
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target

Wants=maestrod.service (not Requires=) — maestro-web is just a proxy to the upstream registry; locally it doesn't depend on maestrod to start. But the UI has nothing to show without a daemon connected, so we order this after maestrod and politely encourage it.

The wizard fills in MAESTRO_REGISTRY from the daemon's ~/.config/maestrod/config.toml automatically; override with --web-registry <URL>.

Running the wizard without the bootstrap script

If you'd rather skip the script:

cargo install --git https://git.naps.pt/naps62/maestro maestro-installer
maestro-install

This leaves maestro-installer permanently in ~/.cargo/bin — the bootstrap script avoids that by installing to a scratch dir.

Fully manual install (no wizard)

cargo install --git https://git.naps.pt/naps62/maestro --locked maestro-daemon
cargo install --git https://git.naps.pt/naps62/maestro --locked maestro-cli
maestrod configure
maestrod          # foreground; or wire your own service manager

Non-Linux hosts

The wizard works on macOS for the cargo install + maestrod configure parts. The systemd step is automatically skipped (probe of /run/systemd/system). launchd integration is not yet supported — start maestrod from your shell or your own service manager.