Referenz

CaptchaAI in der Produktion: Leitfaden zur Konfigurationsverwaltung

Eine produktionsreife CaptchaAI-Integration steht und fällt mit drei Fragen: Wo liegt der API-Schlüssel, welche Einstellung gewinnt bei einem Konflikt, und lässt sich die Concurrency ändern, ohne neu zu deployen? Dieser Leitfaden beantwortet alle drei – mit einer klaren Präzedenzordnung aus Umgebungsvariablen, Konfigurationsdateien und Code-Defaults, sauberem Secret-Management und umgebungsspezifischen Overrides für Staging und Produktion. Hartcodierte Schlüssel und Timeouts reichen für einen Prototyp; im Betrieb tragen sie nicht.

Präzedenzordnung: welche Einstellung gewinnt

Priority (highest → lowest):

1. Environment variables     ← deployment-specific overrides
2. Config file (YAML/JSON)   ← version-controlled defaults
3. Application defaults      ← fallback values in code

Die Reihenfolge folgt einem einfachen Prinzip – je näher eine Quelle am Betrieb liegt, desto höher ihre Priorität:

  • Umgebungsvariablen überschreiben alles andere und tragen die deployment-spezifischen Werte.
  • Konfigurationsdatei (YAML/JSON) liefert versionierte Defaults pro Umgebung.
  • Code-Defaults greifen nur, wenn weder Variable noch Datei einen Wert setzen.

Wer zusätzlich eine CLI-Flag-Ebene darüberlegt, folgt demselben Muster: Die operatornächste Quelle gewinnt.

Konfigurations-Loader für Python und Node.js

Der Loader gießt diese Präzedenzordnung in eine einzige Funktion: Erst greifen die Defaults, dann die Datei, zuletzt die Umgebungsvariablen. Die validate-Methode bricht früh ab, wenn der API-Schlüssel fehlt oder Poll-Intervall bzw. Concurrency unplausibel sind – ein klarer Fehler beim Start ist besser als ein stiller Ausfall unter Last.

Python

import os
import yaml
from dataclasses import dataclass, field
from pathlib import Path


@dataclass
class CaptchaAIConfig:
    api_key: str = ""
    submit_url: str = "https://ocr.captchaai.com/in.php"
    poll_url: str = "https://ocr.captchaai.com/res.php"
    poll_interval: int = 5
    max_polls: int = 60
    concurrency: int = 10
    timeout: int = 300
    proxy: str = ""
    callback_url: str = ""
    retries: int = 3
    log_level: str = "info"

    @classmethod
    def load(cls, config_path=None):
        """Load config: env vars override file, which overrides defaults."""
        config = cls()

        # Layer 2: Config file
        if config_path and Path(config_path).exists():
            with open(config_path) as f:
                file_config = yaml.safe_load(f) or {}
            for key, value in file_config.items():
                if hasattr(config, key):
                    setattr(config, key, value)

        # Layer 1: Environment variables (highest priority)
        env_map = {
            "CAPTCHAAI_API_KEY": "api_key",
            "CAPTCHAAI_SUBMIT_URL": "submit_url",
            "CAPTCHAAI_POLL_URL": "poll_url",
            "CAPTCHAAI_POLL_INTERVAL": "poll_interval",
            "CAPTCHAAI_MAX_POLLS": "max_polls",
            "CAPTCHAAI_CONCURRENCY": "concurrency",
            "CAPTCHAAI_TIMEOUT": "timeout",
            "CAPTCHAAI_PROXY": "proxy",
            "CAPTCHAAI_CALLBACK_URL": "callback_url",
            "CAPTCHAAI_RETRIES": "retries",
            "CAPTCHAAI_LOG_LEVEL": "log_level",
        }

        for env_key, attr_name in env_map.items():
            value = os.environ.get(env_key)
            if value is not None:
                # Cast to correct type
                current = getattr(config, attr_name)
                if isinstance(current, int):
                    value = int(value)
                setattr(config, attr_name, value)

        config.validate()
        return config

    def validate(self):
        if not self.api_key:
            raise ValueError("CAPTCHAAI_API_KEY is required")
        if self.poll_interval < 1:
            raise ValueError("poll_interval must be >= 1")
        if self.concurrency < 1:
            raise ValueError("concurrency must be >= 1")


# Usage
config = CaptchaAIConfig.load("config/captchaai.yaml")
print(f"Concurrency: {config.concurrency}, Timeout: {config.timeout}s")

JavaScript

const fs = require("fs");
const yaml = require("js-yaml");
const path = require("path");

class CaptchaAIConfig {
  static defaults = {
    apiKey: "",
    submitUrl: "https://ocr.captchaai.com/in.php",
    pollUrl: "https://ocr.captchaai.com/res.php",
    pollInterval: 5,
    maxPolls: 60,
    concurrency: 10,
    timeout: 300,
    proxy: "",
    callbackUrl: "",
    retries: 3,
    logLevel: "info",
  };

  static envMap = {
    CAPTCHAAI_API_KEY: "apiKey",
    CAPTCHAAI_SUBMIT_URL: "submitUrl",
    CAPTCHAAI_POLL_URL: "pollUrl",
    CAPTCHAAI_POLL_INTERVAL: { key: "pollInterval", type: "int" },
    CAPTCHAAI_MAX_POLLS: { key: "maxPolls", type: "int" },
    CAPTCHAAI_CONCURRENCY: { key: "concurrency", type: "int" },
    CAPTCHAAI_TIMEOUT: { key: "timeout", type: "int" },
    CAPTCHAAI_PROXY: "proxy",
    CAPTCHAAI_CALLBACK_URL: "callbackUrl",
    CAPTCHAAI_RETRIES: { key: "retries", type: "int" },
    CAPTCHAAI_LOG_LEVEL: "logLevel",
  };

  static load(configPath = null) {
    let config = { ...CaptchaAIConfig.defaults };

    // Layer 2: Config file
    if (configPath && fs.existsSync(configPath)) {
      const ext = path.extname(configPath);
      const raw = fs.readFileSync(configPath, "utf8");
      const fileConfig = ext === ".json" ? JSON.parse(raw) : yaml.load(raw);
      config = { ...config, ...fileConfig };
    }

    // Layer 1: Environment variables
    for (const [envKey, mapping] of Object.entries(CaptchaAIConfig.envMap)) {
      const value = process.env[envKey];
      if (value !== undefined) {
        const attrKey = typeof mapping === "string" ? mapping : mapping.key;
        const type = typeof mapping === "string" ? "string" : mapping.type;
        config[attrKey] = type === "int" ? parseInt(value, 10) : value;
      }
    }

    CaptchaAIConfig.validate(config);
    return config;
  }

  static validate(config) {
    if (!config.apiKey) throw new Error("CAPTCHAAI_API_KEY is required");
    if (config.pollInterval < 1) throw new Error("pollInterval must be >= 1");
    if (config.concurrency < 1) throw new Error("concurrency must be >= 1");
  }
}

// Usage
const config = CaptchaAIConfig.load("config/captchaai.yaml");
console.log(`Concurrency: ${config.concurrency}, Timeout: ${config.timeout}s`);

Umgebungsspezifische Konfigurationsdateien

Eine Basisdatei hält die gemeinsamen Defaults, je eine Override-Datei pro Umgebung passt Concurrency, Poll-Intervall und Log-Level an. Die Produktion fährt aggressiver – mehr Parallelität, knapperes Timeout, warning-Log –, während Staging konservativ und gesprächig bleibt (debug).

# config/captchaai.yaml — base
api_key: ""  # Always set via env var
concurrency: 5
poll_interval: 5
retries: 3
log_level: info
# config/captchaai.production.yaml
concurrency: 20
poll_interval: 3
timeout: 180
log_level: warning
# config/captchaai.staging.yaml
concurrency: 3
poll_interval: 5
timeout: 300
log_level: debug

Beispiel: Worker-Deployment auf Hetzner Cloud

Angenommen, Ihre Worker laufen als Container auf Hetzner Cloud und werden über GitLab CI ausgerollt. Den API-Schlüssel hinterlegen Sie als geschützte CI/CD-Variable, nicht in der YAML-Datei. Ein wichtiger Richtwert: Setzen Sie CAPTCHAAI_CONCURRENCY nie höher als die Thread-Zahl Ihres Plans. BASIC (15 $/Monat) umfasst 5 Threads, STANDARD (30 $/Monat) 15 und ADVANCE (90 $/Monat) 50 – die Produktions-Override mit concurrency: 20 setzt also mindestens den ADVANCE-Plan voraus. CaptchaAI rechnet pro Thread ab, nicht pro Lösung; die Concurrency-Einstellung ist damit direkt an Ihren Tarif gekoppelt.

Alle Konfigurationsparameter im Überblick

Die folgende Referenz listet jeden Parameter mit zugehöriger Umgebungsvariable und Standardwert. Nur CAPTCHAAI_API_KEY ist zwingend erforderlich; alle übrigen Werte haben brauchbare Defaults, die Sie erst bei Bedarf überschreiben.

Parameter Umgebungsvariable Standard Beschreibung
API-Schlüssel CAPTCHAAI_API_KEY Pflichtfeld. Ihr CaptchaAI-API-Schlüssel
Submit-URL CAPTCHAAI_SUBMIT_URL https://ocr.captchaai.com/in.php Endpunkt für die Aufgabenübermittlung
Poll-URL CAPTCHAAI_POLL_URL https://ocr.captchaai.com/res.php Endpunkt der Ergebnisabfrage
Poll-Intervall CAPTCHAAI_POLL_INTERVAL 5 Sekunden zwischen den Abfrageversuchen
Max. Poll-Versuche CAPTCHAAI_MAX_POLLS 60 Maximale Abfragen vor dem Timeout
Concurrency CAPTCHAAI_CONCURRENCY 10 Maximale parallele CAPTCHA-Aufgaben
Timeout CAPTCHAAI_TIMEOUT 300 Gesamt-Timeout in Sekunden
Proxy CAPTCHAAI_PROXY Proxy-URL für das Lösen von CAPTCHAs
Callback-URL CAPTCHAAI_CALLBACK_URL Webhook-URL für asynchrone Ergebnisse
Wiederholungsversuche CAPTCHAAI_RETRIES 3 Erneute Versuche bei transienten Fehlern
Log-Level CAPTCHAAI_LOG_LEVEL info Ausführlichkeit der Protokollierung

Secret-Management: API-Schlüssel sicher halten

Speichern Sie API-Schlüssel niemals in Konfigurationsdateien oder im Repository. Zwei Grundregeln gelten unabhängig von der gewählten Methode:

  • Der Schlüssel verlässt nie die Versionsverwaltung – auch nicht in einer .env, die versehentlich eingecheckt wird.
  • Zugriff bleibt protokolliert und rotierbar; ein kompromittierter Schlüssel muss sich in Minuten austauschen lassen.

Welche konkrete Methode passt, hängt von Ihrer Infrastruktur ab:

Methode Am besten geeignet für Beispiel
Umgebungsvariablen Container, CI/CD export CAPTCHAAI_API_KEY=abc123
AWS Secrets Manager AWS-Infrastruktur Beim Start abrufen; automatische Rotation
HashiCorp Vault Multi-Cloud, On-Premises Dynamische Secrets mit TTL
Docker Secrets Docker Swarm / Compose Unter /run/secrets/ eingebunden
.env-Datei (nur Entwicklung) Lokale Entwicklung dotenv-Bibliothek; per .gitignore ausschließen

Docker-Compose-Beispiel

services:
  captcha-worker:
    image: captcha-worker:latest
    environment:

      - CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
      - CAPTCHAAI_CONCURRENCY=15
      - CAPTCHAAI_LOG_LEVEL=warning
    env_file:

      - .env.production

