/** * llmindex.io — PM2 process definitions for the m3u96b node * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * License: Proprietary — © Simon-Pierre Boucher, all rights reserved * * m3u96b is macOS (no systemd); PM2 provides the auto-restart layer. The * systemd units in infra/systemd/ are the Linux equivalent. * Usage: pm2 startOrReload infra/ecosystem.config.cjs */ const fs = require('node:fs'); const path = require('node:path'); const APP_DIR = path.resolve(__dirname, '..'); /** Minimal .env parser (no dotenv dependency at the PM2 layer). */ function loadEnv() { const envPath = path.join(APP_DIR, '.env'); const env = {}; if (fs.existsSync(envPath)) { for (const line of fs.readFileSync(envPath, 'utf8').split('\n')) { const m = line.match(/^\s*([A-Z0-9_]+)\s*=\s*(.*)\s*$/); if (m && !line.trim().startsWith('#')) { env[m[1]] = m[2].replace(/^["']|["']$/g, ''); } } } return env; } const env = loadEnv(); module.exports = { apps: [ { name: 'llmindex-web', cwd: APP_DIR, script: 'apps/web/.next/standalone/apps/web/server.js', env: { ...env, NODE_ENV: 'production', PORT: '3100', HOSTNAME: '127.0.0.1' }, max_memory_restart: '1G', autorestart: true, }, { name: 'llmindex-worker', cwd: path.join(APP_DIR, 'apps/worker'), // .bin/tsx is a shell shim PM2 would feed to node — use the real JS entry script: 'node_modules/tsx/dist/cli.mjs', args: 'src/index.ts', env: { ...env, NODE_ENV: 'production' }, max_memory_restart: '1G', autorestart: true, }, { name: 'llmindex-ngrok', script: '/opt/homebrew/bin/ngrok', args: 'http 3100 --url=https://www.llmindex.io --log=stdout', interpreter: 'none', env: env.NGROK_AUTHTOKEN ? { NGROK_AUTHTOKEN: env.NGROK_AUTHTOKEN } : {}, autorestart: true, }, ], };