From 7ae28eef707a2eb107669978dec3f228813d1572 Mon Sep 17 00:00:00 2001 From: Binbim_ProMax Date: Sun, 5 Jul 2026 01:07:57 +0800 Subject: [PATCH] feat: add deployment package for NAS (v9.3.9) --- .env | 10 ++++ build/compose.yaml | 143 +++++++++++++++++++++++++++++++++++++++++++++ build/deploy.sh | 112 +++++++++++++++++++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 .env create mode 100644 build/compose.yaml create mode 100644 build/deploy.sh diff --git a/.env b/.env new file mode 100644 index 0000000..b7250f5 --- /dev/null +++ b/.env @@ -0,0 +1,10 @@ +SAFELINE_DIR=/data/safeline +POSTGRES_PASSWORD=MnPX82WKvF1ztZeDECXq +MGT_PORT=9443 +RELEASE= +CHANNEL= +REGION= +IMAGE_PREFIX=chaitin +IMAGE_TAG=9.3.9 +SUBNET_PREFIX=192.168.90 +ARCH_SUFFIX= diff --git a/build/compose.yaml b/build/compose.yaml new file mode 100644 index 0000000..5536977 --- /dev/null +++ b/build/compose.yaml @@ -0,0 +1,143 @@ +networks: + safeline-ce: + name: safeline-ce + driver: bridge + ipam: + driver: default + config: + - gateway: ${SUBNET_PREFIX:?SUBNET_PREFIX required}.1 + subnet: ${SUBNET_PREFIX}.0/24 + driver_opts: + com.docker.network.bridge.name: safeline-ce + +services: + postgres: + container_name: safeline-pg + restart: always + image: ${IMAGE_PREFIX}/safeline-postgres${ARCH_SUFFIX}:15.2 + volumes: + - ${SAFELINE_DIR}/resources/postgres/data:/var/lib/postgresql/data + - /etc/localtime:/etc/localtime:ro + environment: + - POSTGRES_USER=safeline-ce + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?postgres password required} + networks: + safeline-ce: + ipv4_address: ${SUBNET_PREFIX}.2 + command: [postgres, -c, max_connections=600] + healthcheck: + test: pg_isready -U safeline-ce -d safeline-ce + mgt: + container_name: safeline-mgt + restart: always + image: ${IMAGE_PREFIX}/safeline-mgt${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG:?image tag required} + volumes: + - /etc/localtime:/etc/localtime:ro + - ${SAFELINE_DIR}/resources/mgt:/app/data + - ${SAFELINE_DIR}/logs/nginx:/app/log/nginx:z + - ${SAFELINE_DIR}/resources/sock:/app/sock + - /var/run:/app/run + ports: + - ${MGT_PORT:-9443}:1443 + healthcheck: + test: curl -k -f https://localhost:1443/api/open/health + environment: + - MGT_PG=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable + depends_on: + - postgres + - fvm + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" + networks: + safeline-ce: + ipv4_address: ${SUBNET_PREFIX}.4 + detect: + container_name: safeline-detector + restart: always + image: ${IMAGE_PREFIX}/safeline-detector${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG} + volumes: + - ${SAFELINE_DIR}/resources/detector:/resources/detector + - ${SAFELINE_DIR}/logs/detector:/logs/detector + - /etc/localtime:/etc/localtime:ro + environment: + - LOG_DIR=/logs/detector + networks: + safeline-ce: + ipv4_address: ${SUBNET_PREFIX}.5 + tengine: + container_name: safeline-tengine + restart: always + image: ${IMAGE_PREFIX}/safeline-tengine${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG} + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/resolv.conf:/etc/resolv.conf:ro + - ${SAFELINE_DIR}/resources/nginx:/etc/nginx + - ${SAFELINE_DIR}/resources/detector:/resources/detector + - ${SAFELINE_DIR}/resources/chaos:/resources/chaos + - ${SAFELINE_DIR}/logs/nginx:/var/log/nginx:z + - ${SAFELINE_DIR}/resources/cache:/usr/local/nginx/cache + - ${SAFELINE_DIR}/resources/sock:/app/sock + environment: + - TCD_MGT_API=https://${SUBNET_PREFIX}.4:1443/api/open/publish/server + - TCD_SNSERVER=${SUBNET_PREFIX}.5:8000 + # deprecated + - SNSERVER_ADDR=${SUBNET_PREFIX}.5:8000 + - CHAOS_ADDR=${SUBNET_PREFIX}.10 + ulimits: + nofile: 131072 + network_mode: host + luigi: + container_name: safeline-luigi + restart: always + image: ${IMAGE_PREFIX}/safeline-luigi${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG} + environment: + - MGT_IP=${SUBNET_PREFIX}.4 + - LUIGI_PG=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable + volumes: + - /etc/localtime:/etc/localtime:ro + - ${SAFELINE_DIR}/resources/luigi:/app/data + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" + depends_on: + - detect + - mgt + networks: + safeline-ce: + ipv4_address: ${SUBNET_PREFIX}.7 + fvm: + container_name: safeline-fvm + restart: always + image: ${IMAGE_PREFIX}/safeline-fvm${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG} + volumes: + - /etc/localtime:/etc/localtime:ro + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" + networks: + safeline-ce: + ipv4_address: ${SUBNET_PREFIX}.8 + chaos: + container_name: safeline-chaos + restart: always + image: ${IMAGE_PREFIX}/safeline-chaos${REGION}${ARCH_SUFFIX}${RELEASE}:${IMAGE_TAG} + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "10" + environment: + - DB_ADDR=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable + volumes: + - ${SAFELINE_DIR}/resources/sock:/app/sock + - ${SAFELINE_DIR}/resources/chaos:/app/chaos + networks: + safeline-ce: + ipv4_address: ${SUBNET_PREFIX}.10 \ No newline at end of file diff --git a/build/deploy.sh b/build/deploy.sh new file mode 100644 index 0000000..6048ba9 --- /dev/null +++ b/build/deploy.sh @@ -0,0 +1,112 @@ +#!/bin/bash +set -euo pipefail + +# SafeLine WAF 部署脚本 +# 用法: bash deploy.sh [安装目录] [管理端口] + +INSTALL_DIR="${1:-/data/safeline}" +MGT_PORT="${2:-9443}" +IMAGE_TAG="9.3.9" +SUBNET_PREFIX="192.168.90" + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +info() { echo -e "${GREEN}[INFO]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; } + +# 检查 root +if [ "$(id -u)" -ne 0 ]; then + error "需要 root 权限运行" +fi + +# 检查 Docker +if ! command -v docker &>/dev/null; then + error "Docker 未安装" +fi + +if ! docker compose version &>/dev/null && ! docker-compose version &>/dev/null; then + error "Docker Compose 未安装" +fi + +# 检测 docker compose 命令 +if docker compose version &>/dev/null; then + COMPOSE="docker compose" +else + COMPOSE="docker-compose" +fi + +info "安装目录: $INSTALL_DIR" +info "管理端口: $MGT_PORT" + +# 创建目录 +mkdir -p "$INSTALL_DIR"/{resources/{mgt,postgres/data,nginx,detector,chaos,cache,sock,luigi},logs/{nginx,detector}} + +# 生成随机密码 +POSTGRES_PASSWORD=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c 20) + +# 如果已有 .env 则保留 +ENV_FILE="$INSTALL_DIR/.env" +if [ -f "$ENV_FILE" ]; then + info "检测到已有 .env 配置,保留原配置" + source "$ENV_FILE" +else + cat > "$ENV_FILE" << EOF +SAFELINE_DIR=$INSTALL_DIR +POSTGRES_PASSWORD=$POSTGRES_PASSWORD +MGT_PORT=$MGT_PORT +RELEASE= +CHANNEL= +REGION= +IMAGE_PREFIX=chaitin +IMAGE_TAG=$IMAGE_TAG +SUBNET_PREFIX=$SUBNET_PREFIX +ARCH_SUFFIX= +EOF + info ".env 配置已生成" +fi + +# 复制 compose.yaml +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [ -f "$SCRIPT_DIR/compose.yaml" ]; then + cp "$SCRIPT_DIR/compose.yaml" "$INSTALL_DIR/docker-compose.yaml" +elif [ -f "$SCRIPT_DIR/../compose.yaml" ]; then + cp "$SCRIPT_DIR/../compose.yaml" "$INSTALL_DIR/docker-compose.yaml" +else + warn "未找到 compose.yaml,请手动复制到 $INSTALL_DIR/" +fi + +# 拉取镜像 +info "拉取 Docker 镜像..." +cd "$INSTALL_DIR" +$COMPOSE pull 2>&1 || warn "部分镜像拉取失败,继续尝试启动..." + +# 启动容器 +info "启动容器..." +$COMPOSE up -d --remove-orphans + +# 等待健康检查 +info "等待服务启动..." +for i in $(seq 1 60); do + if docker inspect --format='{{.State.Health.Status}}' safeline-mgt 2>/dev/null | grep -q healthy; then + info "管理服务已启动" + break + fi + sleep 5 +done + +# 获取本机 IP +LOCAL_IP=$(hostname -I 2>/dev/null | awk '{print $1}' || echo "本机IP") + +echo "" +echo "=========================================" +info "部署完成!" +info "管理面板: https://$LOCAL_IP:$MGT_PORT/" +info "默认用户名: admin" +info "首次登录需要通过 mgt-cli 获取密码:" +info " docker exec safeline-mgt /app/mgt-cli reset-admin --once" +echo "========================================="