Answers · Keys & Services

What is the minimum set of keys needed to launch an app?

RAILS_MASTER_KEY is the only one production will not boot without. APP_HOST is not a secret but belongs in the same pass, because without it every emailed link points at localhost. Add a Stripe key when you want to charge and a Resend key when you want mail to leave the building; both run on fakes until then.

Required

RAILS_MASTER_KEY, or SECRET_KEY_BASE if you prefer environment variables to the encrypted file. Rails cannot decrypt credentials or sign cookies without one, so it raises during initialization and the deploy fails on its health check.

bin/kamal secrets print

Not a secret, but launch-blocking anyway

APP_HOST. Mailers and the SEO surfaces have no request to infer a hostname from, so they read this. Without it, magic-code sign-in emails link to localhost:3000 and your sitemap advertises localhost URLs, both silently.

Add when you need the thing

Variable Until you set it
STRIPE_SECRET_KEY Checkout runs against the local fake and entitlement works.
STRIPE_WEBHOOK_SECRET Needed as soon as the Stripe key is real.
RESEND_API_KEY and MAIL_FROM Mail is not delivered.
TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY The bot check passes everything.
S3_BUCKET and the AWS pair Uploads go to the mounted volume.

Every row in that table is genuinely optional, which is the property the adapter and fake pattern buys. docs/BRING_YOUR_OWN_KEYS.md is the full list with what each one unlocks.

The order that avoids rework

  1. Deploy with the master key only, and confirm the app is up.
  2. Add APP_HOST, then send yourself a sign-in code and click the link.
  3. Add Resend, and check a real inbox shows SPF, DKIM and DMARC passing.
  4. Add Stripe in test mode, run a checkout, confirm the webhook lands.
  5. Switch Stripe to live, and set the statement descriptor before the first real charge.

Each step is verifiable on its own, so a failure names its own cause. Doing all five at once means debugging five integrations against one symptom.

Confirm before you announce

bin/check
curl -sI https://yourdomain.com/up | head -1

Related questions

Do I need API keys to run a Rails starter kit locally?

No. Billing, email, bot checking and error reporting each sit behind an adapter that returns a real client when its credential is present and a deterministic local fake when it is not. A fresh clone runs bin/setup and bin/dev with no keys, and checkout, sign-in and gated features all work end to end.

How do I stop bot signups on a Rails sign-up form?

Set TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY. app/adapters/bot_check.rb returns a real Cloudflare Turnstile verifier when both are present and a pass-everything fake when they are not, so the form works in development with no account and starts blocking bots in production without a code change.

How do I store uploaded files on S3 instead of local disk?

Set S3_BUCKET, S3_REGION, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, plus S3_ENDPOINT for a non-AWS provider. config/storage.yml already defines the service, so production uses object storage instead of the container's disk. Existing files on local disk do not move by themselves.