Files
microdao-daarion/scripts/deploy-daarion-web-node1.sh
Apple d77a4769c6 🔒 security(daarion-web): Hardening after crypto-mining incidents
## Root Cause Analysis
- Found CRITICAL RCE vulnerability in Next.js 15.0.3 (GHSA-9qr9-h5gf-34mp)
- 10 vulnerabilities total including SSRF, DoS, Auth Bypass
- Attack vector: exposed port 3000 + vulnerable Next.js → remote code execution

## Security Fixes
- Upgraded Next.js: 15.0.3 → 15.5.9 (0 vulnerabilities)
- Upgraded eslint-config-next: 15.0.3 → 15.5.9

## Hardening (New Files)
- apps/web/Dockerfile.secure: Multi-stage build, read-only FS, no shell
- docker-compose.web.secure.yml: Resource limits, cap_drop ALL, localhost bind
- scripts/rebuild-daarion-web-secure.sh: Local secure rebuild with Trivy scan
- scripts/deploy-daarion-web-node1.sh: Production deployment to NODE1
- SECURITY-REBUILD-REPORT.md: Full incident analysis and remediation report

## Key Security Measures
- restart: "no" (until verified)
- ports: 127.0.0.1:3000 (localhost only, use Nginx reverse proxy)
- read_only: true
- cap_drop: ALL
- resources.limits: 1 CPU, 512M RAM
- no-new-privileges: true

## Related Incidents
- Incident #1 (Jan 8): catcal, G4NQXBp miners
- Incident #2 (Jan 9): softirq, vrarhpb miners
- Hetzner AbuseID: 10F3971:2A

Co-authored-by: Cursor Agent <agent@cursor.sh>
2026-01-09 02:08:13 -08:00

176 lines
5.3 KiB
Bash
Executable File

