# BookStack upgrade

你現在已經在 **Ubuntu 24.04 新主機安裝最新版 BookStack**，所以不需要在舊站逐版升級。正確方式是：

> 將舊版 v21.08.1 的資料庫與上傳檔案還原到新主機，然後由最新版 BookStack 執行 `php artisan migrate`，一次將資料庫結構升級到最新版。

BookStack 官方也明確說明：還原到較新版本時，匯入資料庫後執行 `php artisan migrate` 即可完成必要的資料庫更新。([BookStack](https://www.bookstackapp.com/docs/admin/backup-restore/?utm_source=chatgpt.com "Backup and Restore"))

---

# 一、最重要的注意事項

你目前新站安裝腳本已經執行過：

```bash
php artisan key:generate
php artisan migrate

```

因此現在新站有：

- 一個全新的空白 BookStack 資料庫
- 一個新的 `APP_KEY`
- 預設管理者 `admin@admin.com`
- 最新版的程式碼

接下來要做的是：

1. 備份新站設定。
2. 停止舊站寫入。
3. 備份舊站資料庫。
4. 備份舊站上傳檔案。
5. 將舊站資料庫匯入新站。
6. 保留或搬移舊站 `APP_KEY`。
7. 執行新版 migration。
8. 修正目錄權限。
9. 測試登入、圖片和附件。

---

# 二、APP\_KEY 到底要用新的還是舊的

這是整個搬移最容易忽略的地方。

## 建議使用舊站 APP\_KEY

從舊站取得：

```bash
grep '^APP_KEY=' /var/www/bookstack/.env

```

例如：

```text
APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=

```

然後將這個值放到新站 `.env`：

```bash
vi /var/www/bookstack/.env

```

原因是舊資料庫內可能包含由 Laravel 加密保存的資料。若換成新的 `APP_KEY`，某些加密內容可能無法解密。

因此：

```text
資料庫來自舊站
APP_KEY 也應來自舊站

```

不要再次執行：

```bash
php artisan key:generate

```

除非你確定舊資料庫完全沒有任何依賴舊金鑰的加密資料。

## 新站資料庫帳密則保留新的

新站 `.env` 可以採混合方式：

```dotenv
APP_KEY=舊站的APP_KEY

DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=bookstack
DB_USERNAME=bookstack
DB_PASSWORD=新主機安裝腳本產生的密碼

```

也就是：

<table id="bkmrk-%E8%A8%AD%E5%AE%9A-%E4%BD%BF%E7%94%A8%E4%BE%86%E6%BA%90-app_key-%E8%88%8A%E7%AB%99-a"><thead><tr><th>設定</th><th>使用來源</th></tr></thead><tbody><tr><td>`APP_KEY`</td><td>舊站</td></tr><tr><td>`APP_URL`</td><td>新站</td></tr><tr><td>`DB_HOST`</td><td>新站</td></tr><tr><td>`DB_DATABASE`</td><td>新站</td></tr><tr><td>`DB_USERNAME`</td><td>新站</td></tr><tr><td>`DB_PASSWORD`</td><td>新站</td></tr><tr><td>LDAP、郵件、OIDC 等</td><td>視需求由舊站搬移</td></tr></tbody></table>

官方也建議還原時合併新舊 `.env`，通常保留新環境的資料庫設定，再帶入舊環境需要的應用設定。([BookStack](https://www.bookstackapp.com/docs/admin/backup-restore/?utm_source=chatgpt.com "Backup and Restore"))

---

# 三、舊主機完整備份

以下假設舊站目錄也是：

```text
/var/www/bookstack

```

## 1. 建立備份目錄

```bash
mkdir -p /root/bookstack-migration
cd /root/bookstack-migration

```

## 2. 開啟維護模式

在舊主機執行：

```bash
cd /var/www/bookstack
php artisan down

```

如果舊版 artisan 維護模式有問題，也可以暫停 Apache、Nginx 或 PHP-FPM：

```bash
systemctl stop apache2

```

或者：

```bash
systemctl stop nginx

```

目的是避免備份資料庫期間還有人修改頁面。

---

## 3. 查詢舊站資料庫設定

```bash
grep -E '^(DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' \
  /var/www/bookstack/.env

```

假設結果：

```dotenv
DB_HOST=localhost
DB_DATABASE=bookstack
DB_USERNAME=bookstack
DB_PASSWORD=old-password

```

---

## 4. 備份舊資料庫

```bash
mysqldump \
  --single-transaction \
  --quick \
  --routines \
  --triggers \
  --events \
  --hex-blob \
  --default-character-set=utf8mb4 \
  -u bookstack \
  -p \
  bookstack \
  > /root/bookstack-migration/bookstack-v21.sql

```

輸入舊站資料庫密碼。

檢查：

```bash
ls -lh /root/bookstack-migration/bookstack-v21.sql
head -n 10 /root/bookstack-migration/bookstack-v21.sql
tail -n 10 /root/bookstack-migration/bookstack-v21.sql

```

確認檔案不是 0 bytes，尾端通常會有：

```text
Dump completed

```

## 5. 備份舊站 `.env`

```bash
cp -a /var/www/bookstack/.env \
  /root/bookstack-migration/bookstack-old.env

```

另外直接記錄 APP\_KEY：

```bash
grep '^APP_KEY=' /var/www/bookstack/.env \
  > /root/bookstack-migration/app-key.txt

```

---

# 四、備份哪些上傳檔案

BookStack 的大部分頁面內容都在資料庫內，但圖片、附件等檔案會存在檔案系統。([BookStack](https://www.bookstackapp.com/docs/admin/content-storage/?utm_source=chatgpt.com "Content Storage Format"))

至少備份：

```text
public/uploads/
storage/uploads/

```

比較保險的方式：

```bash
cd /var/www/bookstack

tar czpf /root/bookstack-migration/bookstack-files.tar.gz \
  public/uploads \
  storage/uploads

```

如果有自訂主題，再加入：

```bash
tar czpf /root/bookstack-migration/bookstack-files.tar.gz \
  public/uploads \
  storage/uploads \
  themes

```

檢查內容：

```bash
tar tzf /root/bookstack-migration/bookstack-files.tar.gz | head -n 30

```

## 建議額外備份整個舊站

雖然不能把整個舊程式直接覆蓋到新版，但可以留作查核：

```bash
tar czpf /root/bookstack-migration/bookstack-old-full.tar.gz \
  -C /var/www bookstack

```

---

# 五、將備份傳到新主機

假設新主機 IP：

```text
10.0.0.20

```

在舊主機執行：

```bash
scp /root/bookstack-migration/bookstack-v21.sql \
    /root/bookstack-migration/bookstack-files.tar.gz \
    /root/bookstack-migration/bookstack-old.env \
    root@10.0.0.20:/root/

```

或使用 rsync：

```bash
rsync -avP /root/bookstack-migration/ \
  root@10.0.0.20:/root/bookstack-migration/

```

---

# 六、新主機先備份現有安裝

在新主機執行：

```bash
mkdir -p /root/bookstack-before-restore

```

備份目前 `.env`：

```bash
cp -a /var/www/bookstack/.env \
  /root/bookstack-before-restore/new-install.env

```

備份新資料庫：

```bash
mysqldump -u bookstack -p bookstack \
  > /root/bookstack-before-restore/new-empty-bookstack.sql

```

查看新站資料庫密碼：

```bash
grep '^DB_PASSWORD=' /var/www/bookstack/.env

```

---

# 七、讓新站進入維護狀態

```bash
cd /var/www/bookstack
php artisan down

```

停止 Apache，避免匯入期間有人連入：

```bash
systemctl stop apache2

```

PHP-FPM可以先不停止。

---

# 八、清空新站資料庫

因為安裝腳本已經建立最新版空白資料庫，不能直接把舊 SQL 疊加進去，否則會出現：

```text
Table already exists
Duplicate entry

```

先確認資料庫帳密：

```bash
grep -E '^(DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' \
  /var/www/bookstack/.env

```

## 方法一：刪除並重建資料庫

以 root 執行：

```bash
mysql -u root <<'SQL'
DROP DATABASE IF EXISTS bookstack;
CREATE DATABASE bookstack
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON bookstack.* TO 'bookstack'@'localhost';
FLUSH PRIVILEGES;
SQL

```

你的安裝腳本建立使用者時用了：

```sql
'bookstack'@'localhost'

```

所以權限要授予相同帳號。

確認：

```bash
mysql -u root -e "
SELECT User, Host, plugin
FROM mysql.user
WHERE User='bookstack';
"

```

---

# 九、匯入舊版資料庫

```bash
mysql \
  -u bookstack \
  -p \
  --default-character-set=utf8mb4 \
  bookstack \
  < /root/bookstack-v21.sql

```

輸入新主機 BookStack 資料庫使用者密碼。

檢查資料表：

```bash
mysql -u bookstack -p bookstack -e 'SHOW TABLES;'

```

檢查頁面與使用者數量：

```bash
mysql -u bookstack -p bookstack <<'SQL'
SELECT COUNT(*) AS users FROM users;
SELECT COUNT(*) AS books FROM books;
SELECT COUNT(*) AS chapters FROM chapters;
SELECT COUNT(*) AS pages FROM pages;
SQL

```

---

# 十、合併新舊 `.env`

不要直接用舊 `.env` 完整覆蓋新站，因為舊設定可能含有已棄用參數，資料庫帳密和 URL 也可能不同。

先做對比：

```bash
diff -u \
  /var/www/bookstack/.env \
  /root/bookstack-old.env

```

## 建議至少修改這些項目

```bash
vi /var/www/bookstack/.env

```

範例：

```dotenv
APP_KEY=舊站的APP_KEY

APP_URL=https://bookstack.treemanou.com

DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=bookstack
DB_USERNAME=bookstack
DB_PASSWORD=新站安裝腳本產生的密碼

```

舊站如果有以下設定，也要逐項搬移：

```dotenv
MAIL_DRIVER=
MAIL_HOST=
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_FROM=
MAIL_FROM_NAME=

AUTH_METHOD=
LDAP_SERVER=
LDAP_BASE_DN=
LDAP_DN=
LDAP_PASS=
LDAP_USER_FILTER=
LDAP_VERSION=

OIDC_NAME=
OIDC_DISPLAY_NAME_CLAIMS=
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_ISSUER=
OIDC_ISSUER_DISCOVER=

SAML2_NAME=
SAML2_EMAIL_ATTRIBUTE=
SAML2_EXTERNAL_ID_ATTRIBUTE=

```

查看舊站非註解設定：

```bash
grep -Ev '^(#|$)' /root/bookstack-old.env

```

注意不要把密碼貼到公開環境。

---

# 十一、還原圖片與附件

進入新版 BookStack 目錄：

```bash
cd /var/www/bookstack

```

先看看壓縮檔內容：

```bash
tar tzf /root/bookstack-files.tar.gz | head

```

如果內容路徑是：

```text
public/uploads/...
storage/uploads/...

```

直接解壓：

```bash
tar xvzf /root/bookstack-files.tar.gz \
  -C /var/www/bookstack

```

官方還原方式也是將備份檔案解壓回 BookStack 原始位置。([BookStack](https://www.bookstackapp.com/docs/admin/backup-restore/?utm_source=chatgpt.com "Backup and Restore"))

---

# 十二、執行最新版資料庫 migration

這一步才是真正把 v21.08.1 升級到最新版。

```bash
cd /var/www/bookstack

```

先確認 PHP 與 Composer：

```bash
php -v
composer --version

```

確認 BookStack Git 狀態：

```bash
git status
git branch --show-current
git log -1 --oneline

```

重新確保 PHP dependencies 正確：

```bash
export COMPOSER_ALLOW_SUPERUSER=1

composer install \
  --no-dev \
  --no-interaction \
  --prefer-dist \
  --optimize-autoloader

```

執行 migration：

```bash
php artisan migrate --force -vvv \
  2>&1 | tee /root/bookstack-migrate.log

```

查看結果：

```bash
php artisan migrate:status

```

正常情況下所有 migration 都應為：

```text
Ran

```

BookStack 官方標準更新流程就是更新程式、安裝 Composer dependencies，再執行 `php artisan migrate`。([BookStack](https://www.bookstackapp.com/docs/admin/updates/?utm_source=chatgpt.com "Updating BookStack"))

---

# 十三、清除新版快取

```bash
cd /var/www/bookstack

php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

```

先不要急著執行 `config:cache`，確認網站正常後再決定是否建立快取。

---

# 十四、修正檔案權限

你的安裝腳本將 owner 設為執行安裝腳本的使用者，group 是 `www-data`。

你是以 root 執行，所以目前多半是：

```text
root:www-data

```

可以沿用：

```bash
cd /var/www/bookstack

chown -R root:www-data ./
chmod -R 755 ./

chmod -R 775 \
  bootstrap/cache \
  public/uploads \
  storage

chmod 740 .env

```

更精確地設定：

```bash
find bootstrap/cache public/uploads storage \
  -type d -exec chmod 775 {} \;

find bootstrap/cache public/uploads storage \
  -type f -exec chmod 664 {} \;

```

BookStack需要 Web/PHP 執行帳號能讀寫 `storage`、`bootstrap/cache` 和上傳目錄。([BookStack](https://www.bookstackapp.com/docs/admin/filesystem-permissions/?utm_source=chatgpt.com "Filesystem Permissions"))

確認 PHP-FPM 使用者：

```bash
grep -E '^(user|group) =' /etc/php/8.3/fpm/pool.d/www.conf

```

通常會是：

```text
user = www-data
group = www-data

```

---

# 十五、啟動服務

```bash
systemctl restart php8.3-fpm
systemctl start apache2

```

確認：

```bash
systemctl status php8.3-fpm --no-pager
systemctl status apache2 --no-pager
apachectl configtest

```

離開維護模式：

```bash
cd /var/www/bookstack
php artisan up

```

---

# 十六、檢查日誌

BookStack：

```bash
tail -n 200 /var/www/bookstack/storage/logs/laravel.log

```

Apache：

```bash
tail -n 200 /var/log/apache2/error.log

```

PHP-FPM：

```bash
journalctl -u php8.3-fpm -n 200 --no-pager

```

即時追蹤：

```bash
tail -f \
  /var/www/bookstack/storage/logs/laravel.log \
  /var/log/apache2/error.log

```

---

# 十七、如果新舊網址不同

例如：

舊網址：

```text
http://10.1.1.10

```

新網址：

```text
https://bookstack.treemanou.com

```

BookStack資料庫內有些圖片和連結會保存絕對網址，需要執行 URL 替換。

先備份資料庫：

```bash
mysqldump -u bookstack -p bookstack \
  > /root/bookstack-before-url-update.sql

```

執行：

```bash
cd /var/www/bookstack

php artisan bookstack:update-url \
  'http://10.1.1.10' \
  'https://bookstack.treemanou.com'

```

BookStack官方指出，變更 `APP_URL` 後需要更新資料庫內保存的絕對網址，否則可能出現圖片或連結失效。([BookStack](https://www.bookstackapp.com/docs/admin/debugging/?utm_source=chatgpt.com "Debugging Errors"))

完成後：

```bash
php artisan cache:clear
php artisan config:clear

```

---

# 十八、你的安裝腳本有一個小問題

這段：

```bash
apt install -y git unzip apache2 curl mysql-server-8.0 php8.3 \
php8.3-fpm ...

```

後面使用：

```bash
systemctl start mysql-server.service

```

Ubuntu 24.04 通常服務名稱是：

```bash
mysql.service

```

建議改成：

```bash
systemctl enable --now mysql

```

檢查目前實際服務：

```bash
systemctl status mysql
systemctl status mysql-server

```

另外：

```bash
CREATE USER 'bookstack'@'localhost'
IDENTIFIED WITH mysql_native_password

```

MySQL 8.0 可以使用，但新環境通常更建議使用預設的：

```sql
caching_sha2_password

```

例如：

```sql
CREATE USER 'bookstack'@'localhost'
IDENTIFIED BY 'password';

```

不過你目前既然已安裝成功，這不是搬移前必須修改的項目。

---

# 十九、建議你實際執行的最短流程

## 舊主機

```bash
cd /var/www/bookstack
php artisan down

mkdir -p /root/bookstack-migration

mysqldump \
  --single-transaction \
  --quick \
  --routines \
  --triggers \
  --hex-blob \
  --default-character-set=utf8mb4 \
  -u bookstack -p bookstack \
  > /root/bookstack-migration/bookstack-v21.sql

cp -a .env /root/bookstack-migration/bookstack-old.env

tar czpf /root/bookstack-migration/bookstack-files.tar.gz \
  public/uploads \
  storage/uploads

```

傳到新主機：

```bash
scp /root/bookstack-migration/* root@新主機IP:/root/

```

## 新主機

```bash
cd /var/www/bookstack
php artisan down
systemctl stop apache2

```

保留新站資料庫密碼，但將 `.env` 的 `APP_KEY` 改成舊站值。

清空資料庫：

```bash
mysql -u root <<'SQL'
DROP DATABASE IF EXISTS bookstack;
CREATE DATABASE bookstack
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON bookstack.* TO 'bookstack'@'localhost';
FLUSH PRIVILEGES;
SQL

```

匯入：

```bash
mysql -u bookstack -p bookstack < /root/bookstack-v21.sql

```

還原檔案：

```bash
tar xvzf /root/bookstack-files.tar.gz \
  -C /var/www/bookstack

```

升級：

```bash
cd /var/www/bookstack

composer install \
  --no-dev \
  --no-interaction \
  --prefer-dist \
  --optimize-autoloader

php artisan migrate --force

php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

```

權限：

```bash
chown -R root:www-data /var/www/bookstack
chmod -R 755 /var/www/bookstack
chmod -R 775 \
  /var/www/bookstack/bootstrap/cache \
  /var/www/bookstack/public/uploads \
  /var/www/bookstack/storage
chmod 740 /var/www/bookstack/.env

```

啟動：

```bash
systemctl restart php8.3-fpm
systemctl start apache2

cd /var/www/bookstack
php artisan up

```

這樣就是 **舊資料直接遷移到新安裝的最新版程式，再由 migration 將資料庫從 v21.08.1 升級到 v26.05.2**。