> For the complete documentation index, see [llms.txt](https://blog.micsoftvn.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://blog.micsoftvn.com/use-cases/for-security/tools/backup-va-ma-hoa-file-env.md).

# Backup và mã hóa file env

Simple bashscript mã hóa và dùng cho việc backup file .env ngay trên gits, dùng cho việc quản lý và backup biến môi trường

```
#!/bin/bash

# Màu sắc giao diện cho đẹp và dễ nhìn
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# File cấu hình mẫu
ENV_FILE=".env"
EXAMPLE_FILE=".env.example"
VAULT_FILE=".env.vault"
KEYS_FILE=".env.keys"

# Hàm hiển thị tiêu đề
show_header() {
    clear
    echo -e "${BLUE}==================================================${NC}"
    echo -e "${BLUE}     HỆ THỐNG QUẢN LÝ & BACKUP BIẾN MÔI TRƯỜNG     ${NC}"
    echo -e "${BLUE}==================================================${NC}"
}

# Hàm tạm dừng để xem kết quả
pause() {
    echo ""
    read -p "Nhấn [Enter] để quay lại Menu..."
}

# 1. Khởi tạo cấu hình ban đầu
init_project() {
    show_header
    echo -e "${YELLOW}[1/3] Kiểm tra & Cấu hình .gitignore...${NC}"
    
    # Tạo .gitignore nếu chưa có
    if [ ! -f ".gitignore" ]; then
        touch .gitignore
    fi

    # Thêm .env và .env.keys vào .gitignore nếu chưa có
    for file in "$ENV_FILE" "$KEYS_FILE"; do
        if ! grep -q "^$file$" .gitignore; then
            echo "$file" >> .gitignore
            echo -e "${GREEN}• Đã thêm $file vào .gitignore${NC}"
        else
            echo -e "• $file đã có trong .gitignore từ trước."
        fi
    done

    echo -e "\n${YELLOW}[2/3] Tạo file .env.example tự động...${NC}"
    if [ -f "$ENV_FILE" ]; then
        # Copy cấu hình nhưng xóa giá trị, giữ lại key
        awk -F= '{print $1 "="}' "$ENV_FILE" > "$EXAMPLE_FILE"
        echo -e "${GREEN}• Đã tạo/cập nhật $EXAMPLE_FILE thành công từ $ENV_FILE.${NC}"
    else
        echo -e "${RED}• Không tìm thấy file .env thô để tạo file mẫu.${NC}"
    fi

    echo -e "\n${YELLOW}[3/3] Kiểm tra môi trường Node.js...${NC}"
    if [ ! -f "package.json" ] && [ -d ".git" ]; then
        echo -e "${YELLOW}• Mẹo: Bản @dotenvx/dotenvx chạy trực tiếp qua npx không cần cài cứng vào package.json.${NC}"
    fi
    
    echo -e "\n${GREEN}==> HOÀN THÀNH KHỞI TẠO! Dự án đã sẵn sàng sử dụng dotenvx.${NC}"
    pause
}

# 2. Mã hóa file .env (Sử dụng OpenSSL AES-256-CBC — có sẵn trên mọi server)
build_vault() {
    show_header
    echo -e "${YELLOW}Đang tiến hành mã hóa file .env bằng OpenSSL AES-256...${NC}"
    if [ ! -f "$ENV_FILE" ]; then
        echo -e "${RED}Lỗi: Không tìm thấy file .env ở local để mã hóa!${NC}"
    else
        read -sp "Nhập mật khẩu mã hóa: " enc_pass
        echo ""
        read -sp "Xác nhận mật khẩu: " enc_pass2
        echo ""
        if [ "$enc_pass" != "$enc_pass2" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không khớp!${NC}"
        elif [ -z "$enc_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -salt -pbkdf2 -in "$ENV_FILE" -out "$VAULT_FILE" -pass "pass:${enc_pass}"
            if [ $? -eq 0 ]; then
                echo -e "\n${GREEN}✓ Thành công! Đã mã hóa .env → ${VAULT_FILE}${NC}"
                echo -e "${YELLOW}Lưu ý: Commit file ${VAULT_FILE} lên Git để backup. KHÔNG commit .env gốc!${NC}"
            else
                echo -e "${RED}Lỗi: Quá trình mã hóa thất bại.${NC}"
            fi
        fi
    fi
    pause
}

# 3. Giải mã file .env.vault
decrypt_vault() {
    show_header
    echo -e "${YELLOW}Giải mã file ${VAULT_FILE}...${NC}"
    if [ ! -f "$VAULT_FILE" ]; then
        echo -e "${RED}Lỗi: Không tìm thấy file ${VAULT_FILE}!${NC}"
    else
        read -sp "Nhập mật khẩu giải mã: " dec_pass
        echo ""
        if [ -z "$dec_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -d -pbkdf2 -in "$VAULT_FILE" -out "$ENV_FILE" -pass "pass:${dec_pass}"
            if [ $? -eq 0 ] && [ -s "$ENV_FILE" ]; then
                echo -e "\n${GREEN}✓ Giải mã thành công! Đã tái tạo file .env${NC}"
            else
                echo -e "${RED}Lỗi: Giải mã thất bại. Sai mật khẩu hoặc file bị hỏng.${NC}"
                rm -f "$ENV_FILE"
            fi
        fi
    fi
    pause
}

# 4. Backup file .env thủ công (OpenSSL)
backup_gpg() {
    show_header
    echo -e "${YELLOW}Sao lưu .env bằng OpenSSL AES-256...${NC}"
    if [ ! -f "$ENV_FILE" ]; then
        echo -e "${RED}Lỗi: Không có file .env để backup!${NC}"
    else
        backup_name=".env.$(date +%Y%m%d_%H%M%S).enc"
        read -sp "Nhập mật khẩu bảo vệ backup: " bk_pass
        echo ""
        if [ -z "$bk_pass" ]; then
            echo -e "${RED}Lỗi: Mật khẩu không được để trống!${NC}"
        else
            openssl enc -aes-256-cbc -salt -pbkdf2 -in "$ENV_FILE" -out "$backup_name" -pass "pass:${bk_pass}"
            if [ $? -eq 0 ]; then
                echo -e "\n${GREEN}✓ Backup thành công! File: ${backup_name}${NC}"
                echo -e "${YELLOW}Lưu trữ file .enc này ở nơi an toàn.${NC}"
            else
                echo -e "${RED}Lỗi: Backup thất bại.${NC}"
            fi
        fi
    fi
    pause
}

# 5. Khôi phục file .env từ backup
restore_gpg() {
    show_header
    echo -e "${YELLOW}Khôi phục file .env từ backup...${NC}"
    
    files=(*.enc *.gpg)
    # Filter out non-existing glob patterns
    existing_files=()
    for f in "${files[@]}"; do
        [ -f "$f" ] && existing_files+=("$f")
    done

    if [ ${#existing_files[@]} -eq 0 ]; then
        echo -e "${RED}Không tìm thấy file backup (.enc/.gpg) nào!${NC}"
        pause
        return
    fi

    echo -e "${BLUE}Các file backup hiện có:${NC}"
    for i in "${!existing_files[@]}"; do
        echo -e " [$i] ${existing_files[$i]}"
    done

    read -p "Chọn số thứ tự file: " file_idx
    selected_file="${existing_files[$file_idx]}"

    if [ -f "$selected_file" ]; then
        read -sp "Nhập mật khẩu giải mã: " rs_pass
        echo ""
        openssl enc -aes-256-cbc -d -pbkdf2 -in "$selected_file" -out "$ENV_FILE" -pass "pass:${rs_pass}"
        if [ $? -eq 0 ] && [ -s "$ENV_FILE" ]; then
            echo -e "\n${GREEN}✓ Khôi phục thành công file .env!${NC}"
        else
            echo -e "${RED}Lỗi: Giải mã thất bại. Sai mật khẩu hoặc file lỗi.${NC}"
            rm -f "$ENV_FILE"
        fi
    else
        echo -e "${RED}Lựa chọn không hợp lệ!${NC}"
    fi
    pause
}

# Vòng lặp Menu chính
while true; do
    show_header
    echo -e " [1] Khởi tạo dự án (Cấu hình gitignore + .env.example)"
    echo -e " [2] Mã hóa .env (Tạo/Cập nhật .env.vault bằng OpenSSL)"
    echo -e " [3] Giải mã .env.vault (Cần nhập mật khẩu)"
    echo -e "--------------------------------------------------"
    echo -e " [4] Backup file .env (Mã hóa OpenSSL AES-256)"
    echo -e " [5] Khôi phục .env từ file backup"
    echo -e "--------------------------------------------------"
    echo -e " [0] Thoát chương trình"
    echo -e "${BLUE}==================================================${NC}"
    read -p "Vui lòng chọn một tính năng [0-5]: " choice

    case $choice in
        1) init_project ;;
        2) build_vault ;;
        3) decrypt_vault ;;
        4) backup_gpg ;;
        5) restore_gpg ;;
        0) 
            echo -e "${GREEN}Cảm ơn bạn đã sử dụng. Tạm biệt!${NC}"
            exit 0 
            ;;
        *) 
            echo -e "${RED}Lựa chọn không hợp lệ, vui lòng thử lại!${NC}"
            sleep 1
            ;;
    esac
done
```
