diff --git a/.gitignore b/.gitignore index 31bb55a..d34c599 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,18 @@ -# 运行时数据(数据库与抓取的图标不纳入版本库) -/data/* -!/data/.htaccess -!/data/index.html +# --------------------------------------------------------------------------- +# 运行时数据(绝不入库) +# data/ —— SQLite 数据库等敏感数据 +# uploads/icons/* —— 抓取/上传的网站图标 +# --------------------------------------------------------------------------- +/data/ /uploads/icons/* !/uploads/icons/.gitkeep +# --------------------------------------------------------------------------- +# 部署脚本(与具体服务器、账号、路径绑定) +# 统一放在 ~/code/_tooling/ 下,不属于应用源码,不入库 +# --------------------------------------------------------------------------- +/deploy/ + # 杂项 *.db *.log diff --git a/data/.htaccess b/data/.htaccess deleted file mode 100644 index 4628e4a..0000000 --- a/data/.htaccess +++ /dev/null @@ -1,8 +0,0 @@ -# 禁止 Web 访问 data 目录(SQLite 数据库等敏感文件) - - Require all denied - - - Order allow,deny - Deny from all - diff --git a/data/index.html b/data/index.html deleted file mode 100644 index 7d6a4be..0000000 --- a/data/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/deploy/nginx-simplenav-deny-data.conf b/deploy/nginx-simplenav-deny-data.conf deleted file mode 100644 index e990f2e..0000000 --- a/deploy/nginx-simplenav-deny-data.conf +++ /dev/null @@ -1,14 +0,0 @@ -# SimpleNav 安全规则:禁止通过 Web 访问数据库等敏感目录 -# 用法:把下面几行加入宝塔站点 n.yangyq.net 的 nginx server{} 块中,然后 reload nginx。 -# (放在 /simplenav 子目录部署时用第一条;以后放根目录时用第二组。) - -# —— 子目录部署(当前测试阶段)—— -location ~ ^/simplenav/data/ { deny all; return 404; } -location ~ ^/simplenav/\.git/ { deny all; return 404; } - -# —— 以后放到根目录时启用 —— -# location ~ ^/data/ { deny all; return 404; } -# location ~ ^/\.git/ { deny all; return 404; } - -# 可选:禁止 uploads 目录执行脚本(防上传木马) -location ~* ^/simplenav/uploads/.*\.(php|phtml|phar)$ { deny all; return 404; } diff --git a/deploy/setup-simplenav-user.sh b/deploy/setup-simplenav-user.sh deleted file mode 100644 index 2548081..0000000 --- a/deploy/setup-simplenav-user.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash -# -# SimpleNav(简航)部署账号初始化脚本 -# 在服务器上以 root 身份运行一次即可(可重复运行,幂等) -# -# 作用: -# 1. 创建 simplenav 部署用户(无密码,只能密钥登录,无任何特权组) -# 2. 安装本地 ssh 公钥 -# 3. 只给 /www/wwwroot/n.yangyq.net 的读写权限(POSIX ACL,不改原有属主) -# 4. 预建应用目录 /simplenav/{data,uploads/icons} 并让部署用户与 web 用户都可读写 -# -set -euo pipefail - -# ==================== 配置 ==================== -DEPLOY_USER="simplenav" -SITE="/www/wwwroot/n.yangyq.net" -APP_SUBDIR="simplenav" # 先部署到子目录测试,通过后再放根目录 -PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOCvCGMMkyf9CHaedSdZe4XfXrS0MCW15REibldEF6U4 deploy@n.yangyq.net" -# ============================================== - -[ "$(id -u)" -eq 0 ] || { echo "错误:请用 root 运行"; exit 1; } -[ -d "$SITE" ] || { echo "错误:目录不存在 $SITE"; exit 1; } -command -v setfacl >/dev/null 2>&1 || { - echo "错误:缺少 setfacl,请先安装 acl" - echo " CentOS/RHEL/统信: yum install -y acl" - echo " Debian/Ubuntu: apt-get install -y acl" - exit 1 -} - -WEB_USER=$(stat -c '%U' "$SITE") -echo "站点目录属主(web 用户):$WEB_USER" -echo - -# ---------- 1. 创建用户 ---------- -if id "$DEPLOY_USER" >/dev/null 2>&1; then - echo "[=] 用户 $DEPLOY_USER 已存在,跳过创建" -else - useradd -m -s /bin/bash "$DEPLOY_USER" - passwd -l "$DEPLOY_USER" >/dev/null 2>&1 || true - echo "[+] 已创建用户 $DEPLOY_USER(密码锁定,仅允许密钥登录)" -fi -for g in wheel sudo adm root; do - if id -nG "$DEPLOY_USER" | tr ' ' '\n' | grep -qx "$g"; then - gpasswd -d "$DEPLOY_USER" "$g" >/dev/null 2>&1 || true - echo "[!] 已从特权组 $g 中移除 $DEPLOY_USER" - fi -done -echo "[i] 当前所属组:$(id -nG "$DEPLOY_USER")" - -# ---------- 2. 安装公钥 ---------- -install -d -m 700 -o "$DEPLOY_USER" -g "$DEPLOY_USER" "/home/$DEPLOY_USER/.ssh" -AUTH="/home/$DEPLOY_USER/.ssh/authorized_keys" -touch "$AUTH" -if grep -qF "$PUBKEY" "$AUTH"; then - echo "[=] 公钥已存在,跳过" -else - echo "$PUBKEY" >> "$AUTH" - echo "[+] 公钥已写入 authorized_keys" -fi -chmod 600 "$AUTH" -chown "$DEPLOY_USER:$DEPLOY_USER" "$AUTH" -chmod 700 "/home/$DEPLOY_USER" -echo - -# ---------- 3. 上级目录穿透 ---------- -for d in /www /www/wwwroot; do - if [ -d "$d" ]; then - other_bit=$(stat -c '%a' "$d"); other_bit=${other_bit: -1} - if [ "$other_bit" -lt 1 ]; then - setfacl -m "u:$DEPLOY_USER:x" "$d" - echo "[+] 已为 $d 补充 $DEPLOY_USER 的穿透(x)权限" - fi - fi -done - -# ---------- 4. 目录授权(ACL,不改属主) ---------- -# 站点根下可能有 root 属主文件(宝塔 .user.ini),setfacl -R 会报 EPERM,需要容错 -acl_denied="" -setfacl -R -m "u:$DEPLOY_USER:rwX" "$SITE" 2>/dev/null || acl_denied="yes" -setfacl -R -d -m "u:$DEPLOY_USER:rwX" "$SITE" 2>/dev/null || acl_denied="yes" -if [ "$WEB_USER" != "root" ] && [ "$WEB_USER" != "UNKNOWN" ]; then - setfacl -R -m "u:$WEB_USER:rwX" "$SITE" 2>/dev/null || true - setfacl -R -d -m "u:$WEB_USER:rwX" "$SITE" 2>/dev/null || true -fi -if [ -n "$acl_denied" ]; then - find "$SITE" ! -user "$WEB_USER" -print0 2>/dev/null | while IFS= read -r -d '' p; do - printf " [跳过·属主非 %s] %s\n" "$WEB_USER" "$p" - done - echo "[!] 有部分条目未能设置 ACL(通常是 root 属主的 .user.ini,不影响部署)" -fi -echo "[+] 已对 $SITE 授予 $DEPLOY_USER 与 $WEB_USER 读写权限(属主未改动)" -echo - -# ---------- 5. 预建应用可写目录 ---------- -APP="$SITE/$APP_SUBDIR" -install -d -m 775 "$APP/data" "$APP/uploads/icons" -setfacl -R -m "u:$DEPLOY_USER:rwX,u:$WEB_USER:rwX" "$APP" 2>/dev/null || true -setfacl -R -d -m "u:$DEPLOY_USER:rwX,u:$WEB_USER:rwX" "$APP" 2>/dev/null || true -echo "[+] 已预建 $APP/{data,uploads/icons},并让 $DEPLOY_USER 与 $WEB_USER 可读写" -echo - -# ---------- 6. 验收 ---------- -echo "==================== 验收 ====================" -echo "用户信息: $(id "$DEPLOY_USER")" -echo "密钥文件: $(stat -c '%a %U:%G' "$AUTH")" -echo -echo -n "以 $DEPLOY_USER 身份在 $SITE 写测试: " -if su -s /bin/sh "$DEPLOY_USER" -c "touch '$SITE/.deploy_write_test' && rm -f '$SITE/.deploy_write_test'"; then - echo "通过" -else - echo "失败(请检查上面的 ACL 输出)" -fi -echo -n "以 $DEPLOY_USER 身份读 /etc/shadow: " -if su -s /bin/sh "$DEPLOY_USER" -c "cat /etc/shadow" >/dev/null 2>&1; then - echo "竟然可读(异常)" -else - echo "被拒绝(正常)" -fi -echo "==============================================" -echo -echo "完成后请把下面这行结果发我:" -echo " sudo -l -U $DEPLOY_USER"