迁入通用节点部署工具、离线交付页生成器和共用技能,隔离真实配置与交付产物。统一 Codex 与 Claude Code 开发约定,补充节点迁移与运维文档。 完善 FINAL、策略组引用、输入校验、Surge 字段编码与 AI DNS 例外保护,增加隔离测试和订阅验证工具。 验证:全量类型检查、44 项单测、前端构建、脚本语法、技能入口与凭据隔离检查均通过。
78 lines
3.3 KiB
Python
Executable File
78 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Runs ON the box with aaPanel's bundled python:
|
|
/www/server/panel/pyenv/bin/python /root/_aapanel-sites.py
|
|
Registers 4 domains as panel-native sites (AddSite + SetSSL + CreateProxy + HttpToHttps)
|
|
so they are visible/manageable in the aaPanel UI (never hand-write vhosts — the UI won't
|
|
see those). Reads subdomain labels + cover paths from environment variables.
|
|
"""
|
|
import json, os, sys
|
|
|
|
sys.path.insert(0, "/www/server/panel")
|
|
sys.path.insert(0, "/www/server/panel/class")
|
|
sys.path.insert(0, "/www/server/panel/class_v2") # aaPanel 7.x moved some modules here (e.g. theme_config)
|
|
import public # noqa: E402
|
|
import panelSite # noqa: E402
|
|
|
|
ROOT = os.environ["DOMAIN_ROOT"]
|
|
SUB_PANEL = os.environ["SUB_PANEL"]
|
|
SUB_XUI = os.environ["SUB_XUI"]
|
|
SUB_COVER = os.environ["SUB_COVER"]
|
|
XUI_PORT = os.environ.get("XUI_PORT", "14533")
|
|
PANEL_PORT = public.readFile("/www/server/panel/data/port.pl").strip()
|
|
|
|
D_LANDING = ROOT
|
|
D_COVER = "%s.%s" % (SUB_COVER, ROOT)
|
|
D_XUI = "%s.%s" % (SUB_XUI, ROOT)
|
|
D_PANEL = "%s.%s" % (SUB_PANEL, ROOT)
|
|
|
|
site = panelSite.panelSite()
|
|
|
|
SITES = [
|
|
(D_LANDING, "/www/wwwroot/" + D_LANDING, "edge landing"),
|
|
(D_COVER, "/www/wwwroot/" + D_COVER, "node cover"),
|
|
(D_XUI, "/www/wwwroot/" + D_XUI, "3x-ui panel proxy"),
|
|
(D_PANEL, "/www/wwwroot/" + D_PANEL, "aaPanel proxy"),
|
|
]
|
|
|
|
# 3 protocols x 2 egress = 6 cover proxy rules, all on the same D_COVER site/cert.
|
|
_PROTOCOLS = ["VMESS", "TROJAN", "SS"]
|
|
PROXIES = [
|
|
("xui-panel", D_XUI, "/", "http://127.0.0.1:%s" % XUI_PORT, D_XUI),
|
|
("aapanel", D_PANEL, "/", "https://127.0.0.1:%s" % PANEL_PORT, D_PANEL),
|
|
]
|
|
for proto in _PROTOCOLS:
|
|
for suffix in ("DIRECT", "WARP"):
|
|
path = os.environ["WS_PATH_%s_%s" % (proto, suffix)]
|
|
port = os.environ["PORT_%s_%s" % (proto, suffix)]
|
|
PROXIES.append(("cover-%s-%s" % (proto.lower(), suffix.lower()), D_COVER, path,
|
|
"http://127.0.0.1:%s" % port, D_COVER))
|
|
|
|
|
|
def obj(d):
|
|
return public.to_dict_obj(d)
|
|
|
|
|
|
def main():
|
|
for name, path, ps in SITES:
|
|
get = obj({"webname": json.dumps({"domain": name, "domainlist": [], "count": 0}),
|
|
"path": path, "port": "80", "version": "00", "ps": ps,
|
|
"type_id": "0", "type": "static", "ftp": "false", "sql": "false"})
|
|
print("AddSite", name, "->", site.AddSite(get).get("siteStatus", "?"))
|
|
for name, _p, _ps in SITES:
|
|
cdir = "/www/server/panel/vhost/cert/" + name
|
|
key = public.readFile(cdir + "/privkey.pem"); csr = public.readFile(cdir + "/fullchain.pem")
|
|
if key and csr:
|
|
print("SetSSL", name, "->", site.SetSSL(obj({"siteName": name, "key": key, "csr": csr})).get("status"))
|
|
for pname, sname, pdir, target, todomain in PROXIES:
|
|
get = obj({"proxyname": pname, "sitename": sname, "proxydir": pdir, "proxysite": target,
|
|
"todomain": todomain, "type": "1", "cache": "0", "subfilter": "[]",
|
|
"advanced": "0", "cachetime": "1", "nocheck": "1"})
|
|
print("CreateProxy", sname, pdir, "->", site.CreateProxy(get).get("status"))
|
|
for name, _p, _ps in SITES:
|
|
print("HttpToHttps", name, "->", site.HttpToHttps(obj({"siteName": name})).get("status"))
|
|
print("DONE — reload nginx: /etc/init.d/nginx reload")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|