16d3b7767e
apple / swift (push) Successful in 54s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
windows-host / package (push) Failing after 6m18s
android / android (push) Failing after 2m12s
ci / web (push) Successful in 38s
ci / rust (push) Failing after 1m40s
ci / docs-site (push) Successful in 29s
deb / build-publish (push) Successful in 2m35s
decky / build-publish (push) Successful in 24s
ci / bench (push) Successful in 4m32s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 3m35s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 20s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m33s
docker / deploy-docs (push) Successful in 22s
MSIX (the client's format) can't install the host's LocalSystem secure-desktop service or the SudoVDA kernel driver, so the host ships as a signed Inno Setup setup.exe that runs elevated and delegates to the existing idempotent `punktfunk-host service install`. - packaging/windows/punktfunk-host.iss: lay exe into Program Files, optional SudoVDA driver task, run service install/start; [Code] stops+waits the service before file copy on upgrade; uninstall runs service uninstall. - pack-host-installer.ps1: cert (reuses MSIX_CERT_PFX_B64 / self-signed CN=unom), sign inner exe + setup.exe, fetch/stage SudoVDA, run ISCC, export public .cer. - fetch-sudovda.ps1 / install-sudovda.ps1: pinned SudoVDA + nefcon download, cert import, gated device-node create (no phantom dup), pnputil install (warn-not-abort). - nvenc/: synthesize nvencodeapi.lib via llvm-dlltool from a 2-export .def so --features nvenc links with no GPU/SDK at build time. - .gitea/workflows/windows-host.yml: build (nvenc) -> clippy -> ISCC -> sign -> publish setup.exe + .cer to the generic registry pkg punktfunk-host-windows. Tag host-win-v* -> X.Y.Z (+ latest/ alias); main push -> rolling 0.2.<run>. - setup-windows-runner.ps1: provision Inno Setup; docs: installer instructions. SudoVDA/nefcon release URLs+SHA-256s in fetch-sudovda.ps1 are placeholders (baseline v0.2.1) — fetch warns + prints the computed hash until pinned. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
111 lines
4.9 KiB
Markdown
111 lines
4.9 KiB
Markdown
# Windows service (deployment)
|
|
|
|
The `PunktfunkHost` Windows service is the end-user way to run the host on Windows. It replaces the
|
|
manual bring-up chain (a scheduled task → `PsExec64 -s -i 1` → `wscript launch.vbs` → `host-run.cmd`)
|
|
with one command, auto-start on boot, and supervision.
|
|
|
|
## Install (installer — recommended)
|
|
|
|
Download the signed installer from the package registry
|
|
(`punktfunk-host-windows`, <https://git.unom.io/unom/-/packages>) and run it (it elevates itself):
|
|
|
|
```
|
|
punktfunk-host-setup-<ver>.exe # wizard
|
|
punktfunk-host-setup-<ver>.exe /VERYSILENT # unattended
|
|
```
|
|
|
|
It lays the host into `C:\Program Files\punktfunk`, optionally installs the bundled **SudoVDA**
|
|
virtual-display driver, then runs `service install` + `service start` for you. Upgrades stop the
|
|
service first and re-point it; uninstall (Add/Remove Programs) runs `service uninstall`. Packaging
|
|
details: [`packaging/windows/README.md`](../packaging/windows/README.md). A self-signed CI build also
|
|
publishes a `.cer` — import it once (`Import-Certificate -FilePath punktfunk-host-windows.cer
|
|
-CertStoreLocation Cert:\LocalMachine\TrustedPublisher`) so Windows trusts the signed setup.
|
|
|
|
## Install (manual / CLI)
|
|
|
|
From an **elevated** (Administrator) prompt:
|
|
|
|
```powershell
|
|
punktfunk-host service install # register auto-start LocalSystem service + firewall rules + default host.env
|
|
punktfunk-host service start # start it now (also starts automatically on every boot)
|
|
```
|
|
|
|
`service install` is idempotent — run it again after upgrading the exe to re-point the service at the
|
|
new binary. Register whatever location you keep the exe in (e.g. `C:\Program Files\punktfunk\`); the
|
|
service records the current exe path.
|
|
|
|
Other subcommands:
|
|
|
|
```powershell
|
|
punktfunk-host service stop
|
|
punktfunk-host service status
|
|
punktfunk-host service uninstall # stop + delete the service + remove its firewall rules
|
|
```
|
|
|
|
## How it works
|
|
|
|
The host must run **as SYSTEM in the interactive session** (Session 1+): Desktop Duplication of the
|
|
secure desktop (UAC / lock / login) and `SendInput` need SYSTEM, and capture/injection need the
|
|
interactive session, which a plain Session-0 service is not in.
|
|
|
|
So the service (itself in Session 0) **never captures**. On start, and whenever the active console
|
|
session changes, it:
|
|
|
|
1. resolves the active console session (`WTSGetActiveConsoleSessionId`),
|
|
2. duplicates its own LocalSystem token and retargets it to that session (`SetTokenInformation`
|
|
`TokenSessionId`),
|
|
3. launches the host there with `CreateProcessAsUserW` (`lpDesktop = winsta0\default`),
|
|
4. supervises it: relaunches on exit/crash (with backoff) and on a console connect/disconnect.
|
|
|
|
A kill-on-close **job object** ensures a service crash never orphans the SYSTEM host. The host in turn
|
|
spawns the WGC helper into the *user* session (see [`windows-secure-desktop.md`](windows-secure-desktop.md))
|
|
— two nested launches. Lock/unlock are handled inside the host (the `DesktopWatcher` DDA↔WGC mux), so
|
|
the service deliberately does **not** relaunch on lock/unlock — only on a real session switch.
|
|
|
|
This is the same model Sunshine/Apollo use.
|
|
|
|
## Configuration
|
|
|
|
Config lives in **`%ProgramData%\punktfunk\host.env`** (KEY=VALUE lines, `#` comments). `service
|
|
install` writes a default if none exists. Template: [`scripts/windows/host.env.example`](../scripts/windows/host.env.example).
|
|
|
|
```ini
|
|
PUNKTFUNK_ENCODER=nvenc
|
|
PUNKTFUNK_VIDEO_SOURCE=virtual
|
|
PUNKTFUNK_SECURE_DDA=1
|
|
RUST_LOG=info
|
|
# PUNKTFUNK_HOST_CMD=serve --native # the host subcommand the service launches (default)
|
|
```
|
|
|
|
The service loads these into its environment and carries `PUNKTFUNK_*` + `RUST_LOG` to the host child
|
|
(the same env-merge the WGC helper uses). Restart the service after editing:
|
|
|
|
```powershell
|
|
punktfunk-host service stop; punktfunk-host service start
|
|
```
|
|
|
|
The host's identity (cert/pairing/mgmt token/library) also lives under `%ProgramData%\punktfunk` — a
|
|
machine-wide dir the SYSTEM service and the interactive user share, surviving user logout.
|
|
`PUNKTFUNK_CONFIG_DIR` overrides the location (both platforms; handy for tests).
|
|
|
|
## Logs
|
|
|
|
- `%ProgramData%\punktfunk\logs\service.log` — the service's own supervision log (spawn/exit/session
|
|
switches).
|
|
- `%ProgramData%\punktfunk\logs\host.log` — the host child's stdout/stderr.
|
|
|
|
## Prerequisites
|
|
|
|
- The host built with `--features nvenc` for NVENC (the driver ships `nvEncodeAPI64.dll`; no SDK
|
|
needed at runtime). Software encode otherwise.
|
|
- The **SudoVDA** indirect display driver installed (for `PUNKTFUNK_VIDEO_SOURCE=virtual`).
|
|
- **ViGEmBus** for virtual gamepads (optional).
|
|
|
|
## Gotchas
|
|
|
|
- `service install`/`uninstall` need an **elevated** prompt (the SCM rejects non-admin).
|
|
- `service run` is the SCM entry point — don't run it by hand (it errors with a hint).
|
|
- A **graceful** stop currently `TerminateProcess`es the host, so its RAII teardown (SudoVDA monitor
|
|
REMOVE) doesn't run; a stale virtual monitor can linger until the next start. A cooperative-stop
|
|
signal is a follow-up.
|