Files
my-vault/01_Projects/Infrastructure/VPS/hk2.chans.xyz.md
T

377 lines
9.1 KiB
Markdown
Raw Normal View History

2026-01-05 13:03:55 +08:00
# Install
## debian 13
### vps provider debian 10 install
default root:
```
8txlD7djkkKk
```
Good catch 👍 — youre right.
Debian 11 _Bullseye_ moved from the **main mirrors** to the **Debian archive repository** after its LTS phase ended in 2026. That means:
- You **can still upgrade** from Debian 10 → 11 → 12 → 13,
- But for Debian 11 youll need to point your `sources.list` to the **archive.debian.org** service, since the normal `deb.debian.org` no longer carries Bullseye.
---
## 🔧 How to Handle Missing Debian 11 (Bullseye) Repos
When upgrading **Debian 10 → 11**, change your `/etc/apt/sources.list` to use the archive:
```bash
sed -i 's|deb.debian.org|archive.debian.org|g' /etc/apt/sources.list
sed -i 's|security.debian.org|archive.debian.org|g' /etc/apt/sources.list
```
Then explicitly set it to Bullseye:
```
deb http://archive.debian.org/debian bullseye main contrib non-free
deb http://archive.debian.org/debian-security bullseye-security main contrib non-free
```
⚠️ Important: you also need to **disable `Valid-Until` checks** (since archive metadata is old). Add this to `/etc/apt/apt.conf.d/99no-check-valid-until`:
```
Acquire::Check-Valid-Until "false";
```
After that, `apt update` will work again for Debian 11 packages.
---
## 🔄 Recommended Path
- **Debian 10 → Debian 11 (Bullseye)**
using `archive.debian.org`
- **Debian 11 → Debian 12 (Bookworm)**
switch back to `deb.debian.org`
- **Debian 12 → Debian 13 (Trixie)**
upgrade normally from main repos
---
## ⚠️ Alternative Approach (Skip Hop?)
Some admins **reinstall instead of multi-hop upgrades** when theyre more than 2 releases behind.
Its often faster and cleaner to install Debian 13 fresh and migrate configs/data.
---
👉 Do you want me to prepare the **exact `sources.list` entries** for each step (10 → 11, 11 → 12, 12 → 13), so you can just copy-paste them before each upgrade?
## traefik
```compose.yml
services: 10:47:35 [24/1240]
traefik:
image: traefik:v3.4
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks: [traefik]
ports:
- "80:80"
- "443:443"
- "8080:8080" # dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
- ./dynamic:/dynamic:ro
command:
# Entrypoints
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.websecure.http.tls=true"
# Providers
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=traefik"
- "--providers.file.directory=/dynamic"
- "--providers.file.watch=true"
# Let's Encrypt (ACME)
- "--certificatesresolvers.letsencrypt.acme.email=admin@windy.me"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
# Dashboard
- "--api.dashboard=true"
- "--api.insecure=false"
# Logging
- "--log.level=INFO"
- "--accesslog=true"
# Metrics (optional)
- "--metrics.prometheus=true"
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`npm.chans.xyz`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.middlewares=dashboard-auth@docker"
- "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$apr1$$wrhTVUaG$$tcchNFj..."
networks:
traefik:
external: true
```
dashboard user and pass
```
Ahku+eRei_chu3ah
```
```
htpasswd -nb windy "Ahku+eRei_chu3ah"
```
```
windy:$apr1$wrhTVUaG$tcchNFj.yyA3OpK8f9XnA.
```
## 一步改成 MASTER
执行以下命令即可统一切换类型:
```
docker compose exec -T db psql -U pdns -d pdns -c "UPDATE domains SET type='MASTER';"
```
执行完,再确认:
```
docker compose exec -T db psql -U pdns -d pdns -c "SELECT id, name, type FROM domains ORDER BY name;"
```
应输出:
```
id | name | type ----+-----------+--------- 7 | chans.xyz | MASTER 9 | windy.me | MASTER 8 | wsvc.info | MASTER (3 rows)
```
---
## ✅ 一、明确两种元数据的作用
|kind|作用|主节点是否需要|
|---|---|---|
|`PRESIGNED`|表示该 zone 的 DNSSEC 已经签好,不需要 PowerDNS 重新签名|✅ 需要保留|
|`AXFR-MASTER-TSIG`|从节点用来验证上游 master(旧主)的 TSIG 密钥|❌ 主节点不需要|
---
## 🧹 二、删除无用的 `AXFR-MASTER-TSIG` 记录
执行:
```bash
docker compose exec -T db psql -U pdns -d pdns -c "DELETE FROM domainmetadata WHERE kind='AXFR-MASTER-TSIG';"
```
验证删除结果:
```bash
docker compose exec -T db psql -U pdns -d pdns -c "SELECT domain_id, kind, content FROM domainmetadata;"
```
应该只剩:
```
domain_id | kind | content
------------+------------+---------
7 | PRESIGNED | 1
8 | PRESIGNED | 1
9 | PRESIGNED | 1
(3 rows)
```
---
## 🧩 三、保留 `PRESIGNED`(不要删)
这三条 `PRESIGNED` 的存在说明你的 zone 已经是“预签名区”,
也就是在数据库里已经有 DNSKEY、RRSIG、NSEC/NSEC3 等签名记录,
PowerDNS 不会去重新签名,非常正确 ✅
---
## 🧰 四、确保 `supermasters` 已清空(如果还没执行)
```bash
docker compose exec -T db psql -U pdns -d pdns -c "TRUNCATE TABLE supermasters;"
```
---
## 🚀 五、重启 PDNS 并验证主节点状态
```bash
docker compose exec auth pdnsutil list-all-zones
docker compose exec auth pdnsutil check-all-zones
```
预期输出:
```
Zone "chans.xyz." (MASTER)
Zone "windy.me." (MASTER)
Zone "wsvc.info." (MASTER)
All zones OK
```
---
## ✅ 六、总结(当前应保留状态)
|表|应保留内容|已处理状态|
|---|---|---|
|domains|type=MASTER|✅|
|domainmetadata|仅 `PRESIGNED`|🧹 已清理|
|supermasters|空表|✅|
|records / cryptokeys / tsigkeys|原样保留|✅|
---
如果你愿意,我可以帮你生成一个命令脚本,一次性完成:
- 把所有域设为 MASTER
- 删除 AXFR/MASTER 相关 metadata
- 清空 supermasters
- 验证 zone 状态
你只需执行一条命令即可让任何副节点快照变主节点。是否要我生成?
```
docker compose exec auth pdnsutil metadata set wsvc.info ALLOW-AXFR-FROM "202.91.35.141"
docker compose exec auth pdnsutil metadata set windy.me ALLOW-AXFR-FROM "202.91.35.141"
docker compose exec auth pdnsutil metadata set chans.xyz ALLOW-AXFR-FROM "202.91.35.141"
docker compose exec auth pdnsutil metadata set wsvc.info TSIG-ALLOW-AXFR "mykey."
Set 'wsvc.info' meta TSIG-ALLOW-AXFR = mykey.
docker compose exec auth pdnsutil metadata set windy.me TSIG-ALLOW-AXFR "mykey."
Set 'windy.me' meta TSIG-ALLOW-AXFR = mykey.
docker compose exec auth pdnsutil metadata set chans.xyz TSIG-ALLOW-AXFR "mykey."
Set 'chans.xyz' meta TSIG-ALLOW-AXFR = mykey.
docker compose exec auth pdns_control notify windy.me
docker compose exec auth pdns_control notify chans.xyz
docker compose exec auth pdns_control notify wsvc.info
```
db-init/01-init.sh
```bash
#!/bin/bash
set -e
echo "🔧 Creating PowerDNS role and databases..."
psql -v ON_ERROR_STOP=1 --username "$PGUSER" <<-'EOSQL'
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'pdns') THEN
CREATE USER pdns WITH PASSWORD 'windyboy';
END IF;
END
$$;
EOSQL
for dbname in pdns pdnsadmin; do
if ! psql -tAc "SELECT 1 FROM pg_database WHERE datname='${dbname}'" | grep -q 1; then
echo "🆕 Creating database ${dbname} owned by pdns"
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -c "CREATE DATABASE ${dbname} OWNER pdns;"
else
echo "✅ Database ${dbname} already exists"
fi
done
echo "✅ Initialization finished."
```
```
for z in windy.me chans.xyz wsvc.info; do
docker compose exec auth pdnsutil zone unset-presigned $z
docker compose exec auth pdnsutil zone secure $z
docker compose exec auth pdnsutil zone rectify $z
done
```
```
docker compose exec auth pdnsutil zone list-all | while read z; do
docker compose exec auth pdnsutil zone list "$z" > "auth/export/$z.zone"
done
```
```
labels:
- "traefik.enable=true"
- "traefik.http.routers.pgweb.rule=Host(`pgweb.wsvc.info`)"
- "traefik.http.routers.pgweb.entrypoints=websecure"
- "traefik.http.routers.pgweb.tls.certresolver=letsencrypt"
- "traefik.http.services.pgweb.loadbalancer.server.port=8081"
2026-08-07 15:27:35 +08:00
```
## AdGuard Home
```bash
htpasswd -B -C 10 -n -b zhiqiang 6kjmnGwseQ3jlsW1
```
```
zhiqiang:$2y$10$IMskdbhx33L.L1TVptYad.4AhV4eQUy121/UtzwjXTR/Qa6eUUpHa
```