SSD Nodes Learn 🎉 VPS $4.99/月起
指南 Matt Connor作者: Matt Connor

Ubuntu 24.04 升级 26.04 VPS 的安全方法

Ubuntu 26.04.1 预计于 2026 年 8 月 27 日发布,之前不会提供 LTS 升级路径。了解 VPS 的安全升级顺序、停机风险及可能中断的服务。

何时可以将 Ubuntu 24.04 升级到 26.04?

26.04.1 版本预计于 27 August 2026 发布。该版本发布后,您就可以在 VPS 上将 Ubuntu 24.04 升级到 26.04。在此之前,24.04 服务器不会看到新版本,这是有意设计的。Ubuntu 26.04 LTS(Resolute Raccoon)已于 23 April 2026 发布,但 Canonical 只会在第一个点版本发布后开放 LTS 到 LTS 的升级路径,因为该版本会汇总最初几个月发现的安装和升级问题修复。

在 2026 年 8 月初于 24.04 服务器上运行检查命令时,您会看到以下内容:

sudo do-release-upgrade
Checking for a new Ubuntu release
No new release found.

这不是服务器故障。Ubuntu Server 上的 /etc/update-manager/release-upgrades 包含 Prompt=lts,因此该工具只会提供下一个长期支持版本,而且要等到该版本的 .1 点版本发布后才会提供。设置 Prompt=normal 则会依次引导您升级到 24.10、25.04 和 25.10,但这些中间版本目前都已停止支持。保持 lts,然后等待即可。Canonical 的计划日期可能会变更。如果当天没有发布,请再次检查。

以下每条命令都需要您按给定顺序,在自己的服务器上手动运行。无法在正在升级的服务器上预演版本升级。升级过程会替换内核和 C 库,并需要重启才能完成。

是否应该升级?

Ubuntu 24.04 会持续获得标准安全更新到 2029 年,因此正常运行的生产服务器没有升级期限。升级的理由应是您需要 26.04 提供的功能,例如 PHP 8.5、PostgreSQL 18、MySQL 8.4 LTS、OpenSSH 10.2 或 7.0 内核。“版本号变大了”不是改动客户正在使用的服务器的理由。

满足以下任一条件时,不要直接原地升级:

  • 您从未打开过服务商提供的控制台(VNC 或串行控制台),也从未通过它登录。如果 SSH 中断,该控制台是重新进入服务器的唯一方式。等到您被锁在服务器外才发现控制台无法使用,就已经太晚了。
  • 您无法承受 1 小时的停机时间,并且没有回滚方案。
  • 您的技术栈依赖某个尚未发布 resolute 版本软件包的第三方软件源。
  • 这台服务器是两年多前手动搭建的,且没有人清楚其中运行了什么。

通常,更好的做法是新建一台 26.04 VPS,安装技术栈并恢复数据,确认新服务器能够正常响应后再切换 DNS。在新服务器验证成功前,旧服务器可以继续运行;需要回滚时只需修改 DNS,而不是恢复备份。如果采用这种方式,请先阅读新 VPS 上线后的前 10 分钟,并正确搭建新服务器。

步骤 1:创建可用于恢复的备份

使用两层备份,因为它们的故障方式不同。服务商快照涵盖整个磁盘,可在几分钟内完成恢复,但快照是在数据库写入期间创建的,因此只能保证崩溃一致性,不能保证应用一致性。使用 存储在服务器外的 restic 进行文件级备份,可以恢复单个文件,并保留一份即使您的账户被锁定也能使用的副本。

先手动转储数据库。数据库转储是唯一一种无需停止数据库也可以信任的备份。

sudo -u postgres pg_dumpall | sudo tee /var/backups/pg-all.sql > /dev/null
sudo mysqldump --all-databases --single-transaction --routines | sudo tee /var/backups/mysql-all.sql > /dev/null
sudo tar czf /var/backups/etc-before-upgrade.tgz -C / etc
sudo chmod 600 /var/backups/pg-all.sql /var/backups/mysql-all.sql

--single-transaction 只能为 InnoDB 表创建一致的转储。MyISAM 表需要先停止数据库。/etc tarball 是您实际会优先使用的备份,因为其中包含升级过程中即将要求您确认的所有配置文件。

