#!/bin/bash # ============================================================================= # # ██╗███╗ ██╗███████╗████████╗ █████╗ ██╗ ██╗ # ██║████╗ ██║██╔════╝╚══██╔══╝██╔══██╗██║ ██║ # ██║██╔██╗ ██║███████╗ ██║ ███████║██║ ██║ # ██║██║╚██╗██║╚════██║ ██║ ██╔══██║██║ ██║ # ██║██║ ╚████║███████║ ██║ ██║ ██║███████╗███████╗ # ╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ # # Auto Setup Script (Desktop/GUI) — Ubuntu & Debian Only # Supported Arch : amd64 | arm64 | armv8 # Author : suryacagur # # ============================================================================= main() { # ─── WARNA ──────────────────────────────────────────────────────────────────── RED='\e[0;31m' GREEN='\e[0;32m' YELLOW='\e[1;33m' BLUE='\e[0;34m' CYAN='\e[0;36m' BOLD='\e[1m' DARK_GRAY='\e[90m' RESET='\e[0m' # ─── ERROR TRACKER ──────────────────────────────────────────────────────────── ERRORS=() # ─── HELPER ─────────────────────────────────────────────────────────────────── info() { echo -e "${CYAN}[INFO]${RESET} $*"; } success() { echo -e "${GREEN}[OK]${RESET} $*"; } warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; } fail() { echo -e "${RED}[ERROR]${RESET} $*"; ERRORS+=("$*"); } fatal() { echo -e "${RED}[FATAL]${RESET} $*"; exit 1; } step() { echo -e "\n${BOLD}${BLUE}══════════════════════════════════════${RESET}"; \ echo -e "${BOLD}${BLUE} $*${RESET}"; \ echo -e "${BOLD}${BLUE}══════════════════════════════════════${RESET}"; } # ─── RUN COMMAND DENGAN ERROR HANDLING ─────────────────────────────────────── # Setiap baris output di-pipe dan di-wrap dengan DARK_GRAY + RESET, # sehingga color codes dari apt/brew/dll tidak bisa override warna tampilan. # Exit code command asli diambil via PIPESTATUS[0]. run_cmd() { local desc="$1" shift "$@" 2>&1 | while IFS= read -r line; do echo -e "${DARK_GRAY}${line}${RESET}" done local code="${PIPESTATUS[0]}" if [ "$code" -ne 0 ]; then fail "Gagal: ${desc} (exit code: ${code})" return 1 fi return 0 } # ─── DETEKSI USER & HOME YANG SEBENARNYA ───────────────────────────────────── # Jika dijalankan via sudo, $HOME = /root. Kita cari home user aslinya. if [ -n "$SUDO_USER" ]; then ACTUAL_USER="$SUDO_USER" ACTUAL_HOME="$(eval echo ~${SUDO_USER})" else ACTUAL_USER="$USER" ACTUAL_HOME="$HOME" fi # ─── BANNER ─────────────────────────────────────────────────────────────────── clear echo -e "${CYAN}" cat << 'EOF' ██╗███╗ ██╗███████╗████████╗ █████╗ ██╗ ██╗ ██║████╗ ██║██╔════╝╚══██╔══╝██╔══██╗██║ ██║ ██║██╔██╗ ██║███████╗ ██║ ███████║██║ ██║ ██║██║╚██╗██║╚════██║ ██║ ██╔══██║██║ ██║ ██║██║ ╚████║███████║ ██║ ██║ ██║███████╗███████╗ ╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ EOF echo -e "${RESET}" echo -e " Supported OS : Ubuntu, Debian" echo -e " Supported Arch : amd64 | arm64 | armv8" echo -e " ─────────────────────────────────────────" echo "" # ============================================================================= # PRE-CHECK — VERIFIKASI SUDO PRIVILEGE # ============================================================================= step "PRE-CHECK — Verifikasi Sudo Privilege" info "Memeriksa akses sudo untuk user '${BOLD}${ACTUAL_USER}${RESET}'..." if ! sudo -v 2>/dev/null; then fatal "User '${ACTUAL_USER}' tidak memiliki akses sudo. Jalankan script sebagai user dengan sudo privilege." fi success "Akses sudo terverifikasi untuk user '${BOLD}${ACTUAL_USER}${RESET}'." # ============================================================================= # STEP 1 — CEK ARSITEKTUR # ============================================================================= step "STEP 1 — Cek Arsitektur" RAW_ARCH="$(uname -m)" info "Arsitektur terdeteksi: ${BOLD}$RAW_ARCH${RESET}" case "$RAW_ARCH" in x86_64) ARCH="amd64" ;; aarch64|arm64) ARCH="arm64" ;; armv8*|armv8l) ARCH="armv8" ;; *) fatal "Arsitektur '${RAW_ARCH}' tidak didukung. Script ini hanya mendukung: amd64, arm64, armv8." ;; esac success "Arsitektur valid: ${BOLD}$ARCH${RESET}" # ============================================================================= # STEP 2 — CEK OS # ============================================================================= step "STEP 2 — Cek Sistem Operasi" if [ ! -f /etc/os-release ]; then fatal "Tidak dapat membaca /etc/os-release. OS tidak dapat diidentifikasi." fi . /etc/os-release info "OS terdeteksi: ${BOLD}${NAME} ${VERSION_ID}${RESET}" case "${ID}" in ubuntu|debian) success "Sistem operasi valid: ${BOLD}${NAME}${RESET}" ;; *) fatal "OS '${NAME}' tidak didukung. Script ini hanya berjalan di Ubuntu dan Debian." ;; esac # ============================================================================= # STEP 3 — UPDATE SISTEM # ============================================================================= step "STEP 3 — Update Sistem" info "Menjalankan apt update..." if run_cmd "apt update" sudo apt update; then success "Update selesai." else warn "apt update gagal, melanjutkan ke step berikutnya..." fi # ============================================================================= # STEP 4 — UPGRADE SISTEM # ============================================================================= step "STEP 4 — Upgrade Sistem" info "Menjalankan apt upgrade..." if run_cmd "apt upgrade" sudo apt upgrade -y; then success "Upgrade selesai." else warn "apt upgrade gagal, melanjutkan ke step berikutnya..." fi # ============================================================================= # STEP 5 — INSTALL PAKET DASAR # ============================================================================= step "STEP 5 — Install Paket Dasar" PACKAGES=( curl wget git build-essential ca-certificates openssh-server ) info "Menginstall paket: ${PACKAGES[*]}" if run_cmd "apt install paket dasar" sudo apt install -y "${PACKAGES[@]}"; then success "Semua paket berhasil diinstall (atau sudah tersedia)." else warn "Satu atau lebih paket gagal diinstall, melanjutkan ke step berikutnya..." fi # ============================================================================= # STEP 6 — START DAN ENABLE SSH # ============================================================================= step "STEP 6 — Start dan Enable SSH" info "Menjalankan SSH service..." if run_cmd "systemctl start ssh" sudo systemctl start ssh; then success "SSH service berhasil dijalankan." else warn "Gagal menjalankan SSH service, melanjutkan..." fi info "Mengaktifkan SSH agar otomatis berjalan saat boot..." if run_cmd "systemctl enable ssh" sudo systemctl enable ssh; then success "SSH service berhasil di-enable." else warn "Gagal meng-enable SSH service, melanjutkan..." fi info "Memverifikasi status SSH..." SSH_STATUS="$(systemctl is-active ssh 2>/dev/null)" if [ "$SSH_STATUS" = "active" ]; then success "SSH service aktif dan berjalan (status: ${BOLD}${SSH_STATUS}${RESET})." else warn "SSH service mungkin belum berjalan (status: ${BOLD}${SSH_STATUS:-unknown}${RESET})." fail "SSH tidak aktif setelah start — periksa dengan: sudo systemctl status ssh" fi # ============================================================================= # STEP 7 & 8 — CEK DAN INSTALL BRAVE BROWSER # ============================================================================= step "STEP 7 — Cek Brave Browser" if command -v brave-browser &>/dev/null || command -v brave &>/dev/null; then BRAVE_PKG_VERSION="$(dpkg -l brave-browser 2>/dev/null | awk '/brave-browser/{print $3}' || echo '-')" success "Brave Browser sudah terinstall (versi: ${BOLD}${BRAVE_PKG_VERSION}${RESET}). Melewati instalasi." else if [ "$ARCH" = "arm64" ] || [ "$ARCH" = "armv8" ]; then warn "Brave Browser tidak mendukung arsitektur ${BOLD}${ARCH}${RESET}." info "Melewati instalasi Brave Browser — installer resmi hanya tersedia untuk amd64." ERRORS+=("Brave Browser dilewati: tidak mendukung arsitektur ${ARCH}") else warn "Brave Browser tidak ditemukan. Melanjutkan ke instalasi..." # ── STEP 8 — Install Brave Browser ─────────────────────────────────────── step "STEP 8 — Install Brave Browser" info "Mengunduh dan menjalankan installer Brave Browser..." if run_cmd "install Brave Browser" bash -c 'curl -fsS https://dl.brave.com/install.sh | sh'; then success "Brave Browser berhasil diinstall." else warn "Instalasi Brave Browser gagal, melanjutkan ke step berikutnya..." fi fi fi # ============================================================================= # STEP 9 & 10 — CEK DAN INSTALL NODE/NPM VIA NVM # ============================================================================= step "STEP 9 — Cek npm" if command -v npm &>/dev/null; then NPM_VERSION="$(npm -v 2>/dev/null)" success "npm sudah terinstall (versi: ${BOLD}${NPM_VERSION}${RESET}). Melewati instalasi NVM/Node." else warn "npm tidak ditemukan. Melanjutkan ke instalasi via NVM..." # ── STEP 10 — Install NVM + Node 24 + pnpm ───────────────────────────────── step "STEP 10 — Install NVM, Node 24, dan pnpm" info "Mengunduh dan menjalankan installer NVM v0.40.4..." if run_cmd "install NVM" bash -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash'; then success "NVM berhasil diinstall." # Muat NVM ke sesi ini (sesuai instruksi resmi NVM setelah install) export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion if command -v nvm &>/dev/null; then success "NVM berhasil dimuat ke sesi ini." else fail "Gagal memuat NVM ke sesi ini." fi info "Menginstall Node.js 24..." if run_cmd "nvm install 24" nvm install 24; then success "Node.js 24 berhasil diinstall." else warn "Gagal install Node.js 24, melanjutkan..." fi info "Mengaktifkan pnpm via corepack..." if run_cmd "corepack enable pnpm" corepack enable pnpm; then success "pnpm berhasil diaktifkan." else warn "Gagal mengaktifkan pnpm, melanjutkan..." fi info "Verifikasi versi pnpm..." echo -e "${DARK_GRAY}" COREPACK_ENABLE_STRICT=0 pnpm -y -v 2>/dev/null || fail "Gagal menjalankan pnpm -v" echo -e "${RESET}" else warn "Instalasi NVM gagal, melewati Node.js dan pnpm..." fi fi # ============================================================================= # STEP 11 & 12 — CEK DAN INSTALL HOMEBREW # ============================================================================= step "STEP 11 — Cek Homebrew" if command -v brew &>/dev/null; then BREW_VERSION="$(brew --version 2>/dev/null | head -n1)" success "Homebrew sudah terinstall (${BOLD}${BREW_VERSION}${RESET}). Melewati instalasi." else warn "Homebrew tidak ditemukan. Melanjutkan ke instalasi..." step "STEP 12 — Install Homebrew" info "Menjalankan installer Homebrew (non-interactive)..." if run_cmd "install Homebrew" bash -c 'NONINTERACTIVE=1 CI=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'; then success "Homebrew berhasil diinstall." info "Menambahkan Homebrew ke PATH di .bashrc (user: ${BOLD}${ACTUAL_USER}${RESET})..." if echo "" >> "${ACTUAL_HOME}/.bashrc" && \ echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"' >> "${ACTUAL_HOME}/.bashrc"; then success "Homebrew PATH berhasil ditambahkan ke ${ACTUAL_HOME}/.bashrc." else fail "Gagal menulis ke ${ACTUAL_HOME}/.bashrc" fi info "Mengaktifkan brew shellenv untuk sesi ini..." if eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)" 2>/dev/null; then success "brew shellenv aktif untuk sesi ini." else fail "Gagal menjalankan brew shellenv" fi else warn "Instalasi Homebrew gagal, melewati step 13..." fi fi # ============================================================================= # STEP 13 — INSTALL GCC DAN TREE VIA BREW # ============================================================================= step "STEP 13 — Install gcc dan tree via Homebrew" if command -v brew &>/dev/null; then info "Menginstall gcc..." if run_cmd "brew install gcc" brew install gcc; then success "gcc berhasil diinstall." else warn "Gagal menginstall gcc, melanjutkan..." fi info "Menginstall tree..." if run_cmd "brew install tree" brew install tree; then success "tree berhasil diinstall." else warn "Gagal menginstall tree, melanjutkan..." fi else warn "brew tidak tersedia, melewati instalasi gcc dan tree." fail "Lewati step 13: brew tidak ditemukan di PATH" fi # ============================================================================= # STEP 14 — AUTOREMOVE & AUTOCLEAN # ============================================================================= step "STEP 14 — Autoremove & Autoclean" info "Menghapus package yang tidak lagi dibutuhkan..." if run_cmd "apt autoremove" sudo apt autoremove -y; then success "Autoremove selesai." else warn "apt autoremove gagal, melanjutkan..." fi info "Membersihkan cache apt..." if run_cmd "apt autoclean" sudo apt autoclean; then success "Autoclean selesai." else warn "apt autoclean gagal, melanjutkan..." fi # ============================================================================= # STEP 15 — SELESAI # ============================================================================= echo "" echo -e "${GREEN}${BOLD}" cat << 'EOF' ╔══════════════════════════════════════════╗ ║ INSTALASI SELESAI ✓ ║ ║ Semua paket dan tools telah terpasang. ║ ║ Silakan restart terminal Anda. ║ ╚══════════════════════════════════════════╝ EOF echo -e "${RESET}" echo -e " ${BOLD}Ringkasan:${RESET}" echo -e " • OS : ${NAME} ${VERSION_ID}" echo -e " • Arch : ${ARCH}" echo -e " • User : ${ACTUAL_USER}" echo -e " • ssh : $(systemctl is-active ssh 2>/dev/null || echo '-')" echo -e " • npm : $(npm -v 2>/dev/null || echo '-')" echo -e " • node : $(node -v 2>/dev/null || echo '-')" echo -e " • brew : $(brew --version 2>/dev/null | head -n1 || echo '-')" echo -e " • pnpm : $(COREPACK_ENABLE_STRICT=0 pnpm -v 2>/dev/null || echo '-')" echo -e " • brave : $(dpkg -l brave-browser 2>/dev/null | awk '/brave-browser/{print $3}' || echo '-')" echo "" # ─── TAMPILKAN ERROR JIKA ADA ───────────────────────────────────────────────── if [ ${#ERRORS[@]} -gt 0 ]; then echo -e " ${RED}${BOLD}⚠ Terdapat ${#ERRORS[@]} error selama proses instalasi:${RESET}" for ERR in "${ERRORS[@]}"; do echo -e " ${RED} • ${ERR}${RESET}" done echo "" else echo -e " ${GREEN}${BOLD}✓ Tidak ada error. Semua proses berjalan lancar.${RESET}" echo "" fi echo -e " ${CYAN}Jalankan: ${BOLD}source ~/.bashrc${RESET} ${CYAN}untuk memuat ulang environment.${RESET}" echo "" } # ─── end main() ───────────────────────────────────────────────────────────── # ============================================================================= # Panggil main() dengan stdin dari /dev/null. # Tujuan: mencegah command di dalam main() (npm, brew, apt, dll) menelan # sisa script dari pipe saat dijalankan via: curl ... | bash # Bash membaca SELURUH file dulu (definisi fungsi), baru eksekusi main(). # ============================================================================= main "$@"