Skip to content
View in the app

A better way to browse. Learn more.

PHP论坛人

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Debian 13 自動安全更新

Featured Replies

適用環境

作業系統:Debian 13

VPS規格:2 vCPU / 2GB RAM

權限要求:需具備 root 權限或 sudo 權限

網路需求:需能連線至 Debian 官方套件庫





----------
前言
----------

對於長期運行的論壇網站,自動安全更新是降低人工維護成本、及時修補已知漏洞的第一道防線

然而,不加控制的自動更新同樣可能破壞生產環境,例如,核心升級觸發重開機、PHP版本跳升導致擴充套件相容性斷裂等

本文的目標是在「及時修補安全漏洞」與「維持服務穩定」之間取得平衡,並提供足夠的監控機制讓團隊掌握每一次更新的狀態


-----------------------
事前準備與快照備份
-----------------------

強烈建議:在任何系統層級變更前,先對VPS建立快照(Snapshot)或映像備份

這是生產環境的基本操作紀律,不論操作多熟練皆不應跳過


---------------------
確認目前系統版本
---------------------

cat /etc/os-release


uname -r



預期輸出

PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
...
6.12.xx+deb13-cloud-amd64






----------------------------
確認APT套件庫來源正常
----------------------------

apt update


若出現 404 Not Found 或 GPG 錯誤,必須先修正 /etc/apt/sources.list 再繼續,否則後續步驟都無意義


Debian 13 標準 sources.list 參考

deb http://deb.debian.org/debian trixie main contrib non-free-firmware
deb http://deb.debian.org/debian trixie-updates main contrib non-free-firmware
deb http://security.debian.org/debian-security trixie-security main contrib non-free-firmware


---------------------
全面更新現有套件
---------------------

在設定自動更新前,應先手動將系統更新至最新狀態,確保基線一致

apt update -y && apt upgrade -y



提示:升級過程若出現「是否覆蓋設定檔?」提示,建議選 N(保留原有設定)

避免覆蓋 /etc/nginx/nginx.conf、/etc/mysql/ 等自訂組態



-------------------------
升級後清理多餘套件
-------------------------

apt autoremove --purge -y


apt clean



----------------------
安裝必要套件
----------------------

apt install -y unattended-upgrades apt-listchanges needrestart







說明:
unattended-upgrades  自動安全更新的核心引擎

apt-listchanges  更新前顯示套件變更摘要,有助於審閱 changelog

needrestart  偵測哪些服務使用了已更新的函式庫,提示需重啟的服務


新手容易遺漏:needrestart 是避免「套件已更新但舊版函式庫仍在記憶體中執行」的關鍵工具

例如 OpenSSL 更新後,若 Nginx 未重啟,仍會繼續使用舊版 libssl,安全修補形同虛設




------------------------
啟用自動安全更新
------------------------

啟用自動安全更新
dpkg-reconfigure --priority=low unattended-upgrades



畫面將出現:
Automatically download and install stable updates?
<Yes> /  <No>


選擇 <Yes>,確認啟用自動下載並安裝穩定版更新



-----------------------------------
設定更新來源規則(僅安全更新)
-----------------------------------

此檔案定義哪些套件庫的更新會被自動安裝,以及各項行為控制



寫入生產環境設定
vi /etc/apt/apt.conf.d/50unattended-upgrades



貼上以下內容



// =========================
// 自動安全更新設定 - LNMP 環境
// 最後修改:請填入日期與操作人員
// =========================

