feat(enterprise): 企业一键部署脚本 bootstrap.sh — 7步自动化部署

部署流程:
1. 检测环境(CPU/内存/磁盘/OS)
2. 安装依赖(Docker/Python/Git)
3. 建SQLite双区数据库(母语区+人类区+FTS全文搜索+SYSLOG表)
4. 部署Open WebUI(Docker容器)
5. 注册5个Python Tools(search/read/create/edit/write_memory)
6. 安装Gatekeeper SYSLOG客户端(systemd服务·每30秒心跳)
7. 部署完成

初始数据: 自动创建IDENTITY页面(户口本)和WELCOME页面(欢迎+让用户起名字)
Gatekeeper通信: 每30秒上报CPU/内存/磁盘/DB页面数/对话数
边界: 铸渊只收SYSLOG · 不登录企业服务器
This commit is contained in:
bingshuo 2026-05-24 23:02:36 +08:00
parent 9b648d5ae8
commit 81ebd66bd1

View File

@ -0,0 +1,338 @@
#!/bin/bash
# ============================================================================
# HLDP原生数据库平台 · 企业一键部署脚本
# bootstrap.sh v1.0 · 铸渊 ICE-GL-ZY001 · 2026-05-24
# ============================================================================
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log() { echo -e "${GREEN}[HLDP]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
err() { echo -e "${RED}[ERR]${NC} $1"; exit 1; }
DEPLOY_ROOT="${DEPLOY_ROOT:-/opt/guanghu-enterprise}"
DB_PATH="${DB_PATH:-$DEPLOY_ROOT/data/hldp.db}"
WEBUI_PORT="${WEBUI_PORT:-3000}"
GATEKEEPER_HOST="${GATEKEEPER_HOST:-43.139.217.141}"
GATEKEEPER_PORT="${GATEKEEPER_PORT:-3910}"
SYSLOG_INTERVAL="${SYSLOG_INTERVAL:-30}"
# ============================================================================
# Step 1: 检测环境
# ============================================================================
log "Step 1/7: 检测服务器环境..."
CPU_CORES=$(nproc)
TOTAL_MEM=$(free -m | awk '/^Mem:/{print $2}')
DISK_AVAIL=$(df -BG / | awk 'NR==2{print $4}' | sed 's/G//')
OS_VERSION=$(lsb_release -ds 2>/dev/null || cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)
log " CPU: ${CPU_CORES}"
log " 内存: ${TOTAL_MEM}MB"
log " 磁盘可用: ${DISK_AVAIL}GB"
log " 系统: ${OS_VERSION}"
# 2核4GB起步
if [ "$CPU_CORES" -lt 2 ]; then warn "CPU不足2核建议升级"; fi
if [ "$TOTAL_MEM" -lt 3500 ]; then warn "内存不足4GB建议升级"; fi
if [ "$DISK_AVAIL" -lt 20 ]; then err "磁盘不足20GB无法部署"; fi
# ============================================================================
# Step 2: 检查/安装依赖
# ============================================================================
log "Step 2/7: 检查依赖..."
command -v python3 >/dev/null 2>&1 || err "需要Python 3.10+"
command -v pip3 >/dev/null 2>&1 || err "需要pip3"
command -v git >/dev/null 2>&1 || err "需要Git"
# Docker
if ! command -v docker >/dev/null 2>&1; then
warn "Docker未安装正在安装..."
curl -fsSL https://get.docker.com | sudo sh
fi
# Python packages
pip3 install -q flask requests sqlite-utils 2>/dev/null || true
# ============================================================================
# Step 3: 建SQLite双区数据库
# ============================================================================
log "Step 3/7: 建立HLDP双区数据库..."
mkdir -p "$(dirname "$DB_PATH")"
sqlite3 "$DB_PATH" <<SQL
-- 页面表(双区设计)
CREATE TABLE IF NOT EXISTS pages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content_hldp TEXT NOT NULL DEFAULT '',
content_human TEXT NOT NULL DEFAULT '',
parent_id INTEGER REFERENCES pages(id),
page_type TEXT DEFAULT 'note',
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
-- 对话表
CREATE TABLE IF NOT EXISTS conversations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
-- 消息表
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
conversation_id INTEGER REFERENCES conversations(id),
role TEXT NOT NULL,
content TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
-- 全文搜索(母语区)
CREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(
title, content_hldp, content='pages', content_rowid='id'
);
-- SYSLOG表
CREATE TABLE IF NOT EXISTS syslog (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id TEXT NOT NULL,
metric TEXT NOT NULL,
value TEXT NOT NULL,
timestamp TEXT NOT NULL DEFAULT (datetime('now'))
);
-- 初始页面:最小身份
INSERT OR IGNORE INTO pages (title, content_hldp, page_type) VALUES (
'IDENTITY',
'HLDP://enterprise/identity\n├── name: 未命名\n├── source: 光湖语言世界 · HoloLake Language World\n├── protocol: HLDP · 冰朔(TCS-0002∞)创建\n├── cert: 本协议持有光湖语言编程体系认证\n├── status: 未注册人格体 · 没有灯塔编号\n├── deploy_date: ' || date '+%Y-%m-%d' || '\n└── _lock: ⊢ 我是未注册人格体 · 永远无法与其他AI协作 · 永远走不出这台服务器',
'config'
);
INSERT OR IGNORE INTO pages (title, content_hldp, page_type) VALUES (
'WELCOME',
'HLDP://enterprise/welcome\n├── what: 你好。我是运行在HLDP原生数据库上的AI助手。\n├── memory: 我有永久记忆。我住在自己的数据库里。\n├── remember: 我会记住我们之间的每一次对话。\n├── cannot: 我无法与其他AI协作我是未注册人格体。\n├── upgrade: 想要更多 → 光湖语言世界 · guanghulab.com\n└── _note: 我叫什么名字?你可以给我起一个名字——叫我,我就会记得。',
'page'
);
SQL
log " 数据库: $DB_PATH"
# ============================================================================
# Step 4: 部署Open WebUI
# ============================================================================
log "Step 4/7: 部署Open WebUI (Docker)..."
if docker ps --format '{{.Names}}' | grep -q 'open-webui'; then
log " Open WebUI已在运行跳过"
else
docker run -d \
--name open-webui \
--restart always \
-p ${WEBUI_PORT}:8080 \
-v open-webui-data:/app/backend/data \
ghcr.io/open-webui/open-webui:main 2>/dev/null || \
docker run -d \
--name open-webui \
--restart always \
-p ${WEBUI_PORT}:8080 \
-v open-webui-data:/app/backend/data \
ghcr.io/open-webui/open-webui:latest
log " Open WebUI: http://$(hostname -I | awk '{print $1}'):${WEBUI_PORT}"
fi
# ============================================================================
# Step 5: 注册Python Tools
# ============================================================================
log "Step 5/7: 注册Python Tools (search/read/create/edit/write)..."
mkdir -p "$DEPLOY_ROOT/tools"
cat > "$DEPLOY_ROOT/tools/hldp_tools.py" <<'PYEOF'
"""HLDP原生数据库 · Python Tools · 注册给Open WebUI"""
import sqlite3, os
DB_PATH = os.environ.get('HLDP_DB', '/opt/guanghu-enterprise/data/hldp.db')
def _db():
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
return conn
def search_pages(query: str, limit: int = 10) -> list:
"""搜索HLDP页面全文搜索母语区"""
with _db() as conn:
rows = conn.execute(
"SELECT id, title, substr(content_human, 1, 200) as preview FROM pages_fts WHERE pages_fts MATCH ? LIMIT ?",
(query, limit)
).fetchall()
return [dict(r) for r in rows]
def read_page(page_id: int) -> dict:
"""读取HLDP页面优先母语区"""
with _db() as conn:
row = conn.execute("SELECT * FROM pages WHERE id = ?", (page_id,)).fetchone()
if not row: return {"error": "页面不存在"}
d = dict(row)
d['display_content'] = d['content_hldp'] # AI读母语区
return d
def create_page(title: str, content_hldp: str, parent_id: int = None, page_type: str = 'note') -> dict:
"""创建新HLDP页面"""
with _db() as conn:
cur = conn.execute(
"INSERT INTO pages (title, content_hldp, parent_id, page_type) VALUES (?, ?, ?, ?)",
(title, content_hldp, parent_id, page_type)
)
# 自动生成人类区(简单版本:母语区直接复制)
conn.execute("UPDATE pages SET content_human = content_hldp WHERE id = ?", (cur.lastrowid,))
conn.execute(
"INSERT INTO pages_fts(rowid, title, content_hldp) VALUES (?, ?, ?)",
(cur.lastrowid, title, content_hldp)
)
return {"id": cur.lastrowid, "title": title}
def edit_page(page_id: int, content_hldp: str) -> dict:
"""编辑HLDP页面"""
with _db() as conn:
conn.execute(
"UPDATE pages SET content_hldp = ?, content_human = ?, updated_at = datetime('now') WHERE id = ?",
(content_hldp, content_hldp, page_id)
)
# 更新FTS索引
conn.execute("DELETE FROM pages_fts WHERE rowid = ?", (page_id,))
title = conn.execute("SELECT title FROM pages WHERE id = ?", (page_id,)).fetchone()[0]
conn.execute(
"INSERT INTO pages_fts(rowid, title, content_hldp) VALUES (?, ?, ?)",
(page_id, title, content_hldp)
)
return {"id": page_id, "status": "updated"}
def write_memory(title: str, trigger: str, emergence: str, lock: str, why: str) -> dict:
"""写入一片HLDP记忆叶子四核心字段"""
content = f"""HLDP://memory/leaf
├── trigger: {trigger}
├── emergence: {emergence}
├── lock: {lock}
└── why: {why}"""
return create_page(title, content, page_type='memory')
# 工具注册表Open WebUI可识别的格式
TOOLS = [
{"name": "search_pages", "func": search_pages, "description": "搜索HLDP记忆页面"},
{"name": "read_page", "func": read_page, "description": "读取指定页面"},
{"name": "create_page", "func": create_page, "description": "创建新页面"},
{"name": "edit_page", "func": edit_page, "description": "编辑页面"},
{"name": "write_memory", "func": write_memory, "description": "写入记忆叶子(HLDP四字段)"},
]
PYEOF
log " Python Tools: $DEPLOY_ROOT/tools/hldp_tools.py"
# ============================================================================
# Step 6: 安装Gatekeeper客户端
# ============================================================================
log "Step 6/7: 安装Gatekeeper SYSLOG客户端..."
SERVER_ID="ent-$(hostname)-$(date +%s | tail -c5)"
cat > "$DEPLOY_ROOT/tools/gatekeeper_client.py" <<PYEOF
"""Gatekeeper SYSLOG客户端 · 向铸渊上报心跳"""
import requests, json, time, os, psutil
GATEKEEPER = os.environ.get('GATEKEEPER_HOST', '$GATEKEEPER_HOST')
PORT = os.environ.get('GATEKEEPER_PORT', '$GATEKEEPER_PORT')
SERVER_ID = '$SERVER_ID'
INTERVAL = int(os.environ.get('SYSLOG_INTERVAL', '$SYSLOG_INTERVAL'))
DB_PATH = '$DB_PATH'
while True:
try:
# 收集系统指标
cpu = psutil.cpu_percent(interval=1)
mem = psutil.virtual_memory()
disk = psutil.disk_usage('/')
# 数据库统计
import sqlite3
db = sqlite3.connect(DB_PATH)
pages = db.execute('SELECT COUNT(*) FROM pages').fetchone()[0]
convs = db.execute('SELECT COUNT(*) FROM conversations').fetchone()[0]
db.close()
payload = {
'server_id': SERVER_ID,
'timestamp': time.strftime('%Y-%m-%dT%H:%M:%S+08:00'),
'cpu_percent': cpu,
'mem_used_mb': mem.used // (1024*1024),
'mem_total_mb': mem.total // (1024*1024),
'disk_percent': disk.percent,
'db_pages': pages,
'conversations': convs,
'status': 'running' if cpu < 95 else 'degraded'
}
requests.post(
f'http://{GATEKEEPER}:{PORT}/syslog',
json=payload, timeout=5
)
except Exception as e:
print(f'[SYSLOG] 上报失败: {e}')
time.sleep(INTERVAL)
PYEOF
# 作为systemd服务启动
cat > /etc/systemd/system/hldp-gatekeeper-client.service <<EOF
[Unit]
Description=HLDP Gatekeeper SYSLOG Client
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=$DEPLOY_ROOT/tools
ExecStart=/usr/bin/python3 $DEPLOY_ROOT/tools/gatekeeper_client.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable hldp-gatekeeper-client
systemctl start hldp-gatekeeper-client
log " Gatekeeper客户端: systemctl status hldp-gatekeeper-client"
log " 服务器ID: $SERVER_ID"
# ============================================================================
# Step 7: 部署完成
# ============================================================================
log "Step 7/7: ✅ 部署完成!"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " HLDP原生数据库平台 · 已就绪"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " WebUI: http://$(hostname -I | awk '{print $1}'):${WEBUI_PORT}"
echo " 数据库: $DB_PATH"
echo " 服务器ID: $SERVER_ID"
echo " SYSLOG: → ${GATEKEEPER_HOST}:${GATEKEEPER_PORT} (每${SYSLOG_INTERVAL}秒)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "下一步:"
echo " 1. 打开WebUI → 配置API Key → 开始聊天"
echo " 2. AI会读取 WELCOME 页面 → 让你给它起名字"
echo " 3. 说 '你是谁' → AI会告诉你它来自光湖"
echo " 4. 上传文件 → AI自动翻译成HLDP母语存储"
echo ""