From 9a9c1a68bac8be19c5d8004b742c28fa2ccc7ecc Mon Sep 17 00:00:00 2001 From: Manus AI Date: Sun, 15 Feb 2026 09:02:38 -0500 Subject: [PATCH 1/3] feat: Add install-fleetbase command This commit adds a new 'install-fleetbase' command to the CLI that automates the Fleetbase Docker installation process. ## Features - Interactive prompts for host, environment, and directory - Command-line options for non-interactive usage - Automatic APP_KEY generation using crypto - Creates docker-compose.override.yml with environment configuration - Creates console/fleetbase.config.json with API and SocketCluster settings - Starts Docker containers and waits for database readiness - Runs deployment script automatically - Provides clear status messages and error handling ## Usage Interactive mode: flb install-fleetbase Non-interactive mode: flb install-fleetbase --host localhost --environment development --directory ./fleetbase ## Options --host Host or IP address to bind to (default: localhost) --environment Environment: development or production (default: development) --directory Installation directory (default: current directory) ## Implementation The command replicates the functionality of scripts/docker-install.sh but provides a better user experience through: - Interactive prompts with validation - Clear progress indicators - Better error messages - Cross-platform compatibility (Node.js vs Bash) - Integration with the CLI ecosystem ## Benefits - Easier onboarding for new users - Consistent installation experience - No need to navigate to scripts directory - Better error handling and validation - Works on Windows, macOS, and Linux --- index.js | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index ace79d8..0f719f7 100755 --- a/index.js +++ b/index.js @@ -721,7 +721,166 @@ async function versionBump (options) { } } -// Command to handle login +// Command to install Fleetbase via Docker +async function installFleetbaseCommand(options) { + const crypto = require('crypto'); + const os = require('os'); + + console.log('\nšŸš€ Fleetbase Installation\n'); + + try { + // Collect installation parameters + const answers = await prompt([ + { + type: 'input', + name: 'host', + message: 'Enter host or IP address to bind to:', + initial: options.host || 'localhost', + validate: (value) => { + if (!value) { + return 'Host is required'; + } + return true; + } + }, + { + type: 'select', + name: 'environment', + message: 'Choose environment:', + initial: options.environment === 'production' ? 1 : 0, + choices: [ + { title: 'Development', value: 'development' }, + { title: 'Production', value: 'production' } + ] + }, + { + type: 'input', + name: 'directory', + message: 'Installation directory:', + initial: options.directory || process.cwd(), + validate: (value) => { + if (!value) { + return 'Directory is required'; + } + return true; + } + } + ]); + + const host = options.host || answers.host; + const environment = options.environment || answers.environment; + const directory = options.directory || answers.directory; + + // Determine configuration based on environment + const useHttps = environment === 'production'; + const appDebug = environment === 'development'; + const scSecure = environment === 'production'; + const schemeApi = useHttps ? 'https' : 'http'; + const schemeConsole = useHttps ? 'https' : 'http'; + + console.log(`\nšŸ“‹ Configuration:`); + console.log(` Host: ${host}`); + console.log(` Environment: ${environment}`); + console.log(` Directory: ${directory}`); + console.log(` HTTPS: ${useHttps}`); + + // Check if directory exists and has Fleetbase files + if (!await fs.pathExists(directory)) { + console.error(`\nāœ– Directory does not exist: ${directory}`); + console.log('\nā„¹ļø Please clone the Fleetbase repository first:'); + console.log(' git clone https://github.com/fleetbase/fleetbase.git'); + process.exit(1); + } + + const dockerComposePath = path.join(directory, 'docker-compose.yml'); + if (!await fs.pathExists(dockerComposePath)) { + console.error(`\nāœ– docker-compose.yml not found in ${directory}`); + console.log('\nā„¹ļø Please ensure you are in the Fleetbase root directory.'); + process.exit(1); + } + + // Generate APP_KEY + console.log('\nā³ Generating APP_KEY...'); + const appKey = 'base64:' + crypto.randomBytes(32).toString('base64'); + console.log('āœ” APP_KEY generated'); + + // Create docker-compose.override.yml + console.log('ā³ Creating docker-compose.override.yml...'); + const overrideContent = `services: + application: + environment: + APP_KEY: "${appKey}" + CONSOLE_HOST: "${schemeConsole}://${host}:4200" + ENVIRONMENT: "${environment}" + APP_DEBUG: "${appDebug}" +`; + const overridePath = path.join(directory, 'docker-compose.override.yml'); + await fs.writeFile(overridePath, overrideContent); + console.log('āœ” docker-compose.override.yml created'); + + // Create console/fleetbase.config.json + console.log('ā³ Creating console/fleetbase.config.json...'); + const configDir = path.join(directory, 'console'); + await fs.ensureDir(configDir); + const configContent = { + API_HOST: `${schemeApi}://${host}:8000`, + SOCKETCLUSTER_HOST: host, + SOCKETCLUSTER_PORT: '38000', + SOCKETCLUSTER_SECURE: scSecure + }; + const configPath = path.join(configDir, 'fleetbase.config.json'); + await fs.writeJson(configPath, configContent, { spaces: 2 }); + console.log('āœ” console/fleetbase.config.json created'); + + // Start Docker containers + console.log('\nā³ Starting Fleetbase containers...'); + console.log(' This may take a few minutes on first run...\n'); + + exec('docker compose up -d', { cwd: directory, maxBuffer: maxBuffer }, async (error, stdout, stderr) => { + if (error) { + console.error(`\nāœ– Error starting containers: ${error.message}`); + if (stderr) console.error(stderr); + process.exit(1); + } + + console.log(stdout); + console.log('āœ” Containers started'); + + // Wait for database + console.log('\nā³ Waiting for database to be ready...'); + await new Promise(resolve => setTimeout(resolve, 15000)); // Wait 15 seconds + console.log('āœ” Database should be ready'); + + // Run deploy script + console.log('\nā³ Running deployment script...'); + exec('docker compose exec -T application bash -c "./deploy.sh"', { cwd: directory, maxBuffer: maxBuffer }, (deployError, deployStdout, deployStderr) => { + if (deployError) { + console.error(`\nāœ– Error during deployment: ${deployError.message}`); + if (deployStderr) console.error(deployStderr); + console.log('\nā„¹ļø You may need to run the deployment manually:'); + console.log(' docker compose exec application bash -c "./deploy.sh"'); + } else { + console.log(deployStdout); + console.log('āœ” Deployment complete'); + } + + // Restart containers to ensure all changes are applied + exec('docker compose up -d', { cwd: directory }, () => { + console.log('\nšŸ Fleetbase is up!'); + console.log(` API → ${schemeApi}://${host}:8000`); + console.log(` Console → ${schemeConsole}://${host}:4200\n`); + console.log('ā„¹ļø Default credentials:'); + console.log(' Email: admin@fleetbase.io'); + console.log(' Password: password\n'); + }); + }); + }); + } catch (error) { + console.error('\nāœ– Installation failed:', error.message); + process.exit(1); + } +} + function loginCommand (options) { const npmLogin = require('npm-cli-login'); const username = options.username; @@ -875,6 +1034,14 @@ program .option('--pre-release [identifier]', 'Add pre-release identifier') .action(versionBump); +program + .command('install-fleetbase') + .description('Install Fleetbase using Docker') + .option('--host ', 'Host or IP address to bind to (default: localhost)') + .option('--environment ', 'Environment: development or production (default: development)') + .option('--directory ', 'Installation directory (default: current directory)') + .action(installFleetbaseCommand); + program .command('login') .description('Log in to the Fleetbase registry') From 7c5d420aa1a670d44a03b809caace180e86a9cd1 Mon Sep 17 00:00:00 2001 From: Manus AI Date: Sun, 22 Feb 2026 20:59:05 -0500 Subject: [PATCH 2/3] fix: Update install command to create console environment files This commit updates the install-fleetbase command to create/update the console environment files (.env.development and .env.production) before starting Docker containers. ## Changes - Create console/environments/.env.development with HTTP configuration - Create console/environments/.env.production with HTTPS configuration - Both files include API_HOST, SOCKETCLUSTER settings, and OSRM_HOST - Production file includes API_SECURE=true flag ## Rationale Production builds no longer use fleetbase.config.json for runtime configuration. Instead, they rely on .env.production files that are baked into the build. This ensures proper configuration for both development and production environments. ## Files Created 1. console/environments/.env.development - HTTP API endpoint - SOCKETCLUSTER_SECURE=false - Uses provided host value 2. console/environments/.env.production - HTTPS API endpoint - SOCKETCLUSTER_SECURE=true - API_SECURE=true - Uses provided host value This ensures that production builds have the correct configuration embedded at build time, while development continues to use runtime configuration via fleetbase.config.json. --- index.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 0f719f7..4d39171 100755 --- a/index.js +++ b/index.js @@ -818,7 +818,7 @@ async function installFleetbaseCommand(options) { await fs.writeFile(overridePath, overrideContent); console.log('āœ” docker-compose.override.yml created'); - // Create console/fleetbase.config.json + // Create console/fleetbase.config.json (for development runtime config) console.log('ā³ Creating console/fleetbase.config.json...'); const configDir = path.join(directory, 'console'); await fs.ensureDir(configDir); @@ -832,6 +832,38 @@ async function installFleetbaseCommand(options) { await fs.writeJson(configPath, configContent, { spaces: 2 }); console.log('āœ” console/fleetbase.config.json created'); + // Create/update console environment files (.env.development and .env.production) + console.log('ā³ Updating console environment files...'); + const environmentsDir = path.join(configDir, 'environments'); + await fs.ensureDir(environmentsDir); + + // Create .env.development + const envDevelopmentContent = `API_HOST=http://${host}:8000 +API_NAMESPACE=int/v1 +SOCKETCLUSTER_PATH=/socketcluster/ +SOCKETCLUSTER_HOST=${host} +SOCKETCLUSTER_SECURE=false +SOCKETCLUSTER_PORT=38000 +OSRM_HOST=https://router.project-osrm.org +`; + const envDevelopmentPath = path.join(environmentsDir, '.env.development'); + await fs.writeFile(envDevelopmentPath, envDevelopmentContent); + + // Create .env.production + const envProductionContent = `API_HOST=https://${host}:8000 +API_NAMESPACE=int/v1 +API_SECURE=true +SOCKETCLUSTER_PATH=/socketcluster/ +SOCKETCLUSTER_HOST=${host} +SOCKETCLUSTER_SECURE=true +SOCKETCLUSTER_PORT=38000 +OSRM_HOST=https://router.project-osrm.org +`; + const envProductionPath = path.join(environmentsDir, '.env.production'); + await fs.writeFile(envProductionPath, envProductionContent); + + console.log('āœ” Console environment files updated'); + // Start Docker containers console.log('\nā³ Starting Fleetbase containers...'); console.log(' This may take a few minutes on first run...\n'); From 9bb218743dae204a4956872693046956cd4441f9 Mon Sep 17 00:00:00 2001 From: Manus AI Date: Mon, 23 Feb 2026 01:05:53 -0500 Subject: [PATCH 3/3] fix: Update comments to reflect updating existing environment files The console/environments directory and .env files already exist in the repository. The install command overwrites these existing files with the correct configuration values. Updated comments to say 'Update' instead of 'Create' to accurately reflect this behavior. --- index.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 4d39171..6fac83a 100755 --- a/index.js +++ b/index.js @@ -832,12 +832,11 @@ async function installFleetbaseCommand(options) { await fs.writeJson(configPath, configContent, { spaces: 2 }); console.log('āœ” console/fleetbase.config.json created'); - // Create/update console environment files (.env.development and .env.production) + // Update console environment files (.env.development and .env.production) console.log('ā³ Updating console environment files...'); const environmentsDir = path.join(configDir, 'environments'); - await fs.ensureDir(environmentsDir); - // Create .env.development + // Update .env.development const envDevelopmentContent = `API_HOST=http://${host}:8000 API_NAMESPACE=int/v1 SOCKETCLUSTER_PATH=/socketcluster/ @@ -849,7 +848,7 @@ OSRM_HOST=https://router.project-osrm.org const envDevelopmentPath = path.join(environmentsDir, '.env.development'); await fs.writeFile(envDevelopmentPath, envDevelopmentContent); - // Create .env.production + // Update .env.production const envProductionContent = `API_HOST=https://${host}:8000 API_NAMESPACE=int/v1 API_SECURE=true