mirror of
https://github.com/fleetbase/fleetbase.git
synced 2026-03-15 12:26:57 +00:00
Compare commits
205 Commits
feat/insta
...
cloud
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee83e5d232 | ||
|
|
14f9849d53 | ||
|
|
a8781e4ce8 | ||
|
|
f55462ee9c | ||
|
|
43f9914afa | ||
|
|
cbcf7a239b | ||
|
|
58686b9d77 | ||
|
|
979b451130 | ||
|
|
9d4b1167ab | ||
|
|
98cde6795a | ||
|
|
3a70c42054 | ||
|
|
becf73a83e | ||
|
|
f5c16ffe60 | ||
|
|
4b3d23c0b9 | ||
|
|
7ba7b62096 | ||
|
|
8d8c1d2253 | ||
|
|
0e4baa34e0 | ||
|
|
d6d078df62 | ||
|
|
7252a95805 | ||
|
|
7ba7821fed | ||
|
|
af3c60fc7c | ||
|
|
a372b515da | ||
|
|
f8b9c0415b | ||
|
|
b525ad4b1a | ||
|
|
b161b415d0 | ||
|
|
e444d7994c | ||
|
|
0e44375d32 | ||
|
|
a9bb2f0166 | ||
|
|
ac02a6b6e0 | ||
|
|
4a640561d6 | ||
|
|
5957bc6339 | ||
|
|
9b15a6856f | ||
|
|
0a4e5b31cc | ||
|
|
0d47ffc785 | ||
|
|
3f2c739810 | ||
|
|
6b2ab28ec9 | ||
|
|
42df48c9b0 | ||
|
|
268749fcd9 | ||
|
|
50ae560409 | ||
|
|
2e48024949 | ||
|
|
908f60aaac | ||
|
|
a1f2992f18 | ||
|
|
0252b387e2 | ||
|
|
12e1ec2cac | ||
|
|
5f2003eec5 | ||
|
|
e05d12dd87 | ||
|
|
86378d3ede | ||
|
|
1d36bf144b | ||
|
|
293f67d6d1 | ||
|
|
01e8298968 | ||
|
|
094d1d375e | ||
|
|
8a1dee0cbd | ||
|
|
df2da8cea1 | ||
|
|
ced5e6b6fd | ||
|
|
de2cbd2ded | ||
|
|
894f4348dd | ||
|
|
2030a72a71 | ||
|
|
41d20c41c5 | ||
|
|
9976075843 | ||
|
|
b26f735fee | ||
|
|
791cc7283d | ||
|
|
21601737a1 | ||
|
|
0cd9e076b8 | ||
|
|
5fe799b708 | ||
|
|
878a70d328 | ||
|
|
4c5487b6bb | ||
|
|
599fd0e8f7 | ||
|
|
64561c85a8 | ||
|
|
c8d8be11d2 | ||
|
|
12847437b0 | ||
|
|
53eadee8a6 | ||
|
|
657de6c99d | ||
|
|
db601606c5 | ||
|
|
6ec176011a | ||
|
|
d416baf3cc | ||
|
|
d80b968eaa | ||
|
|
eef6847919 | ||
|
|
2ad569eaf6 | ||
|
|
dc18b48f6a | ||
|
|
3e93e161dc | ||
|
|
fac29308fd | ||
|
|
7b62e992eb | ||
|
|
18af3b4515 | ||
|
|
264c564ad6 | ||
|
|
dbf9a37ae9 | ||
|
|
46c4ac9dda | ||
|
|
e692bc3365 | ||
|
|
0b807011a3 | ||
|
|
80d84e1c3b | ||
|
|
08c722359a | ||
|
|
ebd9b0d8cb | ||
|
|
ec5ace214c | ||
|
|
396e0cbf36 | ||
|
|
3faac3481f | ||
|
|
36f837a4af | ||
|
|
094bd6c8ce | ||
|
|
aea35f6f5f | ||
|
|
96fa0294bc | ||
|
|
72ed388cd6 | ||
|
|
5a79a06642 | ||
|
|
010a6b0d05 | ||
|
|
6d138761ee | ||
|
|
1f59d8831b | ||
|
|
746b2142f0 | ||
|
|
343e07e24d | ||
|
|
d6094b8e29 | ||
|
|
59d7fa3de9 | ||
|
|
14c05a6c6a | ||
|
|
5c12254a58 | ||
|
|
65416833ca | ||
|
|
40e0de6e6b | ||
|
|
5986ced2c0 | ||
|
|
ca260bb94c | ||
|
|
95ef8ef3c9 | ||
|
|
df8513cf7b | ||
|
|
e2c544b0c9 | ||
|
|
77b39fccf9 | ||
|
|
eaa448f762 | ||
|
|
627522d61c | ||
|
|
201ac84dc9 | ||
|
|
78b1f31053 | ||
|
|
63cf8128c0 | ||
|
|
5d66c7a35f | ||
|
|
0603888393 | ||
|
|
cd50d349f8 | ||
|
|
e478767a60 | ||
|
|
17cb0cd274 | ||
|
|
a3289ddd41 | ||
|
|
ff8986541c | ||
|
|
04d0c126de | ||
|
|
ad43f74d5c | ||
|
|
3c013a3817 | ||
|
|
4392c7e3ff | ||
|
|
97dfbedd1a | ||
|
|
6d13f22a98 | ||
|
|
2c09c87bb6 | ||
|
|
f7f6991ef3 | ||
|
|
73acd4833c | ||
|
|
1c3c4c16a5 | ||
|
|
5d01438dc9 | ||
|
|
9d004410ee | ||
|
|
3a396f3b54 | ||
|
|
e86b970fc8 | ||
|
|
122a0d186a | ||
|
|
7e258f698f | ||
|
|
65ef642315 | ||
|
|
d79f034dbd | ||
|
|
05b7d5e112 | ||
|
|
61779ab102 | ||
|
|
a287c05380 | ||
|
|
ecc41e587e | ||
|
|
166529f9b4 | ||
|
|
189547f9de | ||
|
|
90a42e8a93 | ||
|
|
d28b1d41fb | ||
|
|
b056ef62b0 | ||
|
|
e70cbacbc2 | ||
|
|
fbd4a7490a | ||
|
|
b9b0eb308b | ||
|
|
48e1b89ec8 | ||
|
|
5e02c95b66 | ||
|
|
db8b5c4d6a | ||
|
|
aa214ccad7 | ||
|
|
cdd5524cf3 | ||
|
|
d99cefd2a4 | ||
|
|
1c58fd43c3 | ||
|
|
9226394159 | ||
|
|
9b23b39f32 | ||
|
|
5310fc3ff3 | ||
|
|
9569053f50 | ||
|
|
b08c054b99 | ||
|
|
2e517f2f95 | ||
|
|
7038d375b0 | ||
|
|
d5ea7f7790 | ||
|
|
4eb4b04121 | ||
|
|
24c5b93005 | ||
|
|
80610b9a48 | ||
|
|
9e5551972e | ||
|
|
b784f890f3 | ||
|
|
797a3d61fe | ||
|
|
d2f0bfe83e | ||
|
|
f28ad85c1a | ||
|
|
d7b0826f3f | ||
|
|
dd6008a8aa | ||
|
|
6671fefaaa | ||
|
|
7136f6195c | ||
|
|
2384887620 | ||
|
|
a2778f1552 | ||
|
|
acfda5ed1a | ||
|
|
e08255007a | ||
|
|
41761ea50e | ||
|
|
5c623819ed | ||
|
|
2bd885b1a2 | ||
|
|
88c3842441 | ||
|
|
2c2a4121a8 | ||
|
|
aadd03f14b | ||
|
|
706e94270d | ||
|
|
1dabc375f9 | ||
|
|
0efec46155 | ||
|
|
8bb2c6b65d | ||
|
|
1c0af1a119 | ||
|
|
dd65ee619b | ||
|
|
e790a0e123 | ||
|
|
723e3ca3d1 | ||
|
|
4eb706d33e |
4
.github/workflows/cd.yml
vendored
4
.github/workflows/cd.yml
vendored
@@ -240,10 +240,6 @@ jobs:
|
||||
set -u
|
||||
|
||||
DEPLOY_BUCKET=${STATIC_DEPLOY_BUCKET:-${{ env.PROJECT }}-${{ env.STACK }}}
|
||||
NEW_BUCKET="${PROJECT}-${STACK}-console"
|
||||
if aws s3api head-bucket --bucket "$NEW_BUCKET" 2>/dev/null; then
|
||||
DEPLOY_BUCKET="$NEW_BUCKET"
|
||||
fi
|
||||
|
||||
# this value will come from the dotenv above
|
||||
echo "Deploying to $DEPLOY_BUCKET"
|
||||
|
||||
@@ -24,6 +24,15 @@
|
||||
"fleetbase/fleetops-api": "^0.6.37",
|
||||
"fleetbase/registry-bridge": "^0.1.7",
|
||||
"fleetbase/storefront-api": "^0.4.13",
|
||||
"fleetbase/aws-marketplace": "^0.0.8",
|
||||
"fleetbase/billing-api": "^0.1.20",
|
||||
"fleetbase/customer-portal-api": "^0.0.10",
|
||||
"fleetbase/flespi-integration": "^0.1.16",
|
||||
"fleetbase/internals-api": "^0.0.28",
|
||||
"fleetbase/samsara-api": "^0.0.3",
|
||||
"fleetbase/solid-api": "^0.0.7",
|
||||
"fleetbase/valhalla-api": "^0.0.3",
|
||||
"fleetbase/vroom-api": "^0.0.3",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"laravel/framework": "^10.0",
|
||||
"laravel/octane": "^2.3",
|
||||
@@ -52,6 +61,14 @@
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "https://registry.fleetbase.io"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/fleetbase/aws-marketplace"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/fleetbase/internals"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
|
||||
1483
api/composer.lock
generated
1483
api/composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
||||
API_HOST=
|
||||
API_HOST=https://api.fleetbase.io
|
||||
API_NAMESPACE=int/v1
|
||||
API_SECURE=true
|
||||
SOCKETCLUSTER_PATH=/socketcluster/
|
||||
SOCKETCLUSTER_HOST=
|
||||
SOCKETCLUSTER_HOST=socket.fleetbase.io
|
||||
SOCKETCLUSTER_SECURE=true
|
||||
SOCKETCLUSTER_PORT=38000
|
||||
OSRM_HOST=https://router.project-osrm.org
|
||||
SOCKETCLUSTER_PORT=8000
|
||||
OSRM_HOST=https://router.project-osrm.org
|
||||
DISABLE_RUNTIME_CONFIG=true
|
||||
9
console/environments/.env.qa
Normal file
9
console/environments/.env.qa
Normal file
@@ -0,0 +1,9 @@
|
||||
API_HOST=https://api.qa.fleetbase.io
|
||||
API_NAMESPACE=int/v1
|
||||
API_SECURE=true
|
||||
SOCKETCLUSTER_PATH=/socketcluster/
|
||||
SOCKETCLUSTER_HOST=socket.qa.fleetbase.io
|
||||
SOCKETCLUSTER_SECURE=true
|
||||
SOCKETCLUSTER_PORT=8000
|
||||
OSRM_HOST=https://router.project-osrm.org
|
||||
DISABLE_RUNTIME_CONFIG=true
|
||||
@@ -33,15 +33,24 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ember/legacy-built-in-components": "^0.4.2",
|
||||
"@fleetbase/aws-marketplace": "^0.0.8",
|
||||
"@fleetbase/billing-engine": "^0.1.20",
|
||||
"@fleetbase/customer-portal-engine": "^0.0.10",
|
||||
"@fleetbase/dev-engine": "^0.2.12",
|
||||
"@fleetbase/ember-core": "^0.3.12",
|
||||
"@fleetbase/ember-ui": "^0.3.21",
|
||||
"@fleetbase/fleetops-data": "^0.1.25",
|
||||
"@fleetbase/fleetops-engine": "^0.6.37",
|
||||
"@fleetbase/iam-engine": "^0.1.7",
|
||||
"@fleetbase/flespi-engine": "^0.1.16",
|
||||
"@fleetbase/internals-engine": "^0.0.28",
|
||||
"@fleetbase/leaflet-routing-machine": "^3.2.17",
|
||||
"@fleetbase/registry-bridge-engine": "^0.1.7",
|
||||
"@fleetbase/samsara-engine": "^0.0.3",
|
||||
"@fleetbase/solid-engine": "^0.0.7",
|
||||
"@fleetbase/storefront-engine": "^0.4.13",
|
||||
"@fleetbase/valhalla-engine": "^0.0.3",
|
||||
"@fleetbase/vroom-engine": "^0.0.3",
|
||||
"@formatjs/intl-datetimeformat": "^6.18.2",
|
||||
"@formatjs/intl-numberformat": "^8.15.6",
|
||||
"@formatjs/intl-pluralrules": "^5.4.6",
|
||||
|
||||
1753
console/pnpm-lock.yaml
generated
1753
console/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Submodule packages/core-api updated: f6500fb4bd...04ae1ac455
Submodule packages/dev-engine updated: f11d032cb8...64a379ce12
Submodule packages/ember-core updated: 6bcd9d71ad...54a45bbdaa
Submodule packages/ember-ui updated: 3a15f3ddda...c6694206e9
Submodule packages/fleetbase-extensions-indexer updated: db26b8add3...a6f2b4cde9
Submodule packages/fleetops updated: 071a0f06fb...09487c1c50
Submodule packages/fleetops-data updated: 332dc428de...08520b3981
Submodule packages/iam-engine updated: 1a65d083c7...99698152e2
Submodule packages/pallet updated: b343c621f1...9e7592eddb
Submodule packages/storefront updated: aa2a2bc0bd...b5776acef6
@@ -1,562 +1,200 @@
|
||||
#!/usr/bin/env bash
|
||||
# scripts/docker-install.sh
|
||||
# Fleetbase Docker installer — interactive setup wizard
|
||||
# -------------------------------------------------------
|
||||
# Usage:
|
||||
# bash scripts/docker-install.sh # interactive (default)
|
||||
# bash scripts/docker-install.sh --non-interactive # CI/CD, all defaults
|
||||
# -------------------------------------------------------
|
||||
# Fleetbase Docker installer (dev / prod aware)
|
||||
# --------------------------------------------
|
||||
set -euo pipefail
|
||||
|
||||
# ─── Colour helpers ──────────────────────────────────────────────────────────
|
||||
RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'
|
||||
CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
|
||||
info() { echo -e "${CYAN}ℹ ${RESET}$*"; }
|
||||
success() { echo -e "${GREEN}✔ ${RESET}$*"; }
|
||||
warn() { echo -e "${YELLOW}⚠ ${RESET}$*"; }
|
||||
error() { echo -e "${RED}✖ ${RESET}$*" >&2; }
|
||||
section() { echo -e "\n${BOLD}── $* $(printf '─%.0s' {1..40})${RESET}"; }
|
||||
###############################################################################
|
||||
# 1. Ask for host (default: localhost)
|
||||
###############################################################################
|
||||
read -rp "Enter host or IP address to bind to [localhost]: " HOST_INPUT
|
||||
HOST=${HOST_INPUT:-localhost}
|
||||
echo "➜ Using host: $HOST"
|
||||
|
||||
# ─── Non-interactive flag ────────────────────────────────────────────────────
|
||||
NON_INTERACTIVE=false
|
||||
for arg in "$@"; do
|
||||
[[ "$arg" == "--non-interactive" ]] && NON_INTERACTIVE=true
|
||||
###############################################################################
|
||||
# 2. Ask for environment (development | production)
|
||||
###############################################################################
|
||||
while true; do
|
||||
read -rp "Choose environment (development / production) [development]: " ENV_INPUT
|
||||
ENV_INPUT=$(echo "$ENV_INPUT" | tr '[:upper:]' '[:lower:]')
|
||||
case "$ENV_INPUT" in
|
||||
""|d|dev|development) ENVIRONMENT=development; break ;;
|
||||
p|prod|production) ENVIRONMENT=production; break ;;
|
||||
*) echo "Please type either 'development' or 'production'." ;;
|
||||
esac
|
||||
done
|
||||
$NON_INTERACTIVE && info "Non-interactive mode: all optional steps will use safe defaults."
|
||||
echo "➜ Environment: $ENVIRONMENT"
|
||||
|
||||
# ─── Helper: generate a random hex secret ────────────────────────────────────
|
||||
gen_secret() { openssl rand -hex "${1:-20}"; }
|
||||
|
||||
# ─── Helper: append a non-empty env var line to the override builder ─────────
|
||||
# Usage: env_line VAR_NAME "value" → echoes ' VAR_NAME: "value"' if non-empty
|
||||
env_line() {
|
||||
local key="$1" val="$2"
|
||||
[[ -z "$val" ]] && return
|
||||
printf ' %s: "%s"\n' "$key" "$val"
|
||||
}
|
||||
|
||||
echo
|
||||
echo -e "${BOLD}🚀 Fleetbase Installation Wizard${RESET}"
|
||||
echo
|
||||
|
||||
###############################################################################
|
||||
# STEP 0 — Pre-flight checks
|
||||
###############################################################################
|
||||
section "Pre-flight Checks"
|
||||
|
||||
# Required tools
|
||||
for tool in docker git openssl; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
error "$tool is required but not found. Install it and retry."
|
||||
exit 1
|
||||
fi
|
||||
success "$tool found"
|
||||
done
|
||||
|
||||
# Docker Compose v2
|
||||
if ! docker compose version >/dev/null 2>&1; then
|
||||
error "'docker compose' (v2) is required. Please upgrade Docker Desktop or install the Compose plugin."
|
||||
exit 1
|
||||
fi
|
||||
success "Docker Compose v2 found"
|
||||
|
||||
# Port availability (warn only — do not block)
|
||||
for port_label in "8000:API" "4200:Console" "3306:MySQL" "38000:SocketCluster"; do
|
||||
port="${port_label%%:*}"
|
||||
label="${port_label##*:}"
|
||||
if ss -tlnp 2>/dev/null | grep -q ":${port} " || \
|
||||
netstat -tlnp 2>/dev/null | grep -q ":${port} "; then
|
||||
warn "Port ${port} (${label}) is already in use — this may cause a conflict."
|
||||
else
|
||||
success "Port ${port} (${label}) is free"
|
||||
fi
|
||||
done
|
||||
|
||||
success "Pre-flight checks complete"
|
||||
|
||||
###############################################################################
|
||||
# STEP 1 — Core parameters
|
||||
###############################################################################
|
||||
section "Core Configuration"
|
||||
|
||||
if $NON_INTERACTIVE; then
|
||||
HOST="localhost"
|
||||
ENVIRONMENT="development"
|
||||
APP_NAME="Fleetbase"
|
||||
else
|
||||
read -rp "Host or IP address to bind to [localhost]: " HOST_INPUT
|
||||
HOST="${HOST_INPUT:-localhost}"
|
||||
|
||||
while true; do
|
||||
read -rp "Environment (development / production) [development]: " ENV_INPUT
|
||||
ENV_INPUT=$(echo "$ENV_INPUT" | tr '[:upper:]' '[:lower:]')
|
||||
case "$ENV_INPUT" in
|
||||
""|d|dev|development) ENVIRONMENT=development; break ;;
|
||||
p|prod|production) ENVIRONMENT=production; break ;;
|
||||
*) warn "Please type either 'development' or 'production'." ;;
|
||||
esac
|
||||
done
|
||||
|
||||
read -rp "Application name [Fleetbase]: " APP_NAME_INPUT
|
||||
APP_NAME="${APP_NAME_INPUT:-Fleetbase}"
|
||||
USE_HTTPS=false
|
||||
APP_DEBUG=true
|
||||
SC_SECURE=false
|
||||
if [[ "$ENVIRONMENT" == "production" ]]; then
|
||||
USE_HTTPS=true
|
||||
APP_DEBUG=false
|
||||
SC_SECURE=true
|
||||
fi
|
||||
|
||||
# Derive scheme flags
|
||||
USE_HTTPS=false; APP_DEBUG=true; SC_SECURE=false
|
||||
[[ "$ENVIRONMENT" == "production" ]] && { USE_HTTPS=true; APP_DEBUG=false; SC_SECURE=true; }
|
||||
SCHEME_API=$([[ "$USE_HTTPS" == true ]] && echo "https" || echo "http")
|
||||
SCHEME_CONSOLE=$([[ "$USE_HTTPS" == true ]] && echo "https" || echo "http")
|
||||
|
||||
# Detect localhost
|
||||
IS_LOCALHOST=false
|
||||
[[ "$HOST" == "localhost" || "$HOST" == "0.0.0.0" || "$HOST" == "127.0.0.1" ]] && IS_LOCALHOST=true
|
||||
|
||||
info "Host: $HOST | Environment: $ENVIRONMENT | App name: $APP_NAME"
|
||||
|
||||
###############################################################################
|
||||
# STEP 2 — Locate project root
|
||||
# 3. Determine project root no matter where script is called from
|
||||
###############################################################################
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PROJECT_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
###############################################################################
|
||||
# STEP 3 — Database configuration
|
||||
# 4. Generate a fresh Laravel APP_KEY
|
||||
###############################################################################
|
||||
section "Database Configuration"
|
||||
|
||||
DB_MODE="internal" # default
|
||||
|
||||
if ! $NON_INTERACTIVE; then
|
||||
echo " 1) Bundled Docker MySQL (recommended for development)"
|
||||
echo " 2) External MySQL server (e.g. AWS RDS, PlanetScale)"
|
||||
read -rp "Choose [1]: " DB_CHOICE_INPUT
|
||||
[[ "${DB_CHOICE_INPUT:-1}" == "2" ]] && DB_MODE="external"
|
||||
if ! command -v openssl >/dev/null 2>&1; then
|
||||
echo "✖ openssl is required but not found. Install it and retry." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$DB_MODE" == "external" ]]; then
|
||||
read -rp " Database host [127.0.0.1]: " DB_HOST_INPUT; DB_HOST="${DB_HOST_INPUT:-127.0.0.1}"
|
||||
read -rp " Database port [3306]: " DB_PORT_INPUT; DB_PORT="${DB_PORT_INPUT:-3306}"
|
||||
read -rp " Database name [fleetbase]: " DB_NAME_INPUT; DB_NAME="${DB_NAME_INPUT:-fleetbase}"
|
||||
read -rp " Database username: " DB_USER
|
||||
read -srp " Database password: " DB_PASS; echo
|
||||
# URL-encode the password (basic: replace @ and / which are most problematic)
|
||||
DB_PASS_ENC=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1],safe=''))" "$DB_PASS" 2>/dev/null || echo "$DB_PASS")
|
||||
DATABASE_URL="mysql://${DB_USER}:${DB_PASS_ENC}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
||||
DB_ROOT_PASSWORD=""
|
||||
DB_USERNAME="$DB_USER"
|
||||
DB_PASSWORD="$DB_PASS"
|
||||
DB_DATABASE="$DB_NAME"
|
||||
success "External database configured"
|
||||
else
|
||||
DB_ROOT_PASSWORD="$(gen_secret 20)"
|
||||
DB_PASSWORD="$(gen_secret 20)"
|
||||
DB_USERNAME="fleetbase"
|
||||
DB_DATABASE="fleetbase"
|
||||
DATABASE_URL="mysql://${DB_USERNAME}:${DB_PASSWORD}@database/${DB_DATABASE}"
|
||||
success "Secure database credentials auto-generated"
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# STEP 4 — Mail configuration
|
||||
###############################################################################
|
||||
section "Mail Configuration"
|
||||
|
||||
MAIL_MAILER="log"
|
||||
MAIL_HOST=""; MAIL_PORT=""; MAIL_USERNAME=""; MAIL_PASSWORD=""
|
||||
MAIL_FROM_ADDRESS=""; MAIL_FROM_NAME="$APP_NAME"
|
||||
MAILGUN_DOMAIN=""; MAILGUN_SECRET=""
|
||||
POSTMARK_TOKEN=""; SENDGRID_API_KEY=""; RESEND_KEY=""
|
||||
|
||||
CONFIG_MAIL=false
|
||||
if ! $NON_INTERACTIVE; then
|
||||
read -rp "Configure a mail server? Required for password resets & notifications (y/N): " MAIL_YN
|
||||
[[ "${MAIL_YN,,}" == "y" || "${MAIL_YN,,}" == "yes" ]] && CONFIG_MAIL=true
|
||||
fi
|
||||
|
||||
if $CONFIG_MAIL; then
|
||||
echo " Mail drivers: 1) SMTP 2) Mailgun 3) Postmark 4) SendGrid 5) Resend 6) AWS SES 7) Log only"
|
||||
read -rp " Choose driver [1]: " MAIL_DRIVER_INPUT
|
||||
case "${MAIL_DRIVER_INPUT:-1}" in
|
||||
2) MAIL_MAILER="mailgun" ;;
|
||||
3) MAIL_MAILER="postmark" ;;
|
||||
4) MAIL_MAILER="sendgrid" ;;
|
||||
5) MAIL_MAILER="resend" ;;
|
||||
6) MAIL_MAILER="ses" ;;
|
||||
7) MAIL_MAILER="log" ;;
|
||||
*) MAIL_MAILER="smtp" ;;
|
||||
esac
|
||||
|
||||
DEFAULT_FROM="hello@$( $IS_LOCALHOST && echo 'example.com' || echo "$HOST" )"
|
||||
read -rp " From address [$DEFAULT_FROM]: " MAIL_FROM_INPUT
|
||||
MAIL_FROM_ADDRESS="${MAIL_FROM_INPUT:-$DEFAULT_FROM}"
|
||||
read -rp " From name [$APP_NAME]: " MAIL_FROM_NAME_INPUT
|
||||
MAIL_FROM_NAME="${MAIL_FROM_NAME_INPUT:-$APP_NAME}"
|
||||
|
||||
case "$MAIL_MAILER" in
|
||||
smtp)
|
||||
read -rp " SMTP host [smtp.mailgun.org]: " MAIL_HOST_INPUT; MAIL_HOST="${MAIL_HOST_INPUT:-smtp.mailgun.org}"
|
||||
read -rp " SMTP port [587]: " MAIL_PORT_INPUT; MAIL_PORT="${MAIL_PORT_INPUT:-587}"
|
||||
read -rp " SMTP username: " MAIL_USERNAME
|
||||
read -srp " SMTP password: " MAIL_PASSWORD; echo
|
||||
;;
|
||||
mailgun)
|
||||
read -rp " Mailgun domain: " MAILGUN_DOMAIN
|
||||
read -srp " Mailgun API secret: " MAILGUN_SECRET; echo
|
||||
;;
|
||||
postmark)
|
||||
read -srp " Postmark server token: " POSTMARK_TOKEN; echo
|
||||
;;
|
||||
sendgrid)
|
||||
read -srp " SendGrid API key: " SENDGRID_API_KEY; echo
|
||||
;;
|
||||
resend)
|
||||
read -srp " Resend API key: " RESEND_KEY; echo
|
||||
;;
|
||||
ses)
|
||||
info "AWS SES will use the AWS credentials configured in the Storage step."
|
||||
;;
|
||||
esac
|
||||
success "Mail driver set to: $MAIL_MAILER"
|
||||
else
|
||||
info "Skipped — emails will be written to the application log."
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# STEP 5 — File storage
|
||||
###############################################################################
|
||||
section "File Storage Configuration"
|
||||
|
||||
FILESYSTEM_DRIVER="public"
|
||||
AWS_ACCESS_KEY_ID=""; AWS_SECRET_ACCESS_KEY=""; AWS_DEFAULT_REGION=""
|
||||
AWS_BUCKET=""; AWS_URL=""; AWS_USE_PATH_STYLE_ENDPOINT=""
|
||||
GOOGLE_CLOUD_PROJECT_ID=""; GOOGLE_CLOUD_STORAGE_BUCKET=""; GOOGLE_CLOUD_KEY_FILE=""
|
||||
|
||||
if ! $NON_INTERACTIVE; then
|
||||
echo " Storage drivers: 1) Local disk (dev only) 2) AWS S3 3) Google Cloud Storage"
|
||||
read -rp " Choose driver [1]: " STORAGE_INPUT
|
||||
case "${STORAGE_INPUT:-1}" in
|
||||
2) FILESYSTEM_DRIVER="s3" ;;
|
||||
3) FILESYSTEM_DRIVER="gcs" ;;
|
||||
*) FILESYSTEM_DRIVER="public" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [[ "$FILESYSTEM_DRIVER" == "s3" ]]; then
|
||||
read -rp " AWS Access Key ID: " AWS_ACCESS_KEY_ID
|
||||
read -srp " AWS Secret Access Key: " AWS_SECRET_ACCESS_KEY; echo
|
||||
read -rp " AWS Region [us-east-1]: " AWS_REGION_INPUT; AWS_DEFAULT_REGION="${AWS_REGION_INPUT:-us-east-1}"
|
||||
read -rp " S3 Bucket name: " AWS_BUCKET
|
||||
read -rp " S3 Public URL (leave blank for default): " AWS_URL
|
||||
read -rp " Use path-style endpoint? (for MinIO/non-AWS S3) (y/N): " PATH_STYLE_INPUT
|
||||
[[ "${PATH_STYLE_INPUT,,}" == "y" ]] && AWS_USE_PATH_STYLE_ENDPOINT="true"
|
||||
success "S3 storage configured"
|
||||
elif [[ "$FILESYSTEM_DRIVER" == "gcs" ]]; then
|
||||
read -rp " GCS Project ID: " GOOGLE_CLOUD_PROJECT_ID
|
||||
read -rp " GCS Bucket name: " GOOGLE_CLOUD_STORAGE_BUCKET
|
||||
read -rp " Path to GCS key file (JSON): " GOOGLE_CLOUD_KEY_FILE
|
||||
success "Google Cloud Storage configured"
|
||||
else
|
||||
info "Local disk selected — suitable for development only."
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# STEP 6 — Security & CORS
|
||||
###############################################################################
|
||||
section "Security & CORS Configuration"
|
||||
|
||||
# Derive SESSION_DOMAIN
|
||||
SESSION_DOMAIN="$( $IS_LOCALHOST && echo 'localhost' || echo "$HOST" )"
|
||||
|
||||
# Derive SOCKETCLUSTER_OPTIONS origins
|
||||
if $IS_LOCALHOST; then
|
||||
SOCKET_ORIGINS="http://localhost:*,https://localhost:*,ws://localhost:*,wss://localhost:*"
|
||||
else
|
||||
SOCKET_ORIGINS="${SCHEME_CONSOLE}://${HOST}:*,wss://${HOST}:*"
|
||||
fi
|
||||
SOCKETCLUSTER_OPTIONS="{\"origins\":\"${SOCKET_ORIGINS}\"}"
|
||||
|
||||
success "SESSION_DOMAIN set to: $SESSION_DOMAIN"
|
||||
success "WebSocket origins restricted to: $SOCKET_ORIGINS"
|
||||
|
||||
FRONTEND_HOSTS=""
|
||||
if ! $NON_INTERACTIVE; then
|
||||
read -rp "Additional frontend hosts for CORS (comma-separated, leave blank for none): " FRONTEND_HOSTS
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# STEP 7 — Optional third-party API keys
|
||||
###############################################################################
|
||||
section "Optional Third-Party Services"
|
||||
|
||||
IPINFO_API_KEY=""; GOOGLE_MAPS_API_KEY=""; GOOGLE_MAPS_LOCALE="us"
|
||||
TWILIO_SID=""; TWILIO_TOKEN=""; TWILIO_FROM=""
|
||||
|
||||
CONFIG_3P=false
|
||||
if ! $NON_INTERACTIVE; then
|
||||
read -rp "Configure optional third-party API keys now? (Maps, Geolocation, SMS) (y/N): " TP_YN
|
||||
[[ "${TP_YN,,}" == "y" || "${TP_YN,,}" == "yes" ]] && CONFIG_3P=true
|
||||
fi
|
||||
|
||||
if $CONFIG_3P; then
|
||||
read -rp " IPInfo API key (geolocation, leave blank to skip): " IPINFO_API_KEY
|
||||
read -rp " Google Maps API key (leave blank to skip): " GOOGLE_MAPS_API_KEY
|
||||
read -rp " Google Maps locale [us]: " GM_LOCALE_INPUT; GOOGLE_MAPS_LOCALE="${GM_LOCALE_INPUT:-us}"
|
||||
read -rp " Twilio Account SID (SMS, leave blank to skip): " TWILIO_SID
|
||||
read -srp " Twilio Auth Token: " TWILIO_TOKEN; echo
|
||||
read -rp " Twilio From phone number: " TWILIO_FROM
|
||||
success "Third-party services configured"
|
||||
else
|
||||
info "Skipped — these can be added later via docker-compose.override.yml"
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# STEP 8 — Generate APP_KEY
|
||||
###############################################################################
|
||||
section "Generating Application Key"
|
||||
APP_KEY="base64:$(openssl rand -base64 32 | tr -d '\n')"
|
||||
success "APP_KEY generated"
|
||||
echo "✔ Generated APP_KEY"
|
||||
|
||||
###############################################################################
|
||||
# STEP 9 — Write docker-compose.override.yml
|
||||
# 5. Ensure docker‑compose.override.yml is present & updated
|
||||
###############################################################################
|
||||
section "Writing docker-compose.override.yml"
|
||||
|
||||
OVERRIDE_FILE="docker-compose.override.yml"
|
||||
|
||||
# Back up any existing override
|
||||
if [[ -f "$OVERRIDE_FILE" ]]; then
|
||||
BACKUP="${OVERRIDE_FILE}.bak.$(date +%Y%m%d%H%M%S)"
|
||||
cp "$OVERRIDE_FILE" "$BACKUP"
|
||||
info "Existing override backed up to $BACKUP"
|
||||
fi
|
||||
# url helpers
|
||||
SCHEME_API=$([[ "$USE_HTTPS" == true ]] && echo "https" || echo "http")
|
||||
SCHEME_CONSOLE=$([[ "$USE_HTTPS" == true ]] && echo "https" || echo "http")
|
||||
|
||||
# Build the file using a temp file for atomicity
|
||||
OVERRIDE_TMP="${OVERRIDE_FILE}.tmp.$$"
|
||||
update_override_with_yq() {
|
||||
yq -i "
|
||||
.services.application.environment.APP_KEY = \"$APP_KEY\" |
|
||||
.services.application.environment.CONSOLE_HOST = \"$SCHEME_CONSOLE://$HOST:4200\" |
|
||||
.services.application.environment.ENVIRONMENT = \"$ENVIRONMENT\" |
|
||||
.services.application.environment.APP_DEBUG = \"$APP_DEBUG\"
|
||||
" "$OVERRIDE_FILE"
|
||||
echo "✔ $OVERRIDE_FILE updated (yq)"
|
||||
}
|
||||
|
||||
{
|
||||
cat <<YAML_HEADER
|
||||
create_override() {
|
||||
cat > "$OVERRIDE_FILE" <<YML
|
||||
services:
|
||||
application:
|
||||
environment:
|
||||
YAML_HEADER
|
||||
APP_KEY: "$APP_KEY"
|
||||
CONSOLE_HOST: "$SCHEME_CONSOLE://$HOST:4200"
|
||||
ENVIRONMENT: "$ENVIRONMENT"
|
||||
APP_DEBUG: "$APP_DEBUG"
|
||||
YML
|
||||
echo "✔ $OVERRIDE_FILE written"
|
||||
}
|
||||
|
||||
env_line "APP_KEY" "$APP_KEY"
|
||||
env_line "APP_NAME" "$APP_NAME"
|
||||
env_line "APP_URL" "${SCHEME_API}://${HOST}:8000"
|
||||
env_line "CONSOLE_HOST" "${SCHEME_CONSOLE}://${HOST}:4200"
|
||||
env_line "ENVIRONMENT" "$ENVIRONMENT"
|
||||
env_line "APP_DEBUG" "$APP_DEBUG"
|
||||
env_line "DATABASE_URL" "$DATABASE_URL"
|
||||
env_line "SESSION_DOMAIN" "$SESSION_DOMAIN"
|
||||
env_line "FRONTEND_HOSTS" "$FRONTEND_HOSTS"
|
||||
# Mail
|
||||
env_line "MAIL_MAILER" "$MAIL_MAILER"
|
||||
env_line "MAIL_HOST" "$MAIL_HOST"
|
||||
env_line "MAIL_PORT" "$MAIL_PORT"
|
||||
env_line "MAIL_USERNAME" "$MAIL_USERNAME"
|
||||
env_line "MAIL_PASSWORD" "$MAIL_PASSWORD"
|
||||
env_line "MAIL_FROM_ADDRESS" "$MAIL_FROM_ADDRESS"
|
||||
env_line "MAIL_FROM_NAME" "$MAIL_FROM_NAME"
|
||||
env_line "MAILGUN_DOMAIN" "$MAILGUN_DOMAIN"
|
||||
env_line "MAILGUN_SECRET" "$MAILGUN_SECRET"
|
||||
env_line "POSTMARK_TOKEN" "$POSTMARK_TOKEN"
|
||||
env_line "SENDGRID_API_KEY" "$SENDGRID_API_KEY"
|
||||
env_line "RESEND_KEY" "$RESEND_KEY"
|
||||
# Storage
|
||||
[[ "$FILESYSTEM_DRIVER" != "public" ]] && env_line "FILESYSTEM_DRIVER" "$FILESYSTEM_DRIVER"
|
||||
env_line "AWS_ACCESS_KEY_ID" "$AWS_ACCESS_KEY_ID"
|
||||
env_line "AWS_SECRET_ACCESS_KEY" "$AWS_SECRET_ACCESS_KEY"
|
||||
env_line "AWS_DEFAULT_REGION" "$AWS_DEFAULT_REGION"
|
||||
env_line "AWS_BUCKET" "$AWS_BUCKET"
|
||||
env_line "AWS_URL" "$AWS_URL"
|
||||
env_line "AWS_USE_PATH_STYLE_ENDPOINT" "$AWS_USE_PATH_STYLE_ENDPOINT"
|
||||
env_line "GOOGLE_CLOUD_PROJECT_ID" "$GOOGLE_CLOUD_PROJECT_ID"
|
||||
env_line "GOOGLE_CLOUD_STORAGE_BUCKET" "$GOOGLE_CLOUD_STORAGE_BUCKET"
|
||||
env_line "GOOGLE_CLOUD_KEY_FILE" "$GOOGLE_CLOUD_KEY_FILE"
|
||||
# Third-party
|
||||
env_line "IPINFO_API_KEY" "$IPINFO_API_KEY"
|
||||
env_line "GOOGLE_MAPS_API_KEY" "$GOOGLE_MAPS_API_KEY"
|
||||
env_line "GOOGLE_MAPS_LOCALE" "$GOOGLE_MAPS_LOCALE"
|
||||
env_line "TWILIO_SID" "$TWILIO_SID"
|
||||
env_line "TWILIO_TOKEN" "$TWILIO_TOKEN"
|
||||
env_line "TWILIO_FROM" "$TWILIO_FROM"
|
||||
|
||||
cat <<YAML_SOCKET
|
||||
|
||||
socket:
|
||||
environment:
|
||||
SOCKETCLUSTER_OPTIONS: '${SOCKETCLUSTER_OPTIONS}'
|
||||
YAML_SOCKET
|
||||
|
||||
# Add database service block only when using the bundled container
|
||||
if [[ "$DB_MODE" == "internal" ]]; then
|
||||
cat <<YAML_DB
|
||||
|
||||
database:
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
|
||||
MYSQL_DATABASE: "${DB_DATABASE}"
|
||||
MYSQL_USER: "${DB_USERNAME}"
|
||||
MYSQL_PASSWORD: "${DB_PASSWORD}"
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: "no"
|
||||
YAML_DB
|
||||
if [[ -f "$OVERRIDE_FILE" ]]; then
|
||||
if command -v yq >/dev/null 2>&1; then
|
||||
update_override_with_yq
|
||||
else
|
||||
cp "$OVERRIDE_FILE" "${OVERRIDE_FILE}.bak.$(date +%Y%m%d%H%M%S)"
|
||||
echo "ℹ︎ Existing $OVERRIDE_FILE backed up (no yq found — recreating)"
|
||||
create_override
|
||||
fi
|
||||
} > "$OVERRIDE_TMP"
|
||||
|
||||
mv -f "$OVERRIDE_TMP" "$OVERRIDE_FILE"
|
||||
success "$OVERRIDE_FILE written"
|
||||
else
|
||||
create_override
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# STEP 10 — Write console configuration files
|
||||
# 6. Write console/fleetbase.config.json atomically (for development runtime)
|
||||
###############################################################################
|
||||
section "Updating Console Configuration"
|
||||
|
||||
CONFIG_DIR="console"
|
||||
CONFIG_PATH="$CONFIG_DIR/fleetbase.config.json"
|
||||
mkdir -p "$CONFIG_DIR"
|
||||
|
||||
OSRM_HOST="https://router.project-osrm.org"
|
||||
|
||||
cat > "${CONFIG_DIR}/fleetbase.config.json.tmp" <<JSON
|
||||
cat > "${CONFIG_PATH}.tmp" <<JSON
|
||||
{
|
||||
"API_HOST": "${SCHEME_API}://${HOST}:8000",
|
||||
"SOCKETCLUSTER_HOST": "${HOST}",
|
||||
"API_HOST": "$SCHEME_API://$HOST:8000",
|
||||
"SOCKETCLUSTER_HOST": "$HOST",
|
||||
"SOCKETCLUSTER_PORT": "38000",
|
||||
"SOCKETCLUSTER_SECURE": "${SC_SECURE}"
|
||||
"SOCKETCLUSTER_SECURE": "$SC_SECURE"
|
||||
}
|
||||
JSON
|
||||
mv -f "${CONFIG_DIR}/fleetbase.config.json.tmp" "${CONFIG_DIR}/fleetbase.config.json"
|
||||
mv -f "${CONFIG_PATH}.tmp" "$CONFIG_PATH"
|
||||
echo "✔ $CONFIG_PATH updated"
|
||||
|
||||
ENV_DIR="${CONFIG_DIR}/environments"
|
||||
mkdir -p "$ENV_DIR"
|
||||
###############################################################################
|
||||
# 6b. Update console environment files (.env.development and .env.production)
|
||||
###############################################################################
|
||||
ENV_DIR="$CONFIG_DIR/environments"
|
||||
|
||||
cat > "${ENV_DIR}/.env.development" <<ENV_DEV
|
||||
API_HOST=http://${HOST}:8000
|
||||
# Update .env.development
|
||||
cat > "$ENV_DIR/.env.development" <<ENV_DEV
|
||||
API_HOST=http://$HOST:8000
|
||||
API_NAMESPACE=int/v1
|
||||
SOCKETCLUSTER_PATH=/socketcluster/
|
||||
SOCKETCLUSTER_HOST=${HOST}
|
||||
SOCKETCLUSTER_HOST=$HOST
|
||||
SOCKETCLUSTER_SECURE=false
|
||||
SOCKETCLUSTER_PORT=38000
|
||||
OSRM_HOST=${OSRM_HOST}
|
||||
OSRM_HOST=https://router.project-osrm.org
|
||||
ENV_DEV
|
||||
|
||||
cat > "${ENV_DIR}/.env.production" <<ENV_PROD
|
||||
API_HOST=https://${HOST}:8000
|
||||
# Update .env.production
|
||||
cat > "$ENV_DIR/.env.production" <<ENV_PROD
|
||||
API_HOST=https://$HOST:8000
|
||||
API_NAMESPACE=int/v1
|
||||
API_SECURE=true
|
||||
SOCKETCLUSTER_PATH=/socketcluster/
|
||||
SOCKETCLUSTER_HOST=${HOST}
|
||||
SOCKETCLUSTER_HOST=$HOST
|
||||
SOCKETCLUSTER_SECURE=true
|
||||
SOCKETCLUSTER_PORT=38000
|
||||
OSRM_HOST=${OSRM_HOST}
|
||||
OSRM_HOST=https://router.project-osrm.org
|
||||
ENV_PROD
|
||||
|
||||
success "Console configuration files updated"
|
||||
echo "✔ Console environment files updated"
|
||||
|
||||
###############################################################################
|
||||
# STEP 11 — Start containers
|
||||
# 7. Start stack, wait for DB, then run deploy
|
||||
###############################################################################
|
||||
section "Starting Fleetbase Containers"
|
||||
echo " This may take a few minutes on first run..."
|
||||
echo "⏳ Starting Fleetbase containers..."
|
||||
docker compose up -d
|
||||
|
||||
###############################################################################
|
||||
# STEP 12 — Wait for database
|
||||
# 7a. Wait for the database container to be ready
|
||||
###############################################################################
|
||||
section "Waiting for Database"
|
||||
DB_SERVICE="database"
|
||||
DB_WAIT_TIMEOUT=90
|
||||
DB_SERVICE="database" # ← change if your docker‑compose uses a different name
|
||||
DB_WAIT_TIMEOUT=60 # seconds
|
||||
|
||||
DB_CONTAINER=$(docker compose ps -q "$DB_SERVICE" 2>/dev/null || true)
|
||||
if [[ -z "$DB_CONTAINER" ]]; then
|
||||
error "Cannot find a running container for service \"$DB_SERVICE\". Check docker-compose.yml."
|
||||
echo "⏳ Waiting for $DB_SERVICE to become ready (timeout: ${DB_WAIT_TIMEOUT}s)..."
|
||||
DB_CONTAINER=$(docker compose ps -q "$DB_SERVICE")
|
||||
|
||||
if [ -z "$DB_CONTAINER" ]; then
|
||||
echo "✖ Cannot find a running container for service \"$DB_SERVICE\". Check docker‑compose.yml."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Prefer Docker HEALTHCHECK if defined, fall back to mysqladmin ping
|
||||
# If the service defines a HEALTHCHECK we can rely on it…
|
||||
if docker inspect -f '{{.State.Health.Status}}' "$DB_CONTAINER" &>/dev/null; then
|
||||
SECONDS=0
|
||||
until [[ "$(docker inspect -f '{{.State.Health.Status}}' "$DB_CONTAINER")" == "healthy" ]]; do
|
||||
if (( SECONDS >= DB_WAIT_TIMEOUT )); then
|
||||
error "Timed out waiting for the database to become healthy."
|
||||
until [ "$(docker inspect -f '{{.State.Health.Status}}' "$DB_CONTAINER")" = "healthy" ]; do
|
||||
if [ "$SECONDS" -ge "$DB_WAIT_TIMEOUT" ]; then
|
||||
echo "✖ Timed out waiting for the database to become healthy."
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
sleep 5 # brief grace period after healthy
|
||||
sleep 12
|
||||
else
|
||||
# Fallback: use mysqladmin ping (works for MySQL / MariaDB)
|
||||
SECONDS=0
|
||||
until docker compose exec -T "$DB_SERVICE" sh -c "mysqladmin --silent --wait=1 -uroot -h127.0.0.1 ping" &>/dev/null; do
|
||||
if (( SECONDS >= DB_WAIT_TIMEOUT )); then
|
||||
error "Timed out waiting for the database to accept connections."
|
||||
until docker compose exec "$DB_SERVICE" sh -c "mysqladmin --silent --wait=1 -uroot -h127.0.0.1 ping" &>/dev/null; do
|
||||
if [ "$SECONDS" -ge "$DB_WAIT_TIMEOUT" ]; then
|
||||
echo "✖ Timed out waiting for the database to accept connections."
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
fi
|
||||
success "Database is ready"
|
||||
echo "✔ Database is ready."
|
||||
|
||||
###############################################################################
|
||||
# STEP 13 — Run deploy script
|
||||
# 7b. Run the deploy script inside the application container
|
||||
###############################################################################
|
||||
section "Running Deployment Script"
|
||||
docker compose exec -T application bash -c "./deploy.sh"
|
||||
echo "⏳ Running deploy script inside the application container..."
|
||||
docker compose exec application bash -c "./deploy.sh"
|
||||
docker compose up -d
|
||||
success "Deployment complete"
|
||||
|
||||
###############################################################################
|
||||
# STEP 14 — Post-install summary
|
||||
###############################################################################
|
||||
CONFIGURED_ITEMS=()
|
||||
SKIPPED_ITEMS=()
|
||||
|
||||
[[ "$DB_MODE" == "external" ]] \
|
||||
&& CONFIGURED_ITEMS+=("External Database") \
|
||||
|| CONFIGURED_ITEMS+=("Bundled MySQL (secure credentials auto-generated)")
|
||||
|
||||
$CONFIG_MAIL \
|
||||
&& CONFIGURED_ITEMS+=("Mail (${MAIL_MAILER})") \
|
||||
|| SKIPPED_ITEMS+=("Mail (using log driver — configure later)")
|
||||
|
||||
[[ "$FILESYSTEM_DRIVER" != "public" ]] \
|
||||
&& CONFIGURED_ITEMS+=("File Storage (${FILESYSTEM_DRIVER^^})") \
|
||||
|| SKIPPED_ITEMS+=("File storage (local disk — not suitable for production)")
|
||||
|
||||
CONFIGURED_ITEMS+=("WebSocket security (origins restricted to ${HOST})")
|
||||
|
||||
$CONFIG_3P \
|
||||
&& CONFIGURED_ITEMS+=("Third-party APIs (Maps, Geolocation, SMS)") \
|
||||
|| SKIPPED_ITEMS+=("Third-party APIs (Maps, Geolocation, SMS)")
|
||||
|
||||
echo
|
||||
printf '%0.s═' {1..60}; echo
|
||||
echo -e " ${BOLD}🏁 Fleetbase Installation Complete${RESET}"
|
||||
printf '%0.s═' {1..60}; echo
|
||||
echo
|
||||
echo " 📍 Endpoints"
|
||||
printf " API → %s://%s:8000\n" "$SCHEME_API" "$HOST"
|
||||
printf " Console → %s://%s:4200\n" "$SCHEME_CONSOLE" "$HOST"
|
||||
if [[ ${#CONFIGURED_ITEMS[@]} -gt 0 ]]; then
|
||||
echo
|
||||
echo " ✔ Configured:"
|
||||
for item in "${CONFIGURED_ITEMS[@]}"; do echo " • $item"; done
|
||||
fi
|
||||
if [[ ${#SKIPPED_ITEMS[@]} -gt 0 ]]; then
|
||||
echo
|
||||
echo " ⚠ Skipped (defaults applied):"
|
||||
for item in "${SKIPPED_ITEMS[@]}"; do echo " • $item"; done
|
||||
fi
|
||||
echo
|
||||
echo " 🔐 Next Steps"
|
||||
echo " 1. Open the Console URL in your browser."
|
||||
echo " 2. Complete the onboarding wizard to create your"
|
||||
echo " initial organization and administrator account."
|
||||
if [[ ${#SKIPPED_ITEMS[@]} -gt 0 ]]; then
|
||||
echo " 3. To configure skipped options, edit"
|
||||
echo " docker-compose.override.yml and run:"
|
||||
echo " docker compose up -d"
|
||||
fi
|
||||
echo
|
||||
echo " 📄 Config saved to: docker-compose.override.yml"
|
||||
printf '%0.s═' {1..60}; echo
|
||||
echo
|
||||
echo "🏁 Fleetbase is up!"
|
||||
printf " API → %s://%s:8000\n" "$SCHEME_API" "$HOST"
|
||||
printf " Console → %s://%s:4200\n\n" "$SCHEME_CONSOLE" "$HOST"
|
||||
Reference in New Issue
Block a user