SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor

Debianでunattended-upgradesが動かない理由と設定方法

Debianではunattended-upgradesのインストールだけでは有効になりません。Origins-Pattern、apt-dailyのsystemd timers、実行ログを確認し、自動更新が動く状態を検証します。

新規 Debian インストールで unattended-upgrades が何もしない理由

Debian では、unattended-upgrades をインストールしても、アップグレードが一度も実行されないことがあります。パッケージのインストールと有効化は別の手順だからです。パッケージは自身を設定する前に debconf の質問を表示し、Debian installer はその質問への回答を false として保存します。Ubuntu では同じ質問に別の回答を設定します。そのため、同じパッケージが Ubuntu では動作しているように見え、Debian では壊れているように見えます。

この点を示す情報はシステム上にありません。起動時のエラーも、ログイン時の警告もありません。確認できるログファイルもありません。ログを書き込むコードが一度も呼び出されないためです。有効化は 1 つのコマンドで行えます。この後のガイドでは、有効化後も実行を妨げる 4 つの要因を説明します。アップグレード元として使用できるリポジトリ、systemd timers が実際に起動する時刻、実行の失敗を確認する方法、そしてマシンによる自動再起動が許可されているかどうかです。

変更する前に、システムの認識内容を確認する

dpkg -l unattended-upgrades | tail -n 1
sudo apt install -y debconf-utils
sudo debconf-show unattended-upgrades
cat /etc/apt/apt.conf.d/20auto-upgrades
apt-config dump APT::Periodic

debconf-showは、unattended-upgrades/enable_auto_updatesに保存されている値を表示します。その行の先頭にある*は、パッケージのデフォルト値ではなく、何らかの処理によって値が設定されたことを示します。Debian installerで構築したマシンでは、その処理を行ったのはinstallerです。

catの出力がcat: /etc/apt/apt.conf.d/20auto-upgrades: No such file or directoryになることがあります。ファイルがなければ定期的な処理が登録されないため、それだけで何も実行されない理由になります。

重要なのはapt-config dumpです。APTは/etc/apt/apt.conf.d/内のファイルをファイル名順に読み込み、内容を統合します。そのため、99localに設定された通常の値は、20auto-upgradesにある同じ値を上書きします。拡張子のないファイル、または.conf拡張子のファイルだけが対象です。したがって、99local.bakのようなファイルは無視されます。1つのファイルを読むと、そのファイルに記載された内容が分かります。apt-config dumpを使うと、APTが実際に適用する内容が分かります。

何かが実行されるかどうかは、次の2つのキーで決まります。

  • APT::Periodic::Update-Package-Listsはパッケージリストを更新します。これはapt updateが手動で行う処理です。
  • APT::Periodic::Unattended-Upgradeはアップグレード自体を実行します。

これらの値は、trueやfalseではありません。日数単位の間隔です。"1"は「直近1日以内に実行されていなければ実行する」という意味です。"7"は週次、"0"は実行しないという意味です。APT::Periodic::Unattended-Upgrade "0";は有効な設定ですが、エラーを出さずに永久に何も実行しません。そのキーに0が表示されるか、キー自体が表示されない場合は、原因が分かりました。

有効化する: dpkg-reconfigure またはキーを直接記述する

sudo apt update
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

この質問の優先度は low です。そのため、通常のインストールでは表示されません。dpkg-reconfigure は、設定されている debconf の優先度に関係なく、優先度が low の質問を表示します。したがって、--priority=low は既定の動作を明示しているだけです。避けるべきフラグは --default-priority です。これはその動作を無効にし、質問を再び非表示にします。ダイアログでは yes と回答します。すると、パッケージの postinst が回答に基づいて /etc/apt/apt.conf.d/20auto-upgrades を書き込みます。

スクリプトで構築するマシンでは、回答するダイアログがありません。そのため、先に回答を設定します。

echo 'unattended-upgrades unattended-upgrades/enable_auto_updates boolean true' \
  | sudo debconf-set-selections
sudo dpkg-reconfigure -f noninteractive unattended-upgrades
apt-config dump APT::Periodic

2 つのキーを直接記述することもできます。

printf 'APT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "1";\n' \
  | sudo tee /etc/apt/apt.conf.d/20auto-upgrades
apt-config dump APT::Periodic

この方法はすぐに反映されますが、問題の原因を残します。debconf の回答は古い内容のままです。そのため、次回の dpkg-reconfigure、またはパッケージの再インストール時に、debconf の内容からファイルが再作成され、編集内容が出力なしで元に戻ります。両方を設定するか、debconf を設定して postinst にファイルを管理させてください。

これが、もう一方の系列との実質的な違いです。そちらではインストーラーが同じパッケージを有効化します。そのため、Ubuntu の unattended-upgrades の設定 は、すでに自動的にパッチを適用している状態から始まり、調整に時間を使います。ここから下の内容は、どちらにも適用されます。

Debian は実際にどの更新をインストールするのか

タイマーを有効にしても、すべての更新のインストールに同意したことにはなりません。各パッケージソースには、origin、label、suite、codename、site などのリリースメタデータがあります。unattended-upgrades は、更新可能な各パッケージの候補バージョンを確認し、その取得元となるソースのメタデータを読み取ります。そして、そのソースが Unattended-Upgrade::Origins-Pattern または従来の Unattended-Upgrade::Allowed-Origins リストのエントリと一致する場合にだけインストールします。一致しなければ、設計上、何も表示せず更新しません。

パターンを表示し、照合対象のメタデータも表示します。

apt-config dump Unattended-Upgrade::Origins-Pattern
grep -H -E '^(Origin|Label|Suite|Codename|Components):' /var/lib/apt/lists/*Release
apt-cache policy

grep -H は各行にファイル名を残すため、どのメタデータブロックがどのソースに属するかを確認できます。これらのフィールド値が、パターンの右辺です。パターン内の ${distro_codename} は実行時に、現在使用しているリリースの codename に置き換えられます。そのため、リリースをアップグレードしても 1 つのファイルを使い続けられます。

自分のパターンを、対応するメタデータと並べて確認してください。「セキュリティ修正だけを受け取るのか、それとも point release の更新も受け取るのか」という答えは、この 2 つのリストにだけ記載されています。

  • label=Debian-Security を指定するパターンは、security アーカイブに一致します。Debian のセキュリティ勧告に対応する更新は、ここに登録されます。
  • -updates suite を指定するパターンは stable-updates に一致します。ここには、point release の間に Debian が提供する更新(タイムゾーンデータなど)が含まれます。
  • 通常の release suite を指定するパターンは、公開された point release の変更を取得します。その分、変更が増え、利用者側で必要なテスト作業も増えます。
  • 自分で追加したリポジトリは、そのリポジトリ用のパターンを記述するまで、何にも一致しません。

最後の点は意外に思うかもしれません。サードパーティーリポジトリには独自の origin と label があります。そのため、unattended-upgrades は候補バージョンを確認し、ソースがどのパターンにも一致しないことを確認すると、そのまま処理を続けます。サードパーティーリポジトリ用のパターンを追加するかどうかは、慎重に判断してください。ベンダーのリポジトリが同じ suite 内で新しいメジャーバージョンを提供する場合があり、その場合、深夜にそのソフトウェアのメジャーアップグレードを unattended-upgrades に実行させることになります。

unattended-upgrades が Debian のリリース間を移行させることもありません。現在使用しているリリース内でパッケージをアップグレードします。ある stable リリースから次の stable リリースへの移行は、利用者自身が予定を組んで手動で行う作業です。

リストを変更するときは、APT のリストが追記方式であることに注意してください。別のファイルにある 2 つ目の Origins-Pattern ブロックは、配布済みのリストを置き換えずに追加します。置き換えるつもりなら、先に既存のブロックを削除してください。

#clear Unattended-Upgrade::Origins-Pattern;
Unattended-Upgrade::Origins-Pattern {
  "origin=Debian,codename=${distro_codename},label=Debian-Security";
  "origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};

ローカルの変更は、配布済みのファイルより後に並ぶ新しいファイルに記述してください。たとえば /etc/apt/apt.conf.d/52unattended-upgrades-local です。50unattended-upgrades は管理対象の設定ファイルです。そのため、編集後にパッケージ更新で変更版が提供されると処理が停止し、自分の変更をどうするか確認されます。別のファイルを使えば競合しません。

ここで、さらに 2 つのキーも表示しておくと便利です。Unattended-Upgrade::Allowed-Origins は同じ考え方の従来形式で、origin:archive のペアとして記述します。現在も読み込まれるため、チュートリアルからコピーした設定に両方のリストが入り、どちらが一致したのか分からなくなることがあります。Unattended-Upgrade::Package-Blacklist にはパッケージ名に対して照合する正規表現が格納されます。ここで緩すぎる正規表現を指定すると、意図した範囲を大きく超えて更新をブロックします。以下の dry run では、実際に適用された設定を表示します。

予想した時刻に何も実行されなかった理由

これを動かしている systemd timer は 2 つあり、それぞれ役割が異なります。apt-daily.timer は apt-daily.service を起動し、パッケージリストを更新してパッケージをダウンロードします。apt-daily-upgrade.timer は apt-daily-upgrade.service を起動します。こちらが unattended-upgrade を呼び出す timer です。どちらも異なる引数で /usr/lib/apt/apt.systemd.daily を実行します。2 番目の timer が無効化または mask されていると、2 つの定期的なキーが 1 を読み取れても、パッケージは一度もインストールされません。

systemctl list-timers 'apt-daily*' --all
systemctl is-enabled apt-daily.timer apt-daily-upgrade.timer
systemctl cat apt-daily-upgrade.timer

list-timers を実行すると、各 unit の NEXT、LEFT、LAST、PASSED が表示されます。NEXT のない timer は実行されません。is-enabled に masked と表示される場合、その timer は強制的に無効化されています。apt.conf.d に何を書いても、この状態は変わりません。

次に、systemctl cat が表示した [Timer] セクションを確認します。OnCalendar は timer が実行される最も早い時刻です。RandomizedDelaySec はその時刻の後にランダムな待機時間を追加します。これにより、複数の Debian マシンが同じ秒に同じミラーへアクセスすることを防ぎます。そのため、NEXT 列の時刻は OnCalendar と一致せず、前日の実行時刻も異なる分になります。これは仕様どおりの動作です。Persistent=true は、スケジュール時刻に電源が入っていなかったマシンが、その日を飛ばさず、次回のブート直後にジョブを実行することを意味します。

実行時刻の範囲を変更するには、unit 自体を編集せずに override を作成します。

sudo systemctl edit apt-daily-upgrade.timer
[Timer]
OnCalendar=
OnCalendar=03:30
RandomizedDelaySec=30m

空の OnCalendar= 行は必須です。unit のリスト型設定は累積するためです。この行を省略すると、パッケージに含まれるスケジュールが残ったまま、2 つ目のスケジュールが追加されます。systemctl edit は systemd を自動的に reload するため、systemctl list-timers 'apt-daily*' で結果を確認し、新しい NEXT を確認します。

これらをテストするために、timer の実行を待つ必要はありません。

sudo systemctl start apt-daily-upgrade.service
journalctl -u apt-daily-upgrade.service --since -1h

/etc/cron.daily を調べると混乱しやすい点があります。APT には、systemd を使用しないシステム向けに /etc/cron.daily/apt-compat も含まれています。cat で内容を確認できます。systemd を使用するシステムでは早期に終了するため、処理が二重に実行されることはありません。

動作を確認する: unattended-upgrade --dry-run --debug

sudo unattended-upgrade --dry-run --debug

コマンド名は単数形で、パッケージ名は複数形です。Debian 12 と 13 には /usr/bin/unattended-upgrades も含まれているため、そこで複数形の末尾は command not found ではなくなります。ただし、文書化されているコマンドと、このガイド全体で使用するコマンドは単数形の unattended-upgrade です。

このコマンドは、ほぼすべての「なぜそのパッケージをスキップしたのか」という疑問に答えます。判定理由自体を出力するためです。出力の上部付近には、指定したパターンから計算した取得元が表示されます。

Allowed origins are: ...

続いて、候補パッケージごとに1行が表示されます。各行には、インストールされるバージョンの取得元レコードが含まれます。

Checking: curl ([<Origin component:'main' archive:'stable' origin:'Debian' label:'Debian' site:'deb.debian.org' isTrusted:True>])

その後、処理対象になるパッケージの一覧が表示されます。処理対象がないシステムでは、次のように表示されます。

No packages found that can be upgraded unattended and no pending auto-removals

1つ目と2つ目を照合すれば、原因を直接特定できます。アップグレードされるはずだったパッケージの Checking: 行を探します。その取得元レコードの各フィールドを、上に表示された許可済み取得元と比較します。最も多いのは label または archive で、1つでも一致しないフィールドがあれば、それがスキップされた理由です。

--dry-run はパッケージをメモリ上で処理するだけで、インストールは行いません。そのため、必要な回数だけ実行できます。ただし、/var/log/unattended-upgrades/unattended-upgrades.log には追記されます。

取得元が一致しているのにパッケージが保留される場合は、次を確認します。

  • apt-mark showhold には、ユーザーまたはツールが pin したパッケージが一覧表示されます。unattended-upgrades は保留されたパッケージを変更しません。
  • アップグレードのために別のパッケージの削除または追加が必要です。unattended-upgrades は、関連するキーで許可されていない限り、この処理を避けます。sudo apt-get -s upgrade と比較してください。安全策を適用せずに同じ判定を行います。
  • 中断された処理の後で dpkg が構成途中の状態になっています。sudo dpkg --configure -a で修復してから、もう一度確認します。
  • /var に空き容量がないため、ダウンロードも展開もできません。df -h /var で確認します。
  • /boot が古い kernel で埋まっているため、次の kernel アップグレードが失敗します。df -h /boot で確認し、apt-config dump Unattended-Upgrade::Remove-Unused-Kernel-Packages を出力してクリーンアップが有効かどうかを確認します。

タイマーの実行中に apt を手動で実行すると、Could not get lock /var/lib/dpkg/lock-frontend が表示されます。このメッセージは、unattended-upgrades が正常に処理していることを示します。完了するまで待ちます。

実行が失敗した時期を確認するには

まずログを確認します。ほかの設定をしていなくてもログは記録されるためです。

sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.log
sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
journalctl -u apt-daily-upgrade.service --since -7d

最初のファイルは判断ログです。何を確認し、何を選択し、何をインストールしたかを記録します。2 番目のファイルには raw な dpkg の出力が記録されます。パッケージの postinst スクリプトが失敗した場合は、ここに現れます。マシンのシャットダウン中にアップグレードが実行された場合は、別のシャットダウンログも作成されます。

通常はメールで通知します。

Unattended-Upgrade::Mail "you@example.com";
Unattended-Upgrade::MailReport "on-change";

MailReport は always、on-change、only-on-error を受け付けます。only-on-error は慎重な選択に見えますが、誰もログインしないサーバーでは通常適切ではありません。アップグレードが完全に停止したマシンは、エラーも送信しないためです。その結果、正常なサーバーと停止したサーバーを同じ無通知の状態で扱うことになります。on-change では何かがインストールされるたびにメールが送信されるため、そのメールによって timer が動作し続けていることも確認できます。

メールをマシン外へ送信するには、マシンからメールを送信できなければなりません。unattended-upgrades はメッセージをローカルのメールシステムへ渡すため、postfix などの MTA (mail transfer agent) が必要です。または、msmtp などの sendmail 互換の relay クライアントを使用します。command -v sendmail と command -v mail で確認してください。どちらもない場合、レポートは送信先に届きません。アップグレード自体は成功するため、問題全体が見えなくなります。また、新しい VPS の IP アドレスには送信実績がないため、パブリックなメールボックスへ直接送信したメールは迷惑メールとして処理されることがよくあります。自分でメールサーバーを運用するより、すでに利用しているメールプロバイダーを経由してリレーするほうが信頼性は高くなります。

メールを使いたくない場合は、利用中の監視システムでログのタイムスタンプを監視します。

stat -c '%y %n' /var/log/unattended-upgrades/unattended-upgrades.log

1 週間タイムスタンプが更新されていなければ、設定の内容にかかわらず timer が停止しています。この確認は、通常の Linux サーバー保守確認と併せて行います。

サーバーを自動的に再起動しますか?

Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";

Automatic-Reboot に true を設定すると、unattended-upgrades は確認なしで再起動します。ただし、実行完了後に /var/run/reboot-required ファイルが存在する場合に限ります。Debian 12 と 13 では、unattended-upgrades パッケージがカーネルフックの /etc/kernel/postinst.d/unattended-upgrades を通じて、このマーカーファイルを自動的に作成します。/etc/kernel/postinst.d/unattended-upgrades はカーネルパッケージのインストール時に実行されます。ライブラリの更新では実行されません。このファイルが存在すると決めつけないでください。次回カーネルを更新した後に確認します。

ls -l /var/run/reboot-required /var/run/reboot-required.pkgs
uname -r
dpkg -l 'linux-image-*' | grep '^ii'

そのファイルがマシン上に一度も現れない場合、Automatic-Reboot "true" は実行されません。カーネル更新のために再起動しているつもりでも、古いカーネルを使い続けている可能性があります。最新のインストール済み linux-image パッケージに対して uname -r を実行すれば、状況を確認できます。

Automatic-Reboot-Time は、すぐに再起動する代わりに、指定した時刻に再起動を予約します。Automatic-Reboot-WithUsers を false に設定すると、誰かがログイン中の場合は再起動しません。常にセッションが開いているサーバーでは、再起動が一度も実行されないことになります。

判断すべきなのは、再起動そのものではなく、再起動後に何が起きるかです。手動で起動したサービスは自動的に復旧しません。起動時にパスフレーズが必要な暗号化ボリュームはマウントされません。相互に依存する 2 台のマシンが、誤った順序で復旧することもあります。02:00 に 1 分間停止しても問題のないステートレスな Web サーバーでは、自動再起動を有効にします。人の操作が必要な環境では無効のままにし、代わりにマーカーファイルを監視して、担当者が再起動のタイミングを決められるようにします。その中間にあるのが needrestart です。これは、更新済みのライブラリを使い続けているサービスを再起動するため、カーネル以外の更新に対応できます。デフォルトモードでは再起動前に確認を求めるため、無人実行で利用する前に /etc/needrestart/needrestart.conf を確認してください。

テスト版と不安定版でも同じように機能しますか?

上記の内容は、セキュリティ修正が独自のラベルを持つ別アーカイブから提供される Debian stable を前提としています。この構造があるため、「セキュリティ更新のみ」という設定を指定できます。他のスイートは異なる仕組みで構成されているため、stable サーバーからコピーした設定は、作成者が想定するほど適合しません。また、更新が継続するスイートで自動アップグレードを有効にすると、メジャーバージョンの変更も無人で適用されます。これは、受け入れるべき内容が異なります。この選択を検討している場合は、サーバーで Debian stable、testing、または unstable を運用するで、それぞれの位置付けを確認できます。Red Hat 系では、同じ処理に別のツールと用語を使います。Rocky Linux と AlmaLinux の dnf-automaticでは、独自の timer と設定ファイルを使用して実行します。

自動アップグレードにより、修正の公開からインストールまでの時間を短縮できます。ただし、現在も露出している問題は分からないため、サーバー上の既知の CVE を確認する方法と組み合わせてください。CVE は common vulnerabilities and exposures の略で、修正の追跡に使用される公開識別子です。

5 分間の確認

  1. apt-config dump APT::Periodic で、0 ではない値を持つ両方のキーが表示されます。
  2. systemctl list-timers 'apt-daily*' で、両方のタイマーに対して NEXT の時刻が表示されます。
  3. sudo unattended-upgrade --dry-run --debug で、自分の codename 用の security archive を含む許可済みの origin が表示されます。
  4. sudo systemctl start apt-daily-upgrade.service が完了し、/var/log/unattended-upgrades/unattended-upgrades.log のタイムスタンプが更新されます。
  5. 1 週間後、同じログにインストールされたパッケージ名が記録されます。

最初の4つを満たせば、マシンの設定は完了しています。5つ目を満たせば、正常に動作しています。

FAQ

Debian はなぜ unattended-upgrades をインストールするのに、無効のままにするのですか?

このパッケージは debconf の質問 unattended-upgrades/enable_auto_updates を使用し、その回答から /etc/apt/apt.conf.d/20auto-upgrades を書き込みます。Debian installer はこの質問に対する false を保存するため、パッケージが task の一部または依存関係としてインストールされると、何もしない設定になります。sudo debconf-show unattended-upgrades を実行すると保存された回答を確認でき、sudo dpkg-reconfigure --priority=low unattended-upgrades を実行すると変更できます。この質問の優先度は低いため、通常のインストールでは表示されません。しかし dpkg-reconfigure はデフォルトで低優先度の質問を表示するため、フラグなしでもここでは表示されます。

タイマーを待たずに unattended-upgrades をテストするにはどうすればよいですか?

sudo unattended-upgrade --dry-run --debug を実行します。インストール対象として受け入れる origin を表示し、アップグレード可能なパッケージごとに、そのパッケージの origin レコードが付いた Checking: 行を1行ずつ表示します。また、インストールされるパッケージの一覧も表示しますが、実際には何もインストールしません。実際の処理経路を確認するには、sudo systemctl start apt-daily-upgrade.service を実行し、その後 journalctl -u apt-daily-upgrade.service --since -1h と /var/log/unattended-upgrades/unattended-upgrades.log を確認します。

unattended-upgrades はセキュリティ修正だけでなく通常の更新もインストールしますか?

パターンで指定されている場合に限り、インストールします。パッケージの取得元が Unattended-Upgrade::Origins-Pattern または旧形式の Unattended-Upgrade::Allowed-Origins のエントリに一致すると、そのパッケージのアップグレードがインストールされます。security archive、stable-updates suite、ユーザーが追加したリポジトリは、それぞれ別のエントリです。自分のマシンで apt-config dump Unattended-Upgrade::Origins-Pattern と apt-config dump Unattended-Upgrade::Allowed-Origins を表示し、grep -H -E '^(Origin|Label|Suite|Codename):' /var/lib/apt/lists/*Release と比較してください。また、Debian のリリース間を移行することはありません。

なぜアップグレードはタイマーで設定した時刻に実行されないのですか?

apt-daily-upgrade.timer は OnCalendar に加えて RandomizedDelaySec を設定するため、systemd は指定された時刻ではなく、その時間帯の中からランダムに選んだ時刻に実行します。これにより、同じミラーを参照するすべての Debian マシンにかかる負荷が分散されます。実際に選択された時刻は systemctl list-timers 'apt-daily*' で確認できます。時間帯を変更するには sudo systemctl edit apt-daily-upgrade.timer を実行し、空の OnCalendar= 行に続けて独自の値を指定します。

セキュリティ更新で自動再起動を有効にすべきですか?

計画外の再起動が安全な環境に限り、有効にしてください。実行後に /var/run/reboot-required が存在すると、Unattended-Upgrade::Automatic-Reboot "true" は確認なしで再起動します。Debian 12 および 13 では、このマーカーは unattended-upgrades パッケージが提供する kernel hook によって作成されるため、kernel のアップグレード後には現れますが、library のアップグレード後には現れません。この設定を信頼する前に、kernel のアップグレード後に自分のマシンでこのファイルが現れることを確認してください。起動時に passphrase が必要なマシンや、誰かが手動で起動したサービスを実行しているマシンでは、false のままにし、マーカーファイルを検知して通知するようにします。そうすれば、人が再起動のタイミングを選べます。