dotfiles

Repositório dotfiles
git clone git://git.sivaldodavi.com/dotfiles.git
Log | Files | Refs | README

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