Files
webhook-server/installer/webhook-server.iss
T
justin c49a2a12cb Documentation: install/upgrade/uninstall guides + recipes incl. Zerto
Adds a docs/ folder under the repo root with full operator documentation
aimed at sysadmins (not webhook developers). The Zerto pre/post script
recipe is the canonical "why does this exist" walkthrough; the GitHub
HMAC, AD password reset, and UI-on-desktop recipes round out common
patterns.

Pages:
- README.md (index)
- concepts.md (5-minute "what is a webhook" explainer)
- installation.md (interactive + silent install)
- upgrading.md (single-click upgrade flow + edge cases)
- uninstalling.md (clean removal + wiping ProgramData)
- runas-modes.md (Service / InteractiveUser / SpecificUser decision flow)
- service-account-and-ad.md (gMSA setup, delegated rights)
- network-and-security.md (bind addresses, allowlists, HTTPS, secret storage)
- troubleshooting.md (symptom -> first check, common errors)
- recipes/zerto-pre-post-scripts.md (canonical use case)
- recipes/github-style-hmac.md (GitHub / Stripe-shaped webhooks)
- recipes/ad-password-reset.md (gMSA-backed self-service reset)
- recipes/ui-on-desktop.md (InteractiveUser pattern)

Top-level README.md restructured to point at docs/ as the source of
truth, dropping the duplicated installation snippets.

Installer ships docs/ alongside the binaries so they're available
offline at C:\Program Files\WebhookServer\docs\. GUI Help menu gains
a "Documentation" item that opens the docs site in a browser.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 10:47:44 -04:00

119 lines
4.7 KiB
Plaintext

; Inno Setup script for Webhook Server.
;
; Build: iscc /DAppVersion=0.1.0 webhook-server.iss
; Output: ..\dist\WebhookServer-Setup-{AppVersion}.exe
;
; The installer copies published binaries to {pf}\WebhookServer, installs the
; Windows Service via install-service.ps1 post-install, and removes the service
; via uninstall-service.ps1 pre-uninstall. Start Menu gets a single GUI shortcut.
#ifndef AppVersion
#define AppVersion "0.1.0"
#endif
#define AppName "Webhook Server"
#define AppPublisher "Justin Paul"
#define AppURL "https://jpaul.me"
#define AppExeName "WebhookServer.Gui.exe"
#define ServiceExeName "WebhookServer.Service.exe"
#define ServiceName "WebhookServer"
#define RepoRoot "..\"
[Setup]
AppId={{6E3B3C1A-9C20-4F50-B6A8-2B6D6D7E2F11}
AppName={#AppName}
AppVersion={#AppVersion}
AppPublisher={#AppPublisher}
AppPublisherURL={#AppURL}
AppSupportURL=https://github.com/recklessop/webhook-server
AppUpdatesURL=https://github.com/recklessop/webhook-server/releases
DefaultDirName={autopf}\WebhookServer
DefaultGroupName={#AppName}
DisableProgramGroupPage=yes
OutputBaseFilename=WebhookServer-Setup-{#AppVersion}
OutputDir={#RepoRoot}dist
SetupIconFile={#RepoRoot}resources\webhook-server.ico
UninstallDisplayIcon={app}\{#AppExeName}
PrivilegesRequired=admin
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
Compression=lzma2/max
SolidCompression=yes
WizardStyle=modern
VersionInfoVersion={#AppVersion}.0
VersionInfoCompany={#AppPublisher}
VersionInfoProductName={#AppName}
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "Create a &desktop shortcut"; GroupDescription: "Additional shortcuts:"; Flags: unchecked
[Files]
Source: "{#RepoRoot}publish\service\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#RepoRoot}publish\gui\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#RepoRoot}scripts\install-service.ps1"; DestDir: "{app}\scripts"; Flags: ignoreversion
Source: "{#RepoRoot}scripts\uninstall-service.ps1"; DestDir: "{app}\scripts"; Flags: ignoreversion
Source: "{#RepoRoot}README.md"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#RepoRoot}docs\*"; DestDir: "{app}\docs"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#RepoRoot}resources\webhook-server.ico"; DestDir: "{app}"; Flags: ignoreversion
[Icons]
Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"; IconFilename: "{app}\webhook-server.ico"
Name: "{group}\Uninstall {#AppName}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; IconFilename: "{app}\webhook-server.ico"; Tasks: desktopicon
[Run]
Filename: "powershell.exe"; \
Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\scripts\install-service.ps1"" -BinaryPath ""{app}\{#ServiceExeName}"""; \
StatusMsg: "Installing Windows Service..."; \
Flags: runhidden
Filename: "{app}\{#AppExeName}"; \
Description: "Launch {#AppName}"; \
Flags: postinstall nowait skipifsilent
[UninstallRun]
Filename: "powershell.exe"; \
Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\scripts\uninstall-service.ps1"""; \
Flags: runhidden; \
RunOnceId: "RemoveWebhookService"
[Code]
function ServiceExists(): Boolean;
var
ResultCode: Integer;
begin
// sc.exe query returns 0 when the service exists, 1060 when it does not.
Exec(ExpandConstant('{sys}\sc.exe'), 'query WebhookServer', '', SW_HIDE,
ewWaitUntilTerminated, ResultCode);
Result := (ResultCode = 0);
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
ResultCode: Integer;
begin
Result := '';
// 1. If the service exists, stop it so its binaries are unlocked before file
// copy. net stop is synchronous (blocks until the service is actually
// stopped), unlike sc stop which is fire-and-forget. Non-zero exit -
// already stopped, missing, dependency error - we ignore; the file copy
// will fail loudly if the binaries are still locked.
if ServiceExists() then
begin
WizardForm.PreparingLabel.Caption := 'Stopping the WebhookServer service...';
Exec(ExpandConstant('{sys}\net.exe'), 'stop WebhookServer', '', SW_HIDE,
ewWaitUntilTerminated, ResultCode);
end;
// 2. Kill any running GUI / tray instances so their binaries are unlocked too.
// /f forces termination, /im matches by image name, "*" wildcard would be
// risky so we name them explicitly.
Exec(ExpandConstant('{sys}\taskkill.exe'), '/f /im WebhookServer.Gui.exe',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
Exec(ExpandConstant('{sys}\taskkill.exe'), '/f /im WebhookServer.Service.exe',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;