From 22157fe723fb52dbbb12587bf6b5e1917ed4c177 Mon Sep 17 00:00:00 2001 From: Hannes Ahlin Date: Sat, 22 Aug 2026 15:23:33 +0200 Subject: [PATCH] Fix: integrera i befintlig nextcloud-node-red :1880, ingen ny container --- README.md | 62 +++++----- bootstrap-install.sh | 193 ++++++++---------------------- docker-compose.yml | 12 +- docs/AGENT-MANUAL.md | 4 +- docs/INFRASTRUCTURE.md | 7 +- install.sh | 123 +++++-------------- scripts/integrate-into-nodered.sh | 184 ++++++++++++++++++++++++++++ 7 files changed, 302 insertions(+), 283 deletions(-) create mode 100644 scripts/integrate-into-nodered.sh diff --git a/README.md b/README.md index a0a6057..c7c2f03 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,54 @@ # nextcloud-collabora-nodered -Node-RED sidecar (port **1881**) med Collabora/Nextcloud Office-noder. +Collabora/Nextcloud Office-noder för **befintlig** `nextcloud-node-red` på port **1880**. -**Version 1.0 — 22 augusti 2026** +Skapar **ingen** ny Node-RED-container. -## Snabbaste installation (valfri VM) +## Installation (cloud / valfri VM) ```bash -curl -fsSL https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered/raw/branch/main/bootstrap-install.sh | bash +curl -fsSL https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered/raw/branch/main/bootstrap-install.sh | sudo -u ncadmin bash ``` -Skriptet: -- installerar git/curl/Docker om de saknas -- klonar från **Gitea** (`n3wk/nextcloud-collabora-nodered`) -- detekterar CODE-IP på Docker `bridge` -- bygger och startar Node-RED sidecar med alla noder -- lämnar `:1880`, odds-scraper och CODE orörda +Det skriptet: +1. Klonar detta repo till `/home/ncadmin/nextcloud-collabora-nodered` +2. Kopierar noder till `/home/ncadmin/nextcloud-node-red/nodes/nextcloud-collabora/` +3. Patchar `Dockerfile` + `entrypoint.sh` i nextcloud-node-red +4. Bygger om **samma** `nextcloud-node-red`-image och startar om containern +5. Ansluter `nextcloud-node-red` till Docker `bridge` så CODE (`172.17.0.2:9980`) nås -### Miljövariabler (valfritt) - -```bash -GIT_REPO_URL=https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered.git \ -INSTALL_DIR=/home/ncadmin/nextcloud-collabora-nodered \ -NC_HOST=cloud.hannesahlin.se \ -NC_HOST_IP=192.168.1.26 \ -bash bootstrap-install.sh -``` - -## Manuell installation (repo redan klonat) +## Uppdatera noder ```bash cd /home/ncadmin/nextcloud-collabora-nodered +git pull ./install.sh ``` -## Repo +## Manuell integration -- **Gitea:** https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered -- **SSH clone:** `ssh -p 2222 git@kode.hannesahlin.se:n3wk/nextcloud-collabora-nodered.git` +```bash +cd /home/ncadmin/nextcloud-collabora-nodered +NODERED_DIR=/home/ncadmin/nextcloud-node-red ./scripts/integrate-into-nodered.sh +``` -## Dokumentation +## Sidecar :1881 (ej rekommenderat) -- [docs/AGENT-MANUAL.md](docs/AGENT-MANUAL.md) -- [docs/INFRASTRUCTURE.md](docs/INFRASTRUCTURE.md) +Endast om du uttryckligen vill separat instans: + +```bash +INSTALL_MODE=sidecar docker compose --profile sidecar up -d --build +``` ## Noder `nc-collab-config` · `collabora-bridge` · `nc-office` · `collabora-convert` · `collabora-extract` · `collabora-transform` · `collabora-wopi` -## Utveckling / push +## Repo -```bash -git remote add origin https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered.git -git push -u origin main -``` +https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered -## Licens +## Dokumentation -MIT +- [docs/AGENT-MANUAL.md](docs/AGENT-MANUAL.md) +- [docs/INFRASTRUCTURE.md](docs/INFRASTRUCTURE.md) diff --git a/bootstrap-install.sh b/bootstrap-install.sh index abc863a..9a8bc24 100644 --- a/bootstrap-install.sh +++ b/bootstrap-install.sh @@ -1,207 +1,118 @@ #!/usr/bin/env bash -# bootstrap-install.sh — full installation på valfri VM-variant +# bootstrap-install.sh — klona från Gitea och integrera i befintlig nextcloud-node-red # -# Laddar ned från Gitea, installerar Docker vid behov, bygger Node-RED sidecar -# med alla Collabora-noder och startar på port 1881. +# Skapar INTE ny Node-RED-container. Patchar /home/ncadmin/nextcloud-node-red och bygger om. # -# One-liner (efter repo finns på Gitea): +# One-liner: # curl -fsSL https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered/raw/branch/main/bootstrap-install.sh | bash # -# Med miljövariabler: -# GIT_REPO_URL=https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered.git \ -# INSTALL_DIR=/home/ncadmin/nextcloud-collabora-nodered \ -# bash bootstrap-install.sh +# Som ncadmin (rekommenderat): +# curl -fsSL ... | sudo -u ncadmin bash # set -euo pipefail VERSION="1.0.0" GIT_REPO_URL="${GIT_REPO_URL:-https://kode.hannesahlin.se/n3wk/nextcloud-collabora-nodered.git}" GIT_BRANCH="${GIT_BRANCH:-main}" -INSTALL_DIR="${INSTALL_DIR:-${HOME}/nextcloud-collabora-nodered}" +INSTALL_MODE="${INSTALL_MODE:-integrate}" + +# Som root: använd ncadmin-sökvägar (inte /root) +if [ "$(id -u)" -eq 0 ] && [ -d "/home/ncadmin" ]; then + INSTALL_DIR="${INSTALL_DIR:-/home/ncadmin/nextcloud-collabora-nodered}" + NODERED_DIR="${NODERED_DIR:-/home/ncadmin/nextcloud-node-red}" +else + INSTALL_DIR="${INSTALL_DIR:-${HOME}/nextcloud-collabora-nodered}" + NODERED_DIR="${NODERED_DIR:-${HOME}/nextcloud-node-red}" +fi + NC_HOST="${NC_HOST:-cloud.hannesahlin.se}" -NC_URL="${NC_URL:-https://${NC_HOST}}" CODE_CONTAINER="${CODE_CONTAINER:-code}" -CODE_PORT="${CODE_PORT:-9980}" -NODERED_PORT="${NODERED_PORT:-1881}" +NODERED_CONTAINER="${NODERED_CONTAINER:-nextcloud-node-red}" +NODERED_PORT="${NODERED_PORT:-1880}" SKIP_APT="${SKIP_APT:-0}" -SKIP_DOCKER_INSTALL="${SKIP_DOCKER_INSTALL:-0}" +SKIP_DOCKER_INSTALL="${SKIP_DOCKER_INSTALL:-1}" 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.26" -} - -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" + if [ "$(id -u)" -eq 0 ]; then "$@"; elif command -v sudo >/dev/null 2>&1; then sudo "$@"; else die "sudo krävs"; fi } 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)..." + command -v apt-get >/dev/null 2>&1 || return 0 + log "Installerar git, curl, rsync..." 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 + [ "${SKIP_DOCKER_INSTALL}" = "1" ] && return 0 + command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1 && return 0 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 + curl -fsSL https://get.docker.com | run_as_root sh } clone_or_update_repo() { if [ -d "${INSTALL_DIR}/.git" ]; then - log "Uppdaterar befintlig klon i ${INSTALL_DIR}..." + log "Uppdaterar ${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" + git -C "${INSTALL_DIR}" pull --ff-only origin "${GIT_BRANCH}" || warn "git pull misslyckades" 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}" + if [ "$(id -u)" -eq 0 ] && [ -d "/home/ncadmin" ]; then + chown -R ncadmin:ncadmin "${INSTALL_DIR}" 2>/dev/null || true + fi } -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 +preflight() { + command -v docker >/dev/null 2>&1 || die "Docker saknas" + docker ps --format '{{.Names}}' | grep -qx "${NODERED_CONTAINER}" \ + || die "'${NODERED_CONTAINER}' körs inte — detta skript integrerar i befintlig Node-RED, skapar ingen ny" + docker ps --format '{{.Names}}' | grep -qx "${CODE_CONTAINER}" \ + || die "'${CODE_CONTAINER}' (Collabora) körs inte" + [ -d "${NODERED_DIR}" ] || die "nextcloud-node-red-katalog saknas: ${NODERED_DIR}" + log "OK: ${NODERED_CONTAINER} + ${CODE_CONTAINER} körs" } main() { - log "nextcloud-collabora-nodered bootstrap v${VERSION}" - log "Repo: ${GIT_REPO_URL} (${GIT_BRANCH})" - log "Installationskatalog: ${INSTALL_DIR}" + log "bootstrap v${VERSION} — läge: ${INSTALL_MODE} (befintlig Node-RED :${NODERED_PORT})" + log "Repo → ${INSTALL_DIR}" + log "Integrera → ${NODERED_DIR}" if [ "$(id -u)" -eq 0 ] && [ -z "${SUDO_USER:-}" ]; then - warn "Körs som root — rekommenderat: ncadmin eller annan docker-användare" + warn "Körs som root — rekommenderat: curl ... | sudo -u ncadmin bash" fi install_apt_packages install_docker clone_or_update_repo - write_env_file - preflight_code + preflight - log "Kör lokal install.sh..." - chmod +x "${INSTALL_DIR}/install.sh" + chmod +x "${INSTALL_DIR}/install.sh" "${INSTALL_DIR}/scripts/integrate-into-nodered.sh" INSTALL_DIR="${INSTALL_DIR}" \ + INSTALL_MODE="${INSTALL_MODE}" \ + NODERED_DIR="${NODERED_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}" + local host_ip + host_ip="$(hostname -I 2>/dev/null | awk '{print $1}' || echo "127.0.0.1")" cat <&2; exit 1; } -require_cmd() { - command -v "$1" >/dev/null 2>&1 || die "Saknar kommando: $1" -} +log "nextcloud-collabora-nodered v${VERSION} (läge: ${INSTALL_MODE})" -log "nextcloud-collabora-nodered v${VERSION}" -log "Installationskatalog: ${INSTALL_DIR}" - -require_cmd docker -if docker compose version >/dev/null 2>&1; then +if [ "${INSTALL_MODE}" = "sidecar" ]; then + log "Sidecar-läge — varning: standard är integrate (befintlig :1880)" + require_cmd() { command -v "$1" >/dev/null 2>&1 || die "Saknar: $1"; } + require_cmd docker COMPOSE="docker compose" -elif command -v docker-compose >/dev/null 2>&1; then - COMPOSE="docker-compose" -else - die "Docker Compose saknas" -fi - -cd "${INSTALL_DIR}" - -if [ ! -f docker-compose.yml ]; then - die "docker-compose.yml saknas i ${INSTALL_DIR}" -fi - -if [ ! -f .env ]; then - log "Skapar .env från .env.example" - cp .env.example .env -fi - -# Valfri tarball från Windows -if [ -n "${IMPORT_TARBALL:-}" ] && [ -f "${IMPORT_TARBALL}" ]; then - log "Extraherar ${IMPORT_TARBALL}" - tmpdir="$(mktemp -d)" - tar -xzf "${IMPORT_TARBALL}" -C "${tmpdir}" - src="$(find "${tmpdir}" -maxdepth 2 -name docker-compose.yml -printf '%h\n' | head -1)" - [ -n "${src}" ] || die "Ogiltig tarball" - rsync -a "${src}/" "${INSTALL_DIR}/" - rm -rf "${tmpdir}" -fi - -# Verifiera att CODE redan kör (starta INTE ny) -if ! docker ps --format '{{.Names}}' | grep -qx "${CODE_CONTAINER}"; then - die "CODE-container '${CODE_CONTAINER}' körs inte. Starta inte ny CODE — fixa befintlig instans först." -fi - -code_ip="$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${CODE_CONTAINER}" 2>/dev/null | head -1)" -if [ -n "${code_ip}" ] && [ "${code_ip}" != "${COLLABORA_IP}" ]; then - log "OBS: CODE IP är ${code_ip} (inte ${COLLABORA_IP}). Uppdaterar COLLABORA_URL i .env." - if grep -q '^COLLABORA_URL=' .env; then - sed -i "s|^COLLABORA_URL=.*|COLLABORA_URL=http://${code_ip}:9980|" .env + docker compose version >/dev/null 2>&1 || COMPOSE="docker-compose" + cd "${INSTALL_DIR}" + [ -f docker-compose.yml ] || die "docker-compose.yml saknas" + [ -f .env ] || cp .env.example .env + if ! docker ps --format '{{.Names}}' | grep -qx "${CODE_CONTAINER}"; then + die "CODE-container '${CODE_CONTAINER}' körs inte" fi -fi - -# extra_hosts: uppdatera NC_HOST_IP om vi kan detektera -if [ -f .env ] && grep -q '^NC_HOST_IP=' .env; then - host_ip="$(hostname -I 2>/dev/null | awk '{print $1}' || true)" - if [ -n "${host_ip}" ]; then - sed -i "s|^NC_HOST_IP=.*|NC_HOST_IP=${host_ip}|" .env - fi -fi - -log "Bygger och startar sidecar (port 1881, nätverk bridge + collab_default)..." -if [ "${FORCE_REBUILD:-0}" = "1" ]; then - ${COMPOSE} build --no-cache -else ${COMPOSE} build -fi -${COMPOSE} up -d - -log "Väntar på Node-RED..." -for i in $(seq 1 30); do - if curl -sf "http://127.0.0.1:1881" >/dev/null 2>&1; then - log "Node-RED svarar på http://127.0.0.1:1881" - break - fi - sleep 2 - [ "$i" -eq 30 ] && log "Varning: Node-RED svarade inte inom 60 s" -done - -log "Testar CODE capabilities från sidecar..." -collab_url="$(grep '^COLLABORA_URL=' .env | cut -d= -f2- || echo "http://${COLLABORA_IP}:9980")" -host_ip="$(grep '^NC_HOST_IP=' .env 2>/dev/null | cut -d= -f2- || hostname -I | awk '{print $1}')" -if docker exec nextcloud-collabora-nodered curl -sf "${collab_url}/hosting/capabilities" >/dev/null 2>&1; then - log "OK: CODE nås på ${collab_url}" -else - log "VARNING: Kunde inte nå ${collab_url}/hosting/capabilities från sidecar." - log " Kontrollera: docker network inspect bridge | grep -A2 ${CODE_CONTAINER}" - log " Alternativ: docker network connect bridge nextcloud-collabora-nodered" + ${COMPOSE} up -d + log "Sidecar startad på :1881 (ej rekommenderat om :1880 redan kör)" + exit 0 fi -cat <&2; } +die() { printf '[integrate] FEL: %s\n' "$*" >&2; exit 1; } + +resolve_paths() { + if [ "$(id -u)" -eq 0 ] && [ -d "/home/ncadmin/nextcloud-node-red" ]; then + NODERED_DIR="${NODERED_DIR:-/home/ncadmin/nextcloud-node-red}" + PKG_SRC="${PKG_SRC:-/home/ncadmin/nextcloud-collabora-nodered}" + fi +} + +stop_sidecar_if_any() { + if docker ps -a --format '{{.Names}}' | grep -qx "nextcloud-collabora-nodered"; then + warn "Stoppar felaktig sidecar-container nextcloud-collabora-nodered (skulle inte skapas)" + docker stop nextcloud-collabora-nodered 2>/dev/null || true + docker rm nextcloud-collabora-nodered 2>/dev/null || true + fi +} + +preflight() { + [ -d "${PKG_SRC}" ] || die "Paketkälla saknas: ${PKG_SRC}" + [ -f "${PKG_SRC}/package.json" ] || die "package.json saknas i ${PKG_SRC}" + [ -d "${NODERED_DIR}" ] || die "nextcloud-node-red saknas: ${NODERED_DIR}" + [ -f "${NODERED_DIR}/Dockerfile" ] || die "Dockerfile saknas i ${NODERED_DIR}" + [ -f "${NODERED_DIR}/entrypoint.sh" ] || die "entrypoint.sh saknas i ${NODERED_DIR}" + + if ! docker ps --format '{{.Names}}' | grep -qx "${NODERED_CONTAINER}"; then + die "Container '${NODERED_CONTAINER}' körs inte — starta befintlig nextcloud-node-red först" + fi + if ! docker ps --format '{{.Names}}' | grep -qx "${CODE_CONTAINER}"; then + die "CODE-container '${CODE_CONTAINER}' körs inte" + fi +} + +copy_node_package() { + local dest="${NODERED_DIR}/nodes/nextcloud-collabora" + log "Kopierar noder → ${dest}" + mkdir -p "${dest}" + rsync -a --delete \ + "${PKG_SRC}/package.json" \ + "${PKG_SRC}/lib/" \ + "${PKG_SRC}/nodes/" \ + "${dest}/" +} + +patch_dockerfile() { + local df="${NODERED_DIR}/Dockerfile" + if grep -q "${MARKER}" "${df}"; then + log "Dockerfile redan patchad" + return 0 + fi + log "Patchar Dockerfile" + cat >> "${df}" <<'EOF' + +# nextcloud-collabora-nodered — Collabora/Office-noder (WebDAV + CODE REST) +RUN mkdir -p /opt/nextcloud-nodes/node-red-contrib-nextcloud-collabora +COPY nodes/nextcloud-collabora/package.json /opt/nextcloud-nodes/node-red-contrib-nextcloud-collabora/ +COPY nodes/nextcloud-collabora/lib /opt/nextcloud-nodes/node-red-contrib-nextcloud-collabora/lib +COPY nodes/nextcloud-collabora/nodes /opt/nextcloud-nodes/node-red-contrib-nextcloud-collabora/nodes +RUN cd /opt/nextcloud-nodes/node-red-contrib-nextcloud-collabora && npm install --omit=dev +EOF +} + +patch_entrypoint() { + local ep="${NODERED_DIR}/entrypoint.sh" + if grep -q "node-red-contrib-nextcloud-collabora" "${ep}"; then + log "entrypoint.sh redan patchad" + return 0 + fi + log "Patchar entrypoint.sh" + # Infoga före sista exec/npm start om möjligt, annars append + if grep -q "node-red-contrib-nextcloud-ocs" "${ep}"; then + sed -i '/node-red-contrib-nextcloud-ocs/a\ +cp -a /opt/nextcloud-nodes/node-red-contrib-nextcloud-collabora /data/node_modules/' "${ep}" + else + cat >> "${ep}" <<'EOF' + +# nextcloud-collabora-nodered +mkdir -p /data/node_modules +cp -a /opt/nextcloud-nodes/node-red-contrib-nextcloud-collabora /data/node_modules/ +EOF + fi +} + +connect_code_network() { + log "Ansluter ${NODERED_CONTAINER} till Docker bridge (CODE)" + if docker network inspect bridge --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null | grep -q "${NODERED_CONTAINER}"; then + log "Redan ansluten till bridge" + else + docker network connect bridge "${NODERED_CONTAINER}" 2>/dev/null || warn "Kunde inte ansluta bridge — kontrollera manuellt" + fi +} + +rebuild_nodered() { + local compose="docker compose" + if ! docker compose version >/dev/null 2>&1; then + compose="docker-compose" + fi + log "Bygger om ${NODERED_CONTAINER} (samma instans, port ${NODERED_PORT})..." + cd "${NODERED_DIR}" + if [ "${FORCE_REBUILD:-0}" = "1" ]; then + ${compose} build --no-cache + else + ${compose} build + fi + ${compose} up -d +} + +wait_nodered() { + log "Väntar på Node-RED :${NODERED_PORT}..." + for i in $(seq 1 30); do + if curl -sf "http://127.0.0.1:${NODERED_PORT}" >/dev/null 2>&1; then + log "Node-RED svarar på http://127.0.0.1:${NODERED_PORT}" + return 0 + fi + sleep 2 + done + warn "Node-RED svarade inte inom 60 s" +} + +verify_code_from_nodered() { + local code_ip + code_ip="$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${CODE_CONTAINER}" 2>/dev/null | head -1)" + [ -n "${code_ip}" ] || code_ip="${COLLABORA_IP}" + local url="http://${code_ip}:9980/hosting/capabilities" + log "Testar CODE från ${NODERED_CONTAINER}: ${url}" + if docker exec "${NODERED_CONTAINER}" curl -sf "${url}" >/dev/null 2>&1; then + log "OK: CODE nås från befintlig Node-RED-container" + else + warn "CODE nås inte — kör: docker network connect bridge ${NODERED_CONTAINER}" + warn "nc-collab-config collaboraUrl=http://${code_ip}:9980" + fi +} + +main() { + resolve_paths + log "Integrerar Collabora-noder i befintlig nextcloud-node-red" + log "Paket: ${PKG_SRC}" + log "Node-RED: ${NODERED_DIR} (container ${NODERED_CONTAINER})" + + stop_sidecar_if_any + preflight + copy_node_package + patch_dockerfile + patch_entrypoint + connect_code_network + rebuild_nodered + wait_nodered + verify_code_from_nodered + + local host_ip + host_ip="$(hostname -I 2>/dev/null | awk '{print $1}' || echo "127.0.0.1")" + + cat <