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::Periodicdebconf-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 にある同じ値を上書きします。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ここでは --priority=low は省略できません。この質問の優先度は低いため、デフォルトの優先度では dpkg-reconfigure は何も表示せず、何も変更せず、終了コード 0 で終了します。そのため、コマンドが正常に実行されたように見えます。ダイアログでは 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::Periodic2 つのキーを直接記述することもできます。
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 のエントリに一致する場合だけインストールします。一致しなければ、設計上、何も表示せずに更新しません。
パターンを表示し、次に照合対象のメタデータを表示します。
apt-config dump Unattended-Upgrade::Origins-Pattern
grep -H -E '^(Origin|Label|Suite|Codename|Components):' /var/lib/apt/lists/*Release
apt-cache policygrep -H は各行にファイル名を付けるため、どのメタデータブロックがどのソースに属するかを確認できます。これらのフィールド値が、パターンの右辺です。パターン内の ${distro_codename} は実行時に、現在使用しているリリースの codename に置き換えられます。そのため、リリースアップグレード後も同じファイルを使用できます。
自分のパターンとメタデータを並べて確認してください。「セキュリティ修正だけを受け取るのか、それとも point release の更新も受け取るのか」という答えは、そこにだけ記載されています。
label=Debian-Securityを指定するパターンは、security archive に一致します。Debian のセキュリティアドバイザリはここに公開されます。-updatessuite を指定するパターンは stable-updates に一致します。ここには、タイムゾーンデータなど、Debian が point release の間に提供する更新が含まれます。- 通常の release suite を指定するパターンは、公開された point release の変更を取り込みます。その分、変更が増え、利用者側で必要なテスト作業も増えます。
- 自分で追加したリポジトリは、そのリポジトリ用のパターンを記述するまで、何にも一致しません。
最後の点は意外に思われがちです。サードパーティーのリポジトリには固有の origin と label があります。そのため unattended-upgrades は候補バージョンを確認し、ソースがどのパターンにも一致しないことを確認して、そのまま処理を進めます。サードパーティーのリポジトリ用にパターンを追加するかどうかは、慎重に判断してください。同じ suite 内でベンダーが新しいメジャーバージョンを公開することがあり、その場合、夜間にそのソフトウェアのメジャーアップグレードを自動実行することに同意した状態になります。
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 は conffile なので、編集すると、パッケージの今後のアップグレード時に毎回処理方法を確認するプロンプトが表示されます。別のファイルを使えば競合しません。
ここで、もう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.timerlist-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バイナリ名は単数形ですが、パッケージ名は複数形です。ここで unattended-upgrades と入力すると command not found が表示されます。これを見て、パッケージが存在しない証拠だと考える人は少なくありません。
このコマンドは、自身の判断理由を出力するため、「なぜそのパッケージをスキップしたのか」という疑問のほとんどに答えます。出力の先頭付近には、指定したパターンから計算した取得元が表示されます。
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最初の2つを組み合わせれば、原因を直接特定できます。アップグレードされるはずだったパッケージについて、Checking: の行を探します。その取得元レコードを、上に表示された許可済み取得元とフィールド単位で比較します。1つでも一致しないフィールドがあれば、それがスキップされた理由です。多くの場合は label または archive です。
--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を出力してクリーンアップが有効かどうかを確認します。
timer の実行中に 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.log1 週間タイムスタンプが更新されていなければ、設定の内容にかかわらず 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 ファイルが存在する場合に限ります。このマーカーファイルを unattended-upgrades が作成するわけではありません。別のパッケージが作成する必要があり、Debian では通常 needrestart が作成します。存在すると決めつけないでください。次回のカーネル更新後に確認します。
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 分間の確認
apt-config dump APT::Periodicで、0 ではない値を持つ両方のキーが表示されます。systemctl list-timers 'apt-daily*'で、両方のタイマーに対してNEXTの時刻が表示されます。sudo unattended-upgrade --dry-run --debugで、自分の codename 用の security archive を含む許可済みの origin が表示されます。sudo systemctl start apt-daily-upgrade.serviceが完了し、/var/log/unattended-upgrades/unattended-upgrades.logのタイムスタンプが更新されます。- 1 週間後、同じログにインストールされたパッケージ名が記録されます。
最初の4つを満たせば、マシンの設定は完了しています。5つ目を満たせば、正常に動作しています。
FAQ
Debian は unattended-upgrades をインストールするのに、なぜ無効のままにするのですか?
このパッケージは debconf の質問 unattended-upgrades/enable_auto_updates を使用し、その回答から /etc/apt/apt.conf.d/20auto-upgrades を書き込みます。Debian インストーラーはこの質問に対する false を保存するため、パッケージがタスクの一部または依存関係として導入されると、何もしない設定になります。保存された回答は sudo debconf-show unattended-upgrades で確認し、sudo dpkg-reconfigure --priority=low unattended-upgrades で変更します。優先度を低く指定する必要があります。デフォルトの優先度では、質問を表示しないままコマンドが終了するためです。
タイマーを待たずに 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 のエントリに一致すると、そのパッケージのアップグレードがインストールされます。セキュリティアーカイブ、stable-updates suite、自分で追加したリポジトリは、それぞれ別のエントリです。自分のマシンで apt-config dump Unattended-Upgrade::Origins-Pattern を出力し、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= 行の後に独自の値を指定します。
セキュリティ更新の自動再起動を有効にすべきですか?
計画外の再起動が安全な環境に限って有効にしてください。Unattended-Upgrade::Automatic-Reboot "true" は、実行後に /var/run/reboot-required が存在すると、確認なしで再起動します。このマーカーは通常 needrestart など、別のパッケージが作成するものであり、unattended-upgrades 自体が作成するものではありません。カーネル更新後に自分のマシンでこのファイルが作成されることを確認してから、この設定を信頼してください。起動時にパスフレーズが必要なマシンや、手動で起動したサービスを実行しているマシンでは、false のままにして、マーカーファイルを監視してください。担当者が再起動のタイミングを判断できるようにします。