Unattended-Upgrade::Origins-Pattern {
    // Debian 官方穩定版
    "origin=Debian,codename=${distro_codename},label=Debian";
    // Debian 安全更新(兩種格式皆需保留,視 Debian 版本而定)
    "origin=Debian,codename=${distro_codename},label=Debian-Security";
    "origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};

// 套件黑名單:以下套件不會被自動更新
Unattended-Upgrade::Package-Blacklist {
    // 核心:自動更新核心可能觸發重開機或模組相容性問題
    "linux-image-*";
    "linux-headers-*";
    "linux-modules-*";

    // PHP:版本跳升可能破壞論壇擴充套件(如 IPS、XenForo)
    // 若確認論壇相容,可移除以下黑名單項目
    "php*";

    // MySQL / MariaDB:主版本升級需要手動 schema 遷移
    "mysql-server*";
    "mariadb-server*";

    // Nginx:主要設定變更需人工確認
    // 安全性修補通常可接受,依環境決定是否保留此黑名單
    // "nginx*";
};

// 是否自動重開機(生產環境強烈建議 false)
Unattended-Upgrade::Automatic-Reboot "false";

// 若上方設定為 true,指定重開機時間(避開尖峰時段)
Unattended-Upgrade::Automatic-Reboot-Time "08:00";

// 是否允許在有使用者登入時自動重開機
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";

// 自動移除已不需要的核心套件(節省 /boot 空間)
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";

// 自動移除更新後不再需要的相依套件
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

// 自動移除已廢棄套件
Unattended-Upgrade::Remove-Unused-Dependencies "true";

// 寄送更新通知 Email(需有 MTA,如 msmtp / postfix)
// Unattended-Upgrade::Mail "your-sre-team@example.com";
// Unattended-Upgrade::MailReport "on-change";  // only-on-error | on-change | always

// 分割差異:僅在發生錯誤時寄信(減少通知噪音)
Unattended-Upgrade::MailOnlyOnError "true";

// 詳細日誌(建議 production 環境開啟,便於事後審計)
Unattended-Upgrade::Verbose "false";

// 最小化 APT 輸出(減少日誌雜訊)
Unattended-Upgrade::MinimalSteps "true";




儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter



提醒:php* 黑名單在論壇環境非常重要

Debian 安全更新有時會一併跳升 PHP 次版本(如 8.2 → 8.3)

可能導致舊版論壇外掛或 composer.lock 鎖定的套件出現相容性問題,應先在測試環境驗證後再手動升級



------------------------
啟用自動更新排程
------------------------

APT的定期排程由 apt.conf.d/20auto-upgrades 控制


編輯
vi /etc/apt/apt.conf.d/20auto-upgrades


貼上以下內容



// 每天更新套件清單
APT::Periodic::Update-Package-Lists "1";

// 每天下載可升級的套件(但不安裝,由 Unattended-Upgrade 控制)
APT::Periodic::Download-Upgradeable-Packages "1";

// 每 7 天自動清除已下載但不再需要的套件快取
APT::Periodic::AutocleanInterval "7";

// 每天執行自動更新(值為間隔天數)
APT::Periodic::Unattended-Upgrade "1";





儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter




----------------------------------------------------
重啟 unattended-upgrades 服務使設定生效
----------------------------------------------------

啟用
systemctl enable unattended-upgrades



重啟
systemctl restart unattended-upgrades



確認服務狀態,預期輸出應包含 active (running)
systemctl status unattended-upgrades



------------------------------------------------
確認 needrestart 設定(避免服務靜默中斷)
------------------------------------------------

needrestart 在套件更新後自動偵測哪些服務仍在使用舊版函式庫,是LNMP環境特別重要的環節


-----------------
查看預設設定
-----------------

cat /etc/needrestart/needrestart.conf | grep -v '^#' | grep -v '^$'


------------------
調整重啟模式
------------------

編輯
vi /etc/needrestart/needrestart.conf


搜尋
$nrconf{restart}


接著修改以下設定(生產環境建議使用 i 互動模式)


# 模式說明
# l = list only(僅列出,不重啟)← 生產環境推薦,人工確認後再重啟
# i = interactive(互動詢問)
# a = automatically(自動重啟服務,不含核心)← 可接受,但需謹慎
$nrconf{restart} = 'l';



建議:若論壇有 SLA 要求,應使用 l 模式,搭配後述的 Cron 監控,由維運人員在離峰時段手動重啟



---------------------------------
手動檢查需要重啟的服務
---------------------------------

needrestart -k


輸出示範:
NEEDRESTART-VER: 3.x
NEEDRESTART-SVC: nginx.service
NEEDRESTART-SVC: php8.3-fpm.service
NEEDRESTART-SVC: mariadb.service



看到以上輸出時,依序重啟(建議在低流量時段執行)


systemctl restart nginx


systemctl restart php8.3-fpm


systemctl restart mariadb





-----------------------------
重啟後確認各服務狀態
-----------------------------

systemctl status nginx php8.3-fpm mariadb



--------------------
重開機驗證
--------------------

初次設定完成後建議重開機,確保核心與服務以乾淨狀態啟動


重開機
reboot




重開機後驗證清單


確認自動更新服務正在運行,應顯示 active (running)
systemctl status unattended-upgrades



確認排程設定正確載入
apt-config dump APT::Periodic



預期顯示
APT::Periodic "";
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";








模擬執行自動更新(--dry-run 不會實際安裝套件)
unattended-upgrade --dry-run --verbose




確認LNMP核心服務正常 (此時還未安裝LNMP服務)
systemctl status nginx


systemctl status php8.3-fpm


systemctl status mariadb




確認論壇網站可正常回應 (此時還未安裝LNMP服務)
curl -I http://localhost





----------------------------------------
強制執行一次完整更新(驗證流程)
----------------------------------------

unattended-upgrade --verbose


執行後

查看日誌確認無錯誤
tail -50 /var/log/unattended-upgrades/unattended-upgrades.log



-----------------------------
監控自動更新執行狀態
-----------------------------

啟用
systemctl enable cron


啟動
systemctl start cron



檢查狀態,確認已運行 active (running)
systemctl status cron

---------------------

建立監控腳本

---------------------

比起直接在 crontab 寫複雜指令,建議將監控邏輯封裝成獨立腳本,方便維護與版本控管

建立

vi /usr/local/bin/check-unattended-upgrades.sh

check-unattended-upgrades.sh

貼上以下內容

儲存檔案並離開vi編輯器

按 Esc,輸入 :wq,按 Enter

Edited by Jack

  • Author
--------------------
給予執行權限
--------------------

chmod +x /usr/local/bin/check-unattended-upgrades.sh


chown root:root /usr/local/bin/check-unattended-upgrades.sh



-------------------------------
設定 Cron 排程
-------------------------------

編輯
crontab -e


在未尾加入以下內容



# ====================
# 自動更新監控排程
# ====================

# 每天早上 7:00 檢查自動更新是否有錯誤
0 7 * * * /usr/local/bin/check-unattended-upgrades.sh

# 每天早上 6:00 檢查 needrestart(列出需重啟服務但不自動重啟)
0 6 * * * /usr/sbin/needrestart -k >> /var/log/needrestart-daily.log 2>&1





儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter

------------------------
驗證監控腳本
------------------------

/usr/local/bin/check-unattended-upgrades.sh







--------------------------
定期維護建議
--------------------------

查看日誌目錄
ls -lah /var/log/unattended-upgrades/


即時監看日誌
tail -f /var/log/unattended-upgrades/unattended-upgrades.log


查看詳細除錯日誌
tail -f /var/log/unattended-upgrades/unattended-upgrades.log.1


建議每週至少檢查一次,確認:
無 ERROR 字樣
有正常的 Packages that will be upgraded: 記錄(或「無可用更新」)
更新時間點符合預期




unattended-upgrades 的日誌自帶 logrotate 設定,通常不需額外設定。確認方式:

cat /etc/logrotate.d/unattended-upgrades






---------------------------------------
定期清理舊核心(釋放 /boot 空間)
---------------------------------------

僅在確認新核心運作正常後執行(重開機後驗證 uname -r 版本)


查看目前使用的核心
uname -r


列出所有已安裝核心
dpkg --list | grep linux-image


自動移除舊核心(保留當前使用版本)
apt autoremove --purge -y



--------------------------
手動檢查安全性 CVE
--------------------------

自動更新補的是套件層級的安全修補,但部分 CVE 需要手動確認影響範圍:


查看 Debian Security Tracker(需連網)
https://security-tracker.debian.org/tracker/



本機檢查哪些套件有可用的安全更新
apt list --upgradable 2>/dev/null | grep -i security



-----------------------
測試環境先行原則
-----------------------

對於任何計畫性的手動升級(特別是黑名單中的 PHP、MariaDB、Nginx),務必遵循:

測試環境驗證 → 確認服務正常 → 安排維護時窗 → 生產環境升級 → 監控 15分鐘
  • Author
-------------------
常見問題排除
-------------------

問題一:服務未自動更新

確認服務狀態
systemctl status unattended-upgrades



若未啟動,手動啟動
systemctl start unattended-upgrades


systemctl enable unattended-upgrades




確認排程設定
apt-config dump APT::Periodic::Unattended-Upgrade






問題二:套件被保留(held back)


查看被保留的套件
apt-mark showhold


查看升級摘要
apt upgrade --simulate




問題三:更新失敗(網路問題)

確認 DNS 解析正常
host deb.debian.org


測試套件庫連線
curl -I http://deb.debian.org/debian/dists/trixie/Release


重建套件快取
apt clean

apt update




問題四:/boot 空間不足導致核心更新失敗

查看 /boot 使用狀況
df -h /boot

ls -lah /boot/


確認目前使用的核心版本
uname -r


移除舊核心(請確認要移除的版本不是目前使用中的)
apt autoremove --purge linux-image-<舊版本號>






問題五:unattended-upgrades 鎖定(lock file 問題)

確認是否有 lock 檔
ls -la /var/lib/dpkg/lock*

ls -la /var/lib/apt/lists/lock



確認是否有 apt 進程在執行
ps aux | grep apt



若無相關進程但 lock 仍存在(系統崩潰後的殘留)
確認無 apt 進程後再執行
rm /var/lib/dpkg/lock-frontend


rm /var/lib/dpkg/lock


dpkg --configure -a





問題六:更新後 Nginx / PHP-FPM / MariaDB 無法啟動

查看各服務錯誤日誌
journalctl -xe -u nginx --since "1 hour ago"


journalctl -xe -u php8.3-fpm --since "1 hour ago"


journalctl -xe -u mariadb --since "1 hour ago"




測試 Nginx 設定檔語法
nginx -t


測試 PHP-FPM 設定
php-fpm8.3 --test



若為設定檔被覆蓋導致,從備份恢復 (這也是為什麼升級時要選 N 保留原有設定)





---------------------------------
LNMP 論壇環境特別注意事項
---------------------------------

PHP 版本管理

論壇軟體(IPS、XenForo 等)對 PHP 版本相依性非常敏感

建議將 PHP 相關套件加入黑名單,並採用手動控制PHP版本升級的策略


查看目前安裝的 PHP 套件
dpkg --list | grep php


手動鎖定特定 PHP 版本(避免自動升級)
apt-mark hold php8.3 php8.3-fpm php8.3-mysql php8.3-common



確認鎖定狀態
apt-mark showhold



--------------------------------
MariaDB / MySQL 保護
--------------------------------

資料庫的主版本升級(如 MariaDB 10.x → 11.x)需要執行 mysql_upgrade 或 mariadb-upgrade,否則可能導致資料字典不一致

絕對不能讓自動更新自行完成主版本跳升

鎖定 MariaDB
apt-mark hold mariadb-server mariadb-client mariadb-common



------------------------
Nginx 安全更新策略
------------------------

Nginx 的安全更新風險相對低,但仍可能因 header 行為變更影響論壇的 CSP / CORS 設定

建議:
移除 50unattended-upgrades 中 Nginx 的黑名單註解(讓安全更新自動安裝)

但在 Cron 監控中加入 Nginx 重啟後的健康檢查




------------------------------
記憶體考量(2 GB RAM)
------------------------------

2GB RAM 的 VPS 在自動更新期間(通常在凌晨),系統負載會短暫升高

建議在 50unattended-upgrades 中確認 MinimalSteps "true" 已啟用,讓更新分批執行,降低記憶體峰值壓力


同時確認論壇的 PHP-FPM 設定合理

查看 PHP-FPM 進程設定(避免 OOM)
cat /etc/php/8.3/fpm/pool.d/www.conf | grep -E "pm\.|max_children|memory"



建議 pm.max_children 不超過 (可用記憶體 MB / 平均每個 PHP 進程記憶體) 的計算結果

在 2GB 環境下,若 MariaDB + Nginx 各佔約 200 MB,PHP-FPM 可用約 1.2 GB,建議 pm.max_children = 10~15(視每個進程實際用量而定)



--------------------------
附錄:快速驗證清單
--------------------------

完成所有設定後,執行以下快速驗證:


1. 自動更新服務正常運行
systemctl is-active unattended-upgrades


2. 排程設定正確
apt-config dump APT::Periodic



3. 更新來源設定無語法錯誤
apt-config dump | grep -A 20 "Unattended-Upgrade::Origins"



4. 乾跑測試無錯誤
unattended-upgrade --dry-run --verbose 2>&1 | tail -20



5. LNMP 服務全部正常
for svc in nginx php8.3-fpm mariadb; do
    echo -n "$svc: "
    systemctl is-active $svc
done



6. 監控腳本可正常執行
/usr/local/bin/check-unattended-upgrades.sh && cat /var/log/unattended-upgrades-last-run.txt



7. 確認黑名單套件已鎖定
apt-mark showhold

Edited by Jack

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.