从未执行过恢复的备份只是猜测。现在就从中取出一个文件,避免在需要时承受压力。

第 2 步:先完成 24.04 的全部补丁更新

do-release-upgrade 拒绝在软件包状态损坏的系统上运行,而未完成补丁更新的 24.04 会让后续每个故障都更难判断。

sudo apt update
sudo apt full-upgrade
sudo apt --purge autoremove
sudo dpkg --audit
apt-mark showhold

dpkg --audit 没有输出表示没有软件包处于半配置状态。apt-mark showhold 没有输出表示没有软件包被锁定到会阻止升级的版本。使用 sudo apt-mark unhold 和软件包名称解除其中列出的锁定;或者确认该锁定有其原因,并在此停止。

如果内核发生了变化,请重启。这样升级时,系统运行的就是它认为当前正在运行的代码。

[ -f /var/run/reboot-required ] && sudo reboot

然后检查磁盘空间。升级程序会先下载完整的新软件包集,再安装任何内容。如果空间不足,它会中止,并在消息中指出对应的文件系统。

df -h / /boot

/ 上的可用空间低于约 5 GB 时,通常会出现问题。/boot 小于 300 MB 时,升级会在稍后的内核安装阶段失败,并显示 No space left on device。旧内核通常是原因,使用 sudo apt --purge autoremove 可以清理它们。

开始前还要停止一项任务:如果自动安全更新在升级过程中运行,它们会占用 dpkg 锁,版本升级程序会以 Could not get lock /var/lib/dpkg/lock-frontend 停止。先运行 sudo systemctl stop unattended-upgrades,完成后再重新启动升级程序。

第 3 步:检查第三方软件源和固定版本的软件包

do-release-upgrade 会禁用所有非 Ubuntu 软件源,因为为 noble 构建的软件包可能破坏 resolute 系统。随后,它会重新启用能够识别的软件源,并将其余软件源保留为注释状态。在工具替您决定之前,先确认系统中实际保留了哪些第三方内容。

ls /etc/apt/sources.list.d/
grep -rhE '^(deb |Types:|URIs:|Suites:)' /etc/apt/sources.list.d/
ubuntu-security-status --thirdparty
ls /etc/apt/preferences.d/

Ubuntu 24.04 在该目录中使用两种格式:旧式的单行 .list 文件,以及包含 Types:Suites: 字段的 deb822 .sources 文件。升级过程会禁用这两种文件。ubuntu-security-status --thirdparty 列出所有未由 Ubuntu 软件包归档提供的已安装软件包,这个数量准确反映了您额外安装的内容。/etc/apt/preferences.d/ 中的任何内容都是固定版本配置;如果固定版本配置是为 noble 编写的,升级到新版本后仍会选择旧软件包。

对于每个第三方软件源,在开始前确认供应商已经针对新的代号发布了软件包。Docker 的软件套件列在 https://download.docker.com/linux/ubuntu/dists/ 中,其他供应商也提供相同的目录。指向不存在的软件套件的软件源,在升级后的第一次 apt update 时会显示以下错误:

E: The repository 'https://download.docker.com/linux/ubuntu resolute Release' does not have a Release file.

在供应商发布对应版本前,请保持该软件源处于禁用状态。将代号修改为供应商确实构建过的其他代号,会导致安装链接到错误系统库的软件包。

第4步:在 tmux 中运行升级,不要直接在 SSH shell 中运行

如果您在普通登录 shell 中运行 do-release-upgrade 时连接中断,进程会收到 SIGHUP,并在解包过程中途退出。这会导致 dpkg 处于半配置状态,服务器的网络栈也可能无法正常工作,使您无法重新连接。请改为在终端复用器中运行,这样客户端断开后,进程仍会在服务器上继续运行。

sudo apt install -y tmux
tmux new -s upgrade

在该会话中:

sudo ufw allow 1022/tcp
sudo do-release-upgrade

升级程序会在进行任何更改前,在端口 1022 上启动第二个 SSH daemon,并明确提示这一点:

To make recovery in case of failure easier, an additional sshd will be started on port '1022'. If anything goes wrong with the running ssh you can still connect to the additional one.

