144 lines
4.2 KiB
Bash
144 lines
4.2 KiB
Bash
#!/bin/sh
|
||
# ============================================
|
||
# 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.
|
||
#
|
||
# Environment:
|
||
# BASE_PATH - URL prefix (e.g. "/dev", "/test", or "")
|
||
# ============================================
|
||
set -e
|
||
|
||
BASE_PATH="${BASE_PATH:-}"
|
||
|
||
# Read version from VERSION file (baked in at build time)
|
||
APP_VERSION="dev"
|
||
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
|
||
|
||
# ── Inject into index.html ──────────────────
|
||
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|%%BRANDING_JSON%%|${BRANDING_JSON}|g" \
|
||
/usr/share/nginx/html/index.html
|
||
|
||
echo "✅ Frontend configured: BASE_PATH=${BASE_PATH:-/} VERSION=${APP_VERSION}"
|
||
|
||
# ── 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'
|
||
server {
|
||
listen 80;
|
||
server_name _;
|
||
root /usr/share/nginx/html;
|
||
index index.html;
|
||
|
||
gzip on;
|
||
gzip_vary on;
|
||
gzip_min_length 1024;
|
||
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;
|
||
|
||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
|
||
expires 1y;
|
||
add_header Cache-Control "public, immutable";
|
||
}
|
||
|
||
# Branding assets — served from volume mount, 404s gracefully
|
||
location /branding/ {
|
||
alias /branding/;
|
||
expires 1h;
|
||
add_header Cache-Control "public";
|
||
try_files $uri =404;
|
||
}
|
||
|
||
location / {
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
|
||
# Health check for k8s probes
|
||
location = /healthz {
|
||
return 200 'ok';
|
||
add_header Content-Type text/plain;
|
||
}
|
||
|
||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||
add_header X-Content-Type-Options "nosniff" always;
|
||
add_header X-XSS-Protection "1; mode=block" always;
|
||
}
|
||
NGINX
|
||
else
|
||
cat > /etc/nginx/conf.d/default.conf <<NGINX
|
||
server {
|
||
listen 80;
|
||
server_name _;
|
||
|
||
gzip on;
|
||
gzip_vary on;
|
||
gzip_min_length 1024;
|
||
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;
|
||
|
||
location ${BASE_PATH}/ {
|
||
alias /usr/share/nginx/html/;
|
||
try_files \$uri \$uri/ ${BASE_PATH}/index.html;
|
||
|
||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)\$ {
|
||
expires 1y;
|
||
add_header Cache-Control "public, immutable";
|
||
}
|
||
}
|
||
|
||
# Branding assets — under BASE_PATH so Traefik routes them here
|
||
location ${BASE_PATH}/branding/ {
|
||
alias /branding/;
|
||
expires 1h;
|
||
add_header Cache-Control "public";
|
||
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;
|
||
}
|
||
|
||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||
add_header X-Content-Type-Options "nosniff" always;
|
||
add_header X-XSS-Protection "1; mode=block" always;
|
||
}
|
||
NGINX
|
||
fi
|
||
|
||
# ── Start nginx ─────────────────────────────
|
||
exec nginx -g 'daemon off;'
|