Ubuntu 22.04 安装 DNSControl 5.7 指南

Ubuntu 22.04 从零安装 DNSControl v5.7.0(tar.gz 二进制与官方 deb 双方案实测),含 sha256 校验、BIND provider 的 check/preview/push/dig 全闭环验证、升级卸载与段错误等排障实录。

DNSControlDNSControlDNS服务器网络自动化运维2026/10/26

Ubuntu 22.04 安装 DNSControl 5.7 指南

目标:在 Ubuntu 22.04 服务器上从零安装 DNSControl v5.7.0(官方 tar.gz 二进制与 deb 包两种方案),完成首次配置并用 BIND9 本地 zone 文件跑通 check → preview → push → dig 验证 全闭环。全部命令与回显来自 2026-10-25 的真实环境实测。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(Jammy),x86_64,GLIBC 2.35
  • 软件版本:DNSControl v5.7.0(2026-10-21 发布的最新稳定版)
  • 验证用 DNS 服务器:BIND 9.18.39-0ubuntu0.22.04.7(Ubuntu 官方仓库,named/dig 均来自该版本)
  • 关键路径:配置目录 /etc/dnscontrol/;zone 文件目录 /srv/zones/primary/;二进制 /usr/local/bin/dnscontrol(方案 A)或 /usr/bin/dnscontrol(方案 B)
  • 演示域名:example.io(内网演示,解析地址 192.168.1.71/192.168.1.72、2001:db8::71)

⚠️ 网络说明:实测当日 GitHub Releases 直连下载两次中断(HTTP/2 PROTOCOL_ERROR、SSL_read: Connection reset by peer),改用代理渠道后完整下载成功。下载后务必做 sha256 校验——截断的包能解压出残缺二进制,直接运行会段错误(排障实录见九、常见问题)。

二、前置条件

DNSControl 是 Go 编写的单文件静态二进制,无运行时依赖(不依赖 JDK/Python/数据库),root 或 sudo 权限即可安装。本机环境确认:

uname -m
. /etc/os-release; echo "$PRETTY_NAME"
ldd --version | head -1

实测回显:

x86_64
Ubuntu 22.04.5 LTS
ldd (Ubuntu GLIBC 2.35-0ubuntu3.15) 2.35

为了跑通端到端验证(第六节),需要一台 BIND9 作为权威 DNS。Ubuntu 仓库直接安装:

apt-get update
apt-get install -y bind9 dnsutils
named -v
dig -v | head -1

实测回显(已装环境为幂等提示,新装环境为正常安装流水):

bind9 is already the newest version (1:9.18.39-0ubuntu0.22.04.7).
dnsutils is already the newest version (1:9.18.39-0ubuntu0.22.04.7).
BIND 9.18.39-0ubuntu0.22.04.7-Ubuntu (Extended Support Version) <id:>
DiG 9.18.39-0ubuntu0.22.04.7-Ubuntu

三、版本选型说明

v5.7.0 官方 Release 为各平台提供的发布件(sha256 取自官方 checksums.txt,2026-10-25 检索):

发布件适用平台本机是否适用
dnscontrol_5.7.0_linux_amd64.tar.gzLinux x86_64(含 LICENSE/README/二进制)是(方案 A)
dnscontrol-5.7.0.amd64.debDebian/Ubuntu x86_64是(方案 B)
dnscontrol_5.7.0_linux_arm64.tar.gzLinux ARM64否
dnscontrol-5.7.0.arm64.deb / *.arm64.rpm / *.x86_64.rpmARM64 deb / RPM 系否
dnscontrol_5.7.0_darwin_all.tar.gzmacOS(通用)否
dnscontrol_5.7.0_windows_amd64.zip / windows_arm64.zipWindows否
dnscontrol_5.7.0_freebsd_*.tar.gzFreeBSD否

选型要点:Ubuntu 22.04 x86_64 可选 tar.gz 二进制(装到 /usr/local/bin,卸载干净、便于多版本并存)或 deb 包(装到 /usr/bin,纳入 dpkg 管理)。两者二进制完全相同,按团队包管理规范二选一即可。

四、方案 A:官方 tar.gz 二进制安装(推荐)

4.1 方案说明

从 GitHub Releases 下载官方 tar.gz,sha256 校验后解出单一二进制安装到 /usr/local/bin。优点:路径独立、升级/降级就是换文件、不污染 dpkg 数据库。

4.2 下载与校验

mkdir -p /opt/src && cd /opt/src
curl -fsSL -O https://github.com/DNSControl/dnscontrol/releases/download/v5.7.0/dnscontrol_5.7.0_linux_amd64.tar.gz
curl -fsSL -O https://github.com/DNSControl/dnscontrol/releases/download/v5.7.0/checksums.txt
grep linux_amd64 checksums.txt | sha256sum -c -

实测回显(重试后完整下载,校验通过):

dnscontrol_5.7.0_linux_amd64.tar.gz: OK

官方 checksums.txt 中本发布件的标准值(供核对):

c120b45a550c18c94ba2fddd09cbcddbe116e6040be12657afe7144670afc8a1  dnscontrol_5.7.0_linux_amd64.tar.gz

⚠️ 注意:直连 GitHub 不稳定时按「官方源 → 代理」降级重试,但任何渠道下载后都必须过 sha256 校验。实测第一次直连下载到 8.8MB 即断开(完整包 32,434,947 字节),残缺包解压出的二进制运行即段错误,详见九、常见问题。

4.3 解压与安装

tar -xzf dnscontrol_5.7.0_linux_amd64.tar.gz -C /opt/src
ls -l /opt/src
install -m 0755 /opt/src/dnscontrol /usr/local/bin/dnscontrol

实测回显:

-rw-r--r-- 1 1001 1001      1086 Oct 21 13:17 LICENSE
-rw-r--r-- 1 1001 1001     11181 Oct 21 13:19 README.md
-rw-r--r-- 1 root  root      1088 Oct 25 15:09 checksums.txt
-rwxr-xr-x 1 1001 1001 135127200 Oct 21 13:26 dnscontrol
-rw-r--r-- 1 root  root  32434947 Oct 25 13:50 dnscontrol_5.7.0_linux_amd64.tar.gz

压缩包内只有 LICENSE、README.md、dnscontrol 三个文件,install 将二进制以 0755 权限复制到 /usr/local/bin。

4.4 验证

ls -l /usr/local/bin/dnscontrol
/usr/local/bin/dnscontrol version

实测回显:

-rwxr-xr-x 1 root root 135127200 Oct 25 15:10 /usr/local/bin/dnscontrol
v5.7.0

输出版本号 v5.7.0 即安装成功。DNSControl 是无常驻进程的 CLI 工具,无需 systemd 托管;需要定时漂移检测的场景见七、配置说明的 cron 示例。

五、方案 B:官方 deb 包安装(dpkg 管理)

5.1 方案说明

v5.7.0 官方同时提供 dnscontrol-5.7.0.amd64.deb,适合要求「全部软件纳入 dpkg 台账」的服务器。deb 将二进制安装到 /usr/bin/dnscontrol。

5.2 下载与校验

cd /opt/src
curl -fsSL -O https://github.com/DNSControl/dnscontrol/releases/download/v5.7.0/dnscontrol-5.7.0.amd64.deb
sha256sum dnscontrol-5.7.0.amd64.deb

实测回显(与官方 checksums.txt 完全一致):

39c4aa8d994299d1ccac6d42f2c5fb64fb114f2346606040def55da36e2d3744  dnscontrol-5.7.0.amd64.deb

5.3 安装

dpkg -i dnscontrol-5.7.0.amd64.deb

实测回显:

Selecting previously unselected package dnscontrol.
(Reading database ... 5419 files and directories currently installed.)
Preparing to unpack dnscontrol-5.7.0.amd64.deb ...
Unpacking dnscontrol (5.7.0) ...
Setting up dnscontrol (5.7.0) ...

5.4 验证

dpkg -s dnscontrol | sed -n '1,10p'
dpkg -L dnscontrol
which -a dnscontrol
/usr/bin/dnscontrol version

实测回显:

Package: dnscontrol
Status: install ok installed
Priority: optional
Installed-Size: 131960
Maintainer: Tom Limoncelli <tal@whatexit.org>
Architecture: amd64
Version: 5.7.0
Description: DNSControl: Infrastructure as Code for DNS Zones
Homepage: https://docs.dnscontrol.org/
/usr
/usr/bin
/usr/bin/dnscontrol
/usr/local/bin/dnscontrol
/usr/bin/dnscontrol
/bin/dnscontrol
v5.7.0

which -a 的第一行 /usr/local/bin/dnscontrol 来自方案 A——两方案并存时 PATH 优先命中 /usr/local/bin。正式机请只保留一种安装方式,避免双副本版本漂移(见十、卸载与清理)。

5.5 方案对比与选择建议

维度方案 A:tar.gz 二进制方案 B:deb 包
安装路径/usr/local/bin/dnscontrol/usr/bin/dnscontrol
包管理不纳入 dpkg纳入 dpkg(dpkg -s/-L/-r 可查)
升级方式换文件dpkg -i 新包
多版本并存容易(改文件名即可)不便
适用手工维护的工具机、多版本灰度配置管理(Ansible/Salt)统一台账的服务器

两者二进制一致(均为 135127200 字节、v5.7.0),按团队规范任选其一。

六、首次配置与 0→1 验证(BIND provider 打通)

本节用 BIND provider 把 DNSControl 与本机 BIND9 打通:DNSControl 负责生成 zone 文件,BIND9 负责对外解析。这是零外部账号依赖的最小闭环,接通后再换成云厂商 provider 只是改 creds.json 的事。

6.1 配置目录与 creds.json

mkdir -p /etc/dnscontrol /srv/zones/primary
cd /etc/dnscontrol
cat > creds.json <<'EOF'
{
  "bind": {
    "TYPE": "BIND",
    "directory": "/srv/zones/primary"
  }
}
EOF
chmod 600 creds.json
ls -l /etc/dnscontrol

实测回显:

total 4
-rw------- 1 root root 78 Oct 25 15:10 creds.json

要点:creds.json 的顶层键 bind 是 provider 实例名(后面 dnsconfig.js 里按名引用);TYPE: "BIND" 指定 provider 类型;directory 是 zone 文件输出目录。BIND provider 无需密码,但云厂商凭证也写在这一个文件里,统一 chmod 600 收敛权限。

6.2 首个 dnsconfig.js

cat > /etc/dnscontrol/dnsconfig.js <<'EOF'
var REG_NONE = NewRegistrar("none");
var DSP_BIND = NewDnsProvider("bind", {
  "default_soa": {
    "master": "ns1.example.io.",
    "mbox": "hostmaster.example.io.",
    "refresh": 3600,
    "retry": 600,
    "expire": 604800,
    "minttl": 300
  }
});

D("example.io", REG_NONE, DnsProvider(DSP_BIND),
  NAMESERVER("ns1.example.io."),
  A("ns1", "192.168.1.71"),
  A("@", "192.168.1.71"),
  A("www", "192.168.1.72"),
  AAAA("www", "2001:db8::71"),
  CNAME("blog", "www.example.io."),
  MX("@", 10, "mail.example.io."),
  A("mail", "192.168.1.71"),
  TXT("@", "v=spf1 ip4:192.168.1.71 -all"),
  TXT("_dmarc", "v=DMARC1; p=none; rua=mailto:dmarc@example.io"),
  SRV("_sip._tcp", 10, 60, 5060, "sip.example.io."),
  CAA("@", "issue", "letsencrypt.org")
);
EOF
cd /etc/dnscontrol && dnscontrol check

实测回显:

No errors.

check 只做离线语法与合法性校验、不触碰 provider,输出 No errors. 即配置可进入下一步。DSL 各函数详解见本专栏配置参数篇,这里先把流程打通。

6.3 preview:先看差异

cd /etc/dnscontrol && dnscontrol preview

实测回显:

CONCURRENTLY checking for 1 zone(s)
Waiting for concurrent checking(s) to complete...DONE
******************** Domain: example.io
1 correction (bind)
#1: Ensuring zone "example.io" exists in "bind"
CONCURRENTLY gathering records of 1 zone(s)
Waiting for concurrent gathering(s) to complete...DONE
******************** Domain: example.io
INFO#1: Zone "example.io" does not yet exist at provider "bind". It will be created when you run `dnscontrol push`.
Done. 1 corrections.

首次运行提示 zone 不存在,1 个待执行变更(创建 zone),preview 不会落任何文件。

6.4 push:应用变更

cd /etc/dnscontrol && dnscontrol push

实测回显:

CONCURRENTLY checking for 1 zone(s)
Waiting for concurrent checking(s) to complete...DONE
******************** Domain: example.io
1 correction (bind)
#1: Ensuring zone "example.io" exists in "bind"
SUCCESS!
CONCURRENTLY gathering records of 1 zone(s)
Waiting for concurrent gathering(s) to complete...DONE
******************** Domain: example.io
13 corrections (bind)
#1: + CREATE example.io SOA ns1.example.io. hostmaster.example.io. X 3600 600 604800 300 ttl=300
+ CREATE example.io A 192.168.1.71 ttl=300
+ CREATE example.io TXT "v=spf1 ip4:192.168.1.71 -all" ttl=300
+ CREATE example.io CAA 0 issue "letsencrypt.org" ttl=300
+ CREATE _dmarc.example.io TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.io" ttl=300
+ CREATE _sip._tcp.example.io SRV 10 60 5060 sip.example.io. ttl=300
+ CREATE mail.example.io A 192.168.1.71 ttl=300
+ CREATE ns1.example.io A 192.168.1.71 ttl=300
+ CREATE www.example.io A 192.168.1.72 ttl=300
+ CREATE www.example.io AAAA 2001:db8::71 ttl=300
+ CREATE example.io NS ns1.example.io. ttl=300
+ CREATE example.io MX 10 mail.example.io. ttl=300
+ CREATE blog.example.io CNAME www.example.io. ttl=300
WRITING ZONEFILE: "/srv/zones/primary/example.io.zone" (serial 2026102500)
SUCCESS!
Done. 14 corrections.

