ÆTHER currently ships unsigned on every platform. This document is the setup guide for changing that.
There are two independent signing schemes here, and they are easy to confuse:
| Purpose | Cost | Status | |
|---|---|---|---|
| OS code signing (Apple Developer ID, Azure Trusted Signing) | Stops the OS blocking the first install | ~$220/year | Not wired up — see below |
| Updater signing (minisign) | Lets the app verify an update it downloads itself | Free | Wired up, waiting on a keypair |
They are unrelated: the updater's minisign key is generated locally by the Tauri CLI and has nothing to do with Apple or Microsoft. So in-app updates can be turned on today, without waiting for the paid certificates.
Until OS signing is done, see Install for what users have to do to open an unsigned build.
An unsigned, un-notarized .dmg downloaded through a browser is quarantined by
macOS. The user does not get a "are you sure?" prompt they can click through — they
get "ÆTHER is damaged and can't be opened. You should move it to the Bin." That
message is indistinguishable from a malware warning, and it is the first thing a new
user sees.
On Windows, an unsigned NSIS installer triggers SmartScreen's "Windows protected your PC — unknown publisher" interstitial, where the Run anyway button is behind a More info link.
For a tool whose entire pitch is that it keeps your data on your machine, asking the user to override their OS's security check is the wrong first impression.
Cost: Apple Developer Program, $99/year.
-
Enrol at https://developer.apple.com/programs/. Individual enrolment is enough; it can take a day or two to be approved.
-
Create a Developer ID Application certificate in Certificates, Identifiers & Profiles. Note this is Developer ID Application, not Mac App Distribution — the latter only works for the Mac App Store and will not help with direct downloads.
-
Export it as a
.p12from Keychain Access (right-click the certificate → Export), set a password, then base64 it for CI:base64 -i certificate.p12 | pbcopy -
Create an App Store Connect API key (Users and Access → Integrations → Keys) with the Developer role. Download the
.p8— Apple only lets you download it once. Record the Key ID and Issuer ID shown next to it. -
Add GitHub repository secrets:
Secret Value APPLE_CERTIFICATEbase64 of the .p12APPLE_CERTIFICATE_PASSWORDthe .p12export passwordAPPLE_SIGNING_IDENTITYe.g. Developer ID Application: Your Name (TEAMID)APPLE_API_KEY_IDKey ID from step 4 APPLE_API_ISSUERIssuer ID from step 4 APPLE_API_KEYbase64 of the .p8 -
Config changes. In
src-tauri/tauri.conf.json, underbundle.macOS, add a hardened-runtime entitlements file. Notarization rejects binaries without the hardened runtime, and llama.cpp's Metal path needs the JIT entitlement:<!-- src-tauri/entitlements.plist --> <key>com.apple.security.cs.allow-jit</key><true/> <key>com.apple.security.cs.allow-unsigned-executable-memory</key><true/>
Tauri's bundler reads
APPLE_SIGNING_IDENTITYand theAPPLE_API_*variables directly, so the macOS CI job needs the secrets inenv:and an import step for the certificate — it does not need a separatenotarytoolinvocation. -
Verify a built app before trusting the pipeline:
codesign --verify --deep --strict --verbose=2 "ÆTHER.app" spctl --assess --type execute --verbose "ÆTHER.app" xcrun stapler validate "ÆTHER.app"
spctlmust reportaccepted source=Notarized Developer ID.
Note on the DMG. The installer is built by scripts/make-styled-dmg.sh via
appdmg, not by Tauri's bundler, so the .dmg itself needs signing and stapling as
a separate step after it is assembled — signing the .app alone is not enough.
Cost: roughly $10/month. The older route is an OV or EV certificate from a CA (DigiCert, Sectigo) at a few hundred dollars a year; EV additionally requires a hardware token, which does not work in CI without a cloud HSM. Azure Trusted Signing is the cheaper and more CI-friendly option for a solo project, and it accrues SmartScreen reputation against Microsoft's root rather than from zero.
- Create an Azure account and a Trusted Signing account and certificate profile. Identity validation takes a few days for an individual.
- Register an app in Entra ID, grant it the Trusted Signing Certificate Profile Signer role, and record the tenant, client ID, and client secret.
- Add
AZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_ENDPOINT,AZURE_CODE_SIGNING_NAME,AZURE_CERT_PROFILE_NAMEas repository secrets. - Set
bundle.windows.signCommandintauri.conf.jsonto invoke the Trusted Signing CLI over%1. Tauri passes each artifact path through it.
Reputation is earned per-publisher over download volume, so expect SmartScreen to keep warning for the first weeks even once signing works.
No signing is required for .deb or AppImage — neither apt nor the AppImage
runtime enforces publisher identity by default. If ÆTHER is ever published through
Flathub, that has its own review and build process, and signing is handled there.
This part is wired up. Settings → Updates offers Install Update when a newer release exists, downloads it, verifies its signature, and installs it in place. All that is missing is a keypair, which is free and takes a minute.
Until the key exists nothing changes: builds are byte-identical to before, and the
Install button reports unconfigured — "This build has no update signing key, so
ÆTHER cannot verify a download" — rather than fetching something it could not check.
-
Generate the keypair. The password may be empty, but a real one is better — anyone with the private key can push an update to every ÆTHER install.
bun run tauri signer generate -w ~/.tauri/aether-updater.keyThis prints a public key and writes the private key to that path. Back both up somewhere durable. Losing the private key means no existing install can ever be updated again — every user has to reinstall by hand.
-
Commit the public key into
src-tauri/tauri.conf.jsonunderplugins.updater.pubkey, replacing the empty placeholder. It is a public key; committing it is the intended usage. -
Add two repository secrets:
Secret Value TAURI_SIGNING_PRIVATE_KEYcontents of ~/.tauri/aether-updater.keyTAURI_SIGNING_PRIVATE_KEY_PASSWORDthe password from step 1 The moment
TAURI_SIGNING_PRIVATE_KEYexists, the build jobs start producing signed updater artifacts and the release job publisheslatest.json. Nothing else needs changing — see.github/actions/updater-flags. -
Verify after the next tagged release:
curl -sL https://github.com/CanPixel/aether/releases/latest/download/latest.json | jq .
It should list
darwin-aarch64,darwin-x86_64,windows-x86_64, andlinux-x86_64, each with a non-emptysignatureand a URL pinned to the release tag. The two macOS entries intentionally share the universal updater archive.
| Install | Self-updates | Why |
|---|---|---|
macOS .dmg → /Applications |
Yes | Replaces the .app bundle in place |
Windows -setup.exe |
Yes | Re-runs the NSIS installer silently |
| Linux AppImage | Yes | Rewrites the AppImage file |
Linux .deb / .rpm |
No | Owned by the package manager; ÆTHER reports unsupported rather than corrupting it |
| Linux ARM64 | No | Only a .deb is published, so there is no signed artifact |
| Android | No | Store-managed |
createUpdaterArtifacts is a hard build error without the private key. That is
why it lives in src-tauri/tauri.updater.conf.json and is merged in only when the
secret exists, instead of sitting in the main config — otherwise every branch push
would fail until the key was created.
Updates may sidestep the quarantine problem. Tauri's updater downloads and
extracts the bundle itself rather than going through a browser, so it should not
attach com.apple.quarantine — meaning the xattr dance in the README would apply
only to the first install, not to subsequent updates. This follows from how
quarantine is applied and has not been verified against a real signed release;
confirm it before relying on it.
- Updater keypair first. It is free, takes a minute, and is the only item here that improves anything today — without it, a security fix reaches only users who happen to re-download by hand.
- macOS Developer ID second. It is the only platform where the current state is a hard block rather than a bypassable warning, and it is the platform ÆTHER is developed on.
- Windows last. SmartScreen is unpleasant but clickable, and reputation takes weeks to build regardless of when you start.