Skip to content

Instantly share code, notes, and snippets.

@devnamipress
Created December 29, 2025 08:12
Show Gist options
  • Select an option

  • Save devnamipress/1a51f45622b0dbbc65e9c92910c52552 to your computer and use it in GitHub Desktop.

Select an option

Save devnamipress/1a51f45622b0dbbc65e9c92910c52552 to your computer and use it in GitHub Desktop.
Solana Installer
#!/usr/bin/env bash
# ============================================================
# Solana Development Environment Installer (Ubuntu/Debian)
# Interactive, dialog-based CLI with step-by-step verification
# ============================================================
# Exit handling: we want to control flow on failures, so avoid `set -e`
set -u
# ----------------------------
# Customizable ASCII header
# ----------------------------
CUSTOM_HEADER="$(cat <<'ASCII'
_____ _ ___ _ _ _
/ ____| | | |__ \ | | | | |
| (___ ___ | | __ _ _ __ __ _ ___ ) | ___ __| | _ __ | | | ___ _ __
\___ \ / _ \| |/ _` | '_ \ / _` |/ _ \ / / / _ \/ _` || '_ \| | |/ _ \| '_ \
____) | (_) | | (_| | | | | (_| | __/ / /_| __/ (_| || |_) | | | (_) | | | |
|_____/ \___/|_|\__,_|_| |_|\__, |\___||____|\___|\__,_|| .__/|_|_|\___/|_| |_|
__/ | | |
|___/ |_|
Solana Installer
ASCII
)"
# Dialog defaults
DIALOG_BIN=${DIALOG_BIN:-dialog}
DIALOG_TITLE=${DIALOG_TITLE:-"Solana Installer"}
DIALOG_HEIGHT=${DIALOG_HEIGHT:-12}
DIALOG_WIDTH=${DIALOG_WIDTH:-70}
# Logs
LOG_DIR="$(mktemp -d -t solana-install-XXXXXX)"
RUST_LOG="$LOG_DIR/rust.log"
SOLANA_LOG="$LOG_DIR/solana.log"
ANCHOR_LOG="$LOG_DIR/anchor.log"
SURFPOOL_LOG="$LOG_DIR/surfpool.log"
NODE_LOG="$LOG_DIR/node.log"
VERIFY_LOG="$LOG_DIR/verify.log"
# -------------
# Utilities
# -------------
cleanup() {
rm -rf "$LOG_DIR" 2>/dev/null || true
clear
}
trap cleanup EXIT
have_cmd() { command -v "$1" >/dev/null 2>&1; }
dialog_msg() {
"$DIALOG_BIN" --backtitle "$DIALOG_TITLE" --msgbox "$1" "$DIALOG_HEIGHT" "$DIALOG_WIDTH"
}
dialog_info() {
"$DIALOG_BIN" --backtitle "$DIALOG_TITLE" --infobox "$1" "$DIALOG_HEIGHT" "$DIALOG_WIDTH"
sleep 2
}
dialog_yesno() {
# Returns 0 on Yes, 1 on No, 255 on Cancel/Esc
"$DIALOG_BIN" --backtitle "$DIALOG_TITLE" --yesno "$1" "$DIALOG_HEIGHT" "$DIALOG_WIDTH"
return $?
}
dialog_textbox() {
# $1 = file path
"$DIALOG_BIN" --backtitle "$DIALOG_TITLE" --textbox "$1" 20 "$DIALOG_WIDTH"
}
show_header() {
printf "%s\n" "$CUSTOM_HEADER" >"$LOG_DIR/header.txt"
"$DIALOG_BIN" --backtitle "$DIALOG_TITLE" --title "Welcome" --textbox "$LOG_DIR/header.txt" 15 "$DIALOG_WIDTH"
}
confirm_exit_on_cancel() {
local code="${1:-255}"
if [ "$code" -eq 255 ]; then
dialog_yesno "You pressed Cancel. Do you want to exit the installer?"
if [ $? -eq 0 ]; then
dialog_msg "Exiting installer. Goodbye!"
exit 1
fi
fi
}
require_internet() {
if ! curl -Is --max-time 5 https://solana.com >/dev/null 2>&1; then
dialog_msg "No internet connection detected. Please connect and rerun."
exit 1
fi
}
ensure_dialog_installed() {
if have_cmd "$DIALOG_BIN"; then
return
fi
echo "dialog not found. Installing via apt..."
sudo apt update && sudo apt install -y dialog || {
echo "Failed to install dialog"
exit 1
}
}
# -----------------------------
# Package Descriptions (short)
# -----------------------------
desc_rust="Rust is required to build and install developer tools like Anchor and Surfpool CLI."
desc_solana="Solana CLI lets you interact with Solana clusters, manage keys, and deploy programs."
desc_anchor="Anchor CLI streamlines Solana program development, build flows, and IDL management."
desc_surfpool="Surfpool CLI provides surfpool tooling; installed via Cargo as a developer utility."
desc_node="Node.js and Yarn are needed for JavaScript tooling and Anchor TypeScript workflows."
# -----------------------------
# Version Checks
# -----------------------------
check_rust() { rustc --version >/dev/null 2>&1; }
check_solana() { solana --version >/dev/null 2>&1; }
check_anchor() { anchor --version >/dev/null 2>&1; }
check_surfpool() { surfpool --version >/dev/null 2>&1; }
check_node() { node --version >/dev/null 2>&1 && yarn --version >/dev/null 2>&1; }
# -----------------------------
# Installers
# -----------------------------
install_rust() {
dialog_info "Installing Rust... This may take a few minutes."
{
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
# Source Cargo environment for current session
if [ -f "$HOME/.cargo/env" ]; then
# shellcheck source=/dev/null
. "$HOME/.cargo/env"
fi
# Persist PATH updates if needed
if ! grep -q 'cargo/env' "$HOME/.bashrc" 2>/dev/null; then
echo '. "$HOME/.cargo/env"' >> "$HOME/.bashrc"
fi
} >"$RUST_LOG" 2>&1
}
install_solana() {
dialog_info "Installing Solana CLI... This may take a few minutes."
{
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
} >"$SOLANA_LOG" 2>&1
}
install_anchor() {
dialog_info "Installing Anchor CLI... This may take a few minutes."
{
# Ensure Cargo is available (Rust installed)
if ! have_cmd cargo; then
echo "cargo not found; Rust must be installed first." >&2
exit 1
fi
cargo install --git https://github.com/coral-xyz/anchor anchor-cli --locked
} >"$ANCHOR_LOG" 2>&1
}
install_surfpool() {
dialog_info "Installing Surfpool CLI... This may take a few minutes."
{
if ! have_cmd cargo; then
echo "cargo not found; Rust must be installed first." >&2
exit 1
fi
cargo install surfpool-cli
} >"$SURFPOOL_LOG" 2>&1
}
install_node_yarn() {
dialog_info "Installing Node.js, npm, and Yarn... This may take a few minutes."
{
sudo apt update
sudo apt install -y nodejs npm
sudo npm install -g yarn
} >"$NODE_LOG" 2>&1
}
verify_all() {
{
echo "Verification Output:"
echo "--------------------"
echo
echo "rustc --version:"
rustc --version || echo "rustc not found"
echo
echo "solana --version:"
solana --version || echo "solana not found"
echo
echo "anchor --version:"
anchor --version || echo "anchor not found"
echo
echo "surfpool --version:"
surfpool --version || echo "surfpool not found"
echo
echo "node --version:"
node --version || echo "node not found"
echo
echo "yarn --version:"
yarn --version || echo "yarn not found"
} >"$VERIFY_LOG" 2>&1
dialog_textbox "$VERIFY_LOG"
}
# -----------------------------
# Flow Control
# -----------------------------
main() {
# Ensure dialog is available before using it
ensure_dialog_installed
require_internet
show_header
# Inform about potential sudo prompts
dialog_msg "Some installations require sudo. If prompted, please enter your password in the terminal. Press OK to continue."
# Rust
if check_rust; then
dialog_msg "Package Rust is already installed. Skipping."
else
dialog_msg "$desc_rust"
dialog_yesno "Do you want to install Rust? (Yes/No)"
rc=$?
confirm_exit_on_cancel "$rc"
if [ "$rc" -eq 0 ]; then
install_rust
if check_rust; then
dialog_msg "Rust installed successfully."
else
dialog_msg "Rust installation failed. Please review logs:\n$RUST_LOG"
dialog_textbox "$RUST_LOG"
fi
else
dialog_msg "Skipped Rust installation."
fi
fi
# Solana CLI
if check_solana; then
dialog_msg "Package Solana CLI is already installed. Skipping."
else
dialog_msg "$desc_solana"
dialog_yesno "Do you want to install Solana CLI? (Yes/No)"
rc=$?
confirm_exit_on_cancel "$rc"
if [ "$rc" -eq 0 ]; then
install_solana
if check_solana; then
dialog_msg "Solana CLI installed successfully."
else
dialog_msg "Solana CLI installation failed. Please review logs:\n$SOLANA_LOG"
dialog_textbox "$SOLANA_LOG"
fi
else
dialog_msg "Skipped Solana CLI installation."
fi
fi
# Anchor CLI
if check_anchor; then
dialog_msg "Package Anchor CLI is already installed. Skipping."
else
dialog_msg "$desc_anchor"
dialog_yesno "Do you want to install Anchor CLI? (Yes/No)"
rc=$?
confirm_exit_on_cancel "$rc"
if [ "$rc" -eq 0 ]; then
install_anchor
if check_anchor; then
dialog_msg "Anchor CLI installed successfully."
else
dialog_msg "Anchor CLI installation failed. Please review logs:\n$ANCHOR_LOG"
dialog_textbox "$ANCHOR_LOG"
fi
else
dialog_msg "Skipped Anchor CLI installation."
fi
fi
# Surfpool CLI
if check_surfpool; then
dialog_msg "Package Surfpool CLI is already installed. Skipping."
else
dialog_msg "$desc_surfpool"
dialog_yesno "Do you want to install Surfpool CLI? (Yes/No)"
rc=$?
confirm_exit_on_cancel "$rc"
if [ "$rc" -eq 0 ]; then
install_surfpool
if check_surfpool; then
dialog_msg "Surfpool CLI installed successfully."
else
dialog_msg "Surfpool CLI installation failed. Please review logs:\n$SURFPOOL_LOG"
dialog_textbox "$SURFPOOL_LOG"
fi
else
dialog_msg "Skipped Surfpool CLI installation."
fi
fi
# Node.js & Yarn
if check_node; then
dialog_msg "Packages Node.js & Yarn are already installed. Skipping."
else
dialog_msg "$desc_node"
dialog_yesno "Do you want to install Node.js & Yarn? (Yes/No)"
rc=$?
confirm_exit_on_cancel "$rc"
if [ "$rc" -eq 0 ]; then
install_node_yarn
if check_node; then
dialog_msg "Node.js & Yarn installed successfully."
else
dialog_msg "Node.js/Yarn installation failed. Please review logs:\n$NODE_LOG"
dialog_textbox "$NODE_LOG"
fi
else
dialog_msg "Skipped Node.js & Yarn installation."
fi
fi
# Final verification
verify_all
# Summarize success/failure
if check_rust && check_solana && check_anchor && check_surfpool && check_node; then
dialog_msg "All tools installed and verified successfully!"
else
dialog_msg "Some verifications failed. Please review logs and consider rerunning the installer."
fi
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment