本指南涵盖从裸机 Debian 安装到生产就绪服务器的完整初始化流程,包括系统加固、Docker 部署、存储管理、网络配置和监控设置。适用于 Debian 11/12 (Bullseye/Bookworm) 服务器环境。
服务器基线配置(Baseline Configuration)是指在服务器投入生产环境前,必须完成的一套标准化初始化流程。它确保所有服务器:
| 版本 | 代号 | 状态 | 适用场景 |
|---|---|---|---|
| Debian 12 | Bookworm | 当前稳定版 | 新部署首选 |
| Debian 11 | Bullseye | 维护中 | 已有环境兼容 |
| Debian 13 | Trixie | 测试版 | 开发测试环境 |
建议:生产环境使用 Debian 12 (Bookworm),获得最新的安全更新和软件包支持。
┌─────────────────────────────────────────────────────────────┐
│ Debian 服务器初始化流程 │
├─────────────────────────────────────────────────────────────┤
│ 1. 系统更新 → 2. 时区/主机名 → 3. 创建管理员用户 │
│ 4. SSH 加固 → 5. 防火墙配置 → 6. 安装 Docker │
│ 7. 存储配置 → 8. 监控安装 → 9. 自动化配置 → 10. 基线验证 │
└─────────────────────────────────────────────────────────────┘
首次登录后,立即更新系统到最新状态:
# 更新软件包索引
sudo apt-get update
# 升级已安装软件包
sudo apt-get upgrade -y
# 全面系统升级(包括内核)
sudo apt-get dist-upgrade -y
# 清理旧内核和无用包
sudo apt-get autoremove -y
sudo apt-get autoclean
# 设置时区为上海(东八区)
sudo timedatectl set-timezone Asia/Shanghai
# 安装 NTP 同步服务
sudo apt-get install -y chrony
# 配置国内 NTP 源(阿里云)
sudo tee /etc/chrony/chrony.conf << 'EOF'
pool ntp.aliyun.com iburst
pool ntp1.aliyun.com iburst
makestep 1.0 3
rtcsync
logdir /var/log/chrony
EOF
# 重启 chrony 服务
sudo systemctl restart chronyd
sudo systemctl enable chronyd
# 验证时间同步
chronyc tracking
timedatectl status
# 设置主机名(替换为实际名称)
sudo hostnamectl set-hostname server-prod-01
# 配置 /etc/hosts
cat << 'EOF' | sudo tee /etc/hosts
127.0.0.1 localhost
127.0.1.1 server-prod-01
# 内网节点(根据实际环境配置)
# 192.168.1.10 server-prod-01
# 192.168.1.11 server-prod-02
EOF
# 安装常用系统工具
sudo apt-get install -y \
vim \
curl \
wget \
htop \
tree \
net-tools \
dnsutils \
iputils-ping \
telnet \
traceroute \
jq \
git \
unzip \
zip \
tar \
logrotate \
cron \
software-properties-common \
apt-transport-https \
ca-certificates \
gnupg \
lsb-release \
ncdu \
iotop
禁止使用 root 进行日常操作,创建专用管理员用户:
# 创建管理员用户(替换 yourname)
sudo useradd -m -s /bin/bash -G sudo admin
# 设置密码
sudo passwd admin
# 创建 SSH 目录
sudo mkdir -p /home/admin/.ssh
sudo chmod 700 /home/admin/.ssh
# 添加公钥(替换为实际公钥)
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... admin@company" | sudo tee /home/admin/.ssh/authorized_keys
sudo chmod 600 /home/admin/.ssh/authorized_keys
sudo chown -R admin:admin /home/admin/.ssh
# 为 admin 用户配置免密 sudo(仅用于自动化场景)
echo "admin ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/admin
sudo chmod 440 /etc/sudoers.d/admin
# 禁用 root 密码登录(保留 sudo 权限)
sudo passwd -l root
# 删除不必要的系统用户(根据环境评估)
# sudo userdel -r games
# sudo userdel -r irc
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo tee /etc/ssh/sshd_config << 'EOF'
# 基础配置
Port 22
ListenAddress 0.0.0.0
Protocol 2
# 认证配置
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
MaxAuthTries 3
MaxSessions 10
# 密钥配置
AuthorizedKeysFile .ssh/authorized_keys
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# 安全增强
X11Forwarding no
AllowTcpForwarding no
PermitTunnel no
GatewayPorts no
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 60
# 仅允许特定用户(推荐)
AllowUsers admin
# 日志
SyslogFacility AUTH
LogLevel INFO
# 子系统
Subsystem sftp /usr/lib/openssh/sftp-server
EOF
# 测试配置语法
sudo sshd -t
# 重启服务
sudo systemctl restart sshd
sudo systemctl enable sshd
# 验证状态
sudo systemctl status sshd
# 在本地机器生成密钥
ssh-keygen -t ed25519 -C "admin@company" -f ~/.ssh/id_ed25519_debian
# 复制公钥到服务器
ssh-copy-id -i ~/.ssh/id_ed25519_debian.pub admin@server-ip
# 安装 UFW(Uncomplicated Firewall)
sudo apt-get install -y ufw
# 默认策略:拒绝所有入站,允许所有出站
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 允许 SSH(必须先配置,否则会被锁在外面)
sudo ufw allow 22/tcp comment 'SSH'
# 允许常用服务(根据实际需求配置)
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
# 如果需要 Docker 端口映射,允许特定端口
# sudo ufw allow 8080/tcp comment 'App Port'
# 启用防火墙
sudo ufw enable
# 查看状态
sudo ufw status verbose
# 安装 fail2ban(防暴力破解)
sudo apt-get install -y fail2ban
# 创建本地配置
sudo tee /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
backend = systemd
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
EOF
# 启动服务
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban
# 查看状态
sudo fail2ban-client status sshd
# 添加 Docker 官方 GPG 密钥
sudo apt-get update
sudo apt-get 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
# 添加 Docker 软件源
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" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 验证安装
sudo systemctl status docker
docker --version
docker compose version
# 将 admin 用户加入 docker 组(免 sudo 运行 docker)
sudo usermod -aG docker admin
# 应用组变更(重新登录或执行)
newgrp docker
# 验证
id admin
docker ps
# 配置 Docker 守护进程
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json << 'EOF'
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"storage-driver": "overlay2",
"live-restore": true,
"userland-proxy": false,
"no-new-privileges": true,
"seccomp-profile": "/etc/docker/seccomp-default.json"
}
EOF
# 重启 Docker
sudo systemctl restart docker
# 验证配置
sudo docker info | grep -E "log-driver|storage|live-restore"
# 创建自定义桥接网络(用于容器间通信)
docker network create --driver bridge --subnet=172.20.0.0/16 --gateway=172.20.0.1 app-network
# 查看网络
docker network ls
# 查看所有磁盘
lsblk
# 查看磁盘详细信息
sudo fdisk -l
# 查看文件系统使用情况
df -h
# 查看目录占用空间
du -sh /var/*
场景:服务器新增一块数据盘 /dev/sdb,需要挂载到 /data
# 1. 确认新磁盘
lsblk
# 输出示例:
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# sda 8:0 0 50G 0 disk
# ├─sda1 8:1 0 49G 0 part /
# └─sda2 8:2 0 1G 0 part [SWAP]
# sdb 8:16 0 100G 0 disk <-- 新磁盘
# 2. 创建分区表(GPT)
sudo parted /dev/sdb mklabel gpt
# 3. 创建主分区(使用全部空间)
sudo parted -a optimal /dev/sdb mkpart primary ext4 0% 100%
# 4. 查看分区结果
lsblk
# 输出:sdb1 分区已创建
# 5. 创建 ext4 文件系统
sudo mkfs.ext4 -L data-disk /dev/sdb1
# 6. 创建挂载点
sudo mkdir -p /data
# 7. 手动挂载(临时)
sudo mount /dev/sdb1 /data
# 8. 配置开机自动挂载(/etc/fstab)
# 获取 UUID
sudo blkid /dev/sdb1
# 输出:/dev/sdb1: UUID="xxxxx" TYPE="ext4" LABEL="data-disk"
# 添加到 fstab(使用 UUID 更可靠)
echo 'UUID=xxxxx-xxx-xxx /data ext4 defaults,noatime,nodiratime 0 2' | sudo tee -a /etc/fstab
# 注意:替换为实际的 UUID
# 9. 验证 fstab 配置
sudo mount -a
sudo systemctl daemon-reload
# 10. 验证挂载
df -h /data
# 输出:/dev/sdb1 98G 61M 93G 1% /data
如果需要更灵活的存储管理,使用 LVM:
# 安装 LVM 工具
sudo apt-get install -y lvm2
# 创建物理卷
sudo pvcreate /dev/sdb
# 创建卷组
sudo vgcreate vg_data /dev/sdb
# 创建逻辑卷
sudo lvcreate -l 100%FREE -n lv_data vg_data
# 格式化
sudo mkfs.ext4 /dev/vg_data/lv_data
# 挂载
sudo mkdir -p /data
sudo mount /dev/vg_data/lv_data /data
# 配置 fstab
echo '/dev/vg_data/lv_data /data ext4 defaults 0 2' | sudo tee -a /etc/fstab
# 创建命名卷
docker volume create app-data
docker volume create app-logs
# 查看卷
docker volume ls
# 查看卷详情
docker volume inspect app-data
# 使用卷的 compose 示例
# docker-compose.yml
# volumes:
# app-data:
# driver: local
# app-logs:
# driver: local
#
# services:
# app:
# volumes:
# - app-data:/app/data
# - app-logs:/app/logs
# 下载 Node Exporter
NODE_EXPORTER_VERSION="1.7.0"
wget https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
# 解压安装
tar xvfz node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
sudo cp node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter /usr/local/bin/
# 创建 systemd 服务
sudo tee /etc/systemd/system/node_exporter.service << 'EOF'
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter \
--collector.systemd \
--collector.processes \
--collector.tcpstat
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# 创建用户
sudo useradd --no-create-home --shell /bin/false node_exporter
# 启动服务
sudo systemctl daemon-reload
sudo systemctl start node_exporter
sudo systemctl enable node_exporter
# 验证
sudo systemctl status node_exporter
curl http://localhost:9100/metrics
# 系统日志默认使用 journald,配置持久化
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
# 配置 journald
sudo tee /etc/systemd/journald.conf << 'EOF'
[Journal]
Storage=persistent
SystemMaxUse=500M
SystemMaxFileSize=100M
MaxRetentionSec=1week
EOF
sudo systemctl restart systemd-journald
# 创建应用日志轮转配置
sudo tee /etc/logrotate.d/applications << 'EOF'
/var/log/apps/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0644 admin admin
dateext
dateformat -%Y%m%d-%s
sharedscripts
postrotate
/bin/kill -HUP $(cat /var/run/syslogd.pid 2> /dev/null) 2> /dev/null || true
endscript
}
EOF
# 测试配置
sudo logrotate -d /etc/logrotate.d/applications
# 安装 unattended-upgrades
sudo apt-get install -y unattended-upgrades apt-listchanges
# 配置自动更新
sudo tee /etc/apt/apt.conf.d/50unattended-upgrades << 'EOF'
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::InstallOnShutdown "false";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Mail "";
Unattended-Upgrade::MailReport "on-change";
EOF
# 启用自动更新
sudo tee /etc/apt/apt.conf.d/20auto-upgrades << 'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
EOF
# 测试配置
sudo unattended-upgrades --dry-run --debug
# 创建清理脚本
sudo tee /usr/local/bin/system-cleanup.sh << 'EOF'
#!/bin/bash
# 系统清理脚本
# 清理旧内核
sudo apt-get autoremove -y
# 清理包缓存
sudo apt-get autoclean
# 清理 journal 日志(保留最近一周)
sudo journalctl --vacuum-time=1week
# 清理临时文件
sudo find /tmp -type f -atime +7 -delete
sudo find /var/tmp -type f -atime +7 -delete
# 清理 Docker 未使用资源
docker system prune -f --volumes
# 发送通知(可选)
echo "$(date): System cleanup completed" >> /var/log/system-cleanup.log
EOF
sudo chmod +x /usr/local/bin/system-cleanup.sh
# 添加到 crontab(每周日凌晨 3 点执行)
echo '0 3 * * 0 root /usr/local/bin/system-cleanup.sh' | sudo tee /etc/cron.d/system-cleanup
# 创建备份目录
sudo mkdir -p /backup/{scripts,configs,data}
# 配置备份脚本
sudo tee /usr/local/bin/backup-configs.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/backup/configs/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
# 备份关键配置文件
cp /etc/ssh/sshd_config "$BACKUP_DIR/"
cp /etc/hosts "$BACKUP_DIR/"
cp /etc/fstab "$BACKUP_DIR/"
cp /etc/docker/daemon.json "$BACKUP_DIR/"
cp -r /etc/nginx "$BACKUP_DIR/" 2>/dev/null || true
# 备份用户列表
cut -d: -f1 /etc/passwd > "$BACKUP_DIR/users.txt"
# 打包
tar czf "$BACKUP_DIR.tar.gz" -C "$BACKUP_DIR" .
rm -rf "$BACKUP_DIR"
# 保留最近 30 天的备份
find /backup/configs -name "*.tar.gz" -mtime +30 -delete
echo "$(date): Config backup completed: $BACKUP_DIR.tar.gz"
EOF
sudo chmod +x /usr/local/bin/backup-configs.sh
# 每天凌晨 2 点执行备份
echo '0 2 * * * root /usr/local/bin/backup-configs.sh' | sudo tee /etc/cron.d/backup-configs
| 检查项 | 命令 | 预期结果 |
|---|---|---|
| Root 登录已禁用 | grep PermitRootLogin /etc/ssh/sshd_config |
PermitRootLogin no |
| 密码认证已禁用 | grep PasswordAuthentication /etc/ssh/sshd_config |
PasswordAuthentication no |
| 仅允许特定用户 | grep AllowUsers /etc/ssh/sshd_config |
AllowUsers admin |
| 防火墙已启用 | sudo ufw status |
Status: active |
| fail2ban 运行中 | sudo systemctl status fail2ban |
active (running) |
| 自动更新已配置 | grep Unattended-Upgrade /etc/apt/apt.conf.d/20auto-upgrades |
Unattended-Upgrade "1" |
| Docker 非 root 运行 | id admin |
包含 docker 组 |
| 时间同步正常 | chronyc tracking |
Leap status : Normal |
| 检查项 | 命令 | 预期结果 |
|---|---|---|
| 系统已更新 | sudo apt list --upgradable |
无可用更新 |
| 时区正确 | timedatectl status |
Time zone: Asia/Shanghai |
| 主机名正确 | hostnamectl status |
显示预期主机名 |
| 磁盘挂载正常 | df -h |
所有分区正常挂载 |
| Docker 运行中 | sudo systemctl status docker |
active (running) |
| Node Exporter 运行 | curl -s localhost:9100/metrics |
返回指标数据 |
| 日志轮转配置 | sudo logrotate -d /etc/logrotate.d/applications |
无错误 |
| 备份脚本可执行 | sudo /usr/local/bin/backup-configs.sh |
成功执行 |
#!/bin/bash
# Debian 基线验证脚本
echo "=== Debian Baseline Check ==="
echo "Date: $(date)"
echo "Hostname: $(hostname)"
echo ""
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
check_pass() {
echo -e "${GREEN}[PASS]${NC} $1"
}
check_fail() {
echo -e "${RED}[FAIL]${NC} $1"
}
# 1. SSH 配置
if grep -q "PermitRootLogin no" /etc/ssh/sshd_config; then
check_pass "Root login disabled"
else
check_fail "Root login NOT disabled"
fi
if grep -q "PasswordAuthentication no" /etc/ssh/sshd_config; then
check_pass "Password auth disabled"
else
check_fail "Password auth NOT disabled"
fi
# 2. 防火墙
if sudo ufw status | grep -q "Status: active"; then
check_pass "UFW firewall active"
else
check_fail "UFW firewall NOT active"
fi
# 3. fail2ban
if sudo systemctl is-active fail2ban >/dev/null 2>&1; then
check_pass "fail2ban running"
else
check_fail "fail2ban NOT running"
fi
# 4. Docker
if sudo systemctl is-active docker >/dev/null 2>&1; then
check_pass "Docker running"
else
check_fail "Docker NOT running"
fi
# 5. 时间同步
if chronyc tracking | grep -q "Leap status.*Normal"; then
check_pass "Time sync normal"
else
check_fail "Time sync issue"
fi
# 6. 磁盘空间
DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -lt 80 ]; then
check_pass "Disk usage: ${DISK_USAGE}%"
else
check_fail "Disk usage critical: ${DISK_USAGE}%"
fi
# 7. 内存
MEM_AVAILABLE=$(free | grep Mem | awk '{print $7}')
MEM_TOTAL=$(free | grep Mem | awk '{print $2}')
MEM_PCT=$((MEM_AVAILABLE * 100 / MEM_TOTAL))
if [ "$MEM_PCT" -gt 20 ]; then
check_pass "Memory available: ${MEM_PCT}%"
else
check_fail "Memory low: ${MEM_PCT}%"
fi
# 8. 负载
LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
CPU_CORES=$(nproc)
LOAD_LIMIT=$(echo "$CPU_CORES * 0.8" | bc -l)
if (( $(echo "$LOAD < $LOAD_LIMIT" | bc -l) )); then
check_pass "Load average: $LOAD"
else
check_fail "Load high: $LOAD"
fi
echo ""
echo "=== Check Complete ==="
# 系统信息
uname -a # 内核版本
cat /etc/os-release # OS 版本
lsb_release -a # Debian 版本
# 资源监控
top / htop # 进程监控
free -h # 内存使用
df -h # 磁盘使用
iotop # IO 监控
# 网络
ss -tlnp # 监听端口
ip addr # 网络接口
iptables -L -n -v # 防火墙规则
# Docker
docker ps # 运行容器
docker stats # 容器资源
docker system df # Docker 磁盘使用
docker logs <container> # 容器日志
# 日志
journalctl -xe # 系统日志
journalctl -u docker # Docker 日志
journalctl --since "1 hour ago" # 最近1小时日志
| 问题 | 排查命令 | 解决方案 |
|---|---|---|
| SSH 无法连接 | sudo systemctl status sshd |
检查防火墙、SSH 配置 |
| Docker 无法启动 | sudo journalctl -u docker |
检查 daemon.json 语法 |
| 磁盘空间不足 | du -sh /var/log/* |
清理日志、扩容磁盘 |
| 内存不足 | ps aux --sort=-%mem |
重启服务、增加 SWAP |
| 时间不同步 | chronyc sources |
重启 chronyd、检查 NTP 源 |
维护记录
- 创建日期:基于原 "Debian Baseline" 笔记扩展
- 原内容核心:Docker 安装步骤、磁盘挂载命令
- 扩展内容:系统初始化全流程、安全加固、监控配置、自动化维护、检查清单
- 适用版本:Debian 11/12