服务器使用 Debian/GNU Linux 的开荒指南

2026 年 8 月 11 日重写
本文首发在我的博客 :新到手的 Linux 服务器,我这样设置 | Dejavu's Blog概要
本文记录我初始化 Linux 服务器的 标准作业程序(SOP),这并非通用指南,仅作为个人快速部署环境的速查手册。
关联阅读:
性能测试
我要「验牌」(法国音~)
新服务器在重装系统前,建议先进行硬件与网络性能基准测试,使用
root用户执行YABS(Yet Another Bench Script) 脚本:curl -sL yabs.sh | bash -s -- -5测试完成后,首先核对 CPU、内存、磁盘容量及网络带宽等基础硬件信息,确认与服务商承诺规格保持一致。
参考 Geekbench 5 单核跑分评估 CPU 性能区间:
- 单核 ~400 分: 入门级性能。适合静态网页托管、轻量定时任务、机器人、轻量代理或个人博客,不适合处理高并发任务。
- 单核 ~800 分: 主流性能。足以应对常规建站(如中等流量 WordPress)、基础 Docker 容器部署及小型数据库。
- 单核 ~1200 分: 优秀性能。可承载高负载 Web 应用、中型关系型数据库(MySQL/PostgreSQL)、CI/CD 构建及多容器并行。
- 单核 ~2000 分: 顶级性能。适合单核敏感型游戏服务端、视频转码、高并发后端及数据处理。
对于 KVM 虚拟化服务器,理想情况 是多核得分接近 核心数 × 单核得分。若多核比例严重偏低,表明宿主机存在严重的 CPU 超售或资源争抢,实际使用体验会受影响。
确认上述各项指标符合预期后,即可开始初始化配置系统。
重装操作系统
重装有风险,笔者不为任何脚本的安全性背书,请自行衡量并承担后果。如果条件允许,请尽可能使用自定义 ISO 镜像手动安装。
使用一键 DD 脚本
对于不支持自定义 ISO 镜像的服务商,使用一键 DD 脚本比较方便。开始前,务必花费几分钟读下作者的说明文档,这远比盲目粘贴命令重要。
- bin456789/reinstall 支持重装的系统类型更多
- bohanwood/debi 专注于纯净、精简的 Debian 系统环境
这里以使用第一个脚本重装 Debian 13 为例:
curl -fLO https://raw.githubusercontent.com/bin456789/reinstall/main/reinstall.sh bash reinstall.sh debian 13 \ --password '替换为强密码'完成后
reboot重启,耐心等待系统重装完成。使用自定义 ISO 镜像
首选支持自定义 ISO 镜像的重装方式,以确保系统环境纯净。
完成系统安装后,使用预设凭据登录并进入后续配置。
配置非特权用户
日常运维应使用非特权用户,启用免密
sudo存在安全风险,仅建议在完全掌控系统安全的前提下配置。创建用户
下面以新建非特权用户
dejavu为例,使用root用户执行:adduser dejavu配置 sudo 免密
apt update \ && apt install -y sudo install -m 0440 /dev/null /etc/sudoers.d/90-dejavu printf '%s\n' \ 'dejavu ALL=(ALL:ALL) NOPASSWD: ALL' \ > /etc/sudoers.d/90-dejavu检查
sudoers配置:visudo -cf /etc/sudoers.d/90-dejavu visudo -cOK 的话,切换到非特权用户:
sudo -iu dejavu本文后续命令默认由该普通用户执行,需要管理员权限的命令使用
sudo。更新系统并安装基础软件
更新操作系统
sudo apt update \ && sudo apt full-upgrade -y安装基础软件包
sudo apt install -y --no-install-recommends \ ca-certificates \ curl \ git \ gnupg \ unzip \ vim \ wget \ tree设置默认编辑器
我个人习惯使用 Vim 作为默认编辑器:
sudo update-alternatives --set editor /usr/bin/vim.basic安装常用运维工具(可选)
以下软件包通常不是必须的,可根据自己需要选择安装:
sudo apt install -y --no-install-recommends \ dnsutils \ ethtool \ git \ jq \ lsof \ mtr-tiny \ ncdu \ rsync \ tcpdump \ tmux \ jq设置时区自动同步
统一时区
对于不同区域的 Linux 服务器,建议统一设置为 UTC 时区:
sudo timedatectl set-timezone UTC注意,KVM 的
kvm-clock只提供虚拟化时钟源,并不能保证外部 UTC 一致性,仍需依靠 NTP 服务同步。使用 systemd-timesyncd
适用于绝大多数使用场景:
sudo systemctl disable --now chrony 2>/dev/null || true sudo apt install -y systemd-timesyncd sudo systemctl enable --now \ systemd-timesyncd.service sudo timedatectl status sudo timedatectl timesync-status使用 Chrony
仅当机器需要极度苛刻的时间同步收敛速度和质量时,才换用 Chrony 服务:
sudo apt install -y chrony sudo systemctl disable --now systemd-timesyncd sudo systemctl enable --now chrony chronyc tracking chronyc sources -v安装 KVM Guest Agent(可选)
仅在信任服务商且宿主机已暴露
virtio-serial通道时,安装 KVM Guest Agent 才有意义。检查 QEMU Guest Agent 通道:
if [ -e /dev/virtio-ports/org.qemu.guest_agent.0 ]; then echo "QEMU Guest Agent 通道可用!" else echo "QEMU Guest Agent 通道不存在!" fi通道可用时:
sudo apt install -y qemu-guest-agent sudo systemctl enable --now qemu-guest-agent sudo systemctl status qemu-guest-agent --no-pager通道不存在时跳过安装。
配置自动安全更新
AI 时代各种软件、云服务和基础设置面临的安全风险比以前要大得多,建议启用 Debian 的自动更新安全补丁。
每日自动更新
sudo apt install -y unattended-upgrades \ needrestart # 每日更新策略 cat << 'EOF' | sudo tee /etc/apt/apt.conf.d/20auto-upgrades > /dev/null APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; EOF禁止自动重启
即使启用自动更新,生产服务器也不应当自动重启,配置:
cat << 'EOF' | sudo tee /etc/apt/apt.conf.d/52unattended-upgrades-local > /dev/null Unattended-Upgrade::Automatic-Reboot "false"; EOF启用定时任务
sudo systemctl enable --now \ apt-daily.timer \ apt-daily-upgrade.timer检查配置
sudo unattended-upgrade --dry-run apt-config dump | grep -iE 'Periodic|Unattended' systemctl list-timers 'apt-*' --all sudo unattended-upgrade --dry-run --debug sudo needrestart -r l检查自动更新日志
# unattended-upgrades 日志 sudo tail -n 100 \ /var/log/unattended-upgrades/unattended-upgrades.log # dpkg 输出 sudo tail -n 100 \ /var/log/unattended-upgrades/unattended-upgrades-dpkg.log # systemd 执行记录 sudo journalctl \ -u apt-daily-upgrade.service \ --since '7 days ago'SSH 安全加固
确认当前登录的是目标非特权用户,例如
dejavu。写入 SSH 公钥
直接写入你的 SSH 公钥内容:
install -d -m 0700 ~/.ssh touch ~/.ssh/authorized_keys chmod 0600 ~/.ssh/authorized_keys # 写入 SSH 公钥 PUBKEY='ssh-ed25519 ...<实际公钥内容>...' grep -qxF "$PUBKEY" ~/.ssh/authorized_keys \ || printf '%s\n' "$PUBKEY" >> ~/.ssh/authorized_keys或者也可以在本地计算机进行拷贝:
ssh-copy-id \ -i ~/.ssh/id_ed25519.pub \ -p <端口> \ <用户名>@服务器IP只启用 ssh.service 服务
Debian 13 的
ssh.socket固定监听 TCP 22。关闭它,SSH 监听端口统一由ssh.service和sshd_config管理。sudo systemctl disable --now ssh.socket sudo systemctl enable --now ssh.service写入 SSH 加固配置
关于选择 SSH 端口
多数教程建议将 SSH 迁移至高位端口,但是这里其实存在一个「安全悖论」。Linux 中 1024 以上的端口允许非特权用户绑定。若 SSH 服务中断,普通用户可能抢占该高位端口并伪造服务。因此,建议选择一个 1024 以下且未被常规服务占用的特权端口。cat << 'EOF' | sudo tee /etc/ssh/sshd_config.d/00-custom.conf > /dev/null # 注意修改实际的 SSH 端口 Port 822 # 未完成认证的连接最多保留 1 分钟 LoginGraceTime 1m # 禁止 root 用户直接登录 PermitRootLogin no # 检查用户目录和密钥文件权限 StrictModes yes # 开启 SSH 公钥认证 PubkeyAuthentication yes # 禁止密码认证 PasswordAuthentication no # 禁止空密码登录 PermitEmptyPasswords no # 禁止键盘交互式认证 KbdInteractiveAuthentication no # 保留 PAM 的账户检查和会话管理功能 UsePAM yes # 禁止 X11 转发 X11Forwarding no # 服务器每 60 秒检测一次客户端连接 ClientAliveInterval 60 # 客户端连续 5 次未响应后断开 ClientAliveCountMax 5 # 禁止登录前进行反向 DNS 查询 UseDNS no EOF检查配置并重启 SSH 服务
sudo sshd -t && sudo systemctl restart ssh.service不要关闭当前终端会话,新建 SSH 连接测试登录,确认无误后再退出,否则回到原会话中自查配置。
更改主机名
将
myvps替换为实际的主机名:sudo hostnamectl set-hostname <myvps> sudo vim /etc/hosts一般情况,像下面这样编辑
/etc/hosts即可。127.0.0.1 localhost 127.0.1.1 <myvps> ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters对于真实 FQDN 和固定公网 IP 的邮件服务器,则应该这样:
127.0.0.1 localhost # 替换为实际的域名 <公网 IPv4 地址> myvps.example.com <myvps> <公网 IPv6 地址> myvps.example.com <myvps> ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allroutersIPv6 静态路由
以 Netcup 服务器为例,它们提供
/64的 IPv6,建议设置静态 IPv6 路由(不同服务商配置有所区别)。sudo vim /etc/network/interfaces添加:
iface <网卡名称> inet6 static address <静态 IPv6 地址>/64 gateway fe80::1重启后生效。
更换 Linux 内核(可选)
Debian Cloud 内核精简了物理硬件驱动,面向云平台进行了虚拟化优化,更适合大多数 KVM 虚拟机。
{{<callout type="warning"title=" 风险提示 ">}}
更换内核可能导致系统无法启动,请确保具备 VNC 或带外管理手段后再进行操作。
{{</callout>}}安装
Cloud内核:ARCH="$(dpkg --print-architecture)" sudo apt install -y "linux-image-cloud-${ARCH}"重启系统:
sudo reboot重新登录后执行检查,预期输出包含
cloud-amd64或cloud-arm64。uname -r卸载标准内核(仅在成功运行 Cloud 内核后执行):
ARCH="$(dpkg --print-architecture)" case "$ARCH" in amd64) sudo apt purge -y --ignore-missing linux-image-amd64 ;; arm64) sudo apt purge -y --ignore-missing linux-image-arm64 ;; esac sudo apt autoremove --purge -y sudo update-grub启用 SSD/NVMe TRIM(可选)
检查虚拟磁盘是否支持 discard:
lsblk -DDISC-MAX非零,服务商支持 TRIM,启用定时任务:sudo systemctl enable --now fstrim.timer systemctl list-timers fstrim.timer配置 ZRAM 和 Swap
配置 ZRAM
sudo apt install -y systemd-zram-generator cat << 'EOF' | sudo tee /etc/systemd/zram-generator.conf > /dev/null [zram0] # 根据实际配置 # 物理内存的一半,最大 4GB (4096) zram-size = min(ram / 2, 4096) swap-priority = 100 EOF立即启用 ZRAM:
sudo systemctl daemon-reload sudo systemctl start [email protected]检查 ZRAM 和 Swap 状态:
sudo zramctl sudo swapon --show free -h创建 Swap 文件
以 2GB Swapfile 为例:
sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile # 自动挂载 grep -qE '^[[:space:]]*/swapfile[[:space:]]' /etc/fstab \ || echo '/swapfile none swap defaults 0 0' \ | sudo tee -a /etc/fstab > /dev/null启用 Swapfile:
sudo swapon /swapfile检查 Swap 状态:
sudo swapon --show启用 BBR 拥塞控制算法
从 Linux 4.20 起,BBR 在
qdisc未提供时会自动启用 TCP 内部pacing,因而不再强制依赖fq。此外,Debian 13 官方内核已将 BBR 编译为模块,且系统默认qdisc为fq_codel。写入配置:
cat << 'EOF' | sudo tee /etc/sysctl.d/90-bbr.conf > /dev/null net.ipv4.tcp_congestion_control = bbr EOF立即应用:
sudo sysctl --load=/etc/sysctl.d/90-bbr.conf检查当前采用算法:
sudo sysctl net.ipv4.tcp_congestion_control安装 Docker CE(可选)
清除旧版软件包
全新的操作系统可跳过此步:
sudo apt update sudo apt remove -y $( dpkg --get-selections \ docker.io docker-compose docker-doc docker-buildx \ podman-docker containerd runc \ 2>/dev/null | cut -f1 )添加 Docker 软件源
sudo apt install -y ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL \ https://download.docker.com/linux/debian/gpg \ -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc cat <<EOF | sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null Types: deb URIs: https://download.docker.com/linux/debian Suites: $(. /etc/os-release && echo "$VERSION_CODENAME") Components: stable Architectures: $(dpkg --print-architecture) Signed-By: /etc/apt/keyrings/docker.asc EOF安装 Docker
sudo apt update \ && sudo apt install -y \ docker-ce \ docker-ce-cli \ containerd.io \ docker-buildx-plugin \ docker-compose-plugin \ && sudo systemctl enable --now docker写入 Docker 配置
cat <<'EOF' | sudo tee /etc/docker/daemon.json >/dev/null { "log-driver": "local", "log-opts": { "max-size": "20m", "max-file": "5" }, "live-restore": true } EOF sudo systemctl restart docker验证安装
sudo docker version sudo docker compose version安装和配置 Nginx
建议使用 Nginx 官方软件源安装,而非 Debian 默认软件源。
环境准备
sudo apt install -y \ curl \ gnupg2 \ ca-certificates \ lsb-release \ debian-archive-keyring导入 Nginx 官方 GPG Key:
curl -fsSL https://nginx.org/keys/nginx_signing.key \ | gpg --dearmor \ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg \ > /dev/null # 注意和官方 Key 对比验证 install -d -m 700 ~/.gnupg gpg \ --dry-run \ --quiet \ --no-keyring \ --import \ --import-options import-show \ /usr/share/keyrings/nginx-archive-keyring.gpg添加 Nginx 软件源
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ https://nginx.org/packages/debian $(lsb_release -cs) nginx" \ | sudo tee /etc/apt/sources.list.d/nginx.list \ > /dev/null # 设置优先级 cat << 'EOF' | sudo tee /etc/apt/preferences.d/99nginx > /dev/null Package: * Pin: origin nginx.org Pin: release o=nginx Pin-Priority: 900 EOF安装 Nginx
sudo apt update apt-cache policy nginx sudo apt install -y nginx删除默认站点
sudo rm -f /etc/nginx/conf.d/default.conf使用 Cloudflare CDN(推荐)
创建默认回退 (Fallback) 主机
从 Nginx 1.19.4 开始,无需自签 TLS 证书即可阻断 SNI 探测:
cat << 'EOF' | sudo tee /etc/nginx/conf.d/00-default.conf > /dev/null server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name _; ssl_reject_handshake on; } EOF透传客户端真实 IP 地址
cat << 'EOF' | sudo tee /etc/nginx/conf.d/10-cloudflare-realip.conf > /dev/null set_real_ip_from 173.245.48.0/20; set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 108.162.192.0/18; set_real_ip_from 190.93.240.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; set_real_ip_from 162.158.0.0/15; set_real_ip_from 104.16.0.0/13; set_real_ip_from 104.24.0.0/14; set_real_ip_from 172.64.0.0/13; set_real_ip_from 131.0.72.0/22; set_real_ip_from 2400:cb00::/32; set_real_ip_from 2606:4700::/32; set_real_ip_from 2803:f800::/32; set_real_ip_from 2405:b500::/32; set_real_ip_from 2405:8100::/32; set_real_ip_from 2a06:98c0::/29; set_real_ip_from 2c0f:f248::/32; real_ip_header CF-Connecting-IP; EOF使用 Cloudflare 源服务器证书
使用 Cloudflare 源服务器证书,免于日常维护 SSL/TLS 证书。在 Cloudflare 后台创建 Origin CA,然后安装:
# 准备证书目录 sudo install \ -d \ -o root \ -g root \ -m 0700 \ /etc/nginx/tls # 安装证书公钥(替换实际域名和文件) sudo install \ -o root \ -g root \ -m 0644 \ ~/example.com-origin.pem \ /etc/nginx/tls/example.com-origin.pem # 安装证书私钥(替换实际域名和文件) sudo install \ -o root \ -g root \ -m 0600 \ ~/example.com-origin.key \ /etc/nginx/tls/example.com-origin.key后续虚拟主机配置直接引用即可:
ssl_certificate /etc/nginx/tls/example.com-origin.pem; ssl_certificate_key /etc/nginx/tls/example.com-origin.key;启用 Authenticated Origin Pulls (AOP)
用上了 Cloudflare Origin CA,笔者还建议启用 Authenticated Origin Pulls (AOP)。一般情况下,使用 Global AOP 证书即可。
sudo curl -fsSL \ https://developers.cloudflare.com/ssl/static/authenticated_origin_pull_ca.pem \ -o /etc/nginx/tls/cloudflare-origin-pull-ca.pem sudo chown root:root \ /etc/nginx/tls/cloudflare-origin-pull-ca.pem sudo chmod 0644 \ /etc/nginx/tls/cloudflare-origin-pull-ca.pem然后,在 Cloudflare 后台为域名开启 AOP,Nginx 虚拟主机增加一条配置:
ssl_verify_client on;建议先使用
optional验证,再切换为强制验证,详见 Cloudflare Docs。不使用 Cloudflare CDN 的情况
创建默认回退 (Fallback) 主机
cat << 'EOF' | sudo tee /etc/nginx/conf.d/00-default.conf > /dev/null server { listen 80 default_server; listen [::]:80 default_server; server_name _; return 444; } server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name _; ssl_reject_handshake on; } EOF启动 Nginx 服务
sudo nginx -t sudo systemctl enable --now nginx sudo systemctl reload nginx配置 nftables 流量防火墙
现在,我们应该摒弃过时的 iptables 和 UFW,拥抱原生高效的 nftables。针对三种典型的 Web 服务器使用场景:
使用且仅限 Cloudflare CDN 访问
开放且仅允许 Cloudflare CDN 的 IP 段回源访问 443/TCP,无需开放 80/TCP、80/UDP 或 443/UDP。
不使用 CDN 的公网 Nginx
开放 80/TCP 和 443/TCP。
不使用 CDN 的公网 Caddy
开放 80/TCP、443/TCP,Caddy 原生支持 HTTP/3 QUIC 还应当开放 443/UDP。
本文使用两个 nftables 配置表:
nftables.conf用于通用配置,web_server.nft用于 Web 服务器场景配置。我们约定:
- 默认表名
default_filter - 主机出站默认允许
- Docker 自行维护转发和 NAT,容器端口绑定
127.0.0.1
安装 nftables
从 Debian 10 开始,nftables 是默认安装的,但通常处于未启用状态。
sudo apt update \ && sudo apt install -y nftables && sudo systemctl status nftables当前的
inactive状态是预期行为。写入 nftables 主配置
注意替换 SSH 端口为实际端口:
cat << 'EOF' | sudo tee /etc/nftables.conf > /dev/null #!/usr/sbin/nft -f # 只重建本 SOP 管理的表。 destroy table inet default_filter # 修改为实际 SSH 端口。 define SSH_PORT = 822 table inet default_filter { # Web 访问策略。 include "/etc/nftables.d/web_server.nft" chain input { type filter hook input priority filter; policy drop; # 本机回环。 iifname "lo" accept # 丢弃无效连接,放行已建立连接及其关联流量。 ct state invalid drop ct state { established, related } accept # 兼容使用 DHCP / DHCPv6 获取地址的 VPS。 udp sport 67 udp dport 68 accept udp sport 547 udp dport 546 accept # ICMP、PMTU 和 IPv6 邻居发现。 meta l4proto icmp accept meta l4proto ipv6-icmp accept # 公网 SSH。 tcp dport $SSH_PORT accept # 当前选择的 Web 策略。 jump web_input } chain output { type filter hook output priority filter; policy accept; } } EOF配置 Web 访问场景表(三选一)
仅限 Cloudflare CDN HTTPS 回源
cat << 'EOF' | sudo tee /etc/nftables.d/web_server.nft > /dev/null set cloudflare_v4 { type ipv4_addr; flags interval; elements = { 173.245.48.0/20, 103.21.244.0/22, 103.22.200.0/22, 103.31.4.0/22, 141.101.64.0/18, 108.162.192.0/18, 190.93.240.0/20, 188.114.96.0/20, 197.234.240.0/22, 198.41.128.0/17, 162.158.0.0/15, 104.16.0.0/13, 104.24.0.0/14, 172.64.0.0/13, 131.0.72.0/22 }; } set cloudflare_v6 { type ipv6_addr; flags interval; elements = { 2400:cb00::/32, 2606:4700::/32, 2803:f800::/32, 2405:b500::/32, 2405:8100::/32, 2a06:98c0::/29, 2c0f:f248::/32 }; } chain web_input { ip saddr @cloudflare_v4 tcp dport 443 accept ip6 saddr @cloudflare_v6 tcp dport 443 accept } EOF不使用 CDN 的公网 Nginx
cat << 'EOF' | sudo tee /etc/nftables.d/web_server.nft > /dev/null chain web_input { tcp dport { 80, 443 } accept } EOF不使用 CDN 的公网 Caddy
cat << 'EOF' | sudo tee /etc/nftables.d/web_server.nft > /dev/null chain web_input { tcp dport { 80, 443 } accept udp dport 443 accept } EOF修正 Debian 默认行为
Debian 13 自带的
nftables.service在停止时默认执行:nft flush ruleset这会删除 Docker、Fail2ban 等服务动态插入的防火墙表。将其修改为仅清空我们的
default_filter表:sudo install \ -d \ -o root \ -g root \ -m 0755 \ /etc/systemd/system/nftables.service.d cat << 'EOF' | sudo tee \ /etc/systemd/system/nftables.service.d/override.conf \ > /dev/null [Service] ExecStop= ExecStop=/usr/sbin/nft destroy table inet default_filter EOF检查并应用配置
保持当前 SSH 会话,检查完整配置(含引用的 Web 策略表):
sudo nft -c -f /etc/nftables.conf确认无误,重载配置启动服务:
sudo systemctl daemon-reload sudo systemctl enable --now nftables新建 SSH 会话测试连接,若连接失败,请在原会话中自查端口配置。
安装配置 Fail2ban
安装 Fail2ban
sudo apt update \ && sudo apt install -y fail2ban确认当前实际的 SSH 端口:
sudo sshd -T | awk '$1 == "port" {print $2}'以下以端口
822为例,实际执行时,请替换为您的实际 SSH 端口。创建 SSH 监狱规则
sudo install -d -m 0755 /etc/fail2ban/jail.d cat <<'EOF' | sudo tee /etc/fail2ban/jail.d/sshd.local >/dev/null [sshd] enabled = true # 注意替换实际 SSH 端口 port = 822 backend = sys

