[2025年版] Electron(electron-builder)でMacアプリのコード署名と公証を通す
はじめに
Electronで作ったMacアプリを配布して実行できるようにしたい!
そんなときに避けて通れないのがコード署名(code signing)と公証(notarization)です。初めてで戸惑いながらも先人のおかげで無事に成功できたので、その手順を備忘として記載します。
基本的な流れは以下の2つの記事の通りで、初心者に分かりづらかったポイントに絞って補足記載していきます。
動作環境
- macOS Sonoma 14.3.1
- electron@34.0.2
- electron-builder@25.1.8
- vite@6.0.11
Developer ID Application証明書を作成
大まかな流れは以下の通りです。
- Key Chain Accessから証明書要求を作成
- Apple Developer Programに登録
- Developer ID Application証明書を作成
- 作成された証明書をダウンロードし、ダブルクリックしてKey Chain Accessへインストール
- 証明書が有効であることを確認
step1については以下記事が参考になりました。
step2,3は冒頭の記事をご参照ください。
step4で私は何度か失敗したのですが、Key Chain Accessにインストールする際、インストール先でiCloudを選択していたのが原因だったようです。ダウンロードした証明書はKey Chain Accessのloginにインストールします。
次にstep5についてです。無事にKey Chain AccessにインストールができるとCertificatesタブに表示されるのですが、私の場合はインストールしただけでは「証明書が信頼できない」との記載があり、赤いマークがついました。このままビルドしたところ、コード署名に失敗しました。
electron-builder
を実行した際のログは以下です。
skipped macOS application code signing reason=cannot find valid "Developer ID Application" identity or custom non-Apple code signing certificate, it could cause some undefined behaviour, e.g. macOS localized description not visible, see https://electron.build/code-signing allIdentities= 1)
以下の記事に従って証明書を有効にすることで、本問題は解決できました。
ここまででコード署名ができるようになりました。
App Store Connect API Keyの用意
次に公証ですが、冒頭の参考記事に記載の通り、Apple API Keyの取得が推奨されているようですので、取得しにいきます。
私はこの"Apple API Key"がなんのことを指しているのか分からず手間取ったのですが、結論としてApp Store ConnectのTeam Keyを作成すればよいです。手順は@electron/notarize(electron-builderがnotarizationで内部的に利用しているライブラリ)に記載があるのですが、概要は以下のとおりです。
- App Store ConnectでTeam Keyを作成する
- アクセスとしては
App Manager
を設定する - 作成したAPI Keyをダウンロードする
次に環境変数にこれらの情報を設定します。
APPLE_API_KEY=step3でダウンロードしたAPI Keyファイルへのフルパス
APPLE_API_KEY_ID=App Store ConnectのキーID
APPLE_API_ISSUER=App Store ConnectのIssuer ID
electron-builderでコード署名と公証を実行
最後にelectron-builderを実行しますが、このとき上記のenvを読んでほしいのでdotenvをインストールしました。またCIで実行することも考え、cross-envも入れておきました。
npm install -D dotenv cross-env
最後にenvを読むようにスクリプトを修正して(cross-env-shell \"node -r dotenv/config $(which electron-builder) --mac --arm64\"
の部分)実行。
...
"dist:mac": "npm run build:electron && npm run build && cross-env-shell \"node -r dotenv/config $(which electron-builder) --mac --arm64\"",
...
何度かKey Chain Accessへのアクセス許可のポップアップが出ましたが、承認して無事にコード署名と公証を成功させることができました。コード署名・公証は初めて行いましたが、5分ほどで完了しました。
$ spctl -a -vvv -t install dist/mac-arm64/xxx.app
dist/mac-arm64/xxx.app: accepted
source=Notarized Developer ID
origin=Developer ID Application: xxxxx (xxxxx)
試しに別端末にdmgを送ってインストールしたところ、無事に実行できました!
GitHub ActionsでCIを組む
ここまでできたらCIもやりたいですよね。証明書とかKeychainとかどうするんだろう。。。と思いましたが、GitHubの公式ドキュメントがありました。
name: Build macOS App
on:
push:
tags:
- "v*"
workflow_dispatch:
jobs:
build-macos:
runs-on: macos-latest
name: Build and Sign macOS App
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Prepare for codesigning
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# Create temporary keychain
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Import certificate to keychain
echo -n "$APPLE_CERTIFICATE" | base64 --decode > $RUNNER_TEMP/certificate.p12
security import $RUNNER_TEMP/certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
# Enable codesigning from keychain
security set-key-partition-list -S "apple-tool:,apple:,codesign:" -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Verify certificate import
security find-identity -v -p codesigning $KEYCHAIN_PATH
- name: Setup App Store Connect API key
env:
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: |
# Create private key file from base64
echo -n "$APPLE_API_KEY_BASE64" | base64 --decode > $RUNNER_TEMP/AuthKey_$APPLE_API_KEY_ID.p8
- name: Build and Sign macOS app
env:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY: ${{ runner.temp }}/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8
run: |
npm run build:electron && npm run build
npx electron-builder --mac --arm64 -p always
APPLE_CERTIFICATEは、Keychain Accessから証明書をエクスポートして、base64 -i /path/to/cert.p12 | pbcopy
で取得できます。
また、App Store ConnectのAPI Keyも同様にBASE64エンコードします(APPLE_API_KEY)。これはビルド時にパスを渡す必要があるので、Setup App Store Connect API keyでデコードしてビルド時にenvで渡しています。
署名した出力はelectron-builderの -p always
オプションによって設定したホストに書き出されるようになっています。
Discussion