2befe64a0c
Firewall:
- On service initialize/install, create an idempotent inbound allow rule
("OrchestrAD") for the configured listen port, scoped to RFC 1918 private
ranges plus CGNAT (10/8, 172.16/12, 192.168/16, 100.64/10). The rule is
deleted-then-added so it always reflects the current port, and removed on
service uninstall. Best-effort (needs admin; the MSI custom action and
service run elevated); no-op off Windows. Verified the netsh rule lands
with the expected port and remote-address scoping.
MSI:
- Skip the license/EULA page (Welcome now goes straight to the install
directory), since it was blank. A standard short notice is kept in
license.rtf only so the stock license control resolves at build time.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
152 lines
8.9 KiB
XML
152 lines
8.9 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!--
|
|
OrchestrAD Windows installer (WiX v4+ / built with WiX 5 + the UI extension).
|
|
|
|
Wizard: Welcome -> Install directory -> Network (listen address +
|
|
port) -> Ready -> Finish. The install directory, listen address, and listen
|
|
port are recorded under HKLM\Software\Grace Solutions\OrchestrAD; the service
|
|
reads the address/port from there (env vars still override). The finish page
|
|
shows the URL and the default admin/admin credentials and can open the app.
|
|
|
|
Installs orchestrad.exe to the chosen directory (default Program Files\
|
|
OrchestrAD) and registers + starts the service via the binary's idempotent
|
|
`initialize`; uninstall runs `remove` first. Upgrades update only the binary;
|
|
the runtime data directory (SQLite database) is never touched.
|
|
|
|
Build (from repo root):
|
|
wix extension add -g WixToolset.UI.wixext
|
|
wix build -arch x64 -ext WixToolset.UI.wixext installer/OrchestrAD.wxs \
|
|
-d Version=<x.y.z> -d BinDir=<dir with orchestrad.exe> \
|
|
-d IconPath=<orchestrad.ico> -o OrchestrAD.msi
|
|
-->
|
|
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
|
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
|
|
<Package
|
|
Name="OrchestrAD"
|
|
Manufacturer="Grace Solutions"
|
|
Version="$(Version)"
|
|
UpgradeCode="41EC0251-FC95-4C00-8C91-EC3F9BE1F278"
|
|
Scope="perMachine"
|
|
Compressed="yes">
|
|
|
|
<SummaryInformation Description="OrchestrAD - Active Directory Rule Automation Platform" />
|
|
|
|
<MajorUpgrade DowngradeErrorMessage="A newer version of OrchestrAD is already installed." />
|
|
<MediaTemplate EmbedCab="yes" />
|
|
|
|
<Icon Id="OrchestradIcon" SourceFile="$(IconPath)" />
|
|
<Property Id="ARPPRODUCTICON" Value="OrchestradIcon" />
|
|
|
|
<!-- Wizard-configurable properties (public: settable via UI and command
|
|
line). Listen address/port default to the app's own defaults. -->
|
|
<Property Id="LISTEN_ADDRESS" Value="0.0.0.0" />
|
|
<Property Id="LISTEN_PORT" Value="18090" />
|
|
|
|
<!-- Reuse a previously recorded install directory on upgrade. -->
|
|
<Property Id="INSTALLDIR">
|
|
<RegistrySearch Id="FindInstallDir" Root="HKLM"
|
|
Key="Software\Grace Solutions\OrchestrAD"
|
|
Name="InstallDir" Type="directory" />
|
|
</Property>
|
|
|
|
<StandardDirectory Id="ProgramFiles64Folder">
|
|
<Directory Id="INSTALLDIR" Name="OrchestrAD" />
|
|
</StandardDirectory>
|
|
|
|
<ComponentGroup Id="ProductComponents" Directory="INSTALLDIR">
|
|
<Component Id="OrchestradExe" Bitness="always64">
|
|
<File Id="OrchestradExe" Name="orchestrad.exe" Source="$(BinDir)/orchestrad.exe" KeyPath="yes" />
|
|
</Component>
|
|
|
|
<!-- Install location, version, and the chosen listen binding. The service
|
|
reads ListenAddress/ListenPort from here. -->
|
|
<Component Id="RegistryEntries" Bitness="always64" Guid="7C1E2A64-9B3D-4E1A-9F2B-2D0E6C8A5B10">
|
|
<RegistryKey Root="HKLM" Key="Software\Grace Solutions\OrchestrAD">
|
|
<RegistryValue Name="InstallDir" Type="string" Value="[INSTALLDIR]" KeyPath="yes" />
|
|
<RegistryValue Name="Version" Type="string" Value="$(Version)" />
|
|
<RegistryValue Name="ListenAddress" Type="string" Value="[LISTEN_ADDRESS]" />
|
|
<RegistryValue Name="ListenPort" Type="string" Value="[LISTEN_PORT]" />
|
|
</RegistryKey>
|
|
</Component>
|
|
</ComponentGroup>
|
|
|
|
<Feature Id="Main" Title="OrchestrAD" Level="1">
|
|
<ComponentGroupRef Id="ProductComponents" />
|
|
</Feature>
|
|
|
|
<!-- Service lifecycle via the binary's idempotent CLI (deferred, LocalSystem). -->
|
|
<CustomAction Id="InitializeService" FileRef="OrchestradExe" ExeCommand="initialize"
|
|
Execute="deferred" Impersonate="no" Return="check" />
|
|
<CustomAction Id="RemoveService" FileRef="OrchestradExe" ExeCommand="remove"
|
|
Execute="deferred" Impersonate="no" Return="ignore" />
|
|
|
|
<!-- Optional: open the app in the browser from the finish page. -->
|
|
<CustomAction Id="LaunchApplication" Directory="INSTALLDIR"
|
|
ExeCommand="[WindowsFolder]explorer.exe "https://localhost:[LISTEN_PORT]/""
|
|
Execute="immediate" Impersonate="yes" Return="asyncNoWait" />
|
|
|
|
<InstallExecuteSequence>
|
|
<Custom Action="RemoveService" Before="RemoveFiles" Condition="REMOVE="ALL"" />
|
|
<!-- After WriteRegistryValues so the service reads the recorded
|
|
ListenAddress/ListenPort on its first start (InstallFiles alone runs
|
|
before the registry values are committed). -->
|
|
<Custom Action="InitializeService" After="WriteRegistryValues" Condition="NOT REMOVE="ALL"" />
|
|
</InstallExecuteSequence>
|
|
|
|
<!-- UI: install-dir wizard plus a custom network-binding dialog. The license
|
|
page is skipped (see the WelcomeDlg publish below); this variable only
|
|
keeps the stock license control resolvable at build time. -->
|
|
<WixVariable Id="WixUILicenseRtf" Value="installer/license.rtf" />
|
|
<ui:WixUI Id="WixUI_InstallDir" InstallDirectory="INSTALLDIR" />
|
|
|
|
<!-- Finish page: default credentials + URL, and an optional launch box. The
|
|
text is built with SetProperty so [LISTEN_PORT] is substituted. -->
|
|
<SetProperty Id="WIXUI_EXITDIALOGOPTIONALTEXT" After="CostFinalize" Sequence="both"
|
|
Value="OrchestrAD is installed and the service is running. Open https://localhost:[LISTEN_PORT]/ and sign in with username 'admin' and password 'admin'. You will be prompted to change the password at first login." />
|
|
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Open OrchestrAD in my browser" />
|
|
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
|
|
|
|
<UI>
|
|
<!-- Custom dialog: choose the listen address and port. -->
|
|
<Dialog Id="NetworkDlg" Width="370" Height="270" Title="[ProductName] Setup">
|
|
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="WixUI_Bmp_Banner" />
|
|
<Control Id="Title" Type="Text" X="15" Y="6" Width="300" Height="15" Transparent="yes" NoPrefix="yes" Text="{\WixUI_Font_Title}Network binding" />
|
|
<Control Id="Description" Type="Text" X="25" Y="23" Width="320" Height="15" Transparent="yes" NoPrefix="yes" Text="Choose the address and port the OrchestrAD service listens on." />
|
|
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
|
|
|
|
<Control Id="AddressLabel" Type="Text" X="25" Y="70" Width="320" Height="12" NoPrefix="yes" Text="Listen address (use 0.0.0.0 for all interfaces):" />
|
|
<Control Id="AddressEdit" Type="Edit" X="25" Y="84" Width="200" Height="17" Property="LISTEN_ADDRESS" />
|
|
|
|
<Control Id="PortLabel" Type="Text" X="25" Y="115" Width="320" Height="12" NoPrefix="yes" Text="Listen port:" />
|
|
<Control Id="PortEdit" Type="Edit" X="25" Y="129" Width="80" Height="17" Property="LISTEN_PORT" />
|
|
|
|
<Control Id="Note" Type="Text" X="25" Y="160" Width="320" Height="30" Transparent="yes" NoPrefix="yes" Text="The service serves HTTPS with a self-managed certificate by default. These values are recorded in the registry; environment variables still override them." />
|
|
|
|
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
|
|
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="Back">
|
|
<Publish Event="NewDialog" Value="InstallDirDlg" Condition="1" />
|
|
</Control>
|
|
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Next">
|
|
<Publish Event="NewDialog" Value="VerifyReadyDlg" Condition="1" />
|
|
</Control>
|
|
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel">
|
|
<Publish Event="SpawnDialog" Value="CancelDlg" Condition="1" />
|
|
</Control>
|
|
</Dialog>
|
|
|
|
<!-- Skip the (blank) license page: go straight from Welcome to the
|
|
install-directory dialog and route its Back button back to Welcome. -->
|
|
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="10" Condition="NOT Installed" />
|
|
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="10" Condition="NOT Installed" />
|
|
|
|
<!-- Insert NetworkDlg between the install-directory and ready pages. The
|
|
higher Order (3) makes these transitions win over the standard ones. -->
|
|
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="NetworkDlg" Order="3" Condition="WIXUI_INSTALLDIR_VALID="1"" />
|
|
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="NetworkDlg" Order="3" Condition="NOT Installed" />
|
|
|
|
<!-- Launch the app from the finish page when the box is ticked. -->
|
|
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchApplication" Condition="WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed" />
|
|
</UI>
|
|
</Package>
|
|
</Wix>
|