Windows installer
The MSI installs the engine as a Windows service, Ductus, with a settings file, a folder for
the project and its logs, and an Event Log source. It installs silently for Group Policy, SCCM
or Intune, and upgrades in place.
Use it on a Windows server that runs Ductus for real. Don't where you can't run an
installer (then the .zip has the program alone), or to try Ductus on your own
machine (ductus dev needs no installer and no administrator).
Unsigned before v1.0. The installer isn't signed with a code-signing certificate yet, so Windows SmartScreen says "Windows protected your PC" and "unknown publisher" when it's run from a download. Check the file before you run it: its SHA-256 against the release's
SHA256SUMS(Get-FileHash ductus-0.6.0-x64.msi), and that GitHub built it from the tagged source (gh attestation verify ductus-0.6.0-x64.msi -R thorst/ductus): both are on Downloading and checking a release. Then "More info" → "Run anyway", or unblock it first (Unblock-File). Signing comes with v1.0 (nuance).
Install
As an administrator:
msiexec /i ductus-0.6.0-x64.msi /qn # silent; without /qn, the usual wizard
Before v0.6.0 is released, MSIs are development builds: packaging/windows/build.ps1 in a clone
of the repository makes one (it needs Rust, the Visual Studio Build Tools and WiX 5: see
packaging/README.md).
The install registers the service (it starts automatically at boot) but doesn't start it: nothing is configured yet, and without a database it would stop at once.
What the installer puts where
| Path | What |
|---|---|
C:\Program Files\Ductus\ductus.exe | The engine and its command line (the web UI is inside it). The folder is on the system PATH. |
C:\ProgramData\Ductus\ductus.env | Settings (NAME=value lines): the database URL, the project, the environment, the secrets key. Written once as a template; never overwritten. |
C:\ProgramData\Ductus\project\ | The project (a Git clone, usually). |
C:\ProgramData\Ductus\logs\ | ductus.<date>.log, a file a day, the last 14 kept. |
Service Ductus | "Ductus Integration Engine": ductus.exe run --service --env-file C:\ProgramData\Ductus\ductus.env, as NT SERVICE\Ductus unless you choose another account (below). |
Event Log source Ductus | In the Application log: what operations teams watch for (IDs). |
C:\ProgramData\Ductus can be read by administrators, SYSTEM and the service only: ductus.env
holds the database password. Keep it that way.
The service's account
The account is what SQL Server, file shares and anything else on the network see when the engine logs in with Windows. Three choices (nuance):
| Account | How | When |
|---|---|---|
NT SERVICE\Ductus (the default) | Nothing to do. A virtual account: no password; on the network it is the computer (HOSPITAL\SERVER01$). | The engine logs in to nothing with Windows, or a DBA grants the computer's account. |
| A gMSA (group managed service account) | msiexec /i ductus-0.6.0-x64.msi /qn SERVICEACCOUNT=HOSPITAL\svc-ductus$ | The engine needs its own identity on the network (a SQL Server Windows login, a share). Windows keeps the password; upgrades keep the account. The best choice when you need one. |
| An account with a password | Install, then ductus service account HOSPITAL\svc-ductus --start (it asks for the password; --password-stdin in scripts) | Only where a gMSA isn't possible: after every upgrade the service waits for the password again (why). |
The installer (and ductus service account) grants the account "Log on as a service". Where
Group Policy manages that right, ask for the account to be added to the policy, or the next
policy refresh takes it away (nuance).
ductus service account with no name says who the service runs as now.
Folders outside C:\ProgramData\Ductus. The service can touch only what you give it: a file
interface's inbox, archive or output folder needs a grant
(nuance):
icacls "D:\Interfaces" /grant "NT SERVICE\Ductus:(OI)(CI)M"
That works whatever account runs the service (its own SID is in its token). For a network share,
grant the computer account (HOSPITAL\SERVER01$), or the gMSA.
Configure
-
Settings. Edit
C:\ProgramData\Ductus\ductus.envas an administrator (Notepad run as administrator works). At least the database:DUCTUS_DATABASE_URL=postgres://ductus:PASSWORD@db1.hospital.org/ductus?sslmode=verify-full DUCTUS_PROJECT=C:\ProgramData\Ductus\project DUCTUS_ENV=prod DUCTUS_SECRET_KEY=…No quotes are needed, and backslashes are plain backslashes here. Every variable is in the install overview; the database's login and TLS are on the PostgreSQL page. Secrets are never installer properties (they'd be written to the install log): the password lives in this file only.
-
The project. Clone it into
C:\ProgramData\Ductus\project(or pointDUCTUS_PROJECTelsewhere and grant the service read access there). In YAML, write Windows paths with their drive and in single quotes ('D:\Interfaces\in'): in double quotes a backslash starts an escape (nuance). -
Check before starting, with the service's own settings:
ductus validate --env-file C:\ProgramData\Ductus\ductus.env --root C:\ProgramData\Ductus\project ductus doctor --env-file C:\ProgramData\Ductus\ductus.env --root C:\ProgramData\Ductus\projectThese run as you, not as the service's account: a folder or a SQL Server Windows login can pass here and fail for the service. The service's log says "access denied" then.
Start, stop, look
Start-Service Ductus # after a change to ductus.env: Restart-Service Ductus
Get-Service Ductus
Get-ChildItem C:\ProgramData\Ductus\logs\ductus.*.log | Sort-Object LastWriteTime |
Select-Object -Last 1 | Get-Content -Tail 50 -Wait # the newest log, as it grows
The log files are named by the date in UTC (ductus.2026-10-30.log), so near midnight the
newest one may carry tomorrow's or yesterday's date.
- Starting and stopping report progress to the service manager, so a long migration or a stop finishing the messages in hand isn't taken for a hang.
- A stop is clean, whether from the service manager, a Windows shutdown (the service takes
its preshutdown time, 90 s) or
ductus drain --stop: the messages in hand are finished and saved (what finishes). - A restart is a short gap: measured 0 refused, a few connections reset, the longest wait for an ACK ~1.1 s (measured). Senders resend by themselves.
- If it fails it's started again after a minute, twice, then waits for a person. A start refused because another engine runs these interfaces isn't retried.
- The Event Log gets what operations watch for: started, stopped, couldn't start (with the reason), an interface stopped, a critical alert, and other errors at most once a minute per kind (IDs, nuance). The detail is in the log files.
Upgrade
Run the new version's ductus upgrade --check from its .zip
first, then the new MSI the same way as the first (msiexec /i … /qn; no need to uninstall).
The installer stops the service cleanly, replaces the program and starts it again; settings,
project and logs are never touched. The engine is down for 3.1–3.5 s (measured: a few
connections refused, nothing lost), so pick a quiet moment
(measured).
A sender sending through an upgrade over TLS, on CI's runner: 8 connection attempts refused, the
slowest message 3.3 s to its ACK, 12,000 of 12,000 received once each and in order
(the demo's output).
- A service someone stopped on purpose stays stopped after the upgrade (nuance).
- A password account leaves the service stopped, waiting for
ductus service account NAME --start(Event Log 1005 says so). - Where Group Policy turns Restart Manager off, msiexec may wait 100–160 s before it stops the service (the engine keeps running meanwhile). Close Event Viewer first, or stop the service yourself first to save the wait (why).
- Rolling back is uninstalling, then installing the previous MSI: the installer refuses to put
an older version over a newer one ("A newer version of Ductus is already installed. Uninstall
it first to go back.").
C:\ProgramData\Ductusand the database stay; giveSERVICEACCOUNT=again if the service ran as another account. The database changes a version makes only ever add, so the version before runs on them (Going back).demo-windows.ps1goes back this way on every push.
Uninstall
"Apps" in Settings, or msiexec /x ductus-0.6.0-x64.msi /qn: removes the service, the program
and the Event Log source. C:\ProgramData\Ductus (settings, project, logs) stays, and so does
everything in the database.