fix(deploy): подстановка значений в .env через python3 (sed ломался на @ в паролях)

This commit is contained in:
2026-09-19 20:32:37 +03:00
parent a556a86db7
commit c274abdfa1
+102 -81
View File
@@ -697,88 +697,109 @@ ADMIN_EMAIL=@ADMIN_EMAIL@
ADMIN_PASSWORD=@ADMIN_PASSWORD@
ENVEOF
local pairs=(
"DOMAIN=${DOMAIN}"
"FILES_DOMAIN=${FILES_DOMAIN_RESOLVED}"
"INSTANCE_NAME=${INSTANCE_NAME}"
"MAIN_GUILD_NAME=${MAIN_GUILD_NAME}"
"PROFILE=${PROFILE_RESOLVED}"
"PROXY_MODE=${PROXY_MODE}"
"IMAGE_TAG=${IMAGE_TAG}"
"APP_IMAGE=${APP_IMAGE}"
"CADDY_IMAGE_TAG=${CADDY_IMAGE_TAG}"
"LIVEKIT_IMAGE_TAG=${LIVEKIT_IMAGE_TAG}"
"LOG_LEVEL=${LOG_LEVEL}"
"TLS_ENABLED=${TLS_ENABLED}"
"SKIP_TLS=${SKIP_TLS}"
"TLS_BY_PROXY=${TLS_BY_PROXY}"
"GLCHAT_DATA_DIR=${GLCHAT_DATA_DIR}"
"CADDY_PROFILE=${CADDY_PROFILE}"
"GLCHAT_TURN_CERT_DIR=${TURN_CERT_DIR}"
"GLCHAT_APP_BIND=${APP_BIND_ADDR}"
"GLCHAT_LIVEKIT_BIND=${LIVEKIT_BIND_ADDR}"
"APP_PORT=${APP_PORT}"
"LIVEKIT_WS_PORT=${LIVEKIT_WS_PORT}"
"LIVEKIT_TCP_PORT=${LIVEKIT_TCP_PORT}"
"LIVEKIT_UDP_PORT=${LIVEKIT_UDP_PORT}"
"HTTP_PORT=${HTTP_PORT}"
"HTTPS_PORT=${HTTPS_PORT}"
"SSH_PORT=${SSH_PORT}"
"TURN_ENABLED=${TURN_ENABLED}"
"TURN_DOMAIN=${TURN_DOMAIN_RESOLVED}"
"TURN_UDP_PORT=${TURN_UDP_PORT}"
"TURN_TLS_PORT=${TURN_TLS_PORT}"
"TURN_EXTERNAL_TLS=${TURN_EXTERNAL_TLS}"
"TURN_RELAY_START=${TURN_RELAY_START}"
"TURN_RELAY_END=${TURN_RELAY_END}"
"TURN_RELAY_HOST=${TURN_RELAY_HOST_RESOLVED}"
"TURN_RELAY_PORT=${TURN_RELAY_PORT}"
"TURN_RELAY_TLS_PORT=${TURN_RELAY_TLS_PORT}"
"SESSION_PEPPER=${SESSION_PEPPER}"
"MASTER_KEY=${MASTER_KEY}"
"TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY}"
"WEBHOOK_SECRET=${WEBHOOK_SECRET}"
"LIVEKIT_API_KEY=${LIVEKIT_API_KEY}"
"LIVEKIT_API_SECRET=${LIVEKIT_API_SECRET}"
"TURN_SECRET=${TURN_SECRET_RESOLVED}"
"AGE_RECIPIENT=${AGE_RECIPIENT:-}"
"SQLITE_READ_POOL=${PROFILE_SQLITE_READ_POOL}"
"SQLITE_CACHE_SIZE=-${PROFILE_SQLITE_CACHE_MB}000"
"SQLITE_MMAP_SIZE=$((PROFILE_SQLITE_MMAP_MB * 1024 * 1024))"
"GOMAXPROCS=${PROFILE_GOMAXPROCS}"
"LRU_CACHE_ENTRIES=${PROFILE_LRU_ENTRIES}"
"MAX_UPLOAD_SIZE=$((EFFECTIVE_UPLOAD_MB * 1024 * 1024))"
"PROFILE_UPLOAD_MB=${EFFECTIVE_UPLOAD_MB}"
"APP_CPUS=${PROFILE_APP_CPUS}"
"APP_MEMORY_LIMIT=${PROFILE_APP_LIMIT}"
"LIVEKIT_CPUS=${PROFILE_LIVEKIT_CPUS}"
"LIVEKIT_MEMORY_LIMIT=${PROFILE_LIVEKIT_LIMIT}"
"LIVEKIT_MAX_PARTICIPANTS=${PROFILE_LIVEKIT_MAX_PARTICIPANTS}"
"LIVEKIT_MAX_VIDEO=${PROFILE_LIVEKIT_MAX_VIDEO}"
"LIVEKIT_DISABLE_SIMULCAST=${PROFILE_LIVEKIT_DISABLE_SIMULCAST}"
"LIVEKIT_USE_EXTERNAL_IP=${PROFILE_LIVEKIT_USE_EXTERNAL_IP}"
"SHARE_SOFT=${PROFILE_SHARE_SOFT}"
"SHARE_MAX=${PROFILE_SHARE_MAX}"
"BACKUP_KEEP=${PROFILE_BACKUP_KEEP}"
"SWAP_SIZE=${PROFILE_SWAP_GB}"
"REGISTRATION_ENABLED=${REGISTRATION_ENABLED}"
"ANTI_BOT_ENABLED=${ANTI_BOT_ENABLED:-false}"
"FAIL2BAN_ENABLED=${ENABLE_FAIL2BAN}"
"UFW_ENABLED=${ENABLE_UFW}"
"NFTABLES_ENABLED=${ENABLE_NFTABLES}"
"SSH_HARDENING=${SSH_HARDENING}"
"ADMIN_EMAIL=${ADMIN_EMAIL}"
"ADMIN_PASSWORD=${ADMIN_PASSWORD}"
)
# Подстановка через python3: значения содержат @, /, пробелы и кавычки,
# поэтому sed с произвольным разделителем ненадёжен.
command -v python3 >/dev/null 2>&1 || die "для генерации .env нужен python3"
local pairs_file
pairs_file="$(mktemp)"
cat >"$pairs_file" <<PAIREOF
DOMAIN=${DOMAIN}
FILES_DOMAIN=${FILES_DOMAIN_RESOLVED}
INSTANCE_NAME=${INSTANCE_NAME}
MAIN_GUILD_NAME=${MAIN_GUILD_NAME}
PROFILE=${PROFILE_RESOLVED}
PROXY_MODE=${PROXY_MODE}
IMAGE_TAG=${IMAGE_TAG}
APP_IMAGE=${APP_IMAGE}
CADDY_IMAGE_TAG=${CADDY_IMAGE_TAG}
LIVEKIT_IMAGE_TAG=${LIVEKIT_IMAGE_TAG}
LOG_LEVEL=${LOG_LEVEL}
TLS_ENABLED=${TLS_ENABLED}
SKIP_TLS=${SKIP_TLS}
TLS_BY_PROXY=${TLS_BY_PROXY}
GLCHAT_DATA_DIR=${GLCHAT_DATA_DIR}
CADDY_PROFILE=${CADDY_PROFILE}
GLCHAT_TURN_CERT_DIR=${TURN_CERT_DIR}
GLCHAT_APP_BIND=${APP_BIND_ADDR}
GLCHAT_LIVEKIT_BIND=${LIVEKIT_BIND_ADDR}
APP_PORT=${APP_PORT}
LIVEKIT_WS_PORT=${LIVEKIT_WS_PORT}
LIVEKIT_TCP_PORT=${LIVEKIT_TCP_PORT}
LIVEKIT_UDP_PORT=${LIVEKIT_UDP_PORT}
HTTP_PORT=${HTTP_PORT}
HTTPS_PORT=${HTTPS_PORT}
SSH_PORT=${SSH_PORT}
TURN_ENABLED=${TURN_ENABLED}
TURN_DOMAIN=${TURN_DOMAIN_RESOLVED}
TURN_UDP_PORT=${TURN_UDP_PORT}
TURN_TLS_PORT=${TURN_TLS_PORT}
TURN_EXTERNAL_TLS=${TURN_EXTERNAL_TLS}
TURN_RELAY_START=${TURN_RELAY_START}
TURN_RELAY_END=${TURN_RELAY_END}
TURN_RELAY_HOST=${TURN_RELAY_HOST_RESOLVED}
TURN_RELAY_PORT=${TURN_RELAY_PORT}
TURN_RELAY_TLS_PORT=${TURN_RELAY_TLS_PORT}
SESSION_PEPPER=${SESSION_PEPPER}
MASTER_KEY=${MASTER_KEY}
TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY}
WEBHOOK_SECRET=${WEBHOOK_SECRET}
LIVEKIT_API_KEY=${LIVEKIT_API_KEY}
LIVEKIT_API_SECRET=${LIVEKIT_API_SECRET}
TURN_SECRET=${TURN_SECRET_RESOLVED}
AGE_RECIPIENT=${AGE_RECIPIENT:-}
SQLITE_READ_POOL=${PROFILE_SQLITE_READ_POOL}
SQLITE_CACHE_SIZE=-${PROFILE_SQLITE_CACHE_MB}000
SQLITE_MMAP_SIZE=$((PROFILE_SQLITE_MMAP_MB * 1024 * 1024))
GOMAXPROCS=${PROFILE_GOMAXPROCS}
LRU_CACHE_ENTRIES=${PROFILE_LRU_ENTRIES}
MAX_UPLOAD_SIZE=$((EFFECTIVE_UPLOAD_MB * 1024 * 1024))
PROFILE_UPLOAD_MB=${EFFECTIVE_UPLOAD_MB}
APP_CPUS=${PROFILE_APP_CPUS}
APP_MEMORY_LIMIT=${PROFILE_APP_LIMIT}
LIVEKIT_CPUS=${PROFILE_LIVEKIT_CPUS}
LIVEKIT_MEMORY_LIMIT=${PROFILE_LIVEKIT_LIMIT}
LIVEKIT_MAX_PARTICIPANTS=${PROFILE_LIVEKIT_MAX_PARTICIPANTS}
LIVEKIT_MAX_VIDEO=${PROFILE_LIVEKIT_MAX_VIDEO}
LIVEKIT_DISABLE_SIMULCAST=${PROFILE_LIVEKIT_DISABLE_SIMULCAST}
LIVEKIT_USE_EXTERNAL_IP=${PROFILE_LIVEKIT_USE_EXTERNAL_IP}
SHARE_SOFT=${PROFILE_SHARE_SOFT}
SHARE_MAX=${PROFILE_SHARE_MAX}
BACKUP_KEEP=${PROFILE_BACKUP_KEEP}
SWAP_SIZE=${PROFILE_SWAP_GB}
REGISTRATION_ENABLED=${REGISTRATION_ENABLED}
ANTI_BOT_ENABLED=${ANTI_BOT_ENABLED:-false}
FAIL2BAN_ENABLED=${ENABLE_FAIL2BAN}
UFW_ENABLED=${ENABLE_UFW}
NFTABLES_ENABLED=${ENABLE_NFTABLES}
SSH_HARDENING=${SSH_HARDENING}
ADMIN_EMAIL=${ADMIN_EMAIL}
ADMIN_PASSWORD=${ADMIN_PASSWORD}
PAIREOF
local sed_args=()
local pair key value
for pair in "${pairs[@]}"; do
key="${pair%%=*}"
value="${pair#*=}"
sed_args+=(-e "s@@${key}@@${value}@g")
done
sed -i.bak "${sed_args[@]}" "$tmp"
python3 - "$tmp" "$pairs_file" <<'PYEOF'
import sys
template_path, pairs_path = sys.argv[1], sys.argv[2]
template = open(template_path, encoding="utf-8").read()
values = {}
for line in open(pairs_path, encoding="utf-8"):
line = line.rstrip("
")
if "=" not in line:
continue
key, value = line.split("=", 1)
values[key] = value
for key, value in values.items():
template = template.replace("@" + key + "@", value)
leftovers = [t for t in __import__("re").findall(r"@[A-Z_]{2,}@", template)]
open(template_path, "w", encoding="utf-8").write(template)
if leftovers:
print("незаполненные плейсхолдеры: " + ", ".join(sorted(set(leftovers))), file=sys.stderr)
sys.exit(1)
PYEOF
rm -f "$pairs_file"
install -m 600 "$tmp" "$GLCHAT_ENV_FILE"
rm -f "$tmp" "$tmp.bak"