push 把 13 条记录 + 1 次 zone 创建共 14 项变更写入 /srv/zones/primary/example.io.zone,SOA serial 自动按日期生成(2026102500)。生成的 zone 文件:

cat /srv/zones/primary/example.io.zone

实测回显:

$TTL 300
; generated with dnscontrol 2026-10-25T15:10:00Z
@                IN SOA   ns1.example.io. hostmaster.example.io. 2026102500 3600 600 604800 300
                 IN NS    ns1.example.io.
                 IN A     192.168.1.71
                 IN MX    10 mail.example.io.
                 IN TXT   "v=spf1 ip4:192.168.1.71 -all"
                 IN CAA   0 issue "letsencrypt.org"
_dmarc           IN TXT   "v=DMARC1; p=none; rua=mailto:dmarc@example.io"
_sip._tcp        IN SRV   10 60 5060 sip.example.io.
blog             IN CNAME www.example.io.
mail             IN A     192.168.1.71
ns1              IN A     192.168.1.71
www              IN A     192.168.1.72
                 IN AAAA  2001:db8::71

6.5 BIND9 加载并解析验证

把生成的 zone 挂进 BIND9(真实服务器上用 systemd 服务的 BIND9 同理,改的是同一份 named.conf.local):

cat >> /etc/bind/named.conf.local <<'EOF'

zone "example.io" {
    type master;
    file "/srv/zones/primary/example.io.zone";
    allow-update { none; };
};
EOF
named-checkconf
rndc reload

实测回显:

named-checkconf rc=0
server reload successful

逐条 dig 验证解析结果:

dig @127.0.0.1 +short SOA example.io
dig @127.0.0.1 +short NS example.io
dig @127.0.0.1 +short A example.io
dig @127.0.0.1 +short A www.example.io
dig @127.0.0.1 +short AAAA www.example.io
dig @127.0.0.1 +short CNAME blog.example.io
dig @127.0.0.1 +short MX example.io
dig @127.0.0.1 +short TXT example.io
dig @127.0.0.1 +short SRV _sip._tcp.example.io
dig @127.0.0.1 +short CAA example.io

实测回显(与上方 dig 命令一一对应):

ns1.example.io. hostmaster.example.io. 2026102500 3600 600 604800 300
ns1.example.io.
192.168.1.71
192.168.1.72
2001:db8::71
www.example.io.
10 mail.example.io.
"v=spf1 ip4:192.168.1.71 -all"
10 60 5060 sip.example.io.
0 issue "letsencrypt.org"

十条记录全部与 dnsconfig.js 声明一致,0→1 闭环打通。

6.6 幂等性验证

配置未变时再跑 preview,应报 0 变更(--full 额外打印各 provider 汇总与统计):

cd /etc/dnscontrol && dnscontrol preview --full

实测回显(节选首尾):

CONCURRENTLY checking for 1 zone(s)
Waiting for concurrent checking(s) to complete...DONE
...
******************** Domain: example.io
----- DNS Provider: bind...
0 corrections (bind)
----- Registrar: none...
0 corrections (none)
Inaccurate statistics: {"memory_in_use":17832200,"memory_in_use_str":"18 MB","num_records":12,"num_zones":1,"rc_size":200,"benchmark1":1486016,"benchmark1str":"1.4 MiB bytes"}
Done. 0 corrections.

0 corrections 说明工具幂等:期望状态与线上状态一致时不做任何修改。统计行显示本次管理 1 个 zone、12 条记录、进程内存约 18 MB。

