阿克森雲登入 / 註冊English/中文/cn繁體/tw

自動化腳本:上架首小時的冪等初始化

新服務器上架第一小時的標準動作寫成冪等腳本:跑十遍與跑一遍結果相同。本文給出完整可復制的 first-hour-init 腳本骨架(SSH 加固、防火牆、更新策略、基線採集),以及冪等設計的三條原則。

· AxionServe 編輯部 · 工具中心

手工初始化服務器的問題不在慢,在不可復現:十臺機器十個樣子,出事時沒人說得清哪臺改過什麼。解法是把上架第一小時的標準動作寫成冪等腳本——跑十遍與跑一遍結果相同,新機器一條命令到位。本篇給出可直接抄走的腳本骨架與設計原則。本文屬於安全基線中心系列的工具分支;每個動作的原理與清單在SSH 加固清單與防火牆基線。

冪等初始化腳本結構示意

冪等的三條設計原則

  • 檢查後動作,不是盲目動作:改配置前先 grep 目標狀態(已是目標值就跳過)——grep -q '^PasswordAuthentication no' sshd_config || sed -i ... 的模式貫穿全腳本;
  • 追加用標記塊,不整文件覆蓋:自定義配置寫進帶標記的塊(# BEGIN ax-init / # END ax-init),重跑時先刪舊塊再寫新塊——不動發行版原生行;
  • 失敗要響,成功要靜:set -euo pipefail 起手,每步失敗立即退出並留日志;成功路徑只輸出摘要——腳本的輸出是審計記錄,不是噪音。

腳本骨架:first-hour-init.sh(可直接抄)

#!/usr/bin/env bash
# first-hour-init.sh —— 上架首小時冪等初始化(Debian/Ubuntu 口徑,其他發行版改包管理器)
set -euo pipefail
LOG=/var/log/first-hour-init.log; exec >>("$LOG") 2>&1; echo "=== $(date -u +%FT%TZ) 開始 ==="

# ── 0. 前置:必須以 root 或 sudo 運行;先確認 SSH 密鑰已可用再禁密碼 ──
[ "$(id -u)" = 0 ] || { echo "需要 root"; exit 1; }
[ -s /root/.ssh/authorized_keys ] || { echo "❌ 先配置密鑰再運行(禁用密碼前必須驗證密鑰可登入)"; exit 1; }

# ── 1. SSH 加固(冪等:sshd_config.d 獨立文件,存在即覆蓋)──
cat > /etc/ssh/sshd_config.d/99-hardening.conf <<'EOF'
PermitRootLogin prohibit-password
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 20
EOF
systemd-delta 2>/dev/null | head -1 || true
systemctl reload ssh 2>/dev/null || systemctl reload sshd

# ── 2. 防火牆基線:默認拒絕入站 + 最小白名單(冪等:先重置再聲明)──
if command -v ufw >/dev/null; then
  ufw --force reset >/dev/null
  ufw default deny incoming; ufw default allow outgoing
  ufw allow 22/tcp comment 'ssh'          # 改了 SSH 端口的同步改這裏
  [ -n "${WEB:-}" ] && { ufw allow 80/tcp; ufw allow 443/tcp; }
  ufw --force enable; ufw status numbered
fi

# ── 3. fail2ban(存在即啓用,配置用標記塊冪等寫入)──
if command -v fail2ban-client >/dev/null; then
  printf '[sshd]
enabled = true
maxretry = 5
findtime = 600
bantime = 3600
' > /etc/fail2ban/jail.d/sshd.local
  systemctl enable --now fail2ban; fail2ban-client status sshd | head -5
fi

# ── 4. 自動安全更新(只裝補丁,不跨大版本——紀律見正文)──
if command -v apt >/dev/null; then
  apt-get install -y unattended-upgrades >/dev/null
  dpkg-reconfigure -f noninteractive unattended-upgrades >/dev/null || true
fi

# ── 5. 基線採集(裝機快照:日後「變沒變」的對照物)──
mkdir -p /var/log/baseline
{ echo "# $(date -u +%FT%TZ)"; uname -a; lscpu | grep -E "Model name|^CPU\(s\)"; free -h; df -h /;
  ss -tlnp; ip -brief addr; } > /var/log/baseline/boot-$(date +%F).txt

# ── 6. 時間同步與健康行 ──
timedatectl set-ntp true 2>/dev/null || true
echo "=== 完成:SSH/防火牆/fail2ban/更新/基線 五段全部就位 ==="

用法與驗證

# 上傳並執行(新機器第一條命令):
scp first-hour-init.sh root@新服務器IP:/root/ && ssh root@新服務器IP "bash /root/first-hour-init.sh"
# 冪等驗證:再跑一遍,結果應無差異、無報錯:
ssh root@新服務器IP "bash /root/first-hour-init.sh && tail -3 /var/log/first-hour-init.log"
# 效果驗證(從外部):
ssh -o PreferredAuthentications=password 新服務器IP exit   # 應被拒絕(密碼登入已禁)
nc -zv -w3 新服務器IP 22 && echo "22 開(預期)"
nc -zv -w3 新服務器IP 3306 2>/dev/null || echo "3306 關(預期:默認拒絕生效)"

腳本之外的三個配套動作

  • 版本化:腳本進你的 Git 倉庫(私有庫即可),每次修改留 commit——「誰在什麼時候改了初始化邏輯」有賬可查;配套的作品版(帶注釋的教學版)在創作社區的 first-hour-init.sh 作品頁;
  • 分層擴展:首小時腳本只管安全基線;業務棧(Nginx/數據庫/應用)另寫第二層腳本,兩層分開跑——基線層穩定不動,業務層隨需求迭代;多機器用 Ansible 把兩層編排起來(單腳本是起點不是終點);
  • 恢復演練聯動:備份腳本與恢復演練的自動化口徑見面板與備份——初始化的最後一塊拼圖是「這臺機器沒了,多久能重建」:有 first-hour-init + 備份 + 配置倉庫,答案是一臺新機器的開通時間——這個「重建時間」本身就是你架構成熟度的最好度量。

第二層腳本:業務棧的最小樣例

基線層之上,業務棧腳本同樣守冪等紀律。以最常見的 Nginx + 靜態站爲例,骨架三段:①安裝段——command -v nginx || apt-get install -y nginx(已裝即跳過);②配置段——站點配置寫成獨立文件放入 sites-available 並軟鏈到 sites-enabled,配置內容用「校驗後重載」模式:nginx -t && systemctl reload nginx(校驗失敗不重載,壞配置進不了生產);③驗證段——腳本末尾自測:curl -sf -o /dev/null http://127.0.0.1/ && echo "nginx ok",失敗即非零退出。三層結構(裝/配/驗)適用於一切業務棧腳本;機器多起來後把兩層腳本翻譯成 Ansible role(tasks 即命令、handlers 即重載、inventory 即機器清單)——腳本是 Ansible 的草稿,先寫對腳本再談編排。

常見翻車點清單

  • 禁密碼前沒驗證密鑰 → 把自己鎖在門外(腳本第 0 段的前置檢查就是防這個;真鎖了用機房 IPMI/VNC 通道救回);
  • ufw allow 順序錯 → 改過 SSH 端口的機器先 allow 新端口再 deny 22,順序反了同樣鎖門外;
  • sed 盲改配置文件 → 重跑一次改一次,配置越跑越花——用獨立 drop-in 文件(sshd_config.d 模式)替代 sed 直改;
  • 把密鑰/密碼寫進腳本 → 腳本進 Git 就是泄露:憑據永遠走環境變量或部署時的 secret 注入,腳本裏只留佔位符。

下一步

把腳本抄走、按你的發行版與端口改三行、進你的倉庫——第一臺機器開始就用冪等初始化,運維債從源頭少一半。安全動作的原理與完整清單在安全基線中心(SSH 十二動作/防火牆基線/備份演練三篇是一組);新機器開通入口在在售配置(入門 VPS $5.34/月起,練手成本最低的沙盒)。