servuo-plugins hit both of these on its first real release run; this repo runs the same engine, so it has the same two defects latent. REGISTRY_USER / REGISTRY_TOKEN were empty there, yet the tag push SUCCEEDED: actions/checkout leaves an `http.<host>.extraheader` credential in the local git config, so `git remote set-url` to a URL with empty credentials still authenticated through that leftover header. The release API call had no such fallback and returned 401. Net result was the worst available outcome — the repo tagged, no release, and a failed job. Two fixes: A credential preflight, before anything is built or pushed, gated on the run actually intending to publish so a docs:/chore:-only merge (or this repo's pre-crate no-op) still passes on a repo with no secrets. It names the missing secrets and the scope they need instead of failing wherever they happen to be used first. Orphan-tag recovery. A tag with no release behind it means an earlier run died after tagging, and the old code treated any existing tag as "nothing to release" — so that state could never clear itself: every later run would see the tag and stand down, forever. The plan step now asks the API whether a release exists for the tag, and on 404 reuses the tag and publishes the release it is missing. This deliberately overrides the RELEASE=false the bump logic just decided, which is the whole point — with the tag in place there are no releasable commits after it. Anything other than 200/404 (network failure, bad token) is refused rather than guessed, since assuming "no release" would republish over a good one. The tag step now reuses an existing tag instead of failing on `git tag`, and the changelog for a recovery run summarizes what the tag contains (previous-tag..this-tag) rather than the empty range after it. sync-project-tree gets the same preflight: its first run on main failed with an opaque `git clone` error against `https://:@host/...` that said nothing about a missing secret. Verified by extracting every run block and exercising the paths: empty secrets fail the preflight with a legible message and populated ones pass; the no-Cargo.toml guard still short-circuits to release=false; a crate with no tag still takes the seed path; and against real repo state, a tag with a release stands down while an orphan tag recovers. 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
Planning — no installer code exists 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) that must land before Phase 1 is useful.
This repo currently holds its governance documents and issue/PR templates.
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
Once the crate exists it will be a standard cargo project:
cargo build --release
cargo run -- --help
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.