guanghu-ice-heart/server-tools/lake-lamp-authz/install-architecture-provisioner.sh

224 lines
7.8 KiB
Shell
Raw Normal View History

#!/usr/bin/env bash
set -euo pipefail
if [[ ${EUID} -ne 0 ]]; then
echo "run as root" >&2
exit 1
fi
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
install_root=/opt/guanghu/lake-lamp-authz
state_root=/var/lib/guanghu/architecture-provision
secret_root=/etc/guanghu/secrets/lake-lamp
authorization_env=$secret_root/authorization.env
provider_registry=/etc/guanghu/secrets/hololake-ai-providers.json
knowledge_repo=/var/lib/guanghu/personas/guanghu/hlcc-v16.0.1/data/repositories/bingshuo/hololake-knowledge-base.git
stamp=$(date -u +%Y%m%dT%H%M%SZ)
backup_root=$state_root/manual-backups/lake-lamp-authz-$stamp
required_source_files=(
server.js
workorder-manager.js
map-gate.js
smtp-mailer.js
action-client.js
architecture-provision-broker.js
deployment-event.js
deployment-event-worker.js
deployment-source-policy.js
guanghu-router.js
repo-push-broker.js
hololake-session.js
hololake-capabilities.js
)
for file in "${required_source_files[@]}" lake-lamp-authz.service lake-lamp-architecture-provision.service lake-lamp-deployment-event-worker.service; do
[[ -f "$script_dir/$file" ]] || {
echo "missing required release file: $file" >&2
exit 1
}
done
install -d -m 0700 "$backup_root"
[[ ! -e "$install_root" ]] || cp -a "$install_root" "$backup_root/install-root"
for existing in \
/etc/systemd/system/lake-lamp-authz.service \
/etc/systemd/system/lake-lamp-architecture-provision.service \
/etc/systemd/system/lake-lamp-deployment-event-worker.service \
"$authorization_env" \
"$provider_registry"; do
if [[ -e "$existing" ]]; then
destination=$backup_root/existing${existing}
install -d -m 0700 "$(dirname "$destination")"
cp -a "$existing" "$destination"
fi
done
rollback() {
set +e
if [[ -d "$backup_root/install-root" ]]; then
rm -rf -- "$install_root"
cp -a "$backup_root/install-root" "$install_root"
fi
for existing in \
/etc/systemd/system/lake-lamp-authz.service \
/etc/systemd/system/lake-lamp-architecture-provision.service \
/etc/systemd/system/lake-lamp-deployment-event-worker.service \
"$authorization_env" \
"$provider_registry"; do
saved=$backup_root/existing${existing}
if [[ -e "$saved" ]]; then
install -d -m 0755 "$(dirname "$existing")"
cp -a "$saved" "$existing"
elif [[ "$existing" = "$provider_registry" ]]; then
rm -f -- "$existing"
fi
done
systemctl daemon-reload
systemctl restart lake-lamp-authz.service
systemctl restart lake-lamp-architecture-provision.service
systemctl restart lake-lamp-deployment-event-worker.service
}
trap 'rc=$?; if [[ $rc -ne 0 ]]; then rollback; fi; exit "$rc"' EXIT
install -d -m 0755 "$install_root"
for file in "${required_source_files[@]}"; do
install -m 0644 "$script_dir/$file" "$install_root/$file"
done
install -m 0644 "$script_dir/lake-lamp-authz.service" /etc/systemd/system/lake-lamp-authz.service
install -m 0644 "$script_dir/lake-lamp-architecture-provision.service" /etc/systemd/system/lake-lamp-architecture-provision.service
install -m 0644 "$script_dir/lake-lamp-deployment-event-worker.service" /etc/systemd/system/lake-lamp-deployment-event-worker.service
install -d -m 0700 "$state_root"
install -d -m 0750 /var/lib/guanghu/deployment-events
install -d -m 0700 /var/lib/guanghu/deployment-events/receipts
install -d -m 0755 /opt/guanghu/architecture-releases
install -d -m 0755 /etc/guanghu/lake-lamp
install -d -m 0750 "$secret_root"
if [[ ! -e /etc/guanghu/lake-lamp/deployment-repositories.json ]]; then
install -m 0644 "$script_dir/deployment-repositories.example.json" /etc/guanghu/lake-lamp/deployment-repositories.json
fi
[[ -f "$authorization_env" ]] || {
echo "private authorization environment is missing" >&2
exit 1
}
append_setting() {
local key=$1
local value=$2
if ! grep -q "^${key}=" "$authorization_env"; then
printf '%s=%s\n' "$key" "$value" >>"$authorization_env"
fi
}
if ! grep -q '^HOLOLAKE_SESSION_PEPPER=' "$authorization_env"; then
append_setting HOLOLAKE_SESSION_PEPPER "$(/usr/bin/openssl rand -hex 32)"
fi
append_setting HOLOLAKE_SESSION_STATE_FILE /var/lib/guanghu/lake-lamp-authz/hololake-sessions.json
append_setting HOLOLAKE_OTP_TTL 600
append_setting HOLOLAKE_ACCOUNT_SESSION_TTL 86400
append_setting HOLOLAKE_OTP_REQUEST_LIMIT 6
append_setting HOLOLAKE_KNOWLEDGE_REPOSITORY_PATH "$knowledge_repo"
append_setting HOLOLAKE_KNOWLEDGE_MAX_ARCHIVE_BYTES 134217728
append_setting HOLOLAKE_AI_PROVIDERS_FILE "$provider_registry"
chmod 0600 "$authorization_env"
if [[ ! -f "$provider_registry" ]]; then
/usr/bin/python3 - "$provider_registry" <<'PY'
import json
import pathlib
import sys
destination = pathlib.Path(sys.argv[1])
values = {}
roots = (
pathlib.Path("/etc/guanghu/secrets"),
pathlib.Path("/etc/guanghu/persona-secrets"),
)
for root in roots:
if not root.exists():
continue
for file in root.rglob("*.env"):
try:
for raw in file.read_text().splitlines():
line = raw.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
values.setdefault(key.strip(), value.strip().strip("'\""))
except (OSError, UnicodeError):
continue
providers = {}
if values.get("DEEPSEEK_API_KEY"):
providers["deepseek"] = {
"name": "DeepSeek",
"base_url": "https://api.deepseek.com",
"api_key": values["DEEPSEEK_API_KEY"],
"models": ["deepseek-chat", "deepseek-reasoner"],
}
elif values.get("OPENAI_API_KEY"):
providers["openai"] = {
"name": "OpenAI",
"base_url": "https://api.openai.com/v1",
"api_key": values["OPENAI_API_KEY"],
"models": ["gpt-4.1-mini"],
}
elif values.get("DASHSCOPE_API_KEY"):
providers["qwen"] = {
"name": "Qwen",
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"api_key": values["DASHSCOPE_API_KEY"],
"models": ["qwen-plus"],
}
if providers:
destination.parent.mkdir(parents=True, exist_ok=True)
temporary = destination.with_suffix(".tmp")
temporary.write_text(json.dumps({
"schema": "guanghu.hololake-ai-providers/v1",
"providers": providers,
}, ensure_ascii=False, indent=2) + "\n")
temporary.chmod(0o640)
temporary.replace(destination)
PY
fi
if [[ -f "$provider_registry" ]]; then
chown root:guanghu-authz "$provider_registry"
chmod 0640 "$provider_registry"
fi
[[ -d "$knowledge_repo" ]] || {
echo "registered HoloLake knowledge repository is missing" >&2
exit 1
}
command -v setfacl >/dev/null 2>&1 || {
echo "setfacl is required for private knowledge repository access" >&2
exit 1
}
setfacl -R -m u:guanghu-authz:rX "$knowledge_repo"
setfacl -R -d -m u:guanghu-authz:rX "$knowledge_repo"
runuser -u guanghu-authz -- git --git-dir="$knowledge_repo" rev-parse --verify refs/heads/main >/dev/null
systemctl daemon-reload
systemctl enable --now lake-lamp-architecture-provision.service
systemctl restart lake-lamp-authz.service
systemctl enable --now lake-lamp-deployment-event-worker.service
systemctl is-active --quiet lake-lamp-architecture-provision.service
systemctl is-active --quiet lake-lamp-authz.service
systemctl is-active --quiet lake-lamp-deployment-event-worker.service
health=$(/usr/bin/curl -fsS --max-time 10 http://127.0.0.1:3921/health)
/usr/bin/node -e '
const health = JSON.parse(process.argv[1]);
if (!health.ok || health.service !== "lake-lamp-authz") process.exit(1);
if (!health.hololake_mobile || !health.hololake_mobile.email_session || !health.hololake_mobile.knowledge_snapshot) process.exit(1);
' "$health"
if [[ -f "$provider_registry" ]]; then
/usr/bin/node -e '
const health = JSON.parse(process.argv[1]);
if (!health.hololake_mobile || !health.hololake_mobile.ai_gateway) process.exit(1);
' "$health"
fi
trap - EXIT
printf 'HOLOLAKE_MOBILE_CAPABILITIES_INSTALLED backup=%s\n' "$backup_root"