v0.1.2: Config Checkpoints dialog, descriptions, daily auto-snapshot, docs (#3)
* 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> * Config Checkpoints dialog + daily auto-checkpoint; drop installer GUI launch Three fixes: 1. Config Checkpoints submenu replaced with a proper dialog. Lists checkpoints with timestamp/size/filename, has a "Take Checkpoint Now" button, and a "Roll Back" button that becomes enabled when a row is selected. The previous click-a-menu-entry-immediate-restore flow was too easy to fire by accident. 2. New CheckpointScheduler BackgroundService creates a checkpoint at midnight every day. Combined with the existing auto-on-save snapshots, this guarantees a daily rollback point even if the config wasn't edited that day. A new "create-checkpoint" admin op plus AdminPipeServer.CreateCheckpoint helper does the actual file copy; both manual (via the dialog) and the scheduler use it. 3. Installer: drop the post-install "Launch Webhook Server" wizard step. It tried to launch the GUI un-elevated, which fails because the GUI's manifest is requireAdministrator. The Start Menu shortcut handles elevation correctly, so the user can launch from there. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Docs: replace AD-reset recipe with realistic Zerto failover walkthrough The AD password reset endpoint was a poor fit for what people actually need this server for. Replaced with a realistic Zerto post-failover example that's much closer to the project's purpose: - Update DNS A records for failed-over hostnames - Wait for the VM to come up at the DR site - PowerShell-remote into the VM and check / start critical services - Notify Teams with the result The flagship pattern is now: Zerto post-script (curl, fire-and-forget) calls an Async webhook endpoint -> 202 in milliseconds -> Zerto's failover sequence is never blocked. The server runs the actual work in the background, with full output captured in the daily log. A ready-to-use Zerto-side script ships at scripts/examples/zerto-post-failover.ps1 - pure curl.exe (no PowerShell modules), reads the bearer token from a file the ZVM service account can read. The installer now bundles scripts/examples/ alongside docs/ so the example is also available locally at C:\Program Files\WebhookServer\scripts\examples\. Removed: docs/recipes/ad-password-reset.md. Updated: docs/README.md, README.md, the recipe content itself. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Restore installer GUI launch (via shellexec) + checkpoint descriptions Two follow-ups to the previous Config Checkpoints commit: 1. Bring back the post-install "Launch Webhook Server" checkbox in the installer. The previous attempt failed because Inno Setup's postinstall flag launches via CreateProcess after Setup exits, bypassing the GUI's requireAdministrator manifest. Adding the shellexec flag switches to ShellExecute, which DOES honor the manifest and triggers a clean UAC prompt - so the post-install GUI launch works as expected. 2. Each checkpoint now carries a description, stored in a sidecar .meta.json file next to the snapshot. Defaults: - Auto-on-save: "Before save" - Midnight scheduler: "Nightly auto-checkpoint" - Manual: opens a small dialog so the user can type a meaningful description (defaults to "Manual checkpoint" if blank) The dialog and pruning both clean up sidecars alongside snapshots. The Config Checkpoints grid grows a Description column between When and Size. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v0.1.2: bump checkpoint retention 30 -> 90 Each checkpoint is a few KB of JSON plus a tiny sidecar; even at 90 entries on a config with hundreds of endpoints the on-disk footprint is negligible (worst case ~20 MB). With daily auto-checkpoints plus on-save snapshots, 30 entries could fill in a couple weeks of moderate use; 90 gives a comfortable ~3-month window. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
# Concepts
|
||||
|
||||
If you've never used a webhook before, this is where to start. Five minutes, no surprises.
|
||||
|
||||
## What is a webhook?
|
||||
|
||||
A webhook is just **an HTTP URL that runs something when it gets called.** Some other tool — Zerto, GitHub, your monitoring system, a backup job — does an `HTTP POST` to that URL when an event happens. Whatever's listening on the URL takes that request and does work in response.
|
||||
|
||||
Concretely, a Zerto pre-script might do:
|
||||
|
||||
```powershell
|
||||
Invoke-WebRequest -Method POST -Uri http://webhooks.contoso.local:8080/hook/start-failover `
|
||||
-Body (@{ vmName = $env:ZertoVPGName } | ConvertTo-Json) `
|
||||
-ContentType application/json
|
||||
```
|
||||
|
||||
…and the server at `webhooks.contoso.local:8080` would receive that POST and run a PowerShell script you wrote.
|
||||
|
||||
## What does this server give you that you don't already have?
|
||||
|
||||
You could write a tiny ASP.NET listener, or run a PowerShell script behind IIS, or hand-craft `HttpListener` plumbing. People do, all the time. The trade-off is that **you then own the listener** — auth, retries, logging, restarts, a service wrapper, secret storage, an admin UI. That's where Webhook Server saves you a weekend.
|
||||
|
||||
What you get out of the box:
|
||||
|
||||
- A real **Windows Service** that survives reboots and runs without anyone logged in
|
||||
- Per-endpoint **authentication**: Bearer token, HMAC-signed (GitHub / Stripe / Slack style), or none
|
||||
- Per-endpoint **IP allowlist** (single IPs or CIDR ranges)
|
||||
- **Run-as identity**: the service runs as `LocalSystem` by default, but each individual hook can run as a domain account, the logged-in user, or whoever — without needing Task Scheduler in the middle
|
||||
- **Logging** (Serilog, daily-rolling files) plus a GUI tail
|
||||
- A WPF **GUI** for adding / editing / testing endpoints. No JSON file editing required.
|
||||
- **Outbound callbacks**: when a hook finishes, the server can POST the result to another URL, signed with HMAC, with retry-and-backoff
|
||||
- **HTTPS** via `.pfx` or a cert thumbprint from the local cert store
|
||||
- **Auto-snapshots** of your config on every save, with point-in-time restore from the GUI
|
||||
|
||||
## How the moving parts fit together
|
||||
|
||||
```
|
||||
+------------------+ named pipe +-------------------------------+
|
||||
| GUI (WPF) | <------------> | Windows Service |
|
||||
| add / edit / | SYSTEM+admin | - Kestrel: hook listener |
|
||||
| view logs | ACL'd | - Admin pipe server |
|
||||
+------------------+ | - Executor (process runner) |
|
||||
| - Callback dispatcher |
|
||||
| - Serilog file logging |
|
||||
+-------------------------------+
|
||||
|
|
||||
C:\ProgramData\WebhookServer\
|
||||
- config.json (DPAPI-encrypted secrets)
|
||||
- backups\ (auto-snapshots)
|
||||
- logs\ (daily rolling)
|
||||
```
|
||||
|
||||
- The **Windows Service** does the actual work: listens for HTTP requests, runs your scripts, writes logs.
|
||||
- The **GUI** is purely a config + monitoring tool. It talks to the service over a named pipe ACL'd to `SYSTEM` and `Administrators`. You can launch and close the GUI as you like; the service keeps running.
|
||||
- **Config + secrets** live in `C:\ProgramData\WebhookServer\config.json`. Secrets (bearer tokens, HMAC keys, run-as passwords, PFX passwords) are DPAPI-encrypted with the `LocalMachine` scope, so the same machine can decrypt them under any account but they don't travel to other machines.
|
||||
|
||||
## What's an "endpoint"?
|
||||
|
||||
An endpoint is one URL slug (the part after `/hook/`) plus a configuration: who's allowed to call it, how it's authenticated, what to run when it fires, and what to do with the result. Add as many as you want.
|
||||
|
||||
| Field | What it controls |
|
||||
|---|---|
|
||||
| **Slug** | The URL path. `deploy` → `http://host:8080/hook/deploy` |
|
||||
| **Auth** | None / Bearer / HMAC. None means anyone who can reach the URL can fire it. |
|
||||
| **Allowed clients** | List of IPs or CIDRs allowed to hit this slug. Empty = anyone reachable. |
|
||||
| **Executor** | What to run: Windows PowerShell 5.1, PowerShell Core (7+), `cmd` / `.bat`, or a path to any `.exe` |
|
||||
| **Run As** | Who the script runs as. See [Run As modes](runas-modes.md). |
|
||||
| **Data passing** | How request data reaches the script — JSON to stdin, headers / query as env vars, `{{template}}` arg expansion |
|
||||
| **Response mode** | Sync (the HTTP caller waits for the script to finish and gets its output) or Async (returns 202 immediately, runs in background) |
|
||||
| **Callback** | Optional outbound URL the server POSTs to with the run result. Required for async hooks if the original caller wants the result. |
|
||||
|
||||
## What it isn't
|
||||
|
||||
- **Not an HTTP server for serving static files or pages.** Just hook URLs and a `/healthz`.
|
||||
- **Not a queue.** No durable persistence of inbound requests; if the service crashes mid-execution that run is lost (the inbound caller will see the connection drop or a timeout).
|
||||
- **Not multi-tenant.** It's one config, one set of endpoints, one machine. Run multiple instances on different ports / different machines if you need separation.
|
||||
- **Not an internet-facing public-API server out of the box.** Lock down with HTTPS + auth + IP allowlist + a reverse proxy if you're going to expose it publicly. See [network & security](network-and-security.md).
|
||||
Reference in New Issue
Block a user