Files
vps/hosts/hk2.chans.xyz.md
T

145 lines
5.5 KiB
Markdown

# hk2.chans.xyz
| Item | Value |
|------|--------|
| Role | PowerDNS Authoritative (ns1) + Poweradmin / Traefik |
| SSH | `ssh -4 windy@hk2.chans.xyz` (prefer IPv4 from WSL) |
| IPv4 | `154.36.174.161` |
| Hostname (OS) | `C20210714091792` (Debian 13 trixie) |
| Also DNS | `ns1.wsvc.info` → this host |
| Secondary NS | `ns2.wsvc.info``202.91.35.141` (`us1.wsvc.info`, PowerDNS Auth **5.0.5**) |
| Install path | `/opt/pdns` |
| Compose | `/opt/pdns/compose.yml` |
| Env file | `/opt/pdns/.env` (secrets — **never commit**) |
| TZ | `Asia/Shanghai` |
Upstream docs / config checklist: [docs/pdns-upstream.md](../docs/pdns-upstream.md)
## PowerDNS Authoritative
**Status: operational** (auth + db healthy, API **5.0.6**, DNS on :53 — last config audit 2026-08-01 21:40 CST).
| Item | Value |
|------|--------|
| Image | `powerdns/pdns-auth-50:5.0.6` (pinned) |
| Container | `pdns-auth` |
| Config | `/opt/pdns/auth/pdns.conf` + `auth/templates.d/secrets.j2``pdns.d/secrets.conf` |
| Backend | PostgreSQL 16 (`launch=gpgsql`, DB name `pdns`) |
| DNS ports | host `53/tcp` + `53/udp` |
| API | host `127.0.0.1:8081` only; `webserver-allow-from` private ranges |
| Mode | `primary=yes`; `also-notify` / AXFR ACL → `202.91.35.141`; `only-notify=` empty |
| DNSSEC | `gpgsql-dnssec=yes`; CSK ECDSAP256SHA256 |
| SOA-EDIT | `default-soa-edit(-signed)=INCEPTION-INCREMENT` |
| Poweradmin | `PDNS_VERSION=50`; Traefik Host(`pdns.wsvc.info`) |
| Advisories | 2026-06 + 2026-07 cleared by 5.0.6 |
### Zones (authoritative)
| Zone | Kind | DNSSEC | Zone metadata |
|------|------|--------|---------------|
| `windy.me` | Master | yes | `ALLOW-AXFR-FROM` + `TSIG-ALLOW-AXFR=mykey.` |
| `wsvc.info` | Master | yes | same |
| `chans.xyz` | Master | yes | same |
NS set: `ns1.wsvc.info` / `ns2.wsvc.info`. Dig SOA may differ from backend serial (SOA-EDIT) — expected.
### Intended auth config (sanitized)
See full shape in [docs/pdns-upstream.md](../docs/pdns-upstream.md). Live secrets only in `.env` / generated drop-in on the server.
### Stack
| Container | Service | Status | Image |
|-----------|---------|--------|-------|
| `pdns-auth` | auth | Up (healthy) | `powerdns/pdns-auth-50:5.0.6` |
| `pdns-db` | db | Up (healthy) | `postgres:16` |
| `poweradmin` | poweradmin | Up (healthy) | `poweradmin/poweradmin:stable` |
| `pdns_pgweb` | pgweb | Up | `sosedoff/pgweb:0.16.2` |
| `pdns-backup` | backup | Up | `postgres:16` (scheduler) |
| `powerdns-admin` | *(orphan)* | Exited | legacy PDA UI — not in active compose |
### Network model
| Network | Purpose |
|---------|---------|
| `backend` | Internal (`internal: true`) — DB + service API |
| `edge` | Host-published DNS `:53` and loopback API `:8081` |
| `frontend` (`traefik`) | External Traefik network for web UIs |
### Public / management URLs
| URL | Backend | Notes |
|-----|---------|-------|
| https://pdns.wsvc.info | `poweradmin` via Traefik | DNS admin UI |
| https://pgweb.wsvc.info | `pgweb` via Traefik | DB browser (HTTP basic) |
| DNS `ns1.wsvc.info:53` | `pdns-auth` | Public authoritative |
## Config audit (vs official docs)
**Functional primary/secondary config: OK** after 5.0.6 upgrade + `only-notify=` / `domains.master` cleanup.
| Item | Verdict |
|------|---------|
| `primary` + MASTER zones + gpgsql DNSSEC | OK |
| `also-notify` + empty `only-notify` | OK (docs-recommended pattern) |
| API bind / host port publish | OK |
| SOA-EDIT with PowerDNS secondary | OK |
| API key / DB password hygiene | **Deferred** — weak, plaintext, reused |
| TSIG `mykey` | **Deferred** — any holder can AXFR (bypasses IP ACL) |
## Backup
| Item | Value |
|------|--------|
| Service | `pdns-backup` |
| Schedule | `CRON_SCHEDULE=0 3 * * *` (03:00 Asia/Shanghai) |
| Retention | `RETENTION_DAYS=7`, `MAX_BACKUPS=3` |
| Output | `/opt/pdns/backup/pdns_*.sql.gz` (+ optional `roles_*.sql`) |
| Scheduler | `scripts/backup-scheduler.sh` (daily `M H * * *` only) |
| Manual | `cd /opt/pdns && ./scripts/manual-backup.sh` |
**Quirk:** `backend` is internal — backup must not use Alpine + runtime `apk`/`crond`. Uses `postgres:16` + `backup-scheduler.sh` (fixed 2026-08-01).
## Other software on this host (stubs)
`/opt/traefik`, `/opt/adguard`, `/opt/remark42`, `/opt/rustdesk`, `/opt/nginx-manager`, …
## Ops / runbooks
- [pdns-health](../runbooks/pdns-health.md)
- [pdns-upstream docs](../docs/pdns-upstream.md)
```bash
cd ansible
ansible-playbook playbooks/health-report.yml --limit powerdns
# after reviewed auth config / secret-template / environment changes:
ansible-playbook playbooks/compose-reconcile.yml --limit powerdns \
-e '{"service_reconcile_confirm": true, "service_reconcile_targets": ["auth"]}'
```
Direct SSH remains appropriate for streaming incident logs or running the
on-server, intentionally imperative manual backup command:
```bash
ssh -4 windy@hk2.chans.xyz 'cd /opt/pdns && ./scripts/manual-backup.sh'
```
```bash
dig @154.36.174.161 NS windy.me +short
dig @154.36.174.161 SOA wsvc.info +short
# compare secondary:
dig @202.91.35.141 SOA wsvc.info +short
```
On-server docs: `/opt/pdns/README.md`, `CHANGELOG.md`.
## Verified
Last checked: **2026-08-01 21:40 CST** — operational; docs audit recorded.
- Auth **5.0.6** healthy; no Mandatory security banner
- Zones Master + DNSSEC; SOA in sync with ns2 (served serial)
- `only-notify=` + `also-notify=202.91.35.141`; MASTER `domains.master` cleared
- https://pdns.wsvc.info → **302**; https://pgweb.wsvc.info → **401**
- Hardening backlog: API/DB credential rotation + TSIG rotate (see upstream doc)