#!/bin/bash
# ============================================
# DAARION Web - NODE1 Production Deployment
# Version: 1.0.0
# Created: 2026-01-09
# Purpose: Deploy secure daarion-web to NODE1
# ============================================
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Configuration
NODE1_IP="144.76.224.179"
NODE1_USER="root"
PROJECT_DIR="/opt/microdao-daarion"
LOCAL_DIR="/Users/apple/github-projects/microdao-daarion"
IMAGE_NAME="daarion-web"
IMAGE_TAG="secure-$(date +%Y%m%d)"
echo -e "${BLUE}============================================${NC}"
echo -e "${BLUE} DAARION Web - NODE1 Production Deployment${NC}"
echo -e "${BLUE}============================================${NC}"
echo ""
echo -e "${YELLOW}⚠️ TARGET: ${NODE1_USER}@${NODE1_IP}${NC}"
echo ""
# ============================================
# Step 1: Pre-deployment checks
# ============================================
echo -e "${YELLOW}[1/6] Pre-deployment checks...${NC}"
# Check SSH connectivity
if ! ssh -o ConnectTimeout=5 ${NODE1_USER}@${NODE1_IP} "echo 'SSH OK'" 2>/dev/null; then
echo -e "${RED}ERROR: Cannot connect to NODE1 via SSH${NC}"
exit 1
fi
echo -e "${GREEN}✓ SSH connection OK${NC}"
# ============================================
# Step 2: Sync updated files to NODE1
# ============================================
echo -e "${YELLOW}[2/6] Syncing files to NODE1...${NC}"
# Sync web app directory
rsync -avz --delete \
"${LOCAL_DIR}/apps/web/" \
"${NODE1_USER}@${NODE1_IP}:${PROJECT_DIR}/apps/web/" \
--exclude 'node_modules' \
--exclude '.next'
# Sync docker-compose
scp "${LOCAL_DIR}/docker-compose.web.secure.yml" \
"${NODE1_USER}@${NODE1_IP}:${PROJECT_DIR}/"
# Sync scripts
scp "${LOCAL_DIR}/scripts/rebuild-daarion-web-secure.sh" \
"${NODE1_USER}@${NODE1_IP}:${PROJECT_DIR}/scripts/"
echo -e "${GREEN}✓ Files synced${NC}"
# ============================================
# Step 3: Install dependencies on NODE1
# ============================================
echo -e "${YELLOW}[3/6] Installing dependencies on NODE1...${NC}"
ssh ${NODE1_USER}@${NODE1_IP} << 'ENDSSH'
cd /opt/microdao-daarion/apps/web
npm ci --only=production --ignore-scripts 2>/dev/null || npm install --only=production --ignore-scripts
npm audit || true
ENDSSH
echo -e "${GREEN}✓ Dependencies installed${NC}"
# ============================================
# Step 4: Build secure image on NODE1
# ============================================
echo -e "${YELLOW}[4/6] Building secure Docker image on NODE1...${NC}"
ssh ${NODE1_USER}@${NODE1_IP} << ENDSSH
cd /opt/microdao-daarion
# Stop old container
docker stop daarion-web 2>/dev/null || true
docker rm daarion-web 2>/dev/null || true
# Remove old images (CRITICAL for security)
docker images | grep daarion-web | awk '{print \$3}' | xargs -r docker rmi -f 2>/dev/null || true
# Clear build cache
docker builder prune -f 2>/dev/null || true
# Build new secure image
docker build \
--no-cache \
--pull \
-t ${IMAGE_NAME}:${IMAGE_TAG} \
-t ${IMAGE_NAME}:latest \
-f apps/web/Dockerfile.secure \
apps/web/
ENDSSH
echo -e "${GREEN}✓ Image built on NODE1${NC}"
# ============================================
# Step 5: Security scan on NODE1
# ============================================
echo -e "${YELLOW}[5/6] Running security scan on NODE1...${NC}"
ssh ${NODE1_USER}@${NODE1_IP} << ENDSSH
# Install Trivy if not present
if ! command -v trivy &> /dev/null; then
echo "Installing Trivy..."
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
fi
# Run security scan
trivy image --severity HIGH,CRITICAL ${IMAGE_NAME}:${IMAGE_TAG}
ENDSSH
echo -e "${GREEN}✓ Security scan completed${NC}"
# ============================================
# Step 6: Deploy container
# ============================================
echo -e "${YELLOW}[6/6] Deploying secure container...${NC}"
ssh ${NODE1_USER}@${NODE1_IP} << 'ENDSSH'
cd /opt/microdao-daarion
# Create network if not exists
docker network create dagi-network 2>/dev/null || true
# Deploy with secure compose file
docker compose -f docker-compose.web.secure.yml up -d
# Wait for startup
sleep 10
# Check status
docker ps | grep daarion-web
docker logs --tail 20 daarion-web
ENDSSH
echo -e "${GREEN}✓ Container deployed${NC}"
# ============================================
# Summary
# ============================================
echo ""
echo -e "${BLUE}============================================${NC}"
echo -e "${GREEN} DEPLOYMENT COMPLETED${NC}"
echo -e "${BLUE}============================================${NC}"
echo ""
echo -e "Image: ${IMAGE_NAME}:${IMAGE_TAG}"
echo -e "Node: ${NODE1_IP}"
echo ""
echo -e "${YELLOW}MONITORING COMMANDS:${NC}"
echo " ssh ${NODE1_USER}@${NODE1_IP} docker logs -f daarion-web"
echo " ssh ${NODE1_USER}@${NODE1_IP} docker stats daarion-web"
echo " ssh ${NODE1_USER}@${NODE1_IP} 'docker exec daarion-web ps aux'"
echo ""
echo -e "${RED}⚠️ MONITOR FOR 30+ MINUTES BEFORE ENABLING AUTO-RESTART!${NC}"
echo ""
echo "To enable auto-restart after verification:"
echo " ssh ${NODE1_USER}@${NODE1_IP}"
echo " vim /opt/microdao-daarion/docker-compose.web.secure.yml"
echo " # Change: restart: \"no\" → restart: \"unless-stopped\""
echo " docker compose -f docker-compose.web.secure.yml up -d"