#!/bin/bash # ZScript Bootstrap Installer # Lệnh cài đặt: curl -fsSL https://zscript.zor.vn/install -o install && bash install # LƯU Ý BẢO MẬT: nên xác minh SHA256/chữ ký GPG của file 'install' trước khi chạy, # và ghim theo tag đã ký thay vì nhánh main đang chạy. set -euo pipefail # Không bao giờ để git dừng lại hỏi user/pass giữa lúc cài đặt tự động — # thà fail nhanh với thông báo rõ ràng còn hơn treo chờ nhập liệu. export GIT_TERMINAL_PROMPT=0 export GIT_ASKPASS=/bin/true # Clone qua Cloudflare Worker proxy (deploy/cloudflare-worker/) thay vì gitlab.com # trực tiếp: repo trên GitLab vẫn PRIVATE nhưng VPS KHÔNG cần nhập user/pass/token. # Token GitLab nằm trong Worker Secrets, không bao giờ có mặt trên máy khách. # Đặt ZSCRIPT_REPO_URL để trỏ nguồn khác (vd khi tự dev). REPO_URL="${ZSCRIPT_REPO_URL:-https://zscript.zor.vn/zscript.git}" INSTALL_DIR="/opt/zscript" LOG_DIR="${INSTALL_DIR}/logs" # Màu sắc RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' echo -e "${CYAN}╔═══════════════════════════════════════════╗${NC}" echo -e "${CYAN}║${NC} ${BOLD}ZScript - LEMP Stack Auto Installer${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} ${YELLOW}Developed by ZOR${NC} ${CYAN}║${NC}" echo -e "${CYAN}╚═══════════════════════════════════════════╝${NC}" echo "" # Kiểm tra quyền root if [[ $EUID -ne 0 ]]; then echo -e "${RED}LỖI: Vui lòng chạy script với quyền root.${NC}" echo "Chạy lại: sudo bash install" exit 1 fi # Kiểm tra git đã cài chưa if ! command -v git &>/dev/null; then echo -e "${YELLOW}Đang cài đặt git...${NC}" if command -v apt-get &>/dev/null; then apt-get update -qq && apt-get install -y -qq git elif command -v dnf &>/dev/null; then dnf install -y -q git else echo -e "${RED}LỖI: Không thể cài đặt git. Vui lòng cài thủ công.${NC}" exit 1 fi fi # Clone hoặc cập nhật từ GitLab if [ -d "${INSTALL_DIR}/.git" ]; then echo -e "${YELLOW}ZScript đã tồn tại. Đang cập nhật...${NC}" cd "$INSTALL_DIR" # Backup các file config/logs riêng người dùng trước khi reset BACKUP_PATH="/opt/zscript-backup-$(date +%Y%m%d-%H%M%S).tgz" if [ -d "${INSTALL_DIR}/config" ] || [ -d "${INSTALL_DIR}/logs" ]; then echo -e "${YELLOW}Sao lưu config/logs trước khi cập nhật → ${BACKUP_PATH}${NC}" (umask 077; tar -czf "$BACKUP_PATH" -C /opt zscript/config zscript/logs 2>/dev/null) || true chmod 600 "$BACKUP_PATH" 2>/dev/null || true fi # Chuyển remote sang proxy nếu máy này còn trỏ thẳng vào gitlab.com. # Không chuyển thì `git fetch` sẽ hỏi user/pass GitLab như trước. CUR_REMOTE=$(git remote get-url origin 2>/dev/null || echo "") case "$CUR_REMOTE" in *gitlab.com*) echo -e "${YELLOW}Chuyển remote sang ${REPO_URL} (không cần tài khoản GitLab).${NC}" git remote set-url origin "$REPO_URL" ;; esac # Giữ RIÊNG dữ liệu vận hành ra ngoài repo trước khi đụng vào git. # CHỈ hai file này được khôi phục sau reset — mọi file khác trong config/ là # template và PHẢI theo bản mới, nếu không các bản vá config sẽ không bao giờ # tới được máy đã cài (bung nguyên tar cũ đè lên repo vừa reset là sai). STATE_DIR=$(mktemp -d) for _sf in accounts.conf domains.db; do if [ -f "${INSTALL_DIR}/config/${_sf}" ]; then cp -p "${INSTALL_DIR}/config/${_sf}" "${STATE_DIR}/${_sf}" fi done git fetch origin git reset --hard origin/main # Khôi phục dữ liệu vận hành. Bản ZScript cũ track accounts.conf/domains.db # trong git, nên reset --hard sẽ XOÁ MẤT credential thật nếu không giữ ở đây. mkdir -p "${INSTALL_DIR}/config" for _sf in accounts.conf domains.db; do if [ -f "${STATE_DIR}/${_sf}" ]; then cp -p "${STATE_DIR}/${_sf}" "${INSTALL_DIR}/config/${_sf}" chmod 600 "${INSTALL_DIR}/config/${_sf}" 2>/dev/null || true fi done rm -rf "$STATE_DIR" echo -e "${GREEN}Đã cập nhật ZScript thành công.${NC}" if [ -f "$BACKUP_PATH" ]; then echo -e "${GREEN}Backup config cũ tại: ${BACKUP_PATH}${NC}" fi else # Backup thư mục cũ nếu tồn tại (không phải git repo) if [ -d "$INSTALL_DIR" ]; then BACKUP_PATH="/opt/zscript-backup-$(date +%Y%m%d-%H%M%S).tgz" echo -e "${YELLOW}Phát hiện bản cài cũ. Sao lưu trước khi xóa → ${BACKUP_PATH}${NC}" (umask 077; tar -czf "$BACKUP_PATH" -C /opt "$(basename "$INSTALL_DIR")" 2>/dev/null) || true chmod 600 "$BACKUP_PATH" 2>/dev/null || true rm -rf "$INSTALL_DIR" fi echo -e "${YELLOW}Đang tải ZScript từ GitLab...${NC}" # TODO(bảo mật): ghim theo tag đã ký và xác minh sau clone (git verify-tag), # thay vì tin tưởng hoàn toàn nhánh main qua TLS. Một khi upstream bị chiếm = # thực thi mã tùy ý dưới quyền root trên mọi máy cài đặt. git clone "$REPO_URL" "$INSTALL_DIR" echo -e "${GREEN}Đã tải ZScript thành công.${NC}" fi # Tạo thư mục logs mkdir -p "$LOG_DIR" # Kiểm tra các file quan trọng for required_file in install.sh menu.sh lib/php-repo.sh; do if [ ! -f "${INSTALL_DIR}/${required_file}" ]; then echo -e "${RED}LỖI: Thiếu file ${required_file}. Repo có thể bị lỗi.${NC}" exit 1 fi done # Đặt quyền thực thi chmod +x "${INSTALL_DIR}/install.sh" chmod +x "${INSTALL_DIR}/menu.sh" [ -f "${INSTALL_DIR}/lib/ssh-alert.sh" ] && chmod +x "${INSTALL_DIR}/lib/ssh-alert.sh" # Chạy cài đặt echo "" echo -e "${BOLD}${CYAN}=== Bắt đầu cài đặt ZScript ===${NC}" bash "${INSTALL_DIR}/install.sh" # Dọn dẹp file bootstrap (chỉ xóa đúng script đã được gọi, và chỉ khi là file thường) [ -f "${BASH_SOURCE[0]}" ] && rm -f -- "${BASH_SOURCE[0]}" 2>/dev/null || true