File size: 4,840 Bytes
e110d9d
 
 
320e776
 
 
e110d9d
 
 
 
 
7f99b73
e110d9d
 
 
 
 
 
bd3ae30
 
caf8b68
 
bd3ae30
 
e110d9d
 
 
 
 
 
7f99b73
 
 
 
 
 
 
 
 
e110d9d
 
 
 
 
 
 
5f7429a
279b061
320e776
524ec79
4d69af1
320e776
f398dc5
320e776
 
42a7d7b
e110d9d
 
32b834b
e110d9d
 
 
 
 
 
 
7f99b73
e110d9d
 
 
f398dc5
e110d9d
 
 
 
b47e0f4
 
bff801f
b47e0f4
38b8274
b56c910
b47e0f4
 
 
b56c910
b47e0f4
 
 
e110d9d
 
320e776
658dc16
 
 
 
 
 
 
 
 
 
 
 
 
e110d9d
 
f398dc5
e110d9d
 
 
 
 
 
f398dc5
e110d9d
 
 
 
 
 
5636339
 
 
bb5c703
 
e110d9d
 
 
320e776
 
7f99b73
320e776
7f99b73
 
 
 
 
 
 
 
 
 
 
 
 
 
320e776
 
 
 
e110d9d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/bin/bash
set -euo pipefail

# Tighten default file permissions for any files created by this process
umask 0077

APP_DIR="/home/node/app"
N8N_HOME="/home/node/.n8n"
N8N_PORT="${N8N_PORT:-5678}"
PUBLIC_PORT="${PUBLIC_PORT:-7861}"
SYNC_INTERVAL="${SYNC_INTERVAL:-180}"
N8N_STARTUP_TIMEOUT="${N8N_STARTUP_TIMEOUT:-180}"

mkdir -p "$N8N_HOME"

SPACE_HOST_DETECTED="${SPACE_HOST_OVERRIDE:-${SPACE_HOST:-}}"
if [ -n "$SPACE_HOST_DETECTED" ]; then
  export N8N_HOST="${N8N_HOST:-$SPACE_HOST_DETECTED}"
  # Namespace-based Proxy Configuration (n8n at root internally)
  export N8N_PATH="/"
  export N8N_PROTOCOL="https"
  export N8N_HOST="${SPACE_HOST_DETECTED}"
  export WEBHOOK_URL="https://${SPACE_HOST_DETECTED}/"
  export N8N_EDITOR_BASE_URL="https://${SPACE_HOST_DETECTED}/"
fi

export N8N_PORT
export N8N_PROTOCOL="${N8N_PROTOCOL:-https}"
export N8N_PROXY_HOPS="${N8N_PROXY_HOPS:-1}"
export N8N_LISTEN_ADDRESS="${N8N_LISTEN_ADDRESS:-0.0.0.0}"
if [ -z "${N8N_SECURE_COOKIE:-}" ]; then
  if [ "${N8N_PROTOCOL}" = "https" ]; then
    export N8N_SECURE_COOKIE="true"
  else
    export N8N_SECURE_COOKIE="false"
  fi
else
  export N8N_SECURE_COOKIE
fi
export N8N_DIAGNOSTICS_ENABLED="${N8N_DIAGNOSTICS_ENABLED:-false}"
export N8N_PERSONALIZATION_ENABLED="${N8N_PERSONALIZATION_ENABLED:-false}"
export N8N_USER_FOLDER="$N8N_HOME"
export N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS="${N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS:-true}"
export GENERIC_TIMEZONE="${GENERIC_TIMEZONE:-${TZ:-UTC}}"
export TZ="${TZ:-$GENERIC_TIMEZONE}"



# Disable noisy or unnecessary services
export N8N_PYTHON_NODES_ENABLED="${N8N_PYTHON_NODES_ENABLED:-false}"
export N8N_TASK_RUNNERS_ENABLED="${N8N_TASK_RUNNERS_ENABLED:-false}"
export N8N_LICENSE_AUTO_RENEW_ENABLED="${N8N_LICENSE_AUTO_RENEW_ENABLED:-false}"
export N8N_LOG_LEVEL="${N8N_LOG_LEVEL:-error}"

# n8n v2 uses built-in user management.

echo ""
echo "  ╔════════════════════════════════════╗"
echo "  β•‘            Hugging8n               β•‘"
echo "  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•"
echo ""
echo "Public host : ${SPACE_HOST_DETECTED:-not detected}"
echo "n8n port    : ${N8N_PORT}"
echo "Public port : ${PUBLIC_PORT}"
echo "Timezone    : ${GENERIC_TIMEZONE}"
echo "Sync every  : ${SYNC_INTERVAL}s"
echo "Startup wait: ${N8N_STARTUP_TIMEOUT}s"

if [ -n "${HF_TOKEN:-}" ]; then
  echo "Restoring persisted n8n state from HF Dataset..."
  python3 "$APP_DIR/n8n-sync.py" restore || true
else
  echo "HF_TOKEN is not set. Running without dataset persistence."
fi

CLOUDFLARE_WORKERS_TOKEN="${CLOUDFLARE_WORKERS_TOKEN:-${CLOUDFLARE_API_TOKEN:-}}"
export CLOUDFLARE_WORKERS_TOKEN
CF_PROXY_ENV_FILE="/tmp/hugging8n-cloudflare-proxy.env"
if [ -n "${CLOUDFLARE_WORKERS_TOKEN:-}" ] || [ -n "${CLOUDFLARE_PROXY_URL:-}" ]; then
  export CLOUDFLARE_PROXY_DEBUG="${CLOUDFLARE_PROXY_DEBUG:-false}"
  echo "Preparing Cloudflare outbound proxy..."
  python3 "$APP_DIR/cloudflare-proxy-setup.py" || true
  if [ -f "$CF_PROXY_ENV_FILE" ]; then
    . "$CF_PROXY_ENV_FILE"
    echo "  Proxy environment loaded: ${CLOUDFLARE_PROXY_URL:-none}"
  fi
fi

cleanup() {
  echo "Stopping Hugging8n..."
  [ -n "${PROXY_PID:-}" ] && kill "$PROXY_PID" 2>/dev/null || true

  # Stop the background sync loop gracefully
  if [ -n "${SYNC_PID:-}" ]; then
    kill "$SYNC_PID" 2>/dev/null || true
    wait "$SYNC_PID" 2>/dev/null || true
  fi

  # Wait for n8n to finish its graceful shutdown to ensure DB state is flushed
  if [ -n "${N8N_PID:-}" ]; then
    kill -TERM "$N8N_PID" 2>/dev/null || true
    wait "$N8N_PID" 2>/dev/null || true
  fi

  if [ -n "${HF_TOKEN:-}" ]; then
    echo "Running final backup pass..."
    python3 "$APP_DIR/n8n-sync.py" sync-once || true
  fi
}

trap cleanup EXIT INT TERM

if [ -n "${HF_TOKEN:-}" ]; then
  python3 "$APP_DIR/n8n-sync.py" loop &
  SYNC_PID=$!
fi

node "$APP_DIR/health-server.js" &
PROXY_PID=$!

if [ -n "${CLOUDFLARE_WORKERS_TOKEN:-}" ]; then
  echo "Setting up Cloudflare KeepAlive monitor..."
  python3 "$APP_DIR/cloudflare-keepalive-setup.py" || true
fi

n8n start &
N8N_PID=$!

# Readiness probe
echo "Waiting for n8n to be ready on port ${N8N_PORT}..."
start_ts="$(date +%s)"
until curl -sf "http://127.0.0.1:${N8N_PORT}/healthz" > /dev/null 2>&1; do
  now_ts="$(date +%s)"
  elapsed="$((now_ts - start_ts))"
  if [ "$elapsed" -ge "$N8N_STARTUP_TIMEOUT" ]; then
    echo "n8n did not become ready within ${N8N_STARTUP_TIMEOUT}s. Exiting."
    kill -TERM "$N8N_PID" 2>/dev/null || true
    wait "$N8N_PID" 2>/dev/null || true
    exit 1
  fi

  if ! kill -0 "$N8N_PID" 2>/dev/null; then
    echo "n8n process exited before readiness check passed. Exiting."
    exit 1
  fi

  sleep 1
done
echo "n8n is ready!"

wait "$N8N_PID"