Files
linux-server-setup/scripts/setup.sh
Francesco Picone 0510afa009 Utente opzionale e proposta di estensione LVM nel setup
- La creazione dell'utente non è più obbligatoria: lasciando vuoto il
  nome si usa l'utente corrente (SUDO_USER o root)
- Clona lvm-volume-enlarger in /opt e, se la root è un LV ext* con spazio
  libero nel VG, propone l'esecuzione di enlarge.sh
- Corregge il codename Ubuntu non espanso in docker.sources

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:19:52 +02:00

219 lines
7.1 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# Questo script prepara un Ubuntu Server con utilità di base,
# installa Docker, usa l'utente corrente o ne crea uno nuovo e lo aggiunge al gruppo docker,
# propone l'estensione del volume LVM di root se c'è spazio libero,
# esegue i post-install tramite Make, e deploya Portainer dal repository indicato.
TIMEZONE_DEFAULT="Europe/Rome"
LVM_ENLARGER_REPO="https://repository.pyconetwork.it/francesco/lvm-volume-enlarger.git"
LVM_ENLARGER_DIR="/opt/lvm-volume-enlarger"
require_root() {
if [ "$(id -u)" -ne 0 ]; then
echo "[ERRORE] Esegui questo script come utente root (sudo)." >&2
exit 1
fi
}
prompt_user() {
# Con sudo, l'utente corrente è chi ha lanciato sudo; altrimenti è root
local CURRENT_USER="${SUDO_USER:-$(id -un)}"
read -rp "Nome utente da creare (lascia vuoto per usare l'utente corrente '${CURRENT_USER}'): " TARGET_USER
TARGET_USER=${TARGET_USER:-$CURRENT_USER}
read -rp "Inserisci il timezone (es. Europe/Rome) [${TIMEZONE_DEFAULT}]: " TIMEZONE
TIMEZONE=${TIMEZONE:-$TIMEZONE_DEFAULT}
}
create_user_if_needed() {
if id -u "${TARGET_USER}" >/dev/null 2>&1; then
echo "[INFO] L'utente '${TARGET_USER}' esiste già, procedo."
else
echo "[INFO] Creo l'utente '${TARGET_USER}'."
useradd -m -s /bin/bash "${TARGET_USER}"
echo "[INFO] Imposto la password per '${TARGET_USER}'."
read -srp "Inserisci la password per ${TARGET_USER}: " USER_PASS
echo
echo "${TARGET_USER}:${USER_PASS}" | chpasswd
fi
}
configure_timezone() {
echo "[INFO] Configuro timezone su '${TIMEZONE}'..."
if command -v timedatectl >/dev/null 2>&1; then
timedatectl set-timezone "${TIMEZONE}" || echo "[ATTENZIONE] Impossibile impostare il timezone."
else
echo "[ATTENZIONE] 'timedatectl' non disponibile, salta configurazione timezone."
fi
}
install_base_packages() {
echo "[INFO] Aggiorno il sistema e installo pacchetti di base..."
export DEBIAN_FRONTEND=noninteractive
apt update && apt -y full-upgrade
apt install -y git curl htop zip unzip make
apt autoremove -y --purge
}
# Restituisce 0 se la root è un LV ext2/3/4 e il suo VG ha spazio libero,
# cioè se enlarge.sh (lvextend +100%FREE + resize2fs) può allargarla.
root_lvm_can_grow() {
local ROOT_SRC ROOT_FSTYPE VG_NAME VG_FREE
ROOT_SRC="$(findmnt -n -o SOURCE /)"
ROOT_FSTYPE="$(findmnt -n -o FSTYPE /)"
if [[ "${ROOT_SRC}" != /dev/mapper/* ]]; then
echo "[INFO] Il filesystem root non è su LVM (${ROOT_SRC}), estensione non necessaria."
return 1
fi
if ! command -v lvs >/dev/null 2>&1; then
echo "[ATTENZIONE] Strumenti LVM non disponibili, salto la verifica dello spazio libero."
return 1
fi
case "${ROOT_FSTYPE}" in
ext2|ext3|ext4) ;;
*)
echo "[INFO] Il filesystem root è '${ROOT_FSTYPE}', non supportato da resize2fs: salto l'estensione."
return 1
;;
esac
VG_NAME="$(lvs --noheadings -o vg_name "${ROOT_SRC}" 2>/dev/null | tr -d ' ')"
if [ -z "${VG_NAME}" ]; then
echo "[ATTENZIONE] Impossibile determinare il volume group di ${ROOT_SRC}."
return 1
fi
VG_FREE="$(vgs --noheadings --units b --nosuffix -o vg_free "${VG_NAME}" 2>/dev/null | tr -d ' ')"
if [ -z "${VG_FREE}" ] || [ "${VG_FREE}" -eq 0 ]; then
echo "[INFO] Nessuno spazio libero nel volume group '${VG_NAME}', il disco è già alla dimensione massima."
return 1
fi
echo "[INFO] Il volume group '${VG_NAME}' ha $(numfmt --to=iec "${VG_FREE}") liberi: la root (${ROOT_SRC}) può essere allargata."
return 0
}
clone_and_offer_lvm_enlarge() {
echo "[INFO] Scarico lo script di estensione LVM..."
if [ ! -d "${LVM_ENLARGER_DIR}" ]; then
git clone "${LVM_ENLARGER_REPO}" "${LVM_ENLARGER_DIR}" || {
echo "[ATTENZIONE] Impossibile clonare ${LVM_ENLARGER_REPO}, salto l'estensione LVM."
return 0
}
else
(
cd "${LVM_ENLARGER_DIR}" && git pull --rebase
) || echo "[ATTENZIONE] Impossibile aggiornare ${LVM_ENLARGER_DIR}, uso la versione presente."
fi
if ! root_lvm_can_grow; then
return 0
fi
local ANSWER
read -rp "Vuoi eseguire ora ${LVM_ENLARGER_DIR}/enlarge.sh per allargare il disco? [s/N]: " ANSWER
case "${ANSWER}" in
[sSyY]*)
bash "${LVM_ENLARGER_DIR}/enlarge.sh" || echo "[ATTENZIONE] L'estensione LVM non è andata a buon fine."
;;
*)
echo "[INFO] Estensione saltata. Puoi eseguirla in seguito con: sudo bash ${LVM_ENLARGER_DIR}/enlarge.sh"
;;
esac
}
install_docker() {
echo "[INFO] Preparo repository Docker e installo pacchetti Docker..."
apt update
apt install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker
}
add_user_to_docker_group() {
if [ "${TARGET_USER}" = "root" ]; then
echo "[INFO] L'utente è root, non serve aggiungerlo al gruppo docker."
return 0
fi
echo "[INFO] Aggiungo l'utente '${TARGET_USER}' al gruppo docker..."
groupadd -f docker
usermod -aG docker "${TARGET_USER}"
echo "[INFO] Ricorda: per applicare il gruppo docker, '${TARGET_USER}' deve fare logout/login."
}
run_make_postinstall() {
echo "[INFO] Eseguo Make per installare le utilità post-installazione..."
# Esegue il Makefile nella root del progetto (una cartella sopra 'scripts')
local ROOT_DIR
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)"
make -C "${ROOT_DIR}" postinstall
}
clone_and_deploy_portainer() {
echo "[INFO] Clono il repository Portainer e avvio il deploy..."
local PORTAINER_DIR
PORTAINER_DIR="/opt/portainer"
if [ ! -d "${PORTAINER_DIR}" ]; then
git clone https://git.pyconetwork.it/francesco/portainer.git "${PORTAINER_DIR}"
else
(
cd "${PORTAINER_DIR}" && git pull --rebase
)
fi
(
cd "${PORTAINER_DIR}"
if [ -f docker-compose.yml ] || [ -f compose.yml ]; then
docker compose up -d
else
if [ -f Makefile ]; then
make deploy || true
else
echo "[ATTENZIONE] Nessun docker-compose.yml/compose.yml trovato. Verifica il repository per le istruzioni di deploy."
fi
fi
)
chown -R "${TARGET_USER}":"$(id -gn "${TARGET_USER}")" "${PORTAINER_DIR}"
}
main() {
require_root
prompt_user
create_user_if_needed
configure_timezone
install_base_packages
clone_and_offer_lvm_enlarge
install_docker
add_user_to_docker_group
run_make_postinstall
clone_and_deploy_portainer
echo "[FATTO] Setup completato. Docker è installato e Portainer è stato deployato (se possibile)."
if [ "${TARGET_USER}" = "root" ]; then
echo "- Utente: root"
else
echo "- Utente: ${TARGET_USER} (aggiunto al gruppo docker)"
echo "- Ricorda di eseguire logout/login per applicare i gruppi."
fi
echo "- Timezone: ${TIMEZONE}"
}
main "$@"