这是我们关于 BSD 系列操作系统的七部分系列文章的第五部分。
OpenBSD在我心中有着特殊的地位。我花了很多时间研究它,也了解了它的各种特性。
OpenBSD 最初是从 NetBSD 的一个分支发展而来,因为 Theo de Raadt 似乎不太擅长与人合作。开个玩笑,但这确实是它的由来。OpenBSD 的核心理念始终是“安全”,并且它以对安全性的专注和卓越的声誉而闻名。整个操作系统都采用了严密的加密技术,随机化无处不在,并且默认设置也十分安全。OpenBSD 久经考验,并持续对其代码进行审计,通过大量的测试和模糊测试工具进行严密的测试。此外,OpenBSD 还孕育了许多其他重要的项目,例如 OpenSSH(你几乎肯定正在使用的 SSH)、OpenBGPD、LibreSSL、OpenSMPTD、OpenNTPD、pf 防火墙等等。
我喜欢OpenBSD的几个方面:
- 每个版本都附赠一首超赞的歌曲!没错,我说的是真的。我最喜欢的是3.6 版本里的《Ponderosa Puff》 。看看我们的文章: 十大 OpenBSD 发布歌曲。
- 对我来说,OpenBSD 是系统管理员的理想操作系统。在 OpenBSD 上,像停止/启动/启用服务等基本操作与在 Linux 上一样简单。安装软件包也同样容易。根文件系统备份的配置是预先完成的。许多系统脚本都是用 Perl 编写的。等等。
- 文档简直完美!
- 我还没试用过,但它包含一个由 OpenBSD 开发的虚拟机管理程序。
- 我并非安全专家,但根据我阅读的资料和该项目的声誉,我认为在经验丰富的管理者手中,OpenBSD 的安全性很高。但这并不意味着其他操作系统在经验丰富的管理者手中就不能做到高度安全。
- 在所有 BSD 系统中,我最喜欢它的标志,但这只是我个人的看法。
有些我不喜欢的地方:
- OpenBSD 一直以来都以运行速度慢而闻名。我认为早期这主要是因为 OpenBSD 对 SMP(同步多处理器)的支持较差。另一方面,它比大多数竞争对手支持的硬件范围更广,并且在增强安全性方面也投入了大量精力,所以……
- 安装程序没问题,但磁盘设置有点原始。
- 根据我的经验,你离项目核心代码越远,遇到问题的可能性就越大。请看下面的 Certbot 示例。这并非完全是 OpenBSD 的错,但它的用户群较小,移植优先级自然不会很高,而且它对安全性和正确性要求苛刻,因此那些主要针对其他操作系统设计的软件包往往存在问题。你始终属于那 0.01% 未经充分测试的用户群体。
- 这种文化有点令人尴尬。
OpenBSD 文化对新手不太友好,因为它的文档非常完善,你只需要阅读文档即可;如果你的问题在文档中没有得到解答,你应该去查看源代码。
开发者们也并非特别注重社区建设。他们负责开发这个操作系统。如果你喜欢,很好,可以支持它,但无论如何,开发者们都会按照自己的想法去做。这其中存在着“他们的想法”和“持续的社区支持”之间的矛盾,但我认为前者有时会占据上风。
我对 OpenBSD 的体验可谓是好坏参半。我用它运行过防火墙,它们几乎可以一直稳定运行。我还用 OpenBSD 运行过很长时间的 RAID-1 文件服务器。早期,在虚拟机上运行 OpenBSD 似乎总是需要一些特殊的参数,但现在看来一切正常。另一方面,这些年来,我在一些开发板(例如 Beagle)上试用 OpenBSD 时,也遇到过各种各样奇怪的崩溃和转储问题。
我正在安装适用于 amd64 的 OpenBSD 7.5 。

正在从 cd75.iso 启动。要么是我故意选择了一个不包含文件集的 .iso 文件来演示 OpenBSD 的镜像系统,要么是我选错了 .iso 文件。

啊,那著名的蓝底黑字白字……我也不知道为什么,但这的确是一种经典的配色方案。然后就是那句著名的提示语!

OpenBSD安装程序并非基于图形用户界面(GUI),甚至也不是基于文本用户界面(TUI),而是一个滚动式问卷。
我又开始用DHCP了,不过不管怎样,它本质上就是填写一个简短的表格。效率很高,虽然界面可能不是最友好的。
不过,如果你无法在文本界面中回答基本问题,那么 OpenBSD 可能并不适合你。

有意思……它也默认使用 MBR 而不是 GPT。所以目前只有 NetBSD 默认使用 GPT!
说实话,我觉得这样划分文件很麻烦,而且很容易出错。你不能直接说“给我50GB的根目录,2GB的交换分区,剩下的都放到/apps目录下”。我想如果我整天都这么做,也许会变成下意识的反应……也许不会。
我使用自动布局,因为 OpenBSD 会为你正确地布局权限和功能,这是推荐的做法。当我运行 OpenBSD 时,我通常会创建一个名为 /data 的 al (L) 切片,并将我的应用程序和其他东西放在其中。

分区速度非常快!请注意不同的文件系统属性。现在我们来看看集合。
我输入了“http”,然后可以选择镜像站点。


如今,没有理由不安装所有软件。安装 X Window 系统很有用,因为你最终会遇到需要它的软件包。
'bsd' 是内核。'bsd.mp' 是多进程内核。你可能会觉得在 2026 年多进程应该是默认设置,但别忘了 OpenBSD 运行在各种各样的硬件上。'bsd.rd' 是救援内核。

我很快就把这些都看完了。

恭喜!
我犯了个错误。我知道需要在 Vultr 面板中移除 ISO 文件(模拟“光盘弹出”操作)。于是我照做了,然后才想起来,如果从 Vultr 中移除 ISO 文件,虚拟机就会重启。我觉得这个机制很蠢,但 Vultr 面板就是这样运作的。
如果我先在 OpenBSD 系统中点击“(R)eboot”,它就会先卸载新创建的文件系统。但由于它没有这样做,所以在重启后……

一切恢复正常。

我们已经启动了!
请注意,首次启动时会执行一些特殊操作。我很好奇这些操作是什么……但 rc.firsttime 文件并不存在。事实上,它很难被发现——它只在安装完成后、首次启动完成之前存在。我查看了一下,发现它会运行固件更新,还会调用 syspatch 来告知系统是否有可用的补丁程序。
当然,每次启动时,内核都会重新链接以实现随机化。
安全级别
OpenBSD 有安全级别(securelevel)的概念。FreeBSD 也实现了这个概念。NetBSD 的实现方式则比较原始。这里我将解释 OpenBSD 的模型。
内核有一个名为“安全模式”的设置。它的级别从 -1 到 2,安全级别越高,安全性越高。在 -1 和 0 时,不强制执行任何额外的安全措施。在安全级别 1(默认值)下,一些新功能会生效:
/dev/mem和/dev/kmem无法打开
已挂载文件系统的原始磁盘设备是只读的。
系统不可变文件和仅追加文件标志可能无法移除。
某些 sysctl 变量无法更改
GPIO引脚被锁定
在安全级别 2,您将获得以上所有功能,此外,时间无法倒退,防火墙规则也无法更改。
为什么需要安全级别 2?也许您的路由器在启动时加载规则,日志设置为仅追加,并且防火墙规则必须重启才能更改。如果该路由器遭到入侵,您更有可能通过日志查看发生了什么,而攻击者也无法更改您的规则。
环顾四周
openbsd# df -h 文件系统大小 已用 可用 容量 挂载点 /dev/sd0a 986M 122M 815M 14% / /dev/sd0k 24.3G 18.0K 23.0G 1% /home /dev/sd0d 3.9G 14.7M 3.7G 1% /tmp /dev/sd0f 6.7G 1.4G 4.9G 23% /usr /dev/sd0g 986M 303M 634M 33% /usr/X11R6 /dev/sd0h 8.8G 146K 8.4G 1% /usr/local /dev/sd0j 5.8G 2.0K 5.5G 1% /usr/obj /dev/sd0i 2.5G 2.0K 2.3G 1% /usr/src /dev/sd0e 6.9G 10.5M 6.5G 1% /var
所有推荐大小的文件都安装完毕后,剩余的文件都被放到了 /home 目录下。我本来可以在安装过程中修改这个设置,但目前这样也行。
通常,我的做法是创建 /web 目录,因为我习惯用一个大分区,所以它空间很充足。但在这里行不通,因为 / 目录小于 1GB。我们稍后再讨论这个问题。
顺便一提,OpenBSD 默认有一个 wheel 组,但它是禁用的(因为其中没有任何用户)。“wheel”是一个组(类似于 /etc/group 文件中的组),它列出了允许切换到 root 用户权限的用户。如果该组为空,则没有任何限制——任何知道 root 密码的人都可以切换到 root 用户。OpenBSD 出厂时 wheel 组中没有任何用户。
安装软件
与 FreeBSD 类似,OpenBSD 也拥有 ports 和软件包。如果您需要使用 ports,则必须下载并解压 ports.tar.gz 文件以创建 ports 层级结构。之后,您就可以进入所需的应用程序,并执行 configure/make/make install 等操作。
在这个例子中,我们将使用软件包。我们来试试 wget。
openbsd# pkg_add wget quirks-7.14:updatedb-0p0: 正常 quirks-7.14 于 2026-05-28T20:13:45Z 签名 quirks-7.14:好的 wget-1.21.4p0:libiconv-1.17: 成功 wget-1.21.4p0:gettext-runtime-0.22.5: 成功 wget-1.21.4p0:libunistring-0.9.7: 成功 wget-1.21.4p0:libidn2-2.3.0p0: 成功 wget-1.21.4p0:libpsl-0.21.1: 成功 wget-1.21.4p0:bzip2-1.0.8p0: 成功 wget-1.21.4p0:pcre2-10.37p2: 成功 wget-1.21.4p0:成功 openbsd#
OpenBSD 真棒!它开箱即用。以前,我记得需要先配置一些 PKG 环境变量,但我很高兴现在不需要了,pkg_add(以及它的衍生函数,比如 pkg_delete、pkg_search 等)开箱即用。
我们来试试 MariaDB。
openbsd# pkg_info -Q mariadb mariadb-client-10.9.8v1 mariadb-server-10.9.8p0v1 mariadb-tests-10.9.8v1 p5-DBD-MariaDB-1.23 openbsd# pkg_add mariadb-server mariadb-client quirks-7.14 于 2026-05-28T20:13:45Z 签名 mariadb-server-10.9.8p0v1:xz-5.4.5: 正常 mariadb-server-10.9.8p0v1:lz4-1.9.4: 正常 mariadb-server-10.9.8p0v1:zstd-1.5.5: 正常 mariadb-server-10.9.8p0v1:snappy-1.1.10p1: 正常 mariadb-server-10.9.8p0v1:lzo2-2.10p2: 正常 mariadb-server-10.9.8p0v1:nghttp2-1.58.0: 正常 mariadb-server-10.9.8p0v1:ngtcp2-1.3.0: 正常 mariadb-server-10.9.8p0v1:nghttp3-1.2.0: 正常 mariadb-server-10.9.8p0v1:curl-8.7.1: 成功 mariadb-server-10.9.8p0v1:libxml-2.12.7: 正常 mariadb-server-10.9.8p0v1:mariadb-client-10.9.8v1: 成功 mariadb-server-10.9.8p0v1:p5-Params-Util-1.102: 正常 mariadb-server-10.9.8p0v1:p5-Module-Runtime-0.016p0: 正常 mariadb-server-10.9.8p0v1:p5-Math-Base-Convert-0.11p0: 成功 mariadb-server-10.9.8p0v1:p5-Clone-0.46: 正常 mariadb-server-10.9.8p0v1:p5-SQL-Statement-1.414: 成功 mariadb-server-10.9.8p0v1:p5-FreezeThaw-0.5001p0: 成功 mariadb-server-10.9.8p0v1:p5-MLDBM-2.05p0: 正常 mariadb-server-10.9.8p0v1:p5-Net-Daemon-0.49: 正常 mariadb-server-10.9.8p0v1:p5-PlRPC-0.2020p0: 正常 mariadb-server-10.9.8p0v1:p5-DBI-1.643p0: 正常 mariadb-server-10.9.8p0v1:p5-DBD-MariaDB-1.23: 正常 mariadb-server-10.9.8p0v1:正常 运行标签:确定 已安装以下新的 rcscripts:/etc/rc.d/mysqld 详情请参阅 rcctl(8)。 新增和修改的自述文件: /usr/local/share/doc/pkg-readmes/mariadb-server
所以我个人认为 MariaDB 不应该需要这些 Perl 模块,但显然 OpenBSD 需要。
注意关于“rcscripts”的那一行。我们来启动 MariaDB。我也觉得应该是 /etc/rc.d/mariadb,但我理解兼容性方面的顾虑。
openbsd# rcctl start mysqld mysqld(ok) openbsd#
OpenBSD,请接受我们的致敬。(但请看下文……其实不用致敬。)
那么你更喜欢哪一个?
rcctl start mysqld rcctl mysqld 启动
“rcctl start” 的优点在于它更符合“自然英语”的表达方式,并且具有层级结构:首先是命令,然后是命令要执行的操作,最后是目标。另一方面,“rcctl mysql start” 则允许你使用向上箭头键更轻松地将“start”替换为“stop”。
选择……
此时我会安装 Nginx 和 PHP。但是,OpenBSD 提供了一个独特的选择。它是唯一一个拥有自己 Web 服务器的 BSD 系统,它的名字就叫 OpenHTTPD。
我在一个叫 openbsdhandbook.com 的网站上找到了这篇教程。我不知道这个网站存在的意义,因为我找不到“关于”页面,但它使用了 OpenHTTPD for WordPress。
我还是会继续用Nginx。
openbsd# pkg_add certbot nginx php php-cgi fcgi php-curl php-mysqli php-zip unzip quirks-7.14 于 2026-05-28T20:13:45Z 签名 certbot-2.9.0:sqlite3-3.44.2: 成功 certbot-2.9.0:libffi-3.4.4p1: 好的 certbot-2.9.0:python-3.10.14: 成功 certbot-2.9.0:py3-ConfigArgParse-1.5.3p1: 成功 certbot-2.9.0:py3-zopeevent-4.5.0p0: 成功 certbot-2.9.0:py3-zopeinterface-5.5.2: 成功 certbot-2.9.0:py3-zopecomponent-4.2.2p8: 成功 certbot-2.9.0:py3-six-1.16.0p3: 成功 certbot-2.9.0:py3-configobj-5.0.8: 成功 certbot-2.9.0:py3-parsedatetime-2.6p1: 成功 certbot-2.9.0:py3-setuptools-68.0.0v0: 成功 certbot-2.9.0:py3-cparser-2.21: 成功 certbot-2.9.0:py3-cffi-1.16.0: 好的 certbot-2.9.0:py3-cryptography-42.0.5: 成功 certbot-2.9.0:py3-openssl-24.0.0: 成功 certbot-2.9.0:py3-josepy-1.14.0: 成功 certbot-2.9.0:py3-distro-1.8.0: 成功 certbot-2.9.0:py3-tz-2026.1: 成功 certbot-2.9.0:py3-pyRFC3339-1.1p2: 成功 certbot-2.9.0:py3-brotli-1.0.9p3: 成功 certbot-2.9.0:py3-certifi-2023.7.22: 成功 certbot-2.9.0:py3-idna-3.6: 成功 certbot-2.9.0:py3-urllib3-1.26.15: 成功 certbot-2.9.0:py3-charset-normalizer-3.3.2: 成功 certbot-2.9.0:py3-requests-2.31.0: 成功 certbot-2.9.0:py3-requests-toolbelt-0.10.1: 成功 certbot-2.9.0:py3-acme-2.9.0: 成功 certbot-2.9.0:通过 nginx-1.24.0p0:正常 含义模糊:选择 PHP 软件包 0: 1:php-8.1.28 2:php-8.2.19 3:php-8.3.7 您的选择:3 php-8.3.7:femail-1.0p1: 成功 php-8.3.7:femail-chroot-1.0p3: 成功 php-8.3.7:oniguruma-6.9.9: 正常 php-8.3.7:capstone-5.0: 成功 php-8.3.7:libsodium-1.0.19: 正常 php-8.3.7:argon2-20190702p0: 成功 php-8.3.7:通过 含义模糊:选择 php-cgi 的软件包 0: 1:php-cgi-8.1.28 2:php-cgi-8.2.19 3:php-cgi-8.3.7 您的选择:3 php-cgi-8.3.7:通过 fcgi-2.4.0p18:p5-FCGI-0.82: 正常 fcgi-2.4.0p18:正常 含义模糊:选择 php-curl 的软件包 0: 1:php-curl-8.1.28 2:php-curl-8.2.19 3:php-curl-8.3.7 您的选择:3 php-curl-8.3.7:通过 含义模糊:选择 php-mysqli 的软件包 0: 1:php-mysqli-8.1.28 2:php-mysqli-8.2.19 3:php-mysqli-8.3.7 您的选择:3 php-mysqli-8.3.7:通过 含义模糊:选择 php-zip 的软件包 0: 1:php-zip-8.1.28 2:php-zip-8.2.19 3:php-zip-8.3.7 您的选择:3 php-zip-8.3.7:libzip-1.8.0p0: 成功 php-zip-8.3.7:通过 含义模糊:选择要解压缩的软件包 0: 1:unzip-6.0p17 2:unzip-6.0p17-iconv 您的选择:1 unzip-6.0p17:成功 已安装以下新的 rcscripts:/etc/rc.d/nginx /etc/rc.d/php83_fpm 详情请参阅 rcctl(8)。 新增和修改的自述文件: /usr/local/share/doc/pkg-readmes/femail-chroot /usr/local/share/doc/pkg-readmes/nginx /usr/local/share/doc/pkg-readmes/php-8.3
好的。请注意,PHP 尚未配置。这需要:
openbsd# ls /etc/php-8.3 openbsd# cp /etc/php-8.3.sample/* /etc/php-8.3 openbsd#
我倾向于采用合理的默认值。
php-fpm 自带一个已配置好的 www 池。稍后会详细介绍。
让我们开始吧:
openbsd# rcctl start php83_fpm php83_fpm(ok) openbsd# rcctl enable php83_fpm openbsd# ps ax |grep php 59013 ?? S 0:00.01 php-fpm-8.3: 主进程 (/etc/php-fpm.conf) (php-fpm-8.3) 43846 ?? Ic 0:00.00 php-fpm-8.3: 池 www (php-fpm-8.3) 12243 ?? IC 0:00.00 php-fpm-8.3: 池 www (php-fpm-8.3)
Nginx
默认的 nginx.conf 文件没有任何 sites-available/sites-enabled 之类的配置。我创建了 /etc/nginx/sites 文件,并添加了 blog.lowend.party 的基本条目。
我创建了 /var/log/nginx 目录(尽管 nginx 已安装,但该目录并不存在),然后又创建了 /var/log/nginx/blog.lowend.party/{access,error}.log 目录。
nginx 如何轮换日志?使用 newsyslog。查看 /etc/newsyslog.conf 文件。它是一个表格,看起来我应该像 OpenHTTPD 那样,为 /var/log/nginx/blog.lowend.party/access.log 等目录添加一行。但这对于很多网站来说很快就会变得很繁琐。手册页中没有提到通配符。
我不想干扰用于 OpenHTTPD 的 /var/www 目录,所以我创建了 /var/nginx/blog.lowend.party 目录。我将 /web 目录软链接到了 /var/nginx 目录。
然后,什么方法都不管用了。
我遇到了类似这样的错误:
2026/05/29 16:25:24 [错误] 44074#0: *1 open() "/web/blog.lowend.party/index.html"
失败(2:没有该文件或目录),客户端:xxxx,服务器:blog.lowend.party,
请求:“GET /index.html HTTP/1.1”,主机:“blog.lowend.party”好吧,也许它不喜欢我的符号链接。
2026/05/29 16:38:08 [error] 48621#0: *4 "/var/nginx/blog.lowend.party/index.html"
未找到(2:没有该文件或目录),客户端:xxxx,服务器:
blog.lowend.party,请求:“GET / HTTP/1.1”,主机:“149.28.120.232”我为此苦思冥想了好一会儿。我把www的shell改成了/bin/bash,切换到这个shell,尝试访问那个文件,没问题,然后我又把www的shell改回去,挠了挠头。
那么,在什么情况下,文件完全可以访问,但正在运行的守护进程却无法访问它?
chroot。
以下是 OpenBSD 的 nginx 手册页:
-u默认情况下, nginx会 chroot(2) 到运行守护进程的用户的家目录,通常是“www”,或者nginx.conf中用户的家目录。 -u选项禁用此行为,并将nginx恢复为原始的“不安全”行为。
哦真的吗…
那是 Nginx 1.24 版本。我的 Debian 12.5 系统上安装的是 Nginx 1.22 版本,man 手册页里没有这个选项。而且在那台机器上:
# nginx -u
nginx:无效选项:“u”
所以要么这是在 1.24 版本中添加的(有可能),要么是 OpenBSD 对其进行了修补以包含此功能。
总之,www 已经被 chroot 到 /var/www(这是它的主目录)。关闭 Nginx chroot 似乎不太合适,所以我把网站根目录移动到了其他地方。
总之,如果你查看 php-fpm 的配置,你会发现它运行在/var/www/run/php-fpm.sock 的套接字上,而这个套接字恰好位于该配置内部。
总之,我修改了 Nginx 站点定义。我创建了 /var/www/nginx/blog.lowend.party 并将站点的 Web 根目录设置为
根 /nginx/blog.lowend.party;我不想改动 htdocs(因为那是 OpenHTTPD 的领域)。还有 /var/www/html,但我对 OpenHTTPD 还不熟悉,所以我觉得最好把 nginx 单独放在一个地方。
在那之后…

好了,静态HTML就上线了。现在我们来研究php-fpm。
php-fpm 的定义表明它在/var/www/run/php-fpm.sock 有一个套接字,但我必须配置 Nginx,才能让网站访问 /run/php-fpm.sock。在守护进程切换到非特权用户 (www) 之前发生的一切,都可以使用正常的绝对路径来访问。但一旦切换到“www”用户,就必须使用 chroot 路径。

好了,php-fpm 已经可以正常运行了。
MariaDB
我运行了 mysql_secure_installation 程序,结果如下:
bash-5.2# mysql_secure_installation
注意:建议所有 MariaDB 用户运行此脚本的所有部分。
服务器正在生产环境中使用!请仔细阅读每个步骤!
为了登录 MariaDB 以确保其安全,我们需要当前
root 用户的密码。如果您刚刚安装了 MariaDB,并且
还没设置root密码,直接按回车键就行了。
请输入root用户的当前密码(如果没有密码,请直接按回车):
错误 2002 (HY000): 无法通过套接字“/var/run/mysql/mysql.sock”连接到本地服务器 (2)
请输入root用户的当前密码(如果没有密码,请直接按回车):
嗯。那么……
# rcctl start mysqld mysqld(ok) # ps ax | grep my # ps ax | grep mar # ls -l /var/run/mysql/ 总计 0
所以,-1 表示 rcctl 指向 OpenBSD。如果守护进程没有启动,我希望我用来启动守护进程的工具能够告诉我它没有启动。
openbsd# cd /var/log openbsd# grep -i mysql messages 5月29日 15:15:04 openbsd groupadd[86986]: 添加了新组:名称=_mysql,组 ID=502 5月29日 15:15:04 openbsd useradd[19098]: 添加新用户:name=_mysql, uid=502, gid=502, home=/nonexistent, shell=/sbin/nologin 5月29日 15:42:14 openbsd pkg_add: 添加了 php-mysqli-8.3.7 openbsd# grep -i mysql 守护进程 openbsd#
好吧……
这是标准的 /etc/my.cnf 文件。
[客户端-服务器] #socket=/var/run/mysql/mysql.sock #端口=3306 # 此信息将传递给所有 MariaDB 客户端 [客户] #密码=我的密码 # MariaDB 服务器 [mysqld] # 要监听所有网络地址,请使用“bind-address = *” 绑定地址=localhost # 存放数据的目录 #data=/var/mysql # 这是所有日志、错误和复制文件要使用的前缀名称 #log-basename=mysqld # 日志记录 #通用日志 #慢查询日志
我取消了 general-log 的注释。没有变化。
我注意到既没有 /var/lib/mysql 目录,也没有 /var/mysql 目录。但是,有一个 mysql_install_db 命令。我们来试试运行它。
openbsd# mysql_install_db 警告:无法使用 /usr/local/bin/resolveip 查找主机“openbsd.my.domain”。 这可能意味着您的 libc 库并非完全兼容。 使用此二进制 MariaDB 版本,MariaDB 守护进程 mysqld 应该可以正常工作。 通常情况下,主机名解析会失效。 这意味着你应该使用IP地址而不是主机名。 指定 MariaDB 权限时! 正在“/var/mysql”中安装 MariaDB/MySQL 系统表... 好的 创建了两个拥有所有权限的账户。 一个是 root@localhost,它没有密码,但你需要…… 需要以系统“root”用户身份连接。例如,使用 sudo mysql 命令。 第二个是 _mysql@localhost,它也没有密码,但是 您需要以系统用户“_mysql”的身份进行连接。 连接成功后,您可以设置密码(如果需要的话)。 能够以这些用户中的任何一个身份连接,只需密码,无需 sudo。 请访问 https://mariadb.com/kb 查看 MariaDB 知识库。 您可以使用以下命令启动 MariaDB 守护进程: /etc/rc.d/mysqld 启动 请访问 https://mariadb.org/jira 报告任何问题。 有关 MariaDB 的最新信息可在 https://mariadb.org/ 获取。 欢迎加入 MariaDB 强大而充满活力的社区:介入
之后它就开始运行了:
83277 p0 斯普 0:00.02 /bin/sh /usr/local/bin/mariadbd-safe 32870 p0 S 0:00.18 /usr/local/libexec/mariadbd --basedir=/usr/local --datadir=/var/mysql --pl
真的,这难道不应该作为软件包安装的一部分运行吗?我希望看到的是合理的默认设置和能够正常运行的软件。
现在我可以运行 mysql_secure_installation 并创建数据库和用户了。解压 WordPress 最新压缩包后:

Certbot
当然,我们现在用的是http,但我们想要https。我已经安装了'certbot'软件包。看看它是否有效:
openbsd# certbot --authenticator webroot --installer nginx --webroot-path /var/www/nginx/blog.lowend.party 调试日志已保存至 /var/log/letsencrypt/letsencrypt.log 请求的 nginx 插件似乎未安装。
嗯。Debian 系统上有 python3-certbot-nginx 软件包,但 OpenBSD 系统上没有。
openbsd# man certbot 手册中没有 certbot 的条目。
真令人失望。我去我的Linux系统上看看 certbot 的手册。里面有个“certbot plugins”命令,果然,没有安装 Nginx 插件。
我想我是通过pip安装的……?我搜索的所有结果都指向apt命令,哈哈。
顺便一提,OpenBSD 7.5 自带 Python 3.10。
openbsd# pip3 install certbot-nginx
错误:外部管理环境
× 此环境由外部管理
╰─> 此 Python 安装由 pkg_add(1) 管理。
要在系统范围内安装 Python 包,请使用操作系统软件包管理器。
例如,可以这样写:“pkg_add py3-somepackage”。
否则,对于未包含在软件包中的软件,
建议创建一个“venv”(虚拟环境,参见)。
https://docs.python.org/3/library/venv.html) 并将其安装到那里。
对于独立应用程序,pipx(位于 py3-pipx 包中)可以
我们可以帮您管理这件事。
真是太可惜了。
好的,那么……
openbsd# mkdir -p /usr/local/python3-venv/certbot-venv python3 -m venv /usr/local/python3-venv/certbot-venv /usr/local/python3-venv/certbot-venv/bin/activate 使用 pip3 安装 certbot-nginx
……但失败了
为收集的包裹构建轮子:密码学……因为我没有安装 Rust 编译器。是的,看来我需要一个 Rust 编译器才能使用 Let's Encrypt。
pkg_add rust
进而
构建密码学轮子(pyproject.toml)耗时太久了。真是紧张!可惜,最终还是以一连串的 Rust 错误告终,错误信息如下:
原因:
进程未成功退出:`/tmp/pip-install-g1i5s24a/cryptography_6751bdb65bd643328c0d0dd2cb9623e6/src/rust/target/release/build/cryptography-cffi-69dd56dd49fae026/build-script-build`(退出状态:101)
--- 标准输出
cargo:rustc-check-cfg=cfg(python_implementation, values("CPython", "PyPy"))
cargo:rerun-if-env-changed=PYO3_PYTHON
cargo:rerun-if-changed=../../_cffi_src/
cargo:rerun-if-changed=../../cryptography/__about__.py
cargo:rustc-cfg=python_implementation="CPython"
--- 标准错误输出
主线程在 cryptography-cffi/build.rs:63:49 处发生 panic:
找不到 openssl 包含路径
注意:运行程序时需添加 `RUST_BACKTRACE=1` 环境变量以显示回溯信息。
错误:`cargo rustc --lib --message-format=json-render-diagnostics --manifest-path src/rust/Cargo.toml --release -v --features pyo3/extension-module --crate-type cdylib --` 执行失败,错误代码为 101
[输出结束]
注意:此错误源自子进程,可能与 pip 无关。
错误:构建加密轮失败
构建密码学失败
错误:无法构建加密所需的 wheel 包,这是安装基于 pyproject.toml 的项目所必需的。
我力不从心。
一个CPU?
我在检查的时候,查看了 top 命令,发现只看到一个 CPU。我又仔细检查了 Vultr 控制面板,确认这台虚拟机确实配置了两个 CPU。
那么,如何查看 OpenBSD 系统上有多少个 CPU 呢?没有 /proc 目录。dmesg 显示:
CPU0:英特尔至强处理器(Skylake,IBRS),2594.04 MHz,时序 06-55-04 CPU1:英特尔至强处理器(Skylake,IBRS),2593.97 MHz,时序 06-55-04
或许正确的答案是 sysctl(1)。运行该命令会输出所有 sysctl 值,包括:
hw.ncpufound=2 hw.allowpowerdown=1 hw.smt=0 hw.ncpoonline=1
什么?!只有一个 CPU 在线?这跟 dmesg 里显示有 CPU 在线一致,但 top 命令的输出却不是这样:


那么 CPU1 发生了什么?我们来看看 dmesg 的输出:
OpenBSD 7.5 (GENERIC.MP) #82:2026 年 3 月 20 日星期三 15:48:40 MDT
[email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
实际内存 = 2130554880 (2031MB)
可用内存 = 2045083648 (1950MB)
随机:来自 bootblocks 的良好种子
根目录下的 mpath0
scsibus0 在 mpath0:256 个目标
mainbus0 位于根目录
主总线0上的bios0
acpi0 在 bios0:ACPI 1.0
acpi0:睡眠状态 S3 S4 S5
acpi0:表 DSDT FACP APIC HPET WAET
acpi0:唤醒设备
acpitimer0 在 acpi0:3579545 Hz,24 位
acpimadt0 在 acpi0 地址 0xfee00000:PC-AT 兼容性
mainbus0 处的 cpu0:apid 0(引导处理器)
CPU0:英特尔至强处理器(Skylake,IBRS),2594.04 MHz,时序 06-55-04
cpu0:FPU、VME、DE、PSE、TSC、MSR、PAE、MCE、CX8、APIC、SEP、MTRR、PGE、MCA、CMOV、PAT、PSE36、CFLUSH、MMX、FXSR、SSE、SSE2、HTT、SSE3、PCLMUL、SSSE3、FMA3、CX16、PCID、SSE4.1、SSE4.2、x2APIC、MOVBE、POPCNT、DEADLINE、AES、XSAV E、AVX、F16C、RDRAND、HV、NXE、PAGE1GB、RDTSCP、长、LAHF、ABM、FSGSBASE、BMI1、AVX2、SMEP、BMI2、ERMS、INVPC ID、AVX512F、AVX512DQ、CLWB、AVX512CD、AVX512BW、AVX512VL、PKU、IBRS、IBPB、SSBD、ARAT、XSAVEOPT、熔断
CPU0:32KB 64位/行 8路组相联数据缓存,32KB 64位/行 8路组相联指令缓存,4MB 64位/行 16路组相联二级缓存,16MB 64位/行 16路组相联三级缓存
cpu0:smt 0,核心 0,封装 0
mtrr:支持奔腾Pro MTRR,8个可变范围,88个固定范围
CPU0:APIC 时钟运行频率为 1000MHz
mainbus0 处的 cpu1:apid 1(应用程序处理器)
CPU1:英特尔至强处理器(Skylake,IBRS),2593.97 MHz,时序 06-55-04
cpu1:FPU、VME、DE、PSE、TSC、MSR、PAE、MCE、CX8、APIC、SEP、MTRR、PGE、MCA、CMOV、PAT、PSE36、CFLUSH、MMX、FXSR、SSE、SSE2、HTT、SSE3、PCLMUL、SSSE3、FMA3、CX16、PCID、SSE4.1、SSE4.2、x2APIC、MOVBE、POPCNT、DEADLINE、AES、XSAV E、AVX、F16C、RDRAND、HV、NXE、PAGE1GB、RDTSCP、长、LAHF、ABM、FSGSBASE、BMI1、AVX2、SMEP、BMI2、ERMS、INVPC ID、AVX512F、AVX512DQ、CLWB、AVX512CD、AVX512BW、AVX512VL、PKU、IBRS、IBPB、SSBD、ARAT、XSAVEOPT、熔断
CPU1:32KB 64位/行 8路组相联数据缓存,32KB 64位/行 8路组相联指令缓存,4MB 64位/行 16路组相联二级缓存,16MB 64位/行 16路组相联三级缓存
CPU1:SMT 1,核心 0,封装 0
mainbus0 处的 ioapic0:apid 0 pa 0xfec00000,版本 11,24 引脚
acpihpet0 在 acpi0:100000000 Hz
acpiprt0 在 acpi0:总线 0 (PCI0)
acpi0 处的“ACPI0006”未配置
acpipci0 在 acpi0 PCI0
acpi0 上的“PNP0A06”未配置
acpi0 上的“PNP0A06”未配置
acpi0 上的“PNP0A06”未配置
acpi0 上的“QEMU0002”未配置
acpicmos0 在 acpi0
acpi0 处的“ACPI0010”未配置
acpicpu0 在 acpi0:C1(@1 停止!)
acpicpu1 在 acpi0:C1(@1 停止!)
cpu0:使用 Skylake AVX MDS 变通方案
pvbus0 位于 mainbus0:KVM、Hyper-V 10.0
pvclock0 在 pvbus0
hyperv0 在 pvbus0hyperv0:发布 vmbus 消息失败,错误代码 18
PCI0 在 mainbus0 总线 0
pchb0 在 pci0 设备 0 功能 0 "Intel 82441FX" rev 0x02
pcib0 位于 pci0 设备 1 功能 0 “Intel 82371SB ISA” rev 0x00
pciide0 位于 pci0 设备 1 功能 1 “Intel 82371SB IDE” rev 0x00:DMA,通道 0 连接到兼容性,通道 1 连接到兼容性
pciide0:通道 0 已禁用(无驱动器)
atapiscsi0 在 pciide0 通道 1 驱动器 0
scsibus1 在 atapiscsi0:2 个目标
cd0 在 scsibus1 targ 0 lun 0: <QEMU, QEMU DVD-ROM, 2.5+> 可移动
cd0(pciide0:1:0): 使用 PIO 模式 4,DMA 模式 2
uhci0 在 pci0 设备 1 功能 2“Intel 82371SB USB” rev 0x01: apic 0 int 11
piixpm0 在 pci0 设备 1 功能 3 “Intel 82371AB Power” rev 0x03: apic 0 int 9
iic0 在 piixpm0
vga1 at pci0 dev 2 function 0 "Bochs VGA" rev 0x02
wsdisplay0 在 vga1 mux 1:控制台(80x25,vt100 模拟)
wsdisplay0:新增屏幕 1-5(80x25,VT100 模拟)
virtio0 在 pci0 设备 3 功能 0 "Qumranet Virtio 网络" rev 0x00
vio0 在 virtio0:地址 56:00:04:f0:55:23
virtio0:msix per-VQ
azalia0 在 pci0 设备 4 功能 0 "Intel 82801I HD Audio" rev 0x03: apic 0 int 11
azalia0:未找到编解码器
virtio1 在 pci0 设备 5 功能 0 "Qumranet Virtio 存储" rev 0x00
vioblk0 在 virtio1
scsibus2 在 vioblk0:1 个目标
sd0 在 scsibus2 targ 0 lun 0: <VirtIO, 块设备, >
sd0:66560MB,512字节/扇区,136314880个扇区
virtio1:msix per-VQ
virtio2 在 pci0 设备 6 功能 0 "Qumranet Virtio 内存气球" rev 0x00
viomb0 在 virtio2
virtio2:apic 0 int 10
virtio3 在 pci0 设备 7 功能 0 "Qumranet Virtio RNG" rev 0x00
viornd0 在 virtio3
virtio3:msix per-VQ
“Intel 6300ESB WDT” rev 0x00 在 pci0 设备 8 功能 0 未配置
isa0 在 pcib0
isadma0 在 isa0
fdc0 在 isa0 端口 0x3f0/6 中断 6 延迟 2
pckbc0 在 isa0 端口 0x60/5 中断 1 中断 12
pckbd0 在 pckbc0(键盘插槽)
wskbd0 在 pckbd0:控制台键盘,使用 wsdisplay0
pms0 在 pckbc0(辅助插槽)
wsmouse0 在 pms0 mux 0
pcppi0 在 isa0 端口 0x61
spkr0 在 pcppi0
usb0 在 uhci0:USB 版本 1.0
uhub0 在 usb0 配置 1 接口 0 “Intel UHCI 根集线器” rev 1.00/1.00 地址 1
uhidev0 在 uhub0 端口 1 配置 1 接口 0 "QEMU QEMU USB Tablet" rev 2.00/0.00 addr 2
uhidev0:iclass 3/0
ums0 在 uhidev0:3 个按钮,Z 方向
wsmouse1 在 ums0 mux 0
vscsi0 位于根目录
scsibus3 在 vscsi0:256 个目标
根目录下的 softraid0
软RAID0上的scsibus4:256个目标
sd0a 上的根分区 (5f3c9329743bf957.a) sd0b 上的交换分区 sd0b 上的转储文件
警告:/mnt 未正确卸载
fd0 在 fdc0 驱动器 1:密度未知
没有给出 CPU1 离线的具体原因。
我使用 Vultr 的 7.5 模板启动了另一个配置完全相同的虚拟机。顶部显示:

还记得我说过在虚拟机上运行 OpenBSD 似乎总是需要一些特殊参数吗?
不,实际上发生的情况是,Vultr 显示的是 2 个核心,但 OpenBSD 检测到它启用了超线程,而OpenBSD 认为超线程存在不可接受的安全风险,因此将其禁用。要启用两个 CPU:
openbsd# sysctl hw.smt=1 hw.smt: 0 -> 1
进而:

果然,Vultr 模板会将此内容添加到 /etc/sysctl.conf 中。
不过,我认为 dmesg 在禁用 CPU 时可以更明确一些。
港口
我对 Nginx chroot 功能很好奇,所以就安装了 ports。安装说明在 FAQ 里,可以直接复制粘贴。解压后,ports 里有很多软件可以安装,二进制包就是从这里构建的。我在 www/nginx/patches 上找到了patch-man_nginx_8,里面介绍了 -u 参数。
然后我在 /usr/ports/www/nginx 中执行了“make”命令,并看到出现了各种“应用 OpenBSD 补丁”的消息。
临行之前:pf
OpenBSD 曾使用过 IPFilter,但由于许可条款的变更,他们通过一次精彩的黑客马拉松从零开始开发了一个替代方案。pf 不仅被 OpenBSD 使用,也被其他所有 BSD 系统(FreeBSD、DragonFlyBSD、NetBSD)、macOS、iOS 等广泛使用。
If you've done one firewall, you've done them all in my opinion but I'm sure if I worked on networks and firewalls all day long I'd see the differences. pf has a good reputation.
The default pf.conf and also /etc/examples/pf.conf both show ways how to setup your firewall rules. Here's is another:
# Set macros for port numbers. pf uses the term 'macros' SSH_PORT = 22 HTTP_PORT = 80 # Define interfaces ext_if = "vio0" # Set default policy set block-policy drop # Skip loopback interface set skip on lo0 # Allow inbound SSH and HTTP traffic pass in on $ext_if proto tcp from any to any port $SSH_PORT pass in on $ext_if proto tcp from any to any port $HTTP_PORT # Block all other inbound traffic block in on $ext_if
结论
I learned a lot in this, mainly because I've never used OpenBSD as a web server before. I'm not sure it's the platform's strengths, though I'm sure with some research I could have got certbot working (manually if necessary). BTW, there's no cron job put in place for certbot renewals.
The experience with Certbot above is not atypical of my experiences with OpenBSD over the years. You do learn a lot, but what is easy on Linux often requires a lot of manual work. In this case, instead of a single pkg_add, you install pip, build a venv, install modules, install rust, and it still fails. Now, true, maybe the real answer here is that I should build a certbot plugins package for OpenBSD on Nginx. Or use OpenHTTPD.
OpenBSD's assumption is that you are a very good sysadmin. When I started back on SunOS, building your own kernel, downloading and compiling software from scratch, etc. was considered sysadmin work. There was no package manager per se. OpenBSD to me harkens back to that era, but in between there's been an explosion of complexity in software.
In its core domain, OpenBSD works very well. And of course there are developers who've got OpenBSD laptops with X-windows and people can do nearly everything with it. But I think for me it's going to remain as my firewall/edge/jump server/bastion host go-to, not as a daily app server.