它不会为该端口自动配置防火墙规则,因为未经确认就开放防火墙端口可能带来意外风险。请在开始前手动开放 1022,并在完成 sudo ufw delete allow 1022/tcp 后关闭该端口。请注意,您的服务商可能还会在其控制面板中运行另一层防火墙,该防火墙位于服务器之外。

如果连接仍然中断,请重新登录并运行 tmux attach -t upgrade。您离开期间,升级过程仍在继续。

第 5 步:谨慎处理配置文件提示

dpkg 只会提示由您或脚本修改过的文件。因此,每个提示对应的都是您有意编辑过的文件。按 Enter 让提示消失,可能会使加固后的服务器悄然恢复为默认配置。

Configuration file '/etc/ssh/sshd_config'
 ==> Modified (by you or by a script) since installation.
 ==> Package distributor has shipped an updated version.
   What would you like to do about it ?  Your options are:
    Y or I  : install the package maintainer's version
    N or O  : keep your currently-installed version
      D     : show the differences between the versions
      Z     : start a shell to examine the situation
 The default action is to keep your current version.
*** sshd_config (Y/I/N/O/D/Z) [default=N] ?

每次都先按 D。查看发生了哪些更改,然后使用 N 保留您的版本。默认选项已经是 N,这是安全的选择,因为您的文件当前可以正常工作,而软件包提供的文件从未在这台机器上运行过。

保留您的文件也有代价:您不会获得新的默认配置。之后再进行比对和合并。此时服务器已经启动,您也不再处于时间压力下。

sudo find /etc -name '*.dpkg-dist' -o -name '*.dpkg-new'

对于每个列出的文件,维护者版本都会保存在您的文件旁边。逐个进行差异比较,并将重要设置复制过来。其中有两个文件需要特别谨慎:/etc/ssh/sshd_config,因为选择错误会终止当前会话;以及 Web 服务器配置,因为选择错误会导致网站停止服务。

升级还会通过 needrestart 询问要重启哪些服务。接受完整列表。仍在使用共享库文件的 daemon 可能会继续运行,而该库文件已从磁盘删除;之后它可能在您未监控时处理某个请求并崩溃。

步骤 6:重启,然后检查计算机

sudo reboot

系统重新启动后:

lsb_release -a
uname -r
systemctl --failed
journalctl -p err -b --no-pager | head -50
sudo apt update && sudo apt full-upgrade
sudo apt --purge autoremove

lsb_release -a 应报告 Release: 26.04Codename: resoluteuname -r 应显示 7.0 内核。systemctl --failed 应列出 0 个单元;如果列出了任何单元,下一步就应处理这些单元。最后的 apt update 会获取发布镜像构建后发布的更新。

PostgreSQL 16 到 18:集群悄悄停留在旧版本

Ubuntu 24.04 随附 PostgreSQL 16,Ubuntu 26.04 随附 PostgreSQL 18。升级会在 16 旁边安装 18,但不会迁移数据。Debian 的 postgresql-common 层会为新的主版本创建一个空集群,并使用下一个可用端口,因此 16 继续使用包含全部数据的 5432 端口,18 则以空集群运行在 5433 端口。应用仍会连接 5432,表面上一切正常,这也是很多人几个月后才发现问题的原因。

pg_lsclusters

如果列出了两个集群,说明你还没有完成迁移。请在可以停止应用时执行迁移:

sudo pg_dropcluster --stop 18 main
sudo pg_upgradecluster 16 main
pg_lsclusters
sudo -u postgres vacuumdb --all --analyze-only

先删除空的 18 集群,因为 pg_upgradecluster 不会写入已经存在的目标集群。默认方法会转储 16 并将数据重新加载到 18,因此需要预留大约等于数据库大小的磁盘空间。-m upgrade 改用 pg_upgrade,处理大型数据库时速度快得多。完成后查看 Port 列:新集群会接管 5432 端口,旧集群则保持停止状态。请自行运行 analyze,因为新加载的集群没有统计信息,首次查询会很慢。

让应用连接新集群运行几天并进行测试。确认无误后再删除旧集群:

sudo pg_dropcluster 16 main
sudo apt purge postgresql-16

旧集群的数据目录是最快的回滚手段。不要在升级当天删除它。

MySQL 8.0 到 8.4:被移除的选项会导致服务器停止启动

26.04 会将 MySQL 从 8.0 升级到 8.4 LTS,其中有两项变更可能导致服务器出现问题。

