feat: make BIND paths configurable via env vars (RHEL/CentOS support)
默认路径仍为 Debian/Ubuntu 的 /etc/bind/*。通过环境变量可在 RHEL/CentOS (默认 /var/named + /etc/named.conf)上运行: BIND_CONF_DIR, BIND_ZONES_DIR, BIND_CONF_LOCAL, BIND_CONF_OPTIONS, BIND_RNDC_KEY, BIND_SERVICE README 增加 RHEL/CentOS 安装步骤、systemd Environment 示例, 并提示覆盖 BIND_CONF_LOCAL 后必须在 named.conf 里 include。 Motivation: 同一项目在 CentOS 7 上 zone 文件写不到 /var/named, Web 端新增域名后 rndc reload 找不到 zone。
This commit is contained in:
@@ -70,13 +70,15 @@ dns-service/
|
|||||||
|
|
||||||
## BIND 配置文件
|
## BIND 配置文件
|
||||||
|
|
||||||
| 文件 | 用途 | 路径 |
|
| 文件 | 用途 | 默认路径(Debian/Ubuntu) |
|
||||||
|------|------|------|
|
|------|------|---------------------------|
|
||||||
| `named.conf` | 主配置 | `/etc/bind/named.conf` |
|
| `named.conf` | 主配置 | `/etc/bind/named.conf` |
|
||||||
| `named.conf.options` | 全局选项(监听端口、转发器、查询权限) | `/etc/bind/named.conf.options` |
|
| `named.conf.options` | 全局选项(监听端口、转发器、查询权限) | `/etc/bind/named.conf.options` |
|
||||||
| `named.conf.local` | Zone 声明(由 Web UI 自动管理) | `/etc/bind/named.conf.local` |
|
| `named.conf.local` | Zone 声明(由 Web UI 自动管理) | `/etc/bind/named.conf.local` |
|
||||||
| zone files | DNS 记录文件 | `/etc/bind/zones/db.*` |
|
| zone files | DNS 记录文件 | `/etc/bind/zones/db.*` |
|
||||||
|
|
||||||
|
> **路径可通过环境变量覆盖**(见下方"路径配置"章节)。RHEL/CentOS/Rocky 默认 BIND 路径为 `/var/named`、`/etc/named.conf`,需要在环境变量里重新指。
|
||||||
|
|
||||||
## 安装部署
|
## 安装部署
|
||||||
|
|
||||||
### 1. 安装 BIND9
|
### 1. 安装 BIND9
|
||||||
@@ -88,6 +90,8 @@ apt-get install -y bind9 bind9utils dnsutils
|
|||||||
|
|
||||||
### 2. 配置 BIND
|
### 2. 配置 BIND
|
||||||
|
|
||||||
|
#### Debian/Ubuntu(默认路径)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 创建 zone 文件目录
|
# 创建 zone 文件目录
|
||||||
mkdir -p /etc/bind/zones
|
mkdir -p /etc/bind/zones
|
||||||
@@ -124,6 +128,31 @@ systemctl enable named
|
|||||||
systemctl start named
|
systemctl start named
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### RHEL / CentOS 7 / Rocky Linux
|
||||||
|
|
||||||
|
CentOS 默认 BIND 路径在 `/var/named/` 和 `/etc/named.conf`,需要:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yum install -y bind bind-utils
|
||||||
|
|
||||||
|
# Zone 文件目录(默认 /var/named 即可;如想用 /etc/bind/zones 也可以,但需同步修改下方环境变量)
|
||||||
|
mkdir -p /var/named
|
||||||
|
chown root:named /var/named
|
||||||
|
chmod 2770 /var/named
|
||||||
|
|
||||||
|
# named.conf(追加 include,让 named 加载 Web UI 写入的 named.conf.local)
|
||||||
|
grep -q 'named.conf.local' /etc/named.conf || \
|
||||||
|
echo 'include "/etc/named.conf.local";' >> /etc/named.conf
|
||||||
|
|
||||||
|
# 给 Web UI 一个空白的入口文件
|
||||||
|
touch /etc/named.conf.local
|
||||||
|
chown root:named /etc/named.conf.local
|
||||||
|
chmod 640 /etc/named.conf.local
|
||||||
|
|
||||||
|
systemctl enable named
|
||||||
|
systemctl start named
|
||||||
|
```
|
||||||
|
|
||||||
### 3. 安装 Web 应用
|
### 3. 安装 Web 应用
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -169,6 +198,50 @@ systemctl enable dns-web
|
|||||||
systemctl start dns-web
|
systemctl start dns-web
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 5. 路径配置(环境变量)
|
||||||
|
|
||||||
|
BIND 在不同发行版的默认路径不同,下面这些环境变量可以覆盖默认值(不设置则使用 Debian/Ubuntu 默认):
|
||||||
|
|
||||||
|
| 变量 | Debian/Ubuntu 默认 | RHEL/CentOS 推荐值 |
|
||||||
|
|------|--------------------|--------------------|
|
||||||
|
| `BIND_CONF_DIR` | `/etc/bind` | `/etc` |
|
||||||
|
| `BIND_ZONES_DIR` | `/etc/bind/zones` | `/var/named` |
|
||||||
|
| `BIND_CONF_LOCAL` | `/etc/bind/named.conf.local` | `/etc/named.conf.local` |
|
||||||
|
| `BIND_CONF_OPTIONS` | `/etc/bind/named.conf.options` | `/etc/named.conf` |
|
||||||
|
| `BIND_RNDC_KEY` | `/etc/bind/rndc.key` | `/etc/rndc.key` |
|
||||||
|
| `BIND_SERVICE` | `named` | `named` |
|
||||||
|
|
||||||
|
在 systemd 服务里加 `Environment=`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat > /etc/systemd/system/dns-web.service << 'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=DNS Web Manager
|
||||||
|
After=network.target named.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/root/dns-service
|
||||||
|
Environment=BIND_CONF_DIR=/etc
|
||||||
|
Environment=BIND_ZONES_DIR=/var/named
|
||||||
|
Environment=BIND_CONF_LOCAL=/etc/named.conf.local
|
||||||
|
Environment=BIND_CONF_OPTIONS=/etc/named.conf
|
||||||
|
Environment=BIND_RNDC_KEY=/etc/rndc.key
|
||||||
|
ExecStart=/usr/local/bin/gunicorn --workers 2 --bind 0.0.0.0:5300 wsgi:app
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl restart dns-web
|
||||||
|
```
|
||||||
|
|
||||||
|
> 注意:覆盖 `BIND_CONF_LOCAL` 后,**必须**让 named 主配置 include 这个文件。CentOS 7 的 `/etc/named.conf` 默认不会 include,需要按上面"配置 BIND / RHEL"一节里的命令追加 `include "/etc/named.conf.local";`。
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
### 登录
|
### 登录
|
||||||
|
|||||||
@@ -27,12 +27,16 @@ app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
|||||||
db = SQLAlchemy(app)
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
# ─── BIND paths ───
|
# ─── BIND paths ───
|
||||||
BIND_CONF_DIR = "/etc/bind"
|
# Defaults are Debian/Ubuntu (bind9). Override via env on RHEL/CentOS/Rocky:
|
||||||
BIND_ZONES_DIR = "/etc/bind/zones"
|
# BIND_CONF_DIR=/etc BIND_CONF_LOCAL=/etc/named.conf
|
||||||
BIND_CONF_LOCAL = "/etc/bind/named.conf.local"
|
# BIND_ZONES_DIR=/var/named BIND_CONF_OPTIONS=/etc/named.conf.options
|
||||||
BIND_CONF_OPTIONS = "/etc/bind/named.conf.options"
|
# BIND_RNDC_KEY=/etc/rndc.key
|
||||||
BIND_RNDC_KEY = "/etc/bind/rndc.key"
|
BIND_CONF_DIR = os.environ.get("BIND_CONF_DIR", "/etc/bind")
|
||||||
BIND_SERVICE = "named"
|
BIND_ZONES_DIR = os.environ.get("BIND_ZONES_DIR", "/etc/bind/zones")
|
||||||
|
BIND_CONF_LOCAL = os.environ.get("BIND_CONF_LOCAL", "/etc/bind/named.conf.local")
|
||||||
|
BIND_CONF_OPTIONS = os.environ.get("BIND_CONF_OPTIONS", "/etc/bind/named.conf.options")
|
||||||
|
BIND_RNDC_KEY = os.environ.get("BIND_RNDC_KEY", "/etc/bind/rndc.key")
|
||||||
|
BIND_SERVICE = os.environ.get("BIND_SERVICE", "named")
|
||||||
|
|
||||||
# ─── Record types ───
|
# ─── Record types ───
|
||||||
RECORD_TYPES = ["A", "AAAA", "CNAME", "MX", "TXT", "NS", "PTR", "SRV", "CAA", "SOA"]
|
RECORD_TYPES = ["A", "AAAA", "CNAME", "MX", "TXT", "NS", "PTR", "SRV", "CAA", "SOA"]
|
||||||
@@ -890,17 +894,17 @@ def record_delete(zone_name, idx):
|
|||||||
def service_control(action):
|
def service_control(action):
|
||||||
u = current_user()
|
u = current_user()
|
||||||
if action == "start":
|
if action == "start":
|
||||||
rc, out, err = run_cmd("systemctl start named 2>&1")
|
rc, out, err = run_cmd("systemctl start named")
|
||||||
AuditLog.log(u.username, "启动BIND服务")
|
AuditLog.log(u.username, "启动BIND服务")
|
||||||
msg = "BIND 服务已启动" if rc == 0 else f"启动失败: {err}"
|
msg = "BIND 服务已启动" if rc == 0 else f"启动失败: {out} {err}"
|
||||||
elif action == "stop":
|
elif action == "stop":
|
||||||
rc, out, err = run_cmd("systemctl stop named 2>&1")
|
rc, out, err = run_cmd("systemctl stop named")
|
||||||
AuditLog.log(u.username, "停止BIND服务")
|
AuditLog.log(u.username, "停止BIND服务")
|
||||||
msg = "BIND 服务已停止" if rc == 0 else f"停止失败: {err}"
|
msg = "BIND 服务已停止" if rc == 0 else f"停止失败: {out} {err}"
|
||||||
elif action == "restart":
|
elif action == "restart":
|
||||||
rc, out, err = run_cmd("systemctl restart named 2>&1")
|
rc, out, err = run_cmd("systemctl restart named")
|
||||||
AuditLog.log(u.username, "重启BIND服务")
|
AuditLog.log(u.username, "重启BIND服务")
|
||||||
msg = "BIND 服务已重启" if rc == 0 else f"重启失败: {err}"
|
msg = "BIND 服务已重启" if rc == 0 else f"重启失败: {out} {err}"
|
||||||
elif action == "reload":
|
elif action == "reload":
|
||||||
ok, msg = bind_reload()
|
ok, msg = bind_reload()
|
||||||
AuditLog.log(u.username, "重载BIND配置")
|
AuditLog.log(u.username, "重载BIND配置")
|
||||||
@@ -934,7 +938,7 @@ def config_view():
|
|||||||
main_content = ""
|
main_content = ""
|
||||||
|
|
||||||
# Check config
|
# Check config
|
||||||
rc, out, err = run_cmd("named-checkconf 2>&1")
|
rc, out, err = run_cmd("named-checkconf")
|
||||||
config_ok = rc == 0
|
config_ok = rc == 0
|
||||||
config_msg = out + err
|
config_msg = out + err
|
||||||
|
|
||||||
@@ -956,11 +960,11 @@ def config_options_save():
|
|||||||
# Write to temp and validate
|
# Write to temp and validate
|
||||||
with open("/tmp/named_check.tmp", 'w') as f:
|
with open("/tmp/named_check.tmp", 'w') as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
rc, out, err = run_cmd("named-checkconf /tmp/named_check.tmp 2>&1")
|
rc, out, err = run_cmd("named-checkconf /tmp/named_check.tmp")
|
||||||
run_cmd("rm -f /tmp/named_check.tmp")
|
run_cmd("rm -f /tmp/named_check.tmp")
|
||||||
|
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
flash(f"配置验证失败: {err}", "error")
|
flash(f"配置验证失败: {out} {err}", "error")
|
||||||
return redirect(url_for("config_view"))
|
return redirect(url_for("config_view"))
|
||||||
|
|
||||||
with open(BIND_CONF_OPTIONS, 'w') as f:
|
with open(BIND_CONF_OPTIONS, 'w') as f:
|
||||||
@@ -986,10 +990,10 @@ def config_local_save():
|
|||||||
f.write(content)
|
f.write(content)
|
||||||
run_cmd(f"chown root:bind {BIND_CONF_LOCAL}")
|
run_cmd(f"chown root:bind {BIND_CONF_LOCAL}")
|
||||||
|
|
||||||
rc, out, err = run_cmd("named-checkconf 2>&1")
|
rc, out, err = run_cmd("named-checkconf")
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
run_cmd(f"cp {backup} {BIND_CONF_LOCAL}")
|
run_cmd(f"cp {backup} {BIND_CONF_LOCAL}")
|
||||||
flash(f"配置验证失败,已恢复: {err}", "error")
|
flash(f"配置验证失败,已恢复: {out} {err}", "error")
|
||||||
return redirect(url_for("config_view"))
|
return redirect(url_for("config_view"))
|
||||||
|
|
||||||
bind_reload()
|
bind_reload()
|
||||||
|
|||||||
Reference in New Issue
Block a user