diff --git a/content/de/index.mdx b/content/de/index.mdx
index 68452df85..767dcce96 100644
--- a/content/de/index.mdx
+++ b/content/de/index.mdx
@@ -81,6 +81,15 @@ description: "Installieren Sie RustFS unter Linux, in Containern, auf Kubernetes
+
+
+
+
+ Mit dem SwarmCLI-Chart installieren
+ Stellen Sie RustFS mit dem rustfs-Chart von SwarmCLI auf einem einzelnen Knoten oder verteilt in Docker Swarm bereit.
+
+
+
Cloud-Anbieter
diff --git a/content/de/installation/cloud-native/meta.json b/content/de/installation/cloud-native/meta.json
index 063810fde..054eb7acc 100644
--- a/content/de/installation/cloud-native/meta.json
+++ b/content/de/installation/cloud-native/meta.json
@@ -2,6 +2,7 @@
"title": "Cloud-nativ",
"pages": [
"helm-chart",
- "operator"
+ "operator",
+ "swarmcli-chart"
]
}
diff --git a/content/de/installation/cloud-native/swarmcli-chart.md b/content/de/installation/cloud-native/swarmcli-chart.md
new file mode 100644
index 000000000..1a8bff2da
--- /dev/null
+++ b/content/de/installation/cloud-native/swarmcli-chart.md
@@ -0,0 +1,294 @@
+---
+title: "SwarmCLI-Chart"
+description: "Stellen Sie RustFS mit dem rustfs-Chart von SwarmCLI in Docker Swarm bereit, als Dienst auf einem Knoten oder als verteilten Cluster mit Erasure Coding: Zugangsdaten in Docker-Secrets, versionierte Upgrades und Rollbacks sowie optional HTTPS über Traefik."
+---
+
+[SwarmCLI](https://github.com/Eldara-Tech/swarmcli) ist ein von Helm inspirierter Paketmanager und eine Terminal-Oberfläche für Docker Swarm. Sein quelloffenes [`rustfs`-Chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) stellt RustFS in Docker Swarm bereit. Beide werden von Eldara Tech gepflegt, nicht vom RustFS-Projekt.
+
+Gegenüber einer von Hand geschriebenen Stack-Datei bietet das Chart zusätzlich:
+
+- **Zugangsdaten in Docker-Secrets.** RustFS liest seine Root-Schlüssel über `RUSTFS_ACCESS_KEY_FILE` und `RUSTFS_SECRET_KEY_FILE` aus Dateien, sodass keiner der beiden Werte in der Dienstdefinition oder in `docker inspect` erscheint. Der Standardschlüssel `rustfsadmin` wird abgelehnt.
+- **Versionierte Releases.** Prüfen Sie ein Upgrade vorab, wenden Sie es an und kehren Sie zu einer früheren Revision zurück. SwarmCLI speichert den Revisionsverlauf im Swarm selbst, sodass keine zusätzliche Datenbank nötig ist.
+- **HTTPS über Traefik.** Mit dem zugehörigen [`traefik`-Chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik) erhalten die S3-API und die Console eigene Hostnamen und Zertifikate von Let's Encrypt, und die Console kann Single Sign-on über OpenID Connect nutzen.
+- **Rollouts mit Integritätsprüfung.** In den Werten aufgeführte Buckets werden beim Start angelegt, und jeder Rollout eines Standalone-Releases wird über den Endpunkt `/health/ready` von RustFS überwacht, sodass `--wait` bei einem fehlerhaften Upgrade einen Fehler statt eines Erfolgs meldet.
+- **Rolling Upgrades im Cluster.** Im verteilten Modus aktualisiert ein Upgrade die Peers einzeln nacheinander; laufen alle vier Peers der Standardkonfiguration, bedient der Cluster währenddessen durchgehend Lese- und Schreibzugriffe, mit einem Peer weniger.
+
+Das Chart läuft in einem von zwei Modi, den Sie bei der Installation wählen. Der standardmäßige Standalone-Modus führt einen RustFS-Dienst mit einem Laufwerk auf einem Knoten aus (Single Node Single Disk, SNSD). Ein einzelnes Laufwerk bietet keine Redundanz durch Erasure Coding. Der Standalone-Modus eignet sich daher für Build-Caches, Backup-Ziele und Blob-Speicher von Anwendungen in einem kleinen Swarm. Der verteilte Modus speichert Objekte per Erasure Coding auf vier oder mehr Peers, einem pro Knoten, für Daten, die den Ausfall eines Knotens überstehen müssen. Schritt 4 installiert den Standalone-Modus und Schritt 5 den verteilten Modus; die übrigen Schritte gelten für beide.
+
+## 1. Voraussetzungen
+
+* Ein Docker Swarm (`docker swarm init`) und eine Shell auf einem Manager-Knoten
+* SwarmCLI 2.2.0 oder neuer – siehe die [Installationsanleitung von SwarmCLI](https://github.com/Eldara-Tech/swarmcli/blob/main/docs/installation.md)
+* Für den Standalone-Modus ein freier Port 9000 (S3-API) auf den Swarm-Knoten, da Schritt 4 ihn im Routing-Mesh des Swarms veröffentlicht
+* Für den verteilten Modus ein Knoten pro Peer, mindestens vier (für die Entwicklung genügt ein einzelner Knoten; siehe Schritt 5)
+
+## 2. Zugangsdaten als Docker-Secrets anlegen
+
+Ersetzen Sie die Platzhalter für die Zugangsdaten und legen Sie dann für jeden Schlüssel ein Secret an:
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key -
+printf '%s' '' | docker secret create rustfs-secret-key -
+```
+
+Jeder Wert muss in einer Zeile stehen und darf keine Leerzeichen enthalten. Einen starken geheimen Zugriffsschlüssel erzeugen Sie zum Beispiel mit `openssl rand -base64 30`. Im verteilten Modus liest jeder Peer dieselben beiden Secrets.
+
+:::warning[Der Dienst lehnt schwache Zugangsdaten ab]
+
+SwarmCLI verweigert die Installation des Charts, solange eines der Secrets fehlt, und der Container beendet sich beim Start, wenn ein Schlüssel leer ist, Leerzeichen enthält oder den allgemein bekannten Wert `rustfsadmin` hat. Docker-Secrets lassen sich nicht bearbeiten: Um die Zugangsdaten zu rotieren, legen Sie Secrets unter neuen Namen an und aktualisieren anschließend das Release, wobei `s3.accessKeySecret` und `s3.secretKeySecret` auf die neuen Secrets verweisen. Im verteilten Modus erfordert die Rotation einen vollständigen Stopp, wie unter Upgrade und Rollback beschrieben.
+
+:::
+
+## 3. Chart-Repository hinzufügen
+
+Überspringen Sie diesen Schritt, wenn `swarmcli charts repo list` bereits `swarmcli-charts` anzeigt:
+
+```bash
+swarmcli charts repo add swarmcli-charts https://eldara-tech.github.io/swarmcli-charts
+```
+
+## 4. Standalone-Modus installieren
+
+Führen Sie entweder diesen Schritt oder Schritt 5 aus, nicht beide. Ein benanntes Volume existiert nur auf einem Knoten. Deshalb wird der Dienst an den Knoten mit dem Label `rustfs-data=true` gebunden. Versehen Sie genau einen Knoten mit diesem Label:
+
+```bash
+docker node update --label-add rustfs-data=true
+```
+
+In einem Swarm mit nur einem Knoten können Sie das Label weglassen und stattdessen `--set persistence.nodeLabel=""` an den folgenden Installationsbefehl anhängen.
+
+Installieren Sie das Chart als Release mit dem Namen `rustfs`, veröffentlichen Sie die S3-API auf Port 9000 und legen Sie beim Start einen Bucket an:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+Der Dienst speichert seine Daten unter `/data` auf dem benannten Volume `rustfs-data`, das Docker nach dem Release als `rustfs_rustfs-data` benennt. Jeder Bucket in `buckets` wird angelegt, sobald der Server antwortet; ein bereits vorhandener Bucket bleibt unverändert, sodass Neustarts und Upgrades unbedenklich sind.
+
+## 5. Verteilten Modus installieren
+
+Führen Sie diesen Schritt anstelle von Schritt 4 aus. Im verteilten Modus ist jeder Peer ein eigener Swarm-Dienst (`rustfs_rustfs-1` bis `rustfs_rustfs-4` bei einem Release mit dem Namen `rustfs`) mit einem Replikat, einem eigenen Volume und einem eigenen Knoten-Label. Versehen Sie für jeden Peer einen Knoten mit einem Label:
+
+```bash
+docker node update --label-add rustfs-1=true
+docker node update --label-add rustfs-2=true
+docker node update --label-add rustfs-3=true
+docker node update --label-add rustfs-4=true
+```
+
+Platzieren Sie jeden Peer auf einem anderen Knoten: Peers auf demselben Knoten fallen gemeinsam mit diesem aus, und bei den vier Peers der Standardkonfiguration stoppt der Ausfall eines einzigen Knotens, auf dem zwei Peers laufen, die Schreibzugriffe. In einem Swarm mit nur einem Knoten versehen Sie diesen Knoten mit allen vier Labels; das eignet sich nur für die Entwicklung, da diese Konfiguration keine Verfügbarkeit bietet.
+
+Legen Sie den Modus und den Aufbau des Clusters ausdrücklich fest. Die Gesamtzahl der Laufwerke beträgt `cluster.peers * cluster.drivesPerPeer`.
+
+:::warning[Wählen Sie die Topologie vor der Installation]
+
+`cluster.peers` und `cluster.drivesPerPeer` liegen ab der Installation fest: RustFS speichert die Anzahl der Laufwerke und die Breite des Erasure Sets auf jedem Laufwerk und verweigert den Start mit anderen Werten. Auch `mode` wird bei der Installation gewählt. Eine Änderung des Modus an einem bestehenden Release konvertiert die Daten nicht: Die Dienste des neuen Modus starten auf leeren Laufwerken, die Dienste des alten Modus laufen daneben weiter, und Clients erreichen beide. Um einen Standalone-Speicher in einen Cluster zu überführen, installieren Sie den Cluster als zweites Release und kopieren die Buckets über S3 hinüber.
+
+:::
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+buckets:
+ - my-bucket
+```
+
+Das Beispiel legt vier Peers mit je einem Laufwerk an. Jedes Objekt wird in zwei Daten- und zwei Paritäts-Shards aufgeteilt, sodass Lesezugriffe den Ausfall von zwei Peers überstehen und Schreibzugriffe den Ausfall eines Peers; die nutzbare Kapazität beträgt die Hälfte der Gesamtkapazität der Laufwerke. Mehr als ein Laufwerk pro Peer erfordert `persistence.volumePaths` mit einem Hostverzeichnis pro Laufwerk, jeweils auf einem eigenen Datenträger; die README des Charts beschreibt dies. Installieren Sie das Chart mit der Wertedatei:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+Alle Peers starten gemeinsam. `--wait` kehrt zurück, sobald der Task jedes Peers läuft und seinen Überwachungszeitraum von zwei Minuten überstanden hat. Peer 1 legt die Buckets an, sobald der Cluster Schreibzugriffe annimmt; gelingt ihm das nicht innerhalb von fünf Minuten nach dem Start, protokolliert er den Bucket, den er nicht anlegen konnte (`docker service logs rustfs_rustfs-1` zeigt ihn an), und bedient weiterhin Anfragen. Die Integritätsprüfung eines Peers zeigt nur, dass der Peer lebt; `--wait` zeigt daher nicht, ob der Cluster Anfragen bedient. Das prüft Schritt 6.
+
+## 6. Bereitstellung prüfen
+
+Prüfen Sie im Standalone-Modus das Release, den Task des Dienstes und den Bereitschaftsendpunkt der S3-API:
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs
+curl --fail http://localhost:9000/health/ready
+```
+
+Die S3-API ist auf jedem Swarm-Knoten unter `http://localhost:9000` erreichbar. Clients verwenden pfadbasierte Adressierung (Path-Style) und die Region `us-east-1`. Bleibt der Task mit `no suitable node` im Status Pending, trägt kein Knoten das Label `rustfs-data=true` aus Schritt 4.
+
+Prüfen Sie im verteilten Modus das Release und die Tasks der Peers und fragen Sie dann aus einem Container im Overlay-Netzwerk `rustfs-net` ab, ob der Cluster Anfragen bedient:
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs-1 rustfs_rustfs-2 rustfs_rustfs-3 rustfs_rustfs-4
+docker run --rm --network rustfs-net curlimages/curl -s -o /dev/null -w '%{http_code}\n' \
+ http://rustfs-rustfs:9000/minio/health/cluster
+```
+
+`200` bedeutet, dass jedes Erasure Set das Schreibquorum erreicht. Bleibt der Task eines Peers mit `no suitable node` im Status Pending, trägt kein Knoten das Label `rustfs-=true` dieses Peers aus Schritt 5. Sobald das Label gesetzt ist, startet der Peer; meldet das Log von Peer 1 danach einen Bucket, den er nicht anlegen konnte, starten Sie Peer 1 neu, damit er die Buckets erneut anlegt: `docker service update --force rustfs_rustfs-1`.
+
+Dienste, die `rustfs-net` beitreten, erreichen den Cluster unter `http://rustfs-rustfs:9000` mit pfadbasierter Adressierung und der Region `us-east-1`. Jeder Peer bedient jedes Objekt, und der Name wird in die Adressen aller Peers aufgelöst, deren Integritätsprüfung erfolgreich ist. Diese Prüfung zeigt nur, dass ein Peer lebt; bei einer Erstinstallation oder nachdem alle Peers gestoppt wurden, kann ein Peer daher mit 503 antworten, bis der Cluster Anfragen bedient. Auch eine laufende Anfrage an einen Peer, der stoppt, schlägt fehl. Clients müssen fehlgeschlagene Anfragen wiederholen, wie es S3-Clients standardmäßig tun. Um den Cluster von außerhalb des Swarms zu erreichen, machen Sie ihn erreichbar, wie unter Erreichbarkeitsmodi beschrieben.
+
+## Upgrade und Rollback
+
+Jede Installation, jedes Upgrade und jeder Rollback erzeugt eine nummerierte Revision des Releases. Ein Upgrade geht von den Standardwerten des Charts aus; übergeben Sie daher alle Werte erneut, einschließlich `--set persistence.nodeLabel=""`, falls Sie es in Schritt 4 verwendet haben, oder speichern Sie die Werte in einer Datei und übergeben Sie diese mit `-f`. Prüfen Sie für das Standalone-Release aus Schritt 4 eine Änderung vorab, wenden Sie sie an und listen Sie die Revisionen auf:
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs --wait \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts history rustfs
+```
+
+So kehren Sie zu einer früheren Revision zurück:
+
+```bash
+swarmcli charts rollback rustfs 1
+```
+
+Ein Rollback stellt die Dienstdefinition dieser Revision erneut bereit; Daten stellt er nicht wieder her.
+
+Übergeben Sie im verteilten Modus jedem Upgrade die Wertedatei, mit der Sie installiert haben, statt `--reuse-values` zu verwenden, und tragen Sie spätere Änderungen, etwa Erreichbarkeitseinstellungen, in diese Datei ein. Ein Upgrade, dessen Werte `mode: distributed` nicht enthalten, lässt die Peers unverändert und startet daneben einen Standalone-Dienst.
+
+SwarmCLI aktualisiert die Peers einzeln nacheinander: Es stoppt einen Peer, startet dessen neuen Task und wechselt erst dann zum nächsten Peer, wenn dieser Task läuft und seinen Überwachungszeitraum überstanden hat. Laufen alle vier Peers der Standardkonfiguration, bedient der Cluster währenddessen durchgehend Lese- und Schreibzugriffe, mit einem Peer weniger; ist bereits ein Peer ausgefallen, nimmt der Cluster immer dann keine Schreibzugriffe an, wenn das Upgrade einen weiteren Peer stoppt. Prüfen Sie daher zuerst mit den Befehlen aus Schritt 6, dass der Task jedes Peers läuft und der Cluster mit `200` antwortet; ein `200` allein zeigt nicht, dass jeder Peer läuft. Prüfen Sie dann das Upgrade vorab, wenden Sie es an und prüfen Sie den Cluster anschließend erneut:
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+Ein Rollback geht bei den Peers auf dieselbe Weise vor. Startet bei einem Upgrade ein Peer nicht, hält das Upgrade an dieser Stelle an, und die übrigen Peers bleiben unangetastet.
+
+:::warning[Die Rotation der Zugangsdaten eines Clusters erfordert einen vollständigen Stopp]
+
+Jeder Peer leitet sein Internode-Secret aus dem Schlüsselpaar ab. Peers mit dem alten Paar und Peers mit dem neuen Paar können einander daher nicht erreichen, und ein Upgrade, das die Peers einzeln nacheinander aktualisiert, würde den Cluster spalten. Legen Sie die neuen Secrets an:
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key-2 -
+printf '%s' '' | docker secret create rustfs-secret-key-2 -
+```
+
+Tragen Sie die beiden Secret-Namen in `distributed-values.yaml` ein, damit spätere Upgrades sie beibehalten. Mit den Werten aus Schritt 5 lautet die Datei dann:
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+s3:
+ accessKeySecret: rustfs-access-key-2
+ secretKeySecret: rustfs-secret-key-2
+
+buckets:
+ - my-bucket
+```
+
+Stoppen Sie dann alle Peers und führen Sie das Upgrade aus, damit alle Peers gemeinsam mit dem neuen Paar starten:
+
+```bash
+for n in 1 2 3 4; do docker service scale "rustfs_rustfs-$n=0"; done
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+Die Daten und die Buckets bleiben erhalten; Clients benötigen das neue Paar. Kehren Sie nicht per Rollback zu einer Revision aus der Zeit vor der Rotation zurück: Der Rollback würde die Peers einzeln nacheinander wieder auf das alte Paar umstellen und den Cluster auf dieselbe Weise spalten.
+
+:::
+
+## Erreichbarkeitsmodi
+
+Das Chart macht die S3-API und die Console unabhängig voneinander erreichbar. Die Console ist standardmäßig deaktiviert; aktivieren Sie sie mit `console.enabled=true`. Den Modus der S3-API legt `exposure.mode` fest, den der Console `console.exposure.mode`:
+
+| Modus | Erreichbar von |
+| - | - |
+| `none` (Standard) | Diensten im Overlay-Netzwerk `rustfs-net`, unter `http://-rustfs:9000` (die Console, sofern aktiviert, auf Port 9001); solange der andere Listener `traefik` verwendet, auch Diensten in `traefik-public` |
+| `published` | Einem veröffentlichten Port: `publish.port` für die S3-API, `console.publish.port` (9001) für die Console, im Routing-Mesh des Swarms (im verteilten Modus auf dem eigenen Knoten jedes Peers) |
+| `traefik` | Einem von Traefik über HTTPS gerouteten Hostnamen: `ingress.host` für die S3-API, `console.ingress.host` für die Console |
+
+Der Modus `traefik` setzt ein zuvor installiertes [`traefik`-Chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik) voraus: Es legt das Netzwerk `traefik-public` an, dem RustFS beitritt, und bezieht die Zertifikate von Let's Encrypt. Stellen Sie anschließend die S3-API eines Standalone-Releases unter ihrem Hostnamen bereit:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=traefik \
+ --set ingress.host=s3.example.com \
+ --set 'buckets={my-bucket}'
+```
+
+Ohne Traefik veröffentlichen Sie die Console eines Standalone-Releases so neben der S3-API auf Port 9001:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set console.enabled=true \
+ --set console.exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+:::note[Der Console-Port bedient auch die S3-API]
+
+Der Console-Listener bedient zusätzlich die vollständige signierte S3- und Admin-API. Wenn Sie nur die Console erreichbar machen, ist diese API daher trotzdem unter einer öffentlichen Adresse erreichbar. Lassen Sie die Console deaktiviert, wenn Sie sie nicht verwenden.
+
+:::
+
+Im verteilten Modus erhalten alle Peers dieselben Erreichbarkeitseinstellungen; legen Sie sie in `distributed-values.yaml` fest und führen Sie dann ein Upgrade aus, wie unter Upgrade und Rollback beschrieben. Mit `traefik` verteilt Traefik die Anfragen auf alle fehlerfreien Peers. Der Modus `published` erfordert `publish.mode=host` (und `console.publish.mode=host` für die Console); damit wird der Port statt im Routing-Mesh auf dem eigenen Knoten jedes Peers veröffentlicht, sodass der Port eines Knotens nur den Peer auf diesem Knoten erreicht. Schalten Sie den Knoten einen Load Balancer vor oder verwenden Sie Traefik. Die Veröffentlichung im Host-Modus erfordert, dass jeder Peer auf einem eigenen Knoten läuft; in einem Swarm mit nur einem Knoten ist sie daher nicht möglich.
+
+## Wichtige Werte
+
+| Wert | Zweck | Standardwert des Charts |
+| - | - | - |
+| `image.tag` | Tag des RustFS-Images | `""` (die vom Chart festgelegte RustFS-Version) |
+| `mode` | `standalone` oder `distributed`, bei der Installation gewählt | `standalone` |
+| `cluster.peers` | Peers im verteilten Modus, jeweils mit einem Dienst und einem Knoten-Label; mindestens 4 | `4` |
+| `cluster.drivesPerPeer` | Laufwerke pro Peer im verteilten Modus; mehr als eines erfordert `persistence.volumePaths` | `1` |
+| `s3.accessKeySecret` / `s3.secretKeySecret` | Docker-Secrets mit den Root-Anmeldedaten | `rustfs-access-key` / `rustfs-secret-key` |
+| `buckets` | Buckets, die beim Start angelegt werden, falls sie fehlen | `[]` |
+| `exposure.mode` | Erreichbarkeit der S3-API: `none`, `published` oder `traefik` | `none` |
+| `publish.port` | Veröffentlichter Port der S3-API | `9000` |
+| `ingress.host` | Hostname, den Traefik zur S3-API routet | `s3.example.com` |
+| `console.enabled` | Console-Listener ausführen | `false` |
+| `console.exposure.mode` | Erreichbarkeit der Console: `none`, `published` oder `traefik` | `none` |
+| `persistence.nodeLabel` | Knoten-Label, an das der Standalone-Dienst gebunden wird; `""` für keine Bindung | `rustfs-data` |
+| `persistence.nodeLabelPrefix` | Präfix der Knoten-Labels, das Peer `` im verteilten Modus an das Label `-` bindet; `""` für keine Bindung, nur in einem Swarm mit nur einem Knoten | `rustfs` |
+| `persistence.volumePath` | Hostverzeichnis, das im Standalone-Modus statt des benannten Volumes unter `/data` eingebunden wird; muss `10001` gehören | `""` |
+| `extraEnv` | Zusätzliche `RUSTFS_*`-Umgebungsvariablen, etwa `RUSTFS_SERVER_DOMAINS` | `{}` |
+
+Die [README des Charts](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) beschreibt alle Werte, darunter das Routing über Traefik, Single Sign-on für die Console über OpenID Connect und das Einbinden von Hostverzeichnissen in beiden Modi.
+
+## Deinstallation
+
+```bash
+swarmcli charts uninstall rustfs
+```
+
+Die Deinstallation entfernt den Dienst, im verteilten Modus den Dienst jedes Peers, sowie den Release-Verlauf. Erhalten bleiben das Daten-Volume (im verteilten Modus eines pro Peer), die beiden Docker-Secrets und das Netzwerk `rustfs-net`, das SwarmCLI zusammen mit dem Befehl zum Entfernen auflistet.
+
+:::note[Die Daten-Volumes bleiben nach der Deinstallation erhalten]
+
+Im Standalone-Modus bindet eine spätere Installation mit demselben Release-Namen das Volume samt Daten wieder ein. Um die Daten zu verwerfen, entfernen Sie das Volume auf dem gekennzeichneten Knoten, sobald der Task beendet ist (nach bis zu 30 Sekunden):
+
+```bash
+docker volume rm rustfs_rustfs-data
+```
+
+Im verteilten Modus behält jeder Peer sein eigenes Volume `rustfs_rustfs-data-` auf dem Knoten mit dem Label `rustfs-=true`; entfernen Sie es dort, sobald der Task dieses Peers beendet ist. Eine spätere Installation mit demselben Release-Namen verwendet diese Volumes wieder und muss daher dieselben Werte für `cluster.peers` und `cluster.drivesPerPeer` beibehalten.
+
+Entfernen Sie in beiden Modi die Secrets, falls Sie sie nicht mehr benötigen: das vom Release verwendete Paar und jedes durch eine Rotation ersetzte Paar. Mit den Namen aus Schritt 2:
+
+```bash
+docker secret rm rustfs-access-key rustfs-secret-key
+```
+
+:::
+
+## Nächste Schritte
+
+- [RustFS Console](/administration/console)
+- [S3-Client konfigurieren](../../developer/examples/aws-cli.md)
+- [Checklisten vor der Installation](../requirement/checklists/index.md)
diff --git a/content/de/installation/index.md b/content/de/installation/index.md
index a435f26f2..f085a9d37 100644
--- a/content/de/installation/index.md
+++ b/content/de/installation/index.md
@@ -17,6 +17,7 @@ Legen Sie nach der Installation eindeutige Werte für `RUSTFS_ACCESS_KEY` und `R
- Bei einer Installation als Linux-Binärdatei oder mit systemd tragen Sie beide Werte in `/etc/default/rustfs` ein und starten Sie anschließend den Dienst `rustfs` neu.
- Bei Docker, Podman oder Docker Compose übergeben Sie beide Werte beim Erstellen des Containers als Umgebungsvariablen. Erstellen Sie einen bestehenden Container neu, wenn er ohne diese Werte gestartet wurde.
+- Bei Docker Swarm legen Sie beide Werte als Docker-Secrets an, bevor Sie das Chart installieren.
:::
diff --git a/content/en/index.mdx b/content/en/index.mdx
index 9b9c775a1..e144f3890 100644
--- a/content/en/index.mdx
+++ b/content/en/index.mdx
@@ -81,6 +81,15 @@ description: "Install RustFS on Linux, containers, Kubernetes, macOS, or Windows
+
+
+
+
+ Install with the SwarmCLI chart
+ Deploy single-node or distributed RustFS on Docker Swarm with the SwarmCLI rustfs chart.
+
+
+
Cloud Provider
diff --git a/content/en/installation/cloud-native/meta.json b/content/en/installation/cloud-native/meta.json
index 520b603a5..e9cb9ce71 100644
--- a/content/en/installation/cloud-native/meta.json
+++ b/content/en/installation/cloud-native/meta.json
@@ -2,6 +2,7 @@
"title": "Cloud Native",
"pages": [
"helm-chart",
- "operator"
+ "operator",
+ "swarmcli-chart"
]
}
diff --git a/content/en/installation/cloud-native/swarmcli-chart.md b/content/en/installation/cloud-native/swarmcli-chart.md
new file mode 100644
index 000000000..e0dae9907
--- /dev/null
+++ b/content/en/installation/cloud-native/swarmcli-chart.md
@@ -0,0 +1,294 @@
+---
+title: "SwarmCLI Chart"
+description: "Deploy RustFS on Docker Swarm with the SwarmCLI rustfs chart, as a single-node service or a distributed, erasure-coded cluster: credentials in Docker secrets, versioned upgrades and rollbacks, and optional HTTPS through Traefik."
+---
+
+[SwarmCLI](https://github.com/Eldara-Tech/swarmcli) is a Helm-inspired package manager and terminal UI for Docker Swarm. Its open-source [`rustfs` chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) deploys RustFS on Docker Swarm. Both are maintained by Eldara Tech, not by the RustFS project.
+
+Compared with a hand-written stack file, the chart adds:
+
+- **Credentials in Docker secrets.** RustFS reads its root keys from files through `RUSTFS_ACCESS_KEY_FILE` and `RUSTFS_SECRET_KEY_FILE`, so neither value appears in the service definition or in `docker inspect`. The default `rustfsadmin` key is refused.
+- **Versioned releases.** Preview an upgrade, apply it, and roll back to an earlier revision. SwarmCLI stores the revision history in the swarm itself, so no extra database is needed.
+- **HTTPS through Traefik.** With the companion [`traefik` chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik), the S3 API and the Console get their own host names and Let's Encrypt certificates, and the Console can use single sign-on through OpenID Connect.
+- **Health-checked rollouts.** Buckets listed in the values are created at start, and every rollout of a standalone release is watched through RustFS's `/health/ready` endpoint, so `--wait` reports a broken upgrade instead of success.
+- **Rolling cluster upgrades.** In distributed mode, an upgrade rolls one peer at a time; with the default four peers all running, the cluster keeps serving reads and writes throughout, one peer short.
+
+The chart runs in one of two modes, chosen at install. Standalone mode, the default, runs one RustFS service with one drive on one node (single-node single-disk, SNSD). A single drive has no erasure-coding redundancy, so it suits build caches, backup targets, and application blob stores on a small swarm. Distributed mode erasure-codes objects across four or more peers, one per node, for data that must survive losing a node. Step 4 installs standalone mode and step 5 installs distributed mode; the other steps apply to both.
+
+## 1. Prerequisites
+
+* A Docker Swarm (`docker swarm init`) and a shell on a manager node
+* SwarmCLI 2.2.0 or later — see the [SwarmCLI installation guide](https://github.com/Eldara-Tech/swarmcli/blob/main/docs/installation.md)
+* For standalone mode, port 9000 (S3 API) free on the swarm nodes, because step 4 publishes it on the Swarm routing mesh
+* For distributed mode, one node for each peer, at least four (a single node is enough for development; see step 5)
+
+## 2. Create the credentials as Docker secrets
+
+Replace the credential placeholders, then create one secret for each key:
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key -
+printf '%s' '' | docker secret create rustfs-secret-key -
+```
+
+Keep each value on one line with no whitespace inside it. Generate a strong secret key with, for example, `openssl rand -base64 30`. In distributed mode, every peer reads the same two secrets.
+
+:::warning[The service refuses weak credentials]
+
+SwarmCLI refuses to install the chart while either secret is missing, and the container exits at start if a key is empty, contains whitespace, or is the well-known `rustfsadmin` value. Docker secrets cannot be edited: to rotate the credentials, create secrets under new names, then upgrade the release with `s3.accessKeySecret` and `s3.secretKeySecret` pointing at them. In distributed mode, rotation takes a full stop, as described under Upgrade and roll back.
+
+:::
+
+## 3. Add the chart repository
+
+Skip this step if `swarmcli charts repo list` already shows `swarmcli-charts`:
+
+```bash
+swarmcli charts repo add swarmcli-charts https://eldara-tech.github.io/swarmcli-charts
+```
+
+## 4. Install standalone mode
+
+Follow this step or step 5, not both. A named volume exists on one node only, so the service is pinned to the node labelled `rustfs-data=true`. Label exactly one node:
+
+```bash
+docker node update --label-add rustfs-data=true
+```
+
+On a single-node swarm you can skip the label and add `--set persistence.nodeLabel=""` to the install command below instead.
+
+Install the chart as a release named `rustfs`, publish the S3 API on port 9000, and create a bucket at start:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+The service stores its data under `/data` on the `rustfs-data` named volume, which Docker names `rustfs_rustfs-data` after the release. Each bucket in `buckets` is created once the server answers; a bucket that already exists is left alone, so restarts and upgrades are safe.
+
+## 5. Install distributed mode
+
+Follow this step instead of step 4. In distributed mode, each peer is a Swarm service of its own (`rustfs_rustfs-1` to `rustfs_rustfs-4` for a release named `rustfs`), with one replica, its own volume, and its own node label. Label one node for each peer:
+
+```bash
+docker node update --label-add rustfs-1=true
+docker node update --label-add rustfs-2=true
+docker node update --label-add rustfs-3=true
+docker node update --label-add rustfs-4=true
+```
+
+Put each peer on a different node: peers that share a node share its fate, and with the default four peers, losing one node that holds two peers stops writes. On a single-node swarm, label that one node with all four labels; this suits development only, because it gives no availability.
+
+Set the mode and the cluster shape explicitly. Total drives equal `cluster.peers * cluster.drivesPerPeer`.
+
+:::warning[Choose the topology before installation]
+
+`cluster.peers` and `cluster.drivesPerPeer` are fixed at install: RustFS records the drive count and erasure set width on every drive and refuses to start with other values. `mode` is chosen at install too. Changing it on an existing release does not convert the data: the new mode's services start on empty drives, the old mode's services keep running beside them, and clients reach both. To move a standalone store into a cluster, install the cluster as a second release and copy the buckets across through S3.
+
+:::
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+buckets:
+ - my-bucket
+```
+
+The example creates four peers with one drive each. Every object is split into two data and two parity shards, so reads survive two peers down and writes survive one, and the usable capacity is half of the drives' total. More than one drive per peer needs `persistence.volumePaths`, with one host directory per drive on a disk of its own; the chart README describes it. Install the chart with the values file:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+All peers start together. `--wait` returns once each peer's task runs and has outlived its monitor window of two minutes. Peer 1 creates the buckets once the cluster accepts writes; if it cannot within five minutes of starting, it logs the bucket it could not create (see `docker service logs rustfs_rustfs-1`) and keeps serving. A peer's health check shows only that the peer is alive, so `--wait` does not show whether the cluster serves; step 6 checks that.
+
+## 6. Verify the deployment
+
+In standalone mode, check the release, the service task, and the S3 API readiness endpoint:
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs
+curl --fail http://localhost:9000/health/ready
+```
+
+The S3 API is available at `http://localhost:9000` on every swarm node. Clients use path-style addressing and region `us-east-1`. If the task stays pending with `no suitable node`, no node carries the `rustfs-data=true` label from step 4.
+
+In distributed mode, check the release and the peers' tasks, then ask the cluster whether it serves, from a container on the `rustfs-net` overlay network:
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs-1 rustfs_rustfs-2 rustfs_rustfs-3 rustfs_rustfs-4
+docker run --rm --network rustfs-net curlimages/curl -s -o /dev/null -w '%{http_code}\n' \
+ http://rustfs-rustfs:9000/minio/health/cluster
+```
+
+`200` means that every erasure set has write quorum. If a peer's task stays pending with `no suitable node`, no node carries that peer's `rustfs-=true` label from step 5. Once the label is in place, the peer starts; if peer 1's log then reports a bucket it could not create, restart peer 1 to create the buckets again: `docker service update --force rustfs_rustfs-1`.
+
+Services that join `rustfs-net` reach the cluster at `http://rustfs-rustfs:9000`, with path-style addressing and region `us-east-1`. Any peer serves every object, and the name resolves to every peer whose health check passes. That check shows only that a peer is alive, so on a first install, or after every peer has stopped, a peer can answer 503 until the cluster serves. A request in flight to a peer that stops also fails. Clients must retry, as S3 clients do by default. To reach the cluster from outside the swarm, expose it as described under Exposure modes.
+
+## Upgrade and roll back
+
+Every install, upgrade, and rollback creates a numbered revision of the release. An upgrade starts from the chart's defaults, so pass every value again, including `--set persistence.nodeLabel=""` if you used it in step 4, or keep the values in a file and pass it with `-f`. For the standalone release from step 4, preview a change, apply it, and list the revisions:
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs --wait \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts history rustfs
+```
+
+To return to an earlier revision:
+
+```bash
+swarmcli charts rollback rustfs 1
+```
+
+A rollback redeploys that revision's service definition; it does not restore data.
+
+In distributed mode, pass the values file you installed with to every upgrade, rather than `--reuse-values`, and put later changes, such as exposure settings, into that file. An upgrade whose values lack `mode: distributed` leaves the peers as they are and starts a standalone service beside them.
+
+SwarmCLI updates the peers one at a time: it stops a peer, starts its new task, and moves to the next peer only once that task runs and has outlived its monitor window. With the default four peers all running, the cluster keeps serving reads and writes throughout, one peer short; with one peer already down, it stops accepting writes each time the upgrade stops another. So first check with the commands from step 6 that every peer's task runs and that the cluster answers `200`; a `200` alone does not show that every peer runs. Then preview and apply the upgrade, and check the cluster again afterwards:
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+A rollback rolls the peers the same way. An upgrade whose peer fails to start stops there, with the remaining peers untouched.
+
+:::warning[Rotating the credentials of a cluster takes a full stop]
+
+Every peer derives its internode secret from the key pair, so peers on the old pair and peers on the new one cannot reach each other, and an upgrade that rolls one peer at a time would split the cluster. Create the new secrets:
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key-2 -
+printf '%s' '' | docker secret create rustfs-secret-key-2 -
+```
+
+Add the two secret names to `distributed-values.yaml`, so that later upgrades keep them. With the values from step 5, the file then reads:
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+s3:
+ accessKeySecret: rustfs-access-key-2
+ secretKeySecret: rustfs-secret-key-2
+
+buckets:
+ - my-bucket
+```
+
+Then stop every peer and upgrade, so that all peers start together on the new pair:
+
+```bash
+for n in 1 2 3 4; do docker service scale "rustfs_rustfs-$n=0"; done
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+The data and the buckets survive; clients need the new pair. Do not roll back to a revision from before the rotation: the rollback would move the peers back to the old pair one at a time and split the cluster the same way.
+
+:::
+
+## Exposure modes
+
+The chart exposes the S3 API and the Console independently. The Console is off by default; enable it with `console.enabled=true`. The S3 API mode is `exposure.mode`, and the Console mode is `console.exposure.mode`:
+
+| Mode | Reachable from |
+| - | - |
+| `none` (default) | Services attached to the `rustfs-net` overlay network, at `http://-rustfs:9000` (the Console, when enabled, at port 9001); while the other listener uses `traefik`, also services on `traefik-public` |
+| `published` | A published port: `publish.port` for the S3 API, `console.publish.port` (9001) for the Console, on the Swarm routing mesh (in distributed mode, on each peer's own node) |
+| `traefik` | A host name routed by Traefik over HTTPS: `ingress.host` for the S3 API, `console.ingress.host` for the Console |
+
+The `traefik` mode needs the [`traefik` chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik) installed first: it creates the `traefik-public` network that RustFS joins and obtains the Let's Encrypt certificates. Then serve the S3 API of a standalone release under its host name:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=traefik \
+ --set ingress.host=s3.example.com \
+ --set 'buckets={my-bucket}'
+```
+
+Without Traefik, publish a standalone release's Console on port 9001 next to the S3 API:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set console.enabled=true \
+ --set console.exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+:::note[The Console port serves the S3 API too]
+
+The Console listener also serves the full signed S3 and admin API, so exposing only the Console still puts that API on a public address. Leave the Console disabled where you do not use it.
+
+:::
+
+In distributed mode, every peer gets the same exposure settings; set them in `distributed-values.yaml`, then upgrade as described under Upgrade and roll back. With `traefik`, Traefik balances requests over every healthy peer. The `published` mode needs `publish.mode=host` (and `console.publish.mode=host` for the Console), which publishes the port on each peer's own node instead of the routing mesh, so a node's port reaches only the peer on that node. Put a load balancer in front of the nodes, or use Traefik. Host-mode publishing needs each peer on a node of its own, so a single-node swarm cannot use it.
+
+## Key values
+
+| Value | Purpose | Chart default |
+| - | - | - |
+| `image.tag` | RustFS image tag | `""` (the RustFS version the chart pins) |
+| `mode` | `standalone` or `distributed`, chosen at install | `standalone` |
+| `cluster.peers` | Distributed peers, one service and one node label each; at least 4 | `4` |
+| `cluster.drivesPerPeer` | Drives per distributed peer; more than one needs `persistence.volumePaths` | `1` |
+| `s3.accessKeySecret` / `s3.secretKeySecret` | Docker secrets holding the root credentials | `rustfs-access-key` / `rustfs-secret-key` |
+| `buckets` | Buckets created at start if missing | `[]` |
+| `exposure.mode` | S3 API exposure: `none`, `published`, or `traefik` | `none` |
+| `publish.port` | Published S3 API port | `9000` |
+| `ingress.host` | Host name Traefik routes to the S3 API | `s3.example.com` |
+| `console.enabled` | Run the Console listener | `false` |
+| `console.exposure.mode` | Console exposure: `none`, `published`, or `traefik` | `none` |
+| `persistence.nodeLabel` | Node label the standalone service is pinned to; `""` for no pin | `rustfs-data` |
+| `persistence.nodeLabelPrefix` | Node label prefix pinning distributed peer `` to `-`; `""` for no pins, on a single-node swarm only | `rustfs` |
+| `persistence.volumePath` | Host directory bind-mounted at `/data` instead of the named volume, in standalone mode; must be owned by `10001` | `""` |
+| `extraEnv` | Additional `RUSTFS_*` environment variables, such as `RUSTFS_SERVER_DOMAINS` | `{}` |
+
+The [chart README](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) documents every value, including Traefik routing, single sign-on for the Console through OpenID Connect, and the host-directory bind mounts of both modes.
+
+## Uninstall
+
+```bash
+swarmcli charts uninstall rustfs
+```
+
+Uninstalling removes the service, or every peer's service in distributed mode, and the release history. It keeps the data volume (one per peer in distributed mode), the two Docker secrets, and the `rustfs-net` network, which SwarmCLI lists with the command to remove it.
+
+:::note[The data volumes survive an uninstall]
+
+In standalone mode, a later install with the same release name reattaches the volume and its data. To discard the data, remove the volume on the labelled node once the task has stopped (up to 30 seconds):
+
+```bash
+docker volume rm rustfs_rustfs-data
+```
+
+In distributed mode, each peer keeps its own volume, `rustfs_rustfs-data-`, on the node labelled `rustfs-=true`; remove it there once that peer's task has stopped. A later install with the same release name reuses these volumes, so it must keep the same `cluster.peers` and `cluster.drivesPerPeer`.
+
+In either mode, remove the secrets if you no longer need them: the pair the release uses, and any pair that a rotation replaced. With the names from step 2:
+
+```bash
+docker secret rm rustfs-access-key rustfs-secret-key
+```
+
+:::
+
+## Next steps
+
+- [RustFS Console](/administration/console)
+- [Configure an S3 client](../../developer/examples/aws-cli.md)
+- [Pre-Installation Checklists](../requirement/checklists/index.md)
diff --git a/content/en/installation/index.md b/content/en/installation/index.md
index 8f70bb4ab..de7180459 100644
--- a/content/en/installation/index.md
+++ b/content/en/installation/index.md
@@ -17,6 +17,7 @@ After installation, set unique values for `RUSTFS_ACCESS_KEY` and `RUSTFS_SECRET
- For a Linux binary or systemd installation, set both values in `/etc/default/rustfs`, then restart the `rustfs` service.
- For Docker, Podman, or Docker Compose, pass both values as container environment variables when creating the container. Recreate an existing container if it was started without them.
+- For Docker Swarm, create both values as Docker secrets before you install the chart.
:::
diff --git a/content/fr/index.mdx b/content/fr/index.mdx
index a6756cc82..d783c6e77 100644
--- a/content/fr/index.mdx
+++ b/content/fr/index.mdx
@@ -81,6 +81,15 @@ description: "Installez RustFS sous Linux, dans des conteneurs, sur Kubernetes,
+
+
+
+
+ Installer avec le chart SwarmCLI
+ Déployez RustFS sur Docker Swarm, en mode nœud unique ou distribué, à l’aide du chart rustfs de SwarmCLI.
+
+
+
Fournisseurs cloud
diff --git a/content/fr/installation/cloud-native/meta.json b/content/fr/installation/cloud-native/meta.json
index 6b6519c5d..3c6bd8752 100644
--- a/content/fr/installation/cloud-native/meta.json
+++ b/content/fr/installation/cloud-native/meta.json
@@ -2,6 +2,7 @@
"title": "Cloud natif",
"pages": [
"helm-chart",
- "operator"
+ "operator",
+ "swarmcli-chart"
]
}
diff --git a/content/fr/installation/cloud-native/swarmcli-chart.md b/content/fr/installation/cloud-native/swarmcli-chart.md
new file mode 100644
index 000000000..f3eaed0f5
--- /dev/null
+++ b/content/fr/installation/cloud-native/swarmcli-chart.md
@@ -0,0 +1,294 @@
+---
+title: "Chart SwarmCLI"
+description: "Déployez RustFS sur Docker Swarm avec le chart rustfs de SwarmCLI, sous forme de service à nœud unique ou de cluster distribué avec codage d’effacement : identifiants dans des secrets Docker, mises à niveau et retours arrière versionnés, et HTTPS facultatif via Traefik."
+---
+
+[SwarmCLI](https://github.com/Eldara-Tech/swarmcli) est un gestionnaire de paquets inspiré de Helm et une interface en mode terminal pour Docker Swarm. Son [chart `rustfs`](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) open source déploie RustFS sur Docker Swarm. Tous deux sont maintenus par Eldara Tech, et non par le projet RustFS.
+
+Par rapport à un fichier de stack écrit à la main, le chart apporte :
+
+- **Identifiants dans des secrets Docker.** RustFS lit ses clés racine depuis des fichiers via `RUSTFS_ACCESS_KEY_FILE` et `RUSTFS_SECRET_KEY_FILE`, si bien qu’aucune des deux valeurs n’apparaît dans la définition du service ni dans `docker inspect`. La clé par défaut `rustfsadmin` est refusée.
+- **Releases versionnées.** Prévisualisez une mise à niveau, appliquez-la et revenez à une révision antérieure. SwarmCLI stocke l’historique des révisions dans le swarm lui-même : aucune base de données supplémentaire n’est nécessaire.
+- **HTTPS via Traefik.** Avec le [chart `traefik`](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik) associé, l’API S3 et la Console obtiennent leurs propres noms d’hôte et certificats Let's Encrypt, et la Console peut utiliser l’authentification unique (SSO) via OpenID Connect.
+- **Déploiements avec contrôle d’intégrité.** Les compartiments (buckets) listés dans les valeurs sont créés au démarrage, et chaque déploiement d’une release autonome est surveillé via le point de terminaison `/health/ready` de RustFS : `--wait` signale ainsi une mise à niveau défaillante au lieu d’un succès.
+- **Mises à niveau progressives du cluster.** En mode distribué, une mise à niveau met à jour un pair à la fois ; si les quatre pairs par défaut sont tous en cours d’exécution, le cluster continue de servir les lectures et les écritures pendant toute l’opération, avec un pair en moins.
+
+Le chart fonctionne selon l’un des deux modes suivants, choisi à l’installation. Le mode autonome, utilisé par défaut, exécute un service RustFS avec un seul disque sur un seul nœud (nœud unique, disque unique, SNSD). Un disque unique n’offre aucune redondance par codage d’effacement : ce mode convient donc aux caches de build, aux cibles de sauvegarde et au stockage de blobs d’applications sur un petit swarm. Le mode distribué répartit les objets par codage d’effacement sur quatre pairs ou plus, un par nœud, pour les données qui doivent survivre à la perte d’un nœud. L’étape 4 installe le mode autonome et l’étape 5 le mode distribué ; les autres étapes s’appliquent aux deux.
+
+## 1. Prérequis
+
+* Un Docker Swarm (`docker swarm init`) et un shell sur un nœud manager
+* SwarmCLI 2.2.0 ou version ultérieure : consultez le [guide d’installation de SwarmCLI](https://github.com/Eldara-Tech/swarmcli/blob/main/docs/installation.md)
+* Pour le mode autonome, le port 9000 (API S3) libre sur les nœuds du swarm, car l’étape 4 le publie sur le maillage de routage du swarm
+* Pour le mode distribué, un nœud pour chaque pair, au moins quatre (un seul nœud suffit pour le développement ; voir l’étape 5)
+
+## 2. Créer les identifiants sous forme de secrets Docker
+
+Remplacez les espaces réservés des identifiants, puis créez un secret pour chaque clé :
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key -
+printf '%s' '' | docker secret create rustfs-secret-key -
+```
+
+Chaque valeur doit tenir sur une seule ligne, sans espace. Pour générer une clé d’accès secrète robuste, utilisez par exemple `openssl rand -base64 30`. En mode distribué, chaque pair lit les deux mêmes secrets.
+
+:::warning[Le service refuse les identifiants faibles]
+
+SwarmCLI refuse d’installer le chart tant que l’un des secrets est absent, et le conteneur s’arrête au démarrage si une clé est vide, contient un espace ou a la valeur bien connue `rustfsadmin`. Les secrets Docker ne sont pas modifiables : pour renouveler les identifiants, créez des secrets sous de nouveaux noms, puis mettez à niveau la release en faisant pointer `s3.accessKeySecret` et `s3.secretKeySecret` vers ces secrets. En mode distribué, le renouvellement exige un arrêt complet, comme décrit dans la section Mise à niveau et retour arrière.
+
+:::
+
+## 3. Ajouter le dépôt de charts
+
+Ignorez cette étape si `swarmcli charts repo list` affiche déjà `swarmcli-charts` :
+
+```bash
+swarmcli charts repo add swarmcli-charts https://eldara-tech.github.io/swarmcli-charts
+```
+
+## 4. Installer le mode autonome
+
+Suivez cette étape ou l’étape 5, mais pas les deux. Un volume nommé n’existe que sur un seul nœud ; le service est donc épinglé au nœud portant l’étiquette `rustfs-data=true`. Étiquetez exactement un nœud :
+
+```bash
+docker node update --label-add rustfs-data=true
+```
+
+Sur un swarm à nœud unique, vous pouvez omettre l’étiquette et ajouter plutôt `--set persistence.nodeLabel=""` à la commande d’installation ci-dessous.
+
+Installez le chart en tant que release nommée `rustfs`, publiez l’API S3 sur le port 9000 et créez un compartiment au démarrage :
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+Le service stocke ses données sous `/data` sur le volume nommé `rustfs-data`, que Docker nomme `rustfs_rustfs-data` d’après la release. Chaque compartiment listé dans `buckets` est créé dès que le serveur répond ; un compartiment existant est laissé tel quel, de sorte que les redémarrages et les mises à niveau sont sans risque.
+
+## 5. Installer le mode distribué
+
+Suivez cette étape à la place de l’étape 4. En mode distribué, chaque pair est un service Swarm distinct (de `rustfs_rustfs-1` à `rustfs_rustfs-4` pour une release nommée `rustfs`), avec un seul réplica, son propre volume et sa propre étiquette de nœud. Étiquetez un nœud pour chaque pair :
+
+```bash
+docker node update --label-add rustfs-1=true
+docker node update --label-add rustfs-2=true
+docker node update --label-add rustfs-3=true
+docker node update --label-add rustfs-4=true
+```
+
+Placez chaque pair sur un nœud différent : des pairs qui partagent un nœud partagent aussi son sort, et avec les quatre pairs par défaut, la perte d’un seul nœud qui héberge deux pairs interrompt les écritures. Sur un swarm à nœud unique, attribuez les quatre étiquettes à cet unique nœud ; cette configuration ne convient qu’au développement, car elle n’offre aucune disponibilité.
+
+Définissez explicitement le mode et la structure du cluster. Le nombre total de disques est égal à `cluster.peers * cluster.drivesPerPeer`.
+
+:::warning[Choisir la topologie avant l’installation]
+
+`cluster.peers` et `cluster.drivesPerPeer` sont fixés à l’installation : RustFS enregistre le nombre de disques et la largeur de l’ensemble d’effacement (erasure set) sur chaque disque, et refuse de démarrer avec d’autres valeurs. La valeur `mode` est elle aussi choisie à l’installation. La modifier sur une release existante ne convertit pas les données : les services du nouveau mode démarrent sur des disques vides, ceux de l’ancien mode continuent de s’exécuter à côté d’eux, et les clients atteignent les deux. Pour migrer un stockage autonome vers un cluster, installez le cluster en tant que seconde release et copiez-y les compartiments via S3.
+
+:::
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+buckets:
+ - my-bucket
+```
+
+L’exemple crée quatre pairs dotés chacun d’un disque. Chaque objet est découpé en deux fragments de données et deux fragments de parité : les lectures résistent donc à l’indisponibilité de deux pairs et les écritures à celle d’un pair, et la capacité utile représente la moitié de la capacité totale des disques. Plus d’un disque par pair nécessite `persistence.volumePaths`, avec un répertoire de l’hôte par disque, chacun sur son propre disque physique ; le README du chart décrit ce paramètre. Installez le chart avec le fichier de valeurs :
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+Tous les pairs démarrent ensemble. `--wait` rend la main dès que la tâche de chaque pair s’exécute et est restée active au-delà de sa fenêtre de surveillance de deux minutes. Le pair 1 crée les compartiments dès que le cluster accepte les écritures ; s’il n’y parvient pas dans les cinq minutes qui suivent son démarrage, il consigne dans son journal, visible avec `docker service logs rustfs_rustfs-1`, le compartiment qu’il n’a pas pu créer, et continue de servir les requêtes. Le contrôle d’intégrité d’un pair indique seulement que ce pair est en vie : `--wait` n’indique donc pas si le cluster sert les requêtes ; l’étape 6 le vérifie.
+
+## 6. Vérifier le déploiement
+
+En mode autonome, vérifiez la release, la tâche du service et le point de terminaison d’état de préparation de l’API S3 :
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs
+curl --fail http://localhost:9000/health/ready
+```
+
+L’API S3 est accessible à l’adresse `http://localhost:9000` sur chaque nœud du swarm. Les clients utilisent l’adressage de type chemin (path-style) et la Région `us-east-1`. Si la tâche reste en attente avec `no suitable node`, c’est qu’aucun nœud ne porte l’étiquette `rustfs-data=true` de l’étape 4.
+
+En mode distribué, vérifiez la release et les tâches des pairs, puis demandez au cluster s’il sert les requêtes, depuis un conteneur connecté au réseau overlay `rustfs-net` :
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs-1 rustfs_rustfs-2 rustfs_rustfs-3 rustfs_rustfs-4
+docker run --rm --network rustfs-net curlimages/curl -s -o /dev/null -w '%{http_code}\n' \
+ http://rustfs-rustfs:9000/minio/health/cluster
+```
+
+`200` signifie que chaque ensemble d’effacement dispose du quorum d’écriture. Si la tâche d’un pair reste en attente avec `no suitable node`, c’est qu’aucun nœud ne porte l’étiquette `rustfs-=true` de ce pair, posée à l’étape 5. Une fois l’étiquette en place, le pair démarre ; si le journal du pair 1 signale ensuite un compartiment que le pair n’a pas pu créer, redémarrez le pair 1 pour créer de nouveau les compartiments : `docker service update --force rustfs_rustfs-1`.
+
+Les services qui rejoignent `rustfs-net` atteignent le cluster à l’adresse `http://rustfs-rustfs:9000`, avec l’adressage de type chemin et la Région `us-east-1`. Tout pair sert l’ensemble des objets, et le nom se résout en l’adresse de chaque pair dont le contrôle d’intégrité réussit. Ce contrôle indique seulement qu’un pair est en vie : lors d’une première installation, ou après l’arrêt de tous les pairs, un pair peut donc répondre 503 tant que le cluster ne sert pas les requêtes. Une requête en cours vers un pair qui s’arrête échoue également. Les clients doivent réessayer, comme le font les clients S3 par défaut. Pour atteindre le cluster depuis l’extérieur du swarm, exposez-le comme décrit dans la section Modes d’exposition.
+
+## Mise à niveau et retour arrière
+
+Chaque installation, mise à niveau ou retour arrière crée une révision numérotée de la release. Une mise à niveau repart des valeurs par défaut du chart : transmettez donc de nouveau chaque valeur, y compris `--set persistence.nodeLabel=""` si vous l’avez utilisé à l’étape 4, ou conservez les valeurs dans un fichier et transmettez-le avec `-f`. Pour la release autonome de l’étape 4, prévisualisez une modification, appliquez-la, puis listez les révisions :
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs --wait \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts history rustfs
+```
+
+Pour revenir à une révision antérieure :
+
+```bash
+swarmcli charts rollback rustfs 1
+```
+
+Un retour arrière redéploie la définition du service de cette révision ; il ne restaure pas les données.
+
+En mode distribué, transmettez à chaque mise à niveau le fichier de valeurs utilisé lors de l’installation, plutôt que `--reuse-values`, et reportez dans ce fichier les modifications ultérieures, comme les paramètres d’exposition. Une mise à niveau dont les valeurs ne contiennent pas `mode: distributed` laisse les pairs en l’état et démarre un service autonome à côté d’eux.
+
+SwarmCLI met à jour les pairs un à la fois : il arrête un pair, démarre sa nouvelle tâche et ne passe au pair suivant qu’une fois que cette tâche s’exécute et est restée active au-delà de sa fenêtre de surveillance. Si les quatre pairs par défaut sont tous en cours d’exécution, le cluster continue de servir les lectures et les écritures pendant toute l’opération, avec un pair en moins ; si un pair est déjà indisponible, le cluster cesse d’accepter les écritures chaque fois que la mise à niveau en arrête un autre. Vérifiez donc d’abord, avec les commandes de l’étape 6, que la tâche de chaque pair s’exécute et que le cluster répond `200` ; un `200` à lui seul n’indique pas que tous les pairs s’exécutent. Prévisualisez et appliquez ensuite la mise à niveau, puis vérifiez de nouveau le cluster :
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+Un retour arrière met à jour les pairs de la même manière. Une mise à niveau dont un pair ne parvient pas à démarrer s’arrête là, sans toucher aux pairs restants.
+
+:::warning[Le renouvellement des identifiants d’un cluster exige un arrêt complet]
+
+Chaque pair dérive son secret inter-nœuds de la paire de clés : les pairs qui utilisent l’ancienne paire et ceux qui utilisent la nouvelle ne peuvent donc pas communiquer entre eux, et une mise à niveau qui met à jour un pair à la fois scinderait le cluster. Créez les nouveaux secrets :
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key-2 -
+printf '%s' '' | docker secret create rustfs-secret-key-2 -
+```
+
+Ajoutez les noms des deux secrets à `distributed-values.yaml`, afin que les mises à niveau ultérieures les conservent. Avec les valeurs de l’étape 5, le fichier devient :
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+s3:
+ accessKeySecret: rustfs-access-key-2
+ secretKeySecret: rustfs-secret-key-2
+
+buckets:
+ - my-bucket
+```
+
+Arrêtez ensuite tous les pairs et effectuez la mise à niveau, afin que tous les pairs démarrent ensemble avec la nouvelle paire :
+
+```bash
+for n in 1 2 3 4; do docker service scale "rustfs_rustfs-$n=0"; done
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+Les données et les compartiments sont conservés ; les clients ont besoin de la nouvelle paire. Ne revenez pas à une révision antérieure au renouvellement : le retour arrière ramènerait les pairs vers l’ancienne paire un à la fois et scinderait le cluster de la même manière.
+
+:::
+
+## Modes d’exposition
+
+Le chart expose l’API S3 et la Console indépendamment l’une de l’autre. La Console est désactivée par défaut ; activez-la avec `console.enabled=true`. Le mode de l’API S3 est défini par `exposure.mode`, celui de la Console par `console.exposure.mode` :
+
+| Mode | Accessible depuis |
+| - | - |
+| `none` (par défaut) | Les services connectés au réseau overlay `rustfs-net`, à l’adresse `http://-rustfs:9000` (la Console, si elle est activée, sur le port 9001) ; tant que l’autre écouteur utilise `traefik`, également les services du réseau `traefik-public` |
+| `published` | Un port publié : `publish.port` pour l’API S3, `console.publish.port` (9001) pour la Console, sur le maillage de routage du swarm (en mode distribué, sur le nœud propre à chaque pair) |
+| `traefik` | Un nom d’hôte routé par Traefik en HTTPS : `ingress.host` pour l’API S3, `console.ingress.host` pour la Console |
+
+Le mode `traefik` nécessite d’installer d’abord le [chart `traefik`](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik) : ce chart crée le réseau `traefik-public` rejoint par RustFS et obtient les certificats Let's Encrypt. Exposez ensuite l’API S3 d’une release autonome sous son nom d’hôte :
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=traefik \
+ --set ingress.host=s3.example.com \
+ --set 'buckets={my-bucket}'
+```
+
+Sans Traefik, publiez la Console d’une release autonome sur le port 9001, à côté de l’API S3 :
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set console.enabled=true \
+ --set console.exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+:::note[Le port de la Console sert aussi l’API S3]
+
+L’écouteur de la Console sert également l’API S3 signée complète et l’API d’administration : exposer uniquement la Console place donc tout de même cette API sur une adresse publique. Laissez la Console désactivée si vous ne l’utilisez pas.
+
+:::
+
+En mode distribué, tous les pairs reçoivent les mêmes paramètres d’exposition ; définissez-les dans `distributed-values.yaml`, puis effectuez la mise à niveau comme décrit dans la section Mise à niveau et retour arrière. Avec `traefik`, Traefik répartit les requêtes entre tous les pairs sains. Le mode `published` nécessite `publish.mode=host` (et `console.publish.mode=host` pour la Console), qui publie le port sur le nœud propre à chaque pair plutôt que sur le maillage de routage : le port d’un nœud n’atteint donc que le pair situé sur ce nœud. Placez un équilibreur de charge devant les nœuds, ou utilisez Traefik. La publication en mode hôte nécessite que chaque pair dispose de son propre nœud : un swarm à nœud unique ne peut donc pas l’utiliser.
+
+## Valeurs principales
+
+| Valeur | Rôle | Valeur par défaut du chart |
+| - | - | - |
+| `image.tag` | Tag de l’image RustFS | `""` (la version de RustFS fixée par le chart) |
+| `mode` | `standalone` ou `distributed`, choisi à l’installation | `standalone` |
+| `cluster.peers` | Pairs distribués, chacun avec un service et une étiquette de nœud ; au moins 4 | `4` |
+| `cluster.drivesPerPeer` | Disques par pair distribué ; plus d’un disque nécessite `persistence.volumePaths` | `1` |
+| `s3.accessKeySecret` / `s3.secretKeySecret` | Secrets Docker contenant les identifiants racine | `rustfs-access-key` / `rustfs-secret-key` |
+| `buckets` | Compartiments créés au démarrage s’ils n’existent pas | `[]` |
+| `exposure.mode` | Exposition de l’API S3 : `none`, `published` ou `traefik` | `none` |
+| `publish.port` | Port publié de l’API S3 | `9000` |
+| `ingress.host` | Nom d’hôte que Traefik route vers l’API S3 | `s3.example.com` |
+| `console.enabled` | Exécuter l’écouteur de la Console | `false` |
+| `console.exposure.mode` | Exposition de la Console : `none`, `published` ou `traefik` | `none` |
+| `persistence.nodeLabel` | Étiquette du nœud auquel le service autonome est épinglé ; `""` pour aucun épinglage | `rustfs-data` |
+| `persistence.nodeLabelPrefix` | Préfixe d’étiquette de nœud qui épingle le pair distribué `` au nœud étiqueté `-` ; `""` pour aucun épinglage, uniquement sur un swarm à nœud unique | `rustfs` |
+| `persistence.volumePath` | Répertoire de l’hôte monté sur `/data` à la place du volume nommé, en mode autonome ; doit appartenir à `10001` | `""` |
+| `extraEnv` | Variables d’environnement `RUSTFS_*` supplémentaires, comme `RUSTFS_SERVER_DOMAINS` | `{}` |
+
+Le [README du chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) documente toutes les valeurs, notamment le routage par Traefik, l’authentification unique (SSO) pour la Console via OpenID Connect et les montages de répertoires de l’hôte des deux modes.
+
+## Désinstallation
+
+```bash
+swarmcli charts uninstall rustfs
+```
+
+La désinstallation supprime le service, ou le service de chaque pair en mode distribué, ainsi que l’historique de la release. Elle conserve le volume de données (un par pair en mode distribué), les deux secrets Docker et le réseau `rustfs-net`, que SwarmCLI affiche avec la commande permettant de le supprimer.
+
+:::note[Les volumes de données survivent à la désinstallation]
+
+En mode autonome, une installation ultérieure avec le même nom de release réattache le volume et ses données. Pour supprimer les données, supprimez le volume sur le nœud étiqueté une fois la tâche arrêtée (ce qui peut prendre jusqu’à 30 secondes) :
+
+```bash
+docker volume rm rustfs_rustfs-data
+```
+
+En mode distribué, chaque pair conserve son propre volume, `rustfs_rustfs-data-`, sur le nœud portant l’étiquette `rustfs-=true` ; supprimez-le sur ce nœud une fois la tâche de ce pair arrêtée. Une installation ultérieure avec le même nom de release réutilise ces volumes : elle doit donc conserver les mêmes valeurs de `cluster.peers` et `cluster.drivesPerPeer`.
+
+Dans les deux modes, supprimez les secrets si vous n’en avez plus besoin : la paire utilisée par la release, ainsi que toute paire remplacée lors d’un renouvellement. Avec les noms de l’étape 2 :
+
+```bash
+docker secret rm rustfs-access-key rustfs-secret-key
+```
+
+:::
+
+## Étapes suivantes
+
+- [Console RustFS](/administration/console)
+- [Configurer un client S3](../../developer/examples/aws-cli.md)
+- [Listes de contrôle avant l’installation](../requirement/checklists/index.md)
diff --git a/content/fr/installation/index.md b/content/fr/installation/index.md
index 4475ca913..8f9b95b82 100644
--- a/content/fr/installation/index.md
+++ b/content/fr/installation/index.md
@@ -17,6 +17,7 @@ Après l’installation, définissez des valeurs uniques pour `RUSTFS_ACCESS_KEY
- Pour une installation par binaire Linux ou par systemd, définissez les deux valeurs dans `/etc/default/rustfs`, puis redémarrez le service `rustfs`.
- Pour Docker, Podman ou Docker Compose, transmettez les deux valeurs comme variables d’environnement du conteneur au moment de sa création. Recréez un conteneur existant s’il a été démarré sans elles.
+- Pour Docker Swarm, créez les deux valeurs sous forme de secrets Docker avant d’installer le chart.
:::
diff --git a/content/ja/index.mdx b/content/ja/index.mdx
index c6193e059..5f50c496a 100644
--- a/content/ja/index.mdx
+++ b/content/ja/index.mdx
@@ -80,6 +80,15 @@ description: "Linux、コンテナ、Kubernetes、macOS、Windows に RustFS を
+
+
+
+
+ SwarmCLI チャートでインストール
+ SwarmCLI の rustfs チャートを使用して、Docker Swarm にシングルノードまたは分散構成の RustFS をデプロイします。
+
+
+
クラウドプロバイダー
diff --git a/content/ja/installation/cloud-native/meta.json b/content/ja/installation/cloud-native/meta.json
index 5aacc86ff..75f3de200 100644
--- a/content/ja/installation/cloud-native/meta.json
+++ b/content/ja/installation/cloud-native/meta.json
@@ -2,6 +2,7 @@
"title": "クラウドネイティブ",
"pages": [
"helm-chart",
- "operator"
+ "operator",
+ "swarmcli-chart"
]
}
diff --git a/content/ja/installation/cloud-native/swarmcli-chart.md b/content/ja/installation/cloud-native/swarmcli-chart.md
new file mode 100644
index 000000000..c2bfe4181
--- /dev/null
+++ b/content/ja/installation/cloud-native/swarmcli-chart.md
@@ -0,0 +1,294 @@
+---
+title: "SwarmCLI チャート"
+description: "SwarmCLI の rustfs チャートを使い、RustFS を単一ノードのサービスまたはイレイジャーコーディングを用いた分散クラスターとして Docker Swarm 上にデプロイします。認証情報は Docker シークレットに保持し、バージョン管理されたアップグレードとロールバック、必要に応じて Traefik 経由の HTTPS を利用できます。"
+---
+
+[SwarmCLI](https://github.com/Eldara-Tech/swarmcli) は、Helm に着想を得た Docker Swarm 向けのパッケージマネージャー兼ターミナル UI です。SwarmCLI のオープンソースの [`rustfs` チャート](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs)は、RustFS を Docker Swarm 上にデプロイします。どちらも RustFS プロジェクトではなく Eldara Tech がメンテナンスしています。
+
+手書きのスタックファイルと比べて、このチャートには次の機能が加わります。
+
+- **Docker シークレットによる認証情報**:RustFS は `RUSTFS_ACCESS_KEY_FILE` と `RUSTFS_SECRET_KEY_FILE` を通じてルートキーをファイルから読み込むため、どちらの値もサービス定義や `docker inspect` の出力には現れません。デフォルトの `rustfsadmin` キーは拒否されます。
+- **バージョン管理されたリリース**:アップグレードのプレビューと適用、以前のリビジョンへのロールバックができます。SwarmCLI はリビジョン履歴を Swarm 自体に保存するため、追加のデータベースは不要です。
+- **Traefik 経由の HTTPS**:連携用の [`traefik` チャート](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik)を併用すると、S3 API と Console にそれぞれ専用のホスト名と Let's Encrypt の証明書が割り当てられ、Console では OpenID Connect によるシングルサインオンも利用できます。
+- **ヘルスチェック付きのロールアウト**:設定値に列挙したバケットは起動時に作成されます。また、スタンドアロンモードのリリースでは、すべてのロールアウトが RustFS の `/health/ready` エンドポイントで監視されるため、`--wait` は問題のあるアップグレードを成功ではなく失敗として報告します。
+- **クラスターのローリングアップグレード**:分散モードでは、アップグレードはピアを 1 つずつ順に更新します。デフォルトの 4 つのピアがすべて実行中であれば、クラスターはアップグレードの間ずっと、ピアが 1 つ欠けた状態で読み取りと書き込みを処理し続けます。
+
+このチャートは 2 つのモードのいずれかで動作し、モードはインストール時に選択します。デフォルトのスタンドアロンモードでは、1 つのノード上で 1 台のドライブを使う RustFS サービスを 1 つ実行します(シングルノード・シングルディスク、SNSD)。単一ドライブにはイレイジャーコーディングによる冗長性がないため、小規模な Swarm でのビルドキャッシュ、バックアップ先、アプリケーションの Blob ストアに適しています。分散モードは、ノードを 1 つ失っても失われてはならないデータ向けのモードで、ノードごとに 1 つずつ配置した 4 つ以上のピアにわたってオブジェクトをイレイジャーコーディングします。手順 4 ではスタンドアロンモードを、手順 5 では分散モードをインストールします。その他の手順は両方のモードに共通です。
+
+## 1. 前提条件
+
+* Docker Swarm(`docker swarm init`)と、マネージャーノード上のシェル
+* SwarmCLI 2.2.0 以降([SwarmCLI のインストールガイド](https://github.com/Eldara-Tech/swarmcli/blob/main/docs/installation.md)を参照)
+* スタンドアロンモードでは、Swarm ノード上でポート 9000(S3 API)が空いていること。手順 4 でこのポートを Swarm のルーティングメッシュに公開します
+* 分散モードでは、ピアごとに 1 つ、最低 4 つのノード(開発用途であれば単一ノードで十分です。手順 5 を参照)
+
+## 2. 認証情報を Docker シークレットとして作成する
+
+認証情報のプレースホルダーを置き換え、キーごとにシークレットを 1 つ作成します。
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key -
+printf '%s' '' | docker secret create rustfs-secret-key -
+```
+
+各値は 1 行に収め、内部に空白文字を含めないでください。強力なシークレットアクセスキーは、たとえば `openssl rand -base64 30` で生成できます。分散モードでは、すべてのピアが同じ 2 つのシークレットを読み込みます。
+
+:::warning[弱い認証情報ではサービスが起動しません]
+
+いずれかのシークレットが存在しない場合、SwarmCLI はチャートのインストールを拒否します。また、キーが空である、空白文字を含む、またはよく知られた値 `rustfsadmin` である場合、コンテナは起動時に終了します。Docker シークレットは編集できません。認証情報をローテーションするには、新しい名前でシークレットを作成し、`s3.accessKeySecret` と `s3.secretKeySecret` をそれらに向けてリリースをアップグレードします。分散モードでのローテーションには、「アップグレードとロールバック」で説明するとおり、完全停止が必要です。
+
+:::
+
+## 3. チャートリポジトリを追加する
+
+`swarmcli charts repo list` にすでに `swarmcli-charts` が表示される場合、この手順は不要です。
+
+```bash
+swarmcli charts repo add swarmcli-charts https://eldara-tech.github.io/swarmcli-charts
+```
+
+## 4. スタンドアロンモードをインストールする
+
+この手順と手順 5 のどちらか一方だけを実施します。名前付きボリュームは 1 つのノード上にしか存在しないため、サービスは `rustfs-data=true` ラベルを持つノードに固定されます。ラベルは必ず 1 つのノードにだけ付けます。
+
+```bash
+docker node update --label-add rustfs-data=true
+```
+
+単一ノードの Swarm では、ラベル付けを省略し、代わりに次のインストールコマンドに `--set persistence.nodeLabel=""` を追加できます。
+
+チャートを `rustfs` という名前のリリースとしてインストールし、S3 API をポート 9000 で公開して、起動時にバケットを 1 つ作成します。
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+サービスはデータを名前付きボリューム `rustfs-data` の `/data` 配下に保存します。Docker はこのボリュームにリリース名を付けて `rustfs_rustfs-data` と命名します。`buckets` に指定した各バケットはサーバーが応答した時点で作成され、既存のバケットはそのまま残るため、再起動やアップグレードを行っても問題ありません。
+
+## 5. 分散モードをインストールする
+
+手順 4 の代わりにこの手順を実施します。分散モードでは、各ピアがそれぞれ独立した Swarm サービス(`rustfs` という名前のリリースでは `rustfs_rustfs-1` から `rustfs_rustfs-4` まで)となり、1 つのレプリカ、専用のボリューム、専用のノードラベルを持ちます。ピアごとに 1 つのノードにラベルを付けます。
+
+```bash
+docker node update --label-add rustfs-1=true
+docker node update --label-add rustfs-2=true
+docker node update --label-add rustfs-3=true
+docker node update --label-add rustfs-4=true
+```
+
+各ピアは別々のノードに配置します。同じノード上のピアは、そのノードの障害の影響をまとめて受けます。デフォルトの 4 つのピアでは、2 つのピアを配置したノードを 1 つ失うと書き込みが停止します。単一ノードの Swarm では、その 1 つのノードに 4 つのラベルをすべて付けます。この構成では可用性がまったく得られないため、開発用途にのみ適しています。
+
+モードとクラスター構成を明示的に指定します。ドライブの総数は `cluster.peers * cluster.drivesPerPeer` です。
+
+:::warning[トポロジーはインストール前に決定してください]
+
+`cluster.peers` と `cluster.drivesPerPeer` はインストール時に固定されます。RustFS はドライブ数とイレイジャーセットの幅をすべてのドライブに記録し、それ以外の値では起動を拒否します。`mode` もインストール時に選択します。既存のリリースでモードを変更してもデータは変換されません。新しいモードのサービスは空のドライブで起動し、古いモードのサービスもそれと並行して実行され続け、クライアントのリクエストは両方に届きます。スタンドアロンモードのストアをクラスターに移行するには、クラスターを 2 つ目のリリースとしてインストールし、S3 経由でバケットをコピーします。
+
+:::
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+buckets:
+ - my-bucket
+```
+
+この例では、それぞれ 1 台のドライブを持つ 4 つのピアを作成します。各オブジェクトは 2 つのデータシャードと 2 つのパリティシャードに分割されます。そのため、読み取りはピアが 2 つ停止しても、書き込みは 1 つ停止しても継続でき、利用可能な容量はドライブの合計容量の半分になります。ピアごとに 2 台以上のドライブを使うには `persistence.volumePaths` が必要で、ドライブごとに、それぞれ専用のディスク上にホストディレクトリを 1 つ用意します。詳しくはチャートの README に記載されています。設定値ファイルを指定してチャートをインストールします。
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+すべてのピアは同時に起動します。`--wait` は、各ピアのタスクが実行中になり、2 分間の監視期間を過ぎても動作し続けた時点で完了します。ピア 1 は、クラスターが書き込みを受け付けるようになった時点でバケットを作成します。起動から 5 分以内に作成できなかった場合は、作成できなかったバケットをログに記録し(`docker service logs rustfs_rustfs-1` で確認できます)、そのままリクエストの処理を続けます。ピアのヘルスチェックが示すのはそのピアが生存していることだけなので、`--wait` ではクラスターがリクエストを処理できるかどうかはわかりません。これは手順 6 で確認します。
+
+## 6. デプロイを確認する
+
+スタンドアロンモードでは、リリース、サービスのタスク、S3 API の Readiness エンドポイントを確認します。
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs
+curl --fail http://localhost:9000/health/ready
+```
+
+S3 API は、すべての Swarm ノードで `http://localhost:9000` から利用できます。クライアントはパススタイルアクセスとリージョン `us-east-1` を使用します。タスクが `no suitable node` で保留中のままの場合は、手順 4 の `rustfs-data=true` ラベルが付いたノードがありません。
+
+分散モードでは、リリースと各ピアのタスクを確認したうえで、`rustfs-net` オーバーレイネットワーク上のコンテナから、クラスターがリクエストを処理できるかどうかを問い合わせます。
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs-1 rustfs_rustfs-2 rustfs_rustfs-3 rustfs_rustfs-4
+docker run --rm --network rustfs-net curlimages/curl -s -o /dev/null -w '%{http_code}\n' \
+ http://rustfs-rustfs:9000/minio/health/cluster
+```
+
+`200` は、すべてのイレイジャーセットが書き込みクォーラムを満たしていることを意味します。ピアのタスクが `no suitable node` で保留中のままの場合は、そのピアに対応する手順 5 の `rustfs-=true` ラベルが付いたノードがありません。ラベルを付けるとピアが起動します。その後、作成できなかったバケットがピア 1 のログに記録された場合は、ピア 1 を再起動してバケットを再度作成します(`docker service update --force rustfs_rustfs-1`)。
+
+`rustfs-net` に参加したサービスは、パススタイルアクセスとリージョン `us-east-1` を使い、`http://rustfs-rustfs:9000` でクラスターにアクセスします。どのピアもすべてのオブジェクトを提供でき、この名前はヘルスチェックに合格したすべてのピアに解決されます。このヘルスチェックが示すのはピアが生存していることだけなので、初回インストール時や、すべてのピアが停止した後は、クラスターがリクエストを処理できるようになるまで、ピアが 503 を返すことがあります。停止するピアで処理中のリクエストも失敗します。クライアントは再試行する必要があります(S3 クライアントはデフォルトで再試行します)。Swarm の外部からクラスターにアクセスするには、「公開モード」で説明するとおりにクラスターを公開します。
+
+## アップグレードとロールバック
+
+インストール、アップグレード、ロールバックを行うたびに、リリースの番号付きリビジョンが作成されます。アップグレードはチャートのデフォルト値から開始されるため、すべての値を再度指定するか(手順 4 で `--set persistence.nodeLabel=""` を使用した場合はそれも含めます)、値をファイルにまとめて `-f` で渡します。手順 4 のスタンドアロンモードのリリースでは、次のように変更をプレビューして適用し、リビジョンを一覧表示します。
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs --wait \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts history rustfs
+```
+
+以前のリビジョンに戻すには、次のようにします。
+
+```bash
+swarmcli charts rollback rustfs 1
+```
+
+ロールバックではそのリビジョンのサービス定義が再デプロイされますが、データは復元されません。
+
+分散モードでは、すべてのアップグレードで `--reuse-values` ではなくインストール時に使用した設定値ファイルを渡し、公開設定などの以降の変更もそのファイルに記述します。設定値に `mode: distributed` が含まれていないアップグレードでは、ピアはそのまま残り、それと並行してスタンドアロンモードのサービスが起動します。
+
+SwarmCLI はピアを 1 つずつ更新します。ピアを停止して新しいタスクを起動し、そのタスクが実行中になって監視期間を過ぎても動作し続けた時点で、初めて次のピアに進みます。デフォルトの 4 つのピアがすべて実行中であれば、クラスターはアップグレードの間ずっと、ピアが 1 つ欠けた状態で読み取りと書き込みを処理し続けます。一方、すでに 1 つのピアが停止している場合は、アップグレードが別のピアを停止するたびに、クラスターは書き込みを受け付けなくなります。そのため、まず手順 6 のコマンドで、すべてのピアのタスクが実行中であることと、クラスターが `200` を返すことを確認します。`200` だけでは、すべてのピアが実行中であることはわかりません。そのうえでアップグレードをプレビューして適用し、適用後にもう一度クラスターを確認します。
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+ロールバックも同じ方法でピアを 1 つずつ更新します。ピアの起動に失敗したアップグレードはその時点で停止し、残りのピアは更新されません。
+
+:::warning[クラスターの認証情報のローテーションには完全停止が必要です]
+
+各ピアはノード間シークレットをキーペアから導出します。そのため、古いキーペアを使うピアと新しいキーペアを使うピアは互いに通信できず、ピアを 1 つずつ更新するアップグレードではクラスターが分断されてしまいます。新しいシークレットを作成します。
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key-2 -
+printf '%s' '' | docker secret create rustfs-secret-key-2 -
+```
+
+以降のアップグレードでも使われ続けるように、2 つのシークレット名を `distributed-values.yaml` に追加します。手順 5 の設定値を使っている場合、ファイルは次のようになります。
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+s3:
+ accessKeySecret: rustfs-access-key-2
+ secretKeySecret: rustfs-secret-key-2
+
+buckets:
+ - my-bucket
+```
+
+次に、すべてのピアが新しいキーペアで同時に起動するように、すべてのピアを停止してからアップグレードします。
+
+```bash
+for n in 1 2 3 4; do docker service scale "rustfs_rustfs-$n=0"; done
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+データとバケットはそのまま保持されますが、クライアントには新しいキーペアが必要です。ローテーション前のリビジョンにはロールバックしないでください。ロールバックするとピアが 1 つずつ古いキーペアに戻され、同じようにクラスターが分断されます。
+
+:::
+
+## 公開モード
+
+チャートは S3 API と Console を個別に公開します。Console はデフォルトで無効になっており、`console.enabled=true` で有効にできます。S3 API のモードは `exposure.mode`、Console のモードは `console.exposure.mode` で指定します。
+
+| モード | アクセス元 |
+| - | - |
+| `none`(デフォルト) | `rustfs-net` オーバーレイネットワークに接続されたサービス。アドレスは `http://-rustfs:9000`(Console は有効化した場合ポート 9001)。もう一方のリスナーが `traefik` を使用している間は、`traefik-public` 上のサービスからも到達可能 |
+| `published` | 公開されたポート。S3 API は `publish.port`、Console は `console.publish.port`(9001)。公開先は Swarm のルーティングメッシュ(分散モードでは各ピア自身のノード) |
+| `traefik` | Traefik が HTTPS でルーティングするホスト名。S3 API は `ingress.host`、Console は `console.ingress.host` |
+
+`traefik` モードを使うには、先に [`traefik` チャート](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik)をインストールしておく必要があります。このチャートは、RustFS が参加する `traefik-public` ネットワークを作成し、Let's Encrypt の証明書を取得します。そのうえで、スタンドアロンモードのリリースの S3 API を専用のホスト名で公開します。
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=traefik \
+ --set ingress.host=s3.example.com \
+ --set 'buckets={my-bucket}'
+```
+
+Traefik を使わずに、スタンドアロンモードのリリースで S3 API とあわせて Console もポート 9001 で公開するには、次のようにします。
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set console.enabled=true \
+ --set console.exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+:::note[Console のポートでも S3 API が提供されます]
+
+Console のリスナーは、署名付きの S3 API と管理 API もすべて提供します。そのため、Console だけを公開した場合でも、これらの API はパブリックなアドレスから到達可能になります。Console を使用しない場合は無効のままにしてください。
+
+:::
+
+分散モードでは、すべてのピアに同じ公開設定が適用されます。設定は `distributed-values.yaml` に記述し、「アップグレードとロールバック」で説明するとおりにアップグレードします。`traefik` モードでは、Traefik がリクエストを正常なすべてのピアに分散します。`published` モードには `publish.mode=host`(Console には `console.publish.mode=host` も)が必要です。この設定ではポートがルーティングメッシュではなく各ピア自身のノードで公開されるため、あるノードのポートからは、そのノード上のピアにしか到達できません。ノードの前段にロードバランサーを置くか、Traefik を使用します。ホストモードでの公開には各ピアが専用のノードに配置されている必要があるため、単一ノードの Swarm では使用できません。
+
+## 主な設定値
+
+| 値 | 用途 | チャートのデフォルト |
+| - | - | - |
+| `image.tag` | RustFS イメージのタグ | `""`(チャートが固定している RustFS のバージョン) |
+| `mode` | `standalone` または `distributed`。インストール時に選択 | `standalone` |
+| `cluster.peers` | 分散モードのピア数。ピアごとにサービスとノードラベルを 1 つずつ使用。4 以上 | `4` |
+| `cluster.drivesPerPeer` | 分散モードのピアあたりのドライブ数。2 台以上には `persistence.volumePaths` が必要 | `1` |
+| `s3.accessKeySecret` / `s3.secretKeySecret` | ルート認証情報を保持する Docker シークレット | `rustfs-access-key` / `rustfs-secret-key` |
+| `buckets` | 起動時に存在しなければ作成するバケット | `[]` |
+| `exposure.mode` | S3 API の公開方法:`none`、`published`、`traefik` | `none` |
+| `publish.port` | S3 API の公開ポート | `9000` |
+| `ingress.host` | Traefik が S3 API にルーティングするホスト名 | `s3.example.com` |
+| `console.enabled` | Console のリスナーを実行する | `false` |
+| `console.exposure.mode` | Console の公開方法:`none`、`published`、`traefik` | `none` |
+| `persistence.nodeLabel` | スタンドアロンモードのサービスを固定するノードラベル。`""` で固定しない | `rustfs-data` |
+| `persistence.nodeLabelPrefix` | 分散モードのピア `` を `-` に固定するノードラベルの接頭辞。`""` で固定しない(単一ノードの Swarm のみ) | `rustfs` |
+| `persistence.volumePath` | スタンドアロンモードで、名前付きボリュームの代わりに `/data` へバインドマウントするホストディレクトリ。所有者は `10001` である必要があります | `""` |
+| `extraEnv` | 追加の `RUSTFS_*` 環境変数(`RUSTFS_SERVER_DOMAINS` など) | `{}` |
+
+すべての設定値は[チャートの README](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) に記載されています。Traefik によるルーティング、OpenID Connect を使った Console のシングルサインオン、両方のモードにおけるホストディレクトリのバインドマウントについてもこちらを参照してください。
+
+## アンインストール
+
+```bash
+swarmcli charts uninstall rustfs
+```
+
+アンインストールすると、サービス(分散モードではすべてのピアのサービス)とリリース履歴が削除されます。データボリューム(分散モードではピアごとに 1 つ)、2 つの Docker シークレット、`rustfs-net` ネットワークは残ります。SwarmCLI はこのネットワークを、削除するためのコマンドとともに表示します。
+
+:::note[データボリュームはアンインストール後も残ります]
+
+スタンドアロンモードでは、同じリリース名で再度インストールすると、ボリュームとそのデータが再びマウントされます。データを破棄するには、タスクが停止するのを待ってから(最大 30 秒)、ラベルを付けたノード上でボリュームを削除します。
+
+```bash
+docker volume rm rustfs_rustfs-data
+```
+
+分散モードでは、各ピアが専用のボリューム `rustfs_rustfs-data-` を、`rustfs-=true` ラベルを付けたノード上に保持します。そのピアのタスクが停止したら、そのノード上でボリュームを削除します。同じリリース名で再度インストールするとこれらのボリュームが再利用されるため、`cluster.peers` と `cluster.drivesPerPeer` は同じ値のままにする必要があります。
+
+どちらのモードでも、シークレットが不要であれば削除します。対象は、リリースが使用しているシークレットのペアと、ローテーションで置き換えられたすべてのペアです。手順 2 の名前を使った場合は次のとおりです。
+
+```bash
+docker secret rm rustfs-access-key rustfs-secret-key
+```
+
+:::
+
+## 次のステップ
+
+- [RustFS Console](/administration/console)
+- [S3 クライアントを設定する](../../developer/examples/aws-cli.md)
+- [インストール前チェックリスト](../requirement/checklists/index.md)
diff --git a/content/ja/installation/index.md b/content/ja/installation/index.md
index 99315ed6d..f84e8949e 100644
--- a/content/ja/installation/index.md
+++ b/content/ja/installation/index.md
@@ -17,6 +17,7 @@ Windows 版の RustFS は、開発とデバッグ専用であり、**本番デ
- Linux バイナリまたは systemd でインストールした場合は、`/etc/default/rustfs` に両方の値を設定し、`rustfs` サービスを再起動します。
- Docker、Podman、または Docker Compose の場合は、コンテナ作成時に両方の値をコンテナの環境変数として渡します。これらを設定せずに起動した既存のコンテナは、作り直します。
+- Docker Swarm の場合は、チャートをインストールする前に、両方の値を Docker シークレットとして作成します。
:::
diff --git a/content/zh/index.mdx b/content/zh/index.mdx
index 5b97b8b0b..6cd900afe 100644
--- a/content/zh/index.mdx
+++ b/content/zh/index.mdx
@@ -80,6 +80,15 @@ description: "了解如何安装、配置、管理和维护 RustFS。"
+
+
+
+
+ 使用 SwarmCLI Chart 安装
+ 使用 SwarmCLI 的 rustfs Chart 在 Docker Swarm 上部署单节点或分布式 RustFS。
+
+
+
云服务商
diff --git a/content/zh/installation/cloud-native/meta.json b/content/zh/installation/cloud-native/meta.json
index a72474510..5ec181ab6 100644
--- a/content/zh/installation/cloud-native/meta.json
+++ b/content/zh/installation/cloud-native/meta.json
@@ -2,6 +2,7 @@
"title": "云原生",
"pages": [
"helm-chart",
- "operator"
+ "operator",
+ "swarmcli-chart"
]
}
diff --git a/content/zh/installation/cloud-native/swarmcli-chart.md b/content/zh/installation/cloud-native/swarmcli-chart.md
new file mode 100644
index 000000000..0cbc11382
--- /dev/null
+++ b/content/zh/installation/cloud-native/swarmcli-chart.md
@@ -0,0 +1,294 @@
+---
+title: "SwarmCLI Chart"
+description: "使用 SwarmCLI 的 rustfs Chart 在 Docker Swarm 上部署 RustFS,可部署为单节点服务或采用纠删码的分布式集群:凭证保存在 Docker Secret 中,支持带版本的升级和回滚,并可选择通过 Traefik 启用 HTTPS。"
+---
+
+[SwarmCLI](https://github.com/Eldara-Tech/swarmcli) 是一个受 Helm 启发、面向 Docker Swarm 的包管理器和终端 UI。它的开源 [`rustfs` Chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) 将 RustFS 部署到 Docker Swarm 上。二者均由 Eldara Tech 维护,而非 RustFS 项目。
+
+与手写的 Stack 文件相比,该 Chart 额外提供:
+
+- **凭证保存在 Docker Secret 中。** RustFS 通过 `RUSTFS_ACCESS_KEY_FILE` 和 `RUSTFS_SECRET_KEY_FILE` 从文件中读取根密钥,因此这两个值都不会出现在服务定义或 `docker inspect` 的输出中。默认的 `rustfsadmin` 密钥会被拒绝。
+- **带版本的 Release。** 可以预览升级、应用升级,并回滚到之前的修订版本。SwarmCLI 将修订历史记录保存在 Swarm 自身中,因此无需额外的数据库。
+- **通过 Traefik 启用 HTTPS。** 配合配套的 [`traefik` Chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik),S3 API 和控制台可以获得各自的主机名和 Let's Encrypt 证书,控制台还可以通过 OpenID Connect 使用单点登录。
+- **带健康检查的滚动更新。** 配置值中列出的存储桶会在启动时创建,单机模式 Release 的每次滚动更新都会通过 RustFS 的 `/health/ready` 端点进行监测,因此 `--wait` 会报告出错的升级,而不是报告成功。
+- **集群滚动升级。** 在分布式模式下,升级一次只滚动更新一个对等节点;如果默认的四个对等节点均在运行,集群在整个升级期间会以少一个对等节点的状态持续提供读写服务。
+
+该 Chart 以两种模式之一运行,模式在安装时选择。单机模式为默认模式,在一个节点上运行一个使用单块磁盘的 RustFS 服务(单节点单磁盘,SNSD)。单块磁盘不提供纠删码冗余,因此适用于构建缓存、备份目标和小型 Swarm 上的应用 Blob 存储。分布式模式将对象以纠删码方式分布到四个或更多对等节点上(每个节点一个),适用于必须在丢失一个节点后依然保留的数据。第 4 步安装单机模式,第 5 步安装分布式模式;其他步骤对两种模式均适用。
+
+## 1. 前提条件
+
+* 一个 Docker Swarm(`docker swarm init`),以及管理节点上的 Shell
+* SwarmCLI 2.2.0 或更高版本,请参阅 [SwarmCLI 安装指南](https://github.com/Eldara-Tech/swarmcli/blob/main/docs/installation.md)
+* 单机模式下,Swarm 节点上的 9000 端口(S3 API)未被占用,因为第 4 步会在 Swarm 路由网格上发布该端口
+* 分布式模式下,每个对等节点各需一个节点,至少四个(用于开发时单个节点即可;请参阅第 5 步)
+
+## 2. 将凭证创建为 Docker Secret
+
+替换凭证占位符,然后为每个密钥创建一个 Secret:
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key -
+printf '%s' '' | docker secret create rustfs-secret-key -
+```
+
+每个值都应位于一行内,且内部不含空白字符。例如,可以使用 `openssl rand -base64 30` 生成高强度的秘密密钥。在分布式模式下,每个对等节点都读取同样的这两个 Secret。
+
+:::warning[服务会拒绝弱凭证]
+
+只要任一 Secret 缺失,SwarmCLI 就会拒绝安装该 Chart;如果某个密钥为空、包含空白字符或是众所周知的 `rustfsadmin` 值,容器会在启动时退出。Docker Secret 无法修改:如需轮换凭证,请以新名称创建 Secret,然后在升级该 Release 时将 `s3.accessKeySecret` 和 `s3.secretKeySecret` 指向它们。在分布式模式下,轮换需要完全停机,如“升级与回滚”一节所述。
+
+:::
+
+## 3. 添加 Chart 仓库
+
+如果 `swarmcli charts repo list` 已显示 `swarmcli-charts`,请跳过此步骤:
+
+```bash
+swarmcli charts repo add swarmcli-charts https://eldara-tech.github.io/swarmcli-charts
+```
+
+## 4. 安装单机模式
+
+此步骤与第 5 步二选一,不要同时执行。命名卷只存在于一个节点上,因此服务会被固定到带有 `rustfs-data=true` 标签的节点。请只为一个节点添加该标签:
+
+```bash
+docker node update --label-add rustfs-data=true
+```
+
+在单节点 Swarm 上,可以跳过标签,改为在下面的安装命令中添加 `--set persistence.nodeLabel=""`。
+
+将该 Chart 安装为名为 `rustfs` 的 Release,在 9000 端口发布 S3 API,并在启动时创建一个存储桶:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+服务将数据保存在 `rustfs-data` 命名卷的 `/data` 下,Docker 会以 Release 名称为前缀将其命名为 `rustfs_rustfs-data`。`buckets` 中的每个存储桶会在服务器开始响应后创建;已存在的存储桶保持不变,因此重启和升级都是安全的。
+
+## 5. 安装分布式模式
+
+请执行此步骤,而不是第 4 步。在分布式模式下,每个对等节点都是一个独立的 Swarm 服务(对于名为 `rustfs` 的 Release,为 `rustfs_rustfs-1` 到 `rustfs_rustfs-4`),各自拥有一个副本、自己的卷和自己的节点标签。为每个对等节点各标记一个节点:
+
+```bash
+docker node update --label-add rustfs-1=true
+docker node update --label-add rustfs-2=true
+docker node update --label-add rustfs-3=true
+docker node update --label-add rustfs-4=true
+```
+
+请将每个对等节点放在不同的节点上:共享同一节点的对等节点会随该节点一同失效;采用默认的四个对等节点时,丢失一个承载两个对等节点的节点会导致写入停止。在单节点 Swarm 上,为这一个节点添加全部四个标签;这仅适用于开发,因为这种方式无法提供任何可用性保障。
+
+请显式设置模式和集群结构。磁盘总数等于 `cluster.peers * cluster.drivesPerPeer`。
+
+:::warning[安装前选择拓扑]
+
+`cluster.peers` 和 `cluster.drivesPerPeer` 在安装时即已固定:RustFS 会在每块磁盘上记录磁盘数量和纠删集宽度,使用其他值时会拒绝启动。`mode` 同样在安装时选择。在现有 Release 上更改它不会转换数据:新模式的服务会在空磁盘上启动,旧模式的服务会继续在旁边运行,客户端会访问到两者。要将单机模式的存储迁移到集群,请将集群安装为第二个 Release,并通过 S3 将存储桶复制过去。
+
+:::
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+buckets:
+ - my-bucket
+```
+
+该示例创建四个对等节点,每个对等节点一块磁盘。每个对象会拆分为两个数据分片和两个校验分片,因此读取可容忍两个对等节点宕机,写入可容忍一个,可用容量为磁盘总容量的一半。每个对等节点使用多于一块磁盘时需要 `persistence.volumePaths`,每块磁盘对应一个主机目录,且各自位于独立的物理磁盘上;Chart README 对此有说明。使用该配置值文件安装 Chart:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+所有对等节点会同时启动。当每个对等节点的任务都在运行,且运行时间已超过其两分钟的监控窗口时,`--wait` 就会返回。对等节点 1 会在集群接受写入后创建存储桶;如果在启动后五分钟内仍无法创建,它会记录未能创建的存储桶(可通过 `docker service logs rustfs_rustfs-1` 查看),并继续提供服务。对等节点的健康检查只能表明该对等节点存活,因此 `--wait` 无法表明集群是否在提供服务;第 6 步会检查这一点。
+
+## 6. 验证部署
+
+在单机模式下,检查 Release、服务任务和 S3 API 就绪端点:
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs
+curl --fail http://localhost:9000/health/ready
+```
+
+S3 API 在每个 Swarm 节点上均可通过 `http://localhost:9000` 访问。客户端使用路径式寻址和区域 `us-east-1`。如果任务一直处于 pending 状态并显示 `no suitable node`,说明没有节点带有第 4 步中的 `rustfs-data=true` 标签。
+
+在分布式模式下,检查 Release 和各对等节点的任务,然后从 `rustfs-net` 覆盖网络上的一个容器中查询集群是否在提供服务:
+
+```bash
+swarmcli charts status rustfs
+docker service ps rustfs_rustfs-1 rustfs_rustfs-2 rustfs_rustfs-3 rustfs_rustfs-4
+docker run --rm --network rustfs-net curlimages/curl -s -o /dev/null -w '%{http_code}\n' \
+ http://rustfs-rustfs:9000/minio/health/cluster
+```
+
+`200` 表示每个纠删集都达到写入法定数量。如果某个对等节点的任务一直处于 pending 状态并显示 `no suitable node`,说明没有节点带有第 5 步中该对等节点的 `rustfs-=true` 标签。添加标签后,该对等节点就会启动;如果之后对等节点 1 的日志报告了未能创建的存储桶,请重启对等节点 1 以再次创建存储桶:`docker service update --force rustfs_rustfs-1`。
+
+加入 `rustfs-net` 的服务通过 `http://rustfs-rustfs:9000` 访问集群,使用路径式寻址和区域 `us-east-1`。任一对等节点都能提供所有对象,该名称会解析到每个健康检查通过的对等节点。该检查只能表明对等节点存活,因此在首次安装时,或在所有对等节点都停止之后,对等节点可能会返回 503,直到集群开始提供服务。正在发往某个对等节点的请求在该对等节点停止时也会失败。客户端必须重试,S3 客户端默认会这样做。要从 Swarm 外部访问集群,请按“暴露模式”一节所述将其暴露。
+
+## 升级与回滚
+
+每次安装、升级和回滚都会为该 Release 创建一个带编号的修订版本。升级会从 Chart 的默认值开始,因此请重新传入所有配置值(如果在第 4 步中使用了 `--set persistence.nodeLabel=""`,也要一并传入),或者将配置值保存在文件中并通过 `-f` 传入。对于第 4 步中的单机模式 Release,预览变更、应用变更,并列出修订版本:
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs --wait \
+ --set exposure.mode=published \
+ --set 'buckets={my-bucket,backups}'
+swarmcli charts history rustfs
+```
+
+要恢复到之前的修订版本:
+
+```bash
+swarmcli charts rollback rustfs 1
+```
+
+回滚会重新部署该修订版本的服务定义,但不会恢复数据。
+
+在分布式模式下,请在每次升级时传入安装时使用的配置值文件,而不是使用 `--reuse-values`,并将之后的变更(例如暴露设置)写入该文件。配置值中缺少 `mode: distributed` 的升级会保持对等节点不变,并在它们旁边启动一个单机模式服务。
+
+SwarmCLI 逐个更新对等节点:它停止一个对等节点,启动其新任务,并且只有在该任务运行且运行时间已超过其监控窗口后,才会转到下一个对等节点。如果默认的四个对等节点均在运行,集群在整个升级期间会以少一个对等节点的状态持续提供读写服务;如果已有一个对等节点宕机,则每当升级停止另一个对等节点时,集群都会停止接受写入。因此,请先使用第 6 步中的命令确认每个对等节点的任务都在运行,且集群返回 `200`;仅凭 `200` 并不能表明每个对等节点都在运行。然后预览并应用升级,之后再次检查集群:
+
+```bash
+swarmcli charts diff upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+回滚也会以相同方式滚动更新对等节点。如果升级中某个对等节点启动失败,升级会在此停止,其余对等节点保持不变。
+
+:::warning[轮换集群凭证需要完全停机]
+
+每个对等节点都从凭证对派生其节点间密钥,因此使用旧凭证对的对等节点与使用新凭证对的对等节点无法互相访问,一次只滚动更新一个对等节点的升级会导致集群分裂。创建新的 Secret:
+
+```bash
+printf '%s' '' | docker secret create rustfs-access-key-2 -
+printf '%s' '' | docker secret create rustfs-secret-key-2 -
+```
+
+将这两个 Secret 名称添加到 `distributed-values.yaml` 中,以便之后的升级保留它们。基于第 5 步中的配置值,该文件随后如下所示:
+
+```yaml title="distributed-values.yaml"
+mode: distributed
+
+cluster:
+ peers: 4
+ drivesPerPeer: 1
+
+s3:
+ accessKeySecret: rustfs-access-key-2
+ secretKeySecret: rustfs-secret-key-2
+
+buckets:
+ - my-bucket
+```
+
+然后停止所有对等节点并执行升级,使所有对等节点使用新凭证对同时启动:
+
+```bash
+for n in 1 2 3 4; do docker service scale "rustfs_rustfs-$n=0"; done
+swarmcli charts upgrade rustfs swarmcli-charts/rustfs -f distributed-values.yaml --wait
+```
+
+数据和存储桶会保留下来;客户端需要使用新凭证对。不要回滚到轮换之前的修订版本:回滚会逐个将对等节点切换回旧凭证对,同样会导致集群分裂。
+
+:::
+
+## 暴露模式
+
+该 Chart 分别暴露 S3 API 和控制台。控制台默认关闭,可通过 `console.enabled=true` 启用。S3 API 的模式由 `exposure.mode` 设置,控制台的模式由 `console.exposure.mode` 设置:
+
+| 模式 | 可访问范围 |
+| - | - |
+| `none`(默认) | 连接到 `rustfs-net` 覆盖网络的服务,地址为 `http://-rustfs:9000`(控制台启用后位于 9001 端口);另一个监听器使用 `traefik` 时,`traefik-public` 上的服务也可访问 |
+| `published` | 发布的端口:S3 API 使用 `publish.port`,控制台使用 `console.publish.port`(9001),发布在 Swarm 路由网格上(在分布式模式下,发布在每个对等节点自身所在的节点上) |
+| `traefik` | 由 Traefik 通过 HTTPS 路由的主机名:S3 API 使用 `ingress.host`,控制台使用 `console.ingress.host` |
+
+`traefik` 模式需要先安装 [`traefik` Chart](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/traefik):它会创建 RustFS 所加入的 `traefik-public` 网络,并获取 Let's Encrypt 证书。然后让单机模式 Release 的 S3 API 通过自己的主机名对外提供服务:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=traefik \
+ --set ingress.host=s3.example.com \
+ --set 'buckets={my-bucket}'
+```
+
+不使用 Traefik 时,可以在发布 S3 API 的同时,在 9001 端口发布单机模式 Release 的控制台:
+
+```bash
+swarmcli charts install rustfs swarmcli-charts/rustfs \
+ --set exposure.mode=published \
+ --set console.enabled=true \
+ --set console.exposure.mode=published \
+ --set 'buckets={my-bucket}'
+```
+
+:::note[控制台端口同样提供 S3 API]
+
+控制台监听器同样提供完整的签名 S3 API 和管理 API,因此即使只暴露控制台,也会将这些 API 置于公开地址上。不使用控制台时,请保持其关闭。
+
+:::
+
+在分布式模式下,每个对等节点都使用相同的暴露设置;请在 `distributed-values.yaml` 中设置它们,然后按“升级与回滚”一节所述执行升级。使用 `traefik` 时,Traefik 会在所有健康的对等节点之间均衡请求。`published` 模式需要 `publish.mode=host`(控制台还需要 `console.publish.mode=host`),它会在每个对等节点自身所在的节点上发布端口,而不是在路由网格上发布,因此某个节点的端口只能访问该节点上的对等节点。请在这些节点前部署负载均衡器,或使用 Traefik。主机模式发布要求每个对等节点各自位于独立的节点上,因此单节点 Swarm 无法使用它。
+
+## 关键配置值
+
+| 配置值 | 用途 | Chart 默认值 |
+| - | - | - |
+| `image.tag` | RustFS 镜像标签 | `""`(Chart 固定的 RustFS 版本) |
+| `mode` | `standalone` 或 `distributed`,在安装时选择 | `standalone` |
+| `cluster.peers` | 分布式模式的对等节点数,每个对应一个服务和一个节点标签;至少为 4 | `4` |
+| `cluster.drivesPerPeer` | 每个分布式对等节点的磁盘数;多于一块时需要 `persistence.volumePaths` | `1` |
+| `s3.accessKeySecret` / `s3.secretKeySecret` | 保存根凭证的 Docker Secret | `rustfs-access-key` / `rustfs-secret-key` |
+| `buckets` | 启动时创建的存储桶(若尚不存在) | `[]` |
+| `exposure.mode` | S3 API 暴露方式:`none`、`published` 或 `traefik` | `none` |
+| `publish.port` | 发布的 S3 API 端口 | `9000` |
+| `ingress.host` | Traefik 路由到 S3 API 的主机名 | `s3.example.com` |
+| `console.enabled` | 运行控制台监听器 | `false` |
+| `console.exposure.mode` | 控制台暴露方式:`none`、`published` 或 `traefik` | `none` |
+| `persistence.nodeLabel` | 单机模式服务固定到的节点标签;`""` 表示不固定 | `rustfs-data` |
+| `persistence.nodeLabelPrefix` | 将分布式对等节点 `` 固定到 `-` 的节点标签前缀;`""` 表示不固定,仅适用于单节点 Swarm | `rustfs` |
+| `persistence.volumePath` | 在单机模式下以绑定挂载方式挂载到 `/data` 的主机目录,用于代替命名卷;所有者必须为 `10001` | `""` |
+| `extraEnv` | 额外的 `RUSTFS_*` 环境变量,例如 `RUSTFS_SERVER_DOMAINS` | `{}` |
+
+[Chart README](https://github.com/Eldara-Tech/swarmcli-charts/tree/main/charts/rustfs) 记录了所有配置值,包括 Traefik 路由、通过 OpenID Connect 为控制台配置单点登录,以及两种模式的主机目录绑定挂载。
+
+## 卸载
+
+```bash
+swarmcli charts uninstall rustfs
+```
+
+卸载会删除服务(在分布式模式下为每个对等节点的服务)和 Release 历史记录,但会保留数据卷(在分布式模式下每个对等节点一个)、两个 Docker Secret 和 `rustfs-net` 网络;SwarmCLI 会列出该网络及其删除命令。
+
+:::note[数据卷在卸载后仍会保留]
+
+在单机模式下,之后以相同 Release 名称重新安装时,会重新挂载该卷及其中的数据。如需丢弃数据,请在任务停止后(最多 30 秒)在带标签的节点上删除该卷:
+
+```bash
+docker volume rm rustfs_rustfs-data
+```
+
+在分布式模式下,每个对等节点都在带有 `rustfs-=true` 标签的节点上保留自己的卷 `rustfs_rustfs-data-`;请在该对等节点的任务停止后,在该节点上删除它。之后以相同 Release 名称重新安装时会复用这些卷,因此必须保持相同的 `cluster.peers` 和 `cluster.drivesPerPeer`。
+
+无论哪种模式,如果不再需要这些 Secret,请将其删除:包括该 Release 使用的一对 Secret,以及被轮换替换下来的任何一对 Secret。以第 2 步中的名称为例:
+
+```bash
+docker secret rm rustfs-access-key rustfs-secret-key
+```
+
+:::
+
+## 后续步骤
+
+- [RustFS 控制台](/administration/console)
+- [配置 S3 客户端](../../developer/examples/aws-cli.md)
+- [安装前检查清单](../requirement/checklists/index.md)
diff --git a/content/zh/installation/index.md b/content/zh/installation/index.md
index 1a0d0a337..b28a52ba1 100644
--- a/content/zh/installation/index.md
+++ b/content/zh/installation/index.md
@@ -17,6 +17,7 @@ Windows 版本的 RustFS 仅适用于开发和调试,**不建议用于生产
- 对于 Linux 二进制文件或 systemd 安装,请在 `/etc/default/rustfs` 中设置这两个值,然后重启 `rustfs` 服务。
- 对于 Docker、Podman 或 Docker Compose,请在创建容器时将这两个值作为容器环境变量传入。如果现有容器启动时未设置这些值,请重新创建该容器。
+- 对于 Docker Swarm,请在安装 Chart 前将这两个值创建为 Docker Secret。
:::
diff --git a/src/app.css b/src/app.css
index 73f77a191..5310c1b53 100644
--- a/src/app.css
+++ b/src/app.css
@@ -206,6 +206,10 @@ article:has(.rustfs-install-home) > h1 + p + div {
--rustfs-brand-color: #f28e1e;
}
+.rustfs-install-icon--swarmcli {
+ --rustfs-brand-color: #3b82f6;
+}
+
.rustfs-install-copy {
display: flex;
min-width: 0;
@@ -420,3 +424,7 @@ article:has(.rustfs-install-home) > h1 + p + div {
.dark .rustfs-install-icon--windows {
--rustfs-brand-color: #4bb4ff;
}
+
+.dark .rustfs-install-icon--swarmcli {
+ --rustfs-brand-color: #60a5fa;
+}
diff --git a/src/components/brand-logo.tsx b/src/components/brand-logo.tsx
index bcf222971..b7006e530 100644
--- a/src/components/brand-logo.tsx
+++ b/src/components/brand-logo.tsx
@@ -1,6 +1,7 @@
"use client";
import { FaApple, FaLinux, FaWindows } from "react-icons/fa6";
+import { LuTerminal } from "react-icons/lu";
import { SiDocker, SiHelm, SiKubernetes, SiPodman } from "react-icons/si";
// Brand marks for providers that are not covered by react-icons. Both are the
@@ -79,6 +80,7 @@ const logos = {
linux: FaLinux,
podman: SiPodman,
sealos: SealosLogo,
+ swarmcli: LuTerminal,
windows: FaWindows,
} as const;