commit ea90025ff8da96cde74ec5c325d6e29baeda7f32 Author: drbit-admin Date: Fri Jun 12 15:32:21 2026 -0300 feat: adicionar drbit-new-client.sh (espelho do repo Dashboard) diff --git a/drbit-new-client.sh b/drbit-new-client.sh new file mode 100755 index 0000000..ab21651 --- /dev/null +++ b/drbit-new-client.sh @@ -0,0 +1,271 @@ +#!/usr/bin/env bash +# +# drbit-new-client.sh — provisiona uma VM nova para um cliente DRBIT +# +# Roda no shell do HOST PROXMOX. Não depende de nenhuma VM/template +# pré-existente: baixa a imagem cloud oficial do Ubuntu 24.04, cria a VM +# do zero (qm create + qm importdisk) e anexa um drive de cloud-init que, +# no primeiro boot, clona o repo da intranet e roda install.sh. +# +# Ver wiki/projetos/intranet/provisionamento-novo-cliente.md para o +# contexto arquitetural completo. +# +# Uso: +# ./drbit-new-client.sh --nome ecp [--ip 192.168.1.80 --gw 192.168.1.1] [opções] +# +# Por padrão a VM sobe com DHCP (igual ao modelo community-scripts — fica a +# critério de quem provisiona definir IP fixo depois). Se --ip for informado, +# a VM já sobe com IP estático. +# +# ⚠️ Para clientes que vão virar Domínio AD (Samba 4 AD DC), o IP PRECISA +# ser fixo — defina --ip/--gw aqui, ou configure manualmente depois via +# netplan (ver wiki/infraestrutura/template-vm.md) antes do Setup Wizard +# provisionar o AD. +# +# Opções: +# --nome obrigatório — vira hostname srv- e nome da VM +# --ip opcional — IP estático da VM (ex: 192.168.1.80). Sem isso, usa DHCP +# --gw default: 192.168.1.1 (só usado com --ip) +# --vmid default: próximo livre (pvesh get /cluster/nextid) +# --cores default: 2 +# --ram default: 2048 +# --disk default: 32 +# --bridge default: vmbr0 +# --storage default: local-lvm +# --ssh-key default: ~/.ssh/id_drbit_lab.pub +# --repo-url default: https://git.drbit.tec.br/drbit/Dashboard.git +# Repo privado — passe a URL com o token de provisionamento +# embutido (usuário drbit-provisioning, token read-only): +# https://drbit-provisioning:@git.drbit.tec.br/drbit/Dashboard.git +# +set -euo pipefail + +# ── defaults ────────────────────────────────────────────────────────────── +GW="192.168.1.1" +VMID="" +CORES=2 +RAM=2048 +DISK=32 +BRIDGE="vmbr0" +STORAGE="local-lvm" +SSH_KEY_FILE="$HOME/.ssh/id_drbit_lab.pub" + +UBUNTU_RELEASE="noble" +IMG_URL="https://cloud-images.ubuntu.com/releases/${UBUNTU_RELEASE}/release/ubuntu-24.04-server-cloudimg-amd64.img" +IMG_CACHE="/var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img" +REPO_URL="https://git.drbit.tec.br/drbit/Dashboard.git" + +NOME="" +IP="" + +# ── helpers ─────────────────────────────────────────────────────────────── +msg_info() { echo -e " \033[1;34m➜\033[0m $*"; } +msg_ok() { echo -e " \033[1;32m✓\033[0m $*"; } +msg_error() { echo -e " \033[1;31m✗\033[0m $*" >&2; } + +# ── parse args ──────────────────────────────────────────────────────────── +while [[ $# -gt 0 ]]; do + case "$1" in + --nome) NOME="$2"; shift 2 ;; + --ip) IP="$2"; shift 2 ;; + --gw) GW="$2"; shift 2 ;; + --vmid) VMID="$2"; shift 2 ;; + --cores) CORES="$2"; shift 2 ;; + --ram) RAM="$2"; shift 2 ;; + --disk) DISK="$2"; shift 2 ;; + --bridge) BRIDGE="$2"; shift 2 ;; + --storage) STORAGE="$2"; shift 2 ;; + --ssh-key) SSH_KEY_FILE="$2"; shift 2 ;; + --repo-url) REPO_URL="$2"; shift 2 ;; + *) msg_error "Argumento desconhecido: $1"; exit 1 ;; + esac +done + +# ── validações ──────────────────────────────────────────────────────────── +if [[ -z "$NOME" ]]; then + msg_error "Uso: $0 --nome [--ip --gw ] [opções]" + exit 1 +fi + +if ! command -v qm &>/dev/null; then + msg_error "Comando 'qm' não encontrado — este script roda no host Proxmox." + exit 1 +fi + +if [[ ! -f "$SSH_KEY_FILE" ]]; then + msg_error "Chave pública SSH não encontrada em: $SSH_KEY_FILE (use --ssh-key)" + exit 1 +fi + +HOSTNAME="srv-${NOME}" + +if [[ -z "$VMID" ]]; then + VMID=$(pvesh get /cluster/nextid) +fi + +if [[ -n "$IP" ]]; then + msg_info "Provisionando VM '$HOSTNAME' (VMID $VMID, IP estático $IP)" +else + msg_info "Provisionando VM '$HOSTNAME' (VMID $VMID, IP via DHCP)" +fi + +# ── 1. cache da imagem cloud oficial ───────────────────────────────────── +if [[ -f "$IMG_CACHE" ]]; then + msg_ok "Imagem Ubuntu 24.04 cloud já em cache: $IMG_CACHE" +else + msg_info "Baixando imagem Ubuntu 24.04 cloud (cloud-images.ubuntu.com)..." + mkdir -p "$(dirname "$IMG_CACHE")" + curl -fsSL -o "$IMG_CACHE" "$IMG_URL" + msg_ok "Imagem baixada: $IMG_CACHE" +fi + +# ── 2. garantir que a storage 'local' suporta snippets ─────────────────── +CONTENT=$(awk '/^dir: local$/{f=1; next} f && /^\tcontent/ {print $2; exit} /^[a-z]/{f=0}' /etc/pve/storage.cfg) +if [[ "$CONTENT" != *snippets* ]]; then + msg_info "Habilitando 'snippets' na storage local..." + pvesm set local --content "${CONTENT},snippets" + msg_ok "Storage 'local' agora aceita snippets" +else + msg_ok "Storage 'local' já aceita snippets" +fi + +# ── 3. gerar cloud-init user-data ──────────────────────────────────────── +SSH_PUBKEY=$(cat "$SSH_KEY_FILE") +SNIPPET_PATH="/var/lib/vz/snippets/drbit-${VMID}.yaml" +mkdir -p /var/lib/vz/snippets + +msg_info "Gerando cloud-init user-data ($SNIPPET_PATH)..." +cat > "$SNIPPET_PATH" </dev/null 2>&1; do sleep 5; done + - git clone ${REPO_URL} /opt/drbit-intranet + - bash /opt/drbit-intranet/install.sh +EOF +msg_ok "user-data gerado" + +# ── 4. criar VM ─────────────────────────────────────────────────────────── +msg_info "Criando VM $VMID..." +qm create "$VMID" \ + -name "$HOSTNAME" \ + -memory "$RAM" \ + -cores "$CORES" \ + -net0 "virtio,bridge=${BRIDGE}" \ + -ostype l26 \ + -scsihw virtio-scsi-pci \ + -agent 1 +msg_ok "VM criada" + +# ── 5. importar disco ──────────────────────────────────────────────────── +msg_info "Importando imagem como disco..." +qm importdisk "$VMID" "$IMG_CACHE" "$STORAGE" + +# o disco importado fica como "unused0" na config da VM +DISK_REF=$(qm config "$VMID" | grep -oP '^unused0:\s*\K.*') +if [[ -z "$DISK_REF" ]]; then + msg_error "Não foi possível identificar o disco importado (unused0 não encontrado)." + qm config "$VMID" + exit 1 +fi + +msg_info "Anexando disco ($DISK_REF)..." +qm set "$VMID" -scsi0 "$DISK_REF" +msg_ok "Disco anexado" + +msg_info "Redimensionando disco para ${DISK}G..." +qm resize "$VMID" scsi0 "${DISK}G" +msg_ok "Disco redimensionado (cloud-init faz growpart/resizefs no primeiro boot)" + +# ── 6. cloud-init drive + boot + rede ──────────────────────────────────── +if [[ -n "$IP" ]]; then + IPCONFIG="ip=${IP}/24,gw=${GW}" + msg_info "Configurando cloud-init e rede (IP estático ${IP}/24, gw ${GW})..." +else + IPCONFIG="ip=dhcp" + msg_info "Configurando cloud-init e rede (DHCP)..." +fi + +qm set "$VMID" \ + -ide2 "${STORAGE}:cloudinit" \ + -boot order=scsi0 \ + -serial0 socket -vga serial0 \ + -ipconfig0 "$IPCONFIG" \ + -nameserver "1.1.1.1 8.8.8.8" \ + -cicustom "user=local:snippets/drbit-${VMID}.yaml" +msg_ok "Cloud-init configurado" + +# ── 7. iniciar ──────────────────────────────────────────────────────────── +msg_info "Iniciando VM..." +qm start "$VMID" +msg_ok "VM iniciada" + +# ── 8. descobrir IP (DHCP) e aguardar Setup Wizard responder ───────────── +FINAL_IP="$IP" + +if [[ -z "$FINAL_IP" ]]; then + msg_info "Aguardando guest agent informar o IP (DHCP, até 5min)..." + DEADLINE=$((SECONDS + 300)) + while (( SECONDS < DEADLINE )); do + FINAL_IP=$(qm guest cmd "$VMID" network-get-interfaces 2>/dev/null \ + | grep -oP '"ip-address"\s*:\s*"\K[0-9.]+' \ + | grep -vE '^(127\.|169\.254\.)' \ + | head -1 || true) + [[ -n "$FINAL_IP" ]] && break + sleep 10 + done + + if [[ -z "$FINAL_IP" ]]; then + msg_error "Não foi possível descobrir o IP via guest agent. Verifique com: qm guest cmd $VMID network-get-interfaces" + exit 1 + fi + msg_ok "IP detectado via DHCP: $FINAL_IP" +fi + +msg_info "Aguardando o Setup Wizard subir em http://${FINAL_IP}/setup (até 10min)..." +DEADLINE=$((SECONDS + 600)) +while (( SECONDS < DEADLINE )); do + if curl -sf -o /dev/null "http://${FINAL_IP}/setup"; then + msg_ok "Setup Wizard respondendo!" + break + fi + sleep 10 +done + +if ! curl -sf -o /dev/null "http://${FINAL_IP}/setup"; then + msg_error "Timeout aguardando o Setup Wizard. Verifique a VM (qm terminal $VMID) e o cloud-init (/var/log/cloud-init-output.log)." + exit 1 +fi + +# ── 9. resumo ───────────────────────────────────────────────────────────── +echo "" +echo "──────────────────────────────────────────" +echo " VM $VMID ($HOSTNAME) pronta!" +echo "" +echo " Acesse o Setup Wizard:" +echo " http://${FINAL_IP}/setup" +echo "" +echo " SSH: ssh drbit@${FINAL_IP} (chave $SSH_KEY_FILE ou senha b1tadmin)" +echo " ⚠️ Trocar a senha padrão 'b1tadmin' em produção." +if [[ -z "$IP" ]]; then +echo "" +echo " ⚠️ IP via DHCP ($FINAL_IP). Para Domínio AD (Samba 4 AD DC), defina" +echo " IP fixo antes de provisionar o AD pelo Setup Wizard:" +echo " editar /etc/netplan/50-cloud-init.yaml (ou criar 99-static.yaml)" +echo " → sudo netplan apply" +fi +echo "──────────────────────────────────────────"