The two descending sorts in the applier used an explicit comparator. CI runs clippy 1.97, where `unnecessary_sort_by` flags that and `-D warnings` turns it into a build failure; the local toolchain here is 1.94, which does not have the lint. `sort_by_key` with `Reverse` says the same thing. Co-Authored-By: Claude <noreply@anthropic.com>
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
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 names the current protocol-checked
sidecar + overlay combination, recomposed on every component release and nightly
(see 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
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 | The uo-link sidecar — the network-facing half of the game bridge. Installed and service-registered by this tool. |
| 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 | The public site and admin panel. The installer never contacts it — it prints values for Admin → Shard. |
| 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.
SHA256SUMSis 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 <tag>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:
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, notrunicgateway_installer. Windows' UAC installer detection refuses to launch an unsigned executable whose file name containsinstall(os error 740), and Cargo names test harnesses after their target — so a target under that name makescargo testunrunnable on Windows. The published binary keeps its documented name;[[bin]] test = falsekeeps Cargo from building a harness under it. Expect a UAC prompt when running the built binary on Windows; it needs Administrator anyway. Cargo.lockis committed, and CI builds--locked.
See 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.
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 (note the AI-usage disclosure requirement) and our Code of Conduct. Report vulnerabilities privately per SECURITY.md.