From 7d9350ad652fbf34c1a1e4912cad40b2f2762e8e Mon Sep 17 00:00:00 2001 From: dev-luigi <70869541+dev-luigi@users.noreply.github.com> Date: Tue, 6 Oct 2026 17:19:57 +0200 Subject: [PATCH 1/2] docs: add the 'Updating from the web UI' guide in all languages A page per language on installing a release from the browser: what the button does for each install method, the backup made first, the requirements, setting up Watchtower for Docker, and what to do when an install fails. The Updating page points to it, and its version check no longer uses the health endpoint, which returns only the status now. --- de/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ de/updating.mdx | 10 ++--- docs.json | 24 +++++------ en/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ en/updating.mdx | 10 ++--- es/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ es/updating.mdx | 10 ++--- fr/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ fr/updating.mdx | 10 ++--- it/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ it/updating.mdx | 10 ++--- ja/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ ja/updating.mdx | 10 ++--- ko/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ ko/updating.mdx | 10 ++--- nl/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ nl/updating.mdx | 10 ++--- pl/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ pl/updating.mdx | 10 ++--- pt/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ pt/updating.mdx | 10 ++--- ru/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ ru/updating.mdx | 10 ++--- zh-Hans/update-from-web-ui.mdx | 77 ++++++++++++++++++++++++++++++++++ zh-Hans/updating.mdx | 10 ++--- 25 files changed, 996 insertions(+), 72 deletions(-) create mode 100644 de/update-from-web-ui.mdx create mode 100644 en/update-from-web-ui.mdx create mode 100644 es/update-from-web-ui.mdx create mode 100644 fr/update-from-web-ui.mdx create mode 100644 it/update-from-web-ui.mdx create mode 100644 ja/update-from-web-ui.mdx create mode 100644 ko/update-from-web-ui.mdx create mode 100644 nl/update-from-web-ui.mdx create mode 100644 pl/update-from-web-ui.mdx create mode 100644 pt/update-from-web-ui.mdx create mode 100644 ru/update-from-web-ui.mdx create mode 100644 zh-Hans/update-from-web-ui.mdx diff --git a/de/update-from-web-ui.mdx b/de/update-from-web-ui.mdx new file mode 100644 index 0000000..a952bee --- /dev/null +++ b/de/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Aktualisierung über die Weboberfläche" +description: "Installieren Sie eine neue ipmideck-Version im Browser, und richten Sie Docker-Installationen dafür mit Watchtower ein." +--- + +Sobald eine neuere Version veröffentlicht ist, zeigt ipmideck einmalig eine Benachrichtigung an, und neben der Version in der Seitenleiste bleibt eine Update-Schaltfläche sichtbar, bis Sie sie installieren: ein Pfeil nach oben, bei einer Sicherheitsversion ein Schild. Beide öffnen die Versionshinweise der neuen Version und, wenn ipmideck sie selbst installieren kann, die Schaltfläche **Herunterladen und installieren**. + +## Was die Schaltfläche tut + +Bevor etwas geändert wird, sichert ipmideck die Datenbank, den Verschlüsselungsschlüssel und `config.yaml` nach `backups/` im [Datenverzeichnis](/de/configuration#wo-die-konfiguration-liegt). + +| Installiert mit | Ergebnis | +| --- | --- | +| pip in einer virtuellen Umgebung, pipx, uv | Installiert die neue Version und startet ipmideck neu. Die Seite lädt automatisch neu, sobald die neue Version läuft. | +| pip, pipx oder uv unter Windows | ipmideck wird beendet, damit das Update installiert werden kann; danach starten Sie es erneut. Der Fortschritt wird in `update.log` im Datenverzeichnis protokolliert. | +| Docker mit Watchtower | Watchtower lädt das neue Image und ersetzt den Container. Die Seite lädt automatisch neu. | +| Docker ohne Watchtower | Der Dialog zeigt den Befehl, der auf dem Docker-Host auszuführen ist. | +| git-Checkout, System-Python, editierbare Installation | Der Dialog nennt den Grund und zeigt den auszuführenden Befehl; ein vom System verwaltetes Python wird so aktualisiert, wie es installiert wurde. | + +## Voraussetzungen + +- Die Anmeldung muss aktiviert sein: Die Schaltfläche ersetzt das laufende Programm. +- Im Demo-Modus ist die Schaltfläche nicht verfügbar. +- Für einen automatischen Neustart muss ipmideck mit dem Befehl `ipmideck` gestartet worden sein. Wurde es anders gestartet, installiert es das Update und fordert Sie zum Neustart auf; unter Windows zeigt es stattdessen den Befehl an. + +## Docker mit Watchtower + +Ein Container kann sein eigenes Image nicht ersetzen, und Zugriff auf den Docker-Socket würde ipmideck die Kontrolle über den Host geben. Ein separater [Watchtower](https://github.com/nicholas-fedor/watchtower)-Container übernimmt den Austausch, wenn ipmideck ihn anfordert. + + + + Starten Sie ipmideck mit dem Label, das Watchtower die Verwaltung erlaubt: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Starten Sie Watchtower mit aktivierter HTTP-API, nur vom Host aus erreichbar: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + Dieselben Einstellungen gibt es als `IPMIDECK_UPDATES_WATCHTOWER_URL` und `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. Mit Docker Compose, wo beide Container ein Netzwerk teilen, verwenden Sie `http://watchtower:8080` als Adresse. + + + + + Watchtower steuert Docker über dessen Socket. Verwenden Sie ein langes, zufälliges Token und binden Sie den Port wie gezeigt an `127.0.0.1`. + + + + Watchtower lädt das Tag, das der Container bereits verwendet. Mit `latest` wechselt es zur neuesten Version; ein auf ein Versions-Tag festgelegter Container (zum Beispiel `2.0.0`) bleibt auf dieser Version. + + +## Wenn die Installation fehlschlägt + +Der Dialog zeigt den Grund und die Ausgabe des Installers sowie den Befehl für eine manuelle Installation. Es wird nichts entfernt: Die vor der Installation erstellte Sicherung liegt in `backups/`, und [Sicherung & Wiederherstellung](/de/backup-restore) erklärt, wie Sie sie wiederherstellen. + +## Nächste Schritte + +- [ipmideck aktualisieren](/de/updating): Aktualisierung über die Befehlszeile. +- [Sicherung & Wiederherstellung](/de/backup-restore): Sichern Sie Ihre Daten vor einem Upgrade. diff --git a/de/updating.mdx b/de/updating.mdx index 599a1cf..ea64877 100644 --- a/de/updating.mdx +++ b/de/updating.mdx @@ -7,6 +7,10 @@ Ein Upgrade von ipmideck ersetzt die Anwendung, nicht Ihre Daten. Ihre `config.y und Ihr Verschlüsselungsschlüssel liegen im [Datenverzeichnis](/de/configuration#wo-die-konfiguration-liegt), das über ein Upgrade hinweg erhalten bleibt, sodass Ihre Server, Ihr Verlauf und Ihre Einstellungen übernommen werden. + + Sie können eine neue Version auch im Browser installieren: siehe [Aktualisierung über die Weboberfläche](/de/update-from-web-ui). + + ## Docker Ziehen Sie das neue Image und erstellen Sie den Container mit demselben Daten-Volume neu: @@ -60,11 +64,7 @@ Datenbank nicht. ## Ihre Version prüfen Die laufende Version wird im Dashboard angezeigt, und die Konsole gibt sie in der Credits-Zeile -unter dem Banner aus (zum Beispiel `v2.0.0`). Sie können sie auch über den Health-Endpunkt auslesen: - -```bash -curl http://:3000/api/health -``` +unter dem Banner aus (zum Beispiel `v2.0.0`). In der Weboberfläche steht sie neben dem Logo in der Seitenleiste; ein Klick darauf öffnet den Versionsverlauf. Erstellen Sie vor einem größeren Upgrade eine [Sicherung](/de/backup-restore). Die Wiederherstellung diff --git a/docs.json b/docs.json index c4178b8..dbef43d 100644 --- a/docs.json +++ b/docs.json @@ -21,7 +21,7 @@ }, { "group": "Running", - "pages": ["en/running", "en/updating"] + "pages": ["en/running", "en/updating", "en/update-from-web-ui"] }, { "group": "Configuration", @@ -66,7 +66,7 @@ }, { "group": "Esecuzione", - "pages": ["it/running", "it/updating"] + "pages": ["it/running", "it/updating", "it/update-from-web-ui"] }, { "group": "Configurazione", @@ -111,7 +111,7 @@ }, { "group": "Ausführen", - "pages": ["de/running", "de/updating"] + "pages": ["de/running", "de/updating", "de/update-from-web-ui"] }, { "group": "Konfiguration", @@ -156,7 +156,7 @@ }, { "group": "Ejecución", - "pages": ["es/running", "es/updating"] + "pages": ["es/running", "es/updating", "es/update-from-web-ui"] }, { "group": "Configuración", @@ -201,7 +201,7 @@ }, { "group": "Exécution", - "pages": ["fr/running", "fr/updating"] + "pages": ["fr/running", "fr/updating", "fr/update-from-web-ui"] }, { "group": "Configuration", @@ -246,7 +246,7 @@ }, { "group": "実行", - "pages": ["ja/running", "ja/updating"] + "pages": ["ja/running", "ja/updating", "ja/update-from-web-ui"] }, { "group": "設定", @@ -291,7 +291,7 @@ }, { "group": "실행", - "pages": ["ko/running", "ko/updating"] + "pages": ["ko/running", "ko/updating", "ko/update-from-web-ui"] }, { "group": "구성", @@ -336,7 +336,7 @@ }, { "group": "Draaien", - "pages": ["nl/running", "nl/updating"] + "pages": ["nl/running", "nl/updating", "nl/update-from-web-ui"] }, { "group": "Configuratie", @@ -381,7 +381,7 @@ }, { "group": "Uruchamianie", - "pages": ["pl/running", "pl/updating"] + "pages": ["pl/running", "pl/updating", "pl/update-from-web-ui"] }, { "group": "Konfiguracja", @@ -426,7 +426,7 @@ }, { "group": "Execução", - "pages": ["pt/running", "pt/updating"] + "pages": ["pt/running", "pt/updating", "pt/update-from-web-ui"] }, { "group": "Configuração", @@ -471,7 +471,7 @@ }, { "group": "Запуск", - "pages": ["ru/running", "ru/updating"] + "pages": ["ru/running", "ru/updating", "ru/update-from-web-ui"] }, { "group": "Конфигурация", @@ -516,7 +516,7 @@ }, { "group": "运行", - "pages": ["zh-Hans/running", "zh-Hans/updating"] + "pages": ["zh-Hans/running", "zh-Hans/updating", "zh-Hans/update-from-web-ui"] }, { "group": "配置", diff --git a/en/update-from-web-ui.mdx b/en/update-from-web-ui.mdx new file mode 100644 index 0000000..9b55271 --- /dev/null +++ b/en/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Updating from the web UI" +description: "Install a new ipmideck release from the browser, and set up Docker installs to do the same with Watchtower." +--- + +When a newer version is published, ipmideck shows a notification once, and an upgrade button stays next to the version in the sidebar until you install it: an arrow pointing up, or a shield for a security release. Both open the release notes of the new version and, when ipmideck can install it itself, a **Download and install** button. + +## What the button does + +Before changing anything, ipmideck backs up the database, the encryption key, and `config.yaml` to `backups/` in the [data directory](/en/configuration#where-config-lives). + +| Installed with | Result | +| --- | --- | +| pip in a virtual environment, pipx, uv | Installs the new version and restarts ipmideck. The page reloads by itself when the new version is running. | +| pip, pipx, or uv on Windows | ipmideck stops so the update can be installed, then you start it again. Progress is written to `update.log` in the data directory. | +| Docker with Watchtower | Watchtower pulls the new image and replaces the container. The page reloads by itself. | +| Docker without Watchtower | The dialog shows the command to run on the Docker host. | +| git checkout, system Python, editable install | The dialog explains why and shows the command to run; a Python managed by the system is updated the way it was installed. | + +## Requirements + +- The login must be on: the button replaces the running program. +- The button is not available in demo mode. +- To restart by itself, ipmideck must have been started with the `ipmideck` command. Started any other way, it installs the update and asks you to restart it; on Windows it shows the command instead. + +## Docker with Watchtower + +A container cannot replace its own image, and giving ipmideck access to the Docker socket would give it control of the host. A separate [Watchtower](https://github.com/nicholas-fedor/watchtower) container does the replacement when ipmideck asks for it. + + + + Start ipmideck with the label that lets Watchtower manage it: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Start Watchtower with its HTTP API on, reachable only from the host: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + The same settings are available as `IPMIDECK_UPDATES_WATCHTOWER_URL` and `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. With Docker Compose, where both containers share a network, use `http://watchtower:8080` as the address. + + + + + Watchtower controls Docker through its socket. Use a long random token, and keep its port bound to `127.0.0.1` as shown. + + + + Watchtower pulls the tag the container already uses. With `latest` it moves to the newest release; a container pinned to a version tag (for example `2.0.0`) stays on it. + + +## If the install fails + +The dialog shows the reason and the installer output, together with the command to install the update manually. Nothing is removed: the backup made before the install is in `backups/`, and [Backup & restore](/en/backup-restore) explains how to restore it. + +## Next steps + +- [Updating ipmideck](/en/updating): update from the command line. +- [Backup & restore](/en/backup-restore): snapshot your data before upgrading. diff --git a/en/updating.mdx b/en/updating.mdx index 0f1fe42..7cb6e39 100644 --- a/en/updating.mdx +++ b/en/updating.mdx @@ -7,6 +7,10 @@ Upgrading ipmideck replaces the application, not your data. Your `config.yaml`, and encryption key live in the [data directory](/en/configuration#where-config-lives), which stays put across an upgrade, so your servers, history, and settings carry over. + + You can also install a new release from the browser: see [Updating from the web UI](/en/update-from-web-ui). + + ## Docker Pull the new image and recreate the container with the same data volume: @@ -60,11 +64,7 @@ or database. ## Check your version The running version shows in the dashboard, and the console prints it in the credits line -under the banner (for example `v2.0.0`). You can also read it from the health endpoint: - -```bash -curl http://:3000/api/health -``` +under the banner (for example `v2.0.0`). In the web UI it sits next to the logo in the sidebar, where selecting it opens the release history. Take a [backup](/en/backup-restore) before a major upgrade. Restoring is then a matter of diff --git a/es/update-from-web-ui.mdx b/es/update-from-web-ui.mdx new file mode 100644 index 0000000..66c8ee5 --- /dev/null +++ b/es/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Actualizar desde la interfaz web" +description: "Instala una nueva versión de ipmideck desde el navegador y configura las instalaciones con Docker para hacerlo con Watchtower." +--- + +Cuando se publica una versión más reciente, ipmideck muestra una notificación una sola vez, y junto a la versión en la barra lateral permanece un botón de actualización hasta que la instalas: una flecha hacia arriba, o un escudo si es una versión de seguridad. Ambos abren las notas de la nueva versión y, cuando ipmideck puede instalarla por sí mismo, el botón **Descargar e instalar**. + +## Qué hace el botón + +Antes de cambiar nada, ipmideck hace una copia de seguridad de la base de datos, la clave de cifrado y `config.yaml` en `backups/` dentro del [directorio de datos](/es/configuration#dónde-reside-la-configuración). + +| Instalado con | Resultado | +| --- | --- | +| pip en un entorno virtual, pipx, uv | Instala la nueva versión y reinicia ipmideck. La página se recarga sola cuando la nueva versión está en marcha. | +| pip, pipx o uv en Windows | ipmideck se detiene para que se instale la actualización y después vuelves a iniciarlo. El progreso se registra en `update.log` en el directorio de datos. | +| Docker con Watchtower | Watchtower descarga la nueva imagen y sustituye el contenedor. La página se recarga sola. | +| Docker sin Watchtower | El diálogo muestra el comando que debes ejecutar en el host de Docker. | +| Checkout de git, Python del sistema, instalación editable | El diálogo explica el motivo y muestra el comando que debes ejecutar; un Python gestionado por el sistema se actualiza igual que se instaló. | + +## Requisitos + +- El inicio de sesión debe estar activado: el botón sustituye el programa en ejecución. +- El botón no está disponible en modo demo. +- Para reiniciarse solo, ipmideck debe haberse iniciado con el comando `ipmideck`. Si se inició de otra forma, instala la actualización y te pide que lo reinicies; en Windows muestra el comando en su lugar. + +## Docker con Watchtower + +Un contenedor no puede sustituir su propia imagen, y dar a ipmideck acceso al socket de Docker le daría el control del host. Un contenedor [Watchtower](https://github.com/nicholas-fedor/watchtower) independiente hace la sustitución cuando ipmideck se lo pide. + + + + Inicia ipmideck con la etiqueta que permite a Watchtower gestionarlo: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Inicia Watchtower con su API HTTP activada y accesible solo desde el host: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + Los mismos ajustes están disponibles como `IPMIDECK_UPDATES_WATCHTOWER_URL` e `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. Con Docker Compose, donde ambos contenedores comparten red, usa `http://watchtower:8080` como dirección. + + + + + Watchtower controla Docker a través de su socket. Usa un token largo y aleatorio, y mantén su puerto ligado a `127.0.0.1` como en el ejemplo. + + + + Watchtower descarga la etiqueta que ya usa el contenedor. Con `latest` pasa a la versión más reciente; un contenedor fijado a una etiqueta de versión (por ejemplo `2.0.0`) se queda en ella. + + +## Si la instalación falla + +El diálogo muestra el motivo y la salida del instalador, junto con el comando para instalar la actualización manualmente. No se elimina nada: la copia de seguridad hecha antes de la instalación está en `backups/`, y [Copia de seguridad y restauración](/es/backup-restore) explica cómo restaurarla. + +## Próximos pasos + +- [Actualizar ipmideck](/es/updating): actualizar desde la línea de comandos. +- [Copia de seguridad y restauración](/es/backup-restore): haz una copia de tus datos antes de actualizar. diff --git a/es/updating.mdx b/es/updating.mdx index e63a1c1..b259579 100644 --- a/es/updating.mdx +++ b/es/updating.mdx @@ -7,6 +7,10 @@ Actualizar ipmideck reemplaza la aplicación, no tus datos. Tu `config.yaml`, la y la clave de cifrado residen en el [directorio de datos](/es/configuration#dónde-reside-la-configuración), que permanece intacto durante una actualización, así que tus servidores, historial y ajustes se conservan. + + También puedes instalar una nueva versión desde el navegador: consulta [Actualizar desde la interfaz web](/es/update-from-web-ui). + + ## Docker Descarga la nueva imagen y recrea el contenedor con el mismo volumen de datos: @@ -60,11 +64,7 @@ ni tu base de datos. ## Comprobar tu versión La versión en ejecución se muestra en el panel, y la consola la imprime en la línea de créditos -bajo el banner (por ejemplo `v2.0.0`). También puedes leerla desde el endpoint de salud: - -```bash -curl http://:3000/api/health -``` +bajo el banner (por ejemplo `v2.0.0`). En la interfaz web aparece junto al logotipo en la barra lateral; al seleccionarla se abre el historial de versiones. Haz una [copia de seguridad](/es/backup-restore) antes de una actualización mayor. Restaurar es entonces cuestión de diff --git a/fr/update-from-web-ui.mdx b/fr/update-from-web-ui.mdx new file mode 100644 index 0000000..95c2d97 --- /dev/null +++ b/fr/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Mise à jour depuis l'interface web" +description: "Installez une nouvelle version d'ipmideck depuis le navigateur, et configurez les installations Docker pour le faire avec Watchtower." +--- + +Lorsqu'une version plus récente est publiée, ipmideck affiche une notification une seule fois, et un bouton de mise à jour reste à côté de la version dans la barre latérale jusqu'à ce que vous l'installiez : une flèche vers le haut, ou un bouclier pour une version de sécurité. Les deux ouvrent les notes de la nouvelle version et, lorsqu'ipmideck peut l'installer lui-même, le bouton **Télécharger et installer**. + +## Ce que fait le bouton + +Avant toute modification, ipmideck sauvegarde la base de données, la clé de chiffrement et `config.yaml` dans `backups/` du [répertoire de données](/fr/configuration#où-réside-la-configuration). + +| Installé avec | Résultat | +| --- | --- | +| pip dans un environnement virtuel, pipx, uv | Installe la nouvelle version et redémarre ipmideck. La page se recharge d'elle-même lorsque la nouvelle version est en service. | +| pip, pipx ou uv sous Windows | ipmideck s'arrête pour que la mise à jour soit installée, puis vous le relancez. La progression est consignée dans `update.log` du répertoire de données. | +| Docker avec Watchtower | Watchtower télécharge la nouvelle image et remplace le conteneur. La page se recharge d'elle-même. | +| Docker sans Watchtower | La boîte de dialogue affiche la commande à exécuter sur l'hôte Docker. | +| Checkout git, Python système, installation modifiable | La boîte de dialogue explique pourquoi et affiche la commande à exécuter ; un Python géré par le système se met à jour de la même façon qu'il a été installé. | + +## Prérequis + +- La connexion doit être activée : le bouton remplace le programme en cours d'exécution. +- Le bouton n'est pas disponible en mode démo. +- Pour redémarrer seul, ipmideck doit avoir été lancé avec la commande `ipmideck`. S'il a été lancé autrement, il installe la mise à jour et vous demande de le redémarrer ; sous Windows, il affiche la commande à la place. + +## Docker avec Watchtower + +Un conteneur ne peut pas remplacer sa propre image, et donner à ipmideck l'accès au socket Docker lui donnerait le contrôle de l'hôte. Un conteneur [Watchtower](https://github.com/nicholas-fedor/watchtower) distinct effectue le remplacement lorsqu'ipmideck le demande. + + + + Lancez ipmideck avec l'étiquette qui permet à Watchtower de le gérer : + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Lancez Watchtower avec son API HTTP activée, accessible uniquement depuis l'hôte : + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck : + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + Les mêmes réglages existent sous la forme `IPMIDECK_UPDATES_WATCHTOWER_URL` et `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. Avec Docker Compose, où les deux conteneurs partagent un réseau, utilisez `http://watchtower:8080` comme adresse. + + + + + Watchtower contrôle Docker par son socket. Utilisez un jeton long et aléatoire, et gardez son port lié à `127.0.0.1` comme dans l'exemple. + + + + Watchtower télécharge l'étiquette déjà utilisée par le conteneur. Avec `latest`, il passe à la version la plus récente ; un conteneur figé sur une étiquette de version (par exemple `2.0.0`) y reste. + + +## Si l'installation échoue + +La boîte de dialogue affiche la raison et la sortie de l'installeur, ainsi que la commande pour installer la mise à jour manuellement. Rien n'est supprimé : la sauvegarde faite avant l'installation se trouve dans `backups/`, et [Sauvegarde et restauration](/fr/backup-restore) explique comment la restaurer. + +## Étapes suivantes + +- [Mettre à jour ipmideck](/fr/updating): mise à jour en ligne de commande. +- [Sauvegarde et restauration](/fr/backup-restore): sauvegardez vos données avant une mise à jour. diff --git a/fr/updating.mdx b/fr/updating.mdx index 8fab6ee..05b6e73 100644 --- a/fr/updating.mdx +++ b/fr/updating.mdx @@ -7,6 +7,10 @@ Mettre à niveau ipmideck remplace l'application, pas vos données. Votre `confi et votre clé de chiffrement résident dans le [répertoire de données](/fr/configuration#où-réside-la-configuration), qui reste en place lors d'une mise à niveau, de sorte que vos serveurs, votre historique et vos réglages sont conservés. + + Vous pouvez aussi installer une nouvelle version depuis le navigateur : voir [Mise à jour depuis l'interface web](/fr/update-from-web-ui). + + ## Docker Récupérez la nouvelle image et recréez le conteneur avec le même volume de données : @@ -60,11 +64,7 @@ ni à votre base de données. ## Vérifier votre version La version en cours d'exécution s'affiche dans le tableau de bord, et la console l'affiche dans la ligne de crédits -sous la bannière (par exemple `v2.0.0`). Vous pouvez aussi la lire depuis le point de terminaison de santé : - -```bash -curl http://:3000/api/health -``` +sous la bannière (par exemple `v2.0.0`). Dans l'interface web, elle figure à côté du logo dans la barre latérale ; la sélectionner ouvre l'historique des versions. Faites une [sauvegarde](/fr/backup-restore) avant une mise à niveau majeure. La restauration consiste alors simplement à diff --git a/it/update-from-web-ui.mdx b/it/update-from-web-ui.mdx new file mode 100644 index 0000000..14a03ea --- /dev/null +++ b/it/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Aggiornamento dall'interfaccia web" +description: "Installa una nuova release di ipmideck dal browser e configura le installazioni Docker per farlo tramite Watchtower." +--- + +Quando viene pubblicata una versione più recente, ipmideck mostra una notifica una sola volta e, finché non la installi, accanto alla versione nella barra laterale resta un pulsante di aggiornamento: una freccia verso l'alto, oppure uno scudo per una release di sicurezza. Entrambi aprono le note di rilascio della nuova versione e, quando ipmideck può installarla autonomamente, il pulsante **Scarica e installa**. + +## Cosa fa il pulsante + +Prima di qualsiasi modifica, ipmideck esegue un backup del database, della chiave di cifratura e di `config.yaml` in `backups/` nella [directory dati](/it/configuration#dove-vive-la-configurazione). + +| Metodo di installazione | Risultato | +| --- | --- | +| pip in un ambiente virtuale, pipx, uv | Installa la nuova versione e riavvia ipmideck. La pagina si ricarica automaticamente quando la nuova versione è in esecuzione. | +| pip, pipx o uv su Windows | ipmideck si arresta per consentire l'installazione; al termine va avviato di nuovo. L'avanzamento è registrato in `update.log` nella directory dati. | +| Docker con Watchtower | Watchtower scarica la nuova immagine e sostituisce il container. La pagina si ricarica automaticamente. | +| Docker senza Watchtower | La finestra mostra il comando da eseguire sull'host Docker. | +| Checkout git, Python di sistema, installazione modificabile | La finestra spiega il motivo e mostra il comando da eseguire; un Python gestito dal sistema si aggiorna con lo stesso metodo usato per installarlo. | + +## Requisiti + +- Il login deve essere attivo: il pulsante sostituisce il programma in esecuzione. +- Il pulsante non è disponibile in modalità demo. +- Per riavviarsi automaticamente, ipmideck deve essere stato avviato con il comando `ipmideck`. Se è stato avviato in altro modo, installa l'aggiornamento e chiede di riavviarlo; su Windows mostra invece il comando. + +## Docker con Watchtower + +Un container non può sostituire la propria immagine, e concedere a ipmideck l'accesso al socket Docker gli darebbe il controllo dell'host. Un container [Watchtower](https://github.com/nicholas-fedor/watchtower) separato esegue la sostituzione quando ipmideck lo richiede. + + + + Avvia ipmideck con l'etichetta che consente a Watchtower di gestirlo: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Avvia Watchtower con l'API HTTP attiva, raggiungibile solo dall'host: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + Le stesse impostazioni sono disponibili come `IPMIDECK_UPDATES_WATCHTOWER_URL` e `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. Con Docker Compose, dove i due container condividono una rete, usa `http://watchtower:8080` come indirizzo. + + + + + Watchtower controlla Docker attraverso il suo socket. Usa un token lungo e casuale e mantieni la porta associata a `127.0.0.1` come nell'esempio. + + + + Watchtower scarica il tag già usato dal container. Con `latest` passa alla release più recente; un container fissato a un tag di versione (per esempio `2.0.0`) resta su quella versione. + + +## Se l'installazione non riesce + +La finestra mostra il motivo e l'output del programma di installazione, insieme al comando per installare l'aggiornamento manualmente. Non viene rimosso nulla: il backup eseguito prima dell'installazione si trova in `backups/` e [Backup e ripristino](/it/backup-restore) spiega come ripristinarlo. + +## Prossimi passi + +- [Aggiornamento di ipmideck](/it/updating): aggiornamento da riga di comando. +- [Backup e ripristino](/it/backup-restore): esegui un backup dei dati prima di aggiornare. diff --git a/it/updating.mdx b/it/updating.mdx index 5d3db3d..29aeead 100644 --- a/it/updating.mdx +++ b/it/updating.mdx @@ -7,6 +7,10 @@ Aggiornare ipmideck sostituisce l'applicazione, non i tuoi dati. Il tuo `config. e la chiave di cifratura vivono nella [directory dati](/it/configuration#dove-vive-la-configurazione), che resta al suo posto attraverso un aggiornamento, così i tuoi server, lo storico e le impostazioni vengono trasferiti. + + Puoi installare una nuova release anche dal browser: consulta [Aggiornamento dall'interfaccia web](/it/update-from-web-ui). + + ## Docker Scarica la nuova immagine e ricrea il container con lo stesso volume dati: @@ -60,11 +64,7 @@ o il database. ## Controlla la tua versione La versione in esecuzione compare nella dashboard, e la console la stampa nella riga dei crediti -sotto il banner (per esempio `v2.0.0`). Puoi anche leggerla dall'endpoint di health: - -```bash -curl http://:3000/api/health -``` +sotto il banner (per esempio `v2.0.0`). Nell'interfaccia web si trova accanto al logo nella barra laterale; selezionandola si apre la cronologia delle release. Fai un [backup](/it/backup-restore) prima di un aggiornamento importante. Ripristinare è poi solo una questione di diff --git a/ja/update-from-web-ui.mdx b/ja/update-from-web-ui.mdx new file mode 100644 index 0000000..de581aa --- /dev/null +++ b/ja/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Web UI からの更新" +description: "ブラウザーから ipmideck の新しいリリースをインストールする方法と、Docker で Watchtower を使って同じことを行う設定。" +--- + +新しいバージョンが公開されると、ipmideck は通知を 1 回だけ表示し、インストールするまでサイドバーのバージョンの横に更新ボタン (上向きの矢印、セキュリティリリースの場合は盾) が表示されます。どちらも新しいバージョンのリリースノートを開き、ipmideck が自分でインストールできる場合は **ダウンロードしてインストール** ボタンも表示されます。 + +## ボタンの動作 + +変更を加える前に、ipmideck はデータベース、暗号化キー、`config.yaml` を [データディレクトリ](/ja/configuration#設定の場所) の `backups/` にバックアップします。 + +| インストール方法 | 結果 | +| --- | --- | +| 仮想環境の pip、pipx、uv | 新しいバージョンをインストールして ipmideck を再起動します。新しいバージョンが動作するとページは自動で再読み込みされます。 | +| Windows の pip、pipx、uv | 更新をインストールするため ipmideck が停止します。完了後にもう一度起動してください。進行状況はデータディレクトリの `update.log` に記録されます。 | +| Docker (Watchtower あり) | Watchtower が新しいイメージを取得してコンテナを置き換えます。ページは自動で再読み込みされます。 | +| Docker (Watchtower なし) | Docker ホストで実行するコマンドがダイアログに表示されます。 | +| git チェックアウト、システムの Python、編集可能インストール | ダイアログに理由と実行するコマンドが表示されます。システム管理の Python は、インストールしたときと同じ方法で更新します。 | + +## 要件 + +- ログインが有効である必要があります。このボタンは実行中のプログラムを置き換えるためです。 +- デモモードではボタンを使用できません。 +- 自動で再起動するには、ipmideck が `ipmideck` コマンドで起動されている必要があります。それ以外の方法で起動した場合は、更新をインストールしたうえで再起動を求めます。Windows では代わりにコマンドを表示します。 + +## Docker と Watchtower + +コンテナは自身のイメージを置き換えられません。また、ipmideck に Docker ソケットへのアクセスを与えるとホストを制御できてしまいます。そこで、別の [Watchtower](https://github.com/nicholas-fedor/watchtower) コンテナが ipmideck の要求に応じて置き換えを行います。 + + + + Watchtower による管理を許可するラベルを付けて ipmideck を起動します: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + HTTP API を有効にし、ホストからのみアクセスできるようにして Watchtower を起動します: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + `config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + 同じ設定は `IPMIDECK_UPDATES_WATCHTOWER_URL` と `IPMIDECK_UPDATES_WATCHTOWER_TOKEN` でも指定できます。両方のコンテナが同じネットワークにある Docker Compose では、アドレスに `http://watchtower:8080` を使用してください。 + + + + + Watchtower はソケットを通じて Docker を制御します。長いランダムなトークンを使用し、例のようにポートを `127.0.0.1` にバインドしてください。 + + + + Watchtower はコンテナが使用しているタグを取得します。`latest` の場合は最新リリースに移行し、バージョンタグ (例: `2.0.0`) に固定したコンテナはそのバージョンのままです。 + + +## インストールに失敗した場合 + +ダイアログに理由とインストーラーの出力、および手動でインストールするためのコマンドが表示されます。何も削除されません。インストール前に作成したバックアップは `backups/` にあり、復元方法は [バックアップと復元](/ja/backup-restore) で説明しています。 + +## 次のステップ + +- [ipmideck の更新](/ja/updating): コマンドラインからの更新。 +- [バックアップと復元](/ja/backup-restore): 更新前にデータのバックアップを作成します。 diff --git a/ja/updating.mdx b/ja/updating.mdx index 164b60f..9b3844f 100644 --- a/ja/updating.mdx +++ b/ja/updating.mdx @@ -7,6 +7,10 @@ ipmideck のアップグレードはアプリケーションを置き換えま データベース、暗号化キーは [データディレクトリー](/ja/configuration#設定の場所) にあり、 アップグレードをまたいでそのまま残るので、サーバー、履歴、設定は引き継がれます。 + + 新しいリリースはブラウザーからもインストールできます。[Web UI からの更新](/ja/update-from-web-ui) を参照してください。 + + ## Docker 新しいイメージをプルし、同じデータボリュームでコンテナーを再作成します。 @@ -60,11 +64,7 @@ ipmideck start ## バージョンの確認 実行中のバージョンはダッシュボードに表示され、コンソールはバナーの下のクレジット行に -それを出力します (例: `v2.0.0`)。ヘルスエンドポイントから読むこともできます。 - -```bash -curl http://:3000/api/health -``` +それを出力します (例: `v2.0.0`)。Web UI ではサイドバーのロゴの横に表示され、選択するとリリース履歴が開きます。 メジャーアップグレードの前に [バックアップ](/ja/backup-restore) を取ってください。何か問題が起きたときの diff --git a/ko/update-from-web-ui.mdx b/ko/update-from-web-ui.mdx new file mode 100644 index 0000000..9f53473 --- /dev/null +++ b/ko/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "웹 UI에서 업데이트" +description: "브라우저에서 ipmideck 새 릴리스를 설치하는 방법과 Docker 설치에서 Watchtower로 같은 작업을 하도록 설정하는 방법입니다." +--- + +새 버전이 게시되면 ipmideck은 알림을 한 번 표시하고, 설치할 때까지 사이드바의 버전 옆에 업데이트 버튼(위쪽 화살표, 보안 릴리스는 방패)이 남아 있습니다. 둘 다 새 버전의 릴리스 노트를 열며, ipmideck이 직접 설치할 수 있으면 **다운로드 및 설치** 버튼도 표시합니다. + +## 버튼이 하는 일 + +변경하기 전에 ipmideck은 데이터베이스, 암호화 키, `config.yaml`을 [데이터 디렉터리](/ko/configuration#구성이-위치하는-곳)의 `backups/`에 백업합니다. + +| 설치 방식 | 결과 | +| --- | --- | +| 가상 환경의 pip, pipx, uv | 새 버전을 설치하고 ipmideck을 다시 시작합니다. 새 버전이 실행되면 페이지가 자동으로 새로 고쳐집니다. | +| Windows의 pip, pipx, uv | 업데이트를 설치할 수 있도록 ipmideck이 중지되며, 이후 다시 실행해야 합니다. 진행 상황은 데이터 디렉터리의 `update.log`에 기록됩니다. | +| Watchtower를 사용하는 Docker | Watchtower가 새 이미지를 받아 컨테이너를 교체합니다. 페이지가 자동으로 새로 고쳐집니다. | +| Watchtower 없는 Docker | Docker 호스트에서 실행할 명령이 대화 상자에 표시됩니다. | +| git 체크아웃, 시스템 Python, 편집 가능 설치 | 대화 상자에 이유와 실행할 명령이 표시됩니다. 시스템이 관리하는 Python은 설치한 방식 그대로 업데이트합니다. | + +## 요구 사항 + +- 로그인이 켜져 있어야 합니다. 이 버튼은 실행 중인 프로그램을 교체하기 때문입니다. +- 데모 모드에서는 버튼을 사용할 수 없습니다. +- 자동으로 다시 시작하려면 ipmideck이 `ipmideck` 명령으로 시작되어야 합니다. 다른 방법으로 시작한 경우 업데이트를 설치한 뒤 다시 시작하라고 안내하며, Windows에서는 대신 명령을 표시합니다. + +## Docker와 Watchtower + +컨테이너는 자신의 이미지를 교체할 수 없으며, ipmideck에 Docker 소켓 접근 권한을 주면 호스트를 제어할 수 있게 됩니다. 대신 별도의 [Watchtower](https://github.com/nicholas-fedor/watchtower) 컨테이너가 ipmideck의 요청에 따라 교체를 수행합니다. + + + + Watchtower가 관리할 수 있도록 레이블을 붙여 ipmideck을 시작합니다: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + HTTP API를 켜고 호스트에서만 접근할 수 있게 Watchtower를 시작합니다: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + `config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + 같은 설정을 `IPMIDECK_UPDATES_WATCHTOWER_URL`과 `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`으로도 지정할 수 있습니다. 두 컨테이너가 같은 네트워크를 쓰는 Docker Compose에서는 주소로 `http://watchtower:8080`을 사용하세요. + + + + + Watchtower는 소켓을 통해 Docker를 제어합니다. 길고 무작위한 토큰을 사용하고, 예시처럼 포트를 `127.0.0.1`에 바인딩하세요. + + + + Watchtower는 컨테이너가 이미 사용 중인 태그를 받아옵니다. `latest`이면 최신 릴리스로 이동하고, 버전 태그(예: `2.0.0`)에 고정된 컨테이너는 그대로 유지됩니다. + + +## 설치에 실패한 경우 + +대화 상자에 원인과 설치 프로그램 출력, 그리고 수동 설치 명령이 표시됩니다. 아무것도 삭제되지 않습니다. 설치 전에 만든 백업은 `backups/`에 있으며, 복원 방법은 [백업 및 복원](/ko/backup-restore)에서 설명합니다. + +## 다음 단계 + +- [ipmideck 업데이트](/ko/updating): 명령줄에서 업데이트합니다. +- [백업 및 복원](/ko/backup-restore): 업데이트 전에 데이터를 백업합니다. diff --git a/ko/updating.mdx b/ko/updating.mdx index 2e3b65b..b0c1c40 100644 --- a/ko/updating.mdx +++ b/ko/updating.mdx @@ -7,6 +7,10 @@ ipmideck 업그레이드는 애플리케이션을 교체하지만 데이터는 데이터베이스, 암호화 키는 [데이터 디렉터리](/ko/configuration#구성이-위치하는-곳)에 있으며, 업그레이드에 걸쳐 그대로 유지되므로 서버, 기록, 설정이 이어집니다. + + 새 릴리스는 브라우저에서도 설치할 수 있습니다. [웹 UI에서 업데이트](/ko/update-from-web-ui)를 참조하세요. + + ## Docker 새 이미지를 풀하고 동일한 데이터 볼륨으로 컨테이너를 다시 만듭니다. @@ -60,11 +64,7 @@ ipmideck start ## 버전 확인 실행 중인 버전은 대시보드에 표시되며, 콘솔은 배너 아래의 크레딧 줄에 그것을 출력합니다 -(예: `v2.0.0`). 상태 엔드포인트에서 읽을 수도 있습니다. - -```bash -curl http://:3000/api/health -``` +(예: `v2.0.0`). 웹 UI에서는 사이드바의 로고 옆에 표시되며, 선택하면 릴리스 기록이 열립니다. 메이저 업그레이드 전에 [백업](/ko/backup-restore)을 받으세요. 그러면 문제가 생겼을 때 복원은 diff --git a/nl/update-from-web-ui.mdx b/nl/update-from-web-ui.mdx new file mode 100644 index 0000000..b58e25e --- /dev/null +++ b/nl/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Bijwerken via de webinterface" +description: "Installeer een nieuwe ipmideck-release vanuit de browser, en stel Docker-installaties in om dat met Watchtower te doen." +--- + +Wanneer er een nieuwere versie is gepubliceerd, toont ipmideck eenmalig een melding, en blijft er naast de versie in de zijbalk een updateknop staan totdat je hem installeert: een pijl omhoog, of een schild bij een beveiligingsrelease. Beide openen de release notes van de nieuwe versie en, als ipmideck hem zelf kan installeren, de knop **Downloaden en installeren**. + +## Wat de knop doet + +Voordat er iets verandert, maakt ipmideck een back-up van de database, de encryptiesleutel en `config.yaml` in `backups/` in de [datamap](/nl/configuration#waar-de-configuratie-staat). + +| Geïnstalleerd met | Resultaat | +| --- | --- | +| pip in een virtuele omgeving, pipx, uv | Installeert de nieuwe versie en herstart ipmideck. De pagina herlaadt vanzelf zodra de nieuwe versie draait. | +| pip, pipx of uv op Windows | ipmideck stopt zodat de update kan worden geïnstalleerd; daarna start je het opnieuw. De voortgang wordt vastgelegd in `update.log` in de datamap. | +| Docker met Watchtower | Watchtower haalt de nieuwe image op en vervangt de container. De pagina herlaadt vanzelf. | +| Docker zonder Watchtower | Het venster toont de opdracht die je op de Docker-host uitvoert. | +| git-checkout, systeem-Python, bewerkbare installatie | Het venster legt uit waarom en toont de opdracht die je uitvoert; een door het systeem beheerde Python werk je bij zoals je hem hebt geïnstalleerd. | + +## Vereisten + +- De login moet aan staan: de knop vervangt het draaiende programma. +- De knop is niet beschikbaar in demomodus. +- Om zelf te herstarten moet ipmideck gestart zijn met het commando `ipmideck`. Is het anders gestart, dan installeert het de update en vraagt het je om het te herstarten; op Windows toont het in plaats daarvan de opdracht. + +## Docker met Watchtower + +Een container kan zijn eigen image niet vervangen, en ipmideck toegang geven tot de Docker-socket zou het de controle over de host geven. Een aparte [Watchtower](https://github.com/nicholas-fedor/watchtower)-container voert de vervanging uit wanneer ipmideck daarom vraagt. + + + + Start ipmideck met het label waarmee Watchtower het mag beheren: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Start Watchtower met de HTTP-API aan, alleen bereikbaar vanaf de host: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + Dezelfde instellingen bestaan als `IPMIDECK_UPDATES_WATCHTOWER_URL` en `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. Met Docker Compose, waar beide containers een netwerk delen, gebruik je `http://watchtower:8080` als adres. + + + + + Watchtower bestuurt Docker via de socket. Gebruik een lang, willekeurig token en houd de poort gebonden aan `127.0.0.1` zoals in het voorbeeld. + + + + Watchtower haalt de tag op die de container al gebruikt. Met `latest` gaat hij naar de nieuwste release; een container die vastzit op een versietag (bijvoorbeeld `2.0.0`) blijft daarop. + + +## Als de installatie mislukt + +Het venster toont de reden en de uitvoer van het installatieprogramma, samen met de opdracht om de update handmatig te installeren. Er wordt niets verwijderd: de back-up van vóór de installatie staat in `backups/`, en [Back-up en herstel](/nl/backup-restore) legt uit hoe je hem terugzet. + +## Volgende stappen + +- [ipmideck bijwerken](/nl/updating): bijwerken via de opdrachtregel. +- [Back-up en herstel](/nl/backup-restore): maak een back-up van je gegevens voordat je bijwerkt. diff --git a/nl/updating.mdx b/nl/updating.mdx index a96201a..dc245f1 100644 --- a/nl/updating.mdx +++ b/nl/updating.mdx @@ -7,6 +7,10 @@ Een upgrade van ipmideck vervangt de applicatie, niet je data. Je `config.yaml`, en versleutelingssleutel staan in de [datamap](/nl/configuration#waar-de-configuratie-staat), die bij een upgrade blijft staan, dus je servers, historie en instellingen blijven behouden. + + Je kunt een nieuwe release ook vanuit de browser installeren: zie [Bijwerken via de webinterface](/nl/update-from-web-ui). + + ## Docker Haal de nieuwe image op en maak de container opnieuw aan met hetzelfde datavolume: @@ -60,11 +64,7 @@ of database niet aan. ## Controleer je versie De draaiende versie staat in het dashboard, en de console print hem in de creditsregel -onder de banner (bijvoorbeeld `v2.0.0`). Je kunt hem ook uitlezen via het health-endpoint: - -```bash -curl http://:3000/api/health -``` +onder de banner (bijvoorbeeld `v2.0.0`). In de webinterface staat hij naast het logo in de zijbalk; als je erop klikt, opent de releasegeschiedenis. Maak een [back-up](/nl/backup-restore) vóór een grote upgrade. Herstellen is dan een kwestie van diff --git a/pl/update-from-web-ui.mdx b/pl/update-from-web-ui.mdx new file mode 100644 index 0000000..e2e1c7a --- /dev/null +++ b/pl/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Aktualizacja z interfejsu webowego" +description: "Zainstaluj nowe wydanie ipmideck z przeglądarki i skonfiguruj instalacje Dockera, aby robiły to przez Watchtower." +--- + +Gdy zostanie opublikowana nowsza wersja, ipmideck jednorazowo wyświetla powiadomienie, a obok wersji na pasku bocznym pozostaje przycisk aktualizacji, dopóki jej nie zainstalujesz: strzałka w górę lub tarcza w przypadku wydania bezpieczeństwa. Oba otwierają informacje o nowym wydaniu oraz, gdy ipmideck może zainstalować je samodzielnie, przycisk **Pobierz i zainstaluj**. + +## Co robi przycisk + +Zanim cokolwiek zmieni, ipmideck tworzy kopię zapasową bazy danych, klucza szyfrowania i `config.yaml` w `backups/` w [katalogu danych](/pl/configuration#gdzie-znajduje-się-konfiguracja). + +| Metoda instalacji | Wynik | +| --- | --- | +| pip w środowisku wirtualnym, pipx, uv | Instaluje nową wersję i uruchamia ipmideck ponownie. Strona przeładuje się sama, gdy nowa wersja zacznie działać. | +| pip, pipx lub uv w Windows | ipmideck zatrzymuje się, aby można było zainstalować aktualizację, a następnie uruchamiasz go ponownie. Postęp jest zapisywany w `update.log` w katalogu danych. | +| Docker z Watchtower | Watchtower pobiera nowy obraz i zastępuje kontener. Strona przeładuje się sama. | +| Docker bez Watchtower | Okno pokazuje polecenie do uruchomienia na hoście Dockera. | +| Checkout git, systemowy Python, instalacja edytowalna | Okno wyjaśnia przyczynę i pokazuje polecenie do uruchomienia; Python zarządzany przez system aktualizuje się tak, jak został zainstalowany. | + +## Wymagania + +- Logowanie musi być włączone: przycisk zastępuje działający program. +- Przycisk nie jest dostępny w trybie demo. +- Aby uruchomić się ponownie samodzielnie, ipmideck musi być uruchomiony poleceniem `ipmideck`. Jeśli uruchomiono go inaczej, instaluje aktualizację i prosi o ponowne uruchomienie; w Windows zamiast tego pokazuje polecenie. + +## Docker z Watchtower + +Kontener nie może zastąpić własnego obrazu, a dostęp ipmideck do gniazda Dockera dałby mu kontrolę nad hostem. Osobny kontener [Watchtower](https://github.com/nicholas-fedor/watchtower) wykonuje wymianę, gdy ipmideck o to poprosi. + + + + Uruchom ipmideck z etykietą, która pozwala Watchtower nim zarządzać: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Uruchom Watchtower z włączonym API HTTP, dostępnym tylko z hosta: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + Te same ustawienia są dostępne jako `IPMIDECK_UPDATES_WATCHTOWER_URL` i `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. W Docker Compose, gdzie oba kontenery współdzielą sieć, użyj adresu `http://watchtower:8080`. + + + + + Watchtower steruje Dockerem przez jego gniazdo. Użyj długiego, losowego tokenu i pozostaw port powiązany z `127.0.0.1`, jak w przykładzie. + + + + Watchtower pobiera tag, którego kontener już używa. Z `latest` przechodzi do najnowszego wydania; kontener przypięty do tagu wersji (na przykład `2.0.0`) pozostaje przy nim. + + +## Jeśli instalacja się nie powiedzie + +Okno pokazuje przyczynę i wynik instalatora oraz polecenie do ręcznej instalacji aktualizacji. Nic nie jest usuwane: kopia zapasowa wykonana przed instalacją znajduje się w `backups/`, a [Kopia zapasowa i przywracanie](/pl/backup-restore) wyjaśnia, jak ją przywrócić. + +## Następne kroki + +- [Aktualizacja ipmideck](/pl/updating): aktualizacja z wiersza poleceń. +- [Kopia zapasowa i przywracanie](/pl/backup-restore): zrób kopię danych przed aktualizacją. diff --git a/pl/updating.mdx b/pl/updating.mdx index 68bb025..9c4d6d9 100644 --- a/pl/updating.mdx +++ b/pl/updating.mdx @@ -7,6 +7,10 @@ Aktualizacja ipmideck zastępuje aplikację, a nie twoje dane. Twoje `config.yam i klucz szyfrujący znajdują się w [katalogu danych](/pl/configuration#gdzie-znajduje-się-konfiguracja), który pozostaje na miejscu po aktualizacji, więc twoje serwery, historia i ustawienia są zachowane. + + Nowe wydanie możesz też zainstalować z przeglądarki: zobacz [Aktualizacja z interfejsu webowego](/pl/update-from-web-ui). + + ## Docker Pobierz nowy obraz i odtwórz kontener z tym samym wolumenem danych: @@ -60,11 +64,7 @@ ani bazy danych. ## Sprawdź swoją wersję Działająca wersja jest pokazana na pulpicie, a konsola wypisuje ją w wierszu z podziękowaniami -pod banerem (na przykład `v2.0.0`). Możesz ją również odczytać z punktu końcowego health: - -```bash -curl http://:3000/api/health -``` +pod banerem (na przykład `v2.0.0`). W interfejsie webowym znajduje się obok logo na pasku bocznym; kliknięcie jej otwiera historię wydań. Wykonaj [kopię zapasową](/pl/backup-restore) przed dużą aktualizacją. Przywracanie to wtedy kwestia diff --git a/pt/update-from-web-ui.mdx b/pt/update-from-web-ui.mdx new file mode 100644 index 0000000..56757fe --- /dev/null +++ b/pt/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Atualização a partir da interface web" +description: "Instale uma nova versão do ipmideck a partir do navegador e configure as instalações Docker para o fazer com o Watchtower." +--- + +Quando é publicada uma versão mais recente, o ipmideck mostra uma notificação uma única vez, e junto à versão na barra lateral fica um botão de atualização até a instalar: uma seta para cima, ou um escudo numa versão de segurança. Ambos abrem as notas da nova versão e, quando o ipmideck a consegue instalar sozinho, o botão **Transferir e instalar**. + +## O que o botão faz + +Antes de alterar o que quer que seja, o ipmideck faz uma cópia de segurança da base de dados, da chave de encriptação e do `config.yaml` em `backups/` no [diretório de dados](/pt/configuration#onde-a-configuração-fica). + +| Instalado com | Resultado | +| --- | --- | +| pip num ambiente virtual, pipx, uv | Instala a nova versão e reinicia o ipmideck. A página recarrega sozinha quando a nova versão estiver em execução. | +| pip, pipx ou uv no Windows | O ipmideck para para que a atualização seja instalada; depois, volte a iniciá-lo. O progresso é registado em `update.log` no diretório de dados. | +| Docker com Watchtower | O Watchtower descarrega a nova imagem e substitui o contentor. A página recarrega sozinha. | +| Docker sem Watchtower | A janela mostra o comando a executar no anfitrião Docker. | +| Checkout git, Python do sistema, instalação editável | A janela explica o motivo e mostra o comando a executar; um Python gerido pelo sistema atualiza-se da mesma forma que foi instalado. | + +## Requisitos + +- O início de sessão tem de estar ativo: o botão substitui o programa em execução. +- O botão não está disponível no modo de demonstração. +- Para reiniciar sozinho, o ipmideck tem de ter sido iniciado com o comando `ipmideck`. Se foi iniciado de outra forma, instala a atualização e pede-lhe que o reinicie; no Windows mostra o comando em vez disso. + +## Docker com Watchtower + +Um contentor não consegue substituir a sua própria imagem, e dar ao ipmideck acesso ao socket do Docker dar-lhe-ia o controlo do anfitrião. Um contentor [Watchtower](https://github.com/nicholas-fedor/watchtower) separado faz a substituição quando o ipmideck o pede. + + + + Inicie o ipmideck com a etiqueta que permite ao Watchtower geri-lo: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Inicie o Watchtower com a API HTTP ativa, acessível apenas a partir do anfitrião: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + As mesmas definições existem como `IPMIDECK_UPDATES_WATCHTOWER_URL` e `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. Com Docker Compose, em que ambos os contentores partilham uma rede, use `http://watchtower:8080` como endereço. + + + + + O Watchtower controla o Docker através do seu socket. Use um token longo e aleatório e mantenha a porta associada a `127.0.0.1`, como no exemplo. + + + + O Watchtower descarrega a etiqueta que o contentor já usa. Com `latest` passa para a versão mais recente; um contentor fixado numa etiqueta de versão (por exemplo `2.0.0`) mantém-se nela. + + +## Se a instalação falhar + +A janela mostra o motivo e a saída do instalador, juntamente com o comando para instalar a atualização manualmente. Nada é removido: a cópia de segurança feita antes da instalação está em `backups/`, e [Cópia de segurança e restauro](/pt/backup-restore) explica como a repor. + +## Próximos passos + +- [Atualizar o ipmideck](/pt/updating): atualização a partir da linha de comandos. +- [Cópia de segurança e restauro](/pt/backup-restore): faça uma cópia dos seus dados antes de atualizar. diff --git a/pt/updating.mdx b/pt/updating.mdx index 80e7b4e..b4df8c6 100644 --- a/pt/updating.mdx +++ b/pt/updating.mdx @@ -7,6 +7,10 @@ Atualizar o ipmideck substitui a aplicação, não os seus dados. O seu `config. e chave de cifragem vivem no [diretório de dados](/pt/configuration#onde-a-configuração-fica), que permanece no lugar através de uma atualização, por isso os seus servidores, histórico e definições mantêm-se. + + Também pode instalar uma nova versão a partir do navegador: consulte [Atualização a partir da interface web](/pt/update-from-web-ui). + + ## Docker Puxe a nova imagem e recrie o contentor com o mesmo volume de dados: @@ -60,11 +64,7 @@ nem na base de dados. ## Verifique a sua versão A versão em execução aparece no painel, e a consola imprime-a na linha de créditos -sob o banner (por exemplo `v2.0.0`). Também a pode ler a partir do endpoint de health: - -```bash -curl http://:3000/api/health -``` +sob o banner (por exemplo `v2.0.0`). Na interface web aparece junto ao logótipo na barra lateral; ao selecioná-la abre o histórico de versões. Faça uma [cópia de segurança](/pt/backup-restore) antes de uma atualização importante. Restaurar é então uma questão de diff --git a/ru/update-from-web-ui.mdx b/ru/update-from-web-ui.mdx new file mode 100644 index 0000000..944301f --- /dev/null +++ b/ru/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "Обновление через веб-интерфейс" +description: "Установите новый выпуск ipmideck из браузера и настройте установки Docker на обновление через Watchtower." +--- + +Когда публикуется более новая версия, ipmideck один раз показывает уведомление, а рядом с версией на боковой панели остаётся кнопка обновления, пока вы её не установите: стрелка вверх или щит для выпуска с исправлениями безопасности. Обе открывают примечания к новой версии и, если ipmideck может установить её сам, кнопку **Скачать и установить**. + +## Что делает кнопка + +Перед любыми изменениями ipmideck создаёт резервную копию базы данных, ключа шифрования и `config.yaml` в `backups/` в [каталоге данных](/ru/configuration#где-находится-конфигурация). + +| Способ установки | Результат | +| --- | --- | +| pip в виртуальном окружении, pipx, uv | Устанавливает новую версию и перезапускает ipmideck. Страница перезагрузится сама, когда новая версия заработает. | +| pip, pipx или uv в Windows | ipmideck останавливается, чтобы обновление можно было установить, после чего вы запускаете его снова. Ход установки записывается в `update.log` в каталоге данных. | +| Docker с Watchtower | Watchtower загружает новый образ и заменяет контейнер. Страница перезагрузится сама. | +| Docker без Watchtower | В окне показана команда, которую нужно выполнить на хосте Docker. | +| git-checkout, системный Python, редактируемая установка | В окне объясняется причина и показана команда для выполнения; Python, управляемый системой, обновляется тем же способом, каким был установлен. | + +## Требования + +- Вход должен быть включён: кнопка заменяет работающую программу. +- В демо-режиме кнопка недоступна. +- Чтобы перезапуститься самостоятельно, ipmideck должен быть запущен командой `ipmideck`. Если он запущен иначе, он устанавливает обновление и просит вас перезапустить его; в Windows вместо этого показывается команда. + +## Docker с Watchtower + +Контейнер не может заменить собственный образ, а доступ ipmideck к сокету Docker дал бы ему контроль над хостом. Замену выполняет отдельный контейнер [Watchtower](https://github.com/nicholas-fedor/watchtower) по запросу ipmideck. + + + + Запустите ipmideck с меткой, которая разрешает Watchtower управлять им: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + Запустите Watchtower с включённым HTTP API, доступным только с хоста: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + Те же настройки доступны как `IPMIDECK_UPDATES_WATCHTOWER_URL` и `IPMIDECK_UPDATES_WATCHTOWER_TOKEN`. В Docker Compose, где оба контейнера находятся в одной сети, используйте адрес `http://watchtower:8080`. + + + + + Watchtower управляет Docker через его сокет. Используйте длинный случайный токен и оставьте порт привязанным к `127.0.0.1`, как в примере. + + + + Watchtower загружает тот тег, который уже использует контейнер. С `latest` он переходит на последний выпуск; контейнер, закреплённый за тегом версии (например `2.0.0`), остаётся на нём. + + +## Если установка не удалась + +В окне показаны причина и вывод установщика, а также команда для ручной установки обновления. Ничего не удаляется: резервная копия, сделанная перед установкой, находится в `backups/`, а в разделе [Резервное копирование и восстановление](/ru/backup-restore) описано, как её восстановить. + +## Следующие шаги + +- [Обновление ipmideck](/ru/updating): обновление из командной строки. +- [Резервное копирование и восстановление](/ru/backup-restore): сделайте копию данных перед обновлением. diff --git a/ru/updating.mdx b/ru/updating.mdx index b29db7f..928907d 100644 --- a/ru/updating.mdx +++ b/ru/updating.mdx @@ -7,6 +7,10 @@ description: "Обновите ipmideck до нового выпуска с по и ключ шифрования находятся в [каталоге данных](/ru/configuration#где-находится-конфигурация), который остаётся на месте при обновлении, поэтому ваши серверы, история и настройки сохраняются. + + Новый выпуск можно установить и из браузера: см. [Обновление через веб-интерфейс](/ru/update-from-web-ui). + + ## Docker Загрузите новый образ и пересоздайте контейнер с тем же томом данных: @@ -60,11 +64,7 @@ ipmideck start ## Проверьте свою версию Запущенная версия отображается на панели, а консоль печатает её в строке благодарностей -под баннером (например `v2.0.0`). Её также можно прочитать из конечной точки health: - -```bash -curl http://:3000/api/health -``` +под баннером (например `v2.0.0`). В веб-интерфейсе она указана рядом с логотипом на боковой панели; щелчок по ней открывает историю выпусков. Сделайте [резервную копию](/ru/backup-restore) перед крупным обновлением. Восстановление тогда это вопрос diff --git a/zh-Hans/update-from-web-ui.mdx b/zh-Hans/update-from-web-ui.mdx new file mode 100644 index 0000000..91665cd --- /dev/null +++ b/zh-Hans/update-from-web-ui.mdx @@ -0,0 +1,77 @@ +--- +title: "从 Web 界面更新" +description: "在浏览器中安装 ipmideck 的新版本,并为 Docker 安装配置 Watchtower 以实现同样的操作。" +--- + +发布了更新的版本时,ipmideck 会显示一次通知,并且在你安装之前,侧边栏版本号旁会一直显示更新按钮(向上的箭头;安全版本则为盾牌)。两者都会打开新版本的发行说明;如果 ipmideck 能够自行安装,还会显示 **下载并安装** 按钮。 + +## 按钮的作用 + +在做任何更改之前,ipmideck 会将数据库、加密密钥和 `config.yaml` 备份到[数据目录](/zh-Hans/configuration#配置文件位于何处)中的 `backups/`。 + +| 安装方式 | 结果 | +| --- | --- | +| 虚拟环境中的 pip、pipx、uv | 安装新版本并重启 ipmideck。新版本运行后页面会自动重新加载。 | +| Windows 上的 pip、pipx、uv | ipmideck 会停止以便安装更新,之后需要你再次启动它。进度记录在数据目录的 `update.log` 中。 | +| 使用 Watchtower 的 Docker | Watchtower 拉取新镜像并替换容器。页面会自动重新加载。 | +| 未使用 Watchtower 的 Docker | 对话框会显示需要在 Docker 主机上执行的命令。 | +| git 检出、系统 Python、可编辑安装 | 对话框会说明原因并显示需要执行的命令;由系统管理的 Python 请按原安装方式更新。 | + +## 要求 + +- 必须开启登录:该按钮会替换正在运行的程序。 +- 演示模式下不提供该按钮。 +- 要自动重启,ipmideck 必须是通过 `ipmideck` 命令启动的。如果以其他方式启动,它会安装更新并提示你重启;在 Windows 上则改为显示命令。 + +## Docker 与 Watchtower + +容器无法替换自己的镜像,而让 ipmideck 访问 Docker 套接字就等于让它控制主机。因此由一个独立的 [Watchtower](https://github.com/nicholas-fedor/watchtower) 容器在 ipmideck 请求时执行替换。 + + + + 使用允许 Watchtower 管理的标签启动 ipmideck: + +```bash +docker run -d --name ipmideck --network host \ + --label com.centurylinklabs.watchtower.enable=true \ + -v ipmideck-data:/data devluigi06/ipmideck:latest +``` + + + 启动 Watchtower,开启其 HTTP API,并仅允许从主机访问: + +```bash +docker run -d --name watchtower \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -p 127.0.0.1:8080:8080 \ + -e WATCHTOWER_HTTP_API_UPDATE=true \ + -e WATCHTOWER_HTTP_API_TOKEN=replace-with-a-long-random-token \ + -e WATCHTOWER_LABEL_ENABLE=true \ + nickfedor/watchtower +``` + + + 在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck: + +{'en': 'Add the address of Watchtower and its token under the `updates:` section that `config.yaml` already has, then restart ipmideck:', 'it': "Aggiungi l'indirizzo di Watchtower e il token nella sezione `updates:` già presente in `config.yaml`, poi riavvia ipmideck:", 'de': 'Ergänzen Sie die Adresse von Watchtower und das Token im bereits vorhandenen Abschnitt `updates:` von `config.yaml` und starten Sie ipmideck neu:', 'es': 'Añade la dirección de Watchtower y su token en la sección `updates:` que ya tiene `config.yaml` y reinicia ipmideck:', 'fr': "Ajoutez l'adresse de Watchtower et son jeton dans la section `updates:` déjà présente dans `config.yaml`, puis redémarrez ipmideck :", 'nl': 'Voeg het adres van Watchtower en het token toe aan de sectie `updates:` die al in `config.yaml` staat en herstart ipmideck:', 'pl': 'Dodaj adres Watchtower i token w istniejącej sekcji `updates:` pliku `config.yaml`, a następnie uruchom ipmideck ponownie:', 'pt': 'Adicione o endereço do Watchtower e o token na secção `updates:` que o `config.yaml` já tem e reinicie o ipmideck:', 'ru': 'Добавьте адрес Watchtower и токен в уже существующий раздел `updates:` файла `config.yaml` и перезапустите ipmideck:', 'ja': '`config.yaml` にすでにある `updates:` セクションに Watchtower のアドレスとトークンを追加し、ipmideck を再起動します:', 'ko': '`config.yaml`에 이미 있는 `updates:` 섹션에 Watchtower 주소와 토큰을 추가한 다음 ipmideck을 다시 시작합니다:', 'zh-Hans': '在 `config.yaml` 已有的 `updates:` 部分中添加 Watchtower 的地址和令牌,然后重启 ipmideck:'} + + 同样的设置也可以通过 `IPMIDECK_UPDATES_WATCHTOWER_URL` 和 `IPMIDECK_UPDATES_WATCHTOWER_TOKEN` 指定。使用 Docker Compose 时两个容器在同一网络中,地址请使用 `http://watchtower:8080`。 + + + + + Watchtower 通过套接字控制 Docker。请使用足够长的随机令牌,并像示例中那样将端口绑定到 `127.0.0.1`。 + + + + Watchtower 拉取的是容器当前使用的标签。使用 `latest` 时会升级到最新版本;固定在版本标签(例如 `2.0.0`)上的容器会保持该版本。 + + +## 安装失败时 + +对话框会显示原因、安装程序输出以及手动安装更新的命令。不会删除任何内容:安装前创建的备份位于 `backups/`,[备份与恢复](/zh-Hans/backup-restore) 说明了如何恢复。 + +## 后续步骤 + +- [更新 ipmideck](/zh-Hans/updating): 从命令行更新。 +- [备份与恢复](/zh-Hans/backup-restore): 更新前为数据创建快照。 diff --git a/zh-Hans/updating.mdx b/zh-Hans/updating.mdx index b13f999..657f666 100644 --- a/zh-Hans/updating.mdx +++ b/zh-Hans/updating.mdx @@ -7,6 +7,10 @@ description: "使用 Docker 或 pip 将 ipmideck 升级到新版本。你的数 和加密密钥位于[数据目录](/zh-Hans/configuration#配置文件位于何处)中,它 在升级过程中保持原位,因此你的服务器、历史记录和设置都会延续。 + + 你也可以在浏览器中安装新版本:参见[从 Web 界面更新](/zh-Hans/update-from-web-ui)。 + + ## Docker 拉取新镜像并用相同的数据卷重新创建容器: @@ -60,11 +64,7 @@ ipmideck start ## 检查你的版本 运行中的版本会显示在仪表板上,控制台会在横幅下方的致谢行中 -打印它(例如 `v2.0.0`)。你也可以从 health 端点读取它: - -```bash -curl http://:3000/api/health -``` +打印它(例如 `v2.0.0`)。在 Web 界面中,它显示在侧边栏的标志旁边,点击即可打开发布历史。 在重大升级前先做一次[备份](/zh-Hans/backup-restore)。这样一来,如果出现问题, From 082ed9fbf0c12bf100649ff01c58eddfe996dac6 Mon Sep 17 00:00:00 2001 From: dev-luigi <70869541+dev-luigi@users.noreply.github.com> Date: Tue, 6 Oct 2026 17:20:32 +0200 Subject: [PATCH 2/2] ci(i18n): gate pages, navigation and frontmatter across all languages check-docs-i18n.mjs fails when a language is missing a page that en has (or has one en lacks), when docs.json navigation drifts from en, when a title, description or page body is empty or left in English, or, given --since, when an en page changed without every translation changing with it. [i18n-skip] in a commit message overrides the last check for a deliberate en-only change. The CI workflow runs it on push and pull request; .githooks/pre-push runs it before every push and blocks the push on failure (activate with `git config core.hooksPath .githooks`). .gitattributes keeps the hook LF. --- .gitattributes | 2 + .githooks/pre-push | 20 ++ .github/scripts/check-docs-i18n.mjs | 312 ++++++++++++++++++++++++++++ .github/workflows/ci.yml | 21 ++ 4 files changed, 355 insertions(+) create mode 100644 .gitattributes create mode 100755 .githooks/pre-push create mode 100644 .github/scripts/check-docs-i18n.mjs create mode 100644 .github/workflows/ci.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c516359 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Shell hooks must stay LF so the #!/bin/sh shebang is not corrupted by CRLF on Windows. +.githooks/** text eol=lf diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 0000000..c55df3e --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,20 @@ +#!/bin/sh +# Pre-push i18n gate: blocks the push when a translation is missing or left stale. +# CI runs the same script (.github/workflows/ci.yml). Activate per-clone with: +# git config core.hooksPath .githooks +# Override a deliberate en-only change with [i18n-skip] in a commit message. +zero=0000000000000000000000000000000000000000 +status=0 +while read -r local_ref local_sha remote_ref remote_sha; do + [ "$local_sha" = "$zero" ] && continue # deleting a remote ref: nothing to check + if [ "$remote_sha" = "$zero" ]; then + base=$(git merge-base "$local_sha" origin/HEAD 2>/dev/null || git merge-base "$local_sha" origin/main 2>/dev/null || true) + else + base=$remote_sha + fi + node .github/scripts/check-docs-i18n.mjs --since "$base" --head "$local_sha" || status=1 +done +if [ "$status" -ne 0 ]; then + echo "[pre-push] i18n gate FAILED — push blocked." >&2 +fi +exit $status diff --git a/.github/scripts/check-docs-i18n.mjs b/.github/scripts/check-docs-i18n.mjs new file mode 100644 index 0000000..1e12ad9 --- /dev/null +++ b/.github/scripts/check-docs-i18n.mjs @@ -0,0 +1,312 @@ +#!/usr/bin/env node +// Translation-completeness gate for the docs site. +// +// `en` is the source of truth. Checks that every language in docs.json has a +// folder (and vice versa), the same .mdx files as `en`, the same navigation +// shape, a translated title/description in every page's frontmatter, and no +// page body left identical to en. +// With `--since [--head ]` it also fails when an `en` page changed +// in that range without the matching change in every other language. +// +// Usage: node .github/scripts/check-docs-i18n.mjs [--since ] [--head ] +// Zero dependencies; Node 20+. + +import { execFileSync } from "node:child_process"; +import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; +import { dirname, join, relative, resolve, sep } from "node:path"; +import { fileURLToPath } from "node:url"; + +const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", ".."); +const SOURCE = "en"; +const SKIP_DIRS = new Set(["console", "tutorials", "node_modules"]); +const SKIP_TOKEN = "[i18n-skip]"; +const ZERO_SHA = /^0+$/; + +// Words that are legitimately identical in every language. A non-en title or +// description equal to en's is accepted only when it is built from these +// tokens alone (plus numbers and punctuation). Keep it to brands and acronyms. +const BRAND_TOKENS = new Set( + [ + "ipmideck", "IPMIDeck", "IPMI", "BMC", "CLI", "FAQ", "API", "UI", "LAN", "SEL", "FRU", + "Docker", "Compose", "Dell", "iDRAC", "PowerEdge", "HPE", "iLO", "ProLiant", "Lenovo", + "XCC", "ThinkSystem", "IBM", "IMM", "Supermicro", "IPMIView", "ipmitool", "Linux", + "Windows", "macOS", "pip", "pipx", "Python", "systemd", "TLS", "HTTPS", + ].map((t) => t.toLowerCase()), +); + +// Whole values that are the correct translation and happen to be spelled +// exactly like en (cognates). Add an entry only after confirming the word is +// right in that language -- never to silence a page that was not translated. +const COGNATES = { + de: ["Installation"], + fr: ["Configuration", "Installation"], +}; + +const failures = []; +const fail = (scope, message) => failures.push(`[${scope}] ${message}`); +const toPosix = (p) => p.split(sep).join("/"); + +/* --- arguments --- */ + +function parseArgs(argv) { + const out = { since: undefined, head: "HEAD" }; + for (let i = 0; i < argv.length; i++) { + const arg = argv[i]; + const eq = arg.indexOf("="); + const flag = eq === -1 ? arg : arg.slice(0, eq); + const inline = eq === -1 ? undefined : arg.slice(eq + 1); + if (flag !== "--since" && flag !== "--head") { + console.error(`unknown argument: ${arg}`); + process.exit(2); + } + let value = inline; + if (value === undefined) { + const next = argv[i + 1]; + value = next !== undefined && !next.startsWith("--") ? (i++, next) : ""; + } + if (flag === "--since") out.since = value; + else out.head = value || "HEAD"; + } + return out; +} + +/* --- filesystem helpers --- */ + +function isDir(p) { + try { + return statSync(p).isDirectory(); + } catch { + return false; + } +} + +function listMdx(dir) { + const found = []; + const walk = (d) => { + for (const entry of readdirSync(d, { withFileTypes: true })) { + if (entry.name.startsWith(".") || entry.name === "node_modules") continue; + const full = join(d, entry.name); + if (entry.isDirectory()) walk(full); + else if (entry.isFile() && entry.name.endsWith(".mdx")) found.push(toPosix(relative(dir, full))); + } + }; + if (isDir(dir)) walk(dir); + return found.sort(); +} + +/* --- frontmatter --- */ + +function unquote(raw) { + const v = raw.trim(); + if (v.length >= 2 && v.startsWith('"') && v.endsWith('"')) { + try { + return JSON.parse(v); + } catch { + return v.slice(1, -1); + } + } + if (v.length >= 2 && v.startsWith("'") && v.endsWith("'")) return v.slice(1, -1).replace(/''/g, "'"); + return v.replace(/\s+#.*$/, ""); +} + +/** Frontmatter fields, plus the page body (everything after the block) as `body`. */ +function readFrontmatter(file) { + const text = readFileSync(file, "utf8").replace(/^/, ""); + const lines = text.split(/\r?\n/); + if (lines[0].trim() !== "---") return null; + const fields = {}; + for (let i = 1; i < lines.length; i++) { + if (lines[i].trim() === "---") { + return { ...fields, body: lines.slice(i + 1).join("\n").trim() }; + } + const m = /^([A-Za-z_][\w-]*)\s*:(.*)$/.exec(lines[i]); + if (m) fields[m[1]] = unquote(m[2]); + } + return null; // unterminated block +} + +function isBrandOnly(value) { + const tokens = value.split(/[\s/&()[\],.:;!?+|–—-]+/).filter(Boolean); + return tokens.length > 0 && tokens.every((t) => /^\d+$/.test(t) || BRAND_TOKENS.has(t.toLowerCase().replace(/\d+$/, ""))); +} + +/* --- docs.json navigation --- */ + +function walkNav(node, acc) { + if (Array.isArray(node)) { + for (const item of node) walkNav(item, acc); + } else if (typeof node === "string") { + acc.pages.push(node); + } else if (node && typeof node === "object") { + if (typeof node.group === "string") acc.groups++; + for (const key of ["tabs", "anchors", "dropdowns", "groups", "pages"]) { + if (key in node) walkNav(node[key], acc); + } + } + return acc; +} + +/* --- checks --- */ + +function loadDocsJson() { + try { + return JSON.parse(readFileSync(join(ROOT, "docs.json"), "utf8")); + } catch (e) { + fail("docs.json", `cannot read or parse docs.json: ${e.message}`); + return null; + } +} + +function checkLanguageSet(navLangs) { + const navSet = new Set(navLangs); + const folders = readdirSync(ROOT, { withFileTypes: true }) + .filter((e) => e.isDirectory() && !e.name.startsWith(".") && !SKIP_DIRS.has(e.name)) + .map((e) => e.name) + .filter((name) => navSet.has(name) || listMdx(join(ROOT, name)).length > 0); + const folderSet = new Set(folders); + for (const lang of navLangs) { + if (!folderSet.has(lang)) fail(lang, "listed in docs.json navigation.languages but has no folder"); + } + for (const lang of folders) { + if (!navSet.has(lang)) fail(lang, "folder contains .mdx pages but is missing from docs.json navigation.languages"); + } + return navLangs.filter((l) => folderSet.has(l)); +} + +function checkFileParity(langs, files) { + const enFiles = new Set(files.get(SOURCE)); + for (const lang of langs) { + if (lang === SOURCE) continue; + const own = new Set(files.get(lang)); + for (const f of enFiles) if (!own.has(f)) fail(lang, `missing ${lang}/${f} (exists in ${SOURCE})`); + for (const f of own) if (!enFiles.has(f)) fail(lang, `extra ${lang}/${f} (no ${SOURCE}/${f})`); + } +} + +function checkNavigation(languages) { + const navs = new Map(languages.map((l) => [l.language, walkNav(l, { pages: [], groups: 0 })])); + const en = navs.get(SOURCE); + for (const [lang, nav] of navs) { + for (const page of nav.pages) { + if (!existsSync(join(ROOT, `${page}.mdx`))) fail(lang, `docs.json page "${page}" has no ${page}.mdx`); + } + if (lang === SOURCE || !en) continue; + if (nav.groups !== en.groups) fail(lang, `docs.json has ${nav.groups} group(s), ${SOURCE} has ${en.groups}`); + const expected = en.pages.map((p) => (p.startsWith(`${SOURCE}/`) ? `${lang}/${p.slice(SOURCE.length + 1)}` : p)); + const n = Math.max(expected.length, nav.pages.length); + for (let i = 0; i < n; i++) { + if (expected[i] !== nav.pages[i]) { + fail(lang, `docs.json page #${i + 1} is "${nav.pages[i] ?? "(none)"}", expected "${expected[i] ?? "(none)"}"`); + break; // one positional report per language is enough to locate the drift + } + } + if (nav.pages.length !== expected.length) { + fail(lang, `docs.json lists ${nav.pages.length} page(s), ${SOURCE} lists ${expected.length}`); + } + } +} + +function checkFrontmatter(langs, files) { + const enMeta = new Map(); + for (const lang of [SOURCE, ...langs.filter((l) => l !== SOURCE)]) { + for (const f of files.get(lang)) { + const fm = readFrontmatter(join(ROOT, lang, f)); + if (!fm) { + fail(lang, `${lang}/${f} has no closed --- frontmatter block`); + continue; + } + for (const key of ["title", "description"]) { + if (!fm[key] || !fm[key].trim()) fail(lang, `${lang}/${f} has an empty or missing "${key}"`); + } + if (lang === SOURCE) { + enMeta.set(f, fm); + continue; + } + const src = enMeta.get(f); + if (!src) continue; + for (const key of ["title", "description"]) { + const v = fm[key]?.trim(); + if (v && v === src[key]?.trim() && !isBrandOnly(v) && !COGNATES[lang]?.includes(v)) { + fail(lang, `${lang}/${f} "${key}" is identical to ${SOURCE} (untranslated): "${v}"`); + } + } + if (fm.body && fm.body === src.body) { + fail(lang, `${lang}/${f} body is identical to ${SOURCE} (untranslated page)`); + } + } + } +} + +function git(args) { + return execFileSync("git", args, { cwd: ROOT, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }); +} + +function checkStale(langs, since, head) { + let base = null; + if (since && !ZERO_SHA.test(since)) { + try { + base = git(["rev-parse", "--verify", "--quiet", `${since}^{commit}`]).trim() || null; + } catch { + base = null; + } + } + if (!base) { + console.log("stale check skipped (no base)"); + return; + } + let tip; + try { + tip = git(["rev-parse", "--verify", "--quiet", `${head}^{commit}`]).trim(); + } catch { + fail("git", `cannot resolve --head "${head}"`); + return; + } + const messages = git(["log", "--format=%B", `${base}..${tip}`]); + if (messages.includes(SKIP_TOKEN)) { + console.log(`stale check skipped (${SKIP_TOKEN} in a commit message in ${base.slice(0, 7)}..${tip.slice(0, 7)})`); + return; + } + const changed = new Set( + git(["-c", "core.quotepath=false", "diff", "--name-only", "-z", "--diff-filter=AM", base, tip]) + .split("\0") + .filter(Boolean), + ); + let enChanged = 0; + for (const file of changed) { + if (!file.startsWith(`${SOURCE}/`) || !file.endsWith(".mdx")) continue; + enChanged++; + const rel = file.slice(SOURCE.length + 1); + for (const lang of langs) { + if (lang === SOURCE || changed.has(`${lang}/${rel}`)) continue; + fail(lang, `${rel} not updated after ${SOURCE} change (add ${SKIP_TOKEN} to a commit message to override)`); + } + } + console.log(`stale check: ${enChanged} ${SOURCE} page(s) changed in ${base.slice(0, 7)}..${tip.slice(0, 7)}`); +} + +/* --- main --- */ + +const args = parseArgs(process.argv.slice(2)); +const docs = loadDocsJson(); +const languages = Array.isArray(docs?.navigation?.languages) ? docs.navigation.languages : null; +if (docs && !languages) fail("docs.json", "navigation.languages is missing or not an array"); + +if (languages) { + const navLangs = languages.map((l) => l.language); + if (!navLangs.includes(SOURCE)) fail(SOURCE, "source language missing from docs.json navigation.languages"); + const langs = checkLanguageSet(navLangs); + if (langs.includes(SOURCE)) { + const files = new Map(langs.map((l) => [l, listMdx(join(ROOT, l))])); + checkFileParity(langs, files); + checkNavigation(languages); + checkFrontmatter(langs, files); + if (args.since !== undefined) checkStale(langs, args.since, args.head); + } +} + +if (failures.length) { + for (const f of failures) console.error(f); + console.error(`${failures.length} failure(s)`); + process.exit(1); +} +console.log("i18n OK: all languages match en (files, navigation, frontmatter)."); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f091932 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,21 @@ +name: ci +on: + push: + branches: [main] + pull_request: +permissions: + contents: read +jobs: + i18n: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 # the stale-translation check diffs against the base commit + - uses: actions/setup-node@v4 + with: + node-version: "20" + - run: node .github/scripts/check-docs-i18n.mjs --since "$BASE" + env: + BASE: ${{ github.event.pull_request.base.sha || github.event.before }}