NSIS installer doesn't replace externalBin sidecar on reinstall; path resolution undocumented
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 111k
- Forks
- 4k
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 44
Description
Tauri v2 NSIS Installer: externalBin Sidecar Not Replaced on Reinstall
Summary
When using Tauri v2's externalBin feature with NSIS installers, the sidecar binary may not be replaced during reinstalls or upgrades. This leads to the installed application running a stale sidecar while the main Tauri app binary is correctly updated. The behavior is silent — no errors are reported during install — making it difficult to diagnose.
Environment
- Tauri: v2 (CLI and bundler)
- Platform: Windows 11 (x64)
- Installer: NSIS (via
bundle.targets: ["nsis"]) - Sidecar: PyInstaller-built Python exe (~71MB), configured via
bundle.externalBin
Configuration
{
"bundle": {
"active": true,
"targets": ["nsis"],
"externalBin": ["quote-sidecar"]
}
}
The sidecar binary is placed at:
src-tauri/quote-sidecar-x86_64-pc-windows-msvc.exe
The Problem
Issue 1: Stale sidecar bundled from wrong path
What happened: After rebuilding the sidecar binary and running tauri build, the NSIS installer continued to bundle the old sidecar. The main Tauri app (Rust binary) was correctly rebuilt, but the sidecar inside the installer was stale.
Root cause: Tauri copies the sidecar to src-tauri/target/release/quote-sidecar.exe (stripping the target triple) during the first build. On subsequent builds, if this cached copy exists and the build system doesn't detect the source has changed, it reuses the stale cached copy.
Evidence: The generated NSIS script (target/release/nsis/x64/installer.nsi) correctly references src-tauri/quote-sidecar-x86_64-pc-windows-msvc.exe — but by the time NSIS runs, Tauri's bundler has already resolved the binary path. In our case, a stale 188MB binary persisted while the rebuilt binary was 71MB.
Fix: We had to manually ensure the file at src-tauri/quote-sidecar-{target-triple}.exe was the current build. A binaries/ subdirectory we had been using was not the path Tauri resolves — externalBin resolves relative to src-tauri/, not src-tauri/binaries/.
Issue 2: NSIS installer doesn't replace sidecar on same-version reinstall
What happened: Even when the correct sidecar was bundled in the installer, reinstalling the same version (0.1.0 → 0.1.0) did not overwrite the installed sidecar binary. The main app exe was replaced, but the sidecar was left untouched.
Root cause: NSIS file replacement behavior during same-version installs. The sidecar exe has no Windows version resource (it's a PyInstaller-built binary), so NSIS's version comparison logic may skip it. Additionally, if the sidecar process is still running when the installer copies files, the copy silently fails.
Partial mitigation: We added NSIS installer hooks to kill the running sidecar before install:
; src-tauri/installer-hooks.nsh
!macro NSIS_HOOK_PREINSTALL
nsExec::Exec 'taskkill /F /IM quote-sidecar.exe'
nsExec::Exec 'taskkill /F /IM coda-quote.exe'
Sleep 1000
Delete "$INSTDIR\quote-sidecar.exe"
!macroend
{
"bundle": {
"windows": {
"nsis": {
"installerHooks": "installer-hooks.nsh"
}
}
}
}
This helps with the "file in use" problem but doesn't fully solve the version-comparison issue.
Issue 3: CSP blocks sidecar API in production builds
What happened: The sidecar API (http://127.0.0.1:8000) worked fine in dev mode but returned no data in the installed production app. No errors were visible.
Root cause: In dev mode, the frontend runs on http://localhost:1420. In production, Tauri serves from https://tauri.localhost. The default CSP allowed connect-src to http://127.0.0.1:8000, but the production origin (https://tauri.localhost) treating requests to http:// as mixed content.
Fix: Added https://tauri.localhost to CSP and dangerousDisableAssetCspModification:
{
"app": {
"security": {
"csp": "default-src 'self'; connect-src 'self' http://localhost:8000 http://127.0.0.1:8000 https://tauri.localhost; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'",
"dangerousDisableAssetCspModification": true
}
}
}
Documentation Gaps
-
externalBinpath resolution is not clearly documented. The docs don't explicitly state thatexternalBin: ["quote-sidecar"]resolves tosrc-tauri/quote-sidecar-{target-triple}.exe. Users may assume it resolves from abinaries/subdirectory (which some Tauri v1 examples showed). -
No mention of sidecar caching in
target/release/. When rebuilding a sidecar outside of Cargo (e.g., PyInstaller, Go, etc.), the cached copy intarget/release/is not automatically invalidated. The docs should warn about this. -
NSIS reinstall behavior with unversioned binaries is not documented. The docs describe
installerHooksbut don't explain that sidecars without Windows version resources may not be replaced on reinstall. -
CSP for production sidecar communication is not covered in the sidecar documentation. The dev → production origin change (
http://localhost→https://tauri.localhost) is a common gotcha for sidecar architectures.
Recommendations for Tauri
For the build system:
- Always re-copy
externalBinfiles totarget/release/before bundling, comparing checksums rather than relying on timestamp/existence checks. - Log the sidecar path and size during
tauri buildso developers can verify the correct binary is being bundled. - Warn if
target/release/{sidecar}.exeis older thansrc-tauri/{sidecar}-{triple}.exe.
For NSIS installer:
- Default to
SetOverwrite onfor sidecar binaries, or always delete-then-copy to handle unversioned executables. - Include process termination for known sidecar binaries in the default NSIS template (pre-install hook).
For documentation:
- Explicitly document
externalBinpath resolution:src-tauri/{name}-{target-triple}{.exe}. - Add a "Rebuilding Sidecars" section covering the
target/release/cache issue for non-Cargo sidecars. - Add CSP guidance for sidecar communication in production builds.
- Document
installerHookswith a practical sidecar example (kill process, delete old binary).
What Finally Worked
- Place sidecar at
src-tauri/quote-sidecar-x86_64-pc-windows-msvc.exe(not in a subdirectory) - Use
--cleanflag with PyInstaller and clear__pycache__before building - Use NSIS
installerHooksto kill running processes and delete the old binary pre-install - Add
dangerousDisableAssetCspModification: trueandhttps://tauri.localhostto CSP - Bump the version number when making sidecar changes to force NSIS to treat it as an upgrade
- Add
npm run build:sidecarscript to standardize the sidecar build with correct output path
Build Commands (Working)
# 1. Build the sidecar (outputs to src-tauri/)
npm run build:sidecar
# 2. Build the Tauri app + installer
npm run tauri:build
# Installer output:
# src-tauri/target/release/bundle/nsis/
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src-tauri/installer-hooks.nsh, the generated target/release/nsis/x64/installer.nsi, and the bundle.externalBin and app.security configuration shown in the report. Reproduce the sidecar build and NSIS reinstall behavior, then verify that the documented path resolution, rebuild guidance, installer behavior, and production CSP guidance match the observed workflow.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- build-system, desktop, documentation, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100