Fix config.sh Pangolin setup and MongoDB init for fresh deployments
- Fix Pangolin endpoint: ask separately from API URL (different hostnames) - Add pangolin_create_resources() to create resources + targets during setup - Set all resources as public (no SSO/blockAccess) automatically - Fix API health check URL to use actual org endpoint - Fix MongoDB entrypoint: delegate to docker-entrypoint.sh so INITDB user creation works on fresh volumes (was bypassing Docker's init sequence) Bunker Admin
This commit is contained in:
parent
72dbd0189c
commit
849dea7ce2
186
config.sh
186
config.sh
@ -877,9 +877,15 @@ configure_pangolin() {
|
||||
read -rp " Pangolin API key: " pang_key
|
||||
read -rp " Pangolin Organization ID: " pang_org
|
||||
|
||||
# The Pangolin endpoint (dashboard/Newt WebSocket URL) may differ from the API URL.
|
||||
# For example: API at api.example.org vs dashboard at pangolin.example.org
|
||||
read -rp " Pangolin Endpoint (dashboard/Newt URL) [default: https://pangolin.bnkserve.org]: " pang_endpoint
|
||||
pang_endpoint=${pang_endpoint:-https://pangolin.bnkserve.org}
|
||||
|
||||
update_env_var "PANGOLIN_API_URL" "$pang_url"
|
||||
update_env_var "PANGOLIN_API_KEY" "$pang_key"
|
||||
update_env_var "PANGOLIN_ORG_ID" "$pang_org"
|
||||
update_env_var "PANGOLIN_ENDPOINT" "$pang_endpoint"
|
||||
|
||||
success "Pangolin API credentials saved"
|
||||
|
||||
@ -896,7 +902,7 @@ configure_pangolin() {
|
||||
local health_status
|
||||
health_status=$(curl -s -o /dev/null -w "%{http_code}" -m 10 \
|
||||
-H "Authorization: Bearer $pang_key" \
|
||||
"$pang_url/" 2>/dev/null) || true
|
||||
"$pang_url/org/$pang_org/sites" 2>/dev/null) || true
|
||||
|
||||
if [[ "$health_status" != "200" ]]; then
|
||||
warn "Could not reach Pangolin API (HTTP $health_status)."
|
||||
@ -919,8 +925,8 @@ configure_pangolin() {
|
||||
site_choice=${site_choice:-3}
|
||||
|
||||
case "$site_choice" in
|
||||
1) pangolin_create_site "$pang_url" "$pang_key" "$pang_org" ;;
|
||||
2) pangolin_connect_site "$pang_url" "$pang_key" "$pang_org" ;;
|
||||
1) pangolin_create_site "$pang_url" "$pang_key" "$pang_org" "$pang_endpoint" ;;
|
||||
2) pangolin_connect_site "$pang_url" "$pang_key" "$pang_org" "$pang_endpoint" ;;
|
||||
*)
|
||||
info "Complete tunnel setup in the admin GUI at /app/pangolin after starting services."
|
||||
;;
|
||||
@ -943,8 +949,122 @@ pangolin_api() {
|
||||
"${body_args[@]}" 2>/dev/null
|
||||
}
|
||||
|
||||
pangolin_create_resources() {
|
||||
local api_url=$1 api_key=$2 org_id=$3 site_id=$4 domain=$5
|
||||
|
||||
info "Creating Pangolin resources and targets for $domain..."
|
||||
|
||||
# Look up the domain ID from registered domains
|
||||
local domains_resp domain_id
|
||||
domains_resp=$(pangolin_api GET "$api_url/org/$org_id/domains" "$api_key")
|
||||
domain_id=$(echo "$domains_resp" | jq -r --arg d "$domain" \
|
||||
'.data.domains[]? | select(.baseDomain == $d) | .domainId' 2>/dev/null)
|
||||
|
||||
if [[ -z "$domain_id" ]]; then
|
||||
warn "Domain '$domain' not found in Pangolin. Register it first in the dashboard."
|
||||
info "After registering the domain, run the sync from the admin GUI at /app/pangolin."
|
||||
return
|
||||
fi
|
||||
|
||||
success "Found domain: $domain (ID: $domain_id)"
|
||||
|
||||
# Resource definitions: subdomain|name
|
||||
# Empty subdomain = root domain
|
||||
local -a resource_defs=(
|
||||
"app|Admin GUI"
|
||||
"api|API Server"
|
||||
"|Public Site"
|
||||
"db|NocoDB"
|
||||
"docs|Documentation"
|
||||
"code|Code Server"
|
||||
"n8n|Workflows"
|
||||
"git|Gitea"
|
||||
"home|Homepage"
|
||||
"listmonk|Newsletter"
|
||||
"qr|Mini QR"
|
||||
"draw|Excalidraw"
|
||||
"vault|Vaultwarden"
|
||||
"mail|MailHog"
|
||||
"chat|Rocket.Chat"
|
||||
"events|Gancio Events"
|
||||
"meet|Jitsi Meet"
|
||||
"grafana|Grafana"
|
||||
)
|
||||
|
||||
local created=0 skipped=0 failed=0
|
||||
|
||||
for def in "${resource_defs[@]}"; do
|
||||
local subdomain="${def%%|*}"
|
||||
local name="${def#*|}"
|
||||
local full_domain
|
||||
if [[ -n "$subdomain" ]]; then
|
||||
full_domain="$subdomain.$domain"
|
||||
else
|
||||
full_domain="$domain"
|
||||
fi
|
||||
|
||||
# Build create payload — omit subdomain entirely for root domain (Pangolin rejects empty string)
|
||||
local create_payload
|
||||
if [[ -n "$subdomain" ]]; then
|
||||
create_payload=$(jq -n \
|
||||
--arg name "$name" \
|
||||
--arg domainId "$domain_id" \
|
||||
--arg subdomain "$subdomain" \
|
||||
'{name: $name, domainId: $domainId, subdomain: $subdomain, http: true, protocol: "tcp"}')
|
||||
else
|
||||
create_payload=$(jq -n \
|
||||
--arg name "$name" \
|
||||
--arg domainId "$domain_id" \
|
||||
'{name: $name, domainId: $domainId, http: true, protocol: "tcp"}')
|
||||
fi
|
||||
|
||||
# Create the resource
|
||||
local res_resp
|
||||
res_resp=$(pangolin_api PUT "$api_url/org/$org_id/resource" "$api_key" "$create_payload")
|
||||
|
||||
local resource_id
|
||||
resource_id=$(echo "$res_resp" | jq -r '.data.resourceId // empty' 2>/dev/null)
|
||||
|
||||
if [[ -z "$resource_id" ]]; then
|
||||
local err_msg
|
||||
err_msg=$(echo "$res_resp" | jq -r '.message // "unknown error"' 2>/dev/null)
|
||||
if echo "$err_msg" | grep -qi "already exists\|duplicate\|conflict"; then
|
||||
((skipped++))
|
||||
else
|
||||
warn " Failed to create $full_domain: $err_msg"
|
||||
((failed++))
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
# Create target pointing to nginx:80
|
||||
local target_payload
|
||||
target_payload=$(jq -n \
|
||||
--argjson siteId "$site_id" \
|
||||
'{siteId: $siteId, ip: "nginx", port: 80, method: "http", enabled: true}')
|
||||
|
||||
pangolin_api PUT "$api_url/resource/$resource_id/target" "$api_key" "$target_payload" >/dev/null
|
||||
|
||||
# Set resource as public (no SSO, no access block)
|
||||
pangolin_api POST "$api_url/resource/$resource_id" "$api_key" \
|
||||
'{"sso":false,"blockAccess":false}' >/dev/null
|
||||
|
||||
((created++))
|
||||
done
|
||||
|
||||
if [[ $created -gt 0 ]]; then
|
||||
success "Created $created resources with targets → nginx:80"
|
||||
fi
|
||||
if [[ $skipped -gt 0 ]]; then
|
||||
info "$skipped resources already existed (skipped)"
|
||||
fi
|
||||
if [[ $failed -gt 0 ]]; then
|
||||
warn "$failed resources failed to create"
|
||||
fi
|
||||
}
|
||||
|
||||
pangolin_create_site() {
|
||||
local api_url=$1 api_key=$2 org_id=$3
|
||||
local api_url=$1 api_key=$2 org_id=$3 endpoint=$4
|
||||
local domain="${CONFIGURED_DOMAIN:-cmlite.org}"
|
||||
local site_name
|
||||
|
||||
@ -993,22 +1113,19 @@ pangolin_create_site() {
|
||||
|
||||
success "Site created: $site_id ($site_name)"
|
||||
|
||||
# Derive endpoint from API URL (strip /v1 path)
|
||||
local endpoint
|
||||
endpoint=$(echo "$api_url" | sed 's|/v1/*$||')
|
||||
|
||||
# Write credentials to .env
|
||||
update_env_var "PANGOLIN_SITE_ID" "$site_id"
|
||||
update_env_var "PANGOLIN_NEWT_ID" "$newt_id"
|
||||
update_env_var "PANGOLIN_NEWT_SECRET" "$newt_secret"
|
||||
update_env_var "PANGOLIN_ENDPOINT" "$endpoint"
|
||||
|
||||
success "Tunnel credentials written to .env"
|
||||
info "Resources will be created automatically via the admin GUI or sync endpoint."
|
||||
|
||||
# Create resources and targets
|
||||
pangolin_create_resources "$api_url" "$api_key" "$org_id" "$site_id" "$domain"
|
||||
}
|
||||
|
||||
pangolin_connect_site() {
|
||||
local api_url=$1 api_key=$2 org_id=$3
|
||||
local api_url=$1 api_key=$2 org_id=$3 endpoint=$4
|
||||
|
||||
info "Fetching sites from organization..."
|
||||
local sites_resp
|
||||
@ -1066,37 +1183,50 @@ pangolin_connect_site() {
|
||||
sel_id=$(echo "$selected" | jq -r '.siteId')
|
||||
sel_name=$(echo "$selected" | jq -r '.name')
|
||||
|
||||
# Derive endpoint from API URL
|
||||
local endpoint
|
||||
endpoint=$(echo "$api_url" | sed 's|/v1/*$||')
|
||||
|
||||
# Write site ID to .env
|
||||
update_env_var "PANGOLIN_SITE_ID" "$sel_id"
|
||||
update_env_var "PANGOLIN_ENDPOINT" "$endpoint"
|
||||
|
||||
success "Connected to site: $sel_name (ID: $sel_id)"
|
||||
|
||||
# Check if we also need Newt credentials
|
||||
# Fetch Newt credentials for this site from the API
|
||||
local existing_newt_id
|
||||
existing_newt_id=$(grep "^PANGOLIN_NEWT_ID=" "$ENV_FILE" 2>/dev/null | cut -d= -f2-)
|
||||
|
||||
if [[ -z "$existing_newt_id" ]]; then
|
||||
info "Newt credentials not yet set."
|
||||
info "If you have the Newt ID and Secret for this site, enter them now."
|
||||
info "Otherwise, set them later via the admin GUI."
|
||||
echo ""
|
||||
read -rp " Newt ID (leave blank to skip): " newt_id_input
|
||||
if [[ -n "$newt_id_input" ]]; then
|
||||
read -rp " Newt Secret: " newt_secret_input
|
||||
if [[ -n "$newt_secret_input" ]]; then
|
||||
update_env_var "PANGOLIN_NEWT_ID" "$newt_id_input"
|
||||
update_env_var "PANGOLIN_NEWT_SECRET" "$newt_secret_input"
|
||||
success "Newt credentials written to .env"
|
||||
info "Fetching Newt credentials for this site..."
|
||||
|
||||
# Try pickSiteDefaults for fresh Newt creds
|
||||
local defaults_resp
|
||||
defaults_resp=$(pangolin_api GET "$api_url/org/$org_id/pick-site-defaults" "$api_key")
|
||||
local newt_id newt_secret
|
||||
newt_id=$(echo "$defaults_resp" | jq -r '.data.newtId // .newtId // empty' 2>/dev/null)
|
||||
newt_secret=$(echo "$defaults_resp" | jq -r '.data.newtSecret // .newtSecret // .data.secret // .secret // empty' 2>/dev/null)
|
||||
|
||||
if [[ -n "$newt_id" && -n "$newt_secret" ]]; then
|
||||
update_env_var "PANGOLIN_NEWT_ID" "$newt_id"
|
||||
update_env_var "PANGOLIN_NEWT_SECRET" "$newt_secret"
|
||||
success "Newt credentials fetched and saved (newtId: $newt_id)"
|
||||
else
|
||||
info "Could not auto-fetch Newt credentials."
|
||||
info "Enter them manually (from your Pangolin dashboard)."
|
||||
echo ""
|
||||
read -rp " Newt ID (leave blank to skip): " newt_id_input
|
||||
if [[ -n "$newt_id_input" ]]; then
|
||||
read -rp " Newt Secret: " newt_secret_input
|
||||
if [[ -n "$newt_secret_input" ]]; then
|
||||
update_env_var "PANGOLIN_NEWT_ID" "$newt_id_input"
|
||||
update_env_var "PANGOLIN_NEWT_SECRET" "$newt_secret_input"
|
||||
success "Newt credentials written to .env"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
info "Existing Newt credentials found in .env (newtId: $existing_newt_id)"
|
||||
fi
|
||||
|
||||
# Create resources and targets
|
||||
local domain="${CONFIGURED_DOMAIN:-cmlite.org}"
|
||||
pangolin_create_resources "$api_url" "$api_key" "$org_id" "$sel_id" "$domain"
|
||||
}
|
||||
|
||||
configure_control_panel() {
|
||||
|
||||
@ -914,7 +914,8 @@ services:
|
||||
image: ${GITEA_REGISTRY:-gitea.bnkops.com/admin}/mongo:6.0
|
||||
container_name: mongodb-rocketchat
|
||||
restart: unless-stopped
|
||||
entrypoint: ["/bin/bash", "-c", "if [ ! -f /data/replica.key ]; then openssl rand -base64 756 > /data/replica.key; fi && chmod 400 /data/replica.key && chown 999:999 /data/replica.key && exec mongod --replSet rs0 --bind_ip_all --auth --keyFile /data/replica.key"]
|
||||
# Generate keyfile then delegate to Docker's standard entrypoint (creates INITDB user)
|
||||
entrypoint: ["/bin/bash", "-c", "if [ ! -f /data/replica.key ]; then openssl rand -base64 756 > /data/replica.key; fi && chmod 400 /data/replica.key && chown 999:999 /data/replica.key && exec docker-entrypoint.sh mongod --replSet rs0 --bind_ip_all --keyFile /data/replica.key"]
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER:-rocketchat}
|
||||
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD:?MONGO_ROOT_PASSWORD must be set in .env}
|
||||
|
||||
@ -940,7 +940,8 @@ services:
|
||||
image: mongo:6.0
|
||||
container_name: mongodb-rocketchat
|
||||
restart: unless-stopped
|
||||
entrypoint: ["/bin/bash", "-c", "if [ ! -f /data/replica.key ]; then openssl rand -base64 756 > /data/replica.key; fi && chmod 400 /data/replica.key && chown 999:999 /data/replica.key && exec mongod --replSet rs0 --bind_ip_all --auth --keyFile /data/replica.key"]
|
||||
# Generate keyfile then delegate to Docker's standard entrypoint (creates INITDB user)
|
||||
entrypoint: ["/bin/bash", "-c", "if [ ! -f /data/replica.key ]; then openssl rand -base64 756 > /data/replica.key; fi && chmod 400 /data/replica.key && chown 999:999 /data/replica.key && exec docker-entrypoint.sh mongod --replSet rs0 --bind_ip_all --keyFile /data/replica.key"]
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER:-rocketchat}
|
||||
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD:?MONGO_ROOT_PASSWORD must be set in .env}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user