刚拿到一台空白的 Debian 12 服务器,多数人的第一反应是赶紧把业务装上去跑起来,我踩过足够多的坑之后才明白,真正耗时间的从来不是装软件,而是那些没做好、后面反复来烦你的基础配置。Debian 12(代号 bookworm)是目前非常稳的长期支持版本,它的默认策略比很多人想象中更克制:系统只装最基础的一组包,SSH 默认允许密码登录,防火墙默认不开,时间同步交给 systemd-timesyncd 简单打点。这套默认值放在家里的测试机上问题不大,一旦放到公网环境,基本等于把门虚掩着,谁都能顺手推一下。所以这篇就把我这些年反复打磨的一套 Debian 12 服务器初始化配置流程完整写出来,从账户、SSH、网络、时间、防火墙一直讲到磁盘、容器环境和备份脚本。它适合刚接触 Linux 运维的新手照着抄,也适合有经验的老手拿来当检查清单,看自己哪一步偷懒了。我尽量把每一步“为什么这么做”讲透,而不是丢一条命令让你自己猜。
1. 全新 Debian 12 到手,先建立一套可回退的基线
1.1 为什么初始化最忌讳“边装服务边调基础”
我见过太多新手上来就装 Nginx、装数据库,等跑了两天发现时区不对、日志时间全是 UTC,或者某个服务因为 hostname 没配对导致集群里互相找不到,再回头改的时候,数据已经写进去了,迁移成本比一开始就配好高出一个量级。初始化的本质不是装东西,而是把一台机器从“能开机”变成“状态可控、可复现、出问题能退回去”。所以我的原则永远是:先确立基线,再分层加固,最后才装业务运行时。基线的意思是——我知道这台机器的每个关键配置在哪、值是什么、为什么是这个值。任何一处说不清楚,就说明还没初始化完。
1.2 系统更新与软件源的确认
拿到机器第一步不是改配置,而是先把包索引和已有软件升到最新。Debian 12 默认的软件源通常指向官方镜像,国内机器上如果没换源,apt update会慢到让人怀疑人生。
apt update apt full-upgrade -y apt install -y sudo curl wget vim git htop net-toolsfull-upgrade和upgrade的区别值得说一句:upgrade不会因为依赖变化而删除包,full-upgrade会,全新机器上用它更彻底。至于换源,Debian 12 仍然以传统的/etc/apt/sources.list为主,但已经支持 deb822 新格式。传统写法长这样:
deb https://mirrors.example.org/debian bookworm main contrib non-free non-free-firmware deb https://mirrors.example.org/debian bookworm-updates main contrib non-free non-free-firmware deb https://mirrors.example.org/debian-security bookworm-security main contrib non-free non-free-firmware注意non-free-firmware这个组件是 Debian 12 才正式拆分出来的,很多驱动的固件包都在这里,老教程里没写,照着抄可能装不上网卡或显卡固件。换完源记得再跑一遍apt update,确认没有 GPG 报错再往下走。
提示:改源之前先备份
/etc/apt/sources.list,改坏了至少能cp回来,别问我怎么知道的。
1.3 用 sudo 而不是直接 root
Debian 12 安装时如果设置了 root 密码,默认不会创建普通用户;如果创建了普通用户,那这个用户通常已经在sudo组里。这里有个容易被忽略的变化:从 Debian 12 开始,安装器创建的首个用户默认加入sudo组,而早期版本是直接写进/etc/sudoers。两种方式结果类似,但用组管理更好维护。我个人的习惯是绝对不用 root 直接登录操作,root 只保留一条本地恢复通道,所有日常操作走带 sudo 的普通账户。原因很实际:误删文件时,root 删了就是删了,普通用户删除还有权限提示兜底;审计日志里也能看出是谁在操作。
2. 账户、密钥与 SSH 入口的第一轮收敛
2.1 建立专职管理员账户
如果系统里还没有合适的账户,先建一个。我一般用一个语义明确的名字,比如deploy或ops,而不是admin这种谁都想抢的名字。
adduser deploy usermod -aG sudo deployadduser是 Debian 上更友好的交互式脚本,会顺带创建家目录、设置密码。useradd不带参数的话连家目录都不建,新手最容易在这里栽跟头,建完用户 SSH 登进去发现没有家目录、没有 shell 配置,一脸茫然。
2.2 公钥登录与私钥的存放
密码登录在公网环境下几乎等于裸奔,扫描器一天能撞几万次。正确做法是本地生成密钥对,把公钥放到服务器上。
ssh-keygen -t ed25519 -C "deploy@web01"现在默认推荐 ed25519 而不是 RSA,密钥更短、安全性更好。生成后把公钥贴到服务器的~/.ssh/authorized_keys:
mkdir -p ~/.ssh && chmod 700 ~/.ssh vim ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys权限这步极其关键。SSH 对权限非常挑剔,authorized_keys或家目录权限过松,它会直接拒绝用这把钥匙登录,而且默认只给一句含糊的Permission denied (publickey),让你以为是密钥贴错了。这是我见过新手卡最久的坑之一。
注意:本地私钥文件
id_ed25519永远不要上传到服务器,也不要放进 git 仓库。服务器上只需要公钥。
2.3 sshd_config 逐项收紧
接下来编辑/etc/ssh/sshd_config。我贴一份我常用的关键项,并解释每一项在防什么:
| 配置项 | 建议值 | 作用 |
|---|---|---|
| PermitRootLogin | no | 禁止 root 直接 SSH 登录 |
| PasswordAuthentication | no | 关闭密码登录,只认密钥 |
| PubkeyAuthentication | yes | 开启公钥认证 |
| KbdInteractiveAuthentication | no | 关闭键盘交互式认证,防止绕过密码策略 |
| MaxAuthTries | 3 | 限制认证尝试次数 |
| LoginGraceTime | 30 | 缩短登录宽限期 |
| AllowUsers | deploy | 白名单,只允许指定用户登录 |
改完不是直接重启服务,而是先用sshd -t做语法检查:
sshd -t systemctl restart ssh这里有个常识但很致命的操作纪律:改 SSH 配置时,千万不要关掉当前这个连接,一定要新开一个终端窗口验证新配置能登录成功,确认无误后再关旧连接。否则配置写错、服务重启失败,你就把自己锁在门外了,只能去控制台救场。
3. 主机名、时区与时间同步这些地基配置
3.1 hostname 与 /etc/hosts 的配合
主机名看似无关紧要,但很多分布式组件、监控系统、日志系统都靠它做标识。设置很简单:
hostnamectl set-hostname web01但光设 hostname 不够,还要同步/etc/hosts。因为不少程序在解析自己的主机名时,会先查 hosts 文件,如果里面只有一条127.0.1.1 your-old-hostname,解析会变慢甚至报错。我通常这样改:
127.0.0.1 localhost 127.0.1.1 web01127.0.1.1这一行是 Debian 系的传统,指向本机主机名,保留它是为了兼容。有些服务启动慢、sudo提示卡顿,根源就是这里解析超时。
3.2 时区从 UTC 改到本地
云服务器默认时区常年是 UTC,这本身没错,甚至很多人主张服务器就该用 UTC。但如果你看日志、对业务时间点,UTC 会让人每次都心算加减,容易出错。我的折中是:生产服务器保持 UTC 便于统一,但日志展示层做转换;个人或小团队机器直接设成本地时区省心。
timedatectl set-timezone Asia/Shanghai timedatectl3.3 NTP 时间同步为什么不能省
时间不同步的后果,新手往往体会不深,直到有一天发现:HTTPS 证书校验失败、数据库主从复制报错、分布式日志时间戳乱序、TOTP 两步验证永远验证不过。这些几乎都和系统时钟漂移有关。Debian 12 默认用 systemd-timesyncd,轻量够用:
timedatectl set-ntp true timedatectl timesync-status如果对时间精度要求更高,比如要跑集群、做金融类业务,就换成 chrony,它能更平滑地校准时钟、支持更多上游源:
apt install -y chrony systemctl enable --now chrony chronyc sources -v chronyc trackingchronyc tracking里的System time那个值,正常应该接近 0,如果显示几秒甚至几分钟的偏移,说明同步根本没生效,优先检查 UDP 123 端口有没有被防火墙挡住。
4. 网络配置:从动态地址到固定地址
4.1 先看清楚网卡与当前状态
动手改网络前,必须先确认网卡名字。Debian 12 默认采用可预测网卡命名,名字可能是ens18、enp3s0这种,不再是老掉牙的eth0。
ip addr show ip route showip route里default via后面就是当前网关,这些信息改静态地址时都要用上。很多人改网络改到失联,就是因为把网关或子网掩码写错,一个字符之差就连不上了。
4.2 用 ifupdown 配置静态地址
Debian 12 传统安装默认用 ifupdown,配置文件是/etc/network/interfaces。典型静态配置:
auto ens18 iface ens18 inet static address 192.168.1.50/24 gateway 192.168.1.1 dns-nameservers 223.5.5.5 119.29.29.29改完执行:
ifdown ens18 && ifup ens18如果是云主机,很多平台用 cloud-init 或 systemd-networkd 管理网络,直接手改 interfaces 可能不生效,重启就被覆盖。这种情况要改/etc/systemd/network/下的.network文件,或修改 cloud-init 的网络配置。
4.3 DNS 与 resolv.conf 被覆盖的坑
新手最常见的困惑是:明明改了/etc/resolv.conf,重启后又变回去了。原因是这个文件现在常常是符号链接,实际由systemd-resolved或resolvconf管理,你直接改它当然无效。正确做法是去改/etc/systemd/resolved.conf里的DNS=项,然后:
systemctl restart systemd-resolved提示:
ls -l /etc/resolv.conf看一眼它是不是软链,能省你半小时的困惑。
5. 防火墙、内核参数与自动安全更新
5.1 nftables 与 ufw 怎么选
Debian 12 底层包过滤框架已经是 nftables,iptables 是兼容层。对新手,我推荐用ufw这个前端,规则直观;对要写复杂规则的老手,直接用 nftables 更灵活。
apt install -y ufw ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw enable ufw status verbose先放行 SSH 端口再启用,这个顺序非常重要。你要是先ufw enable再放行 22,那你当前连接立刻被切断,又是一次控制台之旅。云服务器还有一层安全组,两层要配合着开,别只开一层然后怀疑人生。
5.2 内核参数的加固基线
通过 sysctl 调整内核参数,能在网络层挡掉一大批常见扫描和攻击。我一般新建一个独立文件,不直接改/etc/sysctl.conf,方便管理和回退:
vim /etc/sysctl.d/99-hardening.confnet.ipv4.conf.all.rp_filter = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.conf.all.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.icmp_echo_ignore_broadcasts = 1 kernel.dmesg_restrict = 1rp_filter做反向路径校验,能防 IP 欺骗;tcp_syncookies缓解 SYN Flood;accept_redirects关闭 ICMP 重定向,防止路由被恶意篡改。改完执行sysctl --system生效。
5.3 自动安全更新
手动升级系统最容易忘记,安全补丁拖几个月不打的机器一抓一大把。unattended-upgrades 可以自动只打安全更新,既及时又不会把系统升乱:
apt install -y unattended-upgrades dpkg-reconfigure --priority=low unattended-upgrades它默认只处理安全源,这个策略我很认可——自动升级最怕把业务依赖的版本一起升上去,只打安全补丁是风险最低的折中。
6. 常用工具链与运行环境的准备
6.1 必备命令行工具
基础工具要不要装齐,取决于你后面怎么用。我列一组几乎每台机器都会用到的:
apt install -y curl wget git vim htop tmux jq unzip rsync其中tmux值得单独说。你 SSH 上去跑一个耗时半小时的编译或数据同步,网络一抖连接断开,进程跟着被 SIGHUP 杀掉,前面全白干。用 tmux 起一个会话,断线后重连还能接上,这是运维里保命的习惯。
6.2 Docker 与容器运行时
Debian 官方源里的 Docker 版本偏旧,我建议用官方仓库装:
install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc然后添加源、apt update、装docker-ce。装完把需要用的用户加入docker组:
usermod -aG docker deploy注意需要重新登录才生效。另外要清楚,加入 docker 组等于给了接近 root 的权限,因为它能挂载宿主机目录,这点在多人共用的服务器上要谨慎。
6.3 多版本运行时环境
如果机器上要跑 Python,Debian 12 自带 Python 3.11,但系统 Python 是给系统工具用的,你在上面pip install一堆包很容易把系统工具搞崩。稳妥做法是用 venv 隔离:
apt install -y python3-venv python3-pip python3 -m venv /opt/app/venv source /opt/app/venv/bin/activateNode 那边同理,优先用 nvm 或 NodeSource 管理多版本,不要和系统包管理器混着装,否则后面版本冲突能查到你崩溃。
7. 磁盘、Swap 与数据盘规划
7.1 先摸清磁盘与挂载现状
lsblk -f df -hlsblk -f能一眼看清每块盘的容量、分区、文件系统和挂载点。新手最容易忽略的是,云主机常挂一块数据盘,但默认没格式化也没挂载,你把数据写进去其实是写到了系统盘。所以初始化时确认每块盘的去向,比什么优化都重要。
7.2 按需创建 Swap 文件
Debian 12 安装时如果没划 swap 分区,或者容器里默认不给 swap,可以手动加一个 swap 文件。注意fallocate在某些文件系统上创建的文件可能不能直接用,遇到问题换dd:
fallocate -l 2G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo '/swapfile none swap sw 0 0' >> /etc/fstab顺手调一下 swappiness。默认值 60 对服务器偏高,容易频繁换出内存影响性能,我一般设成 10:
vm.swappiness = 107.3 数据盘格式化和持久挂载
新数据盘先分区或直接整盘用,格式化成 ext4 或 xfs:
mkfs.ext4 /dev/sdb1 mkdir -p /data持久挂载强烈建议用 UUID 而不是设备名,因为设备名在重启或加盘后可能变:
blkid /dev/sdb1 echo 'UUID=xxxx-xxxx /data ext4 defaults,noatime 0 2' >> /etc/fstab mount -anoatime能减少每次读文件的元数据写入,对高并发读的场景有实打实的提升。改完 fstab 一定要mount -a验证,写错了会导致系统起不来,那就麻烦了。
8. 登录防护、连接审计与故障定位
8.1 用 fail2ban 挡住暴力破解
即使关了密码登录,日志里依然会刷满来自全网的连接尝试。fail2ban 会监控日志,对反复失败的 IP 自动加临时封禁:
apt install -y fail2ban在/etc/fail2ban/jail.local里配一段针对 SSH 的策略,比如最大重试 5 次、封禁 1 小时。它本质上是给系统加了一层自动反应能力,效果比人工看日志好得多。
8.2 别到出事才想起看日志
初始化阶段就把日志习惯养起来,出问题时你会感谢自己:
journalctl -u ssh -n 50 --no-pager journalctl -p err -b last -a | headjournalctl -p err -b只列本次启动以来的错误级别日志,排查问题非常高效。last能看到最近的登录记录,如果出现你没见过的 IP 登录成功,那就是要紧事了,立刻改密钥、查进程。
8.3 长时间会话的保持
前面提了 tmux,这里补一个客户端侧的小技巧:在本地~/.ssh/config里加心跳,防止长时间无操作被中间设备掐断:
Host web01 HostName 192.168.1.50 User deploy ServerAliveInterval 60 ServerAliveCountMax 3这样每 60 秒发一次心跳,会话能稳定保持,配合 tmux 基本做到断线无感。
9. 快照、备份与把整套初始化脚本化
9.1 动手之前先留一条退路
云主机要充分利用快照功能,在动网络、动 fstab、动 SSH 之前先打一个快照。我年轻的时候改 fstab 挂载把系统改成起不来的状态,最后只能重装,代价是半天时间和一堆没备份的配置。有了快照,改坏了直接回滚,几分钟的事。这个习惯在我看来比任何优化技巧都值钱。
9.2 写一个可复用的 bootstrap 脚本
一次初始化做完,如果你以后还要开第二台、第三台,就不该再手敲一遍。把上面这些步骤整理成一个脚本,参数化的部分抽成变量,比如主机名、IP、时区。脚本里加上set -euo pipefail,任何一步失败立刻停,避免带着半成品状态继续跑下去。这个脚本本质上是你团队的知识沉淀,新人拿到它就能拉起一台合格的机器。
9.3 收尾的检查清单
初始化做完,我会对着清单过一遍:SSH 是否已禁密码登录且新连接验证通过;防火墙是否已启用且放行了必要端口;时间是否同步;防火墙和云安全组是否两层都开了;/etc/fstab是否mount -a无报错;自动安全更新是否生效;有没有做快照。这份清单看着啰嗦,但每一条背后都是我或者同行真实踩过的坑。我自己习惯把这份清单存成一台机器的 README,放在/root/或者仓库里,下次维护时直接照着核对。
最后分享一个我用了很多年的小习惯:每台机器初始化完,我会把关键配置文件(sshd_config、interfaces、fstab、sysctl 那几份)复制到一个统一目录,或者直接进 git。这样半年后你回来改东西,不用去猜当初设了什么值,一对比就知道。运维这行,能省下的从来不是敲命令的时间,而是回忆和排查的时间。