# Runic Gateway installer A single-binary deployment tool that takes a **stock ServUO installation** and configures it for Runic Gateway: deploys the shard plugin overlay, optionally applies the stock-file patch tier, installs the uo-link sidecar and registers it as a service, records what it deployed, and hands the operator the four values that connect the website to the shard. ``` ┌──────────────────────────────────────────┐ │ Runic Gateway installer (>>> HERE <<<)│ └───────────────┬──────────────────────────┘ │ deploys ┌───────────────┴────────────────┐ ▼ ▼ ServUO integration uo-link sidecar overlay sync + opt-in patch tier binary + config + service (RunicGateway/servuo-plugins) (RunicGateway/link) ``` It is a **deployment tool, not a hosted bootstrapper** — no `curl | bash`, no installer service. Artifacts are downloaded from a Gitea release page and run. It also **does not replace ServUO startup behavior.** ServUO keeps running through its existing release/start scripts; the installer never writes a launcher and never restarts the shard. ## Status **Phase 1 (installer core) is built, on the `edge` branch. Nothing is released yet.** The design of record is [`installer/PLAN.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/installer/PLAN.md) in the docs repo: phases, locked decisions, and the Phase 0 prerequisites in other repos (a `servuo-plugins` release workflow, a non-interactive config read-back in `link`, and the bundle-manifest CI here), all of which have landed — [`bundles/current.json`](bundles/current.json) names the current protocol-checked sidecar + overlay combination, recomposed on every component release and nightly (see [`bundles/README.md`](bundles/README.md)). | Phase | State | |---|---| | 0 — prerequisites in the other repos | ✅ merged | | 1 — installer core: bundle resolution, ServUO detection, overlay sync, `install.json` | ✅ on `edge` | | 2 — uo-link install + service registration | next | | 3 — the opt-in stock-file patch tier | | | 4 — `doctor`, `update`, `uninstall` | | **Why `edge`:** `release.yml` publishes an installer binary on every push to `main`, and a binary that deploys the overlay but cannot yet install the sidecar is not something to hand an operator. Phases 1 and 2 land on `edge`; the `edge → main` cutover cuts the first release. PRs into `edge` run the same gates as PRs into `main`. Until then, the way to install is by hand — [INSTALL.md Appendix A](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/installer/INSTALL.md#appendix-a--installing-by-hand) is the same deployment done with `curl`, `tar` and `systemctl`. ## Related repos | Repo | What | |------|------| | **this** — `RunicGateway/installer` | The installer (Rust, one binary per OS). | | [RunicGateway/link](https://gitea.whitlocktech.com/RunicGateway/link) | The **uo-link sidecar** — the network-facing half of the game bridge. Installed and service-registered by this tool. | | [RunicGateway/servuo-plugins](https://gitea.whitlocktech.com/RunicGateway/servuo-plugins) | The **C# ServUO plugin** — deployed as source (`overlay/`) and compiled by ServUO at boot. Synced into the server tree by this tool. | | [RunicGateway/website](https://gitea.whitlocktech.com/RunicGateway/website) | The public site and admin panel. The installer never contacts it — it prints values for Admin → Shard. | | [RunicGateway/docs](https://gitea.whitlocktech.com/RunicGateway/docs) | All project documentation, including the installer plan. | ## Planned commands | Command | What it does | |---|---| | `install` | Detect and validate the ServUO root, sync the overlay, optionally apply patches, install uo-link + service, write `install.json`, print the token handoff. | | `doctor` | Diagnose an installed deployment end to end — through to *"has a shard actually dialed in?"*, the only check that distinguishes a working bridge from copied files. | | `update` | Resolve the current bundle manifest, then update the sidecar (replace + restart) and the overlay (re-sync + tell the operator to restart ServUO). | | `uninstall` | Remove only what the installer exclusively owns. It **never edits the ServUO tree** — it prints the overlay files to delete and the patch hunks to revert, and leaves that call to the operator. | ## Design constraints worth knowing up front - **Releases are unsigned.** `SHA256SUMS` is the trust anchor; SmartScreen and Gatekeeper warnings are expected and documented. The installer nonetheless verifies the SHA256 of everything *it* downloads and refuses on mismatch. - **Composition comes from a published bundle manifest**, not from "latest of each". CI names an exact, protocol-checked combination of sidecar and overlay versions; `--bundle ` pins one for a reproducible install. A new component release regenerates JSON, not this binary. - **The base install must complete without the patch tier.** The patch tier edits stock ServUO files, most real shards are hand-modified, and unverified ServUO versions skip it with a warning rather than being patched blind. - **A successful copy is not a working bridge.** ServUO ignores the script build's exit code and silently reloads the previous `Scripts.dll`, so diagnostics verify post-boot state rather than trusting a clean boot. - **The audience is public** — any ServUO operator, not only shards we run. ## Build & run A standard cargo project, with the crate at the repo root: ```bash cargo build --release cargo run -- --help cargo run -- install --servuo /path/to/ServUO --verify # dry run: writes nothing cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo test ``` `RUNICGATEWAY_STATE_DIR` relocates `install.json` (normally `/etc/runicgateway` or `%ProgramData%\RunicGateway`), which is how a run is tested without root. Two layout notes that look odd until you know why: - **The library target is `rgdeploy`, not `runicgateway_installer`.** Windows' UAC installer detection refuses to launch an unsigned executable whose file name contains `install` (`os error 740`), and Cargo names test harnesses after their target — so a target under that name makes `cargo test` unrunnable on Windows. The published binary keeps its documented name; `[[bin]] test = false` keeps Cargo from building a harness under it. Expect a UAC prompt when running the built binary on Windows; it needs Administrator anyway. - **`Cargo.lock` is committed**, and CI builds `--locked`. See [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup, the local checks CI will run, and the branch/PR workflow. --- ## License Runic Gateway is free software, licensed under the **GNU General Public License v3.0 or later** — see [LICENSE.md](LICENSE.md). Copyright (C) 2026 Runic Gateway This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Contributions are welcome — please read [CONTRIBUTING.md](CONTRIBUTING.md) (note the **AI-usage disclosure** requirement) and our [Code of Conduct](CODE_OF_CONDUCT.md). Report vulnerabilities privately per [SECURITY.md](SECURITY.md).