Changeset 0.22.6 (#148)
This commit is contained in:
@@ -2,16 +2,23 @@
|
||||
# ============================================
|
||||
# Chat Switchboard - Frontend Entrypoint
|
||||
# ============================================
|
||||
# Injects BASE_PATH into index.html and nginx
|
||||
# config at container startup. Supports path-
|
||||
# based multi-env deployment on a single domain.
|
||||
# nginx serves static assets and proxies page
|
||||
# routes to the Go backend for template rendering.
|
||||
# API/WS routes are handled by Ingress directly.
|
||||
#
|
||||
# Environment:
|
||||
# BASE_PATH - URL prefix (e.g. "/dev", "/test", or "")
|
||||
# Environment (required):
|
||||
# BACKEND_URL - Backend service URL
|
||||
# (e.g. "http://switchboard-be:8080")
|
||||
#
|
||||
# Environment (optional):
|
||||
# BASE_PATH - URL prefix (e.g. "/dev", "" for root)
|
||||
# ENVIRONMENT - Environment name for logging
|
||||
# ============================================
|
||||
set -e
|
||||
|
||||
BASE_PATH="${BASE_PATH:-}"
|
||||
BACKEND_URL="${BACKEND_URL:?BACKEND_URL is required (e.g. http://switchboard-be:8080)}"
|
||||
ENVIRONMENT="${ENVIRONMENT:-production}"
|
||||
|
||||
# Read version from VERSION file (baked in at build time)
|
||||
APP_VERSION="dev"
|
||||
@@ -19,39 +26,16 @@ if [ -f /VERSION ]; then
|
||||
APP_VERSION=$(cat /VERSION | tr -d '[:space:]')
|
||||
fi
|
||||
|
||||
# Compute base href (needs trailing slash for <base> tag)
|
||||
if [ -z "${BASE_PATH}" ]; then
|
||||
BASE_HREF="/"
|
||||
else
|
||||
BASE_HREF="${BASE_PATH}/"
|
||||
fi
|
||||
|
||||
# ── Read branding config ────────────────────
|
||||
BRANDING_JSON="{}"
|
||||
if [ -f /branding/branding.json ]; then
|
||||
# Compact to single line for safe sed injection
|
||||
BRANDING_JSON=$(tr -d '\n' < /branding/branding.json | sed 's/ */ /g')
|
||||
echo "✅ Branding config loaded from /branding/branding.json"
|
||||
else
|
||||
echo "ℹ️ No branding mount — using defaults"
|
||||
fi
|
||||
|
||||
# ── Read environment name ─────────────────
|
||||
ENVIRONMENT="${ENVIRONMENT:-production}"
|
||||
|
||||
# Compute build hash from frontend file contents (changes on every deploy)
|
||||
# Compute build hash from JS file contents (unique per deploy)
|
||||
BUILD_HASH=$(find /usr/share/nginx/html/js -name '*.js' -exec md5sum {} + 2>/dev/null | sort | md5sum | cut -c1-8)
|
||||
if [ -z "${BUILD_HASH}" ]; then
|
||||
BUILD_HASH=$(date +%s | md5sum | cut -c1-8)
|
||||
fi
|
||||
|
||||
# ── Inject into index.html ──────────────────
|
||||
# ── Inject into index.html (redirect page) ──
|
||||
sed -i \
|
||||
-e "s|%%BASE_PATH%%|${BASE_PATH}|g" \
|
||||
-e "s|%%BASE_HREF%%|${BASE_HREF}|g" \
|
||||
-e "s|%%APP_VERSION%%|${APP_VERSION}|g" \
|
||||
-e "s|%%ENVIRONMENT%%|${ENVIRONMENT}|g" \
|
||||
-e "s|%%BRANDING_JSON%%|${BRANDING_JSON}|g" \
|
||||
/usr/share/nginx/html/index.html
|
||||
|
||||
# Inject version and build hash into service worker
|
||||
@@ -60,13 +44,45 @@ sed -i \
|
||||
-e "s|%%BUILD_HASH%%|${BUILD_HASH}|g" \
|
||||
/usr/share/nginx/html/sw.js
|
||||
|
||||
echo "✅ Frontend configured: BASE_PATH=${BASE_PATH:-/} VERSION=${APP_VERSION} BUILD=${BUILD_HASH} ENV=${ENVIRONMENT}"
|
||||
echo "✅ Frontend: BASE_PATH=${BASE_PATH:-/} VERSION=${APP_VERSION} BUILD=${BUILD_HASH} BACKEND=${BACKEND_URL}"
|
||||
|
||||
# ── Page route proxy blocks ─────────────────
|
||||
page_proxy_block() {
|
||||
local path="$1"
|
||||
cat <<PROXY
|
||||
location ${path} {
|
||||
proxy_pass ${BACKEND_URL};
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
}
|
||||
PROXY
|
||||
}
|
||||
|
||||
PAGE_ROUTES=$(cat <<ROUTES
|
||||
# ── Page routes → backend ────────────────
|
||||
$(page_proxy_block "= ${BASE_PATH}/")
|
||||
$(page_proxy_block "= ${BASE_PATH}/login")
|
||||
location ~ ^${BASE_PATH}/chat/[^/]+\$ {
|
||||
proxy_pass ${BACKEND_URL};
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
}
|
||||
$(page_proxy_block "${BASE_PATH}/admin")
|
||||
$(page_proxy_block "${BASE_PATH}/editor")
|
||||
$(page_proxy_block "${BASE_PATH}/notes")
|
||||
$(page_proxy_block "${BASE_PATH}/settings")
|
||||
ROUTES
|
||||
)
|
||||
|
||||
# ── Generate nginx config ───────────────────
|
||||
# If BASE_PATH is set, serve under that prefix with alias.
|
||||
# If empty, serve from root (default behavior).
|
||||
if [ -z "${BASE_PATH}" ]; then
|
||||
cat > /etc/nginx/conf.d/default.conf <<'NGINX'
|
||||
cat > /etc/nginx/conf.d/default.conf <<NGINX
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
@@ -84,25 +100,24 @@ server {
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# Service worker must never be cached by the browser
|
||||
location = /sw.js {
|
||||
expires off;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
}
|
||||
|
||||
# Branding assets — served from volume mount, 404s gracefully
|
||||
location /branding/ {
|
||||
alias /branding/;
|
||||
expires 1h;
|
||||
add_header Cache-Control "public";
|
||||
try_files $uri =404;
|
||||
try_files \$uri =404;
|
||||
}
|
||||
|
||||
${PAGE_ROUTES}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
try_files \$uri \$uri/ /index.html;
|
||||
}
|
||||
|
||||
# Health check for k8s probes
|
||||
location = /healthz {
|
||||
return 200 'ok';
|
||||
add_header Content-Type text/plain;
|
||||
@@ -125,6 +140,8 @@ server {
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml application/javascript;
|
||||
|
||||
${PAGE_ROUTES}
|
||||
|
||||
location ${BASE_PATH}/ {
|
||||
alias /usr/share/nginx/html/;
|
||||
try_files \$uri \$uri/ ${BASE_PATH}/index.html;
|
||||
@@ -134,7 +151,6 @@ server {
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# Service worker must never be cached by the browser
|
||||
location = ${BASE_PATH}/sw.js {
|
||||
alias /usr/share/nginx/html/sw.js;
|
||||
expires off;
|
||||
@@ -142,7 +158,6 @@ server {
|
||||
}
|
||||
}
|
||||
|
||||
# Branding assets — under BASE_PATH so Traefik routes them here
|
||||
location ${BASE_PATH}/branding/ {
|
||||
alias /branding/;
|
||||
expires 1h;
|
||||
@@ -150,12 +165,10 @@ server {
|
||||
try_files \$uri =404;
|
||||
}
|
||||
|
||||
# Redirect bare path to trailing slash
|
||||
location = ${BASE_PATH} {
|
||||
return 301 ${BASE_PATH}/;
|
||||
}
|
||||
|
||||
# Health check for k8s probes (always at root)
|
||||
location = /healthz {
|
||||
return 200 'ok';
|
||||
add_header Content-Type text/plain;
|
||||
@@ -168,5 +181,4 @@ server {
|
||||
NGINX
|
||||
fi
|
||||
|
||||
# ── Start nginx ─────────────────────────────
|
||||
exec nginx -g 'daemon off;'
|
||||
|
||||
Reference in New Issue
Block a user