pkg
The top-level pkg key contains set of options instructing electron-builder on how it should build macOS PKG product archive installers.
When to Use PKG
PKG (.pkg) files are macOS installer packages that run Apple's native Installer application. Use PKG when:
- System-level installs are required — installing launch daemons, kernel extensions (or System Extensions on modern macOS), or files outside
/Applications - Custom install scripts are needed — pre/postinstall shell scripts run with root privileges during installation
- Enterprise managed deployment — PKG integrates with MDM systems and software management tools like Munki, Jamf, and SCCM for macOS
- Installer UI customization — displaying welcome screens, license agreements, readme files, and conclusion pages
For standard consumer app distribution, DMG is the conventional choice. For Mac App Store distribution, see MAS.
Certificate Requirements
Signing a PKG file requires a Developer ID Installer certificate — this is a different certificate from the Developer ID Application certificate used to sign the app bundle inside the PKG.
pkg:
identity: "Developer ID Installer: My Company (TEAM1234AB)"
Or use the CSC_INSTALLER_LINK and CSC_INSTALLER_KEY_PASSWORD environment variables in CI.
You can have both Developer ID Application and Developer ID Installer certificates. The application certificate signs the .app bundle, and the installer certificate signs the .pkg wrapper.
Installation Location
By default the app is installed to /Applications. Override with installLocation:
pkg:
installLocation: "/Applications"
Setting a non-standard install location (e.g., /usr/local/bin) is unusual for Electron apps but may be needed for CLI tools bundled with the app.
Install Scripts
Place shell scripts in the scripts directory (default: build/pkg-scripts/). These run at install time with root privileges:
| Script Name | When It Runs |
|---|---|
preinstall | Before files are installed |
postinstall | After files are installed |
preupgrade | Before an upgrade (rarely used) |
postupgrade | After an upgrade (rarely used) |
pkg:
scripts: build/pkg-scripts # default
Example postinstall script:
#!/bin/bash
# Register a launch daemon after install
launchctl load /Library/LaunchDaemons/com.mycompany.myapp.daemon.plist
exit 0
Scripts must be executable (chmod +x). Scripts run as root during installation — test thoroughly. A failing script (non-zero exit code) will abort the installation.
See the macOS Kernel Extensions tutorial for a detailed example.
Installer UI Customization
Customize the pages displayed in Apple's Installer:
pkg:
welcome: build/welcome.html # or .rtf, .txt
license: build/license.html # or .rtf, .txt
conclusion: build/conclusion.html
Supported file formats for each page: HTML, RTF, plain text.
Background image — displayed behind the installer pages (macOS 10.5+):
pkg:
background:
file: build/installer-background.png
alignment: center # center | left | right | top | bottom | topleft | topright | bottomleft | bottomright
scaling: tofit # tofit | proportional | none
Installation Behavior Options
Control how the installer behaves when re-installing or upgrading:
| Option | Default | Description |
|---|---|---|
isRelocatable | true | Allow users to choose a different install location |
isVersionChecked | true | Block downgrades (PKG with older version won't install over newer) |
hasStrictIdentifier | true | Require matching bundle ID for upgrades |
overwriteAction | upgrade | upgrade (recommended) or update |
For most apps, leave these at their defaults.
Forcing App Closure Before Install
If your installer or upgrade requires the app to not be running:
pkg:
mustClose:
- com.mycompany.myapp
- com.mycompany.myapp.helper
The Installer will prompt the user to quit any running processes with matching bundle IDs before proceeding.
Extra Component Packages
Bundle additional .pkg files alongside the main component:
pkg:
extraPkgsDir: build/extra-pkgs
All .pkg files in this directory will be included as additional components in the installer. Useful for installing additional software alongside your app (e.g., a CLI tool, a system extension).
Complete Example
pkg:
identity: "Developer ID Installer: My Company (TEAM1234AB)"
installLocation: "/Applications"
scripts: build/pkg-scripts
welcome: build/welcome.html
license: build/license.rtf
conclusion: build/conclusion.html
background:
file: build/background.png
alignment: center
scaling: tofit
mustClose:
- com.mycompany.myapp
isRelocatable: true
overwriteAction: upgrade
Troubleshooting
"The package is not signed" error: Ensure you have a valid Developer ID Installer certificate (not Application). Check the certificate identity string matches exactly.
Script fails silently: Run the PKG in verbose mode via Terminal: sudo installer -verbose -pkg YourApp.pkg -target /. Non-zero exit from a script aborts installation.
App not found after install: Verify installLocation is correct and the app bundle ends up at the expected path. Check Console.app for installer logs.
PKG won't overwrite existing version: The isVersionChecked: false option disables version checking, allowing downgrades.
Configuration
Interface: PkgOptions
macOS product archive options.
Extends
Properties
allowAnywhere?
readonlyoptionalallowAnywhere?:boolean|null
Whether can be installed at the root of any volume, including non-system volumes. Otherwise, it cannot be installed at the root of a volume.
Corresponds to enable_anywhere.
Default
true
allowCurrentUserHome?
readonlyoptionalallowCurrentUserHome?:boolean|null
Whether can be installed into the current user’s home directory. A home directory installation is done as the current user (not as root), and it cannot write outside of the home directory. If the product cannot be installed in the user’s home directory and be not completely functional from user’s home directory.
Corresponds to enable_currentUserHome.
Default
true
allowRootDirectory?
readonlyoptionalallowRootDirectory?:boolean|null
Whether can be installed into the root directory. Should usually be true unless the product can be installed only to the user’s home directory.
Corresponds to enable_localSystem.
Default
true
artifactName?
readonlyoptionalartifactName?:string|null
The artifact file name template.
Inherited from
TargetSpecificOptions.artifactName
background?
readonlyoptionalbackground?:PkgBackgroundOptions|null
Options for the background image for the installer.
conclusion?
readonlyoptionalconclusion?:string|null
The path to the conclusion file. This may be used to customize the text on the final "Summary" page of the installer.
extraPkgsDir?
readonlyoptionalextraPkgsDir?:string|null
The extra component packages directory (relative to build resources directory) for MacOS product archive
Autoscans directory for any .pkg files and adds to productbuild command as --package-path and --package accordingly
hasStrictIdentifier?
readonlyoptionalhasStrictIdentifier?:boolean|null
Require identical bundle identifiers at install path?
Default
true
identity?
readonlyoptionalidentity?:string|null
The name of certificate to use when signing. Consider using environment variables CSC_LINK or CSC_NAME instead of specifying this option.
installLocation?
readonlyoptionalinstallLocation?:string|null
The install location. Do not use it to create per-user package.
Mostly never you will need to change this option. /Applications would install it as expected into /Applications if the local system domain is chosen, or into $HOME/Applications if the home installation is chosen.
Default
/Applications
isRelocatable?
readonlyoptionalisRelocatable?:boolean|null
Install bundle over previous version if moved by user?
Default
true
isVersionChecked?
readonlyoptionalisVersionChecked?:boolean|null
Don't install bundle if newer version on disk?
Default
true
license?
readonlyoptionallicense?:string|null
The path to EULA license file. Defaults to license.txt or eula.txt (or uppercase variants). In addition to txt, rtf and html supported (don't forget to use target="_blank" for links).
mustClose?
readonlyoptionalmustClose?:string[] |null
Identifies applications that must be closed before the package is installed.
Corresponds to must-close.
overwriteAction?
readonlyoptionaloverwriteAction?:"update"|"upgrade"|null
Specifies how an existing version of the bundle on disk should be handled when the version in the package is installed.
If you specify upgrade, the bundle in the package atomi-cally replaces any version on disk; this has the effect of deleting old paths that no longer exist in the new version of the bundle.
If you specify update, the bundle in the package overwrites the version on disk, and any files not contained in the package will be left intact; this is appropriate when you are delivering an update-only package.
Another effect of update is that the package bundle will not be installed at all if there is not already a version on disk; this allows a package to deliver an update for an app that the user might have deleted.
Default
upgrade
publish?
optionalpublish?:Publish
Inherited from
scripts?
readonlyoptionalscripts?:string|null
The scripts directory, relative to build (build resources directory).
The scripts can be in any language so long as the files are marked executable and have the appropriate shebang indicating the path to the interpreter.
Scripts are required to be executable (chmod +x file).
Default
build/pkg-scripts
See
Scripting in installer packages.
welcome?
readonlyoptionalwelcome?:string|null
The path to the welcome file. This may be used to customize the text on the Introduction page of the installer.