Secrets & Signing
How Tenki Runners handle secrets, and how to import an Apple signing certificate into a macOS job.
Tenki does not operate a secrets store. All secrets used in your workflows live in GitHub Actions secrets (repo, environment, or organization) and are injected into the job at runtime through the standard secrets.* mechanism.
This page explains why.
The model
- You store secrets in GitHub Actions (or in your own secret manager pulled in at job-time).
- Tenki provisions a fresh VM for the job.
- GitHub passes the secret values into the runner environment as usual.
- The VM, including any cached secret material, is destroyed when the job ends.
Because the VM is single-use (see Security & Isolation), there is no persistent state where secret material could leak between jobs.
Why we don't run our own secrets store
Two reasons:
- Smaller blast radius. The fewer places your secrets live, the better. Re-using GitHub's secret store keeps the surface area to systems you already audit and trust.
- No vendor lock-in. Your workflows remain identical to vanilla GitHub Actions. Migrating to or from Tenki does not require re-keying anything.
See Security & Isolation for the full model.
Using secrets in a workflow
Because Tenki uses GitHub Actions secrets natively, referencing them looks exactly like it does on GitHub-hosted runners; only the runs-on value changes:
jobs:
deploy:
runs-on: tenki-standard-small-2c-4g
steps:
- uses: actions/checkout@v4
- name: Deploy
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
run: ./scripts/deploy.shGitHub injects secrets.API_TOKEN into the job at runtime and automatically masks the value in logs. When the job finishes, the VM (and any secret material it held in memory) is destroyed.
Bringing your own secret manager
If your secrets live in an external manager (such as HashiCorp Vault, AWS Secrets Manager, or GCP Secret Manager), nothing changes on Tenki. Authenticate to that provider inside the job, typically using a single GitHub Actions secret or OIDC, and pull the rest at runtime, exactly as you would on GitHub-hosted runners. The fetched values exist only for the lifetime of the ephemeral VM.
Signing macOS and iOS builds
Apple builds need a signing identity in a keychain. Every Tenki macOS job gets a fresh VM, so there is no keychain to reuse and nothing to clean up afterwards: import the certificate at the start of the job and the VM takes it with it when the job ends.
Store the certificate as a GitHub Actions secret, base64-encoded:
base64 -i Certificates.p12 | pbcopyThen import it into a keychain created for that job:
jobs:
build:
runs-on: tenki-macos-latest-medium
steps:
- uses: actions/checkout@v4
- name: Import signing certificate
env:
CERTIFICATE_P12: ${{ secrets.CERTIFICATE_P12 }}
CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
echo "$CERTIFICATE_P12" | base64 -D -o "$RUNNER_TEMP/cert.p12"
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security set-keychain-settings -lut 3600 build.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security list-keychains -d user -s build.keychain $(security list-keychains -d user | tr -d '"')
security default-keychain -s build.keychain
security import "$RUNNER_TEMP/cert.p12" -k build.keychain \
-P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: \
-s -k "$KEYCHAIN_PASSWORD" build.keychain
- name: Build
run: xcodebuild -scheme MyApp -configuration Release archiveset-key-partition-list is the step teams most often miss. Without it codesign prompts for keychain access and the job hangs until it times out.
Provisioning profiles are ordinary files: write them to ~/Library/MobileDevice/Provisioning Profiles/ in the same step.
fastlane match
fastlane match works unchanged. It manages its own certificate repository and its own temporary keychain, so a Tenki macOS runner needs no special configuration beyond the match credentials you already keep in secrets.
Notarization
xcrun notarytool ships with Xcode on the standard macOS images. Authenticate with an App Store Connect API key carried through GitHub Actions secrets the same way as the certificate above.
Why there is no cleanup step
The VM is single-use. The keychain, the certificate, and the private key exist only inside it and go away when the job finishes, so a security delete-keychain step is optional rather than a safety requirement. See Security & Isolation.
Frequently asked questions
Does Tenki store or log my secrets? No. Tenki does not operate a secrets store, and secret values are masked in logs by GitHub. They exist only in the ephemeral VM for the duration of the job.
Can secrets leak between jobs? No. Every job runs in a fresh, single-use VM that is destroyed when the job ends, so there's no persistent state shared between jobs.
Do I need to re-key my secrets when migrating to Tenki?
No. Your workflows and secrets.* references stay identical; only the runs-on label changes.
Do I have to clean up the signing keychain? No. The VM is destroyed at job end, so the keychain and the private key go with it. A cleanup step is harmless but not required.