frigate.sh: interactive camera wizard generates go2rtc + cameras config

Previously Frigate always wrote a placeholder config.yml the operator had
to hand-edit to add cameras. Now install_frigate prompts to add cameras
one at a time (name, RTSP IP/port/user/password/path, optional sub-stream,
enabled, notifications), matching the go2rtc + cameras structure used in
production frigate configs:

- Each camera gets a go2rtc stream entry (+ optional _sub for detection)
  and a cameras: block with ffmpeg inputs/roles, detect, notifications
- RTSP credentials/IPs are written to .env as FRIGATE_* variables (first
  camera gets FRIGATE_RTSP_USER/PASSWORD, later cameras get numbered
  suffixes _1, _2, ... to avoid collisions) and referenced in config.yml
  via Frigate's {FRIGATE_VAR} substitution syntax — secrets never appear
  in the YAML directly
- docker-compose.yml now includes env_file: .env so those vars actually
  reach the container for substitution to work
- Skipping all camera prompts falls back to the original starter
  config.yml for manual editing, preserving existing behavior
- README and DRY-RUN summary updated to reflect the new flow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LQJBvqzXeyuhhAcAA3Q5Wq
This commit is contained in:
Claude
2026-07-01 19:49:26 +00:00
parent 9cf3765f83
commit 7dc9a762a0
+172 -13
View File
@@ -9,7 +9,10 @@
# Ported from ubuntu-post-install-24.04-crowdsec.sh (# ---- FRIGATE NVR ----).
# Own ~/docker/frigate/ with a standalone docker-compose.yml + .env + config.yml.
# Auto-enables /dev/dri/renderD128 for hardware detection (Intel/AMD) when present.
# YOU MUST edit config/config.yml to add your camera RTSP streams before starting.
# Interactively prompts for cameras — RTSP user/pass/IP go in .env as
# FRIGATE_* vars, which config.yml references via Frigate's {FRIGATE_VAR}
# substitution syntax so credentials never appear in the YAML directly.
# Skip the camera prompts to get a starter config.yml to edit by hand.
# ── Standalone bootstrap ──────────────────────────────────────────────────────
# Detected when the script is executed directly rather than sourced by setup.sh.
@@ -205,7 +208,8 @@ install_frigate() {
echo " - Create $FRIGATE_DIR with docker-compose.yml + .env + config/config.yml"
echo " - Auto-enable /dev/dri/renderD128 for GPU-assisted detection if present"
echo " - Expose ports 5000 (web), 8554 (RTSP restream), 8555 (WebRTC)"
echo " - Write a starter config.yml — edit to add camera streams before starting"
echo " - Prompt to add cameras interactively (RTSP creds go in .env)"
echo " or write a starter config.yml if none are added"
echo " - Offer a Caddy reverse proxy and to start the container"
return 0
fi
@@ -258,6 +262,8 @@ services:
restart: unless-stopped
privileged: true
shm_size: "256mb"
env_file:
- .env
environment:
- TZ=$TZ_VAL
$DEVICE_BLOCK
@@ -276,15 +282,117 @@ $DEVICE_BLOCK
${_CADDY_NET_BLOCK}${_CADDY_NET_SECTION}
FRIGATE_COMPOSE
cat > .env << FRIGATE_ENV
FRIGATE_MEDIA=$FRIGATE_MEDIA
CADDY_NET=$SITE_CADDY_NET
FRIGATE_ENV
mkdir -p config
mkdir -p "$FRIGATE_MEDIA"
cat > config/config.yml << 'FRIGATE_CONFIG'
# ── Camera wizard ────────────────────────────────────────────────────────
# Credentials/IPs go in .env as FRIGATE_* variables; Frigate substitutes
# any {FRIGATE_VAR} placeholder in config.yml from its container env at
# startup, so RTSP secrets never need to be typed into the YAML directly.
local GO2RTC_BLOCK="" CAMERAS_BLOCK="" ENV_CAM_VARS="" CAM_INDEX=0
while true; do
local ADD_CAM=""
if [ "$CAM_INDEX" -eq 0 ]; then
prompt_yn "Add a camera now? (y/n):" "y" ADD_CAM
else
prompt_yn "Add another camera? (y/n):" "n" ADD_CAM
fi
[[ "$ADD_CAM" =~ ^[Yy]$ ]] || break
local CAM_NAME=""
prompt_text " Camera name (e.g. front_door):" "camera$((CAM_INDEX+1))" CAM_NAME
CAM_NAME="$(echo "$CAM_NAME" | tr '[:upper:] ' '[:lower:]_' | tr -cd 'a-z0-9_')"
CAM_NAME="${CAM_NAME:-camera$((CAM_INDEX+1))}"
local CAM_UPPER="${CAM_NAME^^}"
local CAM_IP=""
prompt_text " ${CAM_NAME} RTSP IP address:" "" CAM_IP
local CAM_PORT=""
prompt_text " ${CAM_NAME} RTSP port [554]:" "554" CAM_PORT
local CAM_USER=""
prompt_text " ${CAM_NAME} RTSP username:" "admin" CAM_USER
local CAM_PASS=""
prompt_text " ${CAM_NAME} RTSP password (blank = generate one):" "" CAM_PASS
[ -z "$CAM_PASS" ] && CAM_PASS="$(generate_password 20)"
local CAM_PATH=""
prompt_text " ${CAM_NAME} RTSP path (use {sub} for main/sub-stream marker) [/cam/realmonitor?channel=1&subtype={sub}#backchannel=0]:" \
"/cam/realmonitor?channel=1&subtype={sub}#backchannel=0" CAM_PATH
local CAM_SUBSTREAM=""
prompt_yn " Add a lower-res sub-stream for detection? (y/n):" "y" CAM_SUBSTREAM
local CAM_ENABLED=""
prompt_yn " Enable ${CAM_NAME} immediately? (y/n):" "y" CAM_ENABLED
local CAM_NOTIFY=""
prompt_yn " Enable notifications for ${CAM_NAME}? (y/n):" "n" CAM_NOTIFY
# First camera's credentials get no suffix (FRIGATE_RTSP_USER); each
# camera after that gets an index suffix (…USER1, …USER2, …) so
# cameras with different logins don't collide.
local IDX_SUFFIX=""
[ "$CAM_INDEX" -gt 0 ] && IDX_SUFFIX="$CAM_INDEX"
local VAR_USER="FRIGATE_RTSP_USER${IDX_SUFFIX}"
local VAR_PASS="FRIGATE_RTSP_PASSWORD${IDX_SUFFIX}"
local VAR_IP="FRIGATE_${CAM_UPPER}_IP"
ENV_CAM_VARS="${ENV_CAM_VARS}${VAR_USER}=${CAM_USER}
${VAR_PASS}=${CAM_PASS}
${VAR_IP}=${CAM_IP}
"
local MAIN_PATH="${CAM_PATH//\{sub\}/0}"
local SUB_PATH="${CAM_PATH//\{sub\}/1}"
GO2RTC_BLOCK="${GO2RTC_BLOCK} ${CAM_NAME}:
- rtsp://{${VAR_USER}}:{${VAR_PASS}}@{${VAR_IP}}:${CAM_PORT}${MAIN_PATH}
"
local INPUTS_BLOCK
if [[ "$CAM_SUBSTREAM" =~ ^[Yy]$ ]]; then
GO2RTC_BLOCK="${GO2RTC_BLOCK} ${CAM_NAME}_sub:
- rtsp://{${VAR_USER}}:{${VAR_PASS}}@{${VAR_IP}}:${CAM_PORT}${SUB_PATH}
"
INPUTS_BLOCK=" - path: rtsp://127.0.0.1:8554/${CAM_NAME}
input_args: preset-rtsp-restream
roles:
- record
- path: rtsp://127.0.0.1:8554/${CAM_NAME}_sub
input_args: preset-rtsp-restream
roles:
- detect"
else
INPUTS_BLOCK=" - path: rtsp://127.0.0.1:8554/${CAM_NAME}
input_args: preset-rtsp-restream
roles:
- detect
- record"
fi
GO2RTC_BLOCK="${GO2RTC_BLOCK}
"
local ENABLED_VAL="false"; [[ "$CAM_ENABLED" =~ ^[Yy]$ ]] && ENABLED_VAL="true"
local NOTIFY_VAL="false"; [[ "$CAM_NOTIFY" =~ ^[Yy]$ ]] && NOTIFY_VAL="true"
CAMERAS_BLOCK="${CAMERAS_BLOCK} ${CAM_NAME}:
enabled: ${ENABLED_VAL}
ffmpeg:
inputs:
${INPUTS_BLOCK}
detect:
enabled: true
width: 640
height: 480
fps: 5
notifications:
enabled: ${NOTIFY_VAL}
"
CAM_INDEX=$((CAM_INDEX+1))
done
if [ "$CAM_INDEX" -eq 0 ]; then
# No cameras entered — write a starter config the operator edits by hand.
cat > config/config.yml << 'FRIGATE_CONFIG'
# Frigate Configuration — Docs: https://docs.frigate.video
#
# ⚠️ YOU MUST EDIT THIS FILE to add your cameras before starting Frigate.
@@ -319,6 +427,44 @@ snapshots:
retain:
default: 7
FRIGATE_CONFIG
else
cat > config/config.yml << FRIGATE_CONFIG
# Frigate Configuration — Docs: https://docs.frigate.video
#
# RTSP credentials/IPs come from .env — Frigate substitutes {FRIGATE_VAR}
# placeholders below from the container's environment at startup.
mqtt:
enabled: false # Set to true and configure if you use Home Assistant
go2rtc:
streams:
${GO2RTC_BLOCK}
cameras:
${CAMERAS_BLOCK}
detectors:
default:
type: cpu # Change to 'edgetpu' for Coral TPU or 'openvino' for Intel GPU
record:
enabled: true
retain:
days: 7
mode: motion
snapshots:
enabled: true
retain:
default: 7
FRIGATE_CONFIG
fi
cat > .env << FRIGATE_ENV
FRIGATE_MEDIA=$FRIGATE_MEDIA
CADDY_NET=$SITE_CADDY_NET
${ENV_CAM_VARS}
FRIGATE_ENV
chmod 600 .env
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$FRIGATE_DIR"
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$FRIGATE_MEDIA" 2>/dev/null || true
@@ -336,7 +482,8 @@ security cameras. Detects people, cars, animals, and more.
- RTSP restream: port 8554
- WebRTC: port 8555
- Recordings: \`$FRIGATE_MEDIA\`
- Config: \`config/config.yml\` — **add your camera RTSP streams here**
- Config: \`config/config.yml\` — cameras configured during install ($CAM_INDEX added)
- Credentials: \`.env\` — RTSP user/pass/IP per camera as FRIGATE_* variables
## Manage
\`\`\`bash
@@ -347,8 +494,14 @@ docker compose logs -f # logs
docker compose pull && docker compose up -d # update
\`\`\`
## Adding/editing cameras later
Re-run the installer (\`sudo ./setup.sh frigate\`) to add more cameras through
the same wizard, or edit \`config/config.yml\` and \`.env\` by hand — camera
credentials in config.yml use Frigate's \`{FRIGATE_VAR}\` substitution syntax,
resolved from \`.env\` at container startup.
## First steps
1. Edit \`config/config.yml\` — add your camera RTSP URLs under \`cameras:\`
1. Review \`config/config.yml\` — adjust detection zones, masks, retention
2. Start Frigate: \`docker compose up -d\`
3. Open http://localhost:5000 to view cameras and configure detection zones
@@ -359,17 +512,23 @@ docker compose pull && docker compose up -d # update
MD
echo ""
log_warning "Edit config/config.yml to add your camera RTSP streams before starting."
local START_DEFAULT="n"
if [ "$CAM_INDEX" -eq 0 ]; then
log_warning "No cameras added — edit config/config.yml to add camera RTSP streams before starting."
else
log_success "$CAM_INDEX camera(s) configured."
START_DEFAULT="y"
fi
echo ""
local START_FRIGATE=""
prompt_yn "Start Frigate now anyway? (y/n):" "n" START_FRIGATE
prompt_yn "Start Frigate now? (y/n):" "$START_DEFAULT" START_FRIGATE
if [ "$START_FRIGATE" = "y" ] || [ "$START_FRIGATE" = "Y" ]; then
docker compose up -d && log_success "Frigate started" || log_warning "Failed to start — check: docker compose logs"
fi
echo ""
echo " Access at: http://localhost:5000"
echo " Config: $FRIGATE_DIR/config/config.yml (add cameras here)"
echo " Config: $FRIGATE_DIR/config/config.yml"
echo ""
}