Implement shared Caddy setup with initializing and unavailable pages for various apps

- Refactor domain scripts for Ghost, Gitea, Jellyfin, Metabase, n8n, NocoDB, Open WebUI, OpenClaw, PicoClaw, Plausible, Signoz, Uptime Kuma, and Vaultwarden to utilize a common Caddy setup script.
- Introduce `caddy-setup.sh` for managing Caddy configurations and handling app initialization states.
- Create `initializing.html` and `unavailable.html` pages to provide user feedback during app deployment and downtime.
- Update domain handling logic to ensure seamless transitions between initializing and operational states.
- Enhance user experience by providing visual indicators for app status during setup and maintenance.
This commit is contained in:
lolwierd
2026-03-28 14:37:33 +05:30
parent 250730435a
commit ed19997ba0
19 changed files with 810 additions and 181 deletions

130
_common/caddy-setup.sh Normal file
View File

@@ -0,0 +1,130 @@
#!/bin/bash
#
# Shared Caddy setup with initializing/unavailable pages.
#
# Usage in domain.sh:
# source /var/excloud/scripts/caddy-setup.sh
# setup_initializing_page "$DOMAIN" "$APP_NAME" "$APP_DIR/$APP_NAME"
# ... start containers ...
# wait_and_switch_to_proxy "$DOMAIN" "$APP_UPSTREAM_PORT" "$APP_DIR/$APP_NAME" &
#
# For apps with custom Caddyfile (e.g. signoz with multi-route), use:
# write_loading_pages "$APP_NAME" "$APP_DIR/$APP_NAME"
# setup_initializing_page "$DOMAIN" "$APP_NAME" "$APP_DIR/$APP_NAME"
# ... start containers ...
# wait_and_switch_to_proxy "$DOMAIN" "$APP_UPSTREAM_PORT" "$APP_DIR/$APP_NAME" "$CUSTOM_CADDYFILE_CONTENT" &
SCRIPT_DIR_CADDY="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
write_loading_pages() {
local app_name="$1"
local app_dir="$2"
local display_name
display_name="$(echo "$app_name" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)}1')"
mkdir -p "${app_dir}/.excloud"
cp "${SCRIPT_DIR_CADDY}/initializing.html" "${app_dir}/.excloud/initializing.html"
cp "${SCRIPT_DIR_CADDY}/unavailable.html" "${app_dir}/.excloud/unavailable.html"
sed -i "s/APP_DISPLAY_NAME/${display_name}/g" "${app_dir}/.excloud/initializing.html"
sed -i "s/APP_DISPLAY_NAME/${display_name}/g" "${app_dir}/.excloud/unavailable.html"
}
# Phase 1: Serve the initializing page immediately via Caddy file_server.
setup_initializing_page() {
local domain="$1"
local app_name="$2"
local app_dir="$3"
write_loading_pages "$app_name" "$app_dir"
cat > /etc/caddy/Caddyfile <<EOF
https://${domain} {
root * ${app_dir}/.excloud
rewrite * /initializing.html
file_server
}
EOF
systemctl enable caddy
systemctl reload caddy
echo "Caddy serving initializing page for ${app_name}"
}
# Phase 2 (runs in background): Poll the upstream port, then switch Caddy to reverse_proxy.
# Accepts an optional 4th argument with custom Caddyfile content for apps like signoz.
wait_and_switch_to_proxy() {
local domain="$1"
local port="$2"
local app_dir="$3"
local custom_caddyfile="${4:-}"
# Wait for the app to respond (up to 20 minutes)
local start_time
start_time="$(date +%s)"
while ! curl -fsS -o /dev/null "http://127.0.0.1:${port}" 2>/dev/null; do
if [ $(( $(date +%s) - start_time )) -ge 1200 ]; then
echo "App did not become ready within 20 minutes" >&2
break
fi
sleep 5
done
# Switch to reverse proxy with handle_errors for unavailable page
if [ -n "$custom_caddyfile" ]; then
echo "$custom_caddyfile" > /etc/caddy/Caddyfile
else
cat > /etc/caddy/Caddyfile <<EOF
https://${domain} {
reverse_proxy 127.0.0.1:${port}
handle_errors {
root * ${app_dir}/.excloud
rewrite * /unavailable.html
file_server
}
}
EOF
fi
touch "${app_dir}/.excloud/.ready"
systemctl reload caddy
echo "App is ready — Caddy switched to reverse proxy"
}
# Quick domain swap for an already-running app. Skips the initializing page
# and background watcher — just updates the Caddyfile and reloads.
# Accepts an optional 4th argument with custom Caddyfile content.
switch_domain() {
local domain="$1"
local port="$2"
local app_dir="$3"
local custom_caddyfile="${4:-}"
write_loading_pages "$(basename "$app_dir")" "$app_dir"
if [ -n "$custom_caddyfile" ]; then
echo "$custom_caddyfile" > /etc/caddy/Caddyfile
else
cat > /etc/caddy/Caddyfile <<EOF
https://${domain} {
reverse_proxy 127.0.0.1:${port}
handle_errors {
root * ${app_dir}/.excloud
rewrite * /unavailable.html
file_server
}
}
EOF
fi
systemctl reload caddy
echo "Domain switched to ${domain}"
}
# Returns 0 if the app has completed first-time setup, 1 otherwise.
is_app_ready() {
local app_dir="$1"
[ -f "${app_dir}/.excloud/.ready" ]
}