Merge pull request 'docs(installer): record Phase 2 as built — sidecar install and service' (#91) from docs/installer-phase2 into main
Reviewed-on: #91 Reviewed-by: Colby Whitlock <whitlocktech@gmail.com>
This commit is contained in:
@@ -5,10 +5,12 @@ installation and connects it to a Runic Gateway website.
|
|||||||
|
|
||||||
> **Status: the installer binary is not released yet.**
|
> **Status: the installer binary is not released yet.**
|
||||||
>
|
>
|
||||||
> Phase 1 — the installer core: bundle resolution, ServUO detection, the overlay sync and
|
> Phases 1 and 2 are built and live on the installer repo's `edge` branch: the installer core
|
||||||
> `install.json` — is built and lives on the installer repo's `edge` branch. It is deliberately not
|
> (bundle resolution, ServUO detection, the overlay sync, `install.json`) and the sidecar half (the
|
||||||
> released: a binary that deploys the overlay but cannot yet install the sidecar would not do what
|
> binary, its config, its service, and the token handoff). What is still missing is the **patch
|
||||||
> this guide describes. The first release follows Phase 2.
|
> tier** ([§4](#4-the-patch-tier-optional)), which `install` reports as not applied rather than
|
||||||
|
> silently skipping. The first release follows Phase 3, so that a released binary answers every
|
||||||
|
> question this guide says it answers.
|
||||||
>
|
>
|
||||||
> Everything it installs *is* released and published — the sidecar, the plugin overlay, and the
|
> Everything it installs *is* released and published — the sidecar, the plugin overlay, and the
|
||||||
> [bundle manifest](https://gitea.whitlocktech.com/RunicGateway/installer/src/branch/main/bundles/current.json)
|
> [bundle manifest](https://gitea.whitlocktech.com/RunicGateway/installer/src/branch/main/bundles/current.json)
|
||||||
@@ -176,11 +178,14 @@ Overlay sync
|
|||||||
Patch tier skipped (not selected)
|
Patch tier skipped (not selected)
|
||||||
Without it: no vendor.sale events, no in-game moderation audit forwarding.
|
Without it: no vendor.sale events, no in-game moderation audit forwarding.
|
||||||
|
|
||||||
uo-link
|
uo-link sidecar
|
||||||
binary /usr/bin/runicgateway-link
|
binary /usr/bin/runicgateway-link install
|
||||||
config /etc/runicgateway/sidecar.toml (created)
|
✓ sidecar binary verified sha256 27d491ef…
|
||||||
|
config /etc/runicgateway/sidecar.toml created
|
||||||
database /var/lib/runicgateway/uo-link.db
|
database /var/lib/runicgateway/uo-link.db
|
||||||
service runicgateway-link.service enabled, running
|
listening on shard 127.0.0.1:7788 website 127.0.0.1:8080
|
||||||
|
service runicgateway-link.service active, enabled
|
||||||
|
running as runicgateway
|
||||||
|
|
||||||
Recorded /etc/runicgateway/install.json
|
Recorded /etc/runicgateway/install.json
|
||||||
|
|
||||||
@@ -238,7 +243,7 @@ reports "unchanged" and writes nothing.
|
|||||||
| `%ProgramData%\RunicGateway\install.json` | As above |
|
| `%ProgramData%\RunicGateway\install.json` | As above |
|
||||||
| `%ProgramData%\RunicGateway\patches\` | As above |
|
| `%ProgramData%\RunicGateway\patches\` | As above |
|
||||||
| `%ProgramData%\RunicGateway\uo-link.db` | The sidecar's SQLite store |
|
| `%ProgramData%\RunicGateway\uo-link.db` | The sidecar's SQLite store |
|
||||||
| Service `RunicGatewayLink` | Automatic start, restart on failure |
|
| Service `RunicGatewayLink` | Automatic start, restart on failure, running as `NT SERVICE\RunicGatewayLink` |
|
||||||
|
|
||||||
**Inside your ServUO tree** (added by the overlay sync — 24 files):
|
**Inside your ServUO tree** (added by the overlay sync — 24 files):
|
||||||
|
|
||||||
@@ -248,11 +253,30 @@ Scripts/Custom/Bridge/*.cs 22 files: the plugin itself
|
|||||||
Scripts/Scripts.csproj OVERWRITES a stock file (see below)
|
Scripts/Scripts.csproj OVERWRITES a stock file (see below)
|
||||||
```
|
```
|
||||||
|
|
||||||
Both service definitions pin `UOLINK_CONFIG` and `UOLINK_DB_PATH` explicitly. The sidecar's own
|
**Both service definitions pin the config path**, because the sidecar's own default is relative to
|
||||||
defaults are relative to its working directory, and a service manager's working directory is not
|
its working directory — and a service manager's working directory is not somewhere you want a
|
||||||
somewhere you want a database — on Windows it can be `%SystemRoot%\System32` or, under
|
database or a config file. On Windows it can be `%SystemRoot%\System32` or, under
|
||||||
`C:\Program Files\`, a silently redirected VirtualStore copy.
|
`C:\Program Files\`, a silently redirected VirtualStore copy.
|
||||||
|
|
||||||
|
How the *database* path is pinned differs by platform, and that is deliberate:
|
||||||
|
|
||||||
|
| | Config | Database |
|
||||||
|
|---|---|---|
|
||||||
|
| **Linux** | `Environment=UOLINK_CONFIG=` in the unit | `Environment=UOLINK_DB_PATH=` in the unit — `/etc` and `/var/lib` are different directories, so both need naming |
|
||||||
|
| **Windows** | `--config` inside the service's own `binPath` | nothing to set: a relative `[store] path` resolves against the config's directory, which *is* `%ProgramData%\RunicGateway` |
|
||||||
|
|
||||||
|
The Windows service would otherwise need a **machine-wide** environment variable — `sc.exe` has no
|
||||||
|
per-service one — which every process on the host inherits and which outlives an uninstall.
|
||||||
|
|
||||||
|
**Both run as a dedicated, unprivileged account.** Linux gets a `runicgateway` system user; Windows
|
||||||
|
gets a virtual service account, `NT SERVICE\RunicGatewayLink`, which Windows creates as part of
|
||||||
|
registering the service and which has no password. Neither runs as root or `LocalSystem`.
|
||||||
|
|
||||||
|
**`sidecar.toml` is locked down, because it holds your auth token.** Neither default location
|
||||||
|
protects it on its own — `/etc` is world-readable, and `%ProgramData%` grants `Users` read access by
|
||||||
|
inheritance — so the installer sets the permissions itself: `chmod 600` plus `chown` to the service
|
||||||
|
user on Linux, and an explicit ACL of SYSTEM, Administrators and the service account on Windows.
|
||||||
|
|
||||||
> **`Scripts.csproj` is overwritten deliberately.** The stock file omits `Scripts/Custom/`, so the
|
> **`Scripts.csproj` is overwritten deliberately.** The stock file omits `Scripts/Custom/`, so the
|
||||||
> plugin would sit in the tree and never compile — and ServUO would not tell you, because it
|
> plugin would sit in the tree and never compile — and ServUO would not tell you, because it
|
||||||
> ignores the script build's exit code and silently reloads the previous `Scripts.dll`. That
|
> ignores the script build's exit code and silently reloads the previous `Scripts.dll`. That
|
||||||
@@ -509,6 +533,8 @@ The report is also written to a file, so it survives the scrollback.
|
|||||||
| Website says the shard is offline; `/health` is fine locally | The website cannot reach port 8080 — bind address or firewall. See [§5](#if-your-website-is-on-a-different-machine). Note that the site is *designed* to render normally with the shard offline, so this fails quietly by design. |
|
| Website says the shard is offline; `/health` is fine locally | The website cannot reach port 8080 — bind address or firewall. See [§5](#if-your-website-is-on-a-different-machine). Note that the site is *designed* to render normally with the shard offline, so this fails quietly by design. |
|
||||||
| Website logs `409` from the sidecar | Protocol mismatch: the number in Admin → Shard does not match the sidecar's. The sidecar rejects rather than mis-parsing. Set the field to what `/health` reports (`protocol`). If the *sidecar* and *overlay* disagree, you have a hand-assembled pair — reinstall from a bundle. |
|
| Website logs `409` from the sidecar | Protocol mismatch: the number in Admin → Shard does not match the sidecar's. The sidecar rejects rather than mis-parsing. Set the field to what `/health` reports (`protocol`). If the *sidecar* and *overlay* disagree, you have a hand-assembled pair — reinstall from a bundle. |
|
||||||
| `401` from the sidecar | Wrong or missing auth token. Read the live one back with `uo-link-sidecar --print-config --config <path>`; do not retype it from a screenshot. |
|
| `401` from the sidecar | Wrong or missing auth token. Read the live one back with `uo-link-sidecar --print-config --config <path>`; do not retype it from a screenshot. |
|
||||||
|
| **"service NOT REGISTERED" at the end of an otherwise successful run** | The host has no service manager the installer can drive — most often no systemd (a container, or a distro that never had it), or the `runicgateway` user could not be created. The binary and config *are* installed; the run prints the exact unit and commands to finish by hand. It never falls back to running the service as root or `LocalSystem`. |
|
||||||
|
| Service registered but stops immediately | It cannot read its config. On Windows check that `sc qc RunicGatewayLink` shows `--config` in `BINARY_PATH_NAME` and that `NT SERVICE\RunicGatewayLink` has read access to `sidecar.toml`; on Linux check the `runicgateway` user can read `/etc/runicgateway/sidecar.toml` and write `/var/lib/runicgateway/`. |
|
||||||
| A patch will not apply | Expected on a hand-modified shard. The base install is unaffected; you lose only the two features in [§4](#4-the-patch-tier-optional). Apply the hunks by hand if you want them. |
|
| A patch will not apply | Expected on a hand-modified shard. The base install is unaffected; you lose only the two features in [§4](#4-the-patch-tier-optional). Apply the hunks by hand if you want them. |
|
||||||
| `vendor.sale` events never arrive despite patching | The `EventSink.cs` patch is a **core** change. A shard restart is not enough — rebuild the solution (`dotnet build ServUO.sln`). |
|
| `vendor.sale` events never arrive despite patching | The `EventSink.cs` patch is a **core** change. A shard restart is not enough — rebuild the solution (`dotnet build ServUO.sln`). |
|
||||||
| Sidecar writes its database somewhere unexpected | A relative `[store] path` resolves against the directory holding `sidecar.toml` — not the working directory. Run `--print-config` to see the absolute path it will actually use. |
|
| Sidecar writes its database somewhere unexpected | A relative `[store] path` resolves against the directory holding `sidecar.toml` — not the working directory. Run `--print-config` to see the absolute path it will actually use. |
|
||||||
@@ -651,15 +677,35 @@ Copy-Item .\uo-link-sidecar-windows-x86_64.exe "$env:ProgramFiles\RunicGateway\u
|
|||||||
|
|
||||||
& "$env:ProgramFiles\RunicGateway\uo-link-sidecar.exe" --print-config --config "$env:ProgramData\RunicGateway\sidecar.toml"
|
& "$env:ProgramFiles\RunicGateway\uo-link-sidecar.exe" --print-config --config "$env:ProgramData\RunicGateway\sidecar.toml"
|
||||||
|
|
||||||
sc.exe create RunicGatewayLink binPath= "\"$env:ProgramFiles\RunicGateway\uo-link-sidecar.exe\"" start= auto
|
# The config file now holds your auth token. Lock it down before anything else can read it:
|
||||||
|
icacls "$env:ProgramData\RunicGateway\sidecar.toml" /inheritance:r /grant:r '*S-1-5-18:(F)' /grant:r '*S-1-5-32-544:(F)'
|
||||||
|
|
||||||
|
# binPath carries the config path. The single quotes matter: the value itself contains the double
|
||||||
|
# quotes the service manager needs around a path with spaces in it.
|
||||||
|
sc.exe create RunicGatewayLink `
|
||||||
|
binPath= '"C:\Program Files\RunicGateway\uo-link-sidecar.exe" --config "C:\ProgramData\RunicGateway\sidecar.toml"' `
|
||||||
|
obj= 'NT SERVICE\RunicGatewayLink' start= auto
|
||||||
sc.exe failure RunicGatewayLink reset= 86400 actions= restart/5000
|
sc.exe failure RunicGatewayLink reset= 86400 actions= restart/5000
|
||||||
[Environment]::SetEnvironmentVariable('UOLINK_CONFIG', "$env:ProgramData\RunicGateway\sidecar.toml", 'Machine')
|
|
||||||
[Environment]::SetEnvironmentVariable('UOLINK_DB_PATH', "$env:ProgramData\RunicGateway\uo-link.db", 'Machine')
|
# The service account exists only once sc create has created it, so its grants come after:
|
||||||
|
icacls "$env:ProgramData\RunicGateway\sidecar.toml" /grant 'NT SERVICE\RunicGatewayLink:(R)'
|
||||||
|
icacls "$env:ProgramData\RunicGateway" /grant 'NT SERVICE\RunicGatewayLink:(OI)(CI)M'
|
||||||
|
|
||||||
sc.exe start RunicGatewayLink
|
sc.exe start RunicGatewayLink
|
||||||
```
|
```
|
||||||
|
|
||||||
Machine environment variables are read at service start, so set them before starting — and never
|
Three things there are easy to get wrong:
|
||||||
leave the config path to the default, which is relative to the service's working directory.
|
|
||||||
|
- **The config path goes in `binPath`, not in a machine environment variable.** `sc.exe` has no
|
||||||
|
per-service environment, and a machine-wide `UOLINK_CONFIG` would be inherited by every process on
|
||||||
|
the host and survive an uninstall. Never leave the config path to the default — it is relative to
|
||||||
|
the service's working directory, which for a service is `%SystemRoot%\System32`.
|
||||||
|
- **The database needs no pinning here.** A relative `[store] path` resolves against the directory
|
||||||
|
holding `sidecar.toml`, which is already `%ProgramData%\RunicGateway`.
|
||||||
|
- **`obj=` is what keeps this off `LocalSystem`.** `NT SERVICE\RunicGatewayLink` is a virtual
|
||||||
|
service account: Windows creates it with the service, it has no password, and it exists only for
|
||||||
|
this service. Omit `obj=` and you get the most privileged local identity there is, for a process
|
||||||
|
listening on two TCP ports.
|
||||||
|
|
||||||
### A5. Connect the website, start the shard, verify
|
### A5. Connect the website, start the shard, verify
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
# Runic Gateway Installer — plan
|
# Runic Gateway Installer — plan
|
||||||
|
|
||||||
Status: **Phase 1 built, on `edge`.** Phase 0's prerequisites all landed, the installer repo
|
Status: **Phases 1 and 2 built, on `edge`.** Phase 0's prerequisites all landed, the installer repo
|
||||||
publishes the bundle manifest, and [`INSTALL.md`](INSTALL.md) specified the operator-facing run
|
publishes the bundle manifest, and [`INSTALL.md`](INSTALL.md) specified the operator-facing run
|
||||||
before the binary existed. The crate now exists and implements the installer core — bundle
|
before the binary existed. The crate now implements the installer core (bundle resolution, ServUO
|
||||||
resolution, ServUO detection and validation, the overlay sync and `install.json` — on the
|
detection and validation, the overlay sync, `install.json` — [Phase 1 as
|
||||||
`edge` branch, not `main`, so no half-capable binary is released (see
|
built](#phase-1--installer-core)) and the sidecar half (binary, config, service, token handoff —
|
||||||
[Phase 1 as built](#phase-1--installer-core)). **Phase 2 (uo-link install + service) is next.**
|
[Phase 2 as built](#phase-2--uo-link-install-and-service)). Both are on the `edge` branch, not
|
||||||
|
`main`, so no half-capable binary is released. **Phase 3 (the patch tier) is next, and the
|
||||||
|
`edge → main` cutover follows it** rather than Phase 2: `INSTALL.md` §4 describes the tier as part
|
||||||
|
of the run, and a first release whose every patch-tier answer is "not implemented" is the same
|
||||||
|
half-capable binary that kept Phase 1 off `main`.
|
||||||
This document is the design of record; it supersedes the informal overview it grew out of, which
|
This document is the design of record; it supersedes the informal overview it grew out of, which
|
||||||
described a ServUO integration that does not match how `servuo-plugins` actually ships (see
|
described a ServUO integration that does not match how `servuo-plugins` actually ships (see
|
||||||
[Corrections](#corrections-to-the-original-overview)).
|
[Corrections](#corrections-to-the-original-overview)).
|
||||||
@@ -199,13 +203,21 @@ Under `C:\Program Files\` that fails or silently lands in VirtualStore. Phase 0.
|
|||||||
half in the sidecar — a relative `[store].path` now resolves against the directory holding
|
half in the sidecar — a relative `[store].path` now resolves against the directory holding
|
||||||
`sidecar.toml`, so pinning the config alone is enough to put the database somewhere deterministic —
|
`sidecar.toml`, so pinning the config alone is enough to put the database somewhere deterministic —
|
||||||
but the config path itself is still CWD-relative by default, and "deterministic" is not the same as
|
but the config path itself is still CWD-relative by default, and "deterministic" is not the same as
|
||||||
"where this install wants it". The service definitions therefore still pin `UOLINK_CONFIG` and
|
"where this install wants it". The service definition therefore always pins the **config** path:
|
||||||
`UOLINK_DB_PATH` explicitly:
|
|
||||||
|
|
||||||
- Linux: config `/etc/runicgateway/sidecar.toml`, db `/var/lib/runicgateway/uo-link.db`, dedicated
|
- Linux: config `/etc/runicgateway/sidecar.toml`, db `/var/lib/runicgateway/uo-link.db`, dedicated
|
||||||
service user
|
service user
|
||||||
- Windows: binary under `%ProgramFiles%\RunicGateway\`, **data under `%ProgramData%\RunicGateway\`**
|
- Windows: binary under `%ProgramFiles%\RunicGateway\`, **data under `%ProgramData%\RunicGateway\`**
|
||||||
|
|
||||||
|
**How each is pinned differs by platform, and Phase 2 settled it that way deliberately.** Linux's
|
||||||
|
unit carries `Environment=UOLINK_CONFIG=` *and* `Environment=UOLINK_DB_PATH=`, because `/etc` and
|
||||||
|
`/var/lib` are different directories and both need naming. Windows passes the config as `--config`
|
||||||
|
inside the service's own `binPath`, and pins nothing else: config and data are both
|
||||||
|
`%ProgramData%\RunicGateway`, so the sidecar's own anchoring rule already puts the database exactly
|
||||||
|
where the table above says. The alternative on Windows is a **machine-wide** environment variable —
|
||||||
|
`sc.exe` offers no per-service one — which every process on the host would inherit and which would
|
||||||
|
outlive an uninstall. See [Phase 2 as built](#phase-2--uo-link-install-and-service).
|
||||||
|
|
||||||
### 2.4 The token handoff was missing entirely
|
### 2.4 The token handoff was missing entirely
|
||||||
|
|
||||||
The whole point is the website reaching the sidecar, and today that is manual and undocumented in
|
The whole point is the website reaching the sidecar, and today that is manual and undocumented in
|
||||||
@@ -545,6 +557,65 @@ process running out of the tree.
|
|||||||
That both writes the config the service will read and returns the token to print, so the service
|
That both writes the config the service will read and returns the token to print, so the service
|
||||||
never starts against a config that does not exist yet.
|
never starts against a config that does not exist yet.
|
||||||
|
|
||||||
|
**As built** ([installer#5](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/5)) —
|
||||||
|
`src/sidecar.rs` (binary, config, handoff) and `src/service.rs` (systemd, Windows SCM), wired into
|
||||||
|
the same `install` run. The decisions that were not already settled above:
|
||||||
|
|
||||||
|
- **Both platforms run the sidecar as a dedicated unprivileged identity.** Linux gets the system
|
||||||
|
user this section already specified; Windows gets a **virtual service account**
|
||||||
|
(`sc create … obj= "NT SERVICE\RunicGatewayLink"`), which the SCM creates itself and which has no
|
||||||
|
password. Plain `sc create` would have run it as `LocalSystem` — the most privileged local
|
||||||
|
identity there is, for a process that listens on two TCP ports while its Linux twin deliberately
|
||||||
|
does not run as root. The account only exists *after* `sc create`, which fixes the order of the
|
||||||
|
file permissions below.
|
||||||
|
- **`sidecar.toml` is locked down, because it holds the token.** Neither default location protects
|
||||||
|
it: `/etc` is world-readable and `%ProgramData%` grants `Users` read by inheritance, so an
|
||||||
|
unprivileged local account could read the shard's auth token out of a stock install. Linux gets
|
||||||
|
`chmod 600` plus `chown` to the service user; Windows gets `icacls /inheritance:r` down to SYSTEM
|
||||||
|
and Administrators **before** registration, then a read grant for the service account after it
|
||||||
|
exists. The database directory gets a separate write grant, since SQLite writes journal and WAL
|
||||||
|
files beside the database.
|
||||||
|
- **`--verify` runs no part of the sidecar half.** `--print-config` provisions — it writes the
|
||||||
|
config and mints a token — so a dry run that called it would create exactly the state it claims
|
||||||
|
not to. A `--verify` run reports what would be installed, reads no token, and prints no handoff.
|
||||||
|
It also **carries the existing `link` section of `install.json` through untouched**, so a dry run
|
||||||
|
on an installed host cannot make its service disappear from the record.
|
||||||
|
- **The installed binary's protocol version is checked against the bundle, and a mismatch stops the
|
||||||
|
run before the service is registered.** Gate 1 (§7.1) read that number from source at the release
|
||||||
|
tag; this is the same check applied to the binary that will actually answer the website. The
|
||||||
|
binary is left on disk — harmless without a service — rather than the run pretending to succeed.
|
||||||
|
- **`RUNICGATEWAY_STATE_DIR` now relocates the sidecar binary too, and suppresses service
|
||||||
|
registration.** Phase 1 left the binary path alone because nothing wrote it. A relocated run that
|
||||||
|
still dropped a binary into `/usr/bin` and registered a system service would be exactly the
|
||||||
|
half-in-the-real-system accident the variable exists to avoid — and there is no such thing as a
|
||||||
|
relocated systemd unit or Windows service. Such a run also leaves file permissions alone, because
|
||||||
|
hardening a scratch config against the only account that will ever read it just breaks the next
|
||||||
|
test run.
|
||||||
|
- **A host the installer cannot drive gets the recipe, not a failure or a weaker service.** No
|
||||||
|
systemd (`/run/systemd/system` absent — the correct test, since `systemctl` is present in plenty
|
||||||
|
of containers where PID 1 is not systemd), or a service user that cannot be created: the binary
|
||||||
|
and config are still installed, `install.json` records `service: null`, and the run prints the
|
||||||
|
exact unit text and commands. There is **no fallback to `User=root` or `LocalSystem`** — a service
|
||||||
|
quietly running with more privilege than its own documentation promises is worse than one that was
|
||||||
|
not registered. The printed Windows recipe states plainly whether the run locked the config down
|
||||||
|
or the operator still has to.
|
||||||
|
- **`install.json` never records the token.** The `link` section holds versions, the binary's hash,
|
||||||
|
the config and database paths, and the service's name, unit path and account. The token goes to
|
||||||
|
the terminal and to `sidecar.toml`, and the record is a support artifact people paste into bug
|
||||||
|
reports.
|
||||||
|
- **The service is stopped before its binary is replaced, and restarted rather than started
|
||||||
|
afterwards.** On Windows the file is locked while the service runs (and `sc stop` returns as soon
|
||||||
|
as the stop is *pending*, so the stop is polled, not slept on); on Linux the replacement is
|
||||||
|
permitted but leaves the old code serving until something restarts it. `systemctl start` on an
|
||||||
|
active unit is a no-op, which is precisely the wrong outcome after a replacement.
|
||||||
|
|
||||||
|
Verified on this machine end to end against a relocated layout: the bundle's Windows sidecar
|
||||||
|
downloaded and checksum-verified, `--print-config` provisioning a fresh config and returning a
|
||||||
|
token, the §6 handoff printed with the URLs composed from the host rather than the bind address, a
|
||||||
|
second run reporting `unchanged` / `already present` and leaving `install.json` byte-identical, a
|
||||||
|
`--verify` run over an installed host writing nothing and preserving the `link` section, and a
|
||||||
|
tampered binary detected by hash and replaced with no stray staging file left behind.
|
||||||
|
|
||||||
### Phase 3 — patch tier (opt-in)
|
### Phase 3 — patch tier (opt-in)
|
||||||
|
|
||||||
Everything in §2.2. Detect applicability, dry-run, apply, record, warn about the core rebuild, and
|
Everything in §2.2. Detect applicability, dry-run, apply, record, warn about the core rebuild, and
|
||||||
@@ -825,18 +896,24 @@ mismatched pair from being published as a bundle — which is the mechanism that
|
|||||||
|
|
||||||
## 8. Open questions
|
## 8. Open questions
|
||||||
|
|
||||||
1. **Windows service mechanism** — `sc create` against the plain console binary (simplest, works
|
1. **Does the installer manage ServUO stop/start?** Currently it refuses while ServUO runs and tells
|
||||||
today), a bundled WinSW/NSSM shim, or a native `--service` mode in the sidecar using the
|
|
||||||
`windows-service` crate (cleanest, but changes `link`). Recommendation: `sc create` for v1,
|
|
||||||
revisit if restart semantics prove inadequate.
|
|
||||||
2. **Does the installer manage ServUO stop/start?** Currently it refuses while ServUO runs and tells
|
|
||||||
the operator to restart afterward. Offering to stop/start would be friendlier but means owning
|
the operator to restart afterward. Offering to stop/start would be friendlier but means owning
|
||||||
another shard's process lifecycle, and the shard's own start scripts vary.
|
another shard's process lifecycle, and the shard's own start scripts vary.
|
||||||
3. **Co-location assumption** — the shard dials out to the sidecar on loopback `127.0.0.1:7788`, so
|
2. **Co-location assumption** — the shard dials out to the sidecar on loopback `127.0.0.1:7788`, so
|
||||||
sidecar and ServUO must share a host. Should the installer support installing only uo-link on a
|
sidecar and ServUO must share a host. Should the installer support installing only uo-link on a
|
||||||
different host, or hard-assume co-location?
|
different host, or hard-assume co-location?
|
||||||
Resolved and moved into §1 / §2.2 / §5: uninstall scope, and minimum ServUO version.
|
Resolved and moved into §1 / §2.2 / §5: uninstall scope, and minimum ServUO version.
|
||||||
|
|
||||||
|
**Resolved — Windows service mechanism** (was question 1). `sc create` against the plain console
|
||||||
|
binary, as recommended: it works on a stock host, ships nothing extra, and needs no change to
|
||||||
|
`link`. A WinSW/NSSM shim would be a third binary to keep current, and a native `--service` mode
|
||||||
|
using the `windows-service` crate would put Windows service plumbing inside a component whose whole
|
||||||
|
job is being platform-agnostic. Restart semantics turned out to be adequate —
|
||||||
|
`sc failure … actions= restart/5000` is the direct counterpart of systemd's `Restart=on-failure` /
|
||||||
|
`RestartSec=5`. What the recommendation did *not* anticipate is the service identity: plain
|
||||||
|
`sc create` runs as `LocalSystem`, so Phase 2 registers with `obj= "NT SERVICE\RunicGatewayLink"`
|
||||||
|
instead (see [Phase 2 as built](#phase-2--uo-link-install-and-service)).
|
||||||
|
|
||||||
**Resolved — branch targeting for the new repo** (was question 4). The v3 cutover landed:
|
**Resolved — branch targeting for the new repo** (was question 4). The v3 cutover landed:
|
||||||
`servuo-plugins#6` merged, so that repo's `main` and `edge` agree at protocol 3. The release
|
`servuo-plugins#6` merged, so that repo's `main` and `edge` agree at protocol 3. The release
|
||||||
workflow targets `main`, and the installer repo starts clean on `main`. §7.4's caution still applies
|
workflow targets `main`, and the installer repo starts clean on `main`. §7.4's caution still applies
|
||||||
|
|||||||
Reference in New Issue
Block a user