mirror of
https://github.com/okxlin/appstore.git
synced 2026-10-30 08:06:02 +00:00
fix(bookstack): preserve 26.05 package for 26.09 update
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
CONTAINER_NAME=
|
||||
PANEL_APP_PORT_HTTP=6875
|
||||
CONFIG_PATH=./data/config
|
||||
APP_URL=http://bookstack.example.com
|
||||
APP_KEY=base64:replace-with-generated-app-key
|
||||
DB_HOST=bookstack-db
|
||||
DB_PORT=3306
|
||||
DB_USERNAME=bookstack
|
||||
DB_DATABASE=bookstack
|
||||
DB_PASSWORD=replace-with-db-password
|
||||
QUEUE_CONNECTION=
|
||||
DB_DATA_PATH=./data/db
|
||||
TIME_ZONE=Asia/Shanghai
|
||||
@@ -0,0 +1,204 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 6875
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
labelEn: HTTP Port
|
||||
labelZh: HTTP 端口
|
||||
label:
|
||||
en: HTTP Port
|
||||
zh: HTTP 端口
|
||||
zh-Hant: HTTP 連接埠
|
||||
ja: HTTP ポート
|
||||
ko: HTTP 포트
|
||||
ru: HTTP-порт
|
||||
ms: Port HTTP
|
||||
pt-br: Porta HTTP
|
||||
required: true
|
||||
type: number
|
||||
rule: paramPort
|
||||
- default: ./data/config
|
||||
edit: true
|
||||
envKey: CONFIG_PATH
|
||||
labelEn: Config folder path
|
||||
labelZh: 配置文件路径
|
||||
label:
|
||||
en: Config folder path
|
||||
zh: 配置文件路径
|
||||
zh-Hant: 設定檔資料夾路徑
|
||||
ja: 設定フォルダーのパス
|
||||
ko: 설정 폴더 경로
|
||||
ru: Путь к папке конфигурации
|
||||
ms: Laluan folder konfigurasi
|
||||
pt-br: Caminho da pasta de configuração
|
||||
required: true
|
||||
type: text
|
||||
- default: ''
|
||||
edit: true
|
||||
envKey: APP_URL
|
||||
labelEn: Application URL
|
||||
labelZh: 应用访问 URL
|
||||
label:
|
||||
en: Application URL
|
||||
zh: 应用访问 URL
|
||||
zh-Hant: 應用程式存取 URL
|
||||
ja: アプリケーション URL
|
||||
ko: 애플리케이션 URL
|
||||
ru: URL приложения
|
||||
ms: URL aplikasi
|
||||
pt-br: URL do aplicativo
|
||||
required: true
|
||||
type: text
|
||||
- default: ''
|
||||
edit: true
|
||||
envKey: APP_KEY
|
||||
labelEn: Application key
|
||||
labelZh: 应用密钥
|
||||
label:
|
||||
en: Application key
|
||||
zh: 应用密钥
|
||||
zh-Hant: 應用程式密鑰
|
||||
ja: アプリケーションキー
|
||||
ko: 애플리케이션 키
|
||||
ru: Ключ приложения
|
||||
ms: Kunci aplikasi
|
||||
pt-br: Chave do aplicativo
|
||||
required: true
|
||||
random: true
|
||||
type: password
|
||||
rule: paramComplexity
|
||||
- default: bookstack-db
|
||||
edit: true
|
||||
envKey: DB_HOST
|
||||
labelEn: Database host
|
||||
labelZh: 数据库主机
|
||||
label:
|
||||
en: Database host
|
||||
zh: 数据库主机
|
||||
zh-Hant: 資料庫主機
|
||||
ja: データベースホスト
|
||||
ko: 데이터베이스 호스트
|
||||
ru: Хост базы данных
|
||||
ms: Hos pangkalan data
|
||||
pt-br: Host do banco
|
||||
required: true
|
||||
type: text
|
||||
- default: 3306
|
||||
edit: true
|
||||
envKey: DB_PORT
|
||||
labelEn: Database port
|
||||
labelZh: 数据库端口
|
||||
label:
|
||||
en: Database port
|
||||
zh: 数据库端口
|
||||
zh-Hant: 資料庫連接埠
|
||||
ja: データベースポート
|
||||
ko: 데이터베이스 포트
|
||||
ru: Порт базы данных
|
||||
ms: Port pangkalan data
|
||||
pt-br: Porta do banco
|
||||
required: true
|
||||
type: number
|
||||
- default: bookstack
|
||||
edit: true
|
||||
envKey: DB_USERNAME
|
||||
labelEn: Database username
|
||||
labelZh: 数据库用户名
|
||||
label:
|
||||
en: Database username
|
||||
zh: 数据库用户名
|
||||
zh-Hant: 資料庫使用者名稱
|
||||
ja: データベースユーザー名
|
||||
ko: 데이터베이스 사용자 이름
|
||||
ru: Имя пользователя базы
|
||||
ms: Nama pengguna pangkalan data
|
||||
pt-br: Usuario do banco
|
||||
required: true
|
||||
type: text
|
||||
- default: bookstack
|
||||
edit: true
|
||||
envKey: DB_DATABASE
|
||||
labelEn: Database name
|
||||
labelZh: 数据库名称
|
||||
label:
|
||||
en: Database name
|
||||
zh: 数据库名称
|
||||
zh-Hant: 資料庫名稱
|
||||
ja: データベース名
|
||||
ko: 데이터베이스 이름
|
||||
ru: Имя базы данных
|
||||
ms: Nama pangkalan data
|
||||
pt-br: Nome do banco
|
||||
required: true
|
||||
type: text
|
||||
- default: ''
|
||||
edit: true
|
||||
envKey: DB_PASSWORD
|
||||
labelEn: Database password
|
||||
labelZh: 数据库密码
|
||||
label:
|
||||
en: Database password
|
||||
zh: 数据库密码
|
||||
zh-Hant: 資料庫密碼
|
||||
ja: データベースパスワード
|
||||
ko: 데이터베이스 비밀번호
|
||||
ru: Пароль базы данных
|
||||
ms: Kata laluan pangkalan data
|
||||
pt-br: Senha do banco de dados
|
||||
required: true
|
||||
random: true
|
||||
type: password
|
||||
rule: paramComplexity
|
||||
- default: ''
|
||||
edit: true
|
||||
envKey: QUEUE_CONNECTION
|
||||
labelEn: Async queue connection
|
||||
labelZh: 异步队列连接
|
||||
label:
|
||||
en: Async queue connection
|
||||
zh: 异步队列连接
|
||||
zh-Hant: 非同步佇列連線
|
||||
ja: 非同期キュー接続
|
||||
ko: 비동기 큐 연결
|
||||
ru: Подключение асинхронной очереди
|
||||
ms: Sambungan baris gilir tak segerak
|
||||
pt-br: Conexao de fila assincrona
|
||||
required: false
|
||||
type: select
|
||||
values:
|
||||
- label: disabled
|
||||
value: ''
|
||||
- label: database
|
||||
value: database
|
||||
- default: ./data/db
|
||||
edit: true
|
||||
envKey: DB_DATA_PATH
|
||||
labelEn: Database data path
|
||||
labelZh: 数据库数据目录
|
||||
label:
|
||||
en: Database data path
|
||||
zh: 数据库数据目录
|
||||
zh-Hant: 資料庫資料目錄
|
||||
ja: データベースデータディレクトリ
|
||||
ko: 데이터베이스 데이터 디렉터리
|
||||
ru: Каталог данных базы
|
||||
ms: Laluan data pangkalan data
|
||||
pt-br: Caminho de dados do banco
|
||||
required: true
|
||||
type: text
|
||||
- default: Asia/Shanghai
|
||||
edit: true
|
||||
envKey: TIME_ZONE
|
||||
labelEn: Time zone
|
||||
labelZh: 时区
|
||||
label:
|
||||
en: Time zone
|
||||
zh: 时区
|
||||
zh-Hant: 時區
|
||||
ja: タイムゾーン
|
||||
ko: 시간대
|
||||
ru: Часовой пояс
|
||||
ms: Zon waktu
|
||||
pt-br: Fuso horário
|
||||
required: true
|
||||
type: text
|
||||
@@ -0,0 +1,44 @@
|
||||
networks:
|
||||
1panel-network:
|
||||
external: true
|
||||
services:
|
||||
bookstack:
|
||||
image: "linuxserver/bookstack:26.09.20260924"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
- 1panel-network
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:80"
|
||||
volumes:
|
||||
- "${CONFIG_PATH}:/config"
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=${TIME_ZONE}
|
||||
- APP_URL=${APP_URL}
|
||||
- APP_KEY=${APP_KEY}
|
||||
- DB_HOST=${DB_HOST}
|
||||
- DB_PORT=${DB_PORT}
|
||||
- DB_USERNAME=${DB_USERNAME}
|
||||
- DB_PASSWORD=${DB_PASSWORD}
|
||||
- DB_DATABASE=${DB_DATABASE}
|
||||
- QUEUE_CONNECTION=${QUEUE_CONNECTION:-}
|
||||
depends_on:
|
||||
- bookstack-db
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
bookstack-db:
|
||||
image: "mariadb:11.4"
|
||||
restart: always
|
||||
networks:
|
||||
- 1panel-network
|
||||
volumes:
|
||||
- "${DB_DATA_PATH}:/var/lib/mysql"
|
||||
environment:
|
||||
- MARIADB_ROOT_PASSWORD=${DB_PASSWORD}
|
||||
- MARIADB_DATABASE=${DB_DATABASE}
|
||||
- MARIADB_USER=${DB_USERNAME}
|
||||
- MARIADB_PASSWORD=${DB_PASSWORD}
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ENV_FILE="${ENV_FILE:-./.env}"
|
||||
LEGACY_BOOKSTACK_APP_KEY="base64:j1wQ2YbRrQ3j0tG5h6v8cYpV1gW9mN4uQ2xZ7aE3sT8="
|
||||
LEGACY_BOOKSTACK_DB_PASSWORD="bookstack-change-me"
|
||||
|
||||
read_env_value() {
|
||||
local key="$1"
|
||||
|
||||
if [[ ! -f "$ENV_FILE" ]] || ! grep -qE "^${key}=" "$ENV_FILE"; then
|
||||
return
|
||||
fi
|
||||
|
||||
local current
|
||||
current="$(sed -n -E "s/^${key}=//p" "$ENV_FILE" | tail -n 1)"
|
||||
current="${current%\"}"
|
||||
current="${current#\"}"
|
||||
current="${current%\'}"
|
||||
current="${current#\'}"
|
||||
printf '%s\n' "$current"
|
||||
}
|
||||
|
||||
read_cache_value() {
|
||||
local cache_file="$1"
|
||||
if [[ ! -s "$cache_file" ]]; then
|
||||
return
|
||||
fi
|
||||
sed -n '1p' "$cache_file" | tr -d '\r\n'
|
||||
}
|
||||
|
||||
write_cache_value() {
|
||||
local cache_file="$1"
|
||||
local value="$2"
|
||||
|
||||
mkdir -p "$(dirname "$cache_file")"
|
||||
printf '%s\n' "$value" > "$cache_file"
|
||||
chmod 600 "$cache_file" 2>/dev/null || true
|
||||
}
|
||||
|
||||
escape_sed_replacement() {
|
||||
printf '%s' "$1" | sed -e 's/[\/&|]/\\&/g'
|
||||
}
|
||||
|
||||
set_env_value() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
echo "$ENV_FILE not found; skipped $key generation"
|
||||
return
|
||||
fi
|
||||
|
||||
local replacement
|
||||
replacement="$(escape_sed_replacement "$value")"
|
||||
if grep -qE "^${key}=" "$ENV_FILE"; then
|
||||
sed -i -E "s|^${key}=.*|${key}=${replacement}|" "$ENV_FILE"
|
||||
echo "Updated $key"
|
||||
return
|
||||
fi
|
||||
|
||||
printf '%s=%s\n' "$key" "$value" >> "$ENV_FILE"
|
||||
echo "Added $key"
|
||||
}
|
||||
|
||||
generate_alnum_secret() {
|
||||
local secret=""
|
||||
local chunk=""
|
||||
while [[ ${#secret} -lt 32 ]]; do
|
||||
chunk="$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c $((32 - ${#secret})) || true)"
|
||||
secret="${secret}${chunk}"
|
||||
done
|
||||
printf '%s\n' "$secret"
|
||||
}
|
||||
|
||||
generate_laravel_app_key() {
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
printf 'base64:%s\n' "$(openssl rand -base64 32 | tr -d '\r\n')"
|
||||
return
|
||||
fi
|
||||
|
||||
if command -v base64 >/dev/null 2>&1; then
|
||||
printf 'base64:%s\n' "$(head -c 32 /dev/urandom | base64 | tr -d '\r\n')"
|
||||
return
|
||||
fi
|
||||
|
||||
generate_alnum_secret
|
||||
}
|
||||
|
||||
laravel_app_key_is_valid() {
|
||||
local value="$1"
|
||||
[[ "$value" =~ ^base64:[A-Za-z0-9+/=]{43,}$ ]] && return 0
|
||||
[[ "$value" =~ ^[A-Za-z0-9]{32,}$ ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
CONFIG_PATH_VALUE="${CONFIG_PATH:-$(read_env_value CONFIG_PATH || true)}"
|
||||
CONFIG_PATH_VALUE="${CONFIG_PATH_VALUE:-./data/config}"
|
||||
APP_KEY_CACHE="${APP_KEY_CACHE:-${CONFIG_PATH_VALUE}/.bookstack_app_key}"
|
||||
DB_PASSWORD_CACHE="${DB_PASSWORD_CACHE:-${CONFIG_PATH_VALUE}/.bookstack_db_password}"
|
||||
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
app_key="$(read_env_value APP_KEY || true)"
|
||||
cached_app_key="$(read_cache_value "$APP_KEY_CACHE" || true)"
|
||||
if laravel_app_key_is_valid "$app_key" && [[ "$app_key" != "$LEGACY_BOOKSTACK_APP_KEY" ]]; then
|
||||
write_cache_value "$APP_KEY_CACHE" "$app_key"
|
||||
elif laravel_app_key_is_valid "$cached_app_key"; then
|
||||
set_env_value "APP_KEY" "$cached_app_key"
|
||||
else
|
||||
app_key="$(generate_laravel_app_key)"
|
||||
set_env_value "APP_KEY" "$app_key"
|
||||
write_cache_value "$APP_KEY_CACHE" "$app_key"
|
||||
fi
|
||||
|
||||
db_password="$(read_env_value DB_PASSWORD || true)"
|
||||
cached_db_password="$(read_cache_value "$DB_PASSWORD_CACHE" || true)"
|
||||
if [[ -n "$db_password" && "$db_password" != "$LEGACY_BOOKSTACK_DB_PASSWORD" ]]; then
|
||||
write_cache_value "$DB_PASSWORD_CACHE" "$db_password"
|
||||
elif [[ -n "$cached_db_password" ]]; then
|
||||
set_env_value "DB_PASSWORD" "$cached_db_password"
|
||||
else
|
||||
db_password="$(generate_alnum_secret)"
|
||||
set_env_value "DB_PASSWORD" "$db_password"
|
||||
write_cache_value "$DB_PASSWORD_CACHE" "$db_password"
|
||||
fi
|
||||
fi
|
||||
|
||||
paths=(
|
||||
"${CONFIG_PATH:-./data/config}"
|
||||
"${DB_DATA_PATH:-./data/db}"
|
||||
)
|
||||
|
||||
mkdir -p "${paths[@]}"
|
||||
for path in "${paths[@]}"; do
|
||||
case "$path" in
|
||||
./*|../*) chown -R 1000:1000 "$path" 2>/dev/null || true ;;
|
||||
esac
|
||||
done
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
docker-compose down --volumes
|
||||
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ENV_FILE="${ENV_FILE:-./.env}"
|
||||
LEGACY_BOOKSTACK_APP_KEY="base64:j1wQ2YbRrQ3j0tG5h6v8cYpV1gW9mN4uQ2xZ7aE3sT8="
|
||||
LEGACY_BOOKSTACK_DB_PASSWORD="bookstack-change-me"
|
||||
|
||||
ensure_env_default() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
echo "$ENV_FILE not found; skipped $key migration"
|
||||
return
|
||||
fi
|
||||
|
||||
if grep -qE "^${key}=" "$ENV_FILE"; then
|
||||
echo "$key already exists"
|
||||
return
|
||||
fi
|
||||
|
||||
printf '%s=%s\n' "$key" "$value" >> "$ENV_FILE"
|
||||
echo "Added $key"
|
||||
}
|
||||
|
||||
read_env_value() {
|
||||
local key="$1"
|
||||
|
||||
if [[ ! -f "$ENV_FILE" ]] || ! grep -qE "^${key}=" "$ENV_FILE"; then
|
||||
return
|
||||
fi
|
||||
|
||||
local current
|
||||
current="$(sed -n -E "s/^${key}=//p" "$ENV_FILE" | tail -n 1)"
|
||||
current="${current%\"}"
|
||||
current="${current#\"}"
|
||||
current="${current%\'}"
|
||||
current="${current#\'}"
|
||||
printf '%s\n' "$current"
|
||||
}
|
||||
|
||||
read_cache_value() {
|
||||
local cache_file="$1"
|
||||
if [[ ! -s "$cache_file" ]]; then
|
||||
return
|
||||
fi
|
||||
sed -n '1p' "$cache_file" | tr -d '\r\n'
|
||||
}
|
||||
|
||||
write_cache_value() {
|
||||
local cache_file="$1"
|
||||
local value="$2"
|
||||
|
||||
mkdir -p "$(dirname "$cache_file")"
|
||||
printf '%s\n' "$value" > "$cache_file"
|
||||
chmod 600 "$cache_file" 2>/dev/null || true
|
||||
}
|
||||
|
||||
escape_sed_replacement() {
|
||||
printf '%s' "$1" | sed -e 's/[\/&|]/\\&/g'
|
||||
}
|
||||
|
||||
set_env_value() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
echo "$ENV_FILE not found; skipped $key generation"
|
||||
return
|
||||
fi
|
||||
|
||||
local replacement
|
||||
replacement="$(escape_sed_replacement "$value")"
|
||||
if grep -qE "^${key}=" "$ENV_FILE"; then
|
||||
sed -i -E "s|^${key}=.*|${key}=${replacement}|" "$ENV_FILE"
|
||||
echo "Updated $key"
|
||||
return
|
||||
fi
|
||||
|
||||
printf '%s=%s\n' "$key" "$value" >> "$ENV_FILE"
|
||||
echo "Added $key"
|
||||
}
|
||||
|
||||
generate_alnum_secret() {
|
||||
local secret=""
|
||||
local chunk=""
|
||||
while [[ ${#secret} -lt 32 ]]; do
|
||||
chunk="$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c $((32 - ${#secret})) || true)"
|
||||
secret="${secret}${chunk}"
|
||||
done
|
||||
printf '%s\n' "$secret"
|
||||
}
|
||||
|
||||
generate_laravel_app_key() {
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
printf 'base64:%s\n' "$(openssl rand -base64 32 | tr -d '\r\n')"
|
||||
return
|
||||
fi
|
||||
|
||||
if command -v base64 >/dev/null 2>&1; then
|
||||
printf 'base64:%s\n' "$(head -c 32 /dev/urandom | base64 | tr -d '\r\n')"
|
||||
return
|
||||
fi
|
||||
|
||||
generate_alnum_secret
|
||||
}
|
||||
|
||||
laravel_app_key_is_valid() {
|
||||
local value="$1"
|
||||
[[ "$value" =~ ^base64:[A-Za-z0-9+/=]{43,}$ ]] && return 0
|
||||
[[ "$value" =~ ^[A-Za-z0-9]{32,}$ ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
CONFIG_PATH_VALUE="${CONFIG_PATH:-$(read_env_value CONFIG_PATH || true)}"
|
||||
CONFIG_PATH_VALUE="${CONFIG_PATH_VALUE:-./data/config}"
|
||||
APP_KEY_CACHE="${APP_KEY_CACHE:-${CONFIG_PATH_VALUE}/.bookstack_app_key}"
|
||||
DB_PASSWORD_CACHE="${DB_PASSWORD_CACHE:-${CONFIG_PATH_VALUE}/.bookstack_db_password}"
|
||||
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
app_key="$(read_env_value APP_KEY || true)"
|
||||
cached_app_key="$(read_cache_value "$APP_KEY_CACHE" || true)"
|
||||
if laravel_app_key_is_valid "$app_key" && [[ "$app_key" != "$LEGACY_BOOKSTACK_APP_KEY" ]]; then
|
||||
write_cache_value "$APP_KEY_CACHE" "$app_key"
|
||||
elif laravel_app_key_is_valid "$cached_app_key"; then
|
||||
set_env_value "APP_KEY" "$cached_app_key"
|
||||
else
|
||||
app_key="$(generate_laravel_app_key)"
|
||||
set_env_value "APP_KEY" "$app_key"
|
||||
write_cache_value "$APP_KEY_CACHE" "$app_key"
|
||||
fi
|
||||
|
||||
db_password="$(read_env_value DB_PASSWORD || true)"
|
||||
cached_db_password="$(read_cache_value "$DB_PASSWORD_CACHE" || true)"
|
||||
if [[ -n "$db_password" && "$db_password" != "$LEGACY_BOOKSTACK_DB_PASSWORD" ]]; then
|
||||
write_cache_value "$DB_PASSWORD_CACHE" "$db_password"
|
||||
elif [[ -n "$cached_db_password" ]]; then
|
||||
set_env_value "DB_PASSWORD" "$cached_db_password"
|
||||
else
|
||||
db_password="$(generate_alnum_secret)"
|
||||
set_env_value "DB_PASSWORD" "$db_password"
|
||||
write_cache_value "$DB_PASSWORD_CACHE" "$db_password"
|
||||
fi
|
||||
|
||||
ensure_env_default "DB_HOST" "bookstack-db"
|
||||
ensure_env_default "DB_PORT" "3306"
|
||||
ensure_env_default "DB_USERNAME" "bookstack"
|
||||
ensure_env_default "DB_DATABASE" "bookstack"
|
||||
ensure_env_default "QUEUE_CONNECTION" ""
|
||||
else
|
||||
echo "$ENV_FILE not found; skipped LinuxServer environment migration"
|
||||
fi
|
||||
Reference in New Issue
Block a user