Fix Node-RED container net: extra_hosts, CODE HTTPS, force-recreate
Detect host LAN IP and CODE URL so OCS/Collabora work unattended on each VM. Avoid 127.0.1.1 Nextcloud DNS and HTTP-to-TLS CODE.
This commit is contained in:
+10
-2
@@ -5,10 +5,16 @@
|
||||
NEXTCLOUD_URL=https://cloud.domain.name
|
||||
NEXTCLOUD_PUBLIC_URL=https://cloud.domain.name
|
||||
|
||||
# Collabora CODE — bridge IP auto-detected if COLLABORA_IP is empty
|
||||
# Collabora CODE
|
||||
# COLLABORA_URL: https://code:9980 när CODE delar Docker-nätverk med Node-RED
|
||||
# (integrate-into-nodered.sh connectar CODE till nodernätet automatiskt).
|
||||
# Fallback om 'code' inte kan resolvas: https://<CODE-IP>:9980.
|
||||
# ALDRIG http://127.0.0.1:9980 eller http://host.docker.internal:9980 —
|
||||
# CODE lyssnar bara på HTTPS internt och kör inte på Node-RED-värden.
|
||||
# verifyTls=false sätts i nc-collab-config-noden (self-signed cert internt).
|
||||
CODE_CONTAINER=code
|
||||
COLLABORA_IP=
|
||||
COLLABORA_URL=
|
||||
COLLABORA_URL=https://code:9980
|
||||
|
||||
# Existing Node-RED install (integrate mode)
|
||||
NODERED_DIR=
|
||||
@@ -18,6 +24,8 @@ INSTALL_USER=
|
||||
|
||||
# Sidecar mode (not default)
|
||||
NC_HOST=cloud.domain.name
|
||||
# Host-LAN-IP för extra_hosts. Tomt = auto-detekteras av integrate-into-
|
||||
# nodered.sh (hostname -I, 192.168.x/10.x), fallback 192.168.1.10.
|
||||
NC_HOST_IP=
|
||||
TZ=Europe/Stockholm
|
||||
NODERED_CREDENTIAL_SECRET=change-this-secret-in-production
|
||||
|
||||
+2
-1
@@ -13,8 +13,9 @@ services:
|
||||
PORT: "1881"
|
||||
TZ: ${TZ:-Europe/Stockholm}
|
||||
NEXTCLOUD_URL: ${NEXTCLOUD_URL:-https://cloud.domain.name}
|
||||
COLLABORA_URL: ${COLLABORA_URL:-http://172.17.0.2:9980}
|
||||
COLLABORA_URL: ${COLLABORA_URL:-https://code:9980}
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
- "cloud.domain.name:${NC_HOST_IP:-192.168.1.10}"
|
||||
volumes:
|
||||
- nodered_collab_data:/data
|
||||
|
||||
@@ -35,6 +35,13 @@ NODERED_CONTAINER="${NODERED_CONTAINER:-nextcloud-node-red}"
|
||||
NODERED_PORT="${NODERED_PORT:-1880}"
|
||||
CODE_CONTAINER="${CODE_CONTAINER:-code}"
|
||||
COLLABORA_IP="${COLLABORA_IP:-}"
|
||||
# Aldrig http://127.0.0.1:9980 eller http://host.docker.internal:9980
|
||||
case "${COLLABORA_URL:-https://code:9980}" in
|
||||
http://127.0.0.1:*|http://localhost:*|http://host.docker.internal:*|\
|
||||
https://127.0.0.1:*|https://localhost:*|https://host.docker.internal:*|"")
|
||||
COLLABORA_URL="https://code:9980" ;;
|
||||
*) COLLABORA_URL="${COLLABORA_URL}" ;;
|
||||
esac
|
||||
NEXTCLOUD_URL="${NEXTCLOUD_URL:-https://cloud.domain.name}"
|
||||
[ -n "${NEXTCLOUD_URL}" ] || NEXTCLOUD_URL="https://cloud.domain.name"
|
||||
|
||||
@@ -69,6 +76,7 @@ PKG_SRC="${INSTALL_DIR}" \
|
||||
NODERED_PORT="${NODERED_PORT}" \
|
||||
CODE_CONTAINER="${CODE_CONTAINER}" \
|
||||
COLLABORA_IP="${COLLABORA_IP}" \
|
||||
COLLABORA_URL="${COLLABORA_URL}" \
|
||||
NEXTCLOUD_URL="${NEXTCLOUD_URL}" \
|
||||
INSTALL_USER="${INSTALL_USER:-}" \
|
||||
bash "${SCRIPT_DIR}/scripts/integrate-into-nodered.sh"
|
||||
|
||||
@@ -146,6 +146,45 @@ code_bridge_ip() {
|
||||
docker inspect -f '{{range $k,$v := .NetworkSettings.Networks}}{{if eq $k "bridge"}}{{$v.IPAddress}}{{end}}{{end}}' "${CODE_CONTAINER}" 2>/dev/null
|
||||
}
|
||||
|
||||
# Host-LAN-IP för extra_hosts (detektera; fallback 192.168.1.10)
|
||||
detect_host_lan_ip() {
|
||||
local ip=""
|
||||
if command -v hostname >/dev/null 2>&1; then
|
||||
ip="$(hostname -I 2>/dev/null | tr ' ' '\n' \
|
||||
| grep -E '^(192\.168|10)\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1 || true)"
|
||||
fi
|
||||
if [ -z "${ip}" ] && command -v ip >/dev/null 2>&1; then
|
||||
ip="$(ip -4 addr show scope global 2>/dev/null | awk '/inet /{print $2}' | cut -d/ -f1 \
|
||||
| grep -E '^(192\.168|10)\.' | head -n1 || true)"
|
||||
fi
|
||||
if [ -z "${ip}" ]; then
|
||||
warn "Kunde inte detektera host-LAN-IP — fallback 192.168.1.10"
|
||||
ip="192.168.1.10"
|
||||
fi
|
||||
HOST_LAN_IP="${ip}"
|
||||
log "Host-LAN-IP: ${HOST_LAN_IP}"
|
||||
}
|
||||
|
||||
# Skriv NC_HOST_IP i nextcloud-node-red/.env så compose-substitutionen plockar upp den
|
||||
write_nodered_env_ip() {
|
||||
local envfile="${NODERED_DIR}/.env"
|
||||
local existing=""
|
||||
if [ -f "${envfile}" ]; then
|
||||
existing="$(grep -E '^NC_HOST_IP=[[:alnum:].:]+' "${envfile}" 2>/dev/null | tail -n1 | cut -d= -f2 || true)"
|
||||
fi
|
||||
if [ -n "${existing}" ]; then
|
||||
log "${envfile} har redan NC_HOST_IP=${existing} — behåller"
|
||||
HOST_LAN_IP="${existing}"
|
||||
return 0
|
||||
fi
|
||||
if [ -f "${envfile}" ] && grep -q '^NC_HOST_IP=' "${envfile}" 2>/dev/null; then
|
||||
run_as_root sed -i "s|^NC_HOST_IP=.*|NC_HOST_IP=${HOST_LAN_IP}|" "${envfile}"
|
||||
else
|
||||
run_as_root bash -c "echo 'NC_HOST_IP=${HOST_LAN_IP}' >> '${envfile}'"
|
||||
fi
|
||||
log "NC_HOST_IP=${HOST_LAN_IP} → ${envfile}"
|
||||
}
|
||||
|
||||
detect_code_ip() {
|
||||
local ip
|
||||
ip="$(code_bridge_ip)"
|
||||
@@ -202,6 +241,8 @@ resolve_paths() {
|
||||
|
||||
detect_nodered_dir
|
||||
detect_code_ip
|
||||
detect_host_lan_ip
|
||||
write_nodered_env_ip
|
||||
}
|
||||
|
||||
stop_sidecar_if_any() {
|
||||
@@ -316,13 +357,85 @@ EOF
|
||||
fi
|
||||
}
|
||||
|
||||
# Krav: docker network connect <nodered-nät> code — ignorerar already connected
|
||||
connect_code_network() {
|
||||
log "Connecting ${NODERED_CONTAINER} to Docker bridge (CODE)"
|
||||
if docker network inspect bridge --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null | grep -q "${NODERED_CONTAINER}"; then
|
||||
log "Already connected to bridge"
|
||||
else
|
||||
docker network connect bridge "${NODERED_CONTAINER}" 2>/dev/null || warn "Could not connect bridge — check manually"
|
||||
local net
|
||||
net="$(docker inspect -f '{{range $k,$v := .NetworkSettings.Networks}}{{printf "%s\n" $k}}{{end}}' "${NODERED_CONTAINER}" 2>/dev/null \
|
||||
| grep -v '^bridge$' | head -n1)"
|
||||
[ -n "${net}" ] || die "No Node-RED compose network on ${NODERED_CONTAINER}"
|
||||
|
||||
if docker network inspect "${net}" --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null | grep -qw "${CODE_CONTAINER}"; then
|
||||
log "Already connected: ${CODE_CONTAINER} on ${net}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Connecting ${CODE_CONTAINER} → ${net}"
|
||||
if ! docker network connect "${net}" "${CODE_CONTAINER}" 2>/dev/null; then
|
||||
if docker network inspect "${net}" --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null | grep -qw "${CODE_CONTAINER}"; then
|
||||
log "Already connected (race): ${CODE_CONTAINER} on ${net}"
|
||||
else
|
||||
warn "Could not connect ${CODE_CONTAINER} → ${net} — COLLABORA_URL fallar tillbaka till CODE-IP"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
compose_service_name() {
|
||||
local svc
|
||||
svc="$(docker inspect -f '{{index .Config.Labels "com.docker.compose.service"}}' "${NODERED_CONTAINER}" 2>/dev/null || true)"
|
||||
echo "${svc:-node-red}"
|
||||
}
|
||||
|
||||
# Recreate utan 'docker compose down' — volymer (node-red-data) bevaras.
|
||||
# ExtraHosts måste vara ifyllda efteråt.
|
||||
recreate_nodered_service() {
|
||||
local service extra
|
||||
service="$(compose_service_name)"
|
||||
|
||||
log "Recreating ${service} (--no-deps --force-recreate, volymer bevaras)..."
|
||||
if ! compose_run up -d --no-deps --force-recreate "${service}"; then
|
||||
warn "force-recreate misslyckades — rm + up --no-deps (volymen node-red-data ligger kvar)"
|
||||
run_as_root docker rm -f "${NODERED_CONTAINER}" 2>/dev/null || true
|
||||
compose_run up -d --no-deps "${service}"
|
||||
fi
|
||||
|
||||
for _ in $(seq 1 10); do
|
||||
extra="$(docker inspect -f '{{len .HostConfig.ExtraHosts}}' "${NODERED_CONTAINER}" 2>/dev/null || echo 0)"
|
||||
[ "${extra}" != "0" ] && break
|
||||
sleep 1
|
||||
done
|
||||
if [ -z "${extra:-0}" ] || [ "${extra}" = "0" ]; then
|
||||
die "ExtraHosts är [] på ${NODERED_CONTAINER} efter recreate — kontrollera extra_hosts i ${NODERED_DIR}/docker-compose.yml"
|
||||
fi
|
||||
log "ExtraHosts (${extra}): $(docker inspect -f '{{json .HostConfig.ExtraHosts}}' "${NODERED_CONTAINER}")"
|
||||
}
|
||||
|
||||
# COLLABORA_URL: https://code:9980 primärt, fallback https://<CODE-IP>:9980.
|
||||
# Aldrig http://127.0.0.1:9980 eller http://host.docker.internal:9980.
|
||||
resolve_collabora_url() {
|
||||
local url="${COLLABORA_URL:-https://code:9980}"
|
||||
case "${url}" in
|
||||
http://127.0.0.1:*|http://localhost:*|http://host.docker.internal:*|\
|
||||
https://127.0.0.1:*|https://localhost:*|https://host.docker.internal:*)
|
||||
warn "Otillåten COLLABORA_URL '${url}' — tvingar https://code:9980"
|
||||
url="https://code:9980"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Fallback till CODE-IP om 'code' inte kan resolvas från nod-containern
|
||||
if ! docker exec "${NODERED_CONTAINER}" getent hosts code >/dev/null 2>&1; then
|
||||
local ip
|
||||
ip="$(docker inspect -f '{{range $k,$v := .NetworkSettings.Networks}}{{$v.IPAddress}} {{end}}' "${CODE_CONTAINER}" 2>/dev/null | awk '{print $1}')"
|
||||
[ -n "${ip}" ] || ip="${COLLABORA_IP:-}"
|
||||
if [ -n "${ip}" ]; then
|
||||
warn "'code' inte resolvbart från ${NODERED_CONTAINER} — fallback https://${ip}:9980"
|
||||
url="https://${ip}:9980"
|
||||
else
|
||||
die "Varken 'code'-DNS eller CODE-IP tillgänglig — kan inte sätta COLLABORA_URL"
|
||||
fi
|
||||
fi
|
||||
|
||||
COLLABORA_URL="${url}"
|
||||
log "COLLABORA_URL=${COLLABORA_URL}"
|
||||
}
|
||||
|
||||
rebuild_nodered() {
|
||||
@@ -334,7 +447,7 @@ rebuild_nodered() {
|
||||
else
|
||||
compose_run build
|
||||
fi
|
||||
compose_run up -d
|
||||
recreate_nodered_service
|
||||
}
|
||||
|
||||
wait_nodered() {
|
||||
@@ -350,18 +463,35 @@ wait_nodered() {
|
||||
}
|
||||
|
||||
verify_code_from_nodered() {
|
||||
local code_ip
|
||||
code_ip="$(code_bridge_ip)"
|
||||
[ -n "${code_ip}" ] || code_ip="${COLLABORA_IP}"
|
||||
# CODE listens on HTTPS internally (HTTP returns empty reply)
|
||||
local url="https://${code_ip}:9980/hosting/capabilities"
|
||||
log "Testing CODE from ${NODERED_CONTAINER}: ${url}"
|
||||
if docker exec "${NODERED_CONTAINER}" curl -sfk "${url}" >/dev/null 2>&1; then
|
||||
log "OK: CODE reachable from Node-RED container"
|
||||
# Krav 7: getent i containern != 127.0.0.1/127.0.1.1 + curl mot CODE och Nextcloud
|
||||
local fail=0 h ip_out
|
||||
for h in cloud.domain.name docs.domain.name host.docker.internal code; do
|
||||
ip_out="$(docker exec "${NODERED_CONTAINER}" getent hosts "${h}" 2>/dev/null | awk '{print $1}' | head -n1 || true)"
|
||||
if [ -z "${ip_out}" ]; then
|
||||
warn "getent ${h}: INGET SVAR"; fail=1
|
||||
elif [ "${ip_out#127.}" != "${ip_out}" ] || [ "${ip_out}" = "::1" ]; then
|
||||
warn "getent ${h}: loopback (${ip_out}) — extra_hosts/translering trasig"; fail=1
|
||||
else
|
||||
warn "CODE not reachable — run: docker network connect bridge ${NODERED_CONTAINER}"
|
||||
warn "nc-collab-config collaboraUrl=https://${code_ip}:9980 (verifyTls=false)"
|
||||
log "getent ${h}: ${ip_out}"
|
||||
fi
|
||||
done
|
||||
|
||||
if docker exec "${NODERED_CONTAINER}" curl -sfk "${COLLABORA_URL}/hosting/capabilities" >/dev/null 2>&1; then
|
||||
log "OK: CODE nås från Node-RED: ${COLLABORA_URL}/hosting/capabilities"
|
||||
else
|
||||
warn "CODE inte nåbar: ${COLLABORA_URL}/hosting/capabilities"
|
||||
warn "Kör: docker network connect \$(docker inspect -f '{{range \$k,\$_ := .NetworkSettings.Networks}}{{printf \"%s\\n\" \$k}}{{end}}' ${NODERED_CONTAINER} | head -n1) ${CODE_CONTAINER}"
|
||||
fail=1
|
||||
fi
|
||||
|
||||
if docker exec "${NODERED_CONTAINER}" curl -sfk https://cloud.domain.name/status.php >/dev/null 2>&1; then
|
||||
log "OK: Nextcloud nås från Node-RED: https://cloud.domain.name/status.php"
|
||||
else
|
||||
warn "Nextcloud inte nåbar från Node-RED via https://cloud.domain.name/status.php"
|
||||
fail=1
|
||||
fi
|
||||
|
||||
return "${fail}"
|
||||
}
|
||||
|
||||
main() {
|
||||
@@ -377,13 +507,14 @@ main() {
|
||||
patch_entrypoint
|
||||
rebuild_nodered
|
||||
connect_code_network
|
||||
resolve_collabora_url
|
||||
wait_nodered
|
||||
verify_code_from_nodered
|
||||
if ! verify_code_from_nodered; then
|
||||
warn "Verifiering hade fel — se varningarna ovan"
|
||||
fi
|
||||
|
||||
local host_ip code_ip nc_url
|
||||
local host_ip nc_url
|
||||
host_ip="$(hostname -I 2>/dev/null | awk '{print $1}' || echo "127.0.0.1")"
|
||||
code_ip="$(code_bridge_ip)"
|
||||
[ -n "${code_ip}" ] || code_ip="${COLLABORA_IP}"
|
||||
nc_url="${NEXTCLOUD_URL:-https://cloud.domain.name}"
|
||||
|
||||
cat <<EOF
|
||||
@@ -394,7 +525,7 @@ Integrating done — same Node-RED on port ${NODERED_PORT}
|
||||
|
||||
Create config first (gear → nc-collab-config):
|
||||
Nextcloud: ${nc_url}
|
||||
Collabora: https://${code_ip}:9980 (verifyTls=false)
|
||||
Collabora: ${COLLABORA_URL} (verifyTls=false — self-signed internt)
|
||||
Public WOPI: ${nc_url}
|
||||
Auth: username + app password
|
||||
|
||||
|
||||
Reference in New Issue
Block a user