install (18702B)
1 #!/bin/sh 2 3 USER_NAME=$(whoami) 4 BASE_URL="git://git.sivaldodavi.com" 5 SRC_DIR="$HOME/.local/src" 6 SHARE_DIR="$HOME/.local/share" 7 FONT_DIR="$SHARE_DIR/fonts" 8 CONF="$HOME/.config" 9 REPOS="st sent dwm dmenu" 10 11 export GOPATH="$SHARE_DIR/go" 12 export GOBIN="$GOPATH/bin" 13 export PATH="$PATH:$GOBIN" 14 15 # ─── Log de execução ───────────────────────────────────────────── 16 LOG_FILE="$HOME/install_$(date +%Y%m%d_%H%M%S).log" 17 LOG_PIPE="$(mktemp -u)" 18 mkfifo "$LOG_PIPE" 19 tee -a "$LOG_FILE" < "$LOG_PIPE" & 20 exec > "$LOG_PIPE" 2>&1 21 rm -f "$LOG_PIPE" 22 23 # ─── Cores no output ───────────────────────────────────────────── 24 RED='\033[0;31m' 25 GREEN='\033[0;32m' 26 YELLOW='\033[1;33m' 27 NC='\033[0m' 28 29 # Lista global de falhas, usada para o resumo final 30 GLOBAL_FAILURES="" 31 32 log_ok() { 33 printf "${GREEN}OK${NC} %s\n" "$1" 34 } 35 36 log_warn() { 37 printf "${YELLOW}AVISO${NC} %s\n" "$1" 38 } 39 40 log_fail() { 41 printf "${RED}FALHA${NC} %s\n" "$1" 42 GLOBAL_FAILURES="$GLOBAL_FAILURES\n - $1" 43 } 44 45 # ─── Funções utilitárias ────────────────────────────────────────────────────── 46 47 die() { 48 printf "${RED}ERRO:${NC} %s\n" "$1" >&2 49 exit 1 50 } 51 52 # Checagem de comandos essenciais 53 check_dependencies() { 54 for cmd in doas git curl; do 55 command -v "$cmd" >/dev/null 2>&1 || die "'$cmd' não encontrado. Instale-o antes de continuar." 56 done 57 } 58 59 mklink() { 60 target="$1" 61 link_name="$2" 62 mkdir -p "$(dirname "$link_name")" 63 rm -rf "$link_name" 64 ln -s "$target" "$link_name" 65 echo "Link: $link_name -> $target" 66 } 67 68 # ─── Ajuda / Menu de comandos ───────────────────────────────────────────────── 69 70 show_help() { 71 echo "Uso: $0 [comando]" 72 echo "" 73 echo "Comandos de instalação:" 74 echo " repos - Configura os repositórios do Alpine e atualiza" 75 echo " pacotes - Instala todos os pacotes base e ferramentas" 76 echo " permissoes - Configura grupos de usuário, doas e X11" 77 echo " servicos - Ativa serviços essenciais (ex: dbus)" 78 echo " dotfiles - Clona/Atualiza dotfiles e cria links" 79 echo " ferramentas - Clona e compila ferramentas do código-fonte (Suckless e nsxiv)" 80 echo " lf - Instala o gerenciador de arquivos lf via go" 81 echo " vim - Instala o gerenciador e os plugins do Vim" 82 echo " ffsetup - Clona e executa o ffsetup" 83 echo "" 84 echo "Comandos extras:" 85 echo " config - Fluxo normal: executa todos os passos de instalação acima na ordem correta" 86 echo " alpine - Cria o arquivo de configuração para o Alpine (answers.txt)" 87 echo " bookmarks - Cria o arquivo de bookmarks em ~/.local/share/bookmarks" 88 echo " ssh - Configura a chave SSH com o Codeberg" 89 echo " fontes - Baixa e instala as fontes personalizadas" 90 echo " adb - Instala as ferramentas do android-tools" 91 echo " mail - Instala e roda o mbsync" 92 echo " ajuda - Mostra esta tela de ajuda" 93 echo "" 94 } 95 96 # ─── Subcomandos extras ─────────────────────────────────────────────────────── 97 98 install_all_fonts() { 99 install_font() { 100 name="$1"; url="$2"; dir="$FONT_DIR/$name" 101 mkdir -p "$dir" 102 echo "Baixando fonte '$name'..." 103 curl -L -A "Mozilla/5.0" "$url" -o "/tmp/font.zip" || { log_fail "Download da fonte '$name'"; return; } 104 unzip -o "/tmp/font.zip" -d "$dir" || { log_fail "Extração da fonte '$name'"; return; } 105 find "$dir" -type f ! -name "*.ttf" ! -name "*.otf" ! -name "*.ttc" -delete 106 rm "/tmp/font.zip" 107 log_ok "Fonte '$name' instalada." 108 } 109 110 mkdir -p "$FONT_DIR" 111 install_font "FiraCode" "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/FiraCode.zip" 112 install_font "Bebas-Neue" "https://www.1001fonts.com/download/bebas-neue.zip" 113 install_font "Ruda" "https://www.1001fonts.com/download/ruda.zip" 114 install_font "Aptos" "https://dl.dafontfree.io/download/Microsoft-Aptos-Fonts-Family.zip" 115 install_font "Noto-Emoji" "https://www.1001fonts.com/download/noto-emoji.zip" 116 install_font "Arial" "https://font.download/dl/font/arial.zip" 117 install_font "Times-New-Roman" "https://font.download/dl/font/times-new-roman.zip" 118 119 [ -x "$(command -v fc-cache)" ] && fc-cache -f 120 } 121 122 setup_bookmarks() { 123 echo "Criando arquivo de bookmarks..." 124 mkdir -p "$SHARE_DIR" 125 cat << BOOKMARKS_EOF > "$SHARE_DIR/bookmarks" 126 http://localhost:1313/ 127 https://sivaldodavi.com 128 https://web.whatsapp.com 129 http://git.sivaldodavi.com/ 130 https://substack.com 131 https://disroot.org 132 https://cloud.disroot.org 133 https://webmail.disroot.org 134 https://drive.google.com 135 https://classroom.google.com 136 https://facsur.jacad.com.br/academico/aluno-v2/login 137 BOOKMARKS_EOF 138 log_ok "Arquivo 'bookmarks' criado em $SHARE_DIR/bookmarks." 139 } 140 141 setup_ssh() { 142 printf "Email para a chave SSH: " 143 read -r SSH_EMAIL 144 [ -z "$SSH_EMAIL" ] && die "Email não pode ser vazio." 145 146 mkdir -p "$SHARE_DIR/ssh" 147 chmod 700 "$SHARE_DIR/ssh" 148 149 KEY_PATH="$HOME/.ssh/id_ed25519" 150 if [ -f "$KEY_PATH" ]; then 151 echo "Já existe uma chave em $KEY_PATH, pulando geração." 152 else 153 ssh-keygen -t ed25519 -C "$SSH_EMAIL" -f "$KEY_PATH" -N "" || die "Falha ao gerar chave SSH." 154 fi 155 156 printf "\n Chave pública (cole no Codeberg/Github em Settings -> SSH/GPG Keys):\n" 157 echo "─────────────────────────────────────────" 158 cat "$KEY_PATH.pub" 159 echo "─────────────────────────────────────────" 160 printf "Pressione Enter após cadastrar a chave no Codeberg/Github para testar a conexão... " 161 read -r _ 162 163 ssh -o StrictHostKeyChecking=accept-new -T git@codeberg.org 164 } 165 166 setup_android() { 167 echo "Instalando android-tools..." 168 doas apk add android-tools || die "Falha ao instalar android-tools." 169 log_ok "android-tools instalado." 170 } 171 172 setup_email() { 173 echo "Instalando isync (mbsync)..." 174 175 doas apk add isync || die "Falha ao instalar isync." 176 177 # Cria a pasta para armazenamento de e-mails 178 mkdir -p "$HOME/.local/share/mail" 179 log_ok "Diretório de e-mail criado em ~/.local/share/mail." 180 181 # Adiciona a configuração ao arquivo account.aerc 182 AERC_CONF="$HOME/.config/aerc/accounts.conf" 183 184 if [ -f "$AERC_CONF" ]; then 185 { 186 echo "" 187 echo "# Faz o aerc rodar o mbsync automaticamente" 188 echo "check-mail = 3m" 189 echo "check-mail-cmd = mbsync disroot-sync" 190 } >> "$AERC_CONF" 191 log_ok "Configuração de check-mail adicionada ao aerc." 192 else 193 log_warn "Arquivo $AERC_CONF não encontrado. A configuração automática não foi adicionada." 194 fi 195 196 log_ok "Configuração de e-mail concluída." 197 } 198 199 setup_alpine_answers() { 200 echo "Gerando arquivo de respostas para o instalador do Alpine..." 201 log_warn "Confirme antes de usar: disco (/dev/nvme0n1) e interface de rede (usb0) abaixo são valores fixos. Ajuste se necessário." 202 cat << ALPINE_EOF > ./answers.txt 203 # Configuração do teclado 204 KEYMAPOPTS="br br-thinkpad" 205 206 # Nome do host (Hostname) 207 HOSTNAMEOPTS=alpine 208 209 # Gerenciador de dispositivos do sistema 210 DEVDOPTS=mdev 211 212 # Configuração das interfaces de rede 213 INTERFACESOPTS="auto lo 214 iface lo inet loopback 215 216 auto usb0 217 iface usb0 inet dhcp 218 hostname alpine 219 " 220 221 # Definição do fuso horário (Timezone) 222 TIMEZONEOPTS="Brazil/East" 223 224 # Configuração de proxy de rede 225 PROXYOPTS=none 226 227 # Seleção automática do espelho (mirror) mais rápido 228 APKREPOSOPTS="-f" 229 230 # Criação e privilégios do usuário administrador 231 USEROPTS="-a -g audio,input,video,netdev -f \"Sivaldo Davi\" sivas" 232 233 # Ativação do servidor SSH 234 SSHDOPTS=openssh 235 236 # Cliente de sincronização de horário (NTP) 237 NTPOPTS=busybox 238 239 # Instalação no disco com criptografia em modo sistema (sys) 240 DISKOPTS="-e -m sys /dev/nvme0n1" 241 ALPINE_EOF 242 log_ok "Arquivo 'answers.txt' gerado com sucesso para a instalação do Alpine!" 243 } 244 245 # ─── Módulos principais da instalação ───────────────────────────────────────── 246 247 setup_repos() { 248 echo "Configurando repositórios do Alpine..." 249 command -v doas >/dev/null || die "'doas' não está instalado. Instale-o com: apk add doas" 250 251 cat <<REPOS_EOF | doas tee /etc/apk/repositories >/dev/null 252 http://dl-cdn.alpinelinux.org/alpine/edge/main 253 http://dl-cdn.alpinelinux.org/alpine/edge/community 254 REPOS_EOF 255 256 doas apk update || die "Falha em 'apk update'." 257 doas apk upgrade --available || die "Falha em 'apk upgrade'." 258 log_ok "Repositórios atualizados." 259 } 260 261 install_packages() { 262 echo "Instalando pacotes base..." 263 BUILD_DEPS="gcc g++ make git libx11-dev libxft-dev libxinerama-dev ncurses-dev imlib2-dev libexif-dev" 264 X11_TOOLS="brightnessctl xorg-server xinit setxkbmap xclip xdotool xsetroot xautolock unclutter-xfixes font-dejavu font-liberation xf86-input-libinput" 265 AUDIO="alsa-utils alsaconf pipewire pipewire-alsa pipewire-pulse wireplumber pipewire-spa-bluez" 266 DEV_NET="go curl openssh netcat-openbsd iproute2 firefox" 267 CLI_TOOLS="bash vim fastfetch fzf grep ncurses zip unzip imagemagick maim slop mpv jq python3 py3-pip ffmpeg" 268 PROD_SEC="aerc zathura zathura-pdf-mupdf hugo pandoc typst gnupg pass pass-otp openssl openssl-dev dbus dbus-x11" 269 270 ALL_PACKAGES="$BUILD_DEPS $X11_TOOLS $AUDIO $DEV_NET $CLI_TOOLS $PROD_SEC" 271 FAILED_PKGS="" 272 273 for pkg in $ALL_PACKAGES; do 274 if ! doas apk add "$pkg" 2>/dev/null; then 275 log_warn "Pacote não encontrado ou falhou: $pkg" 276 FAILED_PKGS="$FAILED_PKGS $pkg" 277 fi 278 done 279 280 if [ -n "$FAILED_PKGS" ]; then 281 log_fail "Pacotes que falharam:$FAILED_PKGS" 282 echo " Verifique os nomes e instale manualmente se necessário." 283 fi 284 285 doas setup-xorg-base || log_warn "'setup-xorg-base' falhou, continue manualmente se necessário." 286 log_ok "Pacotes processados." 287 } 288 289 setup_permissions() { 290 echo "Configurando permissões e X11..." 291 for grp in lp wheel audio video input messagebus; do 292 doas adduser "$USER_NAME" "$grp" || log_warn "Não foi possível adicionar '$USER_NAME' ao grupo '$grp'." 293 done 294 295 doas mkdir -p /etc/doas.d 296 cat <<DOAS_EOF | doas tee /etc/doas.d/doas.conf >/dev/null 297 permit nopass $USER_NAME 298 permit nopass $USER_NAME as root cmd /sbin/poweroff 299 permit nopass $USER_NAME as root cmd /sbin/reboot 300 DOAS_EOF 301 302 doas mkdir -p /etc/X11/xorg.conf.d 303 cat <<X11_EOF | doas tee /etc/X11/xorg.conf.d/10-mouse.conf >/dev/null 304 Section "InputClass" 305 Identifier "touchpad" 306 MatchIsTouchpad "on" 307 Driver "libinput" 308 Option "Tapping" "on" 309 EndSection 310 X11_EOF 311 log_ok "Permissões configuradas." 312 } 313 314 setup_services() { 315 echo "Configurando serviços..." 316 doas rc-service dbus start || log_warn "Falha ao iniciar dbus." 317 doas rc-update add dbus default 318 log_ok "Serviços configurados." 319 } 320 321 # Verifica se o repositório local de dotfiles aponta para o remote esperado 322 dotfiles_remote_is_valid() { 323 remote_url=$(cd "$HOME" && git remote get-url origin 2>/dev/null) 324 [ "$remote_url" = "$BASE_URL/dotfiles.git" ] || [ "$remote_url" = "$BASE_URL/dotfiles" ] 325 } 326 327 setup_dotfiles() { 328 echo "Configurando Dotfiles..." 329 if [ -d "$HOME/.git" ]; then 330 if dotfiles_remote_is_valid; then 331 (cd "$HOME" && git pull) || log_warn "Falha ao atualizar dotfiles." 332 else 333 log_warn "$HOME/.git existe mas não aponta para $BASE_URL/dotfiles.git — pulando 'git pull' para evitar misturar repositórios." 334 fi 335 else 336 git clone "$BASE_URL/dotfiles.git" "$HOME/dotfiles_tmp" || die "Falha ao clonar dotfiles." 337 cp -af "$HOME/dotfiles_tmp/." "$HOME/" 338 rm -rf "$HOME/dotfiles_tmp" 339 fi 340 341 mklink "$CONF/X11/profile" "$HOME/.profile" 342 mklink "$CONF/X11/xinitrc" "$HOME/.xinitrc" 343 344 mkdir -p "$SHARE_DIR/gnupg" 345 chmod 700 "$SHARE_DIR/gnupg" 346 log_ok "Dotfiles configurados." 347 } 348 349 install_source_tools() { 350 echo "Compilando ferramentas (Suckless + nsxiv)..." 351 mkdir -p "$SRC_DIR" 352 353 # 1. Ferramentas Suckless 354 for repo in $REPOS; do 355 REPO_DIR="$SRC_DIR/$repo" 356 357 if [ -d "$REPO_DIR" ]; then 358 echo "Git: repositório $repo já existe, atualizando..." 359 (cd "$REPO_DIR" && git pull) || log_warn "Falha ao atualizar $repo." 360 else 361 echo "Clonando $repo..." 362 git clone "$BASE_URL/$repo.git" "$REPO_DIR" || log_warn "Falha ao clonar $repo." 363 fi 364 365 if [ -d "$REPO_DIR" ]; then 366 echo "Compilando $repo..." 367 (cd "$REPO_DIR" && doas make clean install) || log_fail "Compilação de '$repo'." 368 fi 369 done 370 371 # 2. nsxiv 372 NSXIV_DIR="$SRC_DIR/nsxiv" 373 if [ -d "$NSXIV_DIR" ]; then 374 echo "Git: repositório nsxiv já existe, atualizando..." 375 (cd "$NSXIV_DIR" && git pull) || log_warn "Falha ao atualizar nsxiv." 376 else 377 echo "Clonando nsxiv..." 378 git clone "https://codeberg.org/nsxiv/nsxiv.git" "$NSXIV_DIR" || log_warn "Falha ao clonar nsxiv." 379 fi 380 381 if [ -d "$NSXIV_DIR" ]; then 382 echo "Compilando nsxiv..." 383 (cd "$NSXIV_DIR" && doas make clean install) || log_fail "Compilação de 'nsxiv'." 384 fi 385 386 log_ok "Ferramentas compiladas." 387 } 388 389 install_lf() { 390 echo "Instalando LF (file manager)..." 391 mkdir -p "$GOPATH" 392 CGO_ENABLED=0 go install -ldflags="-s -w" github.com/gokcehan/lf@latest || die "Falha ao instalar lf via go." 393 394 if [ -f "$GOBIN/lf" ]; then 395 doas mv "$GOBIN/lf" /usr/local/bin/ 396 log_ok "lf instalado em /usr/local/bin/." 397 else 398 log_warn "Binário lf não encontrado após go install." 399 fi 400 } 401 402 setup_vim() { 403 echo "Configurando plugins do Vim..." 404 if command -v vim >/dev/null; then 405 curl -fLo "$HOME/.config/vim/plugin/pm.vim" --create-dirs "https://git.sr.ht/~bpv/pm/blob/master/pm.vim" 406 vim +DownloadPlugins +qall || log_warn "Falha ao instalar plugins do Vim." 407 log_ok "Vim configurado." 408 else 409 log_warn "Vim não encontrado, pulando setup." 410 fi 411 } 412 413 setup_ffsetup() { 414 echo "Configurando Firefox (ffsetup)..." 415 git clone "$BASE_URL/ffsetup.git" "/tmp/ffsetup" || log_warn "Falha ao clonar ffsetup." 416 417 if [ -d "/tmp/ffsetup" ]; then 418 (cd "/tmp/ffsetup" && chmod +x ffsetup.sh && ./ffsetup.sh) || log_warn "Falha ao executar ffsetup.sh." 419 rm -rf "/tmp/ffsetup" 420 log_ok "ffsetup concluído." 421 fi 422 } 423 424 # ─── Fluxo completo (Config) ────────────────────────────────────────────────── 425 426 run_full_installation() { 427 # Confirmação antes de rodar tudo 428 printf "Isso vai executar a instalação completa (repos, pacotes, permissões, dotfiles, etc). Continuar? [s/N] " 429 read -r resp 430 case "$resp" in 431 s|S|sim|Sim) ;; 432 *) echo "Instalação cancelada."; exit 0 ;; 433 esac 434 435 setup_repos 436 install_packages 437 setup_permissions 438 setup_services 439 setup_dotfiles 440 install_source_tools 441 install_lf 442 setup_vim 443 setup_ffsetup 444 445 echo "" 446 echo "──────────────────────" 447 echo " Instalação concluída " 448 echo "──────────────────────" 449 450 # Resumo final de falhas 451 if [ -n "$GLOBAL_FAILURES" ]; then 452 printf "${YELLOW}Resumo de etapas com falha durante a instalação:${NC}\n" 453 printf "%b\n" "$GLOBAL_FAILURES" 454 else 455 log_ok "Nenhuma falha registrada durante a instalação." 456 fi 457 echo "Log completo salvo em: $LOG_FILE" 458 } 459 460 # ─── Pacotes ────────────────────────────────────────────────────── 461 462 # brightnessctl: ajuste de brilho de tela 463 # setxkbmap: definição de layout do teclado 464 # xclip: gerenciador da área de transferência (clipboard) 465 # xdotool / xsetroot: automação e manipulação da barra de status 466 # xautolock: bloqueio automático de tela por inatividade 467 # unclutter-xfixes: oculta o cursor do mouse quando inativo 468 # xf86-...-libinput: driver do Xorg para funcionamento de touchpads/mouses 469 # go: linguagem Golang (usada para instalar o LF) 470 # curl / openssh: requisições web e acessos remotos seguros 471 # lynx /w3m/ / firefox: navegadores (um cli minimalista e um gráfico completo) 472 # netcat / iproute2: ferramentas essenciais de diagnóstico de rede 473 # fzf / jq / grep: buscadores e manipuladores de texto/arquivos JSON 474 # ncurses: biblioteca base para interfaces ricas no terminal 475 # maim / slop: ferramentas para captura de tela (screenshot) 476 # mpv / ffmpeg: player de vídeo leve e motor de conversão de mídia 477 # aerc: cliente de email para terminal 478 # zathura: leitor minimalista para PDFs e e-books 479 # sc-im: editor de planilhas para o terminal (estilo vim) 480 # hugo / pandoc / typst: criadores de sites estáticos, conversores e tipografia 481 # gnupg / pass[-otp]: criptografia de arquivos e gerenciador de senhas 482 # dbus / dbus-x11: barramento de comunicação inter-processos no Linux 483 484 # ─── Controle do Roteamento de Comandos ─────────────────────────────────────── 485 486 check_dependencies 487 488 case "$1" in 489 # Módulos individuais 490 repos) setup_repos ;; 491 pacotes) install_packages ;; 492 permissoes) setup_permissions ;; 493 servicos) setup_services ;; 494 dotfiles) setup_dotfiles ;; 495 ferramentas) install_source_tools ;; 496 lf) install_lf ;; 497 vim) setup_vim ;; 498 ffsetup) setup_ffsetup ;; 499 500 # Fluxos e extras originais 501 config) run_full_installation ;; 502 alpine) setup_alpine_answers ;; 503 bookmarks) setup_bookmarks ;; 504 ssh) setup_ssh ;; 505 fontes) install_all_fonts ;; 506 adb) setup_android ;; 507 mail) setup_email ;; 508 ajuda|"") show_help ;; 509 *) echo "Comando inválido: $1"; show_help; exit 1 ;; 510 esac