Medien in Payload CMS mit Hetzner S3 Object Storage hosten

Wie sich Hetzner Object Storage als Media-Backend in Payload CMS einbinden lässt – inklusive Client-seitiger Uploads und CORS-Konfiguration für Vercel-Deployments.

Porträt eines jungen Mannes mit kurzer brauner Frisur und blauem Hemd vor einer grünen, bewachsenen Landschaft.

Geschrieben von

Jens Becker

Veröffentlicht am

30. Mai 2025

Zuletzt aktualisiert am

1. Juli 2026

Tags

Payload CMS

Dieser Artikel zeigt, wie sich Hetzner Object Storage nutzen lässt, um Mediendateien in Payload CMS zu hosten – über sein flexibles Speicheradapter-System nutzen.

Für benutzerdefinierte CMS-Projekte wie auch produktionsbereite Plattformen mit Asset-Management ist die Integration von Hetzners kostengünstigem S3-kompatiblem Storage mit Payload eine leistungsstarke und erschwingliche Lösung.

Einrichten des Storage Buckets

  1. Im Hetzner Cloud Console anmelden.
  2. Neues Projekt erstellen (oder bestehendes auswählen).
  3. Innerhalb des Projekts einen neuen Speicherbucket hinzufügen.
  4. Zum Abschnitt Access Keys navigieren und ein neues Schlüsselpaar generieren.
  5. Access Key ID und Secret Access Key in die .env-Datei des Payload-Projekts eintragen.
  6. Auch den Namen des Speicherbuckets notieren.

Die .env-Datei benötigt folgende Variablen:

ts
HETZNER_BUCKET="bucket-name"
HETZNER_ACCESS_KEY_ID="access-key-id"
HETZNER_SECRET_ACCESS_KEY="secret-access-key"

Payload-Konfiguration

Zur Verbindung von Payload CMS mit Hetzner Object Storage dient das @joneslloyd/payload-storage-hetzner-Plugin. Dieser Community-Adapter ermöglicht nahtlose Integration mit Hetzners S3-API.

Eine grundlegende Plugin-Konfiguration sieht so aus:

ts
import hetznerStorage from '@joneslloyd/payload-storage-hetzner';

export default buildConfig({
  /* your config */
  plugins: [
    hetznerStorage({
      collections: {
        media: true,
      },
      bucket: process.env.HETZNER_BUCKET!,
      region: 'nbg1',
      credentials: {
        accessKeyId: process.env.HETZNER_ACCESS_KEY_ID!,
        secretAccessKey: process.env.HETZNER_SECRET_ACCESS_KEY!,
      },
      acl: 'public-read',
    }),
  ],
});

Für vollständige Konfigurationsoptionen siehe die npm-Dokumentation.

Unterstützung von Client-seitigen Uploads (Wichtig für Vercel)

Beim Deployment von Payload auf Vercel können Upload-Beschränkungen auftreten, die auf das 4.5 MB Body-Größenlimit von Vercel zurückzuführen sind.

Als Lösung lassen sich Client-seitige Uploads aktivieren: Mediendateien werden dabei direkt vom Browser zu Hetzner hochgeladen, ohne die API-Schicht von Payload zu durchlaufen.

Client-Uploads werden aktiviert, indem clientUploads: true in der Plugin-Konfiguration gesetzt wird.

CORS-Konfiguration für Hetzner

Client-seitige Uploads erfordern korrekt konfigurierte CORS (Cross-Origin Resource Sharing)-Regeln für den Hetzner Object Storage-Bucket. Ohne Konfiguration tritt folgender Fehler auf:

Access to fetch at '<hetzner-url>' from origin '<your-domain>' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Schritt-für-Schritt: CORS über AWS CLI einrichten

Leider bietet Hetzner derzeit keine Benutzeroberfläche zur Bearbeitung der CORS-Einstellungen. Stattdessen verwenden wir die AWS CLI, um sie zu konfigurieren.

1. CORS-Datei anlegen

Im Payload-Projekt eine s3-cors.json-Datei anlegen:

ts
{
  "CORSRules": [
    {
      "AllowedOrigins": ["https://your-domain.com"],
      "AllowedHeaders": ["*"],
      "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
      "MaxAgeSeconds": 3000
    }
  ]
}
Dies ermöglicht die Nachverfolgung der CORS-Konfiguration in der Versionskontrolle.

2. AWS CLI installieren
Installationsschritte in der AWS CLI Installationsanleitung befolgen.

3. AWS CLI-Profil anlegen
Im .aws-Ordner des Systems (z. B. ~/.aws oder C:\Users\<your-user>\.aws) folgendes eintragen:


credentials

ts
[<bucket-name>]
aws_access_key_id = <access-key-id>
aws_secret_access_key = <secret-access-key>

config

ts
[profile <bucket-name>]
region = eu-central-1
output = json
endpoint_url = https://<bucket-region>.your-objectstorage.com


4. CORS-Konfiguration anwenden

Aus dem Verzeichnis des Payload-Projekts folgenden Befehl ausführen:

ts
aws s3api put-bucket-cors \
  --bucket <your-bucket-name> \
  --cors-configuration file://./s3-cors.json \
  --endpoint-url https://<bucket-region>.your-objectstorage.com \
  --profile <bucket-name>


Fazit
Mit dieser Einrichtung ist Payload CMS vollständig in Hetzners Object Storage integriert – bereit für effizientes, skalierbares Medien-Handling. Die Kombination bietet Leistung und Flexibilität ohne hohe Kosten.