From 3ff54df247e2400159497662f20538cdeb348874 Mon Sep 17 00:00:00 2001 From: wooo Date: Thu, 18 Jun 2026 12:11:11 +0800 Subject: [PATCH] ci: harden production ssh deploy target --- .gitea/workflows/cd.yaml | 63 +++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index fe8d91b..e7a0ac3 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -109,14 +109,33 @@ jobs: run: apt-get update -qq && apt-get install -y -qq rsync openssh-client - name: Configure SSH Key + env: + PROD_SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }} + PROD_SERVER_IP_SECRET: ${{ secrets.PROD_SERVER_IP }} + PROD_SERVER_USER_SECRET: ${{ secrets.PROD_SERVER_USER }} run: | + set -euo pipefail + PROD_SERVER_IP="${PROD_SERVER_IP_SECRET:-192.168.0.188}" + PROD_SERVER_USER="${PROD_SERVER_USER_SECRET:-ollama}" + if [ -z "$PROD_SERVER_IP" ] || [ -z "$PROD_SERVER_USER" ]; then + echo "禁止部署:正式主機 IP 或使用者未設定。" + exit 1 + fi + if [ -z "${PROD_SSH_PRIVATE_KEY:-}" ]; then + echo "禁止部署:Gitea secret PROD_SSH_PRIVATE_KEY 未設定。" + exit 1 + fi + echo "PROD_SERVER_IP=$PROD_SERVER_IP" >> "$GITHUB_ENV" + echo "PROD_SERVER_USER=$PROD_SERVER_USER" >> "$GITHUB_ENV" + echo "部署目標:$PROD_SERVER_USER@$PROD_SERVER_IP" mkdir -p ~/.ssh - echo "${{ secrets.PROD_SSH_PRIVATE_KEY }}" > ~/.ssh/id_deploy + printf '%s\n' "$PROD_SSH_PRIVATE_KEY" > ~/.ssh/id_deploy chmod 600 ~/.ssh/id_deploy - ssh-keyscan ${{ secrets.PROD_SERVER_IP }} >> ~/.ssh/known_hosts + ssh-keyscan -T 10 "$PROD_SERVER_IP" >> ~/.ssh/known_hosts - name: Sync Files to Production run: | + set -euo pipefail printf "%s\n" "${{ github.sha }}" > REVISION rsync -az --delete --delay-updates -e "ssh -i ~/.ssh/id_deploy" \ --exclude='.git/' \ @@ -126,28 +145,26 @@ jobs: --exclude='venv/' \ --exclude='__pycache__/' \ --exclude='.env' \ - ./ ${{ secrets.PROD_SERVER_USER }}@${{ secrets.PROD_SERVER_IP }}:/opt/fifa2026/current/ + ./ "$PROD_SERVER_USER@$PROD_SERVER_IP:/opt/fifa2026/current/" - name: Restart Docker Containers - uses: appleboy/ssh-action@v1.0.3 - with: - host: ${{ secrets.PROD_SERVER_IP }} - username: ${{ secrets.PROD_SERVER_USER }} - key: ${{ secrets.PROD_SSH_PRIVATE_KEY }} - script: | - set -euo pipefail - echo "🚀 [Deploy] Starting deployment for 2026fifa.wooo.work" - cd /opt/fifa2026/current + run: | + set -euo pipefail + ssh -i ~/.ssh/id_deploy "$PROD_SERVER_USER@$PROD_SERVER_IP" 'bash -se' <<'DEPLOY_SCRIPT' + set -euo pipefail + echo "[Deploy] Starting deployment for 2026fifa.wooo.work" + cd /opt/fifa2026/current - for file in iwooos_javae_monitor.sh iwooos_autopatch.py fix_guardian.py fix_register.sh fix_wazuh.sh ops/harden-host.sh; do - if [ -e "$file" ]; then - echo "❌ [Deploy] Forbidden emergency script still exists on production: $file" - exit 1 - fi - done + for file in iwooos_javae_monitor.sh iwooos_autopatch.py fix_guardian.py fix_register.sh fix_wazuh.sh ops/harden-host.sh; do + if [ -e "$file" ]; then + echo "[Deploy] Forbidden emergency script still exists on production: $file" + exit 1 + fi + done - docker compose -f docker-compose.prod.yml config -q - docker compose -f docker-compose.prod.yml build --pull - docker compose -f docker-compose.prod.yml up -d --remove-orphans - docker image prune -f - echo "✅ [Deploy] Deployment completed successfully!" + docker compose -f docker-compose.prod.yml config -q + docker compose -f docker-compose.prod.yml build --pull + docker compose -f docker-compose.prod.yml up -d --remove-orphans + docker image prune -f + echo "[Deploy] Deployment completed successfully." + DEPLOY_SCRIPT