Back up existing files before every service overwrites them
Confirmed live: install_frigate()'s fresh-install path overwrote a working, hand-crafted docker-compose.yml (Frigate + mosquitto + frigate-notify) with zero backup, because that file's shape didn't match what frigate.sh's own "existing install" detection knew how to recognize. Every service's own detection is a judgment call about what counts as "already installed" and can miss a real setup built outside this repo's conventions. lib/common.sh gains backup_if_exists(FILE) — copies FILE to FILE.bak.<timestamp> if it exists, no-ops otherwise (including DRY_RUN). Applied before every service's own `cat > docker-compose.yml`/`cat > .env` write across all 60 services that do one (115 call sites), plus a matching standalone-mode stub added to every service's own bootstrap block, same convention already used for port_in_use/find_free_port. This doesn't replace a service's own update/fresh-reinstall detection — it's the safety net underneath it, so a wrong detection costs a .bak file to restore from instead of the original silently disappearing. Also fixes the actual gap that surfaced this: services/frigate.sh's Authelia offer only checked for Authelia installed locally on Frigate's own box, which is never true for a dedicated NVR box with no local Caddy either (the common shape — Caddy lives elsewhere, snippet-generation mode already handles that). Now offers Authelia protection unconditionally and, when Authelia isn't local, asks whether it lives on the same machine as Caddy (still "import authelia", since that's local to wherever Caddy ends up) or on a genuinely separate third machine (the explicit header-pinned forward_auth form, per CLAUDE.md's "forward_auth to a remote Authelia" note, needed because a bare authelia:9091 shortcut only works one hop).
This commit is contained in:
+67
-5
@@ -202,6 +202,11 @@ CBLOCK
|
||||
mkdir -p "$_dir"
|
||||
cat > "$_dir/README.md"
|
||||
}
|
||||
backup_if_exists() {
|
||||
local _file="$1"
|
||||
[ -f "$_file" ] || return 0
|
||||
cp -p "$_file" "${_file}.bak.$(date +%Y%m%d-%H%M%S)" 2>/dev/null
|
||||
}
|
||||
fi
|
||||
|
||||
# Globals — ACTUAL_USER/ACTUAL_HOME must come before DOCKER_DIR
|
||||
@@ -626,6 +631,7 @@ networks:
|
||||
"
|
||||
fi
|
||||
|
||||
backup_if_exists docker-compose.yml
|
||||
cat > docker-compose.yml << FRIGATE_COMPOSE
|
||||
name: frigate
|
||||
|
||||
@@ -673,16 +679,71 @@ FRIGATE_COMPOSE
|
||||
# reverse_proxy block) stops that trust from being spoofed by a
|
||||
# request that reaches Frigate's published host port directly,
|
||||
# bypassing Caddy/Authelia entirely.
|
||||
# Whether to even OFFER this can't just check "$DOCKER_DIR/authelia"
|
||||
# locally — Frigate's own box very often has no local Caddy at all
|
||||
# (configure_caddy_for_service falls back to writing a snippet for
|
||||
# a remote Caddy machine to pick up, confirmed live: this is the
|
||||
# normal shape for a dedicated NVR box), in which case Authelia, if
|
||||
# it exists anywhere, lives on THAT remote Caddy machine instead —
|
||||
# a box this script has no filesystem access to inspect. Default to
|
||||
# "y" only when local Authelia is actually confirmed; otherwise still
|
||||
# offer it (default "n") and sort out local-vs-remote below once the
|
||||
# admin says yes, rather than silently refusing to ask at all.
|
||||
local FRIGATE_USE_AUTHELIA="n" FRIGATE_PROXY_SECRET="" AUTH_CONFIG_BLOCK=""
|
||||
if [ -d "$DOCKER_DIR/authelia" ]; then
|
||||
echo ""
|
||||
prompt_yn "Protect Frigate with Authelia SSO (disables Frigate's own login)? (y/n):" "y" FRIGATE_USE_AUTHELIA
|
||||
fi
|
||||
local _frigate_local_authelia="n"
|
||||
[ -d "$DOCKER_DIR/authelia" ] && _frigate_local_authelia="y"
|
||||
echo ""
|
||||
prompt_yn "Protect Frigate with Authelia SSO (disables Frigate's own login)? (y/n):" "$_frigate_local_authelia" FRIGATE_USE_AUTHELIA
|
||||
|
||||
if [[ "$FRIGATE_USE_AUTHELIA" =~ ^[Yy]$ ]]; then
|
||||
FRIGATE_PROXY_SECRET="${ENV_MAP[FRIGATE_PROXY_AUTH_SECRET]:-$(generate_password 32)}"
|
||||
|
||||
# Local Authelia snippet (import authelia) only actually exists
|
||||
# in the Caddyfile it's imported into if Authelia is on THAT
|
||||
# same machine. When it's on this box, that's this box's own
|
||||
# Caddy — safe to assume. When Caddy itself turns out to be
|
||||
# remote (below), "local" instead means "local to wherever
|
||||
# Caddy is", which this script can't see — so ask, rather than
|
||||
# silently emit an import that would fail Caddy's own reload
|
||||
# with "file to import not found" on that other machine.
|
||||
local _frigate_auth_block=" import authelia"
|
||||
if [ "$_frigate_local_authelia" != "y" ]; then
|
||||
echo ""
|
||||
log_info "No local Authelia on this box — Caddy for Frigate may end up on a"
|
||||
log_info "different machine (decided next)."
|
||||
local _authelia_with_caddy=""
|
||||
prompt_yn " Does Authelia run on that SAME machine as Caddy? (y/n):" "y" _authelia_with_caddy
|
||||
if [[ ! "$_authelia_with_caddy" =~ ^[Yy]$ ]]; then
|
||||
# Genuinely cross-machine: Authelia is a third box,
|
||||
# different from both this one and wherever Caddy ends
|
||||
# up. Needs the explicit header-pinned forward_auth form
|
||||
# — see CLAUDE.md's "forward_auth to a remote Authelia"
|
||||
# note for why the bare "authelia:9091" shortcut can't
|
||||
# be used here and X-Forwarded-Host must be pinned
|
||||
# explicitly (a second Caddy hop otherwise silently
|
||||
# evaluates every domain as if it were auth's own
|
||||
# portal domain — confirmed live, a real incident this
|
||||
# exact snippet shape was written to prevent).
|
||||
local _remote_authelia_domain=""
|
||||
prompt_text " Authelia's own portal domain (e.g. authelia.example.com):" "" _remote_authelia_domain
|
||||
if [ -n "$_remote_authelia_domain" ]; then
|
||||
_frigate_auth_block=" forward_auth https://${_remote_authelia_domain} {
|
||||
uri /api/authz/forward-auth
|
||||
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
|
||||
header_up X-Forwarded-Method {method}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Forwarded-Host {host}
|
||||
header_up X-Forwarded-Uri {uri}
|
||||
}"
|
||||
else
|
||||
log_warning "No domain entered — falling back to 'import authelia', which will fail"
|
||||
log_warning "Caddy's reload unless Authelia is actually local to that Caddy machine."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
configure_caddy_for_service "Frigate" "frigate:5000" "frigate" \
|
||||
" import authelia" \
|
||||
"$_frigate_auth_block" \
|
||||
" header_up X-Proxy-Secret ${FRIGATE_PROXY_SECRET}"
|
||||
if [ "${CADDY_SERVICE_CONFIGURED:-false}" = true ]; then
|
||||
AUTH_CONFIG_BLOCK="auth:
|
||||
@@ -780,6 +841,7 @@ snapshots:
|
||||
FRIGATE_CONFIG
|
||||
fi
|
||||
|
||||
backup_if_exists .env
|
||||
cat > .env << FRIGATE_ENV
|
||||
FRIGATE_MEDIA=$FRIGATE_MEDIA
|
||||
CADDY_NET=$SITE_CADDY_NET
|
||||
|
||||
Reference in New Issue
Block a user