Desktop releases
This page is for maintainers who publish the Nod desktop app, and for anyone helping private-alpha testers install it.
The short version: run Release desktop, review and merge the version pull request, and CI publishes one GitHub release with all three installers.
flowchart TD run([Run Release desktop]):::accent --> pr[Review and merge<br/>the version PR] pr --> ci[CI passes on the<br/>merge commit] ci --> arm[Mac Apple silicon] ci --> intel[Mac Intel] ci --> win[Windows x64] arm --> rel[One GitHub release]:::go intel --> rel win --> rel
Each release is named Nod v0.x.x and links these installers:
| Platform | Installer | Updates |
|---|---|---|
| Mac Apple silicon | nod-arm64.dmg |
Automatic |
| Mac Intel | nod-x64.dmg |
Automatic |
| Windows x64 | nod-Setup-x64.exe |
Automatic |
Mac ZIP files, runtime packs, checksums, the public certificate and update metadata stay on the same release as supporting assets.
Desktop builds include the server source, built web files, production dependencies, required runtime files, and licenses. The server runs TypeScript through tsx.
Builds exclude frontend source, duplicate public files, lockfiles, development package settings, source maps, and type declarations. Dependency tests, examples, build scripts, and unused TypeScript sources are also excluded. Files that a package declares as runtime entry points stay in the bundle. Speech source archives stay with their licenses.
Packaged windows disable DevTools. The production menu excludes developer tools and force reload. It keeps standard reload, zoom, fullscreen, and onboarding replay. Source runs keep the development controls.
Before signing or making an installer, both platform builds disable Node option injection, Node inspector flags, and extra file-protocol privileges. They enable cookie encryption and check the binary settings. Node execution stays enabled because the audio decoder runs in a separate child process.
The runtime dependency overrides use patched Sharp and Undici versions. A single Sharp version avoids duplicate native image libraries.
Configure the repository once
Section titled “Configure the repository once”CI signs Mac builds with n8n's Apple Developer ID and has Apple notarize them, on Blacksmith's Mac runners, so these credentials reach those runners. Create a GitHub environment named release with these values. Never commit certificate keys or passwords.
| Kind | Name | Value |
|---|---|---|
| Secret | APPLE_CERTIFICATE |
Base64-encoded PKCS#12 with the certificate, its private key and Apple's G2 certificate |
| Secret | APPLE_CERTIFICATE_PASSWORD |
The PKCS#12 export password |
| Secret | APPLE_API_KEY |
The App Store Connect team API key (.p8) that notarizes builds |
| Variable | APPLE_API_KEY_ID |
That key's ID |
| Variable | APPLE_API_ISSUER |
The issuer ID shown above the team keys |
| Variable | APPLE_TEAM_ID |
The 10-character Apple team ID |
| Variable | APPLE_SIGNING_IDENTITY |
The exact certificate name, Developer ID Application: n8n GmbH (<team ID>) |
| Variable | APPLE_CERTIFICATE_SHA256 |
Lowercase SHA-256 of the certificate, from shasum -a 256 developerID_application.cer |
| Variable | NOD_SIGNING_MODE |
developer-id |
| Optional variable | NOD_DESKTOP_UPDATE_SOURCE_URL |
Base URL of the private update service. Leave it unset to use the public GitHub API. |
- In the repository's Actions settings, allow GitHub Actions to create pull requests.
- The default mode,
self-signed, signs with an internal certificate and skips notarization. It needs only the certificate rows and a private repository. - The Terminal installer pins the certificate's SHA-256 in
deployment/n8n/install.sh. After the first release signed with a new certificate, update it there and republish the Nod Install workflow.
Windows signing
Section titled “Windows signing”Windows builds are signed with Azure Artifact Signing, so Windows shows n8n GmbH as the publisher. Microsoft keeps the key, and GitHub needs no secret for it. The Windows release job signs in to Azure with GitHub's sign-in token for the release environment, which pull request jobs can't get.
| Azure resource | Name |
|---|---|
| Subscription | n8n Labs |
| Resource group | nod-signing, West Europe |
| Signing account | n8n-nod, Basic plan |
| Certificate profile | nod-windows, Public Trust |
| App registration | nod-release-signing, with the profile's signer role only |
The account, profile, tenant and app IDs are in desktop/scripts/windows-signing.mjs. None of them is secret.
Microsoft verified n8n GmbH once for the profile. It emails the primary contact from 60 days before that verification expires, and signing stops if it lapses. Renew it in the signing account under Identity validations.
Create or renew the certificate
Section titled “Create or renew the certificate”Developer ID certificates expire. Apps signed before then keep opening, but releases fail until you renew. Only the Apple account holder, or an admin they allow, can create one.
-
Create a private key and a signing request.
Terminal mkdir -m 700 ~/nod-signing && cd ~/nod-signing/usr/bin/openssl req -new -newkey rsa:2048 -nodes -keyout nod.key -out nod.csr -subj "/CN=n8n GmbH/C=DE" -
In the Apple Developer account, open Certificates, select +, then Developer ID Application and G2 Sub-CA. Upload
nod.csrand downloaddeveloperID_application.cerinto the same folder. -
Bundle the certificate with its key and Apple's G2 certificate. Without the G2 certificate, a runner can find no valid signing identity. Use macOS's
/usr/bin/openssl, because the keychain can reject files from Homebrew's OpenSSL.Terminal curl -fsSLO https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer/usr/bin/openssl x509 -inform DER -in DeveloperIDG2CA.cer -out g2.pem/usr/bin/openssl x509 -inform DER -in developerID_application.cer -out nod.pem/usr/bin/openssl pkcs12 -export -inkey nod.key -in nod.pem -certfile g2.pem -out nod.p12 -
For a new notarization key, open App Store Connect → Users and Access → Integrations → App Store Connect API → Team Keys. Generate a key with the Developer role and download it. Apple offers the download only once.
-
Save
nod.p12, its password and the.p8key in the company password manager. Set the values above, then delete the folder.
Private releases use the configured n8n download service for first-run downloads and updates. Its GitHub credential stays in n8n, and no token enters the app.
Release a version
Section titled “Release a version”-
Open Actions → Release desktop → Run workflow on
main. Leave version empty for the next patch, or enter a version such as0.2.0. -
Review the
release/desktoppull request. It changes only the desktop version, the release manifest and the changelog, with notes grouped by Conventional Commit type. Edit the notes if a change needs more explanation. -
Merge after review and CI. If
mainchanges before you merge, run Release desktop again to update the source and notes. -
Wait for CI on the merge commit, then Build desktop release. The release workflow builds all three installers and signs the Mac and Windows apps. It checks Mac updates, signature rejection and profile preservation on both Mac architectures. It also checks signing, runtime hashes, Windows workspace paths, installation, startup, updates and downloaded installer bytes. On Windows, every
.exe,.dlland.nodefile in the installed app,Uninstall.exeand the installer itself must carry a valid, timestamped n8n GmbH signature. Files identical to ones Windows ships, such asd3dcompiler_47.dll, are signed too, but Windows reports its own catalog signature for them, so the check accepts that instead when Microsoft signed it. It publishes one release only if every build and check passes. When the n8n download service is configured, it fetches each installer, runtime pack and update through that service. This check uses the app's own update code for both Macs and Windows. If any download is unavailable, the release goes back to draft.
Nod releases are tagged nod-v*, and the n8n download service at webhook/nod/desktop serves only those.
There's no daily release. Only a merged release pull request, which changes desktop/release.json, starts Build desktop release; other merges to main don't run it. The capability evals don't gate publication.
Pull requests and normal merges to main run source checks and isolated native update fixtures on Windows and both Mac architectures when desktop files change. These fixtures check secure storage, installer failures and saved-profile preservation without publishing a release. Packaging the complete desktop apps and verifying their release assets runs in Build desktop release.
The required Checks, tests and build result waits for both Mac update checks. If either Mac check fails, that required result fails too.
Inspect or recover a build
Section titled “Inspect or recover a build”The Build desktop release workflow runs on main by hand for a draft or a recovery run.
| Input | Off | On |
|---|---|---|
| automatic | Use the version and notes from the merged release pull request | Pick the next patch without a version pull request. Use for recovery only. |
| publish | Leave a draft to inspect | Publish after every check passes |
Release builds run one at a time, and up to 100 runs can wait in the queue. A failed build can reuse its matching draft. Published assets are never replaced.
If only the final publisher fails, fix the publisher, then run Recover desktop release on main with the failed run ID. It requires all platform builds and checks, and CI on their exact source, to have passed. It uses the current publisher with the original signed files and release plan, checks their source and hashes, then publishes. It does not rebuild the apps.
The container images, Windows runtime, Mac signing, Mac update checks, and publishing steps run on Blacksmith runners. Both Mac apps build on Apple silicon. The Intel app uses x64 Node under Rosetta. Windows jobs use GitHub's Windows runners because the installer check needs WSL 2.
Docker builds use Blacksmith's disk cache, with a separate cache for each Mac architecture and the Windows runtime. They do not export Docker layers to GitHub's cache service.
Update checks run alongside the builds. App jobs can install dependencies and build the source while their runtimes are prepared. Each Mac job waits only for its own images. It then signs its runtime and app. The final job downloads platform artifacts in parallel. It checks all three platform bundles, then uploads their files together. It downloads the installers, Mac ZIPs, and Windows runtime together to check their bytes before publication.
Developer ID builds submit the signed app to Apple and attach its ticket before they create the disk image and update ZIP. The build then submits the signed disk image and attaches its ticket. It mounts the finished disk image, copies its app to a temporary folder, and checks the app's signature, attached ticket and Gatekeeper result. A failed check stops the release. Runtime host tools have a separate notarization check because the app downloads them separately. ZIP and disk image creation run in parallel.
The Mac build logs show separate times for signing, notarization, ZIP creation, and disk image creation. Use these times and the Actions step times to compare releases. Compare runtime rebuilds with other rebuilds, and runtime reuse with other reuse runs.
How installed apps update
Section titled “How installed apps update”Drafts are never offered to the installer or the updater.
- Every app checks at startup, even when its runtime fails to start, every six hours while it's open, and after waking if a check is due. Check for Updates… checks right away.
- After a failed automatic check, Nod retries after 15 minutes, doubling up to six hours, and the menu shows Update Failed. Try Again….
- When the newest release is incomplete for a platform, Nod tries up to three newer releases and offers the first that validates.
- A Mac app outside Applications offers to move itself there at startup, because it can update itself only from Applications.
- Updates download in the background. While a runtime pack or Windows installer downloads, the update menu item shows its percentage. On a Mac, Nod also loads the new runtime's images into the running VM, so the restart skips that step.
- An automatic check announces a ready update with a notification when notifications are on and quiet hours allow it. Background checks never open a dialog. The menu offers Restart to update until you restart.
- If a reply, schedule or background check is running, or Nod can't tell, it asks before restarting. While Nod shuts down to install, its window shows Updating Nod…, and an unsent feedback draft or unsaved setting can't hold the install back.
- If the runtime hasn't changed, Nod reuses it and downloads only the app or installer.
- A Mac runtime is rebuilt when one of its inputs changes, or by the first release built in a new week (below). Its inputs are the browser worker and its imports, the root lockfile's entries for the packages the browser image bundles or builds with (the worker's imports, agent-browser and esbuild) and their dependencies, the pnpm version,
pnpm-workspace.yaml, the desktop lockfile, scripts the images copy, Dockerfiles, pinned downloads, and runtime build scripts. Other root dependency changes, workflow changes and edits to the fingerprint script alone do not rebuild it. Other app changes reuse the published runtime. A test fails when a runtime build script or Dockerfile reads a repository file the fingerprint does not cover, or when the browser bundle includes a package whose lockfile entry it does not cover. - A Windows runtime follows the same rule, plus its own Dockerfile, guest script and build script. When it hasn't changed, the release build downloads the published one, checks it against its manifest and GitHub's asset digest, and runs the full Windows install check on it. A Windows install that already has that runtime then updates with only the installer.
- The first release built in a new week (from Monday, UTC) rebuilds both runtimes and refetches the images' system packages, such as Chromium, instead of reusing Docker's cached layers. Later releases that week reuse them. A week without a release build ships no refresh.
- A Windows app refuses a downloaded installer unless n8n GmbH signed it with the
nod-windowsprofile. - On Windows, the restart runs the verified installer silently over the current install, then opens Nod again. The profile is kept.
Help private-alpha testers
Section titled “Help private-alpha testers”Mac testers need an Intel or Apple silicon Mac, and a supported provider API key or a ChatGPT Plus or Pro plan. They copy Nod to Applications, or run the Terminal installer, and approve the Keychain prompt if macOS shows it. Managed Macs may need IT approval. The first start downloads the runtime, so it needs an internet connection.
On Windows, testers run irm https://internal.users.n8n.cloud/webhook/nod/install-windows | iex in PowerShell, or download and run nod-Setup-x64.exe. The first start downloads the runtime, unless nod-Runtime-win32-x64.tar.gz sits next to the installer. After that, Nod updates itself.
| Situation | What to know |
|---|---|
| Not enough storage | Nod needs the runtime's extracted size plus 512 MiB, and downloads also reserve the archive size. The error says how much to free. Free it and retry. Existing data is kept. |
| Setup was interrupted | Retry it. |
| It still fails | Open Send feedback in Chat, choose Bug, review the selected diagnostic report, and send. If Chat can't open, describe the visible setup error. |
| Starting over | Select Remove all data… in the Nod menu. It deletes the profile and private computer, keeps the runtime, then restarts and opens setup. |
The report includes recent messages, tool inputs and results, errors, and app activity after best-effort redaction. Review it for personal details before sending, or untick Include diagnostic report. It excludes screenshots, binary data, system prompts, and model thinking. Database and journal sections mark unavailable sources and omitted entries. See Report contents and limits. If preparation fails, select Continue without report, then Send feedback. Your text and selected attachments stay in the draft; check these for personal information.
In development, Copy report copies the same report without sending it. NOD_FEEDBACK_URL changes where feedback goes, and an empty value turns sending off.
Test a local Mac build
Section titled “Test a local Mac build”Use the isolated test installer to try onboarding without changing your normal Nod app, accounts, or computer. It installs nod Setup Test in your user Applications folder and disables updates for that build.
Build the current source first. The helper verifies and reuses the runtime already cached by /Applications/Nod.app, so it doesn't copy or download another runtime:
pnpm --dir desktop install --frozen-lockfilepnpm run buildnode desktop/scripts/test-install.mjs buildnode desktop/scripts/test-install.mjs fresh first-runfresh gracefully closes the previous test instance and creates a new profile with its own computer and empty account storage. It refuses an existing profile name. Omit the name to generate one. It never removes an earlier profile.
To reopen the last test profile, or an earlier named one:
node desktop/scripts/test-install.mjs opennode desktop/scripts/test-install.mjs open first-runnode desktop/scripts/test-install.mjs stopTest profiles live under ~/Library/Application Support/nod Setup Test/test-profiles. Rebuilding the test app preserves them. The helper accepts an installed engine directory after build when the cached runtime comes from another local installation.
This is an ad-hoc signed local app, not a release. It reuses the cached workspace and browser images; it doesn't verify a newly built runtime image or release signing.
Signing limits
Section titled “Signing limits”Mac builds are signed with n8n's Developer ID and notarized by Apple. Windows builds are signed by n8n GmbH with Artifact Signing. SmartScreen can still warn about a new release until Windows trusts its reputation.
Updates check the new build against n8n's Apple team, or the Windows certificate profile, not one certificate, so a renewed certificate doesn't break them. macOS can still ask for Keychain approval. Nod explains that prompt before it reads saved API keys.
GitHub-hosted Mac runners can't run nested virtualization. CI checks binaries and packaging, but it can't prove Nod's private computer boots on a real Mac.
The native update checks cover both Mac key storage names in a disposable Keychain. They check an upgrade from the original name and migration of values saved by 0.4.0. Both paths must keep the vault key, server token, and integration identity. A second read must leave the saved settings unchanged.
Physical Mac checks before wider distribution
Use disposable profiles and synthetic content on a physical Apple silicon Mac.
- Fresh profile: install, pass the first-launch gate, connect a model, finish onboarding, and confirm the runtime is prepared and the workspace and browser work.
- Upgrade: start from the previous Nod release. Try Later and Restart, then confirm settings, conversations, workspace and browser state survive and an unchanged runtime is reused.
- Daily use: check login startup, notification text and clicks, quitting, and retry after an interrupted install.
- Oldest macOS: run on the oldest advertised macOS version.