首先,如果配置中包含新版本已移除的选项,mysqld 将拒绝启动。default_authentication_plugin 是最常见的选项,因为许多旧版指南都要求设置它。服务会启动失败,而 journalctl -u mysql -n 50 会直接指出未知变量。从 /etc/mysql/mysql.conf.d/ 下的文件中删除该行,然后执行 sudo systemctl start mysql

其次,8.4 默认不再启用 mysql_native_password 插件,因此仍在使用该插件的账户将完全无法登录。请在仍使用 8.0 时检查:

sudo mysql -e "SELECT user, host, plugin FROM mysql.user;"

升级前迁移所有显示 mysql_native_password 的账户,然后更新应用配置中的密码:

ALTER USER 'appuser'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'a new password';

如果客户端库版本过旧,无法使用 caching_sha2_password,可以在 8.4 中通过在 [mysqld] 下添加 mysql_native_password=ON,重新启用旧插件。此方案只能作为临时过渡,并应设定停用日期,因为该插件最终会被完全移除。

PHP 8.3 到 8.5:您的虚拟主机指向已不存在的套接字

24.04 发布时包含 PHP 8.3,26.04 发布时包含 PHP 8.5。软件包会安装到带版本号的路径中,不会改写您的 Web 服务器配置。包含 fastcgi_pass unix:/run/php/php8.3-fpm.sock; 的 nginx 虚拟主机现在指向一个没有进程创建的套接字,因此每个 PHP 请求都会返回 502,nginx 错误日志会显示:

connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory)

将其指向新的套接字,测试配置,然后重新加载:

sudo sed -i 's/php8.3-fpm.sock/php8.5-fpm.sock/' /etc/nginx/sites-available/example.com
sudo nginx -t
sudo systemctl reload nginx

如果 Apache 使用 mod_php,表现会不同:Apache 根本无法启动,sudo apache2ctl -t 会报告无法加载 libphp8.3.so,因为文件不存在。已启用的模块是指向已卸载软件包的符号链接。

sudo a2dismod php8.3
sudo a2enmod php8.5
sudo systemctl restart apache2

如果您根据 在 Ubuntu 24.04 上搭建 LAMP 堆栈 部署了服务器,这两处都值得检查,因为该指南会留下带版本号的模块名称和带版本号的套接字。

您的 php.ini 调优配置也不会自动迁移。memory_limitupload_max_filesize 以及您设置的其他内容都位于 /etc/php/8.3/ 中,新版本目录会从默认值开始。比较这两个文件,然后手动复制配置值。将整个旧文件覆盖到新文件上,会把 8.3 的默认值带入 8.5 安装。随后运行 php -m 并进行比较:以 php8.3-redis 形式安装的扩展需要对应的 php8.5- 软件包;如果扩展来自 PPA,升级程序会禁用该软件源,此时扩展会直接缺失。

证书还需要单独检查一次。升级后运行 sudo certbot renew --dry-run。它会执行完整的续期流程,包括 Web 服务器重新加载钩子,但不会修改当前使用的证书。如果钩子调用的服务名称或二进制文件已发生变化,此处会直接报错,而不是在 60 天后静默失败。在 nginx 上使用 Let's Encrypt 配置 Certbot 介绍了这些钩子应采用的形式。

SSH:导致当前会话终止的故障

sshd_config 提示符是导致用户被锁在服务器外的地方。回答 Y 会安装维护者提供的文件,并丢弃您的 PermitRootLoginPasswordAuthenticationAllowUsersPort 以及您添加的其他所有行。如果防火墙只允许自定义端口,而打包配置监听 22,那么下一次连接会被拒绝,当前会话就会成为您能使用的最后一个会话。

