Discourse 容器是否使用 unattended-upgrades?

Discourse 的 Docker 容器是否使用 unattended-upgrades 来保持其基于 Debian 的 Docker 容器操作系统包的更新?

我注意到 INSTALL-cloud.md 指南建议在 Docker 主机机器上安装 unattended-upgrades,因此我好奇 Docker 容器内部操作系统包的状态。我在 GitHub 上搜索了 discoursediscourse_docker 仓库,但唯一能找到的关于 unattended-upgrades 的引用就是同一份安装文档:

那么 Discourse 的 Docker 容器呢?它是否使用 unattended-upgrades

1 个赞

经过进一步排查,发现 unattended-upgrades 在 Discourse Docker 容器中已安装但运行。\n\n首先,它显然已安装:\n\n\nroot@osestaging1-discourse-ose:/var/www/discourse# dpkg -l | grep -i unatt\nii unattended-upgrades 1.11.2 all automatic installation of security upgrades\nroot@osestaging1-discourse-ose:/var/www/discourse# \n\n\n根据相关 Debian Wiki 文章进一步检查 unattended-upgrades 包的配置,结果显示:\n\n * https://wiki.debian.org/UnattendedUpgrades\n\n默认配置看起来是合理的:\n\n```\nroot@osestaging1-discourse-ose:/var/www/discourse# grep -ir ‘origin=’ /etc/apt/apt.conf.d/50unattended-upgrades \n// "origin=Debian,codename={distro_codename}-updates\";\n// \"origin=Debian,codename={distro_codename}-proposed-updates";\n\t\t"origin=Debian,codename={distro_codename},label=Debian\";\n\t\t\"origin=Debian,codename={distro_codename},label=Debian-Security";\nroot@osestaging1-discourse-ose:/var/www/discourse# cat /etc/apt/apt.conf.d/20auto-upgrades \nAPT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "1";\nroot@osestaging1-discourse-ose:/var/www/discourse# \n\n\n但查看日志显示,最后一条记录是在 1 个月前:\n\n\n\nroot@osestaging1-discourse-ose:/var/www/discourse# tail -f /var/log/unattended-upgrades/unattended-upgrades*.log\n==\u003e /var/log/unattended-upgrades/unattended-upgrades-dpkg.log \u003c==\nLog started: 2019-11-17 12:34:54\n(Reading database … 44559 files and directories currently installed.)\nRemoving freetype2-doc (2.9.1-3+deb10u1) …\nLog ended: 2019-11-17 12:34:54\n\nLog started: 2019-11-17 12:34:56\n(Reading database … 44389 files and directories currently installed.)\nRemoving libjs-jquery (3.3.1~dfsg-3) …\nLog ended: 2019-11-17 12:34:57\n\n\n==\u003e /var/log/unattended-upgrades/unattended-upgrades.log \u003c==\n2019-11-26 16:37:47,549 INFO Initial blacklist : \n2019-11-26 16:37:47,550 INFO Initial whitelist: \n2019-11-26 16:37:47,551 INFO Starting unattended upgrades script\n2019-11-26 16:37:47,552 INFO Allowed origins are: origin=Debian,codename=buster,label=Debian, origin=Debian,codename=buster,label=Debian-Security\n2019-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.\n2019-11-26 16:37:50,814 INFO Initial blacklist : \n2019-11-26 16:37:50,815 INFO Initial whitelist: \n2019-11-26 16:37:50,815 INFO Starting unattended upgrades script\n2019-11-26 16:37:50,815 INFO Allowed origins are: origin=Debian,codename=buster,label=Debian, origin=Debian,codename=buster,label=Debian-Security\n2019-11-26 16:37:53,119 INFO No packages found that can be upgraded unattended and no pending auto-removals\n^C\nroot@osestaging1-discourse-ose:/var/www/discourse# \n\n\n...尽管为 `unattended-upgrades` 定义的默认 systemd 定时器设置为至少每天运行一次:\n\n\n\nroot@osestaging1-discourse-ose:/var/www/discourse# cat /lib/systemd/system/apt-daily.timer\n[Unit]\nDescription=Daily apt download activities\n\n[Timer]\nOnCalendar=--* 6,18:00\nRandomizedDelaySec=12h\nPersistent=true\n\n[Install]\nWantedBy=timers.target\nroot@osestaging1-discourse-ose:/var/www/discourse# cat /etc/systemd/system/apt-daily.timer.d/override.conf\ncat: /etc/systemd/system/apt-daily.timer.d/override.conf: No such file or directory\nroot@osestaging1-discourse-ose:/var/www/discourse# cat /lib/systemd/system/apt-daily-upgrade.timer\n[Unit]\nDescription=Daily apt upgrade and clean activities\nAfter=apt-daily.timer\n\n[Timer]\nOnCalendar=--* 6:00\nRandomizedDelaySec=60m\nPersistent=true\n\n[Install]\nWantedBy=timers.target\nroot@osestaging1-discourse-ose:/var/www/discourse# cat /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf\ncat: /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf: No such file or directory\nroot@osestaging1-discourse-ose:/var/www/discourse# \n\n\n但确实,这些定时器已被禁用。\n\n\n\nroot@osestaging1-discourse-ose:/var/www/discourse# sudo systemctl status apt-daily.timer\nSystem has not been booted with systemd as init system (PID 1). Can’t operate.\nFailed to connect to bus: Host is down\nroot@osestaging1-discourse-ose:/var/www/discourse# sudo systemctl status apt-daily-upgrade.timer\nSystem has not been booted with systemd as init system (PID 1). Can’t operate.\nFailed to connect to bus: Host is down\nroot@osestaging1-discourse-ose:/var/www/discourse# \n\n\n这通过手动运行 `unattended-upgrades` 得到了进一步证实,该操作恰好需要更新两个与 git 相关的软件包:\n\n\nroot@osestaging1-discourse-ose:/var/www/discourse# sudo unattended-upgrade -d\n…\nChecking: git ([\u003cOrigin component:‘main’ archive:‘stable’ origin:‘Debian’ label:‘Debian-Security’ site:‘security.debian.org’ isTrusted:True\u003e])\nChecking: git-man ([\u003cOrigin component:‘main’ archive:‘stable’ origin:‘Debian’ label:‘Debian-Security’ site:‘security.debian.org’ isTrusted:True\u003e])\npkgs that look like they should be upgraded: git \ngit-man\n…\nAll upgrades installed\nInstCount=0 DelCount=0 BrokenCount=0\nExtracting content from /var/log/unattended-upgrades/unattended-upgrades-dpkg.log since 2019-12-24 17:32:55\nroot@osestaging1-discourse-ose:/var/www/discourse# \n```\n\n在上述 unattended-upgrades 运行中更新的 git 版本是 git (1:2.20.1-2+deb10u1)。我于今天(2019-12-24)运行了此测试,但该安全升级在 Debian Buster(构建 Discourse Docker 镜像的操作系统)上已可用两周了(自 2019-12-10 起)!\n\n这实际上是一个相当严重的升级,修复了多个漏洞,包括两个远程代码执行(RCE)漏洞。更多信息请参阅 Debian 安全公告 4581-1:\n\n * [SECURITY] [DSA 4581-1] git security update git 只是我偶然发现的一个例子。如果 Discourse Docker 容器默认情况下不对其操作系统应用与安全相关的补丁,这将是非常令人担忧的。\n\n这是一个 bug 吗?还是 Discourse 团队有意做出的决定?或者这仅仅是默认行为,除非有人提出功能请求以在 Discourse Docker 容器上启用 unattended-upgrades

我猜这是故意关闭的,因为它可能会破坏某些功能。只有发现严重安全问题时,镜像才会更新。

如果你需要,可以启用它,只需进入容器即可。

1 个赞

实际上,我刚刚意识到 Discourse 的 Docker 镜像配置为使用 runit。Discourse 的 Docker 容器中甚至安装了 systemd 吗?

我猜没有安装 systemd 是导致 unattended-upgrades 失败的原因。

听起来没错。有些人确实不喜欢 systemd。因此,你要么相信基础容器会由依赖它的专业团队定期更新,要么自己用其他方式更新,但要希望不会弄坏任何东西。

不,它不使用,我们也没有计划让它使用。建议保持您的主机操作系统更新至最新的安全补丁。

6 个赞

顺便提一下,事实确实如此。

5 个赞

供参考,我修复了损坏的 unattended-upgrades 安装(在 Discourse Docker 容器中,如果没有 systemd,它实际上无法运行),方法是通过 cron 任务触发其运行。

我在 /var/discourse/templates/ 目录下创建了以下 yaml 模板文件,以创建必要的 cron 任务(注意:它还包含一条命令来修复 cron 的一个 bug,该 bug 存在于基于 Debian 的 Discourse Docker 镜像中):

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 启动的。

该功能在一台基于 Ubuntu 16 的一年旧 Docker 镜像(基于 discourse/base:2.0.20190321-0122)上也曾运行,我相当确定没有进行任何自定义配置。

1 个赞

由于未安装 systemd,因此它实际上从未运行。

1 个赞