Docs

Signing credentials

Signing an app means trusting something with a certificate and its private key. The Platform's job is to hold those safely and use them only at the moment a build needs them, never exposing them in your repo, your CI logs, or the artifact.

You still need your own developer accounts. Apple charges $99 a year for the Apple Developer Program and Google charges $25 once for a Play Console account. You own and maintain both. What the Platform removes is the Mac: with the Mac-less flow below you can create and use an Apple signing certificate without ever owning one.

What each target needs

The Credentials page shows a readiness checklist per destination, so you can see what is still missing. A build is refused up front, before a runner is dispatched, if any of these are not both uploaded and verified.

Target What it needs
macOS, direct download (macos-arm64:direct) Apple Developer ID certificate (.p12), App Store Connect API key (.p8)
iOS, TestFlight or App Store (ios-arm64:testflight, :app_store) Apple Distribution certificate (.p12), provisioning profile (.mobileprovision), App Store Connect API key (.p8)
Android, Google Play (android-arm64:play) Android keystore (.jks), Google Play service account (.json)
Android, direct download (android-arm64:direct) Android keystore (.jks)

The App Store Connect API key does two jobs: it notarizes a macOS build with Apple, and it lets the runner upload an iOS build to App Store Connect.

Uploading one

Credentials → New, pick the kind, and upload the file. A few kinds need some detail alongside it, because the file alone cannot be used:

  • Apple certificates (.p12): the export password and your team ID.
  • App Store Connect API key (.p8): its key ID and issuer ID, both shown next to the key in App Store Connect.
  • Android keystore (.jks): the store password, key alias, and key password.
  • Provisioning profiles and Play service accounts carry everything the runner needs inside the file, and the Platform reads the rest out for you.

Every credential is verified the moment you save it, and the result shows on the list, so a wrong password or an expired certificate surfaces at once rather than halfway through a build. You can re-verify or delete any credential from that page.

No Mac? No problem

Creating an Apple certificate normally needs a Mac, because Keychain Access is what generates the keypair and the certificate signing request. The Platform offers a Mac-less flow for both Apple certificate kinds, Developer ID and Distribution, so you never need one:

  1. The Platform generates a 2048-bit keypair and a certificate signing request (CSR) on the server. The private key stays in custody.
  2. You download the CSR and upload it to your Apple Developer account, which issues a certificate.
  3. You upload Apple's issued .cer back to the Platform, which pairs it with the private key it already holds, assembles the .p12, reads your team ID out of the certificate, and verifies it.
The Mac-less flow text
Platform ──generate──▶ keypair + CSR
   you  ──download───▶ CSR
   you  ──upload─────▶ Apple Developer  ──issues──▶ certificate
   you  ──upload─────▶ Platform  (completes the credential)

At no point does the private key leave the Platform, and you never touch Keychain.

Android has no equivalent step: a keystore is generated by keytool on any machine with a JDK, and you upload the .jks. Back it up: lose the keystore and you can never update that app on Google Play again.

Just-in-time injection

However a credential got there, it is used the same way. When a hosted build reaches its signing step, the runner pulls the decrypted credential using a token scoped to that one build target, signs, and discards it when the build ends. Credentials are:

  • Encrypted at rest, and decrypted only for a single build.
  • Scoped to one artifact. The runner's token authenticates for its own target and nothing else.
  • Never in your artifact or logs. Only the signature they produced ships.

Google Play goes the other way: the .aab upload runs on the Platform over Play's HTTPS API, so the service-account key never reaches a runner at all.

Update-bucket keys are not credentials. The S3 keys that publish releases live under Settings → Buckets and are used only by the Platform's own publish jobs. They are never sent to a build runner.

Rails · Hanami · Sinatra — built with Ruby