feature/generador-instaladores-linux-windows
This commit is contained in:
150
install.sh
150
install.sh
@@ -1,35 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# Instalador Linux de CloudRestoreAS.
|
||||
#
|
||||
# NO instala ni descarga NADA del sistema: el binario es 100% autocontenido
|
||||
# (Qt/xcb, driver ODBC + Kerberos/OpenSSL, y 7-Zip van embebidos). Este script solo
|
||||
# coloca el binario, marca permisos, hace el bootstrap de config/, y opcionalmente
|
||||
# registra el arranque automático (servicio systemd headless o autostart de escritorio).
|
||||
# NO instala ni descarga NADA del sistema: el binario es 100% autocontenido (Qt/xcb,
|
||||
# driver ODBC + Kerberos/OpenSSL, y 7-Zip van embebidos). Este script solo coloca el
|
||||
# binario, marca permisos, hace el bootstrap de config/, opcionalmente siembra las
|
||||
# credenciales del PANEL, y registra el arranque automático (servicio systemd headless
|
||||
# o autostart de escritorio).
|
||||
#
|
||||
# Uso:
|
||||
# sudo ./install.sh --service # 24/7 headless vía systemd (recomendado en servidor)
|
||||
# ./install.sh --desktop # autostart de escritorio (requiere sesión gráfica)
|
||||
# ./install.sh # solo instala; sin arranque automático
|
||||
#
|
||||
# Opciones:
|
||||
# --panel-env-file <ruta> # archivo KEY=valor con CLOUDRESTORE_PANEL_* que se
|
||||
# # fusiona en config/.env y se borra al terminar.
|
||||
# # Lo usa el instalador remoto del PANEL para dejar
|
||||
# # el servidor configurado sin intervención.
|
||||
#
|
||||
# Variables:
|
||||
# PREFIX=/opt/cloudrestoreas # carpeta destino (default)
|
||||
# SERVICE_USER=<usuario> # usuario del servicio systemd (default: quien invoca)
|
||||
set -euo pipefail
|
||||
|
||||
MODE="none"
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--service) MODE="service" ;;
|
||||
--desktop) MODE="desktop" ;;
|
||||
PANEL_ENV_FILE=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--service) MODE="service"; shift ;;
|
||||
--desktop) MODE="desktop"; shift ;;
|
||||
--panel-env-file)
|
||||
[[ $# -ge 2 ]] || { echo "ERROR: --panel-env-file requiere una ruta" >&2; exit 2; }
|
||||
PANEL_ENV_FILE="$2"; shift 2 ;;
|
||||
--panel-env-file=*) PANEL_ENV_FILE="${1#*=}"; shift ;;
|
||||
-h|--help)
|
||||
grep '^#' "$0" | grep -v '^#!' | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||
*) echo "Opción desconocida: $arg" >&2; exit 2 ;;
|
||||
*) echo "Opción desconocida: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PREFIX="${PREFIX:-/opt/cloudrestoreas}"
|
||||
BIN_NAME="CloudRestoreAS"
|
||||
UNIT_NAME="cloudrestoreas.service"
|
||||
|
||||
# Localizar el binario: dist/CloudRestoreAS, dist/CloudRestoreAS-linux, o junto al script.
|
||||
SRC=""
|
||||
@@ -52,8 +66,27 @@ echo " Destino : $PREFIX"
|
||||
echo " Modo : $MODE"
|
||||
echo "==============================================="
|
||||
|
||||
# --- Detener el servicio si está corriendo ------------------------------------
|
||||
# Un ELF en ejecución no se puede sobrescribir (ETXTBSY), así que una actualización
|
||||
# tiene que detenerlo antes de reemplazar el binario. Se recuerda si estaba activo
|
||||
# para volver a levantarlo al final incluso en los modos que no tocan systemd.
|
||||
WAS_ACTIVE=0
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
if systemctl is-active --quiet "$UNIT_NAME" 2>/dev/null; then
|
||||
WAS_ACTIVE=1
|
||||
echo "Deteniendo $UNIT_NAME para reemplazar el binario..."
|
||||
systemctl stop "$UNIT_NAME" >/dev/null 2>&1 || \
|
||||
echo "AVISO: no se pudo detener $UNIT_NAME (¿falta sudo?); la copia puede fallar." >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$PREFIX"
|
||||
install -m 0755 "$SRC" "$PREFIX/$BIN_NAME"
|
||||
if ! install -m 0755 "$SRC" "$PREFIX/$BIN_NAME"; then
|
||||
echo "ERROR: no se pudo instalar el binario en $PREFIX/$BIN_NAME" >&2
|
||||
echo " Si el archivo está en uso, detén el proceso y reintenta:" >&2
|
||||
echo " sudo systemctl stop $UNIT_NAME # o mata el proceso de escritorio" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Binario instalado en $PREFIX/$BIN_NAME"
|
||||
|
||||
# Bootstrap de config/: el propio binario crea config/, .env y carpetas de trabajo
|
||||
@@ -68,11 +101,94 @@ else
|
||||
echo "NOTA: config/.env se creará en la primera ejecución."
|
||||
fi
|
||||
|
||||
# --- Siembra de credenciales del PANEL ----------------------------------------
|
||||
# Fusión replace-or-append: respeta el resto de config/.env y es idempotente, así que
|
||||
# reinstalar no duplica claves ni pierde ajustes locales. Se escribe vía archivo y no
|
||||
# por argumentos para que el token no quede visible en `ps` ni en el historial.
|
||||
merge_env_keys() {
|
||||
local target="$1"; shift
|
||||
local -a pairs=("$@")
|
||||
local tmp line key pair matched
|
||||
|
||||
tmp="$(mktemp)"
|
||||
if [[ -f "$target" ]]; then
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
matched=""
|
||||
for pair in "${pairs[@]}"; do
|
||||
key="${pair%%=*}"
|
||||
if [[ "$line" =~ ^[[:space:]]*"$key"[[:space:]]*= ]]; then
|
||||
matched="$pair"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ -n "$matched" ]]; then
|
||||
printf '%s\n' "$matched" >> "$tmp"
|
||||
else
|
||||
printf '%s\n' "$line" >> "$tmp"
|
||||
fi
|
||||
done < "$target"
|
||||
fi
|
||||
|
||||
for pair in "${pairs[@]}"; do
|
||||
key="${pair%%=*}"
|
||||
if ! grep -qE "^[[:space:]]*${key}[[:space:]]*=" "$tmp" 2>/dev/null; then
|
||||
printf '%s\n' "$pair" >> "$tmp"
|
||||
fi
|
||||
done
|
||||
|
||||
# cat > preserva el inodo y los permisos 0600 del .env; mv los reemplazaría.
|
||||
cat "$tmp" > "$target"
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
if [[ -n "$PANEL_ENV_FILE" ]]; then
|
||||
if [[ ! -f "$PANEL_ENV_FILE" ]]; then
|
||||
echo "ERROR: no existe el archivo indicado en --panel-env-file: $PANEL_ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ENV_PATH="$PREFIX/config/.env"
|
||||
touch "$ENV_PATH"
|
||||
chmod 0600 "$ENV_PATH" 2>/dev/null || true
|
||||
|
||||
# Lista blanca: el archivo llega por la red y no debe poder inyectar otras claves.
|
||||
ALLOWED_KEYS="CLOUDRESTORE_PANEL_API_URL CLOUDRESTORE_PANEL_API_TOKEN"
|
||||
ALLOWED_KEYS="$ALLOWED_KEYS CLOUDRESTORE_PANEL_INSTANCE_KEY CLOUDRESTORE_PANEL_VERIFY_SSL"
|
||||
|
||||
PAIRS=()
|
||||
while IFS= read -r raw || [[ -n "$raw" ]]; do
|
||||
raw="${raw%$'\r'}" # tolera CRLF si vino de Windows
|
||||
raw="${raw#"${raw%%[![:space:]]*}"}" # recorta espacios a la izquierda
|
||||
if [[ -z "$raw" || "${raw:0:1}" == "#" || "$raw" != *=* ]]; then
|
||||
continue
|
||||
fi
|
||||
key="${raw%%=*}"
|
||||
key="${key//[[:space:]]/}"
|
||||
value="${raw#*=}"
|
||||
for allowed in $ALLOWED_KEYS; do
|
||||
if [[ "$key" == "$allowed" ]]; then
|
||||
PAIRS+=("${key}=${value}")
|
||||
break
|
||||
fi
|
||||
done
|
||||
done < "$PANEL_ENV_FILE"
|
||||
|
||||
if [[ "${#PAIRS[@]}" -gt 0 ]]; then
|
||||
merge_env_keys "$ENV_PATH" "${PAIRS[@]}"
|
||||
echo "${#PAIRS[@]} clave(s) del PANEL escritas en config/.env"
|
||||
else
|
||||
echo "AVISO: --panel-env-file no traía claves CLOUDRESTORE_PANEL_* válidas." >&2
|
||||
fi
|
||||
|
||||
# El archivo trae el token en claro: se borra en cuanto se consumió.
|
||||
rm -f "$PANEL_ENV_FILE"
|
||||
fi
|
||||
|
||||
case "$MODE" in
|
||||
service)
|
||||
SERVICE_USER="${SERVICE_USER:-${SUDO_USER:-$(id -un)}}"
|
||||
UNIT_SRC="$SCRIPT_DIR/packaging/linux/cloudrestoreas.service"
|
||||
UNIT_DST="/etc/systemd/system/cloudrestoreas.service"
|
||||
UNIT_SRC="$SCRIPT_DIR/packaging/linux/$UNIT_NAME"
|
||||
UNIT_DST="/etc/systemd/system/$UNIT_NAME"
|
||||
if [[ ! -w "$(dirname "$UNIT_DST")" ]]; then
|
||||
echo "ERROR: se requiere sudo para instalar el servicio systemd" >&2
|
||||
exit 1
|
||||
@@ -82,7 +198,7 @@ case "$MODE" in
|
||||
-e "s|__EXEC__|$PREFIX/$BIN_NAME|g" \
|
||||
"$UNIT_SRC" > "$UNIT_DST"
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now cloudrestoreas.service
|
||||
systemctl enable --now "$UNIT_NAME"
|
||||
echo "Servicio systemd instalado y arrancado (usuario: $SERVICE_USER)."
|
||||
echo " Estado : systemctl status cloudrestoreas"
|
||||
echo " Logs : journalctl -u cloudrestoreas -f"
|
||||
@@ -97,6 +213,14 @@ case "$MODE" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Si se detuvo un servicio que estaba activo y el modo elegido no lo relevanta, se
|
||||
# restaura: una actualización no debe dejar el restaurador apagado en silencio.
|
||||
if [[ "$WAS_ACTIVE" -eq 1 && "$MODE" != "service" ]]; then
|
||||
echo "Reiniciando $UNIT_NAME (estaba activo antes de la actualización)..."
|
||||
systemctl start "$UNIT_NAME" >/dev/null 2>&1 || \
|
||||
echo "AVISO: no se pudo reiniciar $UNIT_NAME; hazlo a mano." >&2
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Siguiente paso: edita $PREFIX/config/.env (CLOUDRESTORE_PANEL_*) y reinicia."
|
||||
[[ "$MODE" == "service" ]] && echo " Tras editar: sudo systemctl restart cloudrestoreas"
|
||||
|
||||
Reference in New Issue
Block a user