Deployment Server 架設:部署伺服器建置指南【2025】
每次部署都要 SSH 進五台伺服器,一台一台執行指令?
Deployment Server(部署伺服器)是集中管理部署作業的中心節點。透過它,你可以一次將程式碼部署到所有目標伺服器,同時保持部署流程的一致性和可追蹤性。
這篇文章將教你從零開始架設 Deployment Server,從基礎設定到進階自動化,建立專業的部署管理系統。
什麼是 Deployment Server?
Deployment Server 是專門用來執行部署作業的伺服器,作為部署流程的控制中心。
Deployment Server 的角色
集中化管理
所有部署作業都從 Deployment Server 發起:
- 統一的部署入口點
- 一致的部署環境
- 集中的日誌記錄
安全隔離
Deployment Server 作為中介層:
- 開發者不需要直接存取生產伺服器
- 部署金鑰集中管理
- 減少暴露面
自動化執行
與 CI/CD 整合:
- 接收 Webhook 觸發部署
- 執行預定義的部署腳本
- 處理多伺服器部署
架構示意
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────┐ │
│ │ Developer│ │
│ └────┬─────┘ │
│ │ git push │
│ ▼ │
│ ┌──────────┐ Webhook ┌─────────────────┐ │
│ │ GitHub │ ────────────────▶│ Deployment │ │
│ │ GitLab │ │ Server │ │
│ └──────────┘ └────────┬────────┘ │
│ │ │
│ ┌────────────────┼────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Web │ │ API │ │ Worker │ │
│ │ Server │ │ Server │ │ Server │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
何時需要 Deployment Server?
| 情境 | 需要 Deployment Server |
|---|---|
| 單一伺服器、小型專案 | 不一定需要 |
| 多台伺服器、團隊協作 | 建議使用 |
| 需要審計追蹤 | 必要 |
| 安全合規要求高 | 必要 |
| 複雜的部署流程 | 強烈建議 |
想了解更多部署基礎知識,請參考我們的 程式部署完整指南。
Deployment Server 規格與準備
讓我們開始準備 Deployment Server 的環境。
硬體規格建議
Deployment Server 主要執行腳本和網路傳輸,不需要太強的規格:
| 規格 | 最低需求 | 建議規格 |
|---|---|---|
| CPU | 1 vCPU | 2 vCPU |
| RAM | 1 GB | 2 GB |
| 儲存 | 20 GB SSD | 50 GB SSD |
| 網路 | 與目標伺服器同網段 | 內網低延遲 |
作業系統選擇
推薦使用 Linux:
- Ubuntu 22.04 LTS:最常見,社群支援好
- Debian 12:穩定,更新週期長
- Rocky Linux 9:RHEL 相容,企業環境常用
網路規劃
Deployment Server 的網路位置很重要:
內網部署(推薦)
Internet → Firewall → DMZ → [App Servers]
↑
Internal Network
↓
[Deployment Server]
優點:
- 與目標伺服器低延遲
- 不暴露在公網
- 安全性較高
雲端部署
Cloud VPC
├── Public Subnet
│ └── Bastion Host
└── Private Subnet
├── Deployment Server
└── App Servers
初始設定
SSH 進入新建立的伺服器,執行初始設定:
# 更新系統
sudo apt update && sudo apt upgrade -y
# 設定時區
sudo timedatectl set-timezone Asia/Taipei
# 安裝基本工具
sudo apt install -y git curl wget vim htop
# 建立部署專用帳號
sudo useradd -m -s /bin/bash deployer
sudo usermod -aG sudo deployer
💡 部署架構設計需要協助?讓 VibeFix 幫你規劃
SSH 金鑰管理
SSH 金鑰是 Deployment Server 的核心,需要妥善管理。
產生部署金鑰
在 Deployment Server 上產生專用金鑰:
# 切換到 deployer 帳號
sudo su - deployer
# 產生 Ed25519 金鑰(推薦)
ssh-keygen -t ed25519 -C "deployer@deployment-server" -f ~/.ssh/deploy_key
# 或 RSA 金鑰(相容性較好)
ssh-keygen -t rsa -b 4096 -C "deployer@deployment-server" -f ~/.ssh/deploy_key
部署公鑰到目標伺服器
將公鑰複製到所有目標伺服器:
# 方法一:ssh-copy-id
ssh-copy-id -i ~/.ssh/deploy_key.pub user@target-server
# 方法二:手動複製
cat ~/.ssh/deploy_key.pub | ssh user@target-server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
SSH Config 設定
設定 ~/.ssh/config 簡化連線:
# Web Server
Host web-1
HostName 10.0.1.10
User deploy
IdentityFile ~/.ssh/deploy_key
StrictHostKeyChecking accept-new
Host web-2
HostName 10.0.1.11
User deploy
IdentityFile ~/.ssh/deploy_key
StrictHostKeyChecking accept-new
# API Server
Host api-1
HostName 10.0.2.10
User deploy
IdentityFile ~/.ssh/deploy_key
StrictHostKeyChecking accept-new
# 批次設定
Host 10.0.*.*
User deploy
IdentityFile ~/.ssh/deploy_key
StrictHostKeyChecking accept-new
設定完成後,可以直接用主機名稱連線:
ssh web-1
ssh api-1
金鑰安全最佳實踐
最小權限原則
目標伺服器上的部署帳號只給予必要權限:
# 在目標伺服器上
# 建立專用部署帳號
sudo useradd -m -s /bin/bash deploy
# 只給予部署相關目錄的權限
sudo chown -R deploy:deploy /var/www/app
sudo chown -R deploy:deploy /opt/app
# 如需重啟服務,使用 sudoers 限制
echo "deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp" | sudo tee /etc/sudoers.d/deploy
金鑰輪換
定期更換部署金鑰:
# 產生新金鑰
ssh-keygen -t ed25519 -f ~/.ssh/deploy_key_new
# 部署新公鑰到所有伺服器
for host in web-1 web-2 api-1; do
ssh-copy-id -i ~/.ssh/deploy_key_new.pub $host
done
# 測試新金鑰
ssh -i ~/.ssh/deploy_key_new web-1 "echo 'New key works'"
# 替換舊金鑰
mv ~/.ssh/deploy_key ~/.ssh/deploy_key_old
mv ~/.ssh/deploy_key_new ~/.ssh/deploy_key
更多 SSH 金鑰設定,請參考我們的 GitHub Deploy Key 設定教學。
防火牆與安全設定
Deployment Server 是高價值目標,必須做好安全防護。
UFW 防火牆設定
# 安裝 UFW
sudo apt install -y ufw
# 預設拒絕所有連入
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 允許 SSH(限制來源 IP)
sudo ufw allow from 10.0.0.0/8 to any port 22
# 如果需要接收 Webhook
sudo ufw allow from 192.30.252.0/22 to any port 9000 # GitHub
sudo ufw allow from 185.199.108.0/22 to any port 9000 # GitHub
sudo ufw allow from 140.82.112.0/20 to any port 9000 # GitHub
# 啟用防火牆
sudo ufw enable
sudo ufw status verbose
SSH 強化
編輯 /etc/ssh/sshd_config:
# 禁用密碼登入
PasswordAuthentication no
ChallengeResponseAuthentication no
# 禁用 root 登入
PermitRootLogin no
# 限制登入使用者
AllowUsers deployer admin
# 設定連線逾時
ClientAliveInterval 300
ClientAliveCountMax 2
# 限制同時連線數
MaxSessions 10
MaxStartups 10:30:60
重啟 SSH 服務:
sudo systemctl restart sshd
Fail2ban 防暴力破解
# 安裝 Fail2ban
sudo apt install -y fail2ban
# 建立設定檔
sudo tee /etc/fail2ban/jail.local << EOF
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
EOF
# 啟動服務
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
部署工具選擇與設定
有多種工具可以在 Deployment Server 上執行部署作業。
Ansible
最流行的組態管理與部署工具,使用 YAML 語法。
安裝
sudo apt install -y ansible
設定 Inventory
建立 /etc/ansible/hosts 或專案目錄下的 inventory.ini:
[webservers]
web-1 ansible_host=10.0.1.10
web-2 ansible_host=10.0.1.11
[apiservers]
api-1 ansible_host=10.0.2.10
api-2 ansible_host=10.0.2.11
[workers]
worker-1 ansible_host=10.0.3.10
[all:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/deploy_key
建立部署 Playbook
deploy.yml:
---
- name: Deploy Application
hosts: webservers
become: yes
vars:
app_path: /var/www/app
repo_url: [email protected]:company/app.git
branch: main
tasks:
- name: Pull latest code
git:
repo: "{{ repo_url }}"
dest: "{{ app_path }}"
version: "{{ branch }}"
force: yes
notify: Restart app
- name: Install dependencies
command: npm ci
args:
chdir: "{{ app_path }}"
- name: Build application
command: npm run build
args:
chdir: "{{ app_path }}"
handlers:
- name: Restart app
systemd:
name: myapp
state: restarted
執行部署
# 部署到所有 webservers
ansible-playbook -i inventory.ini deploy.yml
# 只部署到特定伺服器
ansible-playbook -i inventory.ini deploy.yml --limit web-1
# 試跑(不實際執行)
ansible-playbook -i inventory.ini deploy.yml --check
💡 不確定該用哪個部署工具?讓 VibeFix 專家幫你評估
Capistrano
Ruby 生態系常用的部署工具,特別擅長管理 Release 版本。
安裝
# 安裝 Ruby
sudo apt install -y ruby ruby-dev
sudo gem install capistrano
初始化專案
cd /path/to/project
cap install
設定 config/deploy.rb
set :application, "myapp"
set :repo_url, "[email protected]:company/app.git"
set :deploy_to, "/var/www/myapp"
set :branch, "main"
set :linked_files, %w{.env}
set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets vendor/bundle}
set :keep_releases, 5
namespace :deploy do
desc 'Restart application'
task :restart do
on roles(:app) do
execute :sudo, :systemctl, :restart, :myapp
end
end
after :publishing, :restart
end
設定 config/deploy/production.rb
server "10.0.1.10", user: "deploy", roles: %w{app web}
server "10.0.1.11", user: "deploy", roles: %w{app web}
set :ssh_options, {
keys: %w(~/.ssh/deploy_key),
forward_agent: false
}
執行部署
cap production deploy
Capistrano 會自動管理 Release 目錄:
/var/www/myapp/
├── current -> releases/20250115120000
├── releases/
│ ├── 20250115120000/
│ ├── 20250114100000/
│ └── 20250113090000/
├── shared/
│ ├── .env
│ └── log/
└── repo/
Fabric
Python 生態系的部署工具,適合簡單任務。
安裝
pip install fabric
建立 fabfile.py
from fabric import task, Connection
from fabric import SerialGroup
SERVERS = [
"[email protected]",
"[email protected]",
]
@task
def deploy(c):
"""Deploy to all servers"""
group = SerialGroup(*SERVERS, connect_kwargs={"key_filename": "~/.ssh/deploy_key"})
with group.cd("/var/www/app"):
group.run("git pull origin main")
group.run("npm ci")
group.run("npm run build")
group.sudo("systemctl restart myapp")
@task
def rollback(c):
"""Rollback to previous version"""
group = SerialGroup(*SERVERS, connect_kwargs={"key_filename": "~/.ssh/deploy_key"})
with group.cd("/var/www/app"):
group.run("git checkout HEAD~1")
group.run("npm ci")
group.run("npm run build")
group.sudo("systemctl restart myapp")
@task
def status(c):
"""Check service status on all servers"""
group = SerialGroup(*SERVERS, connect_kwargs={"key_filename": "~/.ssh/deploy_key"})
group.sudo("systemctl status myapp")
執行
fab deploy
fab rollback
fab status
工具比較
| 特性 | Ansible | Capistrano | Fabric |
|---|---|---|---|
| 語言 | YAML/Python | Ruby | Python |
| Agentless | 是 | 是 | 是 |
| Release 管理 | 需設定 | 內建 | 需自己實作 |
| 學習曲線 | 中等 | 中等 | 低 |
| 適合場景 | 基礎設施管理 | Web App 部署 | 簡單任務 |
| 社群生態 | 豐富 | Ruby 生態 | Python 生態 |
Git Webhook 自動部署
讓 Deployment Server 接收 Webhook,實現 Push 後自動部署。
設定 Webhook Server
使用 webhook 工具接收 GitHub/GitLab 的 Webhook:
# 安裝 webhook
sudo apt install -y webhook
# 或使用 Go 版本
wget https://github.com/adnanh/webhook/releases/download/2.8.1/webhook-linux-amd64.tar.gz
tar -xzf webhook-linux-amd64.tar.gz
sudo mv webhook-linux-amd64/webhook /usr/local/bin/
設定 Webhook 規則
建立 /etc/webhook/hooks.json:
[
{
"id": "deploy-app",
"execute-command": "/opt/scripts/deploy.sh",
"command-working-directory": "/opt/scripts",
"response-message": "Deployment triggered",
"trigger-rule": {
"and": [
{
"match": {
"type": "payload-hmac-sha256",
"secret": "your-webhook-secret",
"parameter": {
"source": "header",
"name": "X-Hub-Signature-256"
}
}
},
{
"match": {
"type": "value",
"value": "refs/heads/main",
"parameter": {
"source": "payload",
"name": "ref"
}
}
}
]
},
"pass-arguments-to-command": [
{
"source": "payload",
"name": "after"
}
]
}
]
建立部署腳本
/opt/scripts/deploy.sh:
#!/bin/bash
set -e
COMMIT_SHA=$1
LOG_FILE="/var/log/deploy/deploy-$(date +%Y%m%d-%H%M%S).log"
SLACK_WEBHOOK="https://hooks.slack.com/services/xxx"
# 記錄開始
echo "=== Deployment started at $(date) ===" | tee -a $LOG_FILE
echo "Commit: $COMMIT_SHA" | tee -a $LOG_FILE
# 通知開始
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"🚀 Deployment started: $COMMIT_SHA\"}" \
$SLACK_WEBHOOK
# 執行 Ansible 部署
cd /opt/deploy/myapp
if ansible-playbook -i inventory.ini deploy.yml 2>&1 | tee -a $LOG_FILE; then
# 成功通知
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"✅ Deployment succeeded: $COMMIT_SHA\"}" \
$SLACK_WEBHOOK
echo "=== Deployment succeeded ===" | tee -a $LOG_FILE
else
# 失敗通知
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"❌ Deployment failed: $COMMIT_SHA\"}" \
$SLACK_WEBHOOK
echo "=== Deployment failed ===" | tee -a $LOG_FILE
exit 1
fi
啟動 Webhook 服務
建立 systemd 服務 /etc/systemd/system/webhook.service:
[Unit]
Description=Webhook Server
After=network.target
[Service]
Type=simple
User=deployer
ExecStart=/usr/local/bin/webhook -hooks /etc/webhook/hooks.json -port 9000 -verbose
Restart=always
[Install]
WantedBy=multi-user.target
啟動服務:
sudo systemctl enable webhook
sudo systemctl start webhook
設定 GitHub Webhook
- 前往 GitHub Repository → Settings → Webhooks
- 點擊「Add webhook」
- 設定:
- Payload URL:http://your-deployment-server:9000/hooks/deploy-app
- Content type:application/json
- Secret:與 hooks.json 中設定的相同
- Events:選擇「Just the push event」
日誌與監控
Deployment Server 需要良好的日誌記錄,方便追蹤和除錯。
部署日誌管理
# 建立日誌目錄
sudo mkdir -p /var/log/deploy
sudo chown deployer:deployer /var/log/deploy
# 設定 logrotate
sudo tee /etc/logrotate.d/deploy << EOF
/var/log/deploy/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 deployer deployer
}
EOF
部署歷史追蹤
建立部署歷史記錄:
#!/bin/bash
# /opt/scripts/record-deploy.sh
HISTORY_FILE="/var/log/deploy/history.csv"
# 記錄格式:時間,Commit,部署者,結果
echo "$(date -Iseconds),$1,$2,$3" >> $HISTORY_FILE
監控與告警
使用 Prometheus + Alertmanager 監控部署狀態:
# prometheus/alerts/deploy.yml
groups:
- name: deployment
rules:
- alert: DeploymentFailed
expr: deployment_status{status="failed"} > 0
for: 1m
labels:
severity: critical
annotations:
summary: "Deployment failed"
description: "Deployment to {{ $labels.environment }} failed"
VibeFix 部署架構服務
建立專業的 Deployment Server 需要考慮很多細節:
- 伺服器規格與網路架構
- SSH 金鑰管理與安全設定
- 部署工具選擇與設定
- 自動化流程設計
- 監控與告警整合
VibeFix 團隊提供完整的部署架構設計與實作服務。
服務範圍:
- Deployment Server 規劃與建置
- Ansible / Capistrano 設定
- CI/CD 整合
- 安全性強化
- 監控系統建置
想了解更詳細的服務?查看 VibeFix 服務內容。
結語:建立可靠的部署基礎設施
Deployment Server 是自動化部署的核心,一個好的部署伺服器可以:
- 集中管理所有部署作業
- 提供一致的部署環境
- 加強安全性與存取控制
- 完整記錄部署歷史
- 實現自動化部署流程
透過這篇教學,你已經學會:
- Deployment Server 的角色與架構
- 伺服器規格與初始設定
- SSH 金鑰管理與安全最佳實踐
- 防火牆與安全強化
- Ansible、Capistrano、Fabric 三種部署工具
- Git Webhook 自動部署設定
- 日誌與監控管理
接下來,你可以學習 CI/CD 建置與部署流程,將 Deployment Server 整合進完整的 CI/CD Pipeline。或者參考 軟體部署策略,了解藍綠部署、滾動部署等進階策略。
部署失敗?別擔心
Deployment Server 架設涉及多個技術面向,踩坑是正常的。VibeFix 團隊可以幫你快速建立可靠的部署基礎設施。