リリースを出荷し、ネイティブバイナリを署名し、正常にプロダクションロールアウトを開始した後、サポートはユーザーが購入を完了できないことを報告します。クラッシュログは関係ないように見えますので、リクエスト、プラグインの初期化、最近のJavaScriptの変更を追跡するのに数時間を費やします。原因は、急いでプロダクションビルドに残したステージングURLAPIであることがわかります。
そのような失敗は珍しいことではありません。 環境設定 は、APIエンドポイント、機能フラグ、データベースクレデンシャル、第三者キーなどのデプロイメント固有の設定を、アプリケーションcodeから分離するという学問です。CapacitorとElectronアプリでは、分離は難しいことです。ウェブアセットはネイティブコンテナ内にバンドルされているため、設定ミスは署名されたアーティファクトの一部になり、サーバー上で変更できる値ではありません。
根本的な問題は 設定の漂流開発環境、ステージング環境、実稼働環境の間で、徐々に開きが生じることがあります。開発者が 1 つの環境を更新すると、 .env 開発とプロダクションの違いを理解しているチームは、__CAPGO_KEEP_0__アプリで明らかなミスを避けることができますが、漂流には運用モデルが必要であり、ファイル名の命名規則だけでは十分ではありません。 differences between development and production in Capacitor apps 運用するモデルを設定することで、明らかなミスを避けることができますが、漂流には運用モデルが必要であり、ファイル名の命名規則だけでは十分ではありません。
実用的な質問は、簡単です: 同じコードベースを複数の環境に配信するには、再構築、署名、または各構成変更のためにネイティブアプリを提出するのを繰り返すことなくどうすればよいのでしょうか?
目次
- 環境設定が生産アプリを壊す理由
- 4つの主な設定パターンを比較する
- 無視できないセキュリティとCI/CDの影響
- CapacitorとElectronで環境設定を実装する
- Capgoを使用してターゲットされたアップデートとロールバックを簡素化する
- 環境設定のチェックリスト
環境設定が生産アプリケーションを壊す理由
最も高価な設定のバグは、まれに設定のバグのように見えます。間違ったAPIのベースURLは、認証エラー、空のアカウント画面、支払いエラー、またはネイティブプラグインのクラッシュとして表面化することがあります。インシデントがビルドパイプラインを所有するエンジニアに到達するまで、元のミスは複数のコミットと成功したストアの提出の下に埋もれていました。
ハイブリッドアプリケーションには特定の障害パターンがあります。CapacitorはWebアプリケーションをコンパイルし、iOSまたはAndroidプロジェクトにアセットを格納します。Electronはレンダラーとメインプロセスのcodeをデスクトップアプリケーションにパッケージ化します。エンドポイントまたは機能フラグがビルド中に解決された場合、結果の値はアーティファクトと共に移動します。後で変更すると、通常、新しいバンドルを生成し、署名し、適用可能なチャネルを通じて配布する必要があります。
ドリフトは無害な例外から始まります
環境設定のズレは、妥当なショートカットから生じます:
- ローカルオーバーライド: 開発者がテストエンドポイントをハードコードして機能をブロックし、削除しなかった場合:
- 別のパイプライン変数: CIがリポジトリのドキュメントで記載された設定と一致しないプロダクション値を使用している場合:
- ネイティブのみの設定: Android、iOS、およびElectronが異なるプラグイン識別子またはコールバック設定を受け取っている場合:
- 未文書化のフラグ: 運用チームがデプロイメントシステムで直接機能フラグを変更し、ステージングでは古い動作を続けている場合:
各選択肢は単独で機能することができます。問題は、誰もが当該値が権威あるものであるか、どの環境が所有しているか、そして最後に変更された時期がわからない場合に生じます。
実用的なルール: 設定値がアプリケーションロジックとは独立して変更できる場合、ソースcodeとして扱うのではなく、デプロイメント入力として扱うこと。
A staging environment should resemble production closely enough to expose integration problems, while still using isolated endpoints, credentials, and data. When the environments drift, staging stops being a useful rehearsal. A release can pass every test against one set of assumptions and fail immediately against another.
ビルド時設定はリリースのボトルネックとなる
ビルド時設定は有用である。パブリックのコンパイル時値、プラットフォーム固有の識別子、ネイティブツールに必要な設定は、パッケージ化される前に存在する必要がある。問題は、オペレーションがリリース後に変更できる値をビルド時インジェクションで使用することである。
生産環境のAPIが新しいエンドポイントに移行したと仮定すると、伝統的なCapacitorワークフローではチームは値を変更し、Webアセットをビルドし、ネイティブプロジェクトを同期し、アプリケーションを署名し、プラットフォームのリリースプロセスを通じて配布する。
そのワークフローは、意図的な製品リリースのために適切である。急迫の設定修正に対する悪い対応である。バイナリは健康であり、JavaScriptは変更されていないが、単一の文字列が完全な配信サイクルを強制する。
より安全な設計では、3つの層を分離する。
- アプリケーションロジック、環境間で同一のまま残すべきである。
- 環境設定、エンドポイント、フラグ、非機密の実行時動作を選択する。
- シークレットマテリアル、必要な場合にのみインジェクトされるべきである。
分離により、ドリフトが視覚化されます。 また、生産環境が異なる場合に、チームは明確な答えを得ることができます: 比較するには、 code の構成入力の前と責任を負う。
4つの主な構成パターンの比較
ハイブリッドアプリケーションのすべての部分に適合する単一の構成パターンはありません。 バックエンドは起動時にプロセス環境変数を読み取ることができますが、 Capacitor レンダラーには、伝統的なサーバープロセスがない場合があります。 Electronは、メインプロセスとレンダラー間の境界を追加します。 値がパブリック、機密、リリース後変更可能、またはネイティブビルドツールによって必要であるかどうかに応じて、正しい選択肢が決まります。
パターン1、12要素環境変数
12要素モデルでは、構成を環境固有の入力として扱います。 これは、サーバープロセス、コンテナ、CIジョブにとって自然なアプローチです。 サービスは起動時に値を読み取り、同じアーティファクトを複数のデプロイで使用できます。
クライアントサイドアプリケーションはモデルを複雑にします。 ブラウザのJavaScriptが参照する値は、最終的にはクライアントにアクセス可能でなければなりません。 したがって、環境変数からのみ受け取られた値は、単に機密情報である必要はありません。 公開 API の起源または機能フラグは、ビルド時_substitutionを使用できますが、意味を持つ特権を持つ資格情報は、逆還元可能なクライアントバンドルに配信してはなりません。
Capacitor および Electronの場合、このパターンは ビルドオーケストレーションとパブリック構成セキュリティの秘密を保護するために使用しない。概念的オーバーヘッドは低いが、実行時変化性は制限され、別の配信レイヤーが存在しない限りです。
パターン2、環境ごとのビルド
チームは開発、ステージング、生産用ビルドのプロファイルを維持することがよくあります。各プロファイルはエンドポイント、App ID、ネイティブサービスファイル、機能フラグを選択します。アプローチは簡単に説明でき、プラットフォームの要件と互換性があります。
その弱点はアーティファクトの分散です。3つのビルドには、条件付きコンパイルやプラットフォーム固有のスクリプトがパイプラインに侵入した場合に特に、異なる動作が含まれる可能性があります。各構成変更は別のビルドを作成し、署名、認証、ストア処理、または手動リリースの調整をトリガーする可能性があります。
ロールバックもアーティファクトの配信とつながっています。古いバイナリに戻すことができますが、ユーザーはすでに異なるバージョンをインストールしている可能性があり、ロールバックのパスは配信チャネルによって決まります。
パターン3、実行時構成
Runtime configuration moves mutable values outside the native artifact. The application retrieves a configuration document on launch or reads a locally cached document that was previously delivered. This lets teams correct endpoints and flags without changing application code.
トレードオフは新しいスタートアップ依存関係です。リモート設定サービスが利用できない場合、安全なキャッシュ、バウンドされたタイムアウト、知られているフォールバックポリシーが必要です。フォールバックは、間違った環境を指すことはできません。ドキュメントのスキーマを検証し、適切な場合はソースを認証し、適用した設定バージョンを記録します。
ハイブリッドアプリケーションでは、このパターンは通常、非秘密値の最も柔軟なパターンです。ただし、モバイルユーザーがネットワーク接続なしでアプリケーションを起動できるため、慎重なオフライン動作が必要です。
パターン4、専用のシークレット管理
HashiCorp VaultやAWS Secrets Managerなどのプラットフォームは、機密なバックエンドデータを制御するように設計されています。アクセスポリシー、監査トレイル、暗号化、ローテーションワークフローをサポートしています。これにより、サーバーサイドサービスがクレデンシャルをユーザーに公開せずに秘密ストアに認証できるため、機密情報を管理するのに適しています。
これらはクライアントシークレットの問題を解決しません。デバイスの所有者がデバイスを検査できるため、モバイルまたはデスクトップクライアントにシークレットを配信することは通常、検査できます。クライアントアプリケーションは、秘密情報を公開することなく安全に提示される値を受信する必要があります。特権的な操作は、バックエンドに残す必要があります。
| パターン | ビルド複雑さ | 再提出が必要なストア | ロールバック速度 | ベストフォー |
|---|---|---|---|---|
| 12要素変数 | サーバーでは低く、ハイブリッドビルドではモデレート | 通常、バンドルされたクライアント値の場合 | 普通 | バックエンドサービスとパブリックビルド入力 |
| 環境ごとのビルド | 環境が増えると、高速 | はい、バンドルされた値が変更された場合 | 遅いから普通 | リリース頻度が低い小規模チーム |
| 実行時構成 | 普通 | 互換性のあるウェブ層の変更の場合 | バージョン付のペイロードとともに高速 | 環境設定 |
| シークレット管理プラットフォーム | 中程度から高 | バックエンドのみのシークレットには使用しない | サーバーコンシューマー向けに高速 | バックエンドの特権情報 |
単一アプリケーションに取り組むチームが、時々リリースする場合、環境ごとのビルドに厳密な検証を組み合わせて始めることができます。並行してステージングとプロダクションを実行する大きなチームには、アーティファクトの分散を減らすためにランタイム層が必要です。高頻度のリリースチームは、バックエンドのクレデンシャルに秘密管理者を組み合わせて、ImmutableアプリケーションBundle、ランタイム設定、そしてバックエンドのクレデンシャルに秘密管理者を組み合わせる必要があります。 Capacitorの機能フラグ実装ガイドライン 機能フラグは、スコープ、監査、クライアントに公開する安全であることを保証することで、ランタイム層に組み込まれる
セキュリティとCI/CDの影響を無視できない
設定値はCIから自動的に安全ではない。クライアントバンドル、ネイティブリソース、Electronアーカイブ、ログファイル、クラッシュレポート、またはデバイスバックアップに値が入り、誰かがそのアーティファクトにアクセスしている場合、値を検査できるものと想定する
公開識別子とクライアント側の設定は、シークレットとは異なります。モバイル API キーがアプリケーションを特定するためにのみ使用される場合、提供者がそれを期待している場合とその使用を制限している場合、バンドル内で許容されるかもしれません。データベースのクレデンシャル、署名シークレット、特権トークン、または制限されていないサービス クレデンシャルは同じ場所に安全ではありません。OWASP SAMMは、責任の分離または生産シークレットの暗号化を推奨し、保護されていないシークレットがリポジトリに侵入しないようにし、インシデントの待ち合わせではなく、シークレットのライフサイクルを管理することを推奨しています。

