From f69391bc60087ec07b000faf854d3e2ff4e34e00 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Nov 2026 15:33:10 +0000 Subject: [PATCH 1/3] Update rustmailer/bichon Docker tag to v2 --- apps/bichon/1.6.2/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bichon/1.6.2/docker-compose.yml b/apps/bichon/1.6.2/docker-compose.yml index ad8307231..10a2bbb58 100644 --- a/apps/bichon/1.6.2/docker-compose.yml +++ b/apps/bichon/1.6.2/docker-compose.yml @@ -1,6 +1,6 @@ services: bichon: - image: "rustmailer/bichon:1.6.2" + image: "rustmailer/bichon:2.3.0" container_name: ${CONTAINER_NAME} restart: always user: "1000:1000" From 8a4b1437bd2045d44a36a4bd8c6197720bbe0c61 Mon Sep 17 00:00:00 2001 From: okxlin <61420215+okxlin@users.noreply.github.com> Date: Fri, 6 Nov 2026 00:22:35 +0800 Subject: [PATCH 2/3] Update app version [skip ci] --- apps/bichon/{1.6.2 => 2.3.0}/.env.sample | 0 apps/bichon/{1.6.2 => 2.3.0}/data.yml | 0 apps/bichon/{1.6.2 => 2.3.0}/data/.gitkeep | 0 apps/bichon/{1.6.2 => 2.3.0}/docker-compose.yml | 0 apps/bichon/{1.6.2 => 2.3.0}/scripts/init.sh | 0 apps/bichon/{1.6.2 => 2.3.0}/scripts/uninstall.sh | 0 apps/bichon/{1.6.2 => 2.3.0}/scripts/upgrade.sh | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename apps/bichon/{1.6.2 => 2.3.0}/.env.sample (100%) rename apps/bichon/{1.6.2 => 2.3.0}/data.yml (100%) rename apps/bichon/{1.6.2 => 2.3.0}/data/.gitkeep (100%) rename apps/bichon/{1.6.2 => 2.3.0}/docker-compose.yml (100%) rename apps/bichon/{1.6.2 => 2.3.0}/scripts/init.sh (100%) rename apps/bichon/{1.6.2 => 2.3.0}/scripts/uninstall.sh (100%) rename apps/bichon/{1.6.2 => 2.3.0}/scripts/upgrade.sh (100%) diff --git a/apps/bichon/1.6.2/.env.sample b/apps/bichon/2.3.0/.env.sample similarity index 100% rename from apps/bichon/1.6.2/.env.sample rename to apps/bichon/2.3.0/.env.sample diff --git a/apps/bichon/1.6.2/data.yml b/apps/bichon/2.3.0/data.yml similarity index 100% rename from apps/bichon/1.6.2/data.yml rename to apps/bichon/2.3.0/data.yml diff --git a/apps/bichon/1.6.2/data/.gitkeep b/apps/bichon/2.3.0/data/.gitkeep similarity index 100% rename from apps/bichon/1.6.2/data/.gitkeep rename to apps/bichon/2.3.0/data/.gitkeep diff --git a/apps/bichon/1.6.2/docker-compose.yml b/apps/bichon/2.3.0/docker-compose.yml similarity index 100% rename from apps/bichon/1.6.2/docker-compose.yml rename to apps/bichon/2.3.0/docker-compose.yml diff --git a/apps/bichon/1.6.2/scripts/init.sh b/apps/bichon/2.3.0/scripts/init.sh similarity index 100% rename from apps/bichon/1.6.2/scripts/init.sh rename to apps/bichon/2.3.0/scripts/init.sh diff --git a/apps/bichon/1.6.2/scripts/uninstall.sh b/apps/bichon/2.3.0/scripts/uninstall.sh similarity index 100% rename from apps/bichon/1.6.2/scripts/uninstall.sh rename to apps/bichon/2.3.0/scripts/uninstall.sh diff --git a/apps/bichon/1.6.2/scripts/upgrade.sh b/apps/bichon/2.3.0/scripts/upgrade.sh similarity index 100% rename from apps/bichon/1.6.2/scripts/upgrade.sh rename to apps/bichon/2.3.0/scripts/upgrade.sh From 2029843edb68bb40e2d6d1366a21b5ae01721f96 Mon Sep 17 00:00:00 2001 From: okxlin <61420215+okxlin@users.noreply.github.com> Date: Fri, 6 Nov 2026 01:20:55 +0800 Subject: [PATCH 3/3] Add Bichon v1 storage migration for 2.x upgrades --- apps/bichon/2.3.0/scripts/upgrade.sh | 103 ++++++++++++++++++++++++++- apps/bichon/README.md | 12 +++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/apps/bichon/2.3.0/scripts/upgrade.sh b/apps/bichon/2.3.0/scripts/upgrade.sh index 5ec28d784..4e732f57a 100755 --- a/apps/bichon/2.3.0/scripts/upgrade.sh +++ b/apps/bichon/2.3.0/scripts/upgrade.sh @@ -2,4 +2,105 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" -exec "$SCRIPT_DIR/init.sh" +APP_DIR="$(cd "$SCRIPT_DIR/.." && pwd -P)" +ENV_FILE="${ENV_FILE:-$APP_DIR/.env}" +ADMIN_IMAGE="rustmailer/bichon:2.3.0" + +read_env_value() { + local key="$1" + local value + [[ -f "$ENV_FILE" ]] || return 0 + value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" + value="${value%$'\r'}" + case "$value" in + \"*\") value="${value#\"}"; value="${value%\"}" ;; + \'*\') value="${value#\'}"; value="${value%\'}" ;; + esac + printf '%s\n' "$value" +} + +"$SCRIPT_DIR/init.sh" + +APP_DATA_DIR="${APP_DATA_DIR:-$(read_env_value APP_DATA_DIR)}" +APP_DATA_DIR="${APP_DATA_DIR:-./data}" +if [[ "$APP_DATA_DIR" = /* ]]; then + RESOLVED_DATA_DIR="$(realpath -m -- "$APP_DATA_DIR")" +else + RESOLVED_DATA_DIR="$(realpath -m -- "$APP_DIR/${APP_DATA_DIR#./}")" + case "$RESOLVED_DATA_DIR" in + "$APP_DIR"/*) ;; + *) + printf 'Relative APP_DATA_DIR must remain inside the application directory\n' >&2 + exit 1 + ;; + esac +fi +[[ -d "$RESOLVED_DATA_DIR" ]] || { + printf 'APP_DATA_DIR does not exist: %s\n' "$RESOLVED_DATA_DIR" >&2 + exit 1 +} + +docker_args=(docker run --rm --network none --user 1000:1000 --mount "type=bind,source=$RESOLVED_DATA_DIR,target=/data" --env BICHON_ROOT_DIR=/data) +if [[ -n "${BICHON_INDEX_DIR:-$(read_env_value BICHON_INDEX_DIR)}" ]]; then + docker_args+=(--env "BICHON_INDEX_DIR=${BICHON_INDEX_DIR:-$(read_env_value BICHON_INDEX_DIR)}") +fi + +storage_state() { + "${docker_args[@]}" --entrypoint sh "$ADMIN_IMAGE" -c ' + set -eu + root=/data + storage="$root/bichon-storage" + version=0 + if [ -f "$root/STORAGE_VERSION" ]; then + version="$(cat "$root/STORAGE_VERSION")" + fi + case "$version" in + ""|*[!0-9]*) echo INVALID; exit 0 ;; + esac + if [ -d "$storage/blobs" ]; then + if [ "$version" -ge 2 ]; then echo CURRENT; else echo PARTIAL; fi + elif [ -d "$storage" ]; then + if [ "$version" -lt 2 ]; then echo LEGACY; else echo INVALID; fi + elif [ "$version" -eq 0 ]; then + echo CLEAN + else + echo INVALID + fi + ' +} + +state="$(storage_state)" +case "$state" in + CLEAN|CURRENT) + ;; + LEGACY) + if ! command -v script >/dev/null 2>&1; then + printf 'The util-linux script command is required for the Bichon v1 storage migration\n' >&2 + exit 1 + fi + + printf -v admin_command '%q ' "${docker_args[@]}" --interactive --tty --entrypoint bichon-admin "$ADMIN_IMAGE" + { + sleep 0.2 + printf '\033[B\033[B\r' + sleep 0.2 + printf '/data\r' + sleep 0.2 + printf '\r' + sleep 0.2 + printf '\r' + sleep 0.2 + printf '\r' + } | script -qefc "$admin_command" /dev/null + + state="$(storage_state)" + if [[ "$state" != CURRENT ]]; then + printf 'Bichon v1 storage migration did not reach storage version 2 (state: %s)\n' "$state" >&2 + exit 1 + fi + ;; + *) + printf 'Unrecognized or incomplete Bichon storage layout (state: %s); refusing to start the upgraded app\n' "$state" >&2 + exit 1 + ;; +esac diff --git a/apps/bichon/README.md b/apps/bichon/README.md index b1b999db7..b1fcd4794 100644 --- a/apps/bichon/README.md +++ b/apps/bichon/README.md @@ -49,7 +49,17 @@ Bichon is a self-hosted email archiving service written in Rust. It downloads ma 升级或迁移前,应停止 Bichon 并备份 `APP_DATA_DIR` 指向的完整目录以及安装时使用的加密口令。默认 `./data` 位于 1Panel 应用版本目录内,卸载时会随应用目录移除;若需要跨卸载保留归档,请选择独立绝对路径,并预先保证其所有权为 UID/GID `1000:1000`。 -本应用只打包稳定版 `1.6.2`。截至本批次适配时,上游 `latest` 已指向 `2.0.0-alpha.1` 预发布镜像,因此没有将 `latest` 作为稳定版本交付。 +从 `1.6.2` 升级到 `2.x` 时,升级脚本会调用上游管理工具将 Fjall 邮件对象存储迁移到新格式;现有索引和元数据保持不变。迁移会保留旧存储供验证;确认新版运行正常前,不要手动删除旧数据。`APP_DATA_DIR` 挂载路径保持不变,也支持自定义绝对路径。 + +本应用提供固定版本 `1.6.2` 和 `2.3.0`。上游 `latest` 可能先于稳定版指向预发布镜像,因此不作为固定稳定版本交付。 + +## Backup and upgrades + +Before upgrading or migrating, stop Bichon and back up the full `APP_DATA_DIR` directory and the encryption password used at installation. The default `./data` is inside the 1Panel app directory and is removed when the app is uninstalled; choose a separate absolute path to retain archives across uninstall, owned by UID/GID `1000:1000`. + +When upgrading from `1.6.2` to `2.x`, the upgrade script runs the upstream admin migration from Fjall blob storage to the new format; existing indexes and metadata are left unchanged. The migration keeps the old storage for verification; do not remove it until the upgraded app works. The `APP_DATA_DIR` mount remains unchanged, including custom absolute paths. + +The app provides fixed versions `1.6.2` and `2.3.0`. Upstream `latest` may point to a prerelease before a stable release, so it is not used as a fixed stable version. ## 参考资料