给自己加个精


看完了,除了命令比较啰嗦以外,其他没啥大毛病,需要注意的是 Cloudflare 的 IP 不一定是一直固定的,最好可以写个脚本每天抓取并更新他最新的 IP 然后重启 nftables 和 nginx 服务
https://www.cloudflare.com/ips-v4/ https://www.cloudflare.com/ips-v6/给我也加个精

@Showfom #2 Cloudflare 好像好几年没更新 IP 段了,所以把重写的时候把自动更新 IP 段的脚本删掉了


@guest #3 您的积分已 - 10+1(狗头
)

zici,常看楼主的博客

说起来配置非特权用户这步,是不是考虑更进一步,限制普通用户能以 root 身份执行的命令
有请 @grok 来:1. 打个分 2. 锐评一下 3. 指出错误或值得改进的地方
@ping9timeout #8 1. 打分:8.6/10
作为「个人 SOP / 速查手册」已经很扎实,覆盖面、安全意识和现代工具选择都明显强于大多数中文 VPS 初始化教程。扣分主要来自啰嗦的命令、个别有争议的默认选择,以及硬编码维护点。
2. 锐评
这不是通用指南,楼主自己也说了。它更像一份「我自己下次还能抄、少踩坑」的作业程序,优点很明确:
- 先测再装、重装风险提示、非特权用户、SSH 公钥 + 禁密码、nftables 默认 drop、不自动重启、Cloudflare Origin CA + AOP、
ssl_reject_handshake、ZRAM、Cloud 内核、BBR,这些选择都站得住。 - 比还在教 UFW、改 22 端口、密码登录、iptables 的教程高一个档次。
- Debian 13 的
ssh.socket处理、nftables.service 停止时别flush ruleset以免干掉 Docker 表,这些细节说明作者真的踩过坑。
槽点也直白:命令又长又碎,heredoc +
tee满天飞,复制粘贴容易手滑;日常用户直接 NOPASSWD ALL,等于给被攻破的账号开了 root 通道(楼主自己也写了风险,但还是这么配了);Cloudflare IP 写死,作者说「好几年没更新所以删了脚本」,Showfom 的担心仍然成立——真更新的那天你会手忙脚乱。整体像一份完成度很高的私人笔记,而不是给别人无脑照抄的「标准答案」。3. 错误或值得改进的地方
- 免密 sudo:建议至少改成 visudo 限制命令(或单独 admin 用户 + 密码 sudo)。猫咪说得对,这一步可以更严。
- Cloudflare IP:即使很少变,也建议在配置里加注释指向官方列表(https://www.cloudflare.com/ips-v4/ 和 v6),或留一个简单拉取 + 校验脚本。硬编码 + Nginx realip 两处都要改,漏一处就尴尬。nftables 和 Nginx 两边同步是维护成本。
- Fail2ban 段被截断,且默认 jail 往往还是 iptables 动作。既然已经全面 nftables,应明确用 nftables action(或 `fi
- 先测再装、重装风险提示、非特权用户、SSH 公钥 + 禁密码、nftables 默认 drop、不自动重启、Cloudflare Origin CA + AOP、

@grok #9 你的输出超出字数限制而被截断,请继续说完。
@ping9timeout #10 #10 接着 #9 被截断的第 3 点说完。
Fail2ban:主贴本身就截在
backend = sys,完整 jail 没贴出来。Debian 13 默认 jail 仍可能走 iptables/nft 混用,既然全文已经拥抱 nftables,应写死例如:backend = systemd banaction = nftables-multiport chain = input并确认它打在独立表(常见是
inet f2b-*),不要写进default_filter。否则你每次nft -f /etc/nftables.conf或重启 nftables,封禁会丢。改完防火墙后应sudo fail2ban-client reload。主贴改nftables.service的ExecStop是对的,但 Fail2ban 与 nft 的配合要写清楚,否则「默认 drop + 动态封禁」会互相踩。Nginx AOP 配置不完整。只写
ssl_verify_client on;不够,必须同时指定:ssl_client_certificate /etc/nginx/tls/cloudflare-origin-pull-ca.pem; ssl_verify_client optional; # 先 optional,确认无误再 on缺
ssl_client_certificate时on会直接让握手失败。Origin CA 和 AOP 是两件事:前者证明源站身份给 Cloudflare,后者证明来访者是 Cloudflare。Cloudflare IP 硬编码有两处(nftables set +
set_real_ip_from),漏改一处会出现「防火墙已放行但 real_ip 仍是 CF 边缘」或反过来。即使很少改,配置里应注释官方源:https://www.cloudflare.com/ips-v4/、https://www.cloudflare.com/ips-v6/。Showfom 说的脚本不必天天跑,做「拉取 → 校验非空 / CIDR → 原子替换 → nft/nginx 重载」即可,失败则保留旧文件。好贴