Wenn Sie zusätzlich einen Proxy über CAPTCHAAI_PROXY einbinden, sollten Sie die DSGVO mitdenken: IP-Adressen gelten als personenbezogene Daten. Prüfen Sie Zweck und Rechtsgrundlage Ihrer Datenflüsse, bevor Sie Proxy-Traffic in der Produktion aktivieren – das ist Sorgfaltspflicht auf Ihrer Seite, keine Compliance-Zusage des Dienstes.

Feature-Flags ohne Redeploy

Feature-Flags schalten Verhalten zur Laufzeit um, ohne dass Sie neu deployen müssen. Typische Kandidaten:

  • Callback-Modus an- oder abschalten, statt synchron auf das Ergebnis zu warten.
  • Proxy-Nutzung pro Umgebung aktivieren, ohne den Code anzufassen.
  • Obergrenze paralleler Aufgaben kurzfristig anheben oder senken.

Das folgende Muster liest die Flags aus Umgebungsvariablen:

class FeatureFlags:
    def __init__(self):
        self.flags = {
            "use_callback": os.environ.get("FF_USE_CALLBACK", "false") == "true",
            "enable_proxy": os.environ.get("FF_ENABLE_PROXY", "true") == "true",
            "max_concurrent": int(os.environ.get("FF_MAX_CONCURRENT", "10")),
        }

    def is_enabled(self, flag):
        return self.flags.get(flag, False)

    def get(self, flag, default=None):
        return self.flags.get(flag, default)

Fehlerbehebung

Die häufigsten Störungen entstehen nicht beim Lösen selbst, sondern beim Laden der Konfiguration. Diese Tabelle deckt die typischen Fälle ab:

Problem Ursache Lösung
API-Schlüssel wird nicht geladen Umgebungsvariable fehlt oder ist falsch benannt echo $CAPTCHAAI_API_KEY prüfen, Schreibweise kontrollieren
Konfigurationsdatei wird ignoriert Falscher Pfad oder fehlende YAML-Bibliothek Existenz der Datei prüfen, pyyaml bzw. js-yaml installieren
Produktion nutzt Entwicklungswerte Umgebungsspezifischer Override greift nicht Präzedenz der Variablen prüfen, APP_ENV / NODE_ENV verifizieren
Secrets erscheinen im Log Config-Dump enthält den API-Schlüssel Sensible Felder in der Log-Ausgabe maskieren

Häufige Fragen

Wie hoch sollte ich die Concurrency in der Produktion setzen?

Höchstens so hoch wie die Thread-Zahl Ihres Plans. Da CaptchaAI pro Thread abrechnet, bringt eine Concurrency oberhalb Ihrer Thread-Zuteilung keinen zusätzlichen Durchsatz – ADVANCE (90 $/Monat) erlaubt bis zu 50 parallele Aufgaben, BASIC (15 $/Monat) fünf. Beginnen Sie konservativ und erhöhen Sie schrittweise unter realer Last.

Wo gehört der CaptchaAI-API-Schlüssel im Deployment hin?

In eine Umgebungsvariable oder einen Secret-Manager, niemals in die Konfigurationsdatei oder ins Repository. Für Container genügt CAPTCHAAI_API_KEY als Umgebungsvariable; auf AWS bietet sich der Secrets Manager mit automatischer Rotation an.

Kann ich Einstellungen ändern, ohne neu zu deployen?

Ja. Lesen Sie Werte wie die Concurrency zu Beginn jedes Aufgaben-Batches aus der Umgebungsvariable oder einem Config-Dienst aus, nicht nur beim Start. Dann genügen ein aktualisierter Wert und ein Reload-Signal.

Welche Timeout- und Poll-Werte sind in der Produktion sinnvoll?

In der Produktion oft ein knapperes Gesamt-Timeout (etwa 180 Sekunden) bei kürzerem Poll-Intervall (3 Sekunden), damit hängende Aufgaben schnell auffallen. Staging darf großzügiger sein (300 Sekunden, debug-Log), um Fehler in Ruhe zu analysieren.


Verwandte Leitfäden

Kommentare sind für diesen Artikel deaktiviert.