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@ ADMIN_PASSWORD=@ADMIN_PASSWORD@
ENVEOF ENVEOF
local pairs=( # Подстановка через python3: значения содержат @, /, пробелы и кавычки,
"DOMAIN=${DOMAIN}" # поэтому sed с произвольным разделителем ненадёжен.
"FILES_DOMAIN=${FILES_DOMAIN_RESOLVED}" command -v python3 >/dev/null 2>&1 || die "для генерации .env нужен python3"
"INSTANCE_NAME=${INSTANCE_NAME}" local pairs_file
"MAIN_GUILD_NAME=${MAIN_GUILD_NAME}" pairs_file="$(mktemp)"
"PROFILE=${PROFILE_RESOLVED}" cat >"$pairs_file" <<PAIREOF
"PROXY_MODE=${PROXY_MODE}" DOMAIN=${DOMAIN}
"IMAGE_TAG=${IMAGE_TAG}" FILES_DOMAIN=${FILES_DOMAIN_RESOLVED}
"APP_IMAGE=${APP_IMAGE}" INSTANCE_NAME=${INSTANCE_NAME}
"CADDY_IMAGE_TAG=${CADDY_IMAGE_TAG}" MAIN_GUILD_NAME=${MAIN_GUILD_NAME}
"LIVEKIT_IMAGE_TAG=${LIVEKIT_IMAGE_TAG}" PROFILE=${PROFILE_RESOLVED}
"LOG_LEVEL=${LOG_LEVEL}" PROXY_MODE=${PROXY_MODE}
"TLS_ENABLED=${TLS_ENABLED}" IMAGE_TAG=${IMAGE_TAG}
"SKIP_TLS=${SKIP_TLS}" APP_IMAGE=${APP_IMAGE}
"TLS_BY_PROXY=${TLS_BY_PROXY}" CADDY_IMAGE_TAG=${CADDY_IMAGE_TAG}
"GLCHAT_DATA_DIR=${GLCHAT_DATA_DIR}" LIVEKIT_IMAGE_TAG=${LIVEKIT_IMAGE_TAG}
"CADDY_PROFILE=${CADDY_PROFILE}" LOG_LEVEL=${LOG_LEVEL}
"GLCHAT_TURN_CERT_DIR=${TURN_CERT_DIR}" TLS_ENABLED=${TLS_ENABLED}
"GLCHAT_APP_BIND=${APP_BIND_ADDR}" SKIP_TLS=${SKIP_TLS}
"GLCHAT_LIVEKIT_BIND=${LIVEKIT_BIND_ADDR}" TLS_BY_PROXY=${TLS_BY_PROXY}
"APP_PORT=${APP_PORT}" GLCHAT_DATA_DIR=${GLCHAT_DATA_DIR}
"LIVEKIT_WS_PORT=${LIVEKIT_WS_PORT}" CADDY_PROFILE=${CADDY_PROFILE}
"LIVEKIT_TCP_PORT=${LIVEKIT_TCP_PORT}" GLCHAT_TURN_CERT_DIR=${TURN_CERT_DIR}
"LIVEKIT_UDP_PORT=${LIVEKIT_UDP_PORT}" GLCHAT_APP_BIND=${APP_BIND_ADDR}
"HTTP_PORT=${HTTP_PORT}" GLCHAT_LIVEKIT_BIND=${LIVEKIT_BIND_ADDR}
"HTTPS_PORT=${HTTPS_PORT}" APP_PORT=${APP_PORT}
"SSH_PORT=${SSH_PORT}" LIVEKIT_WS_PORT=${LIVEKIT_WS_PORT}
"TURN_ENABLED=${TURN_ENABLED}" LIVEKIT_TCP_PORT=${LIVEKIT_TCP_PORT}
"TURN_DOMAIN=${TURN_DOMAIN_RESOLVED}" LIVEKIT_UDP_PORT=${LIVEKIT_UDP_PORT}
"TURN_UDP_PORT=${TURN_UDP_PORT}" HTTP_PORT=${HTTP_PORT}
"TURN_TLS_PORT=${TURN_TLS_PORT}" HTTPS_PORT=${HTTPS_PORT}
"TURN_EXTERNAL_TLS=${TURN_EXTERNAL_TLS}" SSH_PORT=${SSH_PORT}
"TURN_RELAY_START=${TURN_RELAY_START}" TURN_ENABLED=${TURN_ENABLED}
"TURN_RELAY_END=${TURN_RELAY_END}" TURN_DOMAIN=${TURN_DOMAIN_RESOLVED}
"TURN_RELAY_HOST=${TURN_RELAY_HOST_RESOLVED}" TURN_UDP_PORT=${TURN_UDP_PORT}
"TURN_RELAY_PORT=${TURN_RELAY_PORT}" TURN_TLS_PORT=${TURN_TLS_PORT}
"TURN_RELAY_TLS_PORT=${TURN_RELAY_TLS_PORT}" TURN_EXTERNAL_TLS=${TURN_EXTERNAL_TLS}
"SESSION_PEPPER=${SESSION_PEPPER}" TURN_RELAY_START=${TURN_RELAY_START}
"MASTER_KEY=${MASTER_KEY}" TURN_RELAY_END=${TURN_RELAY_END}
"TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY}" TURN_RELAY_HOST=${TURN_RELAY_HOST_RESOLVED}
"WEBHOOK_SECRET=${WEBHOOK_SECRET}" TURN_RELAY_PORT=${TURN_RELAY_PORT}
"LIVEKIT_API_KEY=${LIVEKIT_API_KEY}" TURN_RELAY_TLS_PORT=${TURN_RELAY_TLS_PORT}
"LIVEKIT_API_SECRET=${LIVEKIT_API_SECRET}" SESSION_PEPPER=${SESSION_PEPPER}
"TURN_SECRET=${TURN_SECRET_RESOLVED}" MASTER_KEY=${MASTER_KEY}
"AGE_RECIPIENT=${AGE_RECIPIENT:-}" TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY}
"SQLITE_READ_POOL=${PROFILE_SQLITE_READ_POOL}" WEBHOOK_SECRET=${WEBHOOK_SECRET}
"SQLITE_CACHE_SIZE=-${PROFILE_SQLITE_CACHE_MB}000" LIVEKIT_API_KEY=${LIVEKIT_API_KEY}
"SQLITE_MMAP_SIZE=$((PROFILE_SQLITE_MMAP_MB * 1024 * 1024))" LIVEKIT_API_SECRET=${LIVEKIT_API_SECRET}
"GOMAXPROCS=${PROFILE_GOMAXPROCS}" TURN_SECRET=${TURN_SECRET_RESOLVED}
"LRU_CACHE_ENTRIES=${PROFILE_LRU_ENTRIES}" AGE_RECIPIENT=${AGE_RECIPIENT:-}
"MAX_UPLOAD_SIZE=$((EFFECTIVE_UPLOAD_MB * 1024 * 1024))" SQLITE_READ_POOL=${PROFILE_SQLITE_READ_POOL}
"PROFILE_UPLOAD_MB=${EFFECTIVE_UPLOAD_MB}" SQLITE_CACHE_SIZE=-${PROFILE_SQLITE_CACHE_MB}000
"APP_CPUS=${PROFILE_APP_CPUS}" SQLITE_MMAP_SIZE=$((PROFILE_SQLITE_MMAP_MB * 1024 * 1024))
"APP_MEMORY_LIMIT=${PROFILE_APP_LIMIT}" GOMAXPROCS=${PROFILE_GOMAXPROCS}
"LIVEKIT_CPUS=${PROFILE_LIVEKIT_CPUS}" LRU_CACHE_ENTRIES=${PROFILE_LRU_ENTRIES}
"LIVEKIT_MEMORY_LIMIT=${PROFILE_LIVEKIT_LIMIT}" MAX_UPLOAD_SIZE=$((EFFECTIVE_UPLOAD_MB * 1024 * 1024))
"LIVEKIT_MAX_PARTICIPANTS=${PROFILE_LIVEKIT_MAX_PARTICIPANTS}" PROFILE_UPLOAD_MB=${EFFECTIVE_UPLOAD_MB}
"LIVEKIT_MAX_VIDEO=${PROFILE_LIVEKIT_MAX_VIDEO}" APP_CPUS=${PROFILE_APP_CPUS}
"LIVEKIT_DISABLE_SIMULCAST=${PROFILE_LIVEKIT_DISABLE_SIMULCAST}" APP_MEMORY_LIMIT=${PROFILE_APP_LIMIT}
"LIVEKIT_USE_EXTERNAL_IP=${PROFILE_LIVEKIT_USE_EXTERNAL_IP}" LIVEKIT_CPUS=${PROFILE_LIVEKIT_CPUS}
"SHARE_SOFT=${PROFILE_SHARE_SOFT}" LIVEKIT_MEMORY_LIMIT=${PROFILE_LIVEKIT_LIMIT}
"SHARE_MAX=${PROFILE_SHARE_MAX}" LIVEKIT_MAX_PARTICIPANTS=${PROFILE_LIVEKIT_MAX_PARTICIPANTS}
"BACKUP_KEEP=${PROFILE_BACKUP_KEEP}" LIVEKIT_MAX_VIDEO=${PROFILE_LIVEKIT_MAX_VIDEO}
"SWAP_SIZE=${PROFILE_SWAP_GB}" LIVEKIT_DISABLE_SIMULCAST=${PROFILE_LIVEKIT_DISABLE_SIMULCAST}
"REGISTRATION_ENABLED=${REGISTRATION_ENABLED}" LIVEKIT_USE_EXTERNAL_IP=${PROFILE_LIVEKIT_USE_EXTERNAL_IP}
"ANTI_BOT_ENABLED=${ANTI_BOT_ENABLED:-false}" SHARE_SOFT=${PROFILE_SHARE_SOFT}
"FAIL2BAN_ENABLED=${ENABLE_FAIL2BAN}" SHARE_MAX=${PROFILE_SHARE_MAX}
"UFW_ENABLED=${ENABLE_UFW}" BACKUP_KEEP=${PROFILE_BACKUP_KEEP}
"NFTABLES_ENABLED=${ENABLE_NFTABLES}" SWAP_SIZE=${PROFILE_SWAP_GB}
"SSH_HARDENING=${SSH_HARDENING}" REGISTRATION_ENABLED=${REGISTRATION_ENABLED}
"ADMIN_EMAIL=${ADMIN_EMAIL}" ANTI_BOT_ENABLED=${ANTI_BOT_ENABLED:-false}
"ADMIN_PASSWORD=${ADMIN_PASSWORD}" 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=() python3 - "$tmp" "$pairs_file" <<'PYEOF'
local pair key value import sys
for pair in "${pairs[@]}"; do
key="${pair%%=*}" template_path, pairs_path = sys.argv[1], sys.argv[2]
value="${pair#*=}" template = open(template_path, encoding="utf-8").read()
sed_args+=(-e "s@@${key}@@${value}@g") values = {}
done for line in open(pairs_path, encoding="utf-8"):
sed -i.bak "${sed_args[@]}" "$tmp" 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" install -m 600 "$tmp" "$GLCHAT_ENV_FILE"
rm -f "$tmp" "$tmp.bak" rm -f "$tmp" "$tmp.bak"