Windows
Many configuration keys were renamed or restructured in v27 (e.g. mac.sign, win.sign, electronGet, asar, nativeModules, snapcraft, fileOptions). Run electron-builder migrate-schema to rewrite your config automatically, then skim What's New in v27 and the full v27 Breaking Changes.
The top-level win key contains a set of options instructing electron-builder on how it should build Windows targets. These options are applicable to any Windows target.
Common Questions
How do you delegate code signing?
In v27, all Windows signing is configured through the single win.sign discriminated union (type: "signtool" | "hsm" | "pkcs11" | "azure"). To delegate signing to a custom function, set the sign field on that union — it works for the signtool, hsm and pkcs11 types. See the Windows Code Signing guide and why sign.js is called 8 times.
"win": {
"sign": {
"type": "signtool",
"sign": "./customSign.js",
"publisherName": "CN=My Company, O=My Company, C=US"
}
}
electron-builder cannot read the certificate your hook signs with, so set publisherName to that certificate's subject: it is written to app-update.yml, and electron-updater checks every downloaded update against it. It is never derived from a certificate for a hook, not even one in the config, so without it a build that writes app-update.yml (an nsis, nsis-web or electronUpdaterAware appx target with a publish configuration, including one inferred from a GitHub repository) fails. Set win.verifyUpdateCodeSignature: false instead only if your updates are not Authenticode-signed or you don't use electron-updater.
Copy the subject from a binary your hook has already signed (a previous release, or win-unpacked from an electron-builder --win dir build, which does not write app-update.yml) instead of typing it by hand. electron-builder cannot check it against the certificate the hook uses, and every component you list (CN, O, C, …) must match the certificate exactly — otherwise installed apps reject every later update:
- Windows (PowerShell):
(Get-AuthenticodeSignature .\dist\win-unpacked\<App>.exe).SignerCertificate.Subjectprints it in the form to use as-is. - macOS / Linux:
osslsigncode verify -in <App>.exe— theSubject:line under "Signer's certificate", printed as/C=US/ST=California/O=My Company, Inc./CN=My Company, Inc.. Keep onlyCN,OandCand write them asCN="My Company, Inc.", O="My Company, Inc.", C=US: OpenSSL names some other components differently from Windows (STinstead ofS, for example), and a value that contains a comma must be wrapped in double quotes.
The v26 win.signtoolOptions / win.azureSignOptions keys were removed — electron-builder migrate-schema rewrites them to win.sign automatically. See v27 Breaking Changes → Windows signing.
File customSign.js in the project root directory:
exports.default = async function(configuration) {
// your custom code
}
How do you use a custom verify function to enable nsis signature verification alternatives instead of powershell?
Use the NsisUpdater.verifyUpdateFileAuthenticodeSignature interface:
export type VerifyUpdateFileResult =
| { response: "success" }
| { response: "failure"; message: string }
export type VerifyUpdateFileAuthenticodeSignature = (
publisherName: string[],
path: string
) => Promise<VerifyUpdateFileResult>
Pass a custom verify function to the nsis updater. For example, if you want to use a native verify function, you can use win-verify-signature.
import { NsisUpdater } from "electron-updater"
import { verifySignatureByPublishName } from "win-verify-signature"
export default class AppUpdater {
constructor() {
const options = {
requestHeaders: {
// Any request headers to include here
},
provider: 'generic',
url: 'https://example.com/auto-updates'
}
const autoUpdater = new NsisUpdater(options)
autoUpdater.verifyUpdateFileAuthenticodeSignature = async (publisherName: string[], path: string) => {
const result = verifySignatureByPublishName(path, publisherName)
return result.signed ? { response: "success" } : { response: "failure", message: result.message }
}
autoUpdater.addAuthHeader(`Bearer ${token}`)
autoUpdater.checkForUpdatesAndNotify()
}
}
The built-in default uses windowsExecutableCodeSignatureVerifier, which runs Windows PowerShell's Get-AuthenticodeSignature and rejects an update it cannot verify (ERR_UPDATER_SIGNATURE_UNVERIFIABLE) — for example when powershell.exe is blocked, which electron-updater 6 answered by installing the update with a warning. Where PowerShell may not run on your users' machines, a native verifier like the one above keeps updates working: ship it in your first release built with electron-updater 7, since installs that cannot verify an update cannot receive a later release that adds it.
The default verify function also rejects an update whose signature Windows reports from a security catalog instead of one embedded in the installer, since an update installer is in no catalog. If your installers are catalog-signed on purpose, set autoUpdater.allowCatalogSignature = true (false by default): a valid catalog signature is then accepted, with a warning, when its signer matches publisherName. To decide it per release instead, build with win.allowCatalogSignature: true, which writes allowCatalogSignature: true into the latest.yml of the nsis and nsis-web targets: electron-updater honors it only when the signature of that manifest was verified against a trusted key, and ignores it with a warning otherwise. It is covered by the manifest signature, so turning it on or off for a published release means re-signing or republishing its latest.yml. electron-updater 7.0.0-alpha.8 to alpha.11 installs with an update key configured reject a signed manifest that sets allowCatalogSignature: true (ERR_UPDATER_MANIFEST_SIGNATURE_INVALID), the same way alpha.8 treats a signed files[].blockMapUrl. A custom verify function ignores both.
A custom verify function is called only with the publisherName of app-update.yml: without one, electron-updater rejects the update before any verify function runs, unless the app was built with win.verifyUpdateCodeSignature: false (see the v27 migration guide).
The older property verifyUpdateCodeSignature, which differs only in name and return interface, is deprecated and kept only as a compatibility shim (shall be removed in electron-builder v28). The protected _verifyUpdateCodeSignature member is likewise deprecated in favour of _verifyUpdateFileAuthenticodeSignature.
How do you create a Parallels Windows 10 Virtual Machine?
If you use Parallels, you must not use "Share Mac user folders with Windows" feature and must not run installers from such folders.
You don't need to have a Windows 10 license. A free license is provided (expires after 90 days, but this is not a problem because no additional setup is required).
- Open Parallels Desktop.
- File -> New.
- Select "Modern.IE" in the "Free Systems".
- Continue, Continue, Accept software license agreement.
- Select "Microsoft Edge on Windows 10".
- The next steps are general, see Installing Windows on your Mac using Parallels Desktop from "Step 6: Specify a name and location".
Parallels Windows 10 VM will be used automatically to build AppX on macOS. No need even start VM — it will be started automatically on demand and suspended after build. No need to specify VM — it will be detected automatically (first Windows 10 VM will be used).
electron-builder runs the Parallels Desktop command line tool by absolute path, from /Applications/Parallels Desktop.app/Contents/MacOS/prlctl or /usr/local/bin/prlctl, the locations its installer uses, or from toolsets.executables.prlctl; it is never looked up on PATH.
How do you create a VirtualBox Windows 10 Virtual Machine?
If you are not on macOS or don't want to buy Parallels Desktop, you can use free VirtualBox.
- Download a Windows evaluation ISO from the Microsoft Evaluation Center (Microsoft no longer publishes the prebuilt "MSEdge on Win10" virtual machines).
- Create a new virtual machine in VirtualBox and install Windows from the ISO.
VirtualBox is not supported by electron-builder for now, so you need to set up the build environment on Windows if you want to use VirtualBox to build AppX (and other Windows-only tasks).
Configuration
Interface: WindowsConfiguration
Extends
Properties
allowCatalogSignature?
readonlyoptionalallowCatalogSignature?:boolean
Whether electron-updater accepts an update installer whose signature Windows reports from a security catalog (a signed list of file hashes) instead of one embedded in the installer — for update installers that are catalog-signed on purpose, such as an enterprise deployment that adds their hashes to a catalog. The catalog signer must still match the publisher name.
When true, the latest.yml written for the nsis and nsis-web targets carries allowCatalogSignature: true. electron-updater
honors it only when the signature of that update manifest
was verified against a trusted key; in an unsigned manifest (or one signed by an untrusted key) it is ignored with a warning, and
catalog signatures stay rejected unless the app sets autoUpdater.allowCatalogSignature = true. Since it is covered by the manifest
signature, changing it for a published release means signing latest.yml again or republishing it.
Installs running electron-updater 7.0.0-alpha.8 to alpha.11 with an update key configured reject a signed manifest that sets it
(ERR_UPDATER_MANIFEST_SIGNATURE_INVALID).
Default
false
appId?
readonlyoptionalappId?:string|null
The application id. Used as CFBundleIdentifier for MacOS and as Application User Model ID for Windows (NSIS target only, Squirrel.Windows not supported). It is strongly recommended that an explicit ID is set.
Default
com.electron.${name}
Inherited from
PlatformSpecificBuildOptions.appId
artifactName?
readonlyoptionalartifactName?:string|null
The artifact file name template. Defaults to ${productName}-${version}.${ext} (some target can have other defaults, see corresponding options).
Inherited from
PlatformSpecificBuildOptions.artifactName
asar?
readonlyoptionalasar?:boolean|AsarOptions|null
Whether to package the application's source code into an archive, using Electron's archive format.
Node modules that must be unpacked will be detected automatically. Use AsarOptions.unpack to specify additional files to unpack.
Default
true
Inherited from
PlatformSpecificBuildOptions.asar
compression?
readonlyoptionalcompression?:CompressionLevel|null
The compression level. If you want to rapidly test build, store can reduce build time significantly. maximum doesn't lead to noticeable size difference, but increase build time.
Default
normal
Inherited from
PlatformSpecificBuildOptions.compression
defaultArch?
readonlyoptionaldefaultArch?:string
The default architecture to build for when no --arch flag is specified.
Defaults to the current machine's architecture.
Inherited from
PlatformSpecificBuildOptions.defaultArch
detectUpdateChannel?
readonlyoptionaldetectUpdateChannel?:boolean
Whether to infer update channel from application version pre-release components. e.g. if version 0.12.1-alpha.1, channel will be set to alpha. Otherwise to latest.
This does not apply to github publishing, which will never auto-detect the update channel.
Default
true
Inherited from
PlatformSpecificBuildOptions.detectUpdateChannel
electronLanguages?
readonlyoptionalelectronLanguages?:string|string[]
The electron locales to keep. By default, all Electron locales used as-is.
Inherited from
PlatformSpecificBuildOptions.electronLanguages
electronUpdaterCompatibility?
readonlyoptionalelectronUpdaterCompatibility?:string|null
The electron-updater compatibility semver range: the
electron-updater versions the installed apps ship, which have to read the update files this build writes. It selects the
.blockmap format (see blockmap), and the build fails when the app's electron-updater does not satisfy it.
Default
>=7
Inherited from
PlatformSpecificBuildOptions.electronUpdaterCompatibility
executableName?
readonlyoptionalexecutableName?:string|null
The executable name. Defaults to productName
Note: Except for Linux, where this would constitute a breaking change in previous behavior and lead to both invalid executable names and Desktop files. Ref comments in: https://github.com/electron-userland/electron-builder/pull/9068
Inherited from
PlatformSpecificBuildOptions.executableName
fileAssociations?
readonlyoptionalfileAssociations?:FileAssociation|FileAssociation[]
The file associations.
Inherited from
PlatformSpecificBuildOptions.fileAssociations
fileOptions?
optionalfileOptions?:FilesBuildOptions|null
Which files to copy into the packaged app (files, the app sources, extraResources and extraFiles), which file extensions to exclude
from it (excludedExts), and whether symlinks among them may lead outside the app and the workspace (allowExternalLinks).
Set at the configuration root, per platform (e.g. mac.fileOptions), or both: a platform's file lists are added to the root ones,
and a platform's excludedExts and allowExternalLinks replace the root ones.
{
"fileOptions": {
"files": ["dist/**/*", "package.json"],
"extraResources": [{ "from": "assets/bin", "to": "bin" }]
}
}
files, extraResources and extraFiles set directly on the configuration or a platform section are moved here
when the configuration is loaded, with a warning. Run electron-builder migrate-schema to update the configuration.
Inherited from
PlatformSpecificBuildOptions.fileOptions
forceCodeSigning?
readonlyoptionalforceCodeSigning?:boolean
Overrides the root forceCodeSigning for this platform: whether to fail the build if the app could not be code-signed,
notarized, or have its auto-update manifests signed, and to verify the signatures it produces. See the root option for
what is enforced. Mac App Store builds cascade mac → mas (→ masDev for mas-dev), like every other option, so mas.forceCodeSigning / masDev.forceCodeSigning apply to their targets only.
Default
false
Inherited from
PlatformSpecificBuildOptions.forceCodeSigning
generateUpdatesFilesForAllChannels?
readonlyoptionalgenerateUpdatesFilesForAllChannels?:boolean
Please see Building and Releasing using Channels.
Default
false
Inherited from
PlatformSpecificBuildOptions.generateUpdatesFilesForAllChannels
icon?
readonlyoptionalicon?:string|null
The path to application icon.
Default
build/icon.ico
Overrides
PlatformSpecificBuildOptions.icon
legalTrademarks?
readonlyoptionallegalTrademarks?:string|null
The trademarks and registered trademarks.
protocols?
The URL protocol schemes.
Inherited from
PlatformSpecificBuildOptions.protocols
publish?
optionalpublish?:Publish
Publisher configuration. See Auto Update for more information.
Inherited from
PlatformSpecificBuildOptions.publish
releaseInfo?
readonlyoptionalreleaseInfo?:ReleaseInfo
The release info. Intended for command line usage:
-c.releaseInfo.releaseNotes="new features"
Inherited from
PlatformSpecificBuildOptions.releaseInfo
requestedExecutionLevel?
readonlyoptionalrequestedExecutionLevel?:RequestedExecutionLevel|null
The security level at which the application requests to be executed.
Cannot be specified per target, allowed only in the win.
Default
asInvoker
sign?
readonlyoptionalsign?:false|WindowsSigningConfiguration|null
Code signing configuration. Code signing stamps every installer and executable electron-builder produces with an Authenticode signature, so that Windows (SmartScreen / UAC) and your auto-updater can verify the publisher and that the files were not tampered with.
How this option behaves:
-
Leave unset to sign using credentials discovered from the environment — primarily a certificate supplied via
WIN_CSC_LINK(orCSC_LINK) with its password inWIN_CSC_KEY_PASSWORD(orCSC_KEY_PASSWORD).WIN_CSC_LINKaccepts a file path, anhttps://URL, or a base64-encoded certificate. This is the recommended setup for CI. -
Set to
falseornullto disable code signing entirely (executable resources such as the icon and metadata are still edited). A build that writesapp-update.ymlthen also needs verifyUpdateCodeSignature set tofalse, since no publisher name is derived; if you sign outside electron-builder, use{ type: "signtool", publisherName: [...] }instead. -
Set to an object to configure signing explicitly. The required
typefield selects the signing backend (signtool,hsm,pkcs11, orazure) and dispatches to a dedicated sign manager; provide exactly one of the modes below. Whenwin.signis left unset, thesigntoolbackend is used with env-discovered credentials. Each output artifact is signed individually, and by default executables are dual-signed (seesigningHashAlgorithms). -
{ type: "signtool", ... }— Sign with a local certificate file (.pfx/.p12) or a certificate from the Windows certificate store. Uses Microsoftsigntool.exeon Windows andosslsigncodeon macOS/Linux. -
{ type: "hsm", ... }— Sign using a Hardware Security Module (HSM) or FIPS-compliant hardware token via signtool's/csp(cryptographic service provider) and/kc(key container) flags. Requires a modernwinCodeSigntoolset (the default — only the legacy"0.0.0"pin is unsupported). Windows-only. -
{ type: "pkcs11", ... }— Sign using a PKCS#11 hardware token via osslsigncode. Available on macOS and Linux CI without a Windows VM. -
{ type: "azure", ... }— Sign via Azure Trusted Signing (cloud service). Requires Azure Entra ID environment variables for authentication.
See Code Signing.
signExts?
readonlyoptionalsignExts?:string[] |null
Additional file name suffixes to code sign, beyond the default. By default electron-builder
only signs .exe files; list extra suffixes here to also sign e.g. .dll, .node, or
specific file names. Advanced option — most apps do not need it.
Each entry is matched with String.endsWith, so both bare extensions (".dll") and full file
names ("mybinary.dll") work. Prefix a pattern with ! to exclude a suffix that would
otherwise be signed. Positive patterns are evaluated first, then negative ones. For example,
["somefilename", ".dll", "!.appx"] signs .dll files (and anything ending in somefilename)
but never signs .appx files.
See
https://github.com/electron-userland/electron-builder/issues/7329
Default
null
target?
readonlyoptionaltarget?:TargetConfigType
The target package type: list of nsis, nsis-web (Web installer), portable (portable app without installation), appx, msix, msi, msi-wrapped, squirrel, 7z, zip, tar.xz, tar.lz, tar.gz, tar.bz2, dir.
AppX and MSIX packages can be built on Windows 10 or Windows Server 2012 R2 (version 6.3+) or later, and on macOS via Parallels Desktop.
To use Squirrel.Windows please install electron-builder-squirrel-windows dependency.
Default
nsis
Overrides
PlatformSpecificBuildOptions.target
updateManifest?
readonlyoptionalupdateManifest?:false|UpdateManifestSigningOptions|null
Ed25519 signing of the auto-update manifest (latest*.yml). Each manifest is signed and its public key is
embedded into app-update.yml, so electron-updater verifies the signature before downloading an update.
Signing is required. Publishing a build that emits auto-update metadata fails unless a signing key
resolves. Generate one once with electron-builder create-update-key, then supply it via
ELECTRON_BUILDER_UPDATE_SIGN_KEY (the PEM file, base64-encoded) / ELECTRON_BUILDER_UPDATE_SIGN_KEY_FILE (its path),
preferred in CI, or via signingKey / signingKeyFile below. Leaving this option unset — or null — keeps signing required and
resolves the key from the environment; null is not an opt-out.
Set to false, the only opt-out, to ship unsigned manifests. Every build that produces a manifest then
logs a warning. false also short-circuits the environment variables, so a leftover
ELECTRON_BUILDER_UPDATE_SIGN_KEY in CI cannot re-enable signing by accident.
The requirement is enforced when a publish policy is in effect (--publish) or forceCodeSigning is set; any other
build warns instead, so local builds and pipelines that sign the manifest in a later step of their own are
unaffected. It is also waived when every publish provider has publishAutoUpdate: false, since no manifest is
emitted then, and for a build whose targets write no update info (e.g. only snap, flatpak, MSI/MSIX, portable,
mas/pkg or plain archives). A publishing (or forceCodeSigning) build checks for the key at build start, before
anything is packed or uploaded. Every signed manifest is read back and verified before it is written.
Inherited from
PlatformSpecificBuildOptions.updateManifest
verifyUpdateCodeSignature?
readonlyoptionalverifyUpdateCodeSignature?:boolean
Whether the NSIS auto-updater should verify the Authenticode signature of a downloaded update before installing it. The verification itself runs in your app, via electron-updater.
When enabled (the default), the resolved publisher name is embedded into
app-update.yml at build time. At update time electron-updater inspects the certificate that
signed the downloaded installer and compares its subject (Distinguished Name) against that
publisher name, refusing to install on a mismatch or when the signature cannot be verified.
This prevents a tampered or maliciously substituted update from being installed.
While enabled, electron-builder also checks at build time that the signed NSIS installer (or nsis-web stub) is signed by a certificate matching that publisher name, using the same matching rules, and fails the build otherwise.
Since v27 a build that writes app-update.yml (an nsis, nsis-web or electronUpdaterAware
appx target with a publish configuration) fails while this is enabled and no publisher name
resolves (sign: false / null, no certificate, publisherName: null): electron-updater 7
rejects every update of an app whose app-update.yml has no publisher name. Sign the build, set
publisherName, or set this to false.
Set to false to skip verification explicitly — the publisher name is then not embedded, and
app-update.yml carries verifyUpdateCodeSignature: false instead, which tells electron-updater
to install updates without verifying their signature. This is the only opt-out.
Disable this only if your updates are not Authenticode-signed.
Default
true