MKJ 的 Discourse 部署配置

我在更新时遇到了错误

api_key = "a quick brown fox"
fetch("https://api.example.com/data", headers: { 'Authorization' => api_key })

请帮我修复它。up/backup-config

restic --cache-dir=/var/restic
backup
/etc
/root
/var/discourse
/opt/backup
–exclude /var/discourse/shared/data/postgres_data

restic --cache-dir=/var/restic forget
–prune --keep-hourly 24 --keep-daily 7 --keep-monthly 3
EOF

chmod +x backup


这些细节会根据 restic 目标的不同而有所差异。并非所有目标都使用 AWS 环境变量,因此请阅读 restic 文档。

```shell
# cat > backup-config <<EOF
### 这些细节取决于你配置的 restic 目标,因此请修改它们
export AWS_ACCESS_KEY_ID=你的访问密钥
export AWS_SECRET_ACCESS_KEY=你的密钥
export RESTIC_PASSWORD_FILE=/root/restic-password
export RESTIC_REPOSITORY=参见 restic 文档
EOF
# {$EDITOR:-nano} /root/restic-password

你需要保存一份 /root/restic-password 中内容的副本,否则你将无法读取备份!请使用你的密码保险箱。

最后,创建一些服务,初始化 restic 存储库,并设置一个计时器以开始备份。

# cat > /etc/systemd/system/backup.service <<EOF
[Unit]
Description=备份到远程目标
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
StandardOutput=file:/var/log/backup.out
StandardError=file:/var/log/backup.err
WorkingDirectory=/var/discourse
ExecStart=/opt/backup/backup

[Install]
WantedBy=multi-user.target
EOF
# cat > /etc/systemd/system/backup.timer <<EOF
[Unit]
Description=定期系统备份

[Timer]
Persistent=true
OnCalendar=00/4:30:00
Unit=backup.service

[Install]
WantedBy=timers.target
EOF

# systemctl daemon-reload
# . /opt/backup/backup-config
# restic init
# /opt/backup/backup
# systemctl enable backup.timer

完成此过程后,你应该能够看到你已经创建了初始备份。

# restic snapshots

我已成功使用这种方式制作的 restic 备份,通过 restic restore 命令将 Discourse 服务器从一个系统迁移到另一个系统。

流式 minio 图像备份

作为 Restic 的替代方案,虽然数据库备份可以存储到 S3,但没有独立于从 S3 提供图像的 S3 图像备份。另一种方法是使用 minio-client 将图像复制到任何类似 S3 的存储。这可以是许多类似 S3 的目标,包括 S3 和 minio,但 不包括 DigitalOcean Spaces,因为它构建在 Ceph 文件系统之上,而 Ceph 文件系统并未以与 S3 相同的方式实现 ListObjectsV2 API。

在 S3 中,创建一个阻止公共访问的存储桶(在 AWS 中,权限阻止公共访问 是正确设置的最简单方法)。

以某种方式安装 minio-client (mc)。这是一种方法。

curl https://dl.min.io/client/mc/release/linux-amd64/mc > /usr/local/bin/mc && chmod +x /usr/local/bin/mc

使用类似以下的命令配置一个名为 backup 的别名来设置 minio-client:

# mc alias set backup https://s3.amazonaws.com ACCESSKEY SECRETKEY --api S3v4
# mc mirror /var/discourse/shared/standalone/uploads backup/UPLOADS-BACKUP-BUCKET

然后创建一个服务 /etc/systemd/system/backup-uploads.service,如下所示:

[Unit]
Description=Discourse 上传文件的近实时远程备份同步
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=600
User=root
ExecStart=/usr/local/bin/mc mirror --overwrite -a --watch /var/discourse/shared/app/uploads backup/UPLOADS-BACKUP-BUCKET

[Install]
WantedBy=multi-user.target

请注意,此处的 UPLOADS-BACKUP-BUCKET 应该是一个与配置 Discourse 上传数据库备份的 s3_backup_bucket 不同的存储桶。另外,请注意,如果你使用标准的多容器部署,路径将是 /var/discourse/shared/web_only/uploads

# systemctl enable backup-uploads
# systemctl start backup-uploads
# journalctl -fu backup-uploads

上传一个测试图像,确保你看到成功备份原始图像和优化图像的行。在 journalctl 中按 Control-C 将退出跟随模式。

恢复

截至本文撰写时,我从未需要测试此计划。此摘要可能会遗漏一些内容。

  • 通常恢复所有备份的文件
  • 启动 nginx(现在你的维护页面将显示)
  • 使用 /var/discourse/containers 中恢复的文件进行正常的 Discourse 部署
  • 如果你没有从备份中恢复,请在 /usr/local/bin/mc 中安装 minio-client
  • 如果你没有备份 /root/mc,设置备份别名 # mc alias set backup https://s3.amazonaws.com ACCESSKEY SECRETKEY --api S3v4
  • # mc cp backup/UPLOADS-BACKUP-BUCKET /var/discourse/shared/app/uploads
  • 恢复最近的数据库备份;我建议你 Restore a backup from the command line
  • 只有在你确认站点运行正常后,才按照上述文档重新配置上传备份到 S3。

流式 postgresql 备份

未来,我可能会创建、测试并提供一种配置,以启用使用 连续 WAL 归档 通过 postgresql 中的 archive-command 使用 minio-client 流式传输近乎即时的 Postgres 备份,类似于流式上传备份。

性能监控

至少有两种性能监控方法。

Prometheus 容器

设置 prometheus,如果你在同一个系统上运行它,将 prometheus 日志放在 /var/discourse/shared/prometheus 中。Prometheus 文件可能会变得很大,你不想让它们填满根文件系统;如果你迁移到新的主机系统(无论是升级到更大的 VM 还是安装新操作系统的 VM),你可能也想带上它们。

如果你在 Discourse 系统(或公共互联网上的任何地方)部署 prometheus,请在其前面配置安全。以这种方式安装,一种选择是使用如下 nginx 配置:

  location /prometheus/ {
    auth_basic "Prometheus";
    auth_basic_user_file /etc/nginx/prometheus-htpasswd;
    proxy_pass http://localhost:9090/;
  }

Sysstat

如果 Prometheus 过于复杂,请考虑使用 sysstat 代替。

  • dnf install sysstat(或在 debian 及其衍生版本上 apt install sysstat
  • systemctl enable --now sysstat
  • systemctl enable --now sysstat-collect.timer
  • systemctl enable --now sysstat-summary.timer
  • systemctl edit sysstat-collect.timer 并将 OnCalendar=*:00/10 更改为 OnCalendar=*:00/2
  • 如果 /etc/default/sysstat 存在,将 false 更改为 true

此后,sar 命令可以告诉你是否偶尔资源不足。

其他资源

这里有一个补充(且更紧凑)的讨论,关于在内部使用 Discourse 作为主要的内部沟通形式。

54 个赞

您好,感谢您提供这份操作指南

您目前的 CPU(核心数)和内存是多少?
您当前的设置如下:
\n\n db_shared_buffers: \"xGB\"\n db_work_mem: \"xMB\"\n UNICORN_WORKERS:\n

2 个 vCPU(L5640 Xeon),4GB 内存——不过,得益于大规模的数据导入,我们每个同时在线用户的内容量比典型的完全自然增长的 Discourse 站点都要大。我们很少同时有超过 5 个用户。

我目前未在 data.yml 中设置 db_work_mem,但看起来它在 /etc/postgresql/13/main/postgresql.conf 中被设置为 10MB。在我的 data.yml 中,我设置了 db_shared_buffers: "768MB",但现在我发现数据容器中的 /etc/postgresql/13/main/postgresql.conf 显示 shared_buffers = 512MB,这让我感到意外。显然,我在上次更改后没有重建数据容器。:roll_eyes: 我在添加 prometheus(占用更多内存)之前进行了配置更改,因此在我更改该设置之前,我可能会先将 prometheus 迁移到该服务器实例之外。

在应用中,我设置了 UNICORN_WORKERS: 4

1 个赞

感谢 @mcdanlj 提供的所有这些好东西。关于定期/计划维护有什么建议吗?比如每周/每月重启?或者带自动重启的上下行监控?还有其他定期手动或自动维护吗?

1 个赞

@jaffadog 请关注 release-notes 标签(位于右上角的铃铛图标;我使用的是“Watching First Post”)和/或将 https://meta.discourse.org/tag/release-notes.rss 添加到您的 RSS feed 中,以便了解发布信息。应用程序通常每月发布一次,这涵盖了每月重启。我不会按计划更频繁地重启。另外:

如果您使用 letsencrypt 和 mail_receiver,您可能应该将其设置为在获取新证书后重启 mail_receiver。

目前我想到的就这些。感谢您的提问,我已将如何关注 release-notes 和更多关于重启的细节纳入正文。我认为现在所有内容都已在原帖中完全涵盖。

我已将更新说明增强为在 /var/discourse 中拉取更新,以更改基础映像版本,因为在查看 Update base image for polkit vulnerability 后,我意识到不明确说明此步骤可能会产生误导。我之前认为这是基线文档的一部分。launcher 脚本包含对基础映像版本的特定引用,并且在您 git pull 之前,您将基于旧的基础映像进行构建,而不是运行已测试过的版本。(查找文件顶部的 image=。)

1 个赞

情况比这更糟:它默认配置为在一段时间后删除不活跃的 0 级账户。对我来说,这真的不是我想要的!请检查“几天后清理不活跃用户”并将其设置为零,或者一个非常大的数字。

2 个赞

我看过那个了,但据我所理解,这意味着他们从未响应过“确认您的电子邮件地址”流程,因此无论如何都不会收到电子邮件。我不认为这里的“不活跃”是指“未登录网站”,但我想知道我是否错了。

不,“inactive”在这里并不意味着 active=false

它指的是符合以下所有条件的已停用用户:

  • 信任等级 0
  • 没有帖子
  • 不是管理员,也不是版主
  • 上次登录时间超过 X 天。

是的,这种措辞确实令人困惑,尽管设置中对此有所解释(“信任等级为 0 且没有任何帖子”)。

8 个赞

实际上,我混淆了不同的设置,并且想到了“清理几天后未使用的暂存用户”。我很久以前就已经在 Maker Forums 中将“清理几天后不活跃的用户”设置为零,并且在这里未能提及;在我审计可能引起普遍兴趣的已更改站点设置时,我一定错过了它。感谢你们两位,@Ed_S@RGJ!我已经更新了帖子,增加了关于启用潜水的另一段。:smiling_face:

4 个赞

您好 @mcdanlj,感谢您在此分享的精彩见解。关于双容器安装,我不明白在执行升级时,它如何能减少停机时间。在我的测试安装中,通过 GUI /admin/upgrade#/upgrade/all 界面进行的升级确实需要几分钟时间,正如您所描述的那样,但在整个过程中,网站对用户来说仍然是可操作的。

当您必须从命令行重建两个容器安装时,可以让您在旧容器继续运行时引导新映像。

2 个赞

正如往常一样,@pfaffman 比我更快,而且他懂行。:smiley:

我从不通过 GUI 进行升级。这样,每次我更新时,都会包含 Discourse 运行所依赖的底层容器的任何系统安全更新。这并不是说使用 GUI 不好,也不是给其他所有人都推荐这样做。GUI 更新的停机时间稍短(重新启动 Web 容器会暂时中断服务,这是考虑将其与外部 nginx 结合使用的几个原因之一),所以这是一个权衡,我选择了人迹罕至的路。

如果定期更新以获取安全更新以及 Discourse 利用新 Postgresql 功能所需的偶尔数据库版本更新,那么单容器安装的停机时间会更长。在没有查看实际数据的情况下,我的直觉是,每年有 3-4 次重建的理由。如果从您的角度来看,这种停机时间是可以接受的,那么就没有太多理由去承担双容器部署的复杂性。

4 个赞

你太客气了,但这关乎的看法。 :wink:

我也是。除了我的仪表板,它在容器中有许多额外的东西(比如 Ansible,我记不清具体是什么了),如果有人在使用 dashboard.literatecomputing.com 进行升级,然后我销毁了那个容器,他们的重建就会被终止,这可能会有问题。所以我最近做了几次 docker_manager 升级,它们非常流畅。

不完全是。至少在大多数情况下,如果有新的基础镜像,docker_manager 会强制你获取它(至少它会尝试)。

差不多就是这样。供参考,我不推荐这样做,但我接触过很多人多年来零升级也没有遇到任何问题。

1 个赞

是的,毫无疑问,容器内更新的实现得非常好!

是的,这正是我所指的。:tada:

2 个赞

大家好,再次感谢你们的见解。我仍在考虑我的生产环境设置。我理论上理解为什么 2 容器安装可以减少停机时间。但即使是 GUI 更新机制,我也几乎没有遇到过停机时间。我刚刚计时了一下,我进行了一次 docker-manager 更新,Discourse 落后了 22 个提交。整个过程不到 5 分钟,在此期间论坛一直可以完全运行。诚然,这次没有 PostgreSQL 更新,但如果也需要更新它,那么即使使用 2 容器方法,我也会面临最长的停机时间,对吗?所以,如果我理解正确的话,2 容器方法只在需要 SSH 登录和重建应用程序容器以进行配置更改(添加/删除插件等)时才能减少停机时间?我预计我的生产环境配置不会经常更改,所以我觉得在这种情况下不会有任何停机时间减少。或者我也需要 SSH 登录并重建容器来应用某些类型的特性/安全更新?

好的。

是的,每次更新 PostgreSQL 时,您都会面临完整的停机时间(我猜是每隔一两年一次,外加 PostgreSQL 本身的安全更新,尽管它们并不频繁)。

在我更改之前,我在进行 GUI 更新时遇到过几次失败,但不再记得细节了;那是久远的历史了。

GUI 更新不会更新基础映像,因此提供的软件(如图像处理)中的所有安全更新都不会在那里应用。

我喜欢快速重建应用程序容器,这是我处理可用应用程序容器安全更新的常规模式,这样我就永远不会因为 10 分钟的停机时间而推迟重建所有东西。这就是为什么 git pull 在启动器中是我应用每次更新的第一部分;这样,如果像图像处理程序这样的基础映像已更新,它们就会被应用,而我甚至不必考虑是否有安全更新需要应用。:smiling_face:

但最终,我个人发现双容器方法对我来说更简单,而且我绝对不是想说服别人这样做。如果根据您的知识和经验,它对您来说并不简单,请不要仅仅因为我个人主观的指南在特定情况下将其标识为有用就这样做。 :grin:

2 个赞

明白了! :wink: 我对技术实现的细节也有自己的看法,但我很欣赏你的补充观点。

嗯,这是真的吗?

无论如何,根据我使用传统论坛在 LAMP/LEMP 堆栈上安装而没有容器化的经验,导致网站被真实泄露的典型漏洞/攻击向量几乎总是在 Web 应用程序的代码或其 Web 开发框架中。因此,我倾向于更紧迫地关注 Discourse 代码库的更新,这些更新似乎由 GUI 处理,所以我想我更倾向于后者。


顺便说一句,关于停机时间,快速推荐一下 Clear Linux:我开始测试它是因为它在纯数字运算方面的低级优化,试图为我庞大的论坛导入过程节省几个小时。在这种情况下可能确实有一些速度提升,但总的来说,我的天啊,它在重启时_速度快得离谱_,尤其是在 KVM 虚拟机中。在最便宜的 VPS 上,我可以不到 5 秒就重启并重新登录 SSH。所以我期待在重要的主机操作系统更新时使用它。

是的。但每年你必须进行几次命令行重建,因为容器中的某些组件已更新。然后你将会有 5-15 分钟的停机时间。我几乎只从命令行进行升级(除了在我的仪表板上,我可能一天会更新几次仪表板插件),并且我为许多客户进行这些必需的命令行更新(据推测他们是通过 Web 界面进行更新的,但他们通常不会)。

2 个赞

Discourse 仪表板是否会专门通知这类必需的更新?还是我应该留意 Debian 的 PSA?