Adds an optional Agent Tunnel wizard step to the Devolutions Agent
installer so admins can enroll the agent in a Gateway QUIC tunnel as
part of MSI install (UI or unattended).
Surfaces three MSI public properties for unattended installs:
- AGENT_TUNNEL_ENROLLMENT_STRING (dgw-enroll:v1:<base64> from DVLS/Hub/Gateway)
- AGENT_TUNNEL_ADVERTISE_SUBNETS (CSV CIDR; empty = none)
- AGENT_TUNNEL_ADVERTISE_DOMAINS (CSV DNS suffixes; empty = auto-detect only)
Wires a new deferred elevated custom action (EnrollAgentTunnel) that
runs Before StartServices when AGENT_TUNNEL_FEATURE is being installed.
It base64-decodes the enrollment payload, shells out to
`devolutions-agent.exe enroll <url> <token> <name> [subnets]` with a 60s
timeout, and redacts the token in the session log. Advertise domains
are persisted by patching `Tunnel.AdvertiseDomains` in agent.json
post-enrollment, matching the agreed direction that domain config lives
in the file rather than as a CLI flag.
The Tunnel feature itself is opt-in (isEnabled:false, allowChange:true);
the dialog is skipped when the feature isn't selected. An empty
enrollment string also skips tunnel setup, allowing the installer to be
used without touching the tunnel.
Summary
Adds an optional Agent Tunnel wizard step to the Devolutions Agent MSI installer so admins can enrol the agent in a Gateway QUIC tunnel during install — UI or unattended.
Three text fields in the dialog: enrolment string, advertise subnets, advertise domains. The feature is opt-in (
isEnabled: false, allowChange: true); the dialog is skipped when the feature isn't selected, and an empty enrolment string skips tunnel setup even if the feature is on, so the installer remains usable for non-tunnel deployments.Smoke-tested end-to-end against a local DVLS + Gateway + Agent stack: MSI built clean, agent enrolled successfully, RDP TCP traffic routed through the agent tunnel to
IT-HELP-DC:3389.MSI public properties (unattended install)
Custom action
EnrollAgentTunnelis deferred + elevated +Impersonate=false, runsBefore StartServices, gated byFeatures.AGENT_TUNNEL_FEATURE.BeingInstall(). It:dgw-enroll:v1:prefix, strips whitespace, pads base64url, decodes JSON payload (api_base_url,enrollment_token, optionalname).devolutions-agent.exe enroll <url> <token> <name> [subnets]with a 60s timeout; on timeout the child is killed.***) symmetrically across the command-line log and child stdout/stderr.Tunnel.AdvertiseDomainsof%ProgramData%\Devolutions\Agent\agent.json. This matches the design that advertise domains live in config, not on the CLI (replaces the closed feat(agent): --advertise-domains CLI flag #1774).Depends on
/jet/tunnel/enroll)Both merged to master 2026-05-20.
Test plan
CNDL1138/CNDL1006warnings from existing code, not introduced here)dgw-enroll:v1:prefix → validation error in dialogIT-HELP-DC:3389succeedsReview history
Pre-review and codex-review passes folded into the single commit. Notable points addressed:
JObject,Value<string>(),IsNullOrWhiteSpacevalidation)WaitForExit(60_000)return-value check with child kill on timeoutInstallDirDlg*strings leaked into en-us