请在升级前防止此问题。24.04 上的 /etc/ssh/sshd_configInclude /etc/ssh/sshd_config.d/*.conf 开始,OpenSSH 会为每个设置保留它首次读取到的值,因此,在顶部包含的 drop-in 文件会覆盖下面的所有内容。将您的设置移到由 dpkg 不负责管理的文件中:

sudo tee /etc/ssh/sshd_config.d/99-local.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
AllowUsers deploy
EOF
sudo chmod 644 /etc/ssh/sshd_config.d/99-local.conf
sudo sshd -t && sudo systemctl restart ssh

/etc/ssh/sshd_config 中不再包含任何您维护的内容后,该提示就不再重要:无论选择哪个回答,您的设置都会保留,因为它们位于另一个文件中。

自定义端口还需要进行一次检查,因为配置位置可能与您预期不同:

systemctl is-enabled ssh.socket

如果输出为 enabled,则监听端口由 systemd 管理,sshd_config 中的 Port 行会被忽略。自 22.10 起,Ubuntu 一直为 sshd 使用套接字激活机制,这就是修改 Port 2222 后看似没有效果的原因。请改为使用 sudo systemctl edit ssh.socket 在套接字单元中设置端口:

[Socket]
ListenStream=
ListenStream=2222

空的 ListenStream= 是必需的。它会清除继承的值;如果没有它,套接字会同时监听 22 和 2222。使用 sudo systemctl daemon-reload && sudo systemctl restart ssh.socket 应用设置。

升级完成后,在关闭当前会话之前:

sudo sshd -t
sudo systemctl status ssh.socket --no-pager
sudo ss -lntp | grep -E ':(22|2222)'

然后在您自己的计算机上打开第二个终端,并再次登录。第二个终端中能够正常使用的 shell 才是唯一有效的验证。确认第二个会话可用前,请保持第一个会话打开。VPS 上的 SSH 加固介绍了该 drop-in 文件中值得保留的设置。

如果现在已经太晚,服务提供商的 Web 控制台可以提供不依赖 SSH 的登录方式。登录控制台,修复配置,运行 sudo sshd -t,然后重启服务。正因为有该控制台,您应在升级前测试控制台访问,而不是等到升级过程中再测试。

FAQ

为什么在 Ubuntu 24.04 上运行 do-release-upgrade 时显示“No new release found”?

因为在 Ubuntu Server 上,/etc/update-manager/release-upgrades 包含 Prompt=lts。该设置只有在下一个长期支持版本的首个点版本发布后,才会提供升级选项。Ubuntu 26.04 LTS 已于 23 April 2026 发布,26.04.1 计划于 27 August 2026 发布。在此之前,24.04 服务器不会检测到新版本。请保持该设置不变,不要切换到 Prompt=normal,否则系统会先经过中间版本。

完成升级后必须重启服务器吗?

必须。升级过程会安装新的内核、新的 C 库和新的 init 系统。运行中的系统在重启前仍会使用旧版本。do-release-upgrade 会在结束时要求重启。如果一直运行到“later”,系统就会同时使用两个版本中的组件。系统恢复后,检查 uname -r 以确认新内核,并检查 systemctl --failed 以找出未能恢复的服务。

应该原地升级,还是新建一台 26.04 服务器?

条件允许时,建议新建服务器。新 VPS 可以在旧服务器继续提供网络流量期间安装软件栈、恢复数据并完成测试。这样回滚只需修改 DNS,而不必从备份恢复。以下情况可以原地升级:服务器保存了难以迁移的状态;服务商按机器计费;或者你有快照和经过验证的控制台访问权限。原地升级流程较为成熟,但在执行期间无法轻易撤销。

如果升级期间 SSH 连接断开,会发生什么?

在普通登录 shell 中,进程会收到 SIGHUP 并中途退出,导致 dpkg 处于部分配置状态。请在 tmuxscreen 中启动升级进程。这样进程可以继续运行,你重新连接后执行 tmux attach -t upgrade 即可继续升级。升级程序还会在 1022 端口启动备用 SSH daemon,作为第二种访问方式。但它不会自动为该端口配置防火墙规则,因此请先自行放行 1022,完成后再关闭该端口。

升级后 PHP 网站返回 502。哪里出了问题?

PHP FPM 套接字路径随版本发生了变化。Ubuntu 24.04 使用 PHP 8.3,26.04 使用 PHP 8.5。因此,/run/php/php8.3-fpm.sock 已不存在,而你的 nginx vhost 仍引用该路径。nginx 错误日志会显示 connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory)。将 fastcgi_pass 更新为 8.5 的套接字路径,执行 sudo nginx -t,然后重新加载 nginx。对于使用 mod_php 的 Apache,等效修复是执行 sudo a2dismod php8.3,然后执行 sudo a2enmod php8.5 并重启服务。