پیشنمایش خصوصی: سایت آنلاین اما غیرعمومی تا زمان انتشار
- گیت ورود Traefik (Basic Auth) روی همه مسیرها: سایت، API، تصاویر و چت — بدون رمز فقط ۴۰۱ - لایه دوم noindex: هدر X-Robots-Tag روی همه پاسخها + robots.txt مسدودکننده + نقشه سایت خالی - اسکریپت scripts/preview-mode.sh on|off|status — ساخت خودکار نام کاربری/رمز و هماهنگکردن .env - دو دامنه (DOMAIN + DOMAIN_ALIAS) با گواهی TLS و ریدایرکت ۳۰۱ دامنه دوم به اصلی در زمان انتشار - اسکیمای FAQPage در پوسته سئوی سمت سرور (فارسی و انگلیسی) برای خزندههای بدون جاوااسکریپت - مستندسازی جریان پیشنمایش و چکلیست انتشار در README و .env.example
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env bash
|
||||
# پیشنمایش خصوصی و انتشار عمومی سایت.
|
||||
#
|
||||
# bash scripts/preview-mode.sh status # وضعیت فعلی
|
||||
# bash scripts/preview-mode.sh on # سایت آنلاین ولی خصوصی (گیت ورود + noindex)
|
||||
# bash scripts/preview-mode.sh off # انتشار عمومی (حذف گیت + اجازه ایندکس)
|
||||
#
|
||||
# در حالت «on» کل سایت پشت Basic Auth است: تیم با نام کاربری/رمز مشترک وارد میشود،
|
||||
# محتوا را در همان سایت آنلاین ویرایش میکند (ویرایش درجای ایمیل/تلفن و بقیه محتوا)،
|
||||
# اما نه عموم به سایت دسترسی دارند و نه گوگل چیزی ایندکس میکند.
|
||||
#
|
||||
# پس از هر تغییر، استک را دوباره بالا بیاورید:
|
||||
# bash scripts/stack.sh deploy-prod
|
||||
#
|
||||
# با «فعال شدن» اولین بار، نام کاربری/رمز ساخته و در .env ذخیره میشود
|
||||
# (پیشفرض: preview / یک رمز تصادفی — در خروجی چاپ میشود).
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
ENV_FILE=.env
|
||||
[ -f "$ENV_FILE" ] || { echo "فایل .env پیدا نشد — اول bash scripts/gen-env.sh" >&2; exit 1; }
|
||||
|
||||
# مقدار فعلی یک کلید در .env (یا خالی)
|
||||
env_get() {
|
||||
local key="$1"
|
||||
sed -n "s/^${key}=//p" "$ENV_FILE" | tail -1
|
||||
}
|
||||
|
||||
# تنظیم/جایگزینی یک کلید در .env (بدون آسیب به بقیه خطوط)
|
||||
env_set() {
|
||||
local key="$1" value="$2"
|
||||
if grep -q "^${key}=" "$ENV_FILE"; then
|
||||
# جداکننده | تا کاراکترهای ویژه مقدار (مثل / و $) مشکلی نسازند
|
||||
python - "$ENV_FILE" "$key" "$value" <<'PY'
|
||||
import io, sys
|
||||
path, key, value = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
lines = io.open(path, encoding="utf-8").read().split("\n")
|
||||
out = [f"{key}={value}" if line.startswith(f"{key}=") else line for line in lines]
|
||||
io.open(path, "w", encoding="utf-8", newline="\n").write("\n".join(out))
|
||||
PY
|
||||
else
|
||||
printf '\n%s=%s\n' "$key" "$value" >> "$ENV_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# ساخت هش htpasswd — اول با openssl، در نبودش با ایمیج httpd (Docker لازم است)
|
||||
make_htpasswd() {
|
||||
local user="$1" pass="$2" hash
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
hash=$(openssl passwd -apr1 "$pass")
|
||||
else
|
||||
hash=$(docker run --rm httpd:2.4-alpine htpasswd -nbB "$user" "$pass" | cut -d: -f2)
|
||||
fi
|
||||
printf '%s:%s' "$user" "$hash"
|
||||
}
|
||||
|
||||
# رمز تصادفی خوانا (بدون نویسههای گیجکننده)
|
||||
random_password() {
|
||||
python - <<'PY'
|
||||
import secrets, string
|
||||
alphabet = string.ascii_letters + string.digits
|
||||
print("".join(secrets.choice(alphabet) for _ in range(16)))
|
||||
PY
|
||||
}
|
||||
|
||||
PREVIEW_MIDDLEWARES_VALUE="preview-auth@docker,preview-noindex@docker"
|
||||
|
||||
case "${1:-status}" in
|
||||
on)
|
||||
users="$(env_get PREVIEW_AUTH_USERS)"
|
||||
if [ -z "$users" ]; then
|
||||
password="$(random_password)"
|
||||
users="$(make_htpasswd preview "$password")"
|
||||
env_set PREVIEW_AUTH_USERS "$users"
|
||||
echo "نام کاربری/رمز پیشنمایش ساخته شد:"
|
||||
echo " کاربر: preview"
|
||||
echo " رمز: $password"
|
||||
echo " (این رمز فقط همین یکبار چاپ میشود — در .env ذخیره شده است)"
|
||||
echo ""
|
||||
fi
|
||||
env_set PREVIEW_MODE on
|
||||
env_set PREVIEW_MIDDLEWARES "$PREVIEW_MIDDLEWARES_VALUE"
|
||||
# در پیشنمایش، دامنه دوم به اصلی ریدایرکت نمیشود تا هر دو قابل بررسی باشند
|
||||
env_set ALIAS_REDIRECT_MIDDLEWARES ""
|
||||
echo "پیشنمایش خصوصی فعال شد — سایت آنلاین است، ورود با نام کاربری/رمز، بدون ایندکس."
|
||||
echo "برای اعمال: bash scripts/stack.sh deploy-prod"
|
||||
;;
|
||||
|
||||
off)
|
||||
env_set PREVIEW_MODE off
|
||||
env_set PREVIEW_MIDDLEWARES ""
|
||||
# در انتشار، دامنه دوم به اصلی ریدایرکت میشود تا محتوای تکراری ایجاد نشود
|
||||
env_set ALIAS_REDIRECT_MIDDLEWARES "to-primary@docker"
|
||||
echo "حالت انتشار عمومی فعال شد — گیت ورود حذف و ایندکس مجاز میشود."
|
||||
echo "پس از deploy، نقشه سایت را در Search Console ثبت کنید:"
|
||||
echo " https://\$(grep '^DOMAIN=' .env | cut -d= -f2)/sitemap.xml"
|
||||
echo "برای اعمال: bash scripts/stack.sh deploy-prod"
|
||||
;;
|
||||
|
||||
status)
|
||||
mode="$(env_get PREVIEW_MODE)"
|
||||
mws="$(env_get PREVIEW_MIDDLEWARES)"
|
||||
alias_mws="$(env_get ALIAS_REDIRECT_MIDDLEWARES)"
|
||||
if [ "$mode" = "on" ]; then
|
||||
echo "وضعیت: پیشنمایش خصوصی (آنلاین، غیرعمومی، noindex)"
|
||||
elif [ "$mode" = "off" ]; then
|
||||
echo "وضعیت: انتشار عمومی"
|
||||
else
|
||||
echo "وضعیت: تعییننشده (PREVIEW_MODE=${mode:-خالی}) — پیشفرض compose: off"
|
||||
fi
|
||||
echo " PREVIEW_MIDDLEWARES=${mws:-(خالی — بدون گیت)}"
|
||||
echo " ALIAS_REDIRECT_MIDDLEWARES=${alias_mws:-(خالی — بدون ریدایرکت دامنه دوم)}"
|
||||
if [ -n "$(env_get PREVIEW_AUTH_USERS)" ]; then
|
||||
echo " کاربر پیشنمایش: $(env_get PREVIEW_AUTH_USERS | cut -d: -f1)"
|
||||
else
|
||||
echo " کاربر پیشنمایش: ساخته نشده (اولین «on» میسازد)"
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "استفاده: bash scripts/preview-mode.sh [on|off|status]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user