Discourse コンテナは unattended-upgrades を使用しますか?

Discourse の Docker コンテナは、Debian ベースの Docker コンテナ内の OS パッケージを最新の状態に保つために unattended-upgrades を使用していますか?

INSTALL-cloud.md ガイドでは、Docker ホストマシンに unattended-upgrades をインストールすることが推奨されているため、Docker コンテナ内部の OS パッケージの状態が気になりました。GitHub 上の discourse および discourse_docker リポジトリを検索しましたが、unattended-upgrades への言及が見つかったのは、同じインストールドキュメントのみでした。

では、Discourse の Docker コンテナ自体はどうでしょうか? それunattended-upgrades を使用していますか?

「いいね!」 1

After further digging, it appears that unattended-upgrades is installed but not running on the Discourse docker container.

First, it’s clearly installed

root@osestaging1-discourse-ose:/var/www/discourse# dpkg -l | grep -i unatt
ii  unattended-upgrades             1.11.2                       all          automatic installation of security upgrades
root@osestaging1-discourse-ose:/var/www/discourse# 

Further inspecting of the unattended-upgrades package’s config per the relevant Debian wiki article shows

The default config looks sane

root@osestaging1-discourse-ose:/var/www/discourse# grep -ir 'origin=' /etc/apt/apt.conf.d/50unattended-upgrades 
//      "origin=Debian,codename=${distro_codename}-updates";
//      "origin=Debian,codename=${distro_codename}-proposed-updates";
		"origin=Debian,codename=${distro_codename},label=Debian";
		"origin=Debian,codename=${distro_codename},label=Debian-Security";
root@osestaging1-discourse-ose:/var/www/discourse# cat /etc/apt/apt.conf.d/20auto-upgrades 
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
root@osestaging1-discourse-ose:/var/www/discourse# 

But checking the logs show the last entry was 1 month ago

root@osestaging1-discourse-ose:/var/www/discourse# tail -f /var/log/unattended-upgrades/unattended-upgrades*.log
==> /var/log/unattended-upgrades/unattended-upgrades-dpkg.log <==
Log started: 2019-11-17  12:34:54
(Reading database ... 44559 files and directories currently installed.)
Removing freetype2-doc (2.9.1-3+deb10u1) ...
Log ended: 2019-11-17  12:34:54

Log started: 2019-11-17  12:34:56
(Reading database ... 44389 files and directories currently installed.)
Removing libjs-jquery (3.3.1~dfsg-3) ...
Log ended: 2019-11-17  12:34:57


==> /var/log/unattended-upgrades/unattended-upgrades.log <==
2019-11-26 16:37:47,549 INFO Initial blacklist : 
2019-11-26 16:37:47,550 INFO Initial whitelist: 
2019-11-26 16:37:47,551 INFO Starting unattended upgrades script
2019-11-26 16:37:47,552 INFO Allowed origins are: origin=Debian,codename=buster,label=Debian, origin=Debian,codename=buster,label=Debian-Security
2019-11-26 16:37:50,811 INFO Checking if system is running on battery is skipped. Please install powermgmt-base package to check power status and skip installing updates when the system is running on battery.
2019-11-26 16:37:50,814 INFO Initial blacklist : 
2019-11-26 16:37:50,815 INFO Initial whitelist: 
2019-11-26 16:37:50,815 INFO Starting unattended upgrades script
2019-11-26 16:37:50,815 INFO Allowed origins are: origin=Debian,codename=buster,label=Debian, origin=Debian,codename=buster,label=Debian-Security
2019-11-26 16:37:53,119 INFO No packages found that can be upgraded unattended and no pending auto-removals
^C
root@osestaging1-discourse-ose:/var/www/discourse# 

…Even though the default systemd timers defined for unattended-upgrades are set to run at least once per day

root@osestaging1-discourse-ose:/var/www/discourse# cat /lib/systemd/system/apt-daily.timer
[Unit]
Description=Daily apt download activities

[Timer]
OnCalendar=*-*-* 6,18:00
RandomizedDelaySec=12h
Persistent=true

[Install]
WantedBy=timers.target
root@osestaging1-discourse-ose:/var/www/discourse# cat /etc/systemd/system/apt-daily.timer.d/override.conf
cat: /etc/systemd/system/apt-daily.timer.d/override.conf: No such file or directory
root@osestaging1-discourse-ose:/var/www/discourse# cat /lib/systemd/system/apt-daily-upgrade.timer
[Unit]
Description=Daily apt upgrade and clean activities
After=apt-daily.timer

[Timer]
OnCalendar=*-*-* 6:00
RandomizedDelaySec=60m
Persistent=true

[Install]
WantedBy=timers.target
root@osestaging1-discourse-ose:/var/www/discourse# cat /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf
cat: /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf: No such file or directory
root@osestaging1-discourse-ose:/var/www/discourse# 

But, indeed, those timers are disabled.

root@osestaging1-discourse-ose:/var/www/discourse# sudo systemctl status apt-daily.timer
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
root@osestaging1-discourse-ose:/var/www/discourse# sudo systemctl status apt-daily-upgrade.timer
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
root@osestaging1-discourse-ose:/var/www/discourse# 

This is further confirmed by manually running unattended-upgrades, which just happened to require an update to two git-related packages

