在配置系统文件的时候,我写下了这句话,因为这个坑让我排查了若干小时: 所有的全局配置,必须写在文件的前半部分。所有的Match规则,必须、必须、必须扔到配置文件的绝对最末尾!
概要
本文记录我初始化 Linux 服务器的标准作业程序(SOP),这并非通用指南,仅作为个人快速部署环境的速查手册。
重装操作系统
重装有风险,本文不为任何脚本的安全性背书,请自行衡量并承担后果。如果条件允许,请尽可能使用自定义 ISO 镜像手动安装。
使用一键 DD 脚本
对于不支持自定义 ISO 镜像的服务商,使用一键 DD 脚本比较方便。开始前,务必花费几分钟读下作者的说明文档,这远比盲目粘贴命令重要。
bin456789/reinstall支持重装的系统类型更多
bohanwood/debi专注于纯净、精简的 Debian 系统环境
以 Oracle ARM 机器安装 Debian 为例,使用debi脚本的操作流程如下:
下载脚本
curl-fLOhttps://raw.githubusercontent.com/bohanyang/debi/master/debi.sh&&chmod+x debi.sh重装配置
sudo./debi.sh\--version13\--architecturearm64\--cloudflare\--userviamoe\--authorized-keys-url https://github.com/githubUserName.keys\--ssh-port22122参数说明:
--version 13指定 Debian 13(代号Trixie)--architecture arm64指定系统架构,这里的arm64匹配 ARM 架构机器--cloudflare预设 Cloudflare 作为默认 DNS--user viamoe创建具有 sudo 权限的普通用户viamoe--authorized-keys-url https://github.com/githubUserName.keys导入 SSH 公钥,实现无密码登录--ssh-port 22122更改默认 SSH 端口,规避低级暴力扫描
开始重装
重启后,机器将自动联网重装系统
sudoreboot期间可通过 VNC 观察安装进度,一般几分钟后新系统即可就绪。
使用自定义 ISO 镜像
若服务商支持上传自定义 ISO 镜像手动安装,这是最为推荐的方式,能让我们从源头掌控系统环境的纯净度。针对 Netcup 服务器的具体操作可参考:Netcup 服务器安装自定义 ISO 镜像。
完成重装后,使用预设的用户凭据登录,开始后续配置。
配置用户
赋予普通用户sudo权限,方便后续使用和管理。
# 切换到 root 用户su# sudo 免密码# 替换 dejavu 为实际用户名echo"dejavu ALL=(ALL) NOPASSWD:ALL">/etc/sudoers.d/dejavu# 设置权限chmod440/etc/sudoers.d/dejavuSSH 安全加固
配置公钥登录
# 退出 root 用户exit# 创建公钥目录mkdir-p~/.ssh# 粘贴 SSH 公钥vim~/.ssh/authorized_keys# 或者上传 SSH 公钥# ssh -i /path/to/your/ed25519_key username@<IP> -p <port>chmod700~/.sshchmod600~/.ssh/authorized_keys优化 SSH 配置
sudovim/etc/ssh/sshd_config重点修改以下配置:
# 修改默认 SSH 端口Port22122# 登录宽限时间# 超过 1 分钟不输入密码/密钥自动断开LoginGraceTime 1m# 禁止 root 用户直接登录PermitRootLogin no# 严格模式,检查主目录权限StrictModesyes# 开启 SSH 公钥登录方式PubkeyAuthenticationyes# 禁止传统密码登录方式PasswordAuthentication no# 禁止空密码登录PermitEmptyPasswords no# 禁用键盘交互式认证(防止通过 PAM 绕过密码限制)KbdInteractiveAuthentication no# Debian 默认需要 yes,否则可能会影响部分会话功能。UsePAMyes# 关闭 X11 转发X11Forwarding no# 保持 SSH 会话连接# 服务器每 60 秒发一次心跳包ClientAliveInterval60# 如果客户端 5 次没回应才断开ClientAliveCountMax5# 禁止 DNS 反向解析UseDNS no保持当前终端会话,新开一个 SSH 连接,确认正常,否则回到保持的 SSH 会话中检查配置。
# 检查 SSH 配置sudosshd-t# 使新的 SSH 配置生效sudosystemctl restart sshdIPv6 静态路由
Netcup 服务器提供/64的 IPv6,建议设置静态路由
sudovim/etc/network/interfaces添加
iface ens3 inet6 static address<静态 IPv6 地址>netmask64# Netcup network gatewaygateway fe80::1# 接受路由公告accept_ra2然后执行
sudoipaddr flush dev ens3更换 Linux 内核
推荐使用针对虚拟化优化、更加轻量和高效的 Cloud 内核。
sudoaptinstall-ylinux-image-cloud-amd64重启加载新内核
sudorebootuname-r# 输出6.12.63+deb13-cloud-amd64清理旧内核
# 列出已安装的内核包sudodpkg--list|greplinux-image# 输出示例ii linux-image-6.12.63+deb13-amd646.12.63-1 amd64 Linux6.12for64-bit PCs(signed)ii linux-image-6.12.63+deb13-cloud-amd646.12.63-1 amd64 Linux6.12forx86-64 cloud(signed)ii linux-image-amd646.12.63-1 amd64 Linuxfor64-bit PCs(meta-package)ii linux-image-cloud-amd646.12.63-1 amd64 Linuxforx86-64 cloud(meta-package)# 移除常规内核元包及具体版本(请根据实际输出的版本号替换)sudoaptpurge-ylinux-image-amd64 linux-image-6.12.63+deb13-amd64# 更新引导sudoupdate-grub# 运行清理sudoaptautoremove--purge-y安装常用软件包
按需安装基础软件包及常用应用程序。
基本工具包
sudoaptupdate&&aptupgradesudoaptinstall\apt-transport-https\build-essential\git\curl\wget\unzip\tmux\btop\bind9-dnsutils\tree\vim安装 Docker
参考 Docker 官方文档 说明的步骤,下列命令不保证时效性
# 添加 Docker 官方的 GPG 密钥sudoapt-getupdatesudoapt-getinstallca-certificatescurlsudoinstall-m0755-d/etc/apt/keyringssudocurl-fsSLhttps://download.docker.com/linux/debian/gpg-o/etc/apt/keyrings/docker.ascsudochmoda+r /etc/apt/keyrings/docker.asc# 添加软件源echo\"deb [arch=$(dpkg --print-architecture)signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \$(./etc/os-release&&echo"$VERSION_CODENAME")stable"|\sudotee/etc/apt/sources.list.d/docker.list>/dev/nullsudoapt-getupdatesudoapt-getinstalldocker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginsudosystemctl statusdocker补充资料:给 Docker 启用 IPv6 支持
安装 Nginx
同样地,参考 Nginx 项目文档——在 Debian 上的 安装步骤
sudoaptinstallcurlgnupg2 ca-certificates lsb-release debian-archive-keyring# 导入 GPG 密钥curlhttps://nginx.org/keys/nginx_signing.key|gpg--dearmor\|sudotee/usr/share/keyrings/nginx-archive-keyring.gpg>/dev/null# 验证 GPG 密钥mkdir-m700~/.gnupg gpg --dry-run--quiet--no-keyring--import--import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpgecho"deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ http://nginx.org/packages/debian`lsb_release-cs`nginx"\|sudotee/etc/apt/sources.list.d/nginx.list# 设置仓库锁定,优先使用 Nginx 官方提供的软件包echo-e"Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n"\|sudotee/etc/apt/preferences.d/99nginx# 安装 Nginxsudoaptupdate&&sudoaptinstallnginx# 启动 Nginxsudosystemctl start nginx使用自签 SSL/TLS 证书,设置 Nginx 默认回退 (Fallback) 虚拟主机。
# 准备目录sudomkdir-p/etc/nginx/certsudochmod700/etc/nginx/cert# 生成证书sudoopenssl req-x509-new-nodes-newkeyrsa:2048\-sha256\-days3650\-keyout/etc/nginx/cert/deny.key\-out/etc/nginx/cert/deny.pem\-subj"/C=XX/ST=Denied/L=Denied/O=Denied/CN=invalid.local"\-addext"subjectAltName=DNS:invalid.local"# 设置权限sudochmod600/etc/nginx/cert/deny.keysudochmod644/etc/nginx/cert/deny.pem新建虚拟主机配置文件
sudovim/etc/nginx/conf.d/00-default.conf内容如下:
server{listen80default_server;listen[::]:80 default_server;server_name _;return444;}server{listen443ssl default_server;listen[::]:443 ssl default_server;server_name _;ssl_certificate /etc/nginx/cert/deny.pem;ssl_certificate_key /etc/nginx/cert/deny.key;ssl_protocols TLSv1.2 TLSv1.3;ssl_prefer_server_ciphers off;error_page497=444/dev/null;return444;}重载 Nginx 配置
sudonginx-tsudonginx-sreload设置 ZRAM 和 Swap
合理配置 ZRAM 和 Swap,平衡硬盘 I/O 性能和 CPU 开销。
配置 ZRAM
ZRAM 通过在 RAM 中划分一块区域压缩,速度远快于硬盘上的 Swap 空间。
# 安装 zram-tools 管理工具sudoaptupdate&&sudoaptinstall-yzram-tools编辑 ZRAM 配置
sudovim/etc/default/zramswap参数说明:
# 选择 zstd 算法,最佳平衡压缩比和速度ALGO=zstd# 分配 ZRAM 比例# 1GB RAM 建议 100%# 2~4GB RAM 建议 60%# 8GB RAM 以上建议 25%PERCENT=70# 优先级 100,确保系统优先使用 ZRAMPRIORITY=100配置 Swap
Swapfile 比 Swap 分区更为灵活
# 创建 2GB 的 Swapfile# 1024 * 2 = 2048sudoddif=/dev/zeroof=/swapfilebs=1Mcount=2048status=progress# 设置权限sudochmod600/swapfile# 格式化sudomkswap/swapfile# Swap 启用优先级低于 ZRAMsudoswapon--priority-2/swapfile# 启动时自动挂载echo'/swapfile none swap sw,pri=-2 0 0'|sudotee-a/etc/fstab# 检查挂载sudomount-a系统内核调整
根据物理 RAM 大小,调整设置系统使用 Swap 的「积极性」。
# 1GB RAM(激进)echo"vm.swappiness=100"|sudotee-a/etc/sysctl.conf# 2GB/4GB RAM(积极)echo"vm.swappiness=60"|sudotee-a/etc/sysctl.conf# 8GB RAM 以上(保守)echo"vm.swappiness=10"|sudotee-a/etc/sysctl.conf对于 2GB RAM 以下的机器,应当更倾向于释放文件缓存:
echo"vm.vfs_cache_pressure=50"|sudotee-a/etc/sysctl.conf应用配置
sudosysctl-p验证状态
sudoswapon--showsudozramctlSSD Trim 优化
如果 VPS/VDS 使用的是 NVMe SSD,建议启用 Trim 自动优化。
# 定时任务sudosystemctlenable--nowfstrim.timer并非所有服务商提供的 VPS/VDS 都支持 Trim,可以验证下:
# DISC-MAX 列不为 0lsblk-DNAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO sr000B 0B0zram004K 2T0vda0512B 2G0├─vda10512B 2G0└─vda20512B 2G0# 尝试手动触发sudofstrim-v/ /:434.4GiB(466435428352bytes)trimmedNTP 时区同步
设置 UTC 时区
无论服务器位于何处,我都习惯将时区统一设置为 UTC(世界协调时),避免跨时区运维时产生的日志混乱和时间差纠纷,是一个非常省心的「隐性福利」。
sudotimedatectl set-timezone UTC使用 Chrony 同步时间
与默认的 systemd-timesyncd 比,Chrony 的精度和性能更佳。
# 安装 Chrony 客户端sudoaptupdatesudoaptinstallchrony添加 NTP 服务器
sudovim/etc/chrony/chrony.conf注释默认的pool及server行,添加 Cloudflare NTP 节点:
server time.cloudflare.com iburst server time.cloudflare.com iburst server time.cloudflare.com iburst server time.cloudflare.com iburst启动 Chrony 服务
sudosystemctl mask systemd-timesyncd.servicesudosystemctlenable--nowchrony验证同步状态
chronyc sources-v配置 nftables 防火墙
nftables 是 Linux 内核现代化的包过滤框架。在 Debian 13 中,我们应该摒弃过时的 iptables 和 UFW,直接拥抱原生且高效的 nftables。
检查环境
从 Debian 10 开始,nftables 是默认安装的,但通常处于未启用状态,检查:
# 确保 nftables 已安装sudoaptupdate&&sudoaptinstallnftables-y# 默认 inactive 状态是正常的sudosystemctl status nftables若此前安装过 UFW,建议卸载以免冲突
sudoufw disable&&sudoaptpurge ufw-y理解配置
在编写规则前,只需掌握三个层级:
表(Table):规则的顶级容器
链(Chain):绑定在网络钩子(INPUT/FORWARD/OUTPUT)上的规则集,定义默认策略(Drop 或 Accept)
规则(Rule):具体的匹配条件与行动
开始使用
以下配置是典型的「安全」服务器方案:仅允许 Cloudflare CDN 回源访问 80/443 端口,除 SSH 端口外全部切断。
# 编辑配置文件sudovim/etc/nftables.conf语法很简单,可以看注释
#!/usr/sbin/nft -f# 刷新规则flush ruleset table inet filter{# ============================================================# IP 集合 (Sets)# ============================================================setcloudflare_v4{typeipv4_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}}setcloudflare_v6{typeipv6_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}}# ============================================================# INPUT 链 (入站)# ============================================================chain input{# 规则外流量拒绝typefilter hook input priority filter;policy drop;# 放行已建立连接ct state established, related accept# 丢弃无效包ct state invalid drop# 允许回环接口iif"lo"accept# 允许 IPv6 NDPip6 nexthdr icmpv6 icmpv6type{nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert}accept# 允许 ICMP (速率限速)ipprotocol icmp limit rate4/second accept ip6 nexthdr icmpv6 icmpv6typeecho-request limit rate4/second accept# 允许 SSH 端口tcp dport22122accept# 仅限 Cloudflare IP 段访问 80/443ipsaddr @cloudflare_v4 tcp dport{80,443}accept ip6 saddr @cloudflare_v6 tcp dport{80,443}accept}# ============================================================# FORWARD 链 (转发)# ============================================================chain forward{# 规则外流量拒绝typefilter hook forward priority filter;policy drop;# 放行已建立连接ct state established, related accept# 丢弃无效包ct state invalid drop# 允许 Docker 出站 (覆盖默认网桥和自定义网桥)iifname"docker0"accept iifname"br-*"accept# 允许 Docker 容器间通信iifname"docker0"oifname"docker0"accept iifname"br-*"oifname"br-*"accept}# ============================================================# OUTPUT 链 (出站)# ============================================================chain output{# 默认允许所有出站typefilter hook output priority filter;policy accept;}}应用规则
# 检查语法sudonft-c-f/etc/nftables.conf# 启动服务sudosystemctlenable--nownftables# Docker 重启后会自动注入规则sudosystemctl restart nftables&&sudosystemctl restartdocker# 测试 Docker 出站sudodockerrun--rmbusyboxping-c4dejavu.moe安装配置 Fail2ban
# 安装 Fail2bansudoaptupdate&&sudoaptinstallfail2ban# 创建一个最小的 SSH 服务保护配置sudovim/etc/fail2ban/jail.local配置内容如下:
[DEFAULT]# 本机地址自动忽略,防止误封自己ignoreip=127.0.0.1/8 ::1# 封禁 1 天bantime=1d# 在 10 分钟内累计失败即触发findtime=10m# 触发封禁的失败次数阈值maxretry=3# 自动 nftables 规则插入banaction=nftables-multiport banaction_allports=nftables-allports[sshd]# 启用 SSH 保护enabled=true# SSH 服务的监听端口(务必正确匹配)port=22122# 使用 systemd 日志后端backend=systemd# 严格地匹配失败日志mode=aggressive启动 Fail2ban 服务
sudosystemctlenable--nowfail2bansudosystemctl restart nftables&&sudosystemctl restart fail2ban测试一下封禁
# 封禁一个「黑户」sudofail2ban-clientsetsshd banip2400:6180:0:d2:0:2:9699:d000# 检查 nftables 规则中是否存在 f2b 动态表sudonft list ruleset|grepf2b检查 Fail2ban 配置
# 巡查「监狱」sudofail2ban-client status# 查封禁 IPsudofail2ban-client status sshd至此,一台纯净、安全的服务器已经准备就绪。Happy Hosting!
另请参阅:
Cloudflare WAF 防护策略简易指南
服务器使用 Cloudflare CDN 的最佳实践
原文地址:个人初始化 Linux 服务器的 SOP
本文持续更新,最新内容及相关资料请访问原文。