#!/bin/bash # # setup-mariadb-dbeaver.sh # --------------------------------------------------------------------------- # Instala MariaDB Community Server + DBeaver CE em Debian/Ubuntu, # define senha de acesso local e já cria a conexão dentro do DBeaver. # # Uso: ./setup-mariadb-dbeaver.sh (ele mesmo se eleva) # sudo ./setup-mariadb-dbeaver.sh # # Se o usuário logado não tiver sudo (ex.: "escola"), o script se reexecuta # através de uma conta administrativa (ex.: "pedagogico") via `su -`, pedindo # a senha dessa conta. A conexão do DBeaver continua sendo criada no home do # usuário que INICIOU o script, não no do administrador. # # Variáveis de ambiente opcionais: # ADMIN_USER=... conta com sudo (padrão: pedagogico) # DESKTOP_USER=... dono do workspace DBeaver (padrão: quem chamou) # DB_PASSWORD=... senha do root (padrão: CEP2026) # DB_NAME=... banco de exemplo (padrão: estudo) # MARIADB_VERSION=... versão do repo (padrão: 11.4) # USE_MARIADB_REPO=0 usa o pacote da distro em vez do repo oficial # CONFIGURE_DBEAVER=0 não mexe no workspace do DBeaver # DBEAVER_USERS=all todos os homes (padrão) ou "escola,professor" # CONFIGURE_SKEL=0 não grava o modelo em /etc/skel # # ATENÇÃO: senha fraca / root com senha em texto plano no config do DBeaver. # Ambiente de estudo apenas — não use em produção. # --------------------------------------------------------------------------- set -euo pipefail ADMIN_USER="${ADMIN_USER:-pedagogico}" DESKTOP_USER="${DESKTOP_USER:-}" DB_PASSWORD="${DB_PASSWORD:-CEP2026}" DB_NAME="${DB_NAME:-estudo}" DB_HOST="127.0.0.1" DB_PORT="3306" MARIADB_VERSION="${MARIADB_VERSION:-11.4}" USE_MARIADB_REPO="${USE_MARIADB_REPO:-1}" CONFIGURE_DBEAVER="${CONFIGURE_DBEAVER:-1}" DBEAVER_USERS="${DBEAVER_USERS:-all}" CONFIGURE_SKEL="${CONFIGURE_SKEL:-1}" DBEAVER_URL="https://dbeaver.io/files/dbeaver-ce-latest-linux-x86_64.deb" DS_ID="mariadb-local-cep" export DEBIAN_FRONTEND=noninteractive # -------------------------------------------------------------------------- # helpers # -------------------------------------------------------------------------- log() { printf '\n\033[1;34m==>\033[0m %s\n' "$*"; } ok() { printf '\033[1;32m ok\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m[aviso]\033[0m %s\n' "$*" >&2; } die() { printf '\033[1;31m[erro]\033[0m %s\n' "$*" >&2; exit 1; } json_escape() { printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g'; } sql_escape() { printf '%s' "${1//\'/\'\'}"; } cleanup() { [ -n "${TMPDIR_WORK:-}" ] && rm -rf "$TMPDIR_WORK" [ -n "${SELF_TMP:-}" ] && rm -f "$SELF_TMP" return 0 } trap cleanup EXIT # -------------------------------------------------------------------------- # 0. Elevação de privilégio # root -> segue # tem sudo -> sudo -E # não tem sudo -> su - $ADMIN_USER -c "sudo ... script" # -------------------------------------------------------------------------- if [ "$(id -u)" -ne 0 ]; then CALLER="$(id -un)" : "${DESKTOP_USER:=$CALLER}" export DESKTOP_USER SCRIPT_PATH="$(readlink -f "$0")" if sudo -n -v 2>/dev/null \ || id -nG "$CALLER" | tr ' ' '\n' | grep -qxE 'sudo|admin|wheel|root'; then log "Elevando privilégios com sudo (usuário ${CALLER})" exec sudo -E DESKTOP_USER="$DESKTOP_USER" bash "$SCRIPT_PATH" "$@" fi # --- caminho "escola -> pedagogico" --------------------------------- log "'${CALLER}' não tem sudo; tentando via conta administrativa '${ADMIN_USER}'" getent passwd "$ADMIN_USER" >/dev/null \ || die "A conta '${ADMIN_USER}' não existe. Use: ADMIN_USER= $0" [ -t 0 ] || die "Sem terminal interativo: o 'su' não conseguirá pedir a senha. Rode este script direto num terminal (não por pipe/cron)." # o home de '${CALLER}' pode ser 0700; copia para um local legível por todos SELF_TMP="$(mktemp /tmp/setup-mariadb-dbeaver.XXXXXX.sh)" cat "$SCRIPT_PATH" > "$SELF_TMP" chmod 0755 "$SELF_TMP" # su - limpa o ambiente, então as variáveis vão explícitas na linha do sudo ELEV_CMD="" [ "$ADMIN_USER" != "root" ] && ELEV_CMD="sudo" for _v in DESKTOP_USER DB_PASSWORD DB_NAME MARIADB_VERSION \ USE_MARIADB_REPO CONFIGURE_DBEAVER DBEAVER_USERS CONFIGURE_SKEL SELF_TMP; do ELEV_CMD="${ELEV_CMD} $(printf '%q' "${_v}=${!_v}")" done ELEV_CMD="${ELEV_CMD} bash $(printf '%q' "$SELF_TMP")" printf '\n Digite a senha de \033[1m%s\033[0m' "$ADMIN_USER" [ "$ADMIN_USER" != "root" ] && printf ' (e depois a do sudo, se for pedida)' printf ':\n' SELF_TMP="" # quem apaga é a instância elevada, via SELF_TMP herdado exec su - "$ADMIN_USER" -c "$ELEV_CMD" fi # a partir daqui somos root TARGET_USER="${DESKTOP_USER:-${SUDO_USER:-root}}" getent passwd "$TARGET_USER" >/dev/null \ || die "Usuário '${TARGET_USER}' não existe (confira DESKTOP_USER)." TARGET_HOME="$(getent passwd "$TARGET_USER" | cut -d: -f6)" [ -d "$TARGET_HOME" ] || die "Não achei o home de $TARGET_USER" TARGET_GROUP="$(id -gn "$TARGET_USER")" TMPDIR_WORK="$(mktemp -d)" # -------------------------------------------------------------------------- # 1. apt update + dependências básicas # -------------------------------------------------------------------------- log "Atualizando índices do APT" apt-get update -y log "Instalando dependências básicas" apt-get install -y --no-install-recommends \ ca-certificates curl wget gnupg apt-transport-https openssl # -------------------------------------------------------------------------- # 2. MariaDB Community Server # -------------------------------------------------------------------------- install_from_distro() { log "Instalando MariaDB do repositório da distribuição" apt-get install -y mariadb-server mariadb-client } if [ "$USE_MARIADB_REPO" = "1" ]; then log "Configurando repositório oficial MariaDB Community ${MARIADB_VERSION}" if curl -fsSL https://r.mariadb.com/downloads/mariadb_repo_setup \ -o "$TMPDIR_WORK/mariadb_repo_setup" \ && bash "$TMPDIR_WORK/mariadb_repo_setup" \ --mariadb-server-version="mariadb-${MARIADB_VERSION}" --skip-maxscale; then apt-get update -y log "Instalando MariaDB Community Server ${MARIADB_VERSION}" if ! apt-get install -y mariadb-server mariadb-client mariadb-backup; then warn "Falhou pelo repo oficial; caindo para o pacote da distro." rm -f /etc/apt/sources.list.d/mariadb.list \ /etc/apt/sources.list.d/mariadb.sources 2>/dev/null || true apt-get update -y install_from_distro fi else warn "Não consegui configurar o repo oficial da MariaDB." install_from_distro fi else install_from_distro fi # cliente pode se chamar mariadb ou mysql dependendo da versão MYSQL_BIN="$(command -v mariadb || command -v mysql || true)" [ -n "$MYSQL_BIN" ] || die "Cliente MariaDB não encontrado após a instalação." # -------------------------------------------------------------------------- # 3. Subir o serviço # -------------------------------------------------------------------------- log "Habilitando e iniciando o serviço mariadb" if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then systemctl enable --now mariadb else warn "systemd indisponível (container/WSL?), usando 'service'." service mariadb start || service mysql start fi # espera o socket responder for i in $(seq 1 30); do if "$MYSQL_BIN" --protocol=socket -u root -e 'SELECT 1' >/dev/null 2>&1; then break fi [ "$i" -eq 30 ] && warn "Servidor demorou a responder no socket." sleep 1 done # -------------------------------------------------------------------------- # 4. Senha do root + usuário para acesso via 127.0.0.1 # -------------------------------------------------------------------------- log "Definindo senha do root e criando o banco '${DB_NAME}'" PW_SQL="$(sql_escape "$DB_PASSWORD")" if "$MYSQL_BIN" --protocol=socket -u root </dev/null; then ok "Login TCP funcionando." else warn "Login via 127.0.0.1 falhou — confira o bind-address em /etc/mysql/." fi # -------------------------------------------------------------------------- # 5. DBeaver CE # -------------------------------------------------------------------------- DEB_FILE="$TMPDIR_WORK/dbeaver-ce-latest-linux-x86_64.deb" log "Baixando o DBeaver CE" curl -fL --retry 3 -o "$DEB_FILE" "$DBEAVER_URL" || die "Download do DBeaver falhou." ok "$(du -h "$DEB_FILE" | cut -f1) baixados." log "Instalando o DBeaver CE" apt-get install -y "$DEB_FILE" ok "DBeaver instalado: $(command -v dbeaver || echo '/usr/share/dbeaver-ce')" # -------------------------------------------------------------------------- # 6. Pré-configurar a conexão no workspace do DBeaver # O DBeaver é instalado em nível de sistema, mas o perfil é por usuário. # Aqui provisionamos TODOS os usuários reais + /root + /etc/skel. # -------------------------------------------------------------------------- # JSON da conexão (idêntico para todos os perfis) read -r -d '' DS_JSON < [usuario] [grupo] # Sem usuario/grupo (caso do /etc/skel) o chown é pulado. dbeaver_profile() { local base="$1" user="${2:-}" group="${3:-}" local ws="$base/.local/share/DBeaverData/workspace6/General/.dbeaver" local f stamp mkdir -p "$ws" || { warn "não consegui criar $ws"; return 1; } stamp="$(date +%Y%m%d%H%M%S)" for f in data-sources.json credentials-config.json; do [ -f "$ws/$f" ] && cp -a "$ws/$f" "$ws/$f.bak.$stamp" done printf '%s\n' "$DS_JSON" > "$ws/data-sources.json" # credentials-config.json: AES-128-CBC, chave fixa do DBeaver CE, # com 16 bytes aleatórios de prefixo no início do texto claro. if { head -c 16 /dev/urandom; printf '%s' "$CRED_JSON"; } | \ openssl enc -aes-128-cbc -nosalt \ -K babb4a9f774ab853c96c2d653dfe544a \ -iv 00000000000000000000000000000000 \ -out "$ws/credentials-config.json" 2>/dev/null then chmod 600 "$ws/credentials-config.json" else warn "senha não gravada em $base — o DBeaver vai pedir na conexão." sed -i 's/"save-password": true/"save-password": false/' "$ws/data-sources.json" rm -f "$ws/credentials-config.json" fi if [ -n "$user" ]; then chown -R "$user:$group" "$base/.local/share/DBeaverData" # garante que o usuário atravesse os diretórios recém-criados chown "$user:$group" "$base/.local" "$base/.local/share" 2>/dev/null || true fi return 0 } if [ "$CONFIGURE_DBEAVER" != "1" ]; then log "Configuração do DBeaver desabilitada (CONFIGURE_DBEAVER=0)." else log "Provisionando o perfil do DBeaver para os usuários da máquina" # monta a lista de alvos: usuário:home:grupo TARGETS="" if [ "$DBEAVER_USERS" = "all" ]; then while IFS=: read -r u _ uid gid _ home shell; do # root entra; contas de sistema (uid<1000) e nobody (65534) ficam de fora if [ "$uid" -ne 0 ]; then [ "$uid" -lt 1000 ] && continue [ "$uid" -ge 65534 ] && continue fi case "$shell" in */nologin|*/false|/bin/sync) continue ;; esac case "$home" in /home/*|/root) ;; *) continue ;; esac [ -d "$home" ] || { warn "home inexistente, pulando: $u ($home)"; continue; } TARGETS="${TARGETS}${u}:${home}:$(getent group "$gid" | cut -d: -f1)"$'\n' done < <(getent passwd) else for u in ${DBEAVER_USERS//,/ }; do ent="$(getent passwd "$u" || true)" [ -n "$ent" ] || { warn "usuário '$u' não existe, pulando."; continue; } home="$(printf '%s' "$ent" | cut -d: -f6)" [ -d "$home" ] || { warn "home inexistente, pulando: $u"; continue; } TARGETS="${TARGETS}${u}:${home}:$(id -gn "$u")"$'\n' done fi COUNT=0 while IFS=: read -r u home grp; do [ -n "$u" ] || continue if pgrep -u "$u" -f dbeaver >/dev/null 2>&1; then warn "DBeaver aberto em '$u' — ele sobrescreve o config ao fechar." fi if dbeaver_profile "$home" "$u" "$grp"; then ok "perfil criado: ${u} (${home})" COUNT=$((COUNT + 1)) fi done <<< "$TARGETS" # avisa sobre pastas órfãs em /home (sem usuário correspondente) for d in /home/*/; do [ -d "$d" ] || continue u="$(basename "$d")" getent passwd "$u" >/dev/null || warn "/home/${u} não corresponde a nenhum usuário — ignorado." done # perfil-modelo: usuários criados DEPOIS já nascem com a conexão if [ "$CONFIGURE_SKEL" = "1" ] && [ -d /etc/skel ]; then if dbeaver_profile /etc/skel; then ok "modelo gravado em /etc/skel (vale para contas futuras)" fi fi ok "Conexão \"MariaDB local (${DB_NAME})\" provisionada em ${COUNT} perfil(is)." fi # -------------------------------------------------------------------------- # Resumo # -------------------------------------------------------------------------- cat </dev/null || echo instalado) Host/Porta : ${DB_HOST}:${DB_PORT} Usuário : root Senha : ${DB_PASSWORD} Banco : ${DB_NAME} CLI : mariadb -h ${DB_HOST} -u root -p GUI : a conexão já está cadastrada no DBeaver de todos os usuários locais (na 1ª conexão ele baixa o driver JDBC da MariaDB — precisa de internet) sudo mariadb continua funcionando sem senha (unix_socket preservado). ------------------------------------------------------------------ EOF