七、配置说明

  • /etc/dnscontrol/dnsconfig.js:主配置(声明式 DSL),建议纳入 Git 管理;路径可用 --config 覆盖。
  • /etc/dnscontrol/creds.json:provider 凭证与参数,chmod 600;路径可用 --creds 覆盖,也可写成 !命令 让外部程序动态输出 JSON。
  • /srv/zones/primary/:BIND provider 的 zone 文件输出目录(在 creds.json 的 directory 里指定),BIND9 的 named.conf.local 逐个 zone 引用其中的文件;push 后需 rndc reload 让 BIND9 载入新文件。
  • 定时漂移检测(可选):DNSControl 无常驻进程,用 cron 每天比对一次线上是否被人为改动:
cat > /etc/cron.d/dnscontrol-drift <<'EOF'
17 3 * * * root cd /etc/dnscontrol && /usr/local/bin/dnscontrol preview --expect-no-changes || echo "DNS drift detected" | mail -s "dnscontrol drift" root
EOF

--expect-no-changes 在存在未声明变更时返回非零,配合邮件即可告警。

八、升级、降级与多版本管理

  • 方案 A(tar.gz):下载新版本 tar.gz → 校验 → install 覆盖 /usr/local/bin/dnscontrol;降级同理覆盖回旧版。多版本并存可把二进制命名成 dnscontrol-5.7.0、dnscontrol-5.6.0,用时显式调用全路径。
  • 方案 B(deb):dpkg -i 新版本即升级(显示 Unpacking dnscontrol (新版) over (旧版));降级先 dpkg -r dnscontrol 再装旧包。
  • 升级前阅读对应版本 Release Notes 的 Deprecation warnings 段(如官方预告 REV() 将在后续版本从 RFC2317 切到 RFC4183,属破坏性变更)。
  • 验证升级结果统一用 dnscontrol version,应输出目标版本号:
v5.7.0

九、常见问题

9.1 运行二进制报 Segmentation fault

现象:tar -xzf 解出的 dnscontrol 执行 version 直接段错误。

定位:实测中第一次直连 GitHub 下载被中断(curl 报 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR / SSL_read: Connection reset by peer),tar.gz 只有 8.8MB(完整应为 32,434,947 字节),tar 解出残缺的 32MB 二进制(完整应为 135127200 字节),运行即段错误。

解决:删除残缺文件,换可用渠道重新下载,并用官方 checksums.txt 校验通过后再解压安装。校验不通过的包一律不要用。

9.2 push 时报 could not create zonefile: no such file or directory

现象:WRITING ZONEFILE 一行后报 FAILURE! could not create zonefile: open /srv/zones/notexist/example.io.zone: no such file or directory,末尾 completed with errors。

定位:creds.json 里 directory 指向的目录不存在。

解决:mkdir -p 建好目录再 push;注意 zone 文件本身 DNSControl 会自动创建,但父目录不会。另外此类失败时 push 退出码仍为 0(变更列表照跑、最后报 completed with errors),自动化场景要同时检查输出文本。

9.3 push 成功但 dig 还是旧记录

现象:push 显示 WRITING ZONEFILE ... (serial 2026102502)、SUCCESS!,但 dig 返回修改前的地址。

定位:DNSControl 只负责写 zone 文件,BIND9 不会自动感知文件变化。

解决:每次 push 后执行 rndc reload 再验证。实测对照:未 reload 时 www.example.com 解析为旧值 192.168.1.32,rndc reload 后即新值 192.168.1.33。

9.4 creds.json 里 TYPE 写错导致初始化失败

现象:failed to initialize DNS provider "bind": if cloudflare apitoken is not set, apikey and apiuser must be provided。

定位:实例名 bind 与 TYPE 必须配套——上面这个报错是把 TYPE 误写成 CLOUDFLAREAPI(实例名仍叫 bind),DNSControl 按 TYPE 去初始化 Cloudflare 插件,自然缺凭证。

解决:TYPE 写目标 provider 的官方类型名(自建 BIND 写 "BIND"),实例名可自由起名但建议与类型可对应。

9.5 creds.json 文件缺失

现象:INFO: Config file "/etc/dnscontrol/nope.json" does not exist. Skipping.,随后 provider 初始化失败退出码 1。

解决:确认工作目录下存在 creds.json,或用 --creds=/etc/dnscontrol/creds.json 显式指定。

十、卸载与清理

方案 B(deb)卸载实测:

dpkg -r dnscontrol

实测回显:

(Reading database ... 5420 files and directories currently installed.)
Removing dnscontrol (5.7.0) ...

方案 A(tar.gz)卸载直接删二进制:

rm -f /usr/local/bin/dnscontrol

清理配置与生成的 zone 文件(按需,BIND9 中对应 zone 段先摘除):

rm -rf /etc/dnscontrol
rm -rf /srv/zones/primary
rm -f /etc/cron.d/dnscontrol-drift

十一、参考链接