update: add all apps + zsh default

This commit is contained in:
edemilov committed 2026-04-19 02:01:26 +03:00
1 parent d46650b30e
commit d6018b13f0
1 file changed
+262 -163
+262 -163
View File
@@ -1,15 +1,12 @@
#!/bin/bash
# ═══════════════════════════════════════════════════════════════════
# apps.sh
# Universal app installer — Arch / Parrot / Kali / Debian / Ubuntu
# Detects distro, installs the right packages, skips existing ones
# apps.sh — edemilov universal app installer
# Arch / CachyOS / Parrot / Kali / Debian / Ubuntu
#
# curl -s https://git.edemilov.ru/edemilov/scripts/raw/branch/main/apps.sh | bash
# curl -s https://git.edemilov.ru/edemilov/scripts/raw/branch/master/apps.sh | sudo bash
# ═══════════════════════════════════════════════════════════════════
set -e
# ── Colors ──────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; MAGENTA='\033[0;35m'; BOLD='\033[1m'; NC='\033[0m'
info() { echo -e "${CYAN}[•]${NC} $1"; }
@@ -21,19 +18,17 @@ header() { echo -e "\n${BOLD}${CYAN}── $1 ───────────
echo -e "${BOLD}"
echo " ╔══════════════════════════════════════════════╗"
echo " ║ apps.sh — universal installer ║"
echo " ║ edemilov homelab scripts ║"
echo " ║ apps.sh — edemilov universal installer ║"
echo " ╚══════════════════════════════════════════════╝"
echo -e "${NC}"
# ── Detect distro ───────────────────────────────────────────────────
# ── Detect distro ─────────────────────────────────────────────────
header "Detecting system"
[[ -f /etc/os-release ]] && . /etc/os-release || die "Cannot detect distro"
DISTRO_ID="${ID,,}"
DISTRO_LIKE="${ID_LIKE,,}"
info "Distro: ${PRETTY_NAME}"
# Determine family
if command -v pacman &>/dev/null; then
FAMILY="arch"
elif [[ "$DISTRO_ID" =~ ^(kali|parrot|debian|ubuntu|linuxmint|pop)$ ]] || \
@@ -46,150 +41,136 @@ else
fi
info "Family: $FAMILY"
# ── Package manager setup ────────────────────────────────────────────
# Real user (even when run with sudo)
REAL_USER="${SUDO_USER:-$(logname 2>/dev/null || echo $USER)}"
REAL_HOME=$(eval echo ~$REAL_USER)
info "User: $REAL_USER ($REAL_HOME)"
# ── Package manager setup ─────────────────────────────────────────
case $FAMILY in
arch)
PKG_MGR="pacman"
UPDATE_CMD="pacman -Syu --noconfirm"
INSTALL="pacman -S --noconfirm --needed"
IS_INSTALLED() { pacman -Qi "$1" &>/dev/null; }
# Check for yay/paru for AUR
if command -v yay &>/dev/null; then
AUR_INSTALL="yay -S --noconfirm --needed"
elif command -v paru &>/dev/null; then
AUR_INSTALL="paru -S --noconfirm --needed"
# AUR helper
if command -v paru &>/dev/null; then
AUR="paru -S --noconfirm --needed"
elif command -v yay &>/dev/null; then
AUR="yay -S --noconfirm --needed"
else
AUR_INSTALL=""
AUR=""
fi
;;
debian)
PKG_MGR="apt"
UPDATE_CMD="apt-get update -qq"
INSTALL="apt-get install -y -qq"
IS_INSTALLED() { dpkg -l "$1" 2>/dev/null | grep -q "^ii"; }
$UPDATE_CMD
;;
fedora)
PKG_MGR="dnf"
UPDATE_CMD="dnf check-update -q || true"
INSTALL="dnf install -y -q"
IS_INSTALLED() { rpm -q "$1" &>/dev/null; }
;;
esac
# ── Smart install function ───────────────────────────────────────────
# Usage: pkg_install "display_name" "package_name" ["arch_pkg"] ["deb_pkg"]
pkg_install() {
local NAME="$1"
local PKG_ARCH="${3:-$2}"
local PKG_DEB="${4:-$2}"
local PKG_FED="${5:-$2}"
local PKG
case $FAMILY in
arch) PKG="$PKG_ARCH" ;;
debian) PKG="$PKG_DEB" ;;
fedora) PKG="$PKG_FED" ;;
esac
if IS_INSTALLED "$PKG" 2>/dev/null || command -v "$2" &>/dev/null; then
skip "$NAME"
# Smart install wrapper
pkg() {
local name="$1" arch="$2" deb="${3:-$2}" fed="${4:-$2}"
local pkg
case $FAMILY in arch) pkg="$arch" ;; debian) pkg="$deb" ;; fedora) pkg="$fed" ;; esac
if IS_INSTALLED "$pkg" 2>/dev/null || command -v "$arch" &>/dev/null; then
skip "$name"
else
info "Installing $NAME..."
$INSTALL $PKG && success "$NAME installed" || warn "$NAME failed — skipping"
info "Installing $name..."
$INSTALL $pkg && success "$name" || warn "$name failed — skipping"
fi
}
# ── Update package database ──────────────────────────────────────────
# AUR install wrapper
aur() {
local name="$1" pkg="$2"
if IS_INSTALLED "$pkg" 2>/dev/null || command -v "$pkg" &>/dev/null; then
skip "$name"
elif [[ -n "$AUR" ]]; then
info "Installing $name (AUR)..."
su - "$REAL_USER" -c "$AUR $pkg" && success "$name" || warn "$name AUR failed"
else
warn "$name — no AUR helper found (install paru or yay first)"
fi
}
# ── Update ────────────────────────────────────────────────────────
header "Updating package database"
$UPDATE_CMD
success "Package database updated"
$UPDATE_CMD && success "Updated"
# ── Core system tools ────────────────────────────────────────────────
# ── Core tools ────────────────────────────────────────────────────
header "Core system tools"
pkg_install "git" "git"
pkg_install "curl" "curl"
pkg_install "wget" "wget"
pkg_install "htop" "htop"
pkg_install "btop" "btop"
pkg_install "tmux" "tmux"
pkg_install "neofetch" "neofetch"
pkg_install "tree" "tree"
pkg_install "jq" "jq"
pkg_install "unzip" "unzip"
pkg_install "rsync" "rsync"
pkg_install "openssh" "ssh" "openssh" "openssh-client"
pkg_install "net-tools" "net-tools" "net-tools" "net-tools"
pkg_install "nmap" "nmap"
pkg "git" "git"
pkg "curl" "curl"
pkg "wget" "wget"
pkg "htop" "htop"
pkg "btop" "btop"
pkg "tmux" "tmux"
pkg "neofetch" "neofetch"
pkg "tree" "tree"
pkg "jq" "jq"
pkg "unzip" "unzip"
pkg "rsync" "rsync"
pkg "nmap" "nmap"
pkg "net-tools" "net-tools"
pkg "cifs-utils" "cifs-utils"
pkg "smbclient" "samba" "smbclient"
# ── Shell ────────────────────────────────────────────────────────────
header "Shell setup"
pkg_install "zsh" "zsh"
pkg_install "bash-completion" "bash-completion"
# ── Shell ─────────────────────────────────────────────────────────
header "Shell"
pkg "zsh" "zsh"
# Install oh-my-zsh if not present
if [[ ! -d "$HOME/.oh-my-zsh" ]] && [[ -n "${SUDO_USER:-}" ]]; then
info "Installing oh-my-zsh for $SUDO_USER..."
su - "$SUDO_USER" -c \
'sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended' \
&& success "oh-my-zsh installed" || warn "oh-my-zsh failed — skipping"
elif [[ ! -d "$HOME/.oh-my-zsh" ]]; then
# Set zsh as default for real user
if [[ "$(getent passwd $REAL_USER | cut -d: -f7)" != "$(which zsh)" ]]; then
info "Setting zsh as default shell for $REAL_USER..."
chsh -s "$(which zsh)" "$REAL_USER" && success "zsh set as default"
fi
# oh-my-zsh
if [[ ! -d "$REAL_HOME/.oh-my-zsh" ]]; then
info "Installing oh-my-zsh..."
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended \
&& success "oh-my-zsh installed" || warn "oh-my-zsh failed — skipping"
su - "$REAL_USER" -c \
'sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended' \
&& success "oh-my-zsh" || warn "oh-my-zsh failed"
else
skip "oh-my-zsh"
fi
# ── Development tools ────────────────────────────────────────────────
# ── Dev tools ─────────────────────────────────────────────────────
header "Development tools"
pkg_install "python3" "python3"
pkg_install "pip" "pip" "python-pip" "python3-pip"
pkg_install "nodejs" "node" "nodejs" "nodejs"
pkg_install "npm" "npm" "npm" "npm"
pkg "python3" "python3"
pkg "pip" "python-pip" "python3-pip"
pkg "nodejs" "nodejs"
pkg "npm" "npm"
pkg "git" "git"
# ── Docker ──────────────────────────────────────────────────────────
# ── Docker ────────────────────────────────────────────────────────
header "Docker"
if command -v docker &>/dev/null; then
skip "Docker"
else
info "Installing Docker..."
case $FAMILY in
arch)
$INSTALL docker docker-compose
systemctl enable --now docker
;;
debian)
# Official Docker install script
curl -fsSL https://get.docker.com | sh
;;
fedora)
dnf config-manager --add-repo \
https://download.docker.com/linux/fedora/docker-ce.repo
$INSTALL docker-ce docker-ce-cli containerd.io docker-compose-plugin
systemctl enable --now docker
;;
arch) $INSTALL docker docker-compose; systemctl enable --now docker ;;
debian) curl -fsSL https://get.docker.com | sh ;;
fedora) $INSTALL docker-ce docker-ce-cli containerd.io; systemctl enable --now docker ;;
esac
# Add current/sudo user to docker group
DOCKER_USER="${SUDO_USER:-$USER}"
usermod -aG docker "$DOCKER_USER" 2>/dev/null && \
success "Docker installed — ${DOCKER_USER} added to docker group" || \
success "Docker installed"
usermod -aG docker "$REAL_USER" 2>/dev/null && success "Docker (user added to group)"
fi
# ── VS Code ──────────────────────────────────────────────────────────
# ── VS Code ───────────────────────────────────────────────────────
header "VS Code"
if command -v code &>/dev/null; then
skip "VS Code"
else
info "Installing VS Code..."
case $FAMILY in
arch)
if [[ -n "$AUR_INSTALL" ]]; then
su - "${SUDO_USER:-$USER}" -c "$AUR_INSTALL visual-studio-code-bin" \
&& success "VS Code installed" || warn "VS Code AUR install failed"
else
warn "AUR helper not found — install yay first, then: yay -S visual-studio-code-bin"
fi
aur "VS Code" "visual-studio-code-bin"
;;
debian)
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | \
@@ -197,77 +178,195 @@ else
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] \
https://packages.microsoft.com/repos/vscode stable main" \
> /etc/apt/sources.list.d/vscode.list
apt-get update -qq && $INSTALL code && success "VS Code"
;;
esac
fi
# ── Browsers ──────────────────────────────────────────────────────
header "Browsers"
case $FAMILY in
arch)
pkg "Chromium" "chromium"
pkg "Brave" "brave-bin" || aur "Brave" "brave-bin"
;;
debian)
pkg "Chromium" "chromium" "chromium"
# Brave on debian
if ! command -v brave-browser &>/dev/null; then
info "Installing Brave..."
curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg \
https://brave-keyring.s3.brave.com/brave-browser-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] \
https://brave-browser-apt-release.s3.brave.com/ stable main" \
> /etc/apt/sources.list.d/brave-browser-release.list
apt-get update -qq && $INSTALL brave-browser && success "Brave"
else
skip "Brave"
fi
;;
esac
# ── Communication ─────────────────────────────────────────────────
header "Communication"
case $FAMILY in
arch)
pkg "Discord" "discord"
pkg "Telegram" "telegram-desktop"
# WhatsApp — web app via Chromium, no native package needed
;;
debian)
# Discord
if ! command -v discord &>/dev/null; then
info "Installing Discord..."
wget -qO /tmp/discord.deb "https://discord.com/api/download?platform=linux&format=deb"
dpkg -i /tmp/discord.deb || apt-get install -f -y
success "Discord"
else
skip "Discord"
fi
pkg "Telegram" "telegram-desktop" "telegram-desktop"
;;
esac
# ── Media & Gaming ────────────────────────────────────────────────
header "Media & Gaming"
case $FAMILY in
arch)
pkg "Steam" "steam"
pkg "Heroic Games" "heroic-games-launcher-bin" || aur "Heroic" "heroic-games-launcher-bin"
pkg "qBittorrent" "qbittorrent"
pkg "VLC" "vlc"
pkg "Strawberry" "strawberry"
;;
debian)
# Steam
if ! command -v steam &>/dev/null; then
dpkg --add-architecture i386
apt-get update -qq
$INSTALL code
success "VS Code installed"
;;
fedora)
rpm --import https://packages.microsoft.com/keys/microsoft.asc
cat > /etc/yum.repos.d/vscode.repo << 'EOF'
[code]
name=Visual Studio Code
baseurl=https://packages.microsoft.com/yumrepos/vscode
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc
EOF
$INSTALL code
success "VS Code installed"
;;
esac
fi
$INSTALL steam-installer && success "Steam"
else
skip "Steam"
fi
pkg "qBittorrent" "qbittorrent" "qbittorrent"
pkg "VLC" "vlc" "vlc"
;;
esac
# ── Terminal & GUI apps ──────────────────────────────────────────────
header "Terminal emulator"
# Install a good terminal if none of the preferred ones exist
if command -v kitty &>/dev/null || command -v alacritty &>/dev/null || \
command -v tilix &>/dev/null; then
skip "terminal emulator (already have one)"
else
case $FAMILY in
arch) pkg_install "kitty" "kitty" ;;
debian) pkg_install "tilix" "tilix" ;;
fedora) pkg_install "tilix" "tilix" ;;
esac
fi
# ── Wine / Windows apps ───────────────────────────────────────────
header "Wine (Windows compatibility)"
case $FAMILY in
arch)
if ! command -v wine &>/dev/null; then
info "Installing Wine + Winboat deps..."
$INSTALL wine wine-mono winetricks
aur "Winboat" "winboat"
success "Wine + Winboat"
else
skip "Wine"
fi
;;
debian)
if ! command -v wine &>/dev/null; then
dpkg --add-architecture i386
apt-get update -qq
$INSTALL wine winetricks && success "Wine"
else
skip "Wine"
fi
;;
esac
# ── Network & security tools ─────────────────────────────────────────
header "Network & security tools"
pkg_install "nmap" "nmap"
pkg_install "wireshark" "wireshark" "wireshark-qt" "wireshark"
pkg_install "net-tools" "net-tools"
pkg_install "traceroute" "traceroute"
pkg_install "whois" "whois"
pkg_install "dnsutils" "dig" "bind-tools" "dnsutils"
# ── Virtualisation ────────────────────────────────────────────────
header "Virtualisation"
case $FAMILY in
arch)
if ! command -v virt-manager &>/dev/null; then
$INSTALL virt-manager qemu-full libvirt dnsmasq
systemctl enable --now libvirtd
usermod -aG libvirt "$REAL_USER"
success "virt-manager + QEMU"
else
skip "virt-manager"
fi
;;
debian)
if ! command -v virt-manager &>/dev/null; then
$INSTALL virt-manager qemu-kvm libvirt-daemon-system
systemctl enable --now libvirtd
usermod -aG libvirt "$REAL_USER"
success "virt-manager"
else
skip "virt-manager"
fi
;;
esac
# ── Kali/Parrot specific extras ──────────────────────────────────────
# ── Cloud & sync ──────────────────────────────────────────────────
header "Cloud & sync"
case $FAMILY in
arch)
pkg "Nextcloud client" "nextcloud-client"
pkg "Bitwarden" "bitwarden"
;;
debian)
# Nextcloud
if ! command -v nextcloud &>/dev/null; then
$INSTALL nextcloud-desktop && success "Nextcloud" || warn "Nextcloud not in repos — install from flatpak"
else
skip "Nextcloud"
fi
# Bitwarden
if ! command -v bitwarden &>/dev/null; then
wget -qO /tmp/bitwarden.deb \
"https://vault.bitwarden.com/download/?app=desktop&platform=linux&variant=deb"
dpkg -i /tmp/bitwarden.deb && success "Bitwarden" || warn "Bitwarden install failed"
else
skip "Bitwarden"
fi
;;
esac
# ── Network tools ─────────────────────────────────────────────────
header "Network tools"
pkg "nmap" "nmap"
pkg "wireshark" "wireshark-qt" "wireshark"
pkg "traceroute" "traceroute"
pkg "whois" "whois"
# Kali/Parrot extras
if [[ "$DISTRO_ID" =~ ^(kali|parrot)$ ]]; then
header "Pentesting distro extras"
pkg_install "seclists" "seclists" "" "seclists"
pkg_install "gobuster" "gobuster" "" "gobuster"
pkg_install "ffuf" "ffuf" "" "ffuf"
pkg_install "burpsuite" "burpsuite" "" "burpsuite"
header "Pentesting extras"
pkg "gobuster" "gobuster" "gobuster"
pkg "ffuf" "ffuf" "ffuf"
fi
# ── Samba client (for netdrivelink.sh) ───────────────────────────────
header "Samba client"
pkg_install "cifs-utils" "mount.cifs" "cifs-utils" "cifs-utils"
pkg_install "samba-client" "smbclient" "samba" "smbclient"
# ── Flatpak (for apps not in repos) ──────────────────────────────────
# ── Flatpak ───────────────────────────────────────────────────────
header "Flatpak"
if [[ "$FAMILY" != "arch" ]]; then
pkg_install "flatpak" "flatpak"
pkg "flatpak" "flatpak"
if ! flatpak remotes | grep -q flathub; then
flatpak remote-add --if-not-exists flathub \
https://dl.flathub.org/repo/flathub.flatpakrepo
success "Flathub added"
else
skip "Flathub remote"
skip "Flathub"
fi
fi
# ── Cleanup ──────────────────────────────────────────────────────────
# ── Tailscale ─────────────────────────────────────────────────────
header "Tailscale"
if ! command -v tailscale &>/dev/null; then
case $FAMILY in
arch) $INSTALL tailscale; systemctl enable --now tailscaled ;;
debian) curl -fsSL https://tailscale.com/install.sh | sh ;;
esac
success "Tailscale — run: sudo tailscale up"
else
skip "Tailscale"
fi
# ── Cleanup ───────────────────────────────────────────────────────
header "Cleanup"
case $FAMILY in
arch) pacman -Sc --noconfirm &>/dev/null ;;
@@ -276,15 +375,15 @@ case $FAMILY in
esac
success "Cache cleaned"
# ── Done ─────────────────────────────────────────────────────────────
# ── Done ──────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}${GREEN}═══════════════════════════════════════════════════${NC}"
echo -e "${BOLD} ✓ apps.sh complete!${NC}"
echo -e "${GREEN}═══════════════════════════════════════════════════${NC}"
echo ""
echo -e " ${CYAN}Installed on:${NC} ${PRETTY_NAME}"
echo -e " ${CYAN}Run next:${NC}"
echo -e " ${YELLOW}bash <(curl -s https://git.edemilov.ru/edemilov/scripts/raw/branch/main/netdrivelink.sh)${NC}"
echo -e " ${CYAN}Next steps:${NC}"
echo -e " ${YELLOW}bash <(curl -s https://git.edemilov.ru/edemilov/scripts/raw/branch/master/netdrivelink.sh)${NC}"
echo -e " ${YELLOW}git clone https://git.edemilov.ru/edemilov/dotfiles.git ~/dotfiles && bash ~/dotfiles/install.sh${NC}"
echo ""
echo -e " ${CYAN}Note:${NC} Log out and back in for Docker group to take effect"
echo -e " ${CYAN}Log out and back in for:${NC} docker group, zsh default, libvirt group"
echo ""