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

9.1 KiB
Raw Blame History

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:

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.


  • 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

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 记录

执行:

docker compose exec -T db psql -U pdns -d pdns -c "DELETE FROM domainmetadata WHERE kind='AXFR-MASTER-TSIG';"

验证删除结果:

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 已清空(如果还没执行)

docker compose exec -T db psql -U pdns -d pdns -c "TRUNCATE TABLE supermasters;"

🚀 五、重启 PDNS 并验证主节点状态

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


#!/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"

AdGuard Home

htpasswd -B -C 10 -n -b zhiqiang 6kjmnGwseQ3jlsW1

zhiqiang:$2y$10$IMskdbhx33L.L1TVptYad.4AhV4eQUy121/UtzwjXTR/Qa6eUUpHa