197 lines
11 KiB
Bash
197 lines
11 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
# IRIDE — Installer ambiente base
|
||
|
|
# Tecnotel Servizi SRL — Ubuntu 24.04 / 26.04 LTS
|
||
|
|
# Uso: sudo bash first-setup.sh (lanciato da bootstrap.sh)
|
||
|
|
#
|
||
|
|
# Stesso hardening di argos-setup: aggiornamento del sistema, UFW con default
|
||
|
|
# deny, fail2ban, utente di servizio senza privilegi con sudoers a scope
|
||
|
|
# ristretto, nginx temporaneo, Web Installer su 8888 chiuso a fine wizard.
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||
|
|
BLUE='\033[0;34m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||
|
|
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
|
||
|
|
success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||
|
|
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
||
|
|
section() { echo -e "\n${BLUE}══════════════════════════════════════${NC}"; echo -e "${BLUE} $1${NC}"; echo -e "${BLUE}══════════════════════════════════════${NC}"; }
|
||
|
|
|
||
|
|
[[ $EUID -ne 0 ]] && error "Eseguire come root: sudo bash first-setup.sh"
|
||
|
|
. /etc/os-release
|
||
|
|
SUPPORTED_VERSIONS=("24.04" "26.04")
|
||
|
|
VERSION_OK=0
|
||
|
|
for v in "${SUPPORTED_VERSIONS[@]}"; do
|
||
|
|
[[ "$VERSION_ID" == "$v" ]] && VERSION_OK=1
|
||
|
|
done
|
||
|
|
[[ "$ID" != "ubuntu" || $VERSION_OK -eq 0 ]] && \
|
||
|
|
error "Richiesto Ubuntu 24.04 o 26.04 LTS (rilevato: $ID $VERSION_ID)"
|
||
|
|
info "Sistema rilevato: Ubuntu $VERSION_ID LTS"
|
||
|
|
|
||
|
|
SETUP_PKG="/opt/iride-setup-pkg"
|
||
|
|
APP_USER="iride"
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo -e "${BLUE}╔══════════════════════════════════════════╗${NC}"
|
||
|
|
echo -e "${BLUE}║ IRIDE — Setup ambiente base ║${NC}"
|
||
|
|
echo -e "${BLUE}║ Tecnotel Servizi SRL ║${NC}"
|
||
|
|
echo -e "${BLUE}╚══════════════════════════════════════════╝${NC}"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
section "1. Sistema base"
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
timedatectl set-timezone Europe/Rome
|
||
|
|
export DEBIAN_FRONTEND=noninteractive
|
||
|
|
apt-get update -qq
|
||
|
|
apt-get upgrade -y -qq
|
||
|
|
apt-get install -y -qq \
|
||
|
|
curl wget git vim htop unzip jq \
|
||
|
|
python3 python3-pip python3-venv python3-cryptography python3-dev \
|
||
|
|
nginx certbot python3-certbot-nginx \
|
||
|
|
ufw fail2ban \
|
||
|
|
build-essential libssl-dev libffi-dev \
|
||
|
|
sqlite3 net-tools dnsutils lsof \
|
||
|
|
ca-certificates gnupg apt-transport-https openssl
|
||
|
|
success "Pacchetti sistema installati"
|
||
|
|
|
||
|
|
PY_VER="$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
|
||
|
|
python3 -c 'import sys; sys.exit(0 if sys.version_info >= (3, 12) else 1)' \
|
||
|
|
|| error "Python >= 3.12 richiesto (trovato $PY_VER)"
|
||
|
|
success "Python $PY_VER"
|
||
|
|
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
section "2. Node.js 22 LTS"
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
# Serve alla build del frontend (solo sul server) e alle azioni JavaScript del
|
||
|
|
# Gitea Runner in modalità host (dev-setup.sh).
|
||
|
|
if ! node --version 2>/dev/null | grep -q "v2[2-9]"; then
|
||
|
|
curl -fsSL https://deb.nodesource.com/setup_22.x | bash - >/dev/null 2>&1
|
||
|
|
apt-get install -y -qq nodejs
|
||
|
|
fi
|
||
|
|
success "Node.js $(node --version) installato"
|
||
|
|
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
section "3. Utente applicazione"
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
if ! id "$APP_USER" &>/dev/null; then
|
||
|
|
useradd -r -s /bin/bash -m -d /home/$APP_USER $APP_USER
|
||
|
|
success "Utente $APP_USER creato"
|
||
|
|
else
|
||
|
|
warn "Utente $APP_USER già esistente"
|
||
|
|
fi
|
||
|
|
usermod -aG systemd-journal $APP_USER
|
||
|
|
success "Utente $APP_USER nel gruppo systemd-journal (lettura log dal portale)"
|
||
|
|
|
||
|
|
# Restart dei soli demoni IRIDE dal portale (nessun altro comando)
|
||
|
|
cat > /etc/sudoers.d/iride-systemctl <<'SUDOEOF'
|
||
|
|
iride ALL=(ALL) NOPASSWD: /bin/systemctl restart iride-api
|
||
|
|
iride ALL=(ALL) NOPASSWD: /bin/systemctl restart iride-worker
|
||
|
|
iride ALL=(ALL) NOPASSWD: /bin/systemctl restart iride-scheduler
|
||
|
|
iride ALL=(ALL) NOPASSWD: /bin/systemctl restart iride-voice
|
||
|
|
SUDOEOF
|
||
|
|
chmod 440 /etc/sudoers.d/iride-systemctl
|
||
|
|
visudo -cf /etc/sudoers.d/iride-systemctl > /dev/null
|
||
|
|
success "Sudoers per restart servizi configurato"
|
||
|
|
|
||
|
|
# update.sh dal portale: SOLO quello script, path esatto (symlink /usr/bin/bash e /bin/bash)
|
||
|
|
cat > /etc/sudoers.d/iride-update <<'SUDOEOF'
|
||
|
|
iride ALL=(root) NOPASSWD: /usr/bin/bash /opt/iride/app/scripts/update.sh
|
||
|
|
iride ALL=(root) NOPASSWD: /bin/bash /opt/iride/app/scripts/update.sh
|
||
|
|
SUDOEOF
|
||
|
|
chmod 440 /etc/sudoers.d/iride-update
|
||
|
|
visudo -cf /etc/sudoers.d/iride-update > /dev/null
|
||
|
|
success "Sudoers per update.sh dal portale configurato"
|
||
|
|
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
section "4. Struttura cartelle"
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
mkdir -p /opt/iride/{app,config,data,logs,certs,backups}
|
||
|
|
mkdir -p /opt/iride/config/assets
|
||
|
|
chown -R $APP_USER:$APP_USER /opt/iride
|
||
|
|
chown -R $APP_USER:$APP_USER "$SETUP_PKG"
|
||
|
|
chmod -R 750 /opt/iride
|
||
|
|
chmod 700 /opt/iride/config
|
||
|
|
success "Struttura /opt/iride/ creata"
|
||
|
|
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
section "5. Firewall UFW"
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
ufw --force reset >/dev/null
|
||
|
|
ufw default deny incoming >/dev/null
|
||
|
|
ufw default allow outgoing >/dev/null
|
||
|
|
ufw allow 22/tcp comment 'SSH' >/dev/null
|
||
|
|
ufw allow 80/tcp comment 'HTTP' >/dev/null
|
||
|
|
ufw allow 443/tcp comment 'HTTPS' >/dev/null
|
||
|
|
ufw allow 8888/tcp comment 'IRIDE Web Installer (temporaneo)' >/dev/null
|
||
|
|
ufw --force enable >/dev/null
|
||
|
|
success "Firewall UFW configurato (22, 80, 443, 8888 temporanea)"
|
||
|
|
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
section "6. Fail2ban"
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
systemctl enable --now fail2ban >/dev/null 2>&1
|
||
|
|
success "Fail2ban attivo"
|
||
|
|
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
section "7. Nginx temporaneo"
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
rm -f /etc/nginx/sites-enabled/default
|
||
|
|
cat > /etc/nginx/sites-available/iride-setup << 'NGINX'
|
||
|
|
server {
|
||
|
|
listen 80 default_server;
|
||
|
|
server_name _;
|
||
|
|
return 200 'IRIDE Setup in corso — vai a http://IP:8888';
|
||
|
|
add_header Content-Type text/plain;
|
||
|
|
}
|
||
|
|
NGINX
|
||
|
|
ln -sf /etc/nginx/sites-available/iride-setup /etc/nginx/sites-enabled/
|
||
|
|
nginx -t && systemctl restart nginx
|
||
|
|
success "Nginx temporaneo configurato"
|
||
|
|
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
section "8. Web Installer"
|
||
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
||
|
|
# Gira da /opt/iride-setup-pkg (clone del bootstrap); a fine install la
|
||
|
|
# cartella viene rimossa e la porta 8888 chiusa.
|
||
|
|
cat > /etc/systemd/system/iride-setup.service << 'UNITEOF'
|
||
|
|
[Unit]
|
||
|
|
Description=IRIDE Web Installer
|
||
|
|
After=network.target
|
||
|
|
|
||
|
|
[Service]
|
||
|
|
Type=simple
|
||
|
|
User=root
|
||
|
|
WorkingDirectory=/opt/iride-setup-pkg
|
||
|
|
ExecStart=/usr/bin/python3 /opt/iride-setup-pkg/setup_server.py
|
||
|
|
Restart=on-failure
|
||
|
|
RestartSec=3
|
||
|
|
StandardOutput=journal
|
||
|
|
StandardError=journal
|
||
|
|
SyslogIdentifier=iride-setup
|
||
|
|
|
||
|
|
[Install]
|
||
|
|
WantedBy=multi-user.target
|
||
|
|
|
||
|
|
UNITEOF
|
||
|
|
|
||
|
|
systemctl daemon-reload
|
||
|
|
systemctl enable --now iride-setup
|
||
|
|
success "Web installer avviato"
|
||
|
|
|
||
|
|
SERVER_IP=$(hostname -I | awk '{print $1}')
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo -e "${GREEN}╔══════════════════════════════════════════════════════╗${NC}"
|
||
|
|
echo -e "${GREEN}║ Ambiente pronto! ║${NC}"
|
||
|
|
echo -e "${GREEN}╚══════════════════════════════════════════════════════╝${NC}"
|
||
|
|
echo ""
|
||
|
|
echo -e " ${CYAN}Completa la configurazione aprendo nel browser:${NC}"
|
||
|
|
echo -e " ${YELLOW}→ http://${SERVER_IP}:8888${NC}"
|
||
|
|
echo ""
|
||
|
|
echo -e " ${YELLOW}NOTA:${NC} La porta 8888 verrà chiusa automaticamente"
|
||
|
|
echo -e " al termine dell'installazione."
|
||
|
|
echo -e " Server di sviluppo con runner CI: sudo bash ${SETUP_PKG}/dev-setup.sh --token <token>"
|
||
|
|
echo ""
|