@@ -817,6 +817,199 @@ async function registerCommand(options) {
817817 }
818818}
819819
820+ // Command to install Fleetbase via Docker
821+ async function installFleetbaseCommand ( options ) {
822+ const crypto = require ( 'crypto' ) ;
823+ const os = require ( 'os' ) ;
824+
825+ console . log ( '\n🚀 Fleetbase Installation\n' ) ;
826+
827+ try {
828+ // Collect installation parameters
829+ const answers = await prompt ( [
830+ {
831+ type : 'input' ,
832+ name : 'host' ,
833+ message : 'Enter host or IP address to bind to:' ,
834+ initial : options . host || 'localhost' ,
835+ validate : ( value ) => {
836+ if ( ! value ) {
837+ return 'Host is required' ;
838+ }
839+ return true ;
840+ }
841+ } ,
842+ {
843+ type : 'select' ,
844+ name : 'environment' ,
845+ message : 'Choose environment:' ,
846+ initial : options . environment === 'production' ? 1 : 0 ,
847+ choices : [
848+ { title : 'Development' , value : 'development' } ,
849+ { title : 'Production' , value : 'production' }
850+ ]
851+ } ,
852+ {
853+ type : 'input' ,
854+ name : 'directory' ,
855+ message : 'Installation directory:' ,
856+ initial : options . directory || process . cwd ( ) ,
857+ validate : ( value ) => {
858+ if ( ! value ) {
859+ return 'Directory is required' ;
860+ }
861+ return true ;
862+ }
863+ }
864+ ] ) ;
865+
866+ const host = options . host || answers . host ;
867+ const environment = options . environment || answers . environment ;
868+ const directory = options . directory || answers . directory ;
869+
870+ // Determine configuration based on environment
871+ const useHttps = environment === 'production' ;
872+ const appDebug = environment === 'development' ;
873+ const scSecure = environment === 'production' ;
874+ const schemeApi = useHttps ? 'https' : 'http' ;
875+ const schemeConsole = useHttps ? 'https' : 'http' ;
876+
877+ console . log ( `\n📋 Configuration:` ) ;
878+ console . log ( ` Host: ${ host } ` ) ;
879+ console . log ( ` Environment: ${ environment } ` ) ;
880+ console . log ( ` Directory: ${ directory } ` ) ;
881+ console . log ( ` HTTPS: ${ useHttps } ` ) ;
882+
883+ // Check if directory exists and has Fleetbase files
884+ if ( ! await fs . pathExists ( directory ) ) {
885+ console . error ( `\n✖ Directory does not exist: ${ directory } ` ) ;
886+ console . log ( '\nℹ️ Please clone the Fleetbase repository first:' ) ;
887+ console . log ( ' git clone https://github.com/fleetbase/fleetbase.git' ) ;
888+ process . exit ( 1 ) ;
889+ }
890+
891+ const dockerComposePath = path . join ( directory , 'docker-compose.yml' ) ;
892+ if ( ! await fs . pathExists ( dockerComposePath ) ) {
893+ console . error ( `\n✖ docker-compose.yml not found in ${ directory } ` ) ;
894+ console . log ( '\nℹ️ Please ensure you are in the Fleetbase root directory.' ) ;
895+ process . exit ( 1 ) ;
896+ }
897+
898+ // Generate APP_KEY
899+ console . log ( '\n⏳ Generating APP_KEY...' ) ;
900+ const appKey = 'base64:' + crypto . randomBytes ( 32 ) . toString ( 'base64' ) ;
901+ console . log ( '✔ APP_KEY generated' ) ;
902+
903+ // Create docker-compose.override.yml
904+ console . log ( '⏳ Creating docker-compose.override.yml...' ) ;
905+ const overrideContent = `services:
906+ application:
907+ environment:
908+ APP_KEY: "${ appKey } "
909+ CONSOLE_HOST: "${ schemeConsole } ://${ host } :4200"
910+ ENVIRONMENT: "${ environment } "
911+ APP_DEBUG: "${ appDebug } "
912+ ` ;
913+ const overridePath = path . join ( directory , 'docker-compose.override.yml' ) ;
914+ await fs . writeFile ( overridePath , overrideContent ) ;
915+ console . log ( '✔ docker-compose.override.yml created' ) ;
916+
917+ // Create console/fleetbase.config.json (for development runtime config)
918+ console . log ( '⏳ Creating console/fleetbase.config.json...' ) ;
919+ const configDir = path . join ( directory , 'console' ) ;
920+ await fs . ensureDir ( configDir ) ;
921+ const configContent = {
922+ API_HOST : `${ schemeApi } ://${ host } :8000` ,
923+ SOCKETCLUSTER_HOST : host ,
924+ SOCKETCLUSTER_PORT : '38000' ,
925+ SOCKETCLUSTER_SECURE : scSecure
926+ } ;
927+ const configPath = path . join ( configDir , 'fleetbase.config.json' ) ;
928+ await fs . writeJson ( configPath , configContent , { spaces : 2 } ) ;
929+ console . log ( '✔ console/fleetbase.config.json created' ) ;
930+
931+ // Update console environment files (.env.development and .env.production)
932+ console . log ( '⏳ Updating console environment files...' ) ;
933+ const environmentsDir = path . join ( configDir , 'environments' ) ;
934+
935+ // Update .env.development
936+ const envDevelopmentContent = `API_HOST=http://${ host } :8000
937+ API_NAMESPACE=int/v1
938+ SOCKETCLUSTER_PATH=/socketcluster/
939+ SOCKETCLUSTER_HOST=${ host }
940+ SOCKETCLUSTER_SECURE=false
941+ SOCKETCLUSTER_PORT=38000
942+ OSRM_HOST=https://router.project-osrm.org
943+ ` ;
944+ const envDevelopmentPath = path . join ( environmentsDir , '.env.development' ) ;
945+ await fs . writeFile ( envDevelopmentPath , envDevelopmentContent ) ;
946+
947+ // Update .env.production
948+ const envProductionContent = `API_HOST=https://${ host } :8000
949+ API_NAMESPACE=int/v1
950+ API_SECURE=true
951+ SOCKETCLUSTER_PATH=/socketcluster/
952+ SOCKETCLUSTER_HOST=${ host }
953+ SOCKETCLUSTER_SECURE=true
954+ SOCKETCLUSTER_PORT=38000
955+ OSRM_HOST=https://router.project-osrm.org
956+ ` ;
957+ const envProductionPath = path . join ( environmentsDir , '.env.production' ) ;
958+ await fs . writeFile ( envProductionPath , envProductionContent ) ;
959+
960+ console . log ( '✔ Console environment files updated' ) ;
961+
962+ // Start Docker containers
963+ console . log ( '\n⏳ Starting Fleetbase containers...' ) ;
964+ console . log ( ' This may take a few minutes on first run...\n' ) ;
965+
966+ exec ( 'docker compose up -d' , { cwd : directory , maxBuffer : maxBuffer } , async ( error , stdout , stderr ) => {
967+ if ( error ) {
968+ console . error ( `\n✖ Error starting containers: ${ error . message } ` ) ;
969+ if ( stderr ) console . error ( stderr ) ;
970+ process . exit ( 1 ) ;
971+ }
972+
973+ console . log ( stdout ) ;
974+ console . log ( '✔ Containers started' ) ;
975+
976+ // Wait for database
977+ console . log ( '\n⏳ Waiting for database to be ready...' ) ;
978+ await new Promise ( resolve => setTimeout ( resolve , 15000 ) ) ; // Wait 15 seconds
979+ console . log ( '✔ Database should be ready' ) ;
980+
981+ // Run deploy script
982+ console . log ( '\n⏳ Running deployment script...' ) ;
983+ exec ( 'docker compose exec -T application bash -c "./deploy.sh"' , { cwd : directory , maxBuffer : maxBuffer } , ( deployError , deployStdout , deployStderr ) => {
984+ if ( deployError ) {
985+ console . error ( `\n✖ Error during deployment: ${ deployError . message } ` ) ;
986+ if ( deployStderr ) console . error ( deployStderr ) ;
987+ console . log ( '\nℹ️ You may need to run the deployment manually:' ) ;
988+ console . log ( ' docker compose exec application bash -c "./deploy.sh"' ) ;
989+ } else {
990+ console . log ( deployStdout ) ;
991+ console . log ( '✔ Deployment complete' ) ;
992+ }
993+
994+ // Restart containers to ensure all changes are applied
995+ exec ( 'docker compose up -d' , { cwd : directory } , ( ) => {
996+ console . log ( '\n🏁 Fleetbase is up!' ) ;
997+ console . log ( ` API → ${ schemeApi } ://${ host } :8000` ) ;
998+ console . log ( ` Console → ${ schemeConsole } ://${ host } :4200\n` ) ;
999+ console . log ( 'ℹ️ Default credentials:' ) ;
1000+ console . log ( ' Email: admin@fleetbase.io' ) ;
1001+ console . log ( ' Password: password\n' ) ;
1002+ } ) ;
1003+ } ) ;
1004+ } ) ;
1005+ } catch ( error ) {
1006+ console . error ( '\n✖ Installation failed:' , error . message ) ;
1007+ process . exit ( 1 ) ;
1008+ }
1009+ }
1010+
1011+
1012+
8201013function loginCommand ( options ) {
8211014 const npmLogin = require ( 'npm-cli-login' ) ;
8221015 const username = options . username ;
@@ -979,6 +1172,14 @@ program
9791172 . option ( '-n, --name <name>' , 'Your full name (optional)' )
9801173 . action ( registerCommand ) ;
9811174
1175+ program
1176+ . command ( 'install-fleetbase' )
1177+ . description ( 'Install Fleetbase using Docker' )
1178+ . option ( '--host <host>' , 'Host or IP address to bind to (default: localhost)' )
1179+ . option ( '--environment <environment>' , 'Environment: development or production (default: development)' )
1180+ . option ( '--directory <directory>' , 'Installation directory (default: current directory)' )
1181+ . action ( installFleetbaseCommand ) ;
1182+
9821183program
9831184 . command ( 'login' )
9841185 . description ( 'Log in to the Fleetbase registry' )
0 commit comments