Skip to content

Instantly share code, notes, and snippets.

@cyanff
Last active May 2, 2025 11:45
Show Gist options
  • Save cyanff/65942409aa51631284678233ff0f9a15 to your computer and use it in GitHub Desktop.
Save cyanff/65942409aa51631284678233ff0f9a15 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Development Environment Setup Script for Debian/Ubuntu
# Last Updated: 2025-03-20
# Description: Automatically detects architecture and sets up development environment
# Set environment variable to auto-accept prompts
export DEBIAN_FRONTEND=noninteractive
set -euo pipefail
IFS=$'\n\t'
# Define colors for output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
readonly ZELLIJ_VERSION="v0.42.0"
readonly ZELLIJ_X86_URL="https://github.com/zellij-org/zellij/releases/download/${ZELLIJ_VERSION}/zellij-x86_64-unknown-linux-musl.tar.gz"
readonly ZELLIJ_ARM_URL="https://github.com/zellij-org/zellij/releases/download/${ZELLIJ_VERSION}/zellij-aarch64-unknown-linux-musl.tar.gz"
readonly MINICONDA_X86_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh"
readonly MINICONDA_ARM_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh"
# Logger utility functions
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
# Detect system architecture
detect_architecture() {
local arch=$(uname -m)
case "$arch" in
x86_64|i386|i686)
echo "x86"
;;
aarch64|arm64|armv8*|armv7*|armhf)
echo "arm"
;;
*)
log_error "Unsupported architecture: $arch"
;;
esac
}
# Check if script is run with root privileges
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root (sudo). Exiting..."
fi
}
# Check system requirements
check_system() {
if ! command -v apt-get &> /dev/null; then
log_error "This script requires apt-get package manager. Exiting..."
fi
}
# Update and upgrade system packages
update_system() {
log_info "Updating system packages..."
apt-get update -qq || log_error "Failed to update package lists"
log_info "Upgrading system packages..."
apt-get upgrade -y || log_error "Failed to upgrade packages"
}
# Install and configure Zellij
install_zellij() {
log_info "Installing Zellij ${ZELLIJ_VERSION} for ${ARCH} architecture..."
# Create temporary directory for download
local temp_dir=$(mktemp -d)
cd "$temp_dir"
# Select the appropriate URL based on architecture
local zellij_url="$ZELLIJ_X86_URL"
if [[ "$ARCH" == "arm" ]]; then
zellij_url="$ZELLIJ_ARM_URL"
fi
log_info "Downloading from: $zellij_url"
# Download and extract Zellij binary
wget "$zellij_url" -O zellij.tar.gz || log_error "Failed to download Zellij"
tar xzf zellij.tar.gz || log_error "Failed to extract Zellij"
# Move binary to /usr/bin and set permissions
mv zellij /usr/bin/ || log_error "Failed to move Zellij to /usr/bin"
chmod +x /usr/bin/zellij || log_error "Failed to set Zellij permissions"
# Cleanup
cd - > /dev/null
rm -rf "$temp_dir"
log_info "Zellij installation completed"
}
# Install and configure Fish shell
install_fish() {
log_info "Installing Fish shell..."
apt-get install -y fish || log_error "Failed to install Fish"
# Update shell for root user
local root_bashrc="/root/.bashrc"
# Function to add Fish shell execution to bashrc
add_fish_to_bashrc() {
local bashrc_file="$1"
if [[ ! -f "$bashrc_file" ]]; then
touch "$bashrc_file"
fi
if ! grep -q "exec fish" "$bashrc_file"; then
echo '
if [[ $(ps --no-header --pid=$PPID --format=cmd) != "fish" && -z ${BASH_EXECUTION_STRING} ]]
then
exec fish
fi' >> "$bashrc_file"
fi
}
# Add Fish shell execution to root's .bashrc
add_fish_to_bashrc "$root_bashrc"
# Make Fish the default shell for root (with -f to force)
chsh -s $(which fish) root
log_info "Fish shell installation and configuration completed"
}
# Install fzf and neovim from apt
install_tools() {
log_info "Installing fzf and neovim..."
apt-get install -y fzf neovim || log_error "Failed to install tools"
apt-get install -y rsync
log_info "Tools installation completed"
}
install_gh() {
log_info "Installing GitHub CLI..."
(type -p wget >/dev/null || (apt-get update && apt-get install -y wget)) \
&& mkdir -p -m 755 /etc/apt/keyrings \
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& apt-get update \
&& apt-get install -y gh
log_info "GitHub CLI installation completed"
}
install_uv() {
log_info "Installing uv package installer..."
curl -LsSf https://astral.sh/uv/install.sh | sh
# Ensure uv is in PATH
export PATH="/root/.cargo/bin:$PATH"
log_info "uv installation completed"
}
install_tailscale() {
log_info "Installing Tailscale..."
curl -fsSL https://tailscale.com/install.sh | sh
log_info "Tailscale installation completed"
}
# Install Miniconda
install_miniconda() {
log_info "Installing Miniconda..."
# Create installation directory
local miniconda_dir="/opt/miniconda3"
mkdir -p "$miniconda_dir"
# Select the appropriate URL based on architecture
local miniconda_url="$MINICONDA_X86_URL"
if [[ "$ARCH" == "arm" ]]; then
miniconda_url="$MINICONDA_ARM_URL"
fi
log_info "Downloading from: $miniconda_url"
# Download and install Miniconda
local temp_dir=$(mktemp -d)
cd "$temp_dir"
wget "$miniconda_url" -O miniconda.sh || log_error "Failed to download Miniconda"
bash miniconda.sh -b -u -p "$miniconda_dir" || log_error "Failed to install Miniconda"
# Make Miniconda available to all users
echo "export PATH=\"$miniconda_dir/bin:\$PATH\"" > /etc/profile.d/miniconda.sh
chmod +x /etc/profile.d/miniconda.sh
# Initialize for Fish shell
if command -v fish &> /dev/null; then
mkdir -p /etc/fish/conf.d
echo "set -gx PATH $miniconda_dir/bin \$PATH" > /etc/fish/conf.d/miniconda.fish
fi
# Cleanup
cd - > /dev/null
rm -rf "$temp_dir"
log_info "Miniconda installation completed at $miniconda_dir"
}
install_lazydocker() {
log_info "Installing lazydocker..."
curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | bash
log_info "lazydocker installation completed"
}
# Main installation process
main() {
# Auto-detect architecture
ARCH=$(detect_architecture)
log_info "Detected ${ARCH} architecture..."
check_root
check_system
update_system
# Perform installations
install_zellij
install_fish
install_tools
install_uv
install_gh
install_tailscale
#install_miniconda
install_lazydocker
log_info "Setup completed successfully!"
log_info "Please log out and log back in for all changes to take effect."
log_warn "Note: Fish shell will be activated on next login."
log_info "Miniconda has been installed to /opt/miniconda3 and is available in PATH."
}
# Execute main function
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment