#!/usr/bin/env bash # bootstrap-install.sh — full installation på valfri VM-variant # # Laddar ned från Gitea, installerar Docker vid behov, bygger Node-RED sidecar # med alla Collabora-noder och startar på port 1881. # # One-liner (efter repo finns på Gitea): # curl -fsSL https://git.domain.name/your-user/nextcloud-collabora-nodered/raw/branch/main/bootstrap-install.sh | bash # # Med miljövariabler: # GIT_REPO_URL=https://git.domain.name/your-user/nextcloud-collabora-nodered.git \ # INSTALL_DIR=/home/ncdeploy/nextcloud-collabora-nodered \ # bash bootstrap-install.sh # set -euo pipefail VERSION="1.0.0" GIT_REPO_URL="${GIT_REPO_URL:-https://git.domain.name/your-user/nextcloud-collabora-nodered.git}" GIT_BRANCH="${GIT_BRANCH:-main}" INSTALL_DIR="${INSTALL_DIR:-${HOME}/nextcloud-collabora-nodered}" NC_HOST="${NC_HOST:-cloud.domain.name}" NC_URL="${NC_URL:-https://${NC_HOST}}" CODE_CONTAINER="${CODE_CONTAINER:-code}" CODE_PORT="${CODE_PORT:-9980}" NODERED_PORT="${NODERED_PORT:-1881}" SKIP_APT="${SKIP_APT:-0}" SKIP_DOCKER_INSTALL="${SKIP_DOCKER_INSTALL:-0}" log() { printf '[bootstrap] %s\n' "$*"; } warn() { printf '[bootstrap] VARNING: %s\n' "$*" >&2; } die() { printf '[bootstrap] FEL: %s\n' "$*" >&2; exit 1; } run_as_root() { if [ "$(id -u)" -eq 0 ]; then "$@" elif command -v sudo >/dev/null 2>&1; then sudo "$@" else die "Root/sudo krävs för: $*" fi } detect_host_ip() { if [ -n "${NC_HOST_IP:-}" ]; then echo "${NC_HOST_IP}" return fi local ip ip="$(hostname -I 2>/dev/null | awk '{print $1}' || true)" if [ -n "${ip}" ]; then echo "${ip}" return fi ip="$(ip -4 route get "${NC_HOST}" 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="src") print $(i+1)}' || true)" if [ -n "${ip}" ]; then echo "${ip}" return fi echo "192.168.1.10" } detect_code_ip() { if [ -n "${COLLABORA_IP:-}" ]; then echo "${COLLABORA_IP}" return fi if command -v docker >/dev/null 2>&1 && docker ps --format '{{.Names}}' | grep -qx "${CODE_CONTAINER}"; then docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${CODE_CONTAINER}" 2>/dev/null | head -1 return fi echo "172.17.0.2" } install_apt_packages() { [ "${SKIP_APT}" = "1" ] && return 0 if ! command -v apt-get >/dev/null 2>&1; then warn "apt-get saknas — installera git, curl och docker manuellt" return 0 fi log "Installerar grundpaket (git, curl, ca-certificates)..." run_as_root apt-get update -qq run_as_root apt-get install -y -qq git curl ca-certificates rsync } install_docker() { if [ "${SKIP_DOCKER_INSTALL}" = "1" ]; then return 0 fi if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then log "Docker finns redan" return 0 fi log "Installerar Docker..." if command -v apt-get >/dev/null 2>&1; then run_as_root apt-get install -y -qq docker.io docker-compose-plugin 2>/dev/null || true fi if ! command -v docker >/dev/null 2>&1 || ! docker info >/dev/null 2>&1; then log "Kör get.docker.com..." curl -fsSL https://get.docker.com | run_as_root sh fi local target_user="${SUDO_USER:-${USER}}" if [ -n "${target_user}" ] && [ "${target_user}" != "root" ]; then run_as_root usermod -aG docker "${target_user}" 2>/dev/null || true warn "Användaren ${target_user} lades till i docker-gruppen — logga ut/in om 'permission denied'" fi } clone_or_update_repo() { if [ -d "${INSTALL_DIR}/.git" ]; then log "Uppdaterar befintlig klon i ${INSTALL_DIR}..." git -C "${INSTALL_DIR}" fetch origin git -C "${INSTALL_DIR}" checkout "${GIT_BRANCH}" git -C "${INSTALL_DIR}" pull --ff-only origin "${GIT_BRANCH}" || warn "git pull misslyckades — fortsätter med lokalt innehåll" return 0 fi if [ -d "${INSTALL_DIR}" ] && [ "$(ls -A "${INSTALL_DIR}" 2>/dev/null | wc -l)" -gt 0 ]; then die "${INSTALL_DIR} finns men är inte en git-klon — flytta bort eller sätt INSTALL_DIR" fi log "Klonar ${GIT_REPO_URL} → ${INSTALL_DIR}" mkdir -p "$(dirname "${INSTALL_DIR}")" git clone --branch "${GIT_BRANCH}" --depth 1 "${GIT_REPO_URL}" "${INSTALL_DIR}" } write_env_file() { local host_ip code_ip collab_url host_ip="$(detect_host_ip)" code_ip="$(detect_code_ip)" collab_url="http://${code_ip}:${CODE_PORT}" log "VM host-IP för ${NC_HOST}: ${host_ip}" log "CODE URL: ${collab_url} (container ${CODE_CONTAINER})" cat > "${INSTALL_DIR}/.env" </dev/null || echo "byt-den-här-hemligheten-vid-produktion")} EOF } preflight_code() { if ! command -v docker >/dev/null 2>&1; then die "Docker saknas efter installation" fi if ! docker ps --format '{{.Names}}' | grep -qx "${CODE_CONTAINER}"; then die "CODE-container '${CODE_CONTAINER}' körs inte på denna VM. Starta befintlig CODE — skapa inte ny via detta skript." fi local cap cap="$(docker exec "${CODE_CONTAINER}" curl -sf "http://127.0.0.1:${CODE_PORT}/hosting/capabilities" 2>/dev/null | head -c 80 || true)" if [ -z "${cap}" ]; then warn "CODE svarar inte på capabilities inuti containern — kontrollera aliasgroup och post_allow" else log "CODE capabilities OK inuti container ${CODE_CONTAINER}" fi } main() { log "nextcloud-collabora-nodered bootstrap v${VERSION}" log "Repo: ${GIT_REPO_URL} (${GIT_BRANCH})" log "Installationskatalog: ${INSTALL_DIR}" if [ "$(id -u)" -eq 0 ] && [ -z "${SUDO_USER:-}" ]; then warn "Körs som root — rekommenderat: ncdeploy eller annan docker-användare" fi install_apt_packages install_docker clone_or_update_repo write_env_file preflight_code log "Kör lokal install.sh..." chmod +x "${INSTALL_DIR}/install.sh" INSTALL_DIR="${INSTALL_DIR}" \ CODE_CONTAINER="${CODE_CONTAINER}" \ COLLABORA_IP="$(detect_code_ip)" \ bash "${INSTALL_DIR}/install.sh" local host_ip nodered_url host_ip="$(detect_host_ip)" nodered_url="http://${host_ip}:${NODERED_PORT}" cat <