Wann Object Storage
Kein Dateisystem – eine HTTP-API: put, get, list, delete auf Objekte in einem Bucket. Kein Anhängen an eine Datei, jede Operation ein Request. Dafür: praktisch unbegrenzt, pro GB (Gigabyte) bezahlt, HTTP-erreichbar, Versionierung, Lebenszyklus-Regeln, signierte Links.
| Speicher | gut für | nicht für |
|---|---|---|
| Object Storage (S3) | Backups, App-Uploads, Bilder/Videos, statische Seiten, Logs-Archiv, „w|chst unbegrenzt“ | Datenbank-Dateien, alles mit vielen kleinen Schreibzugriffen, Home-Verzeichnis |
| Hetzner Volume | Datenbank, Nextcloud-data, alles was ein Dateisystem braucht | „unbegrenzt“ (max 10 TB), teurer pro GB |
| Storage Box | Backup-Ziel (SFTP/Borg/restic), Kalt-Archiv – günstig pro GB | HTTP-Zugriff, App-Integration per SDK (Software Development Kit) |
| Server-Platte | heiß & klein | groß, dauerhaft, geteilt |
restic / rclone → Bucket (Zweitkopie außer Haus, Backup-Guide)1 Hetzner Object Storage
-
→ Standort
fsn1/nbg1/hel1, Nameseb4u-data(im Hetzner-Namespace eindeutig), Sichtbarkeit privat. - – Access Key + Secret, sofort in den Passwortmanager.
- Endpoint:
https://fsn1.your-objectstorage.com(Path-Style) oderhttps://<bucket>.fsn1.your-objectstorage.com(Virtual-Hosted). Region-Name = der Standort.
Grundgebühr ~5,99 €/Monat inkl. 1 TB (Terabyte) Speicher + 1 TB Traffic. Darüber ~0,0054 €/GB Speicher, ~1,19 €/TB Egress. Monatlich abgerechnet (kein Stunden-Modell). Bei Hetzner nachsehen.
2 Der Client: rclone / aws
[hos]
type = s3
provider = Other
access_key_id = DEIN_ACCESS_KEY
secret_access_key = DEIN_SECRET
endpoint = https://fsn1.your-objectstorage.com
region = fsn1
acl = private
winget install Rclone.Rclone # bzw. apt install rclone
rclone ls hos:seb4u-data
rclone copy ./dist hos:seb4u-data/site --progress
rclone sync ./fotos hos:seb4u-data/fotos --progress # Achtung: loescht am Ziel, was lokal fehlt
rclone cat hos:seb4u-data/notiz.txt
rclone link hos:seb4u-data/report.pdf --expire 1h # signierter Download-Link
aws configure set default.s3.addressing_style path
$env:AWS_ACCESS_KEY_ID='...'; $env:AWS_SECRET_ACCESS_KEY='...'
aws --endpoint-url https://fsn1.your-objectstorage.com s3 ls s3://seb4u-data
3 Öffentlich vs privat
Standard: alles privat, Zugriff nur mit Key oder signiertem Link. Für statische Assets einen öffentlich lesbaren Prefix.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::seb4u-data/public/*"
}]
}
aws --endpoint-url https://fsn1.your-objectstorage.com \
s3api put-bucket-policy --bucket seb4u-data --policy file://policy.json
# CORS, falls eine Web-App direkt zugreift
aws ... s3api put-bucket-cors --bucket seb4u-data --cors-configuration file://cors.json
public/ = öffentlich lesbar (Bilder, CSS, Downloads). Alles andere privat,
die App verteilt signierte Links mit Ablauf. Keine Access-Keys in den Browser.
4 Versioning & Lifecycle
E=https://fsn1.your-objectstorage.com; B=seb4u-data
# Versionierung an: ueberschriebene/geloeschte Objekte bleiben als alte Version
aws --endpoint-url $E s3api put-bucket-versioning --bucket $B \
--versioning-configuration Status=Enabled
# Lifecycle: alte Versionen nach 30 Tagen weg, abgebrochene Uploads nach 7 Tagen
aws --endpoint-url $E s3api put-bucket-lifecycle-configuration --bucket $B \
--lifecycle-configuration file://lifecycle.json
{"Rules":[
{"ID":"expire-old-versions","Filter":{},"Status":"Enabled",
"NoncurrentVersionExpiration":{"NoncurrentDays":30},
"AbortIncompleteMultipartUpload":{"DaysAfterInitiation":7}},
{"ID":"logs-90-tage","Filter":{"Prefix":"logs/"},"Status":"Enabled",
"Expiration":{"Days":90}}
]}
Mit Versioning wird ein delete zum „als alt markieren“ – der
Platz (und die Kosten) bleiben, bis die Lifecycle-Regel aufräumt. Ohne Lifecycle-Regel
wächst der Bucket unbemerkt. Gut gegen Ransomware / Fehlklick, aber die Regel muss dazu.
5 Statische Website
- Dateien hochladen (
rclone sync ./dist hos:seb4u-data), Bucket / Prefix öffentlich lesbar (Abschnitt 3). - Website-Konfiguration:
aws ... s3 website s3://seb4u-data --index-document index.html --error-document 404.html→ ergibt eine Website-URL. - Cloudflare davor (Hetzner OS macht kein TLS auf deiner Domain):
in Cloudflare
blogals CNAME (Canonical Name) auf die Website-URL, proxied (orange). Cloudflare terminiert TLS (Transport Layer Security), cacht, versteckt den Bucket.
Cloudflare Pages (kostenlos, eigene Domain + TLS eingebaut, Git-Deploy) ist für einen Blog meist einfacher. Object-Storage-Website lohnt, wenn die Seite Teil einer grösseren S3-Nutzung ist oder sehr groß wird.
6 App-Integration
- Env-Muster (fast jede App/SDK):
S3_ENDPOINT,S3_REGION,S3_BUCKET,S3_ACCESS_KEY,S3_SECRET_KEY, oftS3_FORCE_PATH_STYLE=true. Die Keys per SOPS (Secrets OPerationS) verschlüsselt ins Repo. - Direkt-Upload aus dem Browser: der Server erzeugt eine
presigned PUT-URL (SDK:
getSignedUrl('putObject', …)), der Browser lädt direkt in den Bucket – kein Umweg über den Server, keine Keys im Client. - Nextcloud: S3 als Primärspeicher – Nextcloud-Guide, Abschnitt 6 (die DB bleibt trotzdem kritisch).
- Postgres/DB-Backups:
pg_dump | rclone rcat hos:seb4u-data/db/$(date +%F).sql.gzaus dem Cron.
7 Backup-Ziel
export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=...
export RESTIC_REPOSITORY="s3:https://fsn1.your-objectstorage.com/seb4u-data/restic"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
restic init
restic backup /opt --tag files
Für die Zweitkopie außer Haus aus der
Backup-Anleitung
besser ein anderer Anbieter (Backblaze B2, Cloudflare R2) – sonst
hängt alles an einem Hetzner-Konto. Bucket-Versioning + eine Lifecycle-Regel schützen
zusätzlich gegen versehentliches forget.
8 MinIO selbst hosten
Wenn du volle Kontrolle willst, lokal einen S3-Endpoint für die Entwicklung brauchst, oder ohnehin Plattenplatz hast (Volume).
services:
minio:
image: quay.io/minio/minio:latest
command: server /data --console-address ":9001"
restart: unless-stopped
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD_FILE: /run/secrets/minio
volumes: [ /mnt/minio-vol:/data ] # ein Hetzner-Volume
secrets: [ minio ]
networks: [ web ] # Traefik: s3.seb4u.com -> :9000, minio.seb4u.com -> :9001
secrets: { minio: { file: ./minio_pw.txt } }
networks: { web: { name: web, external: true } }
mc alias set local https://s3.seb4u.com admin "$(cat minio_pw.txt)"
mc mb local/seb4u-data
mc anonymous set download local/seb4u-data/public
mc admin user add local app "$(openssl rand -base64 18)" # eigener Key fuer die App
MinIO auf einem Server/einer Platte hat keine Ausfallsicherheit über die eine Platte hinaus – genau wie ein Volume. Echtes verteiltes MinIO braucht 4+ Nodes. Für Dev, kleine Projekte oder als Quelle, deren Inhalt du ohnehin sicherst: völlig ok. Die MinIO-Community-Konsole hat 2025 Funktionen verloren – Garage oder SeaweedFS sind leichtgewichtige Alternativen.
9 Betrieb
- Ein Key je Zweck: Backup-Key (nur ein Prefix, nur put/get), App-Key,
dein Admin-Key. Bei Hetzner über Bucket-Policy einschränken. Bei MinIO
mc admin policy. - Grösse & Requests im Blick:
rclone size hos:bucketregelmässig, oder ein Monitoring-Check – Object Storage wächst leise, und Versioning ohne Lifecycle noch leiser. - Egress kostet: viele öffentliche Downloads → Cloudflare davor (cacht, spart Egress), oder R2 (kein Egress-Preis).
- Keys rotieren: neuen Zugangsschlüssel erzeugen, in SOPS tauschen, deployen, alten löschen.
- Bucket-Namen nach Zweck (
seb4u-backup,seb4u-assets) – Policies und Lifecycle sind pro Bucket.
+ Garage, R2, B2
| Anbieter | Modell | Besonderheit |
|---|---|---|
| Hetzner Object Storage | managed, ~6 €/Mo (1 TB inkl.) | im selben Konto/Netz wie die Server, EU (Europäische Union) |
| Cloudflare R2 | ~0,015 $/GB/Mo, kein Egress-Preis | eigene Domain + TLS nativ, Worker-Integration – ideal für Assets/Website |
| Backblaze B2 | ~6 $/TB/Mo, erste 10 GB gratis | günstig, S3-kompatibel – guter Zweit-Backup-Ort |
| Garage (self-hosted) | 0 € + dein Server/Volume | leichtgewichtig, 1–3 Nodes, von Deuxfleurs – einfacher als MinIO verteilt |
+ Kosten
Preise sind Richtwerte. Hetzner hat 2026 zweimal erhöht (zuletzt 15. Juni: CX/CAX +30–40 %, CPX/CCX über 100 %). Aktuelle Server-Preise, alle Nebenposten, ein Rechner und Beispielrechnungen stehen zentral in Kosten & Budget.
| Variante | ~€/Monat | Anmerkung |
|---|---|---|
| Hetzner Object Storage, < 1 TB | ~5,99 | 1 TB Speicher + 1 TB Traffic inkl. |
| Backblaze B2, 200 GB Backup | ~1,2 | pay-as-you-go, Egress bis 3× Speicher gratis |
| Cloudflare R2, 100 GB Assets | ~1,4 | kein Egress-Preis, ~1 Mio Requests inkl. |
| MinIO auf 100 GB Hetzner-Volume | ~4,4 + Server | plus der Server, keine Redundanz |
| Storage Box BX11 (SFTP, kein S3) | ~3,81 | 1 TB, nur als Backup-Ziel |
Faustregel: Backups → Storage Box oder B2, Assets/Website → R2 (kein Egress) oder Cloudflare Pages, „S3-API im eigenen Netz“ → Hetzner Object Storage, Dev/volle Kontrolle → MinIO/Garage.