Konfiguration
Postbox nutzt sechs Custom Config-Dateien und eine angepasste Laravel-Queue-Config neben den Laravel-Standard-Konfigurationen. Alle projektspezifischen Werte sind ueber .env-Variablen steuerbar.
Location: config/
Config-Dateien Uebersicht
| Datei | Zweck |
|---|---|
postbox.php | Zentrale App-Konfiguration (Admin, Rotation, Health, Sanitizer, Retry, Tags, Mail, Notifications) |
queue.php | Laravel Queue mit angepasstem retry_after (900s) fuer langlebige Jobs |
collector.php | Collector-Job-Settings (Lease TTL) |
feedback.php | Feedback-Feature (Empfaenger, Rate-Limit) |
google_api_usage.php | Google API Quota Monitoring |
server-monitoring.php | Server-Alert-Schwellwerte und Metriken |
vantage.php | Vantage Queue Monitoring Dashboard |
postbox.php
Zentrale Konfiguration mit allen projektspezifischen Einstellungen.
Location: config/postbox.php
Admin
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
admin_emails | POSTBOX_ADMIN_EMAILS | '' | Kommaseparierte Admin-E-Mail-Adressen. Wird normalisiert (Lowercase, Trimming). |
Legal Pages
Pflicht-Checkboxen fuer Datenschutzerklaerung und Nutzungsbedingungen auf der Registrierungsseite. Die Checkboxen verlinken auf CMS-Seiten, deren Inhalt in Alpine.js-Modals angezeigt wird.
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
legal.privacy_page_id | LEGAL_PRIVACY_PAGE_ID | 0 | CMS Page-ID fuer Datenschutzerklaerung (0 = kein Modal-Link) |
legal.terms_page_id | LEGAL_TERMS_PAGE_ID | 0 | CMS Page-ID fuer Nutzungsbedingungen (0 = kein Modal-Link) |
YouTube
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
youtube_custom_url_search_fallback | POSTBOX_YOUTUBE_CUSTOM_URL_SEARCH_FALLBACK | false | Fallback ueber search.list fuer Custom-URL-Aufloesung (Quota-intensiv) |
youtube_rotation_days | POSTBOX_YOUTUBE_ROTATION_DAYS | 3 | Rotation-Kadenz fuer taegliche YouTube-Scrapes (Hard-Cap: max 4 Tage). 1 = taeglich. |
leaderboard_candidate_limit | POSTBOX_LEADERBOARD_CANDIDATE_LIMIT | 200 | Kandidaten-Limit fuer Priority-Scraping (Top/Flop + Rising Stars) |
Low-Priority-Rotation
Profile unter dem Follower-Threshold werden im langsameren Zyklus gescrapt. Gilt plattformuebergreifend fuer Instagram und YouTube. Favorites und PRO-Profile sind ausgenommen.
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
low_priority_follower_count | POSTBOX_LOW_PRIORITY_FOLLOWER_COUNT | 100 | Follower-Schwelle fuer Low-Priority (Minimum: 100). Profile darunter werden seltener gescrapt. |
low_priority_rotation_days | POSTBOX_LOW_PRIORITY_ROTATION_DAYS | 7 | Rotation-Kadenz fuer Low-Priority-Profile (Hard-Cap: max 7 Tage) |
Instagram
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
instagram_rotation_days | POSTBOX_INSTAGRAM_ROTATION_DAYS | 3 | Rotation-Kadenz fuer taegliche Instagram-Scrapes (Hard-Cap: max 4 Tage) |
instagram_priority_default | POSTBOX_INSTAGRAM_PRIORITY_DEFAULT | 0 | Basis-Prioritaet fuer Rotation-Scrapes |
instagram_priority_low_priority_new_profile | POSTBOX_INSTAGRAM_PRIORITY_LOW_PRIORITY_NEW_PROFILE | 5 | Prioritaet fuer nie gescrapte Profile mit < 100 Followers (low-prio Imports) |
instagram_priority_catch_up | POSTBOX_INSTAGRAM_PRIORITY_CATCH_UP | 10 | Prioritaet fuer verpasste Scrapes |
instagram_priority_favorite | POSTBOX_INSTAGRAM_PRIORITY_FAVORITE | 20 | Prioritaet fuer Favoriten-Profile |
instagram_priority_candidate | POSTBOX_INSTAGRAM_PRIORITY_CANDIDATE | 40 | Prioritaet fuer Leaderboard-Kandidaten |
instagram_priority_top_leader | POSTBOX_INSTAGRAM_PRIORITY_TOP_LEADER | 50 | Prioritaet fuer Top-Leader |
instagram_priority_new_profile | POSTBOX_INSTAGRAM_PRIORITY_NEW_PROFILE | 60 | Hoechste Prioritaet fuer nie gescrapte Profile mit >= 100 Followers (regulaere Imports) |
Health Monitoring
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
health.token | HEALTH_TOKEN | null | Token fuer /up_system-Endpoint (X-Health-Token Header) |
health.failed_jobs_threshold | HEALTH_FAILED_JOBS_THRESHOLD | 100 | Warnschwelle fuer Failed Jobs |
health.collector_heartbeat_minutes | HEALTH_COLLECTOR_HEARTBEAT_MINUTES | 30 | Heartbeat-Timeout fuer Collector-Clients |
health.queue_quiet_start | HEALTH_QUEUE_QUIET_START | 4 | Queue Quiet Hours Start (UTC-Stunde, 0-23) |
health.queue_quiet_end | HEALTH_QUEUE_QUIET_END | 6 | Queue Quiet Hours Ende (UTC-Stunde, 0-23) |
Cron-Heartbeat-Monitoring (health.cron_heartbeats):
| Heartbeat | Max Minutes | Label |
|---|---|---|
instagram_scrape | 180 | Instagram Scrape (2h) |
youtube_scrape | 180 | YouTube Scrape (2h) |
explore_metrics | 1560 | Explore Metrics (daily) |
scores_calculate | 1560 | Score Calculation (daily) |
google_api_sync | 150 | Google API Sync (1h) |
queue_metrics | 45 | Queue Metrics (15min) |
server_alerts | 15 | Server Alerts (5min) |
cross_platform_auto_fill | 15 | Cross-Platform Auto-Fill (5min) |
Cross-Platform
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
cross_platform.stale_days | CROSS_PLATFORM_STALE_DAYS | 90 | Tage bis Re-Berechnung faellig wird |
Profile Retry
Steuerung der Retry-Strategie fuer deaktivierte Profile (Fail-Streak).
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
profile_retry.fail_streak_threshold | POSTBOX_FAIL_STREAK_THRESHOLD | 14 | Tage konsekutiver Fehler bis zur Auto-Deaktivierung |
profile_retry.fail_streak_cooldown_after | POSTBOX_FAIL_STREAK_COOLDOWN_AFTER | 3 | Ab welchem Fail-Streak der Cooldown greift |
profile_retry.fail_streak_cooldown_days | POSTBOX_FAIL_STREAK_COOLDOWN_DAYS | 3 | Tage zwischen Retry-Versuchen im Cooldown |
profile_retry.initial_retry_interval_days | POSTBOX_INITIAL_RETRY_INTERVAL_DAYS | 14 | Tage zwischen Retries (Phase 1: intensiv) |
profile_retry.initial_retry_count | POSTBOX_INITIAL_RETRY_COUNT | 3 | Anzahl Retries in der intensiven Phase |
profile_retry.monthly_retry_interval_days | POSTBOX_MONTHLY_RETRY_INTERVAL_DAYS | 30 | Tage zwischen Retries nach Phase 1 (monatlich) |
profile_retry.archive_after_months | POSTBOX_ARCHIVE_AFTER_MONTHS | 6 | Monate bis zur permanenten Archivierung |
profile_retry.queue | POSTBOX_RETRY_QUEUE | profile-retry | Queue-Name fuer Retry-Jobs |
Profile Sanitizer
Automatische Deaktivierung von Low-Value-Profilen.
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
sanitizer.min_age_days | POSTBOX_SANITIZER_MIN_AGE_DAYS | 7 | Mindestalter (Tage) vor Sanitization |
sanitizer.min_data_points | POSTBOX_SANITIZER_MIN_DATA_POINTS | 3 | Mindest-Metriken vor Sanitization |
sanitizer.youtube_min_subscribers | POSTBOX_SANITIZER_YT_MIN_SUBSCRIBERS | 100 | YouTube: Mindest-Subscriber |
sanitizer.youtube_min_videos | POSTBOX_SANITIZER_YT_MIN_VIDEOS | 1 | YouTube: Mindest-Videos |
sanitizer.instagram_min_followers | POSTBOX_SANITIZER_IG_MIN_FOLLOWERS | 100 | Instagram: Mindest-Follower |
sanitizer.instagram_min_posts | POSTBOX_SANITIZER_IG_MIN_POSTS | 1 | Instagram: Mindest-Posts |
sanitizer.recheck_months | POSTBOX_SANITIZER_RECHECK_MONTHS | 3 | Monate bis Re-Check bereits sanitizter Profile |
Tag Consolidation
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
tag_consolidation.chunk_size | POSTBOX_TAG_CHUNK_SIZE | 50 | Tags pro Gemini-Chunk |
tag_consolidation.max_chunks | POSTBOX_TAG_MAX_CHUNKS | 100 | Max. Chunks pro Lauf (Safety Limit) |
tag_consolidation.rate_per_minute | POSTBOX_TAG_RATE_PER_MINUTE | 10 | API-Call-Limit pro Minute |
tag_consolidation.established_threshold | POSTBOX_TAG_ESTABLISHED_THRESHOLD | 5 | Min. Profile fuer "established" Tag |
tag_consolidation.auto_execute_high_confidence | POSTBOX_TAG_AUTO_EXECUTE | true | High-Confidence Merges auto-ausfuehren |
tag_consolidation.min_tag_length | POSTBOX_TAG_MIN_LENGTH | 3 | Minimale Tag-Laenge |
tag_consolidation.consolidation_cooldown_days | POSTBOX_TAG_COOLDOWN_DAYS | 90 | Cooldown pro Tag (Tage) |
Mail Flood Guard
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
mail_flood.cache_store | MAIL_FLOOD_CACHE_STORE | Cache Default | Cache-Store fuer Flood Guard Counter |
mail_flood.threshold_per_hour | MAIL_FLOOD_THRESHOLD_HOUR | 200 | Max. E-Mails pro Stunde |
mail_flood.threshold_per_minute | MAIL_FLOOD_THRESHOLD_MINUTE | 50 | Max. E-Mails pro Minute |
mail_flood.auto_pause | MAIL_FLOOD_AUTO_PAUSE | true | Automatisch pausieren bei Schwelle |
mail_flood.admin_notification | MAIL_FLOOD_ADMIN_NOTIFICATION | true | Admin-Alert bei Pause |
Notification Types
Die Konfiguration unter notification_types definiert alle Benachrichtigungstypen mit Labels, Defaults und Kategorien. Jeder Typ hat:
label/description: Anzeige in der Settings-UIdefault_app/default_email: Default-Kanal (all,important,none)supports_workspace: Workspace-bezogene Filterungcategory: Gruppierung (profiles,data,discovery,system)force_app(optional): Kann nicht deaktiviert werden
queue.php (Laravel Queue — angepasst)
Location: config/queue.php
Standard-Laravel-Konfiguration mit einem wichtigen angepassten Wert:
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
connections.database.retry_after | DB_QUEUE_RETRY_AFTER | 3600 | Reservierungs-Timeout in Sekunden. Muss hoeher sein als der laengste Job-$timeout (aktuell 2400s fuer Leaderboard-Pipeline-Jobs). |
Warum 3600s statt Laravel-Default 90s?
Der Database-Queue-Driver markiert Jobs als "abandoned" nach retry_after Sekunden. Wenn ein Job laenger laeuft als retry_after, gibt der Driver den Job frei und ein zweiter Worker nimmt ihn auf — das fuehrt zu MaxAttemptsExceededException oder doppelter Ausfuehrung. Die Leaderboard-Pipeline-Jobs haben $timeout = 2400 (wachsende Datenmengen erfordern Spielraum), daher muss retry_after deutlich hoeher liegen. 3600s bietet einen komfortablen Puffer.
Tradeoff: Wenn ein Worker abstuerzt waehrend er einen Job verarbeitet, wird der Job erst nach 60 Minuten erneut verfuegbar (statt 90 Sekunden). Da Postbox mehrere Worker-Prozesse parallel laeuft, ist dieser Tradeoff akzeptabel.
collector.php
Location: config/collector.php
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
lease_ttl_seconds | COLLECTOR_LEASE_TTL_SECONDS | 300 | Lease-Dauer fuer Collector-Jobs (Sekunden). Nach Ablauf wird der Job frei fuer andere Clients. |
feedback.php
Location: config/feedback.php
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
recipient | FEEDBACK_RECIPIENT | MAIL_FROM_ADDRESS | E-Mail-Empfaenger fuer Feedback-Reports |
from_address | FEEDBACK_FROM_ADDRESS | hello@postbox.so | Absender-Adresse (sollte vom Empfaenger abweichen) |
from_name | FEEDBACK_FROM_NAME | Postbox | Absender-Name |
rate_limit | FEEDBACK_RATE_LIMIT | 30 | Max. Feedbacks pro User pro Stunde |
google_api_usage.php
Location: config/google_api_usage.php
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
projects | GOOGLE_API_USAGE_PROJECTS | '' | Kommaseparierte Google Cloud Projekt-IDs |
service | GOOGLE_API_USAGE_SERVICE | youtube.googleapis.com | API Service Name fuer Monitoring |
sync_interval_minutes | GOOGLE_API_USAGE_SYNC_INTERVAL | 60 | Sync-Intervall in Minuten |
credentials_path | GOOGLE_APPLICATION_CREDENTIALS | null | Pfad zu Service-Account Credentials JSON |
Fester Scope: https://www.googleapis.com/auth/cloud-platform
server-monitoring.php
Location: config/server-monitoring.php
Alert-Schwellwerte
| Metrik | Warning | Critical | Logik |
|---|---|---|---|
cpu_percent | 75 | 90 | Ueber dem Wert = Alarm |
ram_percent | 80 | 90 | Ueber dem Wert = Alarm |
swap_percent | 25 | 50 | Ueber dem Wert = Alarm |
disk_percent | 80 | 90 | Ueber dem Wert = Alarm |
pg_connections | 80 | 150 | Ueber dem Wert = Alarm |
pg_cache_hit | 95 | 90 | Unter dem Wert = Alarm (invertiert) |
Weitere Einstellungen
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
sustained_alert_cooldown_minutes | SERVER_ALERT_SUSTAINED_COOLDOWN | 240 | Cooldown bei anhaltendem Alert (Minuten). Bei Statuswechsel sofort. |
active_users_minutes | SERVER_ACTIVE_USERS_MINUTES | 5 | Schwelle fuer "aktive" Session (Minuten) |
pg_max_connections | SERVER_PG_MAX_CONNECTIONS | 200 | PostgreSQL max_connections fuer Prozent-Berechnung |
vantage.php
Location: config/vantage.php
| Key | Env-Variable | Default | Beschreibung |
|---|---|---|---|
enabled | VANTAGE_ENABLED | true | Master-Switch fuer das gesamte Package |
store_payload | VANTAGE_STORE_PAYLOAD | true | Job-Payloads fuer Debugging speichern |
redact_keys | -- | [password, token, secret, ...] | Sensitive Keys im Payload werden redacted |
retention_days | VANTAGE_RETENTION_DAYS | 14 | Aufbewahrungsdauer fuer Job-History (Tage) |
routes | VANTAGE_ROUTES | true | Dashboard-Routen registrieren |
route_prefix | VANTAGE_ROUTE_PREFIX | vantage | URL-Prefix fuer das Dashboard |
auth.enabled | VANTAGE_AUTH_ENABLED | true | Gate-basierte Authentifizierung aktivieren |
telemetry.enabled | VANTAGE_TELEMETRY_ENABLED | true | Performance-Telemetrie sammeln |
telemetry.sample_rate | VANTAGE_TELEMETRY_SAMPLE_RATE | 1.0 | Sample Rate (0.0 - 1.0) |
telemetry.capture_cpu | VANTAGE_TELEMETRY_CPU | true | CPU-Metriken erfassen |
database_connection | VANTAGE_DATABASE_CONNECTION | null | Separate DB-Connection (null = Default) |
logging.enabled | VANTAGE_LOGGING_ENABLED | true | Package-Logging aktivieren |
notify.email | VANTAGE_NOTIFY_EMAIL | null | E-Mail fuer Failure-Notifications (deaktiviert, Flare/Nightwatch wird genutzt) |
notify.slack_webhook | VANTAGE_SLACK_WEBHOOK | null | Slack Webhook fuer Notifications |
Vollstaendige .env-Referenz (Custom Variables)
Authentifizierung
WORKOS_CLIENT_ID=client_...
WORKOS_API_KEY=sk_...
WORKOS_REDIRECT_URL=https://app.postbox.so/authenticate
POSTBOX_ADMIN_EMAILS="admin@example.com, second@example.com"
Legal Pages
LEGAL_PRIVACY_PAGE_ID=0
LEGAL_TERMS_PAGE_ID=0
YouTube API
YOUTUBE_API_KEY=AIza...
YOUTUBE_API_KEYS=key1,key2,key3
YOUTUBE_API_VIDEO_KEYS=key4,key5
YOUTUBE_API_EXTENDED_KEYS=key6,key7
YOUTUBE_API_RESEARCH_KEYS=key8
POSTBOX_YOUTUBE_CUSTOM_URL_SEARCH_FALLBACK=false
POSTBOX_YOUTUBE_ROTATION_DAYS=3
POSTBOX_LEADERBOARD_CANDIDATE_LIMIT=200
Instagram
POSTBOX_INSTAGRAM_ROTATION_DAYS=3
POSTBOX_INSTAGRAM_PRIORITY_DEFAULT=0
POSTBOX_INSTAGRAM_PRIORITY_CATCH_UP=10
POSTBOX_INSTAGRAM_PRIORITY_FAVORITE=20
POSTBOX_INSTAGRAM_PRIORITY_NEW_PROFILE=30
POSTBOX_INSTAGRAM_PRIORITY_CANDIDATE=40
POSTBOX_INSTAGRAM_PRIORITY_TOP_LEADER=50
Health Monitoring
HEALTH_TOKEN=your-secret-health-token
HEALTH_FAILED_JOBS_THRESHOLD=100
HEALTH_COLLECTOR_HEARTBEAT_MINUTES=30
HEALTH_QUEUE_QUIET_START=4
HEALTH_QUEUE_QUIET_END=6
Queue
DB_QUEUE_RETRY_AFTER=3600
Reverb (WebSockets)
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=postbox
REVERB_APP_KEY=your-random-key
REVERB_APP_SECRET=your-random-secret
REVERB_SERVER_HOST=127.0.0.1
REVERB_SERVER_PORT=8081
REVERB_HOST=app.postbox.so
REVERB_PORT=443
REVERB_SCHEME=https
Google API
GOOGLE_API_USAGE_PROJECTS=project-1,project-2
GOOGLE_API_USAGE_SERVICE=youtube.googleapis.com
GOOGLE_API_USAGE_SYNC_INTERVAL=60
GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
AI Enhancement
AI_ENHANCER_HOURLY_LIMIT=100
AI_ENHANCER_RATE_PER_MINUTE=15
AI_ENHANCER_COOLDOWN_DAYS=30
Profile Retry
POSTBOX_FAIL_STREAK_THRESHOLD=14
POSTBOX_INITIAL_RETRY_INTERVAL_DAYS=14
POSTBOX_INITIAL_RETRY_COUNT=3
POSTBOX_MONTHLY_RETRY_INTERVAL_DAYS=30
POSTBOX_ARCHIVE_AFTER_MONTHS=6
POSTBOX_RETRY_QUEUE=profile-retry
Profile Sanitizer
POSTBOX_SANITIZER_MIN_AGE_DAYS=7
POSTBOX_SANITIZER_MIN_DATA_POINTS=3
POSTBOX_SANITIZER_YT_MIN_SUBSCRIBERS=100
POSTBOX_SANITIZER_YT_MIN_VIDEOS=1
POSTBOX_SANITIZER_IG_MIN_FOLLOWERS=100
POSTBOX_SANITIZER_IG_MIN_POSTS=1
POSTBOX_SANITIZER_RECHECK_MONTHS=3
Tag Consolidation
POSTBOX_TAG_CHUNK_SIZE=50
POSTBOX_TAG_MAX_CHUNKS=100
POSTBOX_TAG_RATE_PER_MINUTE=10
POSTBOX_TAG_ESTABLISHED_THRESHOLD=5
POSTBOX_TAG_AUTO_EXECUTE=true
POSTBOX_TAG_MIN_LENGTH=3
POSTBOX_TAG_COOLDOWN_DAYS=90
Mail Flood Guard
MAIL_FLOOD_CACHE_STORE=redis
MAIL_FLOOD_THRESHOLD_HOUR=200
MAIL_FLOOD_THRESHOLD_MINUTE=50
MAIL_FLOOD_AUTO_PAUSE=true
MAIL_FLOOD_ADMIN_NOTIFICATION=true
Server Monitoring
SERVER_ALERT_SUSTAINED_COOLDOWN=240
SERVER_ACTIVE_USERS_MINUTES=5
SERVER_PG_MAX_CONNECTIONS=200
Collector
COLLECTOR_LEASE_TTL_SECONDS=300
Feedback
FEEDBACK_RECIPIENT=feedback@example.com
FEEDBACK_FROM_ADDRESS=hello@postbox.so
FEEDBACK_FROM_NAME=Postbox
FEEDBACK_RATE_LIMIT=30
Monitoring (Flare, Matomo, Nightwatch)
FLARE_KEY=your-flare-key
MATOMO_URL=https://analytics.example.com
MATOMO_SITE_ID=1
MATOMO_TOKEN=your-token
MATOMO_ENABLED=true
NIGHTWATCH_TOKEN=your-token
Vantage
VANTAGE_ENABLED=true
VANTAGE_STORE_PAYLOAD=true
VANTAGE_RETENTION_DAYS=14
VANTAGE_AUTH_ENABLED=true
VANTAGE_TELEMETRY_ENABLED=true
VANTAGE_TELEMETRY_SAMPLE_RATE=1.0