fix: panel init without werkzeug; stop tracking .env

Use stdlib pbkdf2 for admin passwords so init_db works reliably.
Remove .env from git to avoid pull conflicts on VPS.
Verify flask install before database init.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-16 09:17:43 +08:00
parent 042ae5a422
commit 59a88a9afe
4 changed files with 31 additions and 20 deletions
-14
View File
@@ -1,14 +0,0 @@
# VPS 环境配置(66.hyf2.cc @ 47.76.87.111
# 部署路径:/opt/jiedian
VPS_IP=47.76.87.111
DOMAIN=66.hyf2.cc
ACME_EMAIL=admin@hyf2.cc
REALITY_SERVER_NAME=www.microsoft.com
PANEL_USERNAME=dekun
PANEL_PASSWORD=Woaini521@
REALITY_PRIVATE_KEY=IPKtaw1aVb4fS0TPcimu8zwaVGml-JJ5H1rj-_TFQHM
REALITY_PUBLIC_KEY=51H_ikqYdDRgCpjq3pvMYNbqrX8S3zuow1UEjqTN-nI
REALITY_SHORT_ID=e126b4ef9d36adfc
+3
View File
@@ -2,6 +2,9 @@
client/generated/ client/generated/
data/ data/
panel/venv/ panel/venv/
# 本地环境配置(勿提交密钥)
.env
# 临时文件 # 临时文件
*.log *.log
.DS_Store .DS_Store
+25 -6
View File
@@ -1,16 +1,36 @@
"""SQLite 数据库:管理员账号与节点。""" """SQLite 数据库:管理员账号与节点。"""
from __future__ import annotations from __future__ import annotations
import hashlib
import hmac
import os import os
import secrets import secrets
import sqlite3 import sqlite3
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from werkzeug.security import check_password_hash, generate_password_hash
ROOT = Path(os.environ.get("JIEDIAN_ROOT", Path(__file__).resolve().parents[1])) ROOT = Path(os.environ.get("JIEDIAN_ROOT", Path(__file__).resolve().parents[1]))
DB_FILE = ROOT / "data" / "nodes.db" DB_FILE = ROOT / "data" / "nodes.db"
_PBKDF2_ITERATIONS = 600000
def _hash_password(password: str) -> str:
salt = secrets.token_hex(16)
digest = hashlib.pbkdf2_hmac(
"sha256", password.encode(), salt.encode(), _PBKDF2_ITERATIONS
)
return f"pbkdf2:sha256:{_PBKDF2_ITERATIONS}${salt}${digest.hex()}"
def _verify_password(stored: str, password: str) -> bool:
if not stored or stored.count("$") < 2:
return False
method, salt, expected = stored.split("$", 2)
if not method.startswith("pbkdf2:sha256:"):
return False
iterations = int(method.rsplit(":", 1)[1])
digest = hashlib.pbkdf2_hmac("sha256", password.encode(), salt.encode(), iterations)
return hmac.compare_digest(digest.hex(), expected)
def connect() -> sqlite3.Connection: def connect() -> sqlite3.Connection:
@@ -49,7 +69,7 @@ def init_db(env: dict[str, str]) -> None:
conn.execute("DELETE FROM admin") conn.execute("DELETE FROM admin")
conn.execute( conn.execute(
"INSERT INTO admin (username, password_hash) VALUES (?, ?)", "INSERT INTO admin (username, password_hash) VALUES (?, ?)",
(username, generate_password_hash(password)), (username, _hash_password(password)),
) )
count = conn.execute("SELECT COUNT(*) AS c FROM nodes").fetchone()["c"] count = conn.execute("SELECT COUNT(*) AS c FROM nodes").fetchone()["c"]
@@ -72,7 +92,7 @@ def verify_admin(username: str, password: str) -> bool:
conn.close() conn.close()
if row is None: if row is None:
return False return False
return check_password_hash(row["password_hash"], password) return _verify_password(row["password_hash"], password)
def list_nodes() -> list[dict]: def list_nodes() -> list[dict]:
@@ -117,7 +137,6 @@ def node_count() -> int:
def _generate_credentials() -> tuple[str, str]: def _generate_credentials() -> tuple[str, str]:
sb = "sing-box" uuid = subprocess.check_output(["sing-box", "generate", "uuid"], text=True).strip()
uuid = subprocess.check_output([sb, "generate", "uuid"], text=True).strip()
hy2 = secrets.token_urlsafe(18)[:24] hy2 = secrets.token_urlsafe(18)[:24]
return uuid, hy2 return uuid, hy2
+3
View File
@@ -140,7 +140,10 @@ nginx -t && systemctl enable nginx && systemctl restart nginx
log "安装 Python 面板依赖 ..." log "安装 Python 面板依赖 ..."
python3 -m venv "$ROOT_DIR/panel/venv" python3 -m venv "$ROOT_DIR/panel/venv"
"$ROOT_DIR/panel/venv/bin/pip" install -q --upgrade pip
"$ROOT_DIR/panel/venv/bin/pip" install -q -r "$ROOT_DIR/panel/requirements.txt" "$ROOT_DIR/panel/venv/bin/pip" install -q -r "$ROOT_DIR/panel/requirements.txt"
"$ROOT_DIR/panel/venv/bin/python" -c "import flask" \
|| err "面板依赖安装失败,请检查网络后重试"
log "初始化节点数据库 ..." log "初始化节点数据库 ..."
"$ROOT_DIR/panel/venv/bin/python" "$ROOT_DIR/panel/init_db.py" "$ROOT_DIR/panel/venv/bin/python" "$ROOT_DIR/panel/init_db.py"