一个生产就绪、符合 POSIX 标准的 Shell 脚本,用于 Linux 服务器的一键初始化与 SSH 安全加固。
该脚本可自动完成 SSH 密钥配置、修改端口、创建用户、开启 BBR 以及 系统更新,并完美兼容 Debian, Ubuntu, CentOS, RHEL 以及 Alpine Linux。
- 全平台兼容: 完美支持 Debian, Ubuntu, CentOS/RHEL, Alma/Rocky, 以及 Alpine Linux。
- POSIX 标准: 纯
/bin/sh编写,无需安装bash。在dash(Debian) 和ash(Alpine/Busybox) 上稳定运行。 - 安全架构 (Fortress Pro):
- 托管配置块: 使用
# BEGIN SERVER-INIT MANAGED BLOCK头部插入配置,确保优先级最高,不受Include指令干扰。 - 自动回滚 (Auto-Rollback): 运行时若发生 SSHD 校验失败、端口未监听或连接测试失败,自动还原系统状态。
- 进程防杀 (Anti-Kill): 为 SSHD 服务添加 systemd
override.conf,防止 OOM 误杀并配置自动重启。 - 防失联死锁检测: 智能检测认证方式,防止出现“既禁用密码又未配好密钥”的死锁。
- 托管配置块: 使用
- 自动化友好:
- 支持 无头模式 (Headless),通过命令行参数实现零交互无人值守安装。
- 审计与报告: 自动生成详细的操作审计日志与系统健康检查报告。
请以 root 身份运行。
curl -fsSL https://raw.githubusercontent.com/247like/linux-ssh-init-sh/main/init.sh -o init.sh && chmod +x init.sh && ./init.sh🛡️ 审计建议:脚本会修改 SSH 配置,建议先下载到本地、查看内容、再执行 (上面这条命令就是 "先下载、再执行" 的写法,请勿改为
curl ... | sh)。
./init.sh --lang=en适用于 CI/CD 或批量装机场景。使用命令行参数传递配置,配合 --yes 跳过确认。
(配置 Root 用户、随机端口、从 GitHub 拉取公钥、开启 BBR、更新系统、自动确认)
curl -fsSL https://raw.githubusercontent.com/247like/linux-ssh-init-sh/main/init.sh | sh -s -- \
--user=root \
--port=random \
--key-gh=247like \
--bbr \
--update \
--strict \
--yes(指定公钥来源,其他选项手动选择)
./init.sh --key-url=https://my-server.com/id_ed25519.pub脚本支持丰富的命令行参数来控制行为:
| 参数类别 | 参数 | 说明 |
|---|---|---|
| 基础控制 | --lang=en |
强制使用英文界面 |
--yes |
自动确认:跳过脚本最后的 "确认执行?" 询问 | |
--strict |
严格模式:遇到任何错误立即退出 (详见下方) | |
--delay-restart |
延迟重启:修改配置但不重启 SSH 服务 (适用于特殊环境) | |
--no-ip-probe |
跳过外网 IP 探测 (api.ipify.org),适用于离线/隔离环境 |
|
-V / --version |
打印版本并退出 | |
-h / --help |
显示完整帮助 | |
| 用户与端口 | --user=root |
指定登录用户 (root 或普通用户名) |
--port=22 |
保持默认 22 端口 | |
--port=random |
生成随机高位端口 (49152-65535) | |
--port=2222 |
指定具体端口号 | |
| 密钥来源 | --key-gh=username |
从 GitHub 用户拉取公钥 |
--key-url=url |
从指定 URL 下载公钥 | |
--key-raw="ssh-..." |
直接传递公钥内容字符串 | |
| 系统选项 | --update |
开启系统软件包更新 |
--no-update |
跳过系统更新 | |
--bbr |
开启 TCP BBR 拥塞控制 | |
--no-bbr |
不开启 BBR |
| 场景 | 普通模式 (默认) | 严格模式 (--strict) |
|---|---|---|
| 设计理念 | "优先保命" (尽力而为) | "优先合规" (零容忍) |
| 公钥失败 | 托管块写入 PasswordAuthentication yes(保留密码登录通道),新建用户保持锁定(不会成为无密码可登录账号)。👉 结果:原有 root/密码用户仍能登录修补;新建用户因为账号锁定无法登录,操作员看到明确告警提示。 |
脚本立即报错退出,不修改任何配置。 |
| 既有用户密码 | v4.7.1 起:脚本不再清除已存在用户的密码,仅对新建账号执行 passwd -d |
同左 |
| 端口失败 | 若随机端口失败,回退使用 端口 22。 | 脚本立即报错退出。 |
| HTTP 密钥 URL | 仅警告并继续 | 拒绝 http://,要求 https:// |
| 防火墙规则添加失败 | 仅警告 | 警告并打日志(非 22 端口时) |
- 权限:必须以
root身份运行 - 必备命令:
cat / grep / awk / sed / cp / mv / chmod / chown / mkdir / rm / id - 建议命令 (脚本会自动补装):
curl或wget、sudo、openssh-server、ss或netstat、nc、base64、ssh-keygen - 支持发行版 (CI 全量验证):
- Debian 11 / 12
- Ubuntu 22.04 / 24.04
- Alpine (latest)
- AlmaLinux 9 / Rocky Linux 9 / CentOS Stream 9
- CentOS 7 (EOL,仅尽力而为)
| 路径 | 说明 |
|---|---|
/etc/ssh/sshd_config |
注入托管配置块;旧值改名为 *.bak_server_init |
/etc/ssh/sshd_config.d/*.conf |
冲突的 drop-in 自动备份重命名 |
/etc/sudoers.d/server-init-<user> |
稳定文件名(v4.7.0 起),可直接删除以撤销 |
/etc/systemd/system/sshd.service.d/override.conf |
防杀/自动重启 |
/etc/profile.d/z99-ssh-init-banner.sh |
登录横幅 |
/etc/motd + /etc/motd.bak |
清理旧的 server-init 行;首次创建 .bak 真备份 |
/etc/sysctl.conf |
启用 BBR 时追加 net.core.default_qdisc=fq 与 tcp_congestion_control=bbr |
| 防火墙规则 (ufw/firewalld/iptables/ip6tables) | 仅在 --port != 22 时打开 TCP;rollback 仅撤销当前 backend 写入的规则 |
| SELinux 端口标签 | 当系统处于 Enforcing 模式时通过 semanage port -a 加 ssh_port_t 标签;-m(modify)路径无法清晰回滚 |
/home/<user>/.ssh/authorized_keys |
已部署的公钥;拒绝符号链接路径;校验家目录所有者 (v4.7.3) |
/var/log/server-init.log |
运行日志 |
/var/log/server-init-audit.log |
审计日志(已脱敏 --key-raw= / --key-url=) |
/var/log/server-init-health.log |
健康快照 |
/var/backups/ssh-config/<TS>/ |
持久备份 + restore.sh + checksums.sha256 |
/var/lib/server-init/last-applied |
(v4.7.3+) 记录上一次成功使用的端口/防火墙后端;v4.7.4 起额外记录 SELINUX_PORT=N;v4.7.5 起记录 SELINUX_OWNED=y/n 区分"本脚本安装的 label" 与"管理员预先存在的 label",跨次运行只清理前者 |
/run/server-init/script.lock/ 或 /var/lib/server-init/script.lock/ |
(v4.7.6+) 脚本级互斥锁目录(含 PID 文件)。运行结束后自动清除;如果脚本被 kill -9 等异常终止可能遗留,下次启动会自动检测 PID 存活并回收 |
/run/server-init/last-artifacts-<UID> 或 /var/lib/server-init/last-artifacts-<UID> |
(v4.7.6+) artifact mirror。运行中 append;正常退出会清除;异常崩溃时遗留,下次启动会展示"遗留改动"清单提示操作员手动清理 |
- 脚本采用托管块机制:再次执行时先删除旧块再写入新块,不会重复堆积
- sudoers 文件名固定为
server-init-<user>,再次执行会覆盖而非新建 - 从 < v4.7.0 升级:旧版本会留下时间戳形式的 sudoers 文件 (
server-init-<user>-YYYYMMDD...)。v4.7.1 起在下次运行时自动清理这些遗留文件;v4.7.2 起严格匹配纯数字后缀,确保管理员自建的server-init-<user>-<非数字>文件(如server-init-admin-special-policy)不会被误删,且不会跨用户误删兄弟账号的稳定文件。每次清理会在 audit log 记录LEGACY_SUDOERS_REMOVED - 备份目录每次按时间戳新建;最多保留 10 个最近备份,更旧的自动清理
| 退出码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 通用错误 / 用户取消 / 配置失败 |
| 130 | SIGINT (Ctrl-C) |
| 143 | SIGTERM |
| 129 | SIGHUP |
| ≠0 (执行中途) | 触发自动回滚;查看 /var/log/server-init.log 与 audit.log |
注意:Ctrl-C 在 确认提示 阶段触发时,此时尚未发生破坏性变更,不会进入回滚路径。
脚本执行后会生成以下重要文件,用于排查问题或审计合规:
📋 日志轮转建议:以下三个日志文件由脚本以追加方式写入,没有自带轮转机制。在频繁运行(CI/批量装机)的场景下建议加
logrotate配置:# /etc/logrotate.d/server-init /var/log/server-init*.log { weekly rotate 12 compress delaycompress missingok notifempty create 0600 root root }
- 运行日志:
/var/log/server-init.log(包含详细的 debug 信息) - 审计日志:
/var/log/server-init-audit.log(记录关键操作 Action、时间戳及操作人)- 主要 Action 类别(应监控加粗项):
- 生命周期:
START/DONE/ROLLBACK/RESTART_REFUSED - 账号:
USER_CREATED/PASSWORD_CLEARED/KEYS_DEPLOYED/ACCOUNT_KEPT_LOCKED/USER_REMOVE_FAILED - sudo:
SUDOERS_WRITTEN/SUDO_FAIL/LEGACY_SUDOERS_REMOVED - 系统配置:
MANAGED_BLOCK_INSTALLED/DROPIN_RENAMED/SYSTEMD_OVERRIDE_WRITTEN/MOTD_BANNER_WRITTEN/BBR_ENABLED/SYSTEM_UPDATE_START/SYSTEM_UPDATE_DONE - 防火墙:
FIREWALL_OPENED/FIREWALL_NOOP/STALE_FIREWALL_REMOVED/LAST_APPLIED_CLEARED - SELinux:
SELINUX_PORT_ADDED/SELINUX_PORT_NOOP/SELINUX_PORT_MODIFIED/SELINUX_PORT_FAIL/STALE_SELINUX_REMOVED/STALE_SELINUX_REMOVE_FAILED/STALE_SELINUX_KEPT/STALE_SELINUX_SKIP - 回滚不完整告警(重点告警):
ROLLBACK_RM_FAILED/ROLLBACK_MOTD_FAILED/ROLLBACK_MOTD_BAK_MISSING/STRANDED_MUTATIONS_DETECTED - 测试 / 安全相关:
LOGIN_TEST_PASSED/LOGIN_TEST_INCONCLUSIVE/INSECURE_KEY_URL/KEY_FETCH_FAILED/DIRECT_SPAWN/DIRECT_SPAWN_REFUSED
- 生命周期:
- stderr 后备格式(当
/var/log不可写时):AUDIT-FALLBACK <timestamp> ACTION=<name> DETAILS=<...> - 适合接入 SIEM 进行集中审计
- 主要 Action 类别(应监控加粗项):
- 健康报告:
/var/log/server-init-health.log(最终的系统配置状态快照)
脚本拥有两层安全机制:运行时自动回滚 和 持久化备份恢复。
如果在脚本执行完成后(显示 "DONE" 后)您无法连接服务器,请通过云服务商的 VNC / Console 控制台登录,并使用以下方法恢复。
脚本在修改前会自动创建带 SHA256 校验 的备份。restore.sh 在覆盖前会校验 checksums.sha256,被篡改的备份将被拒绝。
-
找到最近的备份目录:
ls -ld /var/backups/ssh-config/* -
进入目录并运行恢复脚本:
cd /var/backups/ssh-config/<TIMESTAMP>/ sh restore.sh
restore.sh会:① 校验校验和 → ② 覆盖sshd_config及sshd_config.d/→ ③ 运行sshd -t→ ④ 重启 sshd。任一步骤失败都会以非 0 退出码停止。覆盖校验:若
checksums.sha256缺失或系统无sha256sum,restore.sh会拒绝执行(防止恢复被篡改的备份)。如果你确信备份完整且必须强制恢复(例如手动删除了 checksums 文件),可以:FORCE=1 sh restore.sh
仅在你信任备份内容时使用。
注意:
restore.sh仅还原sshd_config与 drop-in;运行期创建的用户、sudoers、systemd override、防火墙规则等需依靠运行时自动回滚或手动撤销(见上方的"脚本修改/创建的文件"清单)。
如果 restore.sh 不可用,可手动复制文件:
# 1. 校验 (可选但强烈推荐)
cd /var/backups/ssh-config/<TIMESTAMP>/ && sha256sum -c checksums.sha256
# 2. 覆盖配置文件
cp /var/backups/ssh-config/<TIMESTAMP>/sshd_config /etc/ssh/sshd_config
# 3. 重启服务
systemctl restart sshd || service sshd restart本脚本会修改核心系统配置(SSH)。虽然脚本内置了多重安全检查和回滚机制,但请务必确保你拥有服务器的备用访问方式(如 VNC 控制台),以防网络波动或配置意外导致的连接中断。
本项目采用 MIT License 开源。