01 / Das Konzept
Eine Speicherschicht für Dokumente, Backups und Modelle
Unsere Dokumenten-App verarbeitet Scans und Rechnungen auf einem Mac. Fertige Dokumente sollen auf das NAS wandern, statt die Festplatte des Macs zu füllen. Ihre nächtlichen Backups brauchen einen Ort mit eigenen Aufbewahrungsregeln. Ausserdem bewahren wir mit Model Library, unserem quelloffenen Modellarchiv, Kopien der Sprachmodelle auf, die wir lokal betreiben. Das verdient einen eigenen Beitrag.
Alles läuft über MinIO, einen S3-kompatiblen Objektspeicher. Die App kennt nur einen Endpunkt, einen Bucket und einen Schlüssel. Ob der Bucket auf unserem NAS oder bei einem Cloud-Anbieter liegt, spielt für sie keine Rolle, und genau darum geht es. Ist MinIO eines Tages nicht mehr die richtige Wahl, ändern wir einen Endpunkt, nicht die App.
02 / Das Problem
Die Admin-Seiten verschwanden aus der kostenlosen Konsole
Im März 2025 übernahm MinIO eine Änderung, die die Community-Konsole auf einen Objekt-Browser reduzierte. Benutzer, Richtlinien und Zugriffsschlüssel wanderten auf die Kommandozeile mc. Unsere Konsole zeigte Buckets und Dateien. Sonst nichts.
Ein Community-Fork, OpenMaxIO, wollte die vollständige Konsole erhalten. Unterwegs sind wir in zwei Fallen getappt.
Der Hauptzweig des Forks enthält die Änderung von MinIO bereits. Wir haben ihn zuerst gebaut und bekamen denselben reduzierten Objekt-Browser, nur mit anderem Logo. Die letzte Version mit den Admin-Seiten ist der Tag v1.7.6 vom Februar 2025.
Dieser Tag lässt sich so nicht mehr bauen. Sein Frontend lädt die Designbibliothek von MinIO aus github.com/minio/mds, und dieses Repository gibt es nicht mehr. OpenMaxIO hält unter github.com/openmaxio/mds eine Kopie mit genau dem Commit, den v1.7.6 erwartet. Eine Zeile im Build leitet die Abhängigkeit dorthin um.
Eine kleinere Falle kostete uns ebenfalls einen Build. Yarn 4 konnte diese Abhängigkeit im Alpine-basierten Node-Image nicht klonen und brach mit invalid key: core.autocrlf ab. Das Debian-basierte Image funktioniert.
03 / Wie es funktioniert
Eine Konsole, ein Schlüssel pro App, nichts ungeprüft gelöscht
Die vollständige Konsole aus v1.7.6
Wir bauen die Konsole aus dem Quellcode in einem Container. Die beiden Korrekturen sind das Basis-Image und die umgeleitete Abhängigkeit.
FROM node:20-bookworm-slim AS web
RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates
WORKDIR /src
RUN git clone https://github.com/OpenMaxIO/openmaxio-object-browser . && git checkout v1.7.6
WORKDIR /src/web-app
RUN sed -i 's#github.com/minio/mds.git#github.com/openmaxio/mds.git#g' package.json yarn.lock
RUN corepack enable && yarn install && yarn build
FROM golang:1.23-alpine AS go
COPY --from=web /src /src
WORKDIR /src
RUN CGO_ENABLED=0 go build -trimpath --tags=kqueue -o /console ./cmd/console
FROM alpine:3.20
COPY --from=go /console /usr/local/bin/console
ENTRYPOINT ["console", "server", "--port", "9090"]Die Konsole läuft als eigener Container im Docker-Netzwerk von MinIO und spricht intern mit der S3-API. MinIO selbst bleibt unverändert. Wir melden uns mit einem separaten Admin-Benutzer an, nicht mit dem Root-Konto. So laufen die Root-Zugangsdaten nie durch die Konsole.
Ein Bucket, ein Benutzer, ein Schlüssel pro App
Für die Dokumenten-App haben wir eine Richtlinie geschrieben, die das Auflisten eines Buckets sowie das Lesen, Schreiben und Löschen von Objekten darin erlaubt.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:GetBucketLocation"],
"Resource": ["arn:aws:s3:::documents"]
},
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": ["arn:aws:s3:::documents/*"]
}
]
}Ein Benutzer erhält diese Richtlinie, und die App bekommt einen Zugriffsschlüssel dieses Benutzers. Bevor wir den Schlüssel weitergaben, haben wir ihn in beide Richtungen getestet. In seinem Bucket kann er auflisten, schreiben, lesen und löschen. Einen anderen Bucket auflisten, die Admin-API aufrufen oder einen Bucket anlegen, all das endet mit Access Denied.
Testen Sie auch die Verbote. Ein Schlüssel, der alles darf, besteht den positiven Test ebenfalls.
Versionierung statt Aufräumskript
Mit aktivierter Versionierung behält MinIO die vorherige Version, wenn die App eine Datei überschreibt oder löscht. Eine Lifecycle-Regel entfernt diese alten Versionen nach 30 Tagen, damit der Bucket nicht endlos wächst.
Backups landen in einem zweiten Bucket, den der App-Schlüssel nicht erreicht. Dort löscht eine Regel Objekte 30 Tage nach dem Hochladen. Ein Fehler in der App oder ein geleakter App-Schlüssel kann die eigenen Backups nicht löschen.
mc version enable nas/documents
mc ilm rule add nas/documents --noncurrent-expire-days 30
mc ilm rule add nas/documents-backups --expire-days 30Schlüssel in einer Datei, die niemand liest
Beim Einrichten fanden wir die Schlüssel für das Offsite-Backup der App zu Wasabi. Sie lagen seit Juni in .env.local. Docker Compose liest nur .env, und die Compose-Datei hat sie nie an die Container weitergegeben. Der Backup-Job existierte und sah konfiguriert aus, und er hatte nie ein einziges Dokument hochgeladen.
Deshalb liegt der MinIO-Schlüssel im macOS-Schlüsselbund statt in einer Datei. Container können den Schlüsselbund nicht lesen. Der nächste Schritt ist darum ein Startbefehl, der den Schlüssel ausliest und den Containern als Umgebungsvariablen übergibt. Dieser Teil ist noch nicht gebaut.
Zurücklesen, bevor Sie löschen
Wir haben 17 GB Backups der App in den Backup-Bucket verschoben. Bevor wir eine lokale Kopie löschten, haben wir jede Datei erneut heruntergeladen und die SHA-256-Prüfsummen verglichen. Alle 42 Dateien stimmten überein.
Bei einer Abkürzung lauert eine Falle. Bei Dateien, die in Teilen hochgeladen wurden, ist das ETag von MinIO nicht der MD5-Wert der Datei. Wer ETags mit lokalen MD5-Summen vergleicht, hält diese Dateien für verschieden, obwohl sie identisch sind.
Das Risiko, das wir eingehen
v1.7.6 stammt vom Februar 2025, und der Fork hat sich seit Juni 2025 nicht mehr bewegt. Neue Funktionen für die Konsole bekommen wir nicht. Deshalb bleibt sie in unserem privaten Netzwerk und ist nie aus dem Internet erreichbar.
Beim Server sieht es nicht anders aus. MinIO hat sein Open-Source-Repository im April 2026 archiviert. Das letzte Release vom Oktober 2025 behebt eine schwerwiegende Rechteausweitung bei Zugriffsschlüsseln, und weitere Korrekturen wird es nicht geben. Betreiben Sie dieses Release, kein älteres.
Das letzte Server-Release selbst bauen
MinIO veröffentlicht keine Images mehr, deshalb bauen wir dieses Release aus seinem Quell-Tag, genau wie die Konsole. Übernehmen Sie die Umgebungsvorgaben aus MinIOs eigenem Dockerfile.release an diesem Tag, damit sich der Server wie bisher verhält. Sichern Sie vorher .minio.sys im Datenverzeichnis. Dort liegen Benutzer, Richtlinien und Schlüssel.
FROM golang:1.24-alpine AS build
RUN apk add --no-cache git
WORKDIR /src
RUN git clone --depth 1 --branch RELEASE.2025-10-15T17-29-55Z https://github.com/minio/minio .
RUN CGO_ENABLED=0 go build -tags kqueue -trimpath -ldflags "$(go run buildscripts/gen-ldflags.go)" -o /minio
FROM alpine:3.20
RUN apk add --no-cache ca-certificates
COPY --from=build /minio /usr/bin/minio
COPY --from=build /src/dockerscripts/docker-entrypoint.sh /usr/bin/docker-entrypoint.sh
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
CMD ["minio"]Unterwegs gab es noch eine Falle. Wir hatten auf dem Server eine eigene Region gesetzt, und die Konsole konnte sich nicht mehr anmelden. Der Server antwortete mit the region is wrong; expecting 'us-east-1', obwohl er unsere eigene Region erwartete. Ist eine Region gesetzt, akzeptiert MinIO nur Anfragen, die für diese Region signiert sind. Lassen Sie das Feld leer, solange Sie es nicht brauchen, oder setzen Sie CONSOLE_MINIO_REGION in der Konsole auf denselben Wert.
Wir nehmen das vorerst in Kauf, weil unsere Apps nur die S3-API nutzen. Müssen wir wechseln, sprechen Garage und SeaweedFS dieselbe API, und die Apps behalten ihren Code.
04 / Installation
Die Konsole neben Ihrem MinIO betreiben
Sie brauchen MinIO in Docker, den Client mc und für den ersten Build 10 bis 15 Minuten.
- Legen Sie für die Konsole einen Admin-Benutzer mit einer Richtlinie an, die
admin:*unds3:*erlaubt. - Bauen Sie das Image aus dem Dockerfile oben und starten Sie es im Docker-Netzwerk von MinIO, mit gesetzten Werten für
CONSOLE_MINIO_SERVER,CONSOLE_PBKDF_PASSPHRASEundCONSOLE_PBKDF_SALT. - Legen Sie für jede App eine Richtlinie für ihren Bucket an, einen Benutzer mit dieser Richtlinie und einen Zugriffsschlüssel. Testen Sie, was der Schlüssel darf und was nicht.
- Aktivieren Sie die Versionierung und fügen Sie Lifecycle-Regeln hinzu.
services:
console:
build: .
environment:
CONSOLE_MINIO_SERVER: http://minio:9000
CONSOLE_PBKDF_PASSPHRASE: ${CONSOLE_PBKDF_PASSPHRASE}
CONSOLE_PBKDF_SALT: ${CONSOLE_PBKDF_SALT}
ports: ["9102:9090"]
networks: [minio]
networks:
minio: { external: true, name: minio_default }mc admin policy create nas consoleAdmin console-admin.json
mc admin user add nas console-admin "$CONSOLE_ADMIN_PASSWORD"
mc admin policy attach nas consoleAdmin --user console-adminDiesen Leitfaden delegieren
Geben Sie dies Ihrem Agenten
Kopieren Sie diese Eingabeaufforderung in Ihren Codierungsagenten. Es sollte die Voraussetzungen prüfen, diese Anleitung durchführen und berichten, was es überprüft hat.
Help me run the OpenMaxIO admin console next to my existing MinIO and give one app its own bucket and key, as described in this article.
First check that MinIO already runs in Docker, find its Docker network and confirm that the mc client reaches it with an admin account. If there is no MinIO yet, stop and tell me. This guide does not cover a fresh install, because MinIO's open-source project is archived. If the server is older than RELEASE.2025-10-15T17-29-55Z, tell me before going further. Do not change the MinIO server or its data.
Build OpenMaxIO from the tag v1.7.6 with the two fixes from the article: a Debian-based Node image, and the mds dependency redirected to github.com/openmaxio/mds. Do not build the main branch, it lacks the admin pages. Generate CONSOLE_PBKDF_PASSPHRASE and CONSOLE_PBKDF_SALT, keep them in a local .env that stays out of git, and start the console on MinIO's Docker network. Create a separate console admin user instead of using the root account.
Then ask me which app and bucket to set up. Create a policy limited to that bucket, a user with that policy and an access key for the user. Test the key both ways. It must list, write, read and delete a test object in its bucket, and it must be denied on another bucket, on the admin API and when creating a bucket. Remove the test object afterwards.
Ask before enabling versioning, adding lifecycle rules or deleting anything. Never print secrets in full, and store them where I tell you. Report the console URL, what passed, what failed and how to stop the console.05 / Was bleibt
Warum Sie das interessieren könnte
Wenn Sie MinIO bereits betreiben
Die Admin-Seiten sind nicht für immer verloren. OpenMaxIO v1.7.6 bringt Benutzer, Richtlinien und Zugriffsschlüssel zurück, sobald Sie die beiden Korrekturen von oben anwenden. Bringen Sie ausserdem Ihren Server auf das letzte MinIO-Release vom Oktober 2025. Etwas Neueres wird es nicht geben.
Wenn Sie Systeme bauen, die viele Daten erzeugen
Sie kennen das. Erzeugte Dateien stapeln sich auf dem Laptop, bis die Festplatte voll ist, und jedes Projekt erfindet seinen eigenen Weg, sie irgendwohin zu kopieren. Ein S3-Speicher auf Ihrem NAS gibt jedem Projekt dieselbe Schnittstelle. Der Code spricht mit einem Bucket und einem Schlüssel, und Versionierung und Ablauf werden zu Einstellungen statt zu Skripten.
Für eine neue Installation würden wir heute zuerst Garage oder SeaweedFS ansehen, weil das Open-Source-Projekt von MinIO archiviert ist. Der Code, den Sie gegen die S3-API schreiben, bleibt in jedem Fall derselbe.
