Files

390 lines
16 KiB
Bash

#!/bin/bash
# ═══════════════════════════════════════════════════════════════════
# apps.sh — edemilov universal app installer
# Arch / CachyOS / Parrot / Kali / Debian / Ubuntu
#
# curl -s https://git.edemilov.ru/edemilov/scripts/raw/branch/master/apps.sh | sudo bash
# ═══════════════════════════════════════════════════════════════════
set -e
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"; }
success() { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
skip() { echo -e "${MAGENTA}[~]${NC} $1 (already installed)"; }
die() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
header() { echo -e "\n${BOLD}${CYAN}── $1 ──────────────────────────────${NC}"; }
echo -e "${BOLD}"
echo " ╔══════════════════════════════════════════════╗"
echo " ║ apps.sh — edemilov universal installer ║"
echo " ╚══════════════════════════════════════════════╝"
echo -e "${NC}"
# ── 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}"
if command -v pacman &>/dev/null; then
FAMILY="arch"
elif [[ "$DISTRO_ID" =~ ^(kali|parrot|debian|ubuntu|linuxmint|pop)$ ]] || \
[[ "$DISTRO_LIKE" =~ debian ]] || [[ "$DISTRO_LIKE" =~ ubuntu ]]; then
FAMILY="debian"
elif command -v dnf &>/dev/null; then
FAMILY="fedora"
else
die "Unsupported distro: $DISTRO_ID"
fi
info "Family: $FAMILY"
# 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)
UPDATE_CMD="pacman -Syu --noconfirm"
INSTALL="pacman -S --noconfirm --needed"
IS_INSTALLED() { pacman -Qi "$1" &>/dev/null; }
# 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=""
fi
;;
debian)
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)
UPDATE_CMD="dnf check-update -q || true"
INSTALL="dnf install -y -q"
IS_INSTALLED() { rpm -q "$1" &>/dev/null; }
;;
esac
# 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" || warn "$name failed — skipping"
fi
}
# 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 "Updated"
# ── Core tools ────────────────────────────────────────────────────
header "Core system tools"
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"
pkg "zsh" "zsh"
# 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..."
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
# ── Dev tools ─────────────────────────────────────────────────────
header "Development tools"
pkg "python3" "python3"
pkg "pip" "python-pip" "python3-pip"
pkg "nodejs" "nodejs"
pkg "npm" "npm"
pkg "git" "git"
# ── Docker ────────────────────────────────────────────────────────
header "Docker"
if command -v docker &>/dev/null; then
skip "Docker"
else
case $FAMILY in
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
usermod -aG docker "$REAL_USER" 2>/dev/null && success "Docker (user added to group)"
fi
# ── VS Code ───────────────────────────────────────────────────────
header "VS Code"
if command -v code &>/dev/null; then
skip "VS Code"
else
case $FAMILY in
arch)
aur "VS Code" "visual-studio-code-bin"
;;
debian)
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | \
gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
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 steam-installer && success "Steam"
else
skip "Steam"
fi
pkg "qBittorrent" "qbittorrent" "qbittorrent"
pkg "VLC" "vlc" "vlc"
;;
esac
# ── 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
# ── 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
# ── 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 extras"
pkg "gobuster" "gobuster" "gobuster"
pkg "ffuf" "ffuf" "ffuf"
fi
# ── Flatpak ───────────────────────────────────────────────────────
header "Flatpak"
if [[ "$FAMILY" != "arch" ]]; then
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"
fi
fi
# ── 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 ;;
debian) apt-get autoremove -y -qq && apt-get clean -qq ;;
fedora) dnf clean all -q ;;
esac
success "Cache cleaned"
# ── Done ──────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}${GREEN}═══════════════════════════════════════════════════${NC}"
echo -e "${BOLD} ✓ apps.sh complete!${NC}"
echo -e "${GREEN}═══════════════════════════════════════════════════${NC}"
echo ""
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}Log out and back in for:${NC} docker group, zsh default, libvirt group"
echo ""