Free

Claude in Produktion deployen lassen

Deploy-Fehler haben keine Symptome. Vier Leitplanken — getrennte Vaults, EDITOR-Skripte, Rückleseprüfung, Laufzeit-Flip per env — halten Claude nützlich, ohne dass alles brennt.


Der große Unterschied zwischen Deployen und Code schreiben: Deployment ist ein Schuss, hohes Risiko, schmerzhaft rückgängig zu machen. Schreib eine kaputte Zeile Code, ein Testlauf fängt sie. Schreib eine kaputte Zeile Credentials, und du merkst es erst bei der ersten echten Zahlung — User haben ihre Karte belastet, das Geld ist nicht auf deinem Konto, die Logs sind nichts als 400.

Ich habe how2claude kürzlich mit Claude vom lokalen Dev in die Produktion gebracht: Stripe-Live-Konto, x402-Mainnet-Wallet, Google OAuth, Kamal Secrets. Claude weiß nicht, welche Werte Test und welche echt sind. Es weiß nicht, dass sk_live_ vs sk_test_ ein Ein-Buchstaben-Unterschied mit weltuntergangsartigen Konsequenzen ist. Die Leitplanken baust du.

Leitplanke #1: Getrennte Credentials-Dateien für Dev und Prod

Rails kommt per Default mit config/credentials.yml.enc, entschlüsselt durch config/master.key. Wenn du diesen Default nimmst, hast du verloren.

Wenn du sk_live_xxx in diese Datei schreibst und dann lokale Tests fährst, ruft dein Testcode Produktions-Stripe auf. Jeder Testlauf belastet eine echte Karte.

Teile in zwei:
- config/credentials.yml.enc + config/master.key: dev/test, hält sk_test_xxx
- config/credentials/production.yml.enc + config/credentials/production.key: prod, hält sk_live_xxx

Beide .key in .gitignore, beide .enc committen. production.key lebt nur auf der Deploy-Maschine.

Dann müssen die Kamal Secrets auf die richtige Datei zeigen:

 # .kamal/secrets
-RAILS_MASTER_KEY=$(cat config/master.key)
+RAILS_MASTER_KEY=$(cat config/credentials/production.key)

Im Container zeigt RAILS_MASTER_KEY jetzt auf den Produktionsschlüssel, und was entschlüsselt wird, sind die Produktions-Credentials. Ich habe Claude diese Zeile schreiben sehen — das Kamal-Default-Template ist config/master.key (das Dev), das den Dev-Stripe-Key still und leise in die Produktion deployt.

Leitplanke #2: Nutze ein EDITOR-Skript, kein Copy-Paste

bin/rails credentials:edit --environment production öffnet einen interaktiven Editor. Claude kann keinen interaktiven Editor steuern. Du willst auch nicht manuell ein Dutzend Secrets einfügen (ein Tippfehler und alles ist hin).

Nutze dieses Muster:

EDITOR="ruby script/set_prod_webhook_secret.rb" \
  bin/rails credentials:edit --environment production
rm script/set_prod_webhook_secret.rb

script/set_prod_webhook_secret.rb sieht so aus:

# ARGV[0] ist der Pfad zur temporären entschlüsselten YAML-Datei
file = ARGV[0]
require "yaml"
data = YAML.load_file(file) || {}
data["stripe"] ||= {}
data["stripe"]["webhook_secret"] = "whsec_GHWObNAKFh2HPOlJpbGmlYfIiKz1C8EY"
File.write(file, data.to_yaml)

Rails schreibt das entschlüsselte YAML in eine Temp-Datei, ruft deinen „EDITOR" mit diesem Pfad als Argument auf und verschlüsselt beim Beenden neu. Dein „EDITOR" ist einfach ein Ruby-Skript, das chirurgisch einen Key ändert und speichert.

Warum das gut ist:
- Präzise: berührt nur stripe.webhook_secret, sonst nichts.
- Idempotent: zweimal ausführen ist wie einmal.
- Auditierbar: das Skript ist der Diff. Claude schreibt es, du schaust kurz drauf, und weißt genau, was es ändert.
- Verschwindet beim Löschen: nach rm gibt es kein Klartext-Credential auf der Platte, kein whsec_...-Paste in der Shell-History.

Ein Skript pro Credential: set_stripe_live_key.rb, set_webhook_secret.rb, set_price_ids.rb, set_wallet_address.rb. Jedes gleich danach rm.

Leitplanke #3: Verifiziere durch Rücklesen mit Rails Runner

Nach dem Schreiben trau nicht darauf, dass er's richtig geschrieben hat. Lies zurück:

bin/rails runner -e production "
c = Rails.application.credentials
puts 'sk_live set: ' + c.dig(:stripe, :secret_key).to_s.start_with?('sk_live_').to_s
puts 'webhook_secret set: ' + c.dig(:stripe, :webhook_secret).to_s.start_with?('whsec_').to_s
puts 'wallet prefix: ' + c.dig(:x402, :wallet_address).to_s[0..5]
puts 'wallet len: ' + c.dig(:x402, :wallet_address).to_s.length.to_s
"

Der Schlüssel sind Präfix- und Längen-Checks, nicht nur die Werte ausdrucken.

  • Ein Stripe-Live-Secret hat immer das Präfix sk_live_. Liest du sk_test_ zurück, hat Claude den Test-Key in die Prod-Datei gesteckt — ein Bug, den du erst bei der ersten echten Zahlung findest.
  • Webhook-Secrets haben immer das Präfix whsec_. Format stimmt oder nicht, mit einem Blick zu sehen.
  • EVM-Wallet-Adressen sind immer 42 Zeichen, 0x.... Falsche Länge bedeutet, ein anderes Zeichen hat sich eingeschlichen.

Präfix-Checks hinzufügen blockiert die meisten Tippfehler, vergessene Felder und gemischte Umgebungen.

Leitplanke #4: Zur Laufzeit nach Env umschalten, nicht beim Deploy per Hand

Es ist verlockend, zu denken „ich stelle das Netzwerk vor dem Deploy auf Mainnet um". So ein Switch hängt am menschlichen Gedächtnis. Früher oder später wird's dich verbrennen.

Back die Regel in den Initializer:

# config/initializers/x402.rb
X402.configure do |c|
  c.wallet_address = Rails.application.credentials.dig(:x402, :wallet_address)
  c.chain = Rails.env.production? ? "base" : "base-sepolia"
end

Derselbe Code, Testnet (sepolia) in Dev, Mainnet (base) in Prod. Beim Deploy nichts zu ändern. Claude kann nicht „vergessen umzuschalten", weil Umschalten nicht sein Job ist.

Gleicher Trick für basescan_tx_url, Plan-Sichtbarkeit (dev-only Pläne werden in Prod nicht gerendert), Stripe-Price-ID-Auswahl und so weiter. Alles, was sich zwischen Dev und Prod unterscheidet, über Rails.env kippen. Verlass dich nicht aufs Erinnern zur Deploy-Zeit.

Der letzte Schritt: geh den echten Flow selbst durch

Mit allen vier Leitplanken musst du trotzdem die Zahlung mit echtem Geld selbst durchklicken.

Im vorherigen Artikel Stille Bugs mit Claude debuggen habe ich den ersten x402-Zahlungsklick in Prod beschrieben: invalid_string at payTo in der Console. Das 43. Zeichen der Wallet-Adresse war ein Fullwidth-Fragezeichen, das aus einer chinesischen IME reingerutscht war. Präfix-Checks konnten es nicht fangen (0x stand da noch), Tests konnten es nicht fangen (Tests feuern keine echten Transaktionen ab), nur ein echter Klick hat es zutage gefördert.

Deployment-Leitplanken sind nicht für Claude. Sie sind für dich — automatisier, was sich automatisieren lässt (Präfixe, Längen, Env-Switches), damit die gesparte Aufmerksamkeit in die echten Interaktionen fließt, die Automation nicht abdeckt.


Der volle Claude-Deploy-Flow:

  1. Trenne Dev- und Prod-Credentials in getrennte .enc- + .key-Dateien.
  2. Für jeden zu setzenden Wert schreib ein Einweg-Ruby-Skript, füttere es via EDITOR=script, lösch es sofort.
  3. Nach jedem Schreiben: mit Rails Runner zurücklesen, Präfixe und Längen prüfen.
  4. Alle Dev/Prod-Unterschiede über Rails.env kippen, nicht zur Deploy-Zeit.
  5. Den Echtes-Geld-Button beim ersten Mal selbst klicken.

Deployment ist nicht „Code schreiben mit höheren Einsätzen". Deployment ist „Code schreiben, bei dem dir niemand sagt, dass du falsch liegst". Die Leitplanken sind da, um „niemand sagt's dir" in „du weißt es binnen 15 Sekunden" zu verwandeln.