パイプラインが設定を漏洩させる
CI/CD システムは日常的な方法で失敗します。シェル コマンドが展開された変数を印刷したり、失敗したビルドが例外にシークレットを含めたり、デバッグ ステップが環境のダンプをアーカイブしたりすることがあります。ファイルは、リポジトリが不完全なものを継承したため、バージョン管理システムに追加されることもあります。 .env.production ファイルは、リポジトリが不完全な状態で継承されたため、バージョン管理システムにも追加される場合があります。 .gitignore.
分析や他の敏感なデータを扱うチームは、ELECTE の別のリソースを使用できます。
CI/CD システムは日常的な方法で失敗します。シェル コマンドが展開された変数を印刷したり、失敗したビルドが例外にシークレットを含めたり、デバッグ ステップが環境のダンプをアーカイブしたりすることがあります。 AI 分析のためのセキュリティホワイトペーパー より広範なデータ保護の責任を検討する際に、レビューする必要がある。
リリースのスピードとセキュリティは共存しなければならない。
生産用シークレットの安全なパターンは、制御されたストレージ、トランジット中の暗号化、リストア中の暗号化、最小限の特権アクセス、ローテーションです。変化可能なパブリックエンドポイントの場合、安全なパターンは異なります。エンドポイントはバージョン管理されたランタイムドキュメントを通じて配信され、使用前に検証され、不正値がクローズされるように制限される必要があります。
Capacitor または Electron code に特権的な資格情報を格納しないようにして、バックエンドのラウンドトリップを回避する。オブフュージョン、ミニファイション、または隠れたレンダラー変数に頼るのではなく、クライアントデバイスの信頼モデルを変更することはできません。
責任の分離された実用的なパイプラインは次のとおりです:
- ソースコントロール: 構成スキーマと安全な例をコミットし、ライブシークレットはコミットしない。
- ビルドステージ: 必要な値のみをインジェクトし、ログでシークレットの拡張を防止する。
- デリバリーステージ: 認証された、観察可能なチャネルを通じて環境固有のランタイムバンドルを適用する。
- 回転ステージ: 定期のスケジュールでバックエンドの資格情報を取り消し、直ちに無効化するためのインシデントパスを設定します。
この CI/CD secret management practices for Capacitor teams __CAPGO_KEEP_0__とElectronで環境設定を実装する
環境設定の実装については、Capacitor と Electron を使用します。
A maintainable setup starts with one configuration contract, not a pile of framework-specific conditionals. Keep safe environment inputs in predictable files, load them through the build system, and expose them to application code through a small typed service.
ソースコントロールに含めるべきものは
.env
.env.staging
.env.production
.env.example
src/config/
schema.ts
config-service.ts
capacitor.config.ts
electron/
main.ts
preload.ts
Only .env.example 1つの契約を定義し、検証する
Viteの場合、クライアントに公開される変数は通常
__CAPGO_KEEP_0__ VITE_ プレフィックス。プレフィックスは可視性のシグナルであり、セキュリティの境界ではありません。
// src/config/schema.ts
export type AppConfig = {
apiBaseUrl: string
enableNewCheckout: boolean
environment: 'development' | 'staging' | 'production'
}
function required(name: string, value: string | undefined): string {
if (!value) {
throw new Error(`Missing required configuration: ${name}`)
}
return value
}
export function loadConfig(): AppConfig {
const environment = required('VITE_APP_ENV', import.meta.env.VITE_APP_ENV)
if (!['development', 'staging', 'production'].includes(environment)) {
throw new Error(`Unsupported environment: ${environment}`)
}
return {
apiBaseUrl: required('VITE_API_BASE_URL', import.meta.env.VITE_API_BASE_URL),
enableNewCheckout: import.meta.env.VITE_ENABLE_NEW_CHECKOUT === 'true',
environment: environment as AppConfig['environment'],
}
}
呼び出し loadConfig() ローカル環境の設定ガイド
アプリケーション起動中に。欠落した値は明確なエラーを生成するのではなく、ローカルエンドポイントを選択するのではなく、単一の決定は生産性の低いミールルーティングのバグのクラスを防止します。 .env.stagingローカルワークの場合、Viteは適切なファイルを選択できます。 .env.production、はステージングビルドを使用します。
Capacitorネイティブ設定
__CAPGO_KEEP_0__ネイティブの構成 capacitor.config.tsネイティブプロジェクトは、環境固有の識別子、サービスファイル、プラグイン設定などが必要です。
// capacitor.config.ts
import type { CapacitorConfig } from '@capacitor/cli'
const isProduction = process.env.APP_ENV === 'production'
const config: CapacitorConfig = {
appId: isProduction ? 'com.example.app' : 'com.example.app.staging',
appName: isProduction ? 'Example' : 'Example Staging',
webDir: 'dist',
plugins: {
PushNotifications: {
presentationOptions: ['badge', 'sound', 'alert'],
},
},
}
export default config
、に値を保持してくださいが、プライベートクレデンシャルを置かないようにしてください。
The 、Capacitorローカル環境の設定ガイド チームのローカルモードを標準化するのに役立ちますが、リポジトリには明示的な契約とCI検証が必要です。
Electronにはプロセス境界が必要です。
ElectronのレンダラーはNode.jsのメインプロセスと同じではありません。ハード化されたアプリケーションでは、レンダラーでは定義されていないか意図的に利用できないメインプロセスで利用可能な場合があります。安全な構成のみをプレロードブリッジで通過してください。 process.env レンダラーでオブジェクトを再度検証してください。ブリッジは、秘密のストアトークンや特権ファイルシステムの機能性を公開してはなりません。
// electron/main.ts
import { app, BrowserWindow } from 'electron'
import path from 'node:path'
function createWindow() {
const window = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false,
},
})
const safeConfig = {
apiBaseUrl: process.env.API_BASE_URL,
environment: process.env.APP_ENV,
}
window.webContents.on('did-finish-load', () => {
window.webContents.send('app-config', safeConfig)
})
return window
}
app.whenReady().then(createWindow)
// electron/preload.ts
import { contextBridge, ipcRenderer } from 'electron'
contextBridge.exposeInMainWorld('appConfig', {
get: () => new Promise((resolve) => {
ipcRenderer.once('app-config', (_event, config) => resolve(config))
}),
})
アスペクト
| Aspect | Capacitor | Electron |
|---|---|---|
| メイン構成境界 | ネイティブプロジェクトとバンドルされたウェブアセット | メインプロセス、プレロード、レンダラー |
| 安全なクライアント値 | 公開エンドポイントとフラグ | プリロードを通じてパスされた公開エンドポイントとフラグ |
| 機密情報 | アプリケーションバンドルから外す | パッケージされたアーカイブから外す |
| 一般的なエラー | ネイティブシンク後の古いビルド値 | process.env レンダラーでは利用できない |
| ランタイムの更新パス | 署名されたウェブバンドルまたはリモート設定 | 署名されたウェブバンドルまたは制御されたアプリケーション更新 |
最も一般的な実装ミスは、 .env ファイルは自動的にプライベートになります。バンドラーは生成されたJavaScriptに値を含めることができ、パッケージングステップではファイル自体を含めることができます。最終的なアーティファクトを検査するのではなく、ソースツリーのみを検査するのではなく。
Simplifying Targeted Updates and Rollbacks with Capgo
厳格なビルド時設定でも、運用上のハードガップが残ります。リリース後、公開エンドポイントが変更された場合、ネイティブアプリケーションはまだ古い値を保持している可能性があります。再ビルドと新しいバイナリの配布は、Web層に影響を与える変更のみが必要な場合に過剰です。
Capgoのライブアップデートモデルは、そのハードガップを解決するために ターゲットチャンネル 開発、ステージング、またはプロダクションなどのデプロイ階層に対して

Consider a production API endpoint that changes unexpectedly. The team can update the configuration source, build the web bundle, and publish it to the production channel instead of waiting for a native store release. The important boundary remains intact: this approach doesn’t bypass platform rules for native code, and it doesn’t make a secret safe to ship. It does reduce the time required to correct compatible web-layer configuration.
チャンネルは環境の所有権を明示的にします。
A channel should map to an environment, not to an individual developer’s preference. Development testers receive development content, staging users receive staging content, and production users receive only the bundle approved for production. CI can publish the appropriate bundle after the corresponding build and validation steps.
Rollback is equally important. If the new configuration points to an unhealthy service, the release operator should be able to select the previous known-good bundle for that channel. Version history, deployment guardrails, and device-level reporting help the team determine whether the issue is widespread or limited to a rollout segment.
結果は明確なキャリアアップパスになります。
- Development channelのバンドルをビルドして検証する
- 同じテストされたコンテンツをステージングにアップグレードする
- プロダクションチャンネルアップデートを承認する
- 採用とエラーの監視
- チャンネルを戻す必要がある場合
そのプロセスは、各エンドポイントの修正に対して緊急のネイティブビルドを作成する必要性を減らします。 Capgo バージョン管理とロールバックフロー 環境固有のリリースが必要なチームにとって、追跡可能な履歴を失うことなく、特定の環境のリリースが特に重要です。
環境設定チェックリスト
各主なリリースとパイプラインの変更前後にこのオーディットを実行してください。
- アーティファクトを検査してください: コミットされたファイル、生成されたJavaScript、ネイティブリソース、ソースマップ、またはElectronアーカイブに秘密情報が表示されていないことを確認してください。
- 環境を分離してください: 開発、ステージング、およびプロダクションが異なるエンドポイント、識別子、および承認されたキーを使用していることを確認してください。
- 入力を保護してください: 各
.env無視されるように設定し、必要なスキーマを文書化するようにします。.env.exampleCIを確認してください: - CI のレビュー 復旧テストを実行してください:
- テスト復旧: 実行時構成の検証は、必要な値が欠けている場合に速く失敗し、ネイティブシェルの再構築なしで互換性のあるアップデートをロールバックできることを確認します。

アドビューは、すべてのプロダクション構成値のオーナー、ソース、スコープ、およびロールバックプロシージャを特定できるまで完了します。
CapgoはCapacitorJSおよびElectronアプリ向けに署名されたライブアップデートを提供し、ターゲットチャンネルとバージョンロールバックを含む互換性のあるJavaScript、CSS、構成、およびアセットの変更をサポートします。環境アップデートを制御しながら、リビルドサイクルを削減したいチームは、 Capgo と評価します。