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

160 lines
5.7 KiB
Markdown

# 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:
```sh
git show origin/main:install.sh > install.sh
```
2. Run it:
```sh
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:
```sh
MAESTRO_REPO_URL=ssh://git@git.naps.pt/naps62/maestro ./install.sh
```
Pass flags through to the wizard after `./install.sh`:
```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 install`s `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:
```ini
[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:
```sh
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:
```ini
[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:
```sh
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)
```sh
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.