root@osestaging1-discourse-ose:/var/www/discourse# sudo unattended-upgrade -d
...
Checking: git ([<Origin component:'main' archive:'stable' origin:'Debian' label:'Debian-Security' site:'security.debian.org' isTrusted:True>])
Checking: git-man ([<Origin component:'main' archive:'stable' origin:'Debian' label:'Debian-Security' site:'security.debian.org' isTrusted:True>])
pkgs that look like they should be upgraded: git   
git-man
...
All upgrades installed
InstCount=0 DelCount=0 BrokenCount=0
Extracting content from /var/log/unattended-upgrades/unattended-upgrades-dpkg.log since 2019-12-24 17:32:55
root@osestaging1-discourse-ose:/var/www/discourse# 

The git version that was updated in the above unattended-upgrades run was git (1:2.20.1-2+deb10u1). I ran this test today (2019-12-24), but the security upgrade had been available to Debian Buster (the OS on which the Discourse docker image is built) for two weeks (since 2019-12-10)!

This is actually a pretty serious upgrade that fixes several vulnerabilities, including two vectors for Remote Code Execution. More info is available at the Debian Security Advisory 4581-1

But git is just an example I happened to stumble on. It’s extremely concerning if the Discourse docker container doesn’t (by default) actually apply security-related patches to its OS.

Is this a bug? Or was this an intentional decision by the Discourse team? Or is this just the default in-lieu of a feature request to enable unattended-upgrades on the Discourse docker container?

My guess is that it’s off on purpose as it might break something, and the image itself is updated when a serious security issue is found.

You can enable it if you want, just enter the container.

「いいね!」 1

Actually, I just realized that Discourse’s docker image is setup to use runit. Is systemd even installed on the Discourse docker container?

My guess is not having systemd installed is what’s breaking unattended-upgrades.

Sounds right. Some people really don’t like systemd. So you can either trust that the base container gets updated regularly by people running a large team of professionals that depends on it, or you can do it some other way yourself and hope that you don’t break anything.

No it doesn’t and we don’t plan to make it use. The recommendation is to keep your host OS updated with the latest security patches.

「いいね!」 6

Which, for the record, it is.

「いいね!」 5

参考までに、Discourse Docker コンテナでは systemd が動作しないため実際には実行されない unattended-upgrades のインストール不具合を、cron ジョブを介して実行をトリガーすることで修正しました。

必要な cron ジョブを作成するために、以下の YAML テンプレートファイルを /var/discourse/templates/ ディレクトリに作成しました(Debian ベースの Discourse Docker イメージに同梱されている cron のバグ修正 コマンドも含まれています):

cat << EOF > /var/discourse/templates/unattended-upgrades.template.yml
run:
  - file:
     path: /etc/cron.d/unattended-upgrades
     contents: |+
        ################################################################################
        # File:    /etc/cron.d/unattended-upgrades
        # Version: 0.2
        # Purpose: run unattended-upgrades in lieu of systemd. For more info see
        #           * https://wiki.opensourceecology.org/wiki/Discourse
        #           * https://meta.discourse.org/t/does-discourse-container-use-unattended-upgrades/136296/3
        # Author:  Michael Altfield <michael@opensourceecology.org>
        # Created: 2020-03-23
        # Updated: 2020-04-23
        ################################################################################
        20 04 * * * root /usr/bin/nice /usr/bin/unattended-upgrades --debug
        

  - exec: /bin/echo -e "\n" >> /etc/cron.d/unattended-upgrades
  # fix the Docker cron bug https://stackoverflow.com/questions/43323754/cannot-make-remove-an-entry-for-the-specified-session-cron
  - exec: /bin/sed --in-place=.\`date "+%Y%m%d_%H%M%S"\` 's%^\([^#]*\)\(session\s\+required\s\+pam_loginuid\.so\)$%\1#\2%' /etc/pam.d/cron
EOF

上記のテンプレートファイルを有効にするには、アプリの YAML ファイル内の templates リストに追加する必要があります。例を以下に示します:

[root@osestaging1 discourse]# head -n20 /var/discourse/containers/app.yml
## this is the all-in-one, standalone Discourse Docker container template
##
## After making changes to this file, you MUST rebuild
## /var/discourse/launcher rebuild app
##
## BE *VERY* CAREFUL WHEN EDITING!
## YAML FILES ARE SUPER SUPER SENSITIVE TO MISTAKES IN WHITESPACE OR ALIGNMENT!
## visit http://www.yamllint.com/ to validate this file as needed

templates:
  - "templates/unattended-upgrades.template.yml"
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
#  - "templates/web.socketed.template.yml"
  - "templates/web.modsecurity.template.yml"
  - "templates/web.ratelimited.template.yml"
## Uncomment these two lines if you wish to add Lets Encrypt (https)
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"
[root@osestaging1 discourse]# 

新しい Discourse の Docker イメージ(Debian 10 実行中)では、これが有効になっているようです。これは runit → cron → /etc/cron.daily/apt-compat → /usr/lib/apt/apt.systemd.daily を介して起動されます。

また、1 年前の Ubuntu 16 ベースの Docker イメージ(discourse/base:2.0.20190321-0122 ベース)でも動作していました。カスタマイズは行っていないと確信しています。

「いいね!」 1

[quote=“tormod, post:10, topic:136296”]
runit → cron → /etc/cron.daily/apt-compat → /usr/lib/apt/apt.systemd.daily の順で起動されます。[/quote]

systemd がインストールされていないため、実際には実行されません。

「いいね!」 1