File size: 6,307 Bytes
4c98a98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57bd11f
 
4c98a98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57bd11f
 
4c98a98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57bd11f
4c98a98
 
 
57bd11f
 
4c98a98
 
 
 
 
 
 
 
 
 
 
 
 
57bd11f
4c98a98
 
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
#!/bin/sh
# entrypoint.sh — single-container HF Space bootstrap (Alpine)
set -eu

log() { echo "[entrypoint] $*"; }
warn() { echo "[entrypoint][WARN] $*" >&2; }
err() { echo "[entrypoint][ERROR] $*" >&2; }

# Load .env if present (local dev); HF Space Secrets come as env already
if [ -f /app/.env ]; then
  log "Loading /app/.env"
  set -a; . /app/.env; set +a
fi
if [ -f .env ]; then
  log "Loading ./.env"
  set -a; . ./.env; set +a
fi

# Defaults — HF expects 7860
export N8N_PORT=${N8N_PORT:-7860}
export N8N_LISTEN_ADDRESS=${N8N_LISTEN_ADDRESS:-0.0.0.0}
export N8N_PORT N8N_LISTEN_ADDRESS
export DB_TYPE=${DB_TYPE:-postgresdb}
export DB_POSTGRESDB_HOST=${DB_POSTGRESDB_HOST:-127.0.0.1}
export DB_POSTGRESDB_PORT=${DB_POSTGRESDB_PORT:-5432}
export DB_POSTGRESDB_DATABASE=${DB_POSTGRESDB_DATABASE:-n8n}
export DB_POSTGRESDB_USER=${DB_POSTGRESDB_USER:-n8n}
export PGDATA=${PGDATA:-/data/postgres}
export N8N_USER_FOLDER=${N8N_USER_FOLDER:-/data/n8n}
export N8N_RUNNERS_ENABLED=${N8N_RUNNERS_ENABLED:-true}
export N8N_RUNNERS_MODE=${N8N_RUNNERS_MODE:-external}
export N8N_RUNNERS_BROKER_PORT=${N8N_RUNNERS_BROKER_PORT:-5679}
export N8N_RUNNERS_BROKER_LISTEN_ADDRESS=${N8N_RUNNERS_BROKER_LISTEN_ADDRESS:-0.0.0.0}
export N8N_RUNNERS_TASK_BROKER_URI=${N8N_RUNNERS_TASK_BROKER_URI:-http://127.0.0.1:5679}
export N8N_RUNNERS_AUTH_TOKEN=${N8N_RUNNERS_AUTH_TOKEN:-}
export N8N_RUNNERS_TASK_TIMEOUT=${N8N_RUNNERS_TASK_TIMEOUT:-300}
export N8N_INSTANCE_AI_SANDBOX_ENABLED=${N8N_INSTANCE_AI_SANDBOX_ENABLED:-true}
export N8N_INSTANCE_AI_SANDBOX_PROVIDER=${N8N_INSTANCE_AI_SANDBOX_PROVIDER:-n8n-sandbox}
export N8N_SANDBOX_SERVICE_URL=${N8N_SANDBOX_SERVICE_URL:-http://127.0.0.1:8080}
export GENERIC_TIMEZONE=${GENERIC_TIMEZONE:-Asia/Kolkata}

# Secrets persistence: /data/.env.secrets (survives bucket mount, else ephemeral)
SECRETS_FILE="/data/.env.secrets"
mkdir -p /data/postgres /data/n8n /data/sandbox /var/log/supervisor /var/run/postgresql 2>/dev/null || true
chmod 777 /data 2>/dev/null || true
chown postgres:postgres /var/run/postgresql 2>/dev/null || true

gen_secret() { cat /dev/urandom 2>/dev/null | tr -dc 'a-f0-9' | head -c 64 || openssl rand -hex 32 2>/dev/null || head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' | head -c 64; }

if [ ! -f "$SECRETS_FILE" ]; then
  log "Generating $SECRETS_FILE"
  {
    echo "# auto-generated $(date -u) — persists on /data bucket, else ephemeral"
    echo "N8N_ENCRYPTION_KEY=$(gen_secret)"
    echo "DB_POSTGRESDB_PASSWORD=$(gen_secret | cut -c1-32)"
    echo "N8N_RUNNERS_AUTH_TOKEN=$(gen_secret)"
    echo "N8N_USER_MANAGEMENT_JWT_SECRET=$(gen_secret)"
    echo "SANDBOX_API_KEYS=$(gen_secret | cut -c1-32)"
  } > "$SECRETS_FILE"
  chmod 600 "$SECRETS_FILE"
fi

# Load secrets file, but do not override already-exported env (HF Secrets win)
set -a
# shellcheck disable=SC1090
while IFS='=' read -r k v; do
  case "$k" in \#*|"") continue;; esac
  # only set if not already set
  if eval "[ -z \"\${$k:-}\" ]"; then
    # strip possible quotes
    v=$(printf "%s" "$v" | sed "s/^['\"]//;s/['\"]$//")
    export "$k=$v"
  fi
done < "$SECRETS_FILE"
set +a

# Export DB password from file if not set
if [ -z "${DB_POSTGRESDB_PASSWORD:-}" ]; then
  DB_POSTGRESDB_PASSWORD=$(grep '^DB_POSTGRESDB_PASSWORD=' "$SECRETS_FILE" | cut -d= -f2-)
  export DB_POSTGRESDB_PASSWORD
fi
if [ -z "${N8N_ENCRYPTION_KEY:-}" ]; then
  N8N_ENCRYPTION_KEY=$(grep '^N8N_ENCRYPTION_KEY=' "$SECRETS_FILE" | cut -d= -f2-)
  export N8N_ENCRYPTION_KEY
fi
if [ -z "${SANDBOX_API_KEYS:-}" ]; then
  SANDBOX_API_KEYS=$(grep '^SANDBOX_API_KEYS=' "$SECRETS_FILE" | cut -d= -f2-)
  export SANDBOX_API_KEYS
fi
export N8N_SANDBOX_SERVICE_API_KEY=${N8N_SANDBOX_SERVICE_API_KEY:-$SANDBOX_API_KEYS}
export SANDBOX_API_KEYS N8N_SANDBOX_SERVICE_API_KEY

# Also persist PGDATA ownership (fast, avoid chown -R on large /opt/runners)
chown postgres:postgres "$PGDATA" 2>/dev/null || true
chown node:node /home/node 2>/dev/null || true
chown runner:runner /home/runner 2>/dev/null || true
mkdir -p /data/n8n && chown node:node /data/n8n 2>/dev/null || true

# Init postgres if needed (only if POSTGRES_ENABLED != false and PG_VERSION missing)
if [ "${POSTGRES_ENABLED:-true}" != "false" ] && [ ! -f "$PGDATA/PG_VERSION" ]; then
  log "Initializing postgres PGDATA=$PGDATA"
  # ensure directory owned
  chown postgres:postgres "$PGDATA"
  # initdb as postgres user via su-exec
  su-exec postgres initdb -D "$PGDATA" -U postgres --no-locale --encoding=UTF8 2>&1 | tail -20
  # allow md5 + trust for local
  cat >> "$PGDATA/pg_hba.conf" <<EOF
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
EOF
  # tune for low RAM HF
  cat >> "$PGDATA/postgresql.conf" <<EOF
listen_addresses = '127.0.0.1'
port = 5432
max_connections = 40
shared_buffers = 128MB
effective_cache_size = 256MB
maintenance_work_mem = 64MB
checkpoint_completion_target = 0.9
wal_buffers = 4MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 100
work_mem = 4MB
min_wal_size = 80MB
max_wal_size = 256MB
EOF
  log "Postgres initialized"
else
  log "Postgres PGDATA exists or disabled, skipping initdb"
fi

log "N8N_VERSION=${N8N_VERSION:-unknown} N8N_PORT=$N8N_PORT DB=$DB_POSTGRESDB_HOST:$DB_POSTGRESDB_PORT/$DB_POSTGRESDB_DATABASE"
log "Runner broker $N8N_RUNNERS_BROKER_LISTEN_ADDRESS:$N8N_RUNNERS_BROKER_PORT mode=$N8N_RUNNERS_MODE"
log "Sandbox $N8N_INSTANCE_AI_SANDBOX_PROVIDER enabled=$N8N_INSTANCE_AI_SANDBOX_ENABLED url=$N8N_SANDBOX_SERVICE_URL (no Daytona)"

# Ensure N8N_USER_FOLDER exists
mkdir -p "$N8N_USER_FOLDER" 2>/dev/null || true
chown node:node "$N8N_USER_FOLDER" 2>/dev/null || true

# Export all for supervisord child processes (supervisord inherits env)
export N8N_PORT N8N_LISTEN_ADDRESS DB_TYPE DB_POSTGRESDB_HOST DB_POSTGRESDB_PORT DB_POSTGRESDB_DATABASE DB_POSTGRESDB_USER DB_POSTGRESDB_PASSWORD
export PGDATA N8N_USER_FOLDER N8N_ENCRYPTION_KEY N8N_RUNNERS_ENABLED N8N_RUNNERS_MODE N8N_RUNNERS_TASK_BROKER_URI N8N_RUNNERS_BROKER_PORT N8N_RUNNERS_BROKER_LISTEN_ADDRESS N8N_RUNNERS_AUTH_TOKEN N8N_RUNNERS_TASK_TIMEOUT
export N8N_INSTANCE_AI_SANDBOX_ENABLED N8N_INSTANCE_AI_SANDBOX_PROVIDER N8N_SANDBOX_SERVICE_URL N8N_SANDBOX_SERVICE_API_KEY SANDBOX_API_KEYS
export GENERIC_TIMEZONE

log "Starting supervisord"
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf