Extend conf_populate.sh with all auto-detectable fields
Adds SSH key (hostname convention), arr path maps (docker volume mounts), Authelia container + config path, boot device storage mode detection, and master.conf HOST identity + Gitea container. Also fixes RADARR_MOVIE_ROOT → RADARR_MOVIES_ROOT to match the variable name used by all other scripts.
This commit is contained in:
+144
-11
@@ -16,16 +16,23 @@
|
|||||||
# AUTO-DETECTED FIELDS
|
# AUTO-DETECTED FIELDS
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
#
|
#
|
||||||
|
# HOST CONF (Configurations/<hostid>.conf)
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────
|
||||||
# HOSTN_OWNER from hostname (strip unRAID- prefix, lowercase)
|
# HOSTN_OWNER from hostname (strip unRAID- prefix, lowercase)
|
||||||
|
# HOSTN_SSH_KEY from hostname convention (/root/.ssh/<owner>_rsync_automation)
|
||||||
|
# HOSTN_STORAGE_MODE_INTERNAL from boot device transport (NVMe/SSD=true, USB=false)
|
||||||
# HOSTN_RADARR_API_KEY from Radarr config.xml (found via docker volume mount)
|
# HOSTN_RADARR_API_KEY from Radarr config.xml (found via docker volume mount)
|
||||||
# HOSTN_RADARR_URL from Radarr config.xml port
|
# HOSTN_RADARR_URL from Radarr config.xml port
|
||||||
|
# HOSTN_RADARR_MOVIES_ROOT from Radarr rootFolder API
|
||||||
|
# HOSTN_RADARR_PATH_MAP from Radarr docker volume mounts vs root folder path
|
||||||
# HOSTN_SONARR_API_KEY from Sonarr config.xml
|
# HOSTN_SONARR_API_KEY from Sonarr config.xml
|
||||||
# HOSTN_SONARR_URL from Sonarr config.xml port
|
# HOSTN_SONARR_URL from Sonarr config.xml port
|
||||||
|
# HOSTN_SONARR_TV_ROOT from Sonarr rootFolder API
|
||||||
|
# HOSTN_SONARR_PATH_MAP from Sonarr docker volume mounts vs root folder path
|
||||||
# HOSTN_LIDARR_API_KEY from Lidarr config.xml
|
# HOSTN_LIDARR_API_KEY from Lidarr config.xml
|
||||||
# HOSTN_LIDARR_URL from Lidarr config.xml port
|
# HOSTN_LIDARR_URL from Lidarr config.xml port
|
||||||
# HOSTN_RADARR_MOVIE_ROOT from Radarr rootFolder API
|
|
||||||
# HOSTN_SONARR_TV_ROOT from Sonarr rootFolder API
|
|
||||||
# HOSTN_LIDARR_MUSIC_ROOT from Lidarr rootFolder API
|
# HOSTN_LIDARR_MUSIC_ROOT from Lidarr rootFolder API
|
||||||
|
# HOSTN_LIDARR_PATH_MAP from Lidarr docker volume mounts vs root folder path
|
||||||
# HOSTN_SABNZBD_API_KEY from sabnzbd.ini
|
# HOSTN_SABNZBD_API_KEY from sabnzbd.ini
|
||||||
# HOSTN_SABNZBD_URL from sabnzbd.ini port
|
# HOSTN_SABNZBD_URL from sabnzbd.ini port
|
||||||
# HOSTN_SLSKD_API_KEY from slskd config.yml
|
# HOSTN_SLSKD_API_KEY from slskd config.yml
|
||||||
@@ -38,8 +45,15 @@
|
|||||||
# HOSTN_JELLYFIN_CONTAINER fuzzy match from docker ps
|
# HOSTN_JELLYFIN_CONTAINER fuzzy match from docker ps
|
||||||
# HOSTN_JELLYFIN_URL from docker port binding
|
# HOSTN_JELLYFIN_URL from docker port binding
|
||||||
# HOSTN_TRANSCODE_SSD from Emby/Jellyfin container /transcode volume mount
|
# HOSTN_TRANSCODE_SSD from Emby/Jellyfin container /transcode volume mount
|
||||||
|
# HOSTN_AUTHELIA_CONTAINER fuzzy match from docker ps
|
||||||
|
# HOSTN_AUTHELIA_CONFIG from Authelia container /config volume mount
|
||||||
# HOSTN_SYS_WATCHDOG_NIC from ip route default gateway interface
|
# HOSTN_SYS_WATCHDOG_NIC from ip route default gateway interface
|
||||||
#
|
#
|
||||||
|
# MASTER CONF (Configurations/master.conf)
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────
|
||||||
|
# HOST1 / HOST2 local hostname written to MY_ID slot
|
||||||
|
# GITEA_CONTAINER fuzzy match from docker ps
|
||||||
|
#
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
# RUNTIME MODES
|
# RUNTIME MODES
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
@@ -74,6 +88,8 @@ detect_hosts
|
|||||||
CONF_FILE="$SCRIPTS_ROOT/Configurations/${MY_ID,,}.conf"
|
CONF_FILE="$SCRIPTS_ROOT/Configurations/${MY_ID,,}.conf"
|
||||||
[[ ! -f "$CONF_FILE" ]] && { error "Conf file not found: $CONF_FILE"; exit 1; }
|
[[ ! -f "$CONF_FILE" ]] && { error "Conf file not found: $CONF_FILE"; exit 1; }
|
||||||
|
|
||||||
|
MASTER_CONF="$SCRIPTS_ROOT/Configurations/master.conf"
|
||||||
|
|
||||||
log "$ICON_GEAR Config: conf=${CONF_FILE} overwrite=${OVERWRITE:-false} no-push=${NO_PUSH:-false}"
|
log "$ICON_GEAR Config: conf=${CONF_FILE} overwrite=${OVERWRITE:-false} no-push=${NO_PUSH:-false}"
|
||||||
|
|
||||||
UPDATED=0
|
UPDATED=0
|
||||||
@@ -85,13 +101,14 @@ echo ""
|
|||||||
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made"
|
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made"
|
||||||
[[ "$OVERWRITE" == true ]] && warn "OVERWRITE mode — existing values will be replaced"
|
[[ "$OVERWRITE" == true ]] && warn "OVERWRITE mode — existing values will be replaced"
|
||||||
|
|
||||||
# ── Helper: write a var into conf if empty (or --overwrite) ──────────────────
|
# ── Helper: write a var into a conf file if empty (or --overwrite) ────────────
|
||||||
|
# Optional 4th arg: target file (defaults to $CONF_FILE)
|
||||||
_set_conf_var() {
|
_set_conf_var() {
|
||||||
local var_name="$1" value="$2" label="$3"
|
local var_name="$1" value="$2" label="$3" target="${4:-$CONF_FILE}"
|
||||||
[[ -z "$value" ]] && return
|
[[ -z "$value" ]] && return
|
||||||
|
|
||||||
local current
|
local current
|
||||||
current=$(grep -oP "(?<=^\s*${var_name}=\")[^\"]*" "$CONF_FILE" 2>/dev/null | head -1)
|
current=$(grep -oP "(?<=^\s*${var_name}=\")[^\"]*" "$target" 2>/dev/null | head -1)
|
||||||
|
|
||||||
if [[ -n "$current" ]] && [[ "$OVERWRITE" == false ]]; then
|
if [[ -n "$current" ]] && [[ "$OVERWRITE" == false ]]; then
|
||||||
log "$label: already set (${current:0:8}…) — skipping"
|
log "$label: already set (${current:0:8}…) — skipping"
|
||||||
@@ -104,15 +121,59 @@ _set_conf_var() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep -q "^\s*${var_name}=" "$CONF_FILE"; then
|
if grep -q "^\s*${var_name}=" "$target"; then
|
||||||
sed -i "s|^\(\s*${var_name}\s*=\s*\)\"[^\"]*\"|\1\"${value}\"|" "$CONF_FILE"
|
sed -i "s|^\(\s*${var_name}\s*=\s*\)\"[^\"]*\"|\1\"${value}\"|" "$target"
|
||||||
else
|
else
|
||||||
printf '\n %s="%s"\n' "$var_name" "$value" >> "$CONF_FILE"
|
printf '\n %s="%s"\n' "$var_name" "$value" >> "$target"
|
||||||
fi
|
fi
|
||||||
info "$label: set ✅"
|
info "$label: set ✅"
|
||||||
(( UPDATED++ ))
|
(( UPDATED++ ))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Helper: add or update an entry in a declare -A map block ──────────────────
|
||||||
|
# Inserts [key]="value" before the closing ) of the named map in $CONF_FILE.
|
||||||
|
# Skips if an identical uncommented entry already exists (unless --overwrite).
|
||||||
|
_set_conf_map_entry() {
|
||||||
|
local map_name="$1" key="$2" value="$3" label="$4"
|
||||||
|
[[ -z "$key" || -z "$value" ]] && return
|
||||||
|
|
||||||
|
if grep -qP "^\s*\[\"${key//\//\\/}\"\]=" "$CONF_FILE" 2>/dev/null; then
|
||||||
|
if [[ "$OVERWRITE" == false ]]; then
|
||||||
|
log "$label: already set — skipping"
|
||||||
|
(( SKIPPED++ ))
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
[[ "$DRY_RUN" == true ]] && { warn "DRY RUN — would update ${map_name}[\"${key}\"]"; return; }
|
||||||
|
sed -i "s|^\(\s*\)\[\"${key}\"\]=\"[^\"]*\"|\1[\"${key}\"]=\"${value}\"|" "$CONF_FILE"
|
||||||
|
info "$label: set ✅"
|
||||||
|
(( UPDATED++ ))
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "declare -A ${map_name}=" "$CONF_FILE" 2>/dev/null; then
|
||||||
|
warn "$label: ${map_name} not found in conf — skipping"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ "$DRY_RUN" == true ]] && { warn "DRY RUN — would set ${map_name}[\"${key}\"] = \"${value}\""; return; }
|
||||||
|
|
||||||
|
awk -v mapname="${map_name}" -v key="$key" -v val="$value" '
|
||||||
|
BEGIN { in_map=0; done=0 }
|
||||||
|
!done && index($0, "declare -A " mapname) { in_map=1 }
|
||||||
|
in_map && !done && /^\s*\)/ {
|
||||||
|
printf " [\"%s\"]=\"%s\"\n", key, val
|
||||||
|
done=1; in_map=0
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
' "$CONF_FILE" > "${CONF_FILE}.tmp" && mv "${CONF_FILE}.tmp" "$CONF_FILE" || {
|
||||||
|
rm -f "${CONF_FILE}.tmp"
|
||||||
|
warn "$label: failed to update ${map_name}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
info "$label: set ✅"
|
||||||
|
(( UPDATED++ ))
|
||||||
|
}
|
||||||
|
|
||||||
# ── Helper: find arr config dir via docker volume mount ───────────────────────
|
# ── Helper: find arr config dir via docker volume mount ───────────────────────
|
||||||
_arr_config_dir() {
|
_arr_config_dir() {
|
||||||
local pattern="$1"
|
local pattern="$1"
|
||||||
@@ -150,19 +211,35 @@ _docker_volume_host() {
|
|||||||
'.[0].Mounts[]? | select(.Destination == $d) | .Source' 2>/dev/null | head -1
|
'.[0].Mounts[]? | select(.Destination == $d) | .Source' 2>/dev/null | head -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Helper: find host↔container path mapping for a given container path ───────
|
||||||
|
# Finds the most specific mount whose destination is a prefix of container_path
|
||||||
|
# and where source != destination (i.e. an actual remapping exists).
|
||||||
|
# Outputs "source|destination" or nothing if no remapping found.
|
||||||
|
_docker_path_map() {
|
||||||
|
local container="$1" container_path="$2"
|
||||||
|
docker inspect "$container" 2>/dev/null | \
|
||||||
|
jq -r '.[0].Mounts[]? | select(.Destination != "/config") | "\(.Source)|\(.Destination)"' \
|
||||||
|
2>/dev/null | \
|
||||||
|
awk -F'|' -v target="$container_path" '
|
||||||
|
$1 != $2 && length($2) > 0 && index(target, $2) == 1 { print length($2), $0 }
|
||||||
|
' | sort -rn | head -1 | cut -d' ' -f2-
|
||||||
|
}
|
||||||
|
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
# ── Owner short name ──────────────────────────────────────────────────────────────────────────
|
# ── Owner short name + SSH key ────────────────────────────────────────────────────────────────
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
|
|
||||||
owner=$(echo "$LOCAL_SERVER_NAME" | sed 's/^[Uu][Nn][Rr][Aa][Ii][Dd]-//i' | tr '[:upper:]' '[:lower:]')
|
owner=$(echo "$LOCAL_SERVER_NAME" | sed 's/^[Uu][Nn][Rr][Aa][Ii][Dd]-//i' | tr '[:upper:]' '[:lower:]')
|
||||||
_set_conf_var "${MY_ID}_OWNER" "$owner" "Owner short name"
|
_set_conf_var "${MY_ID}_OWNER" "$owner" "Owner short name"
|
||||||
|
_set_conf_var "${MY_ID}_SSH_KEY" "/root/.ssh/${owner}_rsync_automation" "SSH key path"
|
||||||
|
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
# ── Arr API keys + URLs + root paths ─────────────────────────────────────────────────────────
|
# ── Arr API keys + URLs + root paths + path maps ──────────────────────────────────────────────
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
|
|
||||||
for arr in radarr sonarr lidarr; do
|
for arr in radarr sonarr lidarr; do
|
||||||
arr_upper="${arr^^}"
|
arr_upper="${arr^^}"
|
||||||
|
arr_container=$(docker ps -a --format '{{.Names}}' 2>/dev/null | grep -im1 "^${arr}")
|
||||||
config_dir=$(_arr_config_dir "$arr") || {
|
config_dir=$(_arr_config_dir "$arr") || {
|
||||||
log "${arr_upper}: no running container found — skipping"
|
log "${arr_upper}: no running container found — skipping"
|
||||||
continue
|
continue
|
||||||
@@ -189,10 +266,23 @@ for arr in radarr sonarr lidarr; do
|
|||||||
root_path=$(echo "$root_json" | jq -r '.[0].path // empty' 2>/dev/null)
|
root_path=$(echo "$root_json" | jq -r '.[0].path // empty' 2>/dev/null)
|
||||||
|
|
||||||
case "$arr" in
|
case "$arr" in
|
||||||
radarr) _set_conf_var "${MY_ID}_RADARR_MOVIE_ROOT" "$root_path" "Radarr movie root" ;;
|
radarr) _set_conf_var "${MY_ID}_RADARR_MOVIES_ROOT" "$root_path" "Radarr movies root" ;;
|
||||||
sonarr) _set_conf_var "${MY_ID}_SONARR_TV_ROOT" "$root_path" "Sonarr TV root" ;;
|
sonarr) _set_conf_var "${MY_ID}_SONARR_TV_ROOT" "$root_path" "Sonarr TV root" ;;
|
||||||
lidarr) _set_conf_var "${MY_ID}_LIDARR_MUSIC_ROOT" "$root_path" "Lidarr music root" ;;
|
lidarr) _set_conf_var "${MY_ID}_LIDARR_MUSIC_ROOT" "$root_path" "Lidarr music root" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if [[ -n "$root_path" && -n "$arr_container" ]]; then
|
||||||
|
map_entry=$(_docker_path_map "$arr_container" "$root_path")
|
||||||
|
if [[ -n "$map_entry" ]]; then
|
||||||
|
map_src="${map_entry%%|*}"
|
||||||
|
map_dest="${map_entry##*|}"
|
||||||
|
case "$arr" in
|
||||||
|
radarr) _set_conf_map_entry "${MY_ID}_RADARR_PATH_MAP" "$map_dest" "$map_src" "Radarr path map" ;;
|
||||||
|
sonarr) _set_conf_map_entry "${MY_ID}_SONARR_PATH_MAP" "$map_dest" "$map_src" "Sonarr path map" ;;
|
||||||
|
lidarr) _set_conf_map_entry "${MY_ID}_LIDARR_PATH_MAP" "$map_dest" "$map_src" "Lidarr path map" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -276,6 +366,18 @@ done
|
|||||||
[[ -n "$transcode_dir" ]] && \
|
[[ -n "$transcode_dir" ]] && \
|
||||||
_set_conf_var "${MY_ID}_TRANSCODE_SSD" "${transcode_dir%/}/" "Transcode SSD path"
|
_set_conf_var "${MY_ID}_TRANSCODE_SSD" "${transcode_dir%/}/" "Transcode SSD path"
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ── Authelia container + config path ──────────────────────────────────────────────────────────
|
||||||
|
# ==============================================================================================
|
||||||
|
|
||||||
|
authelia_container=$(docker ps -a --format '{{.Names}}' 2>/dev/null | grep -im1 "authelia")
|
||||||
|
if [[ -n "$authelia_container" ]]; then
|
||||||
|
_set_conf_var "${MY_ID}_AUTHELIA_CONTAINER" "$authelia_container" "Authelia container"
|
||||||
|
authelia_cfg_dir=$(_docker_volume_host "$authelia_container" "/config")
|
||||||
|
[[ -n "$authelia_cfg_dir" ]] && \
|
||||||
|
_set_conf_var "${MY_ID}_AUTHELIA_CONFIG" "${authelia_cfg_dir}/configuration.yml" "Authelia config path"
|
||||||
|
fi
|
||||||
|
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
# ── Network interface ─────────────────────────────────────────────────────────────────────────
|
# ── Network interface ─────────────────────────────────────────────────────────────────────────
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
@@ -283,6 +385,37 @@ done
|
|||||||
nic=$(ip route show default 2>/dev/null | grep -oP '(?<=dev )\S+' | head -1)
|
nic=$(ip route show default 2>/dev/null | grep -oP '(?<=dev )\S+' | head -1)
|
||||||
_set_conf_var "${MY_ID}_SYS_WATCHDOG_NIC" "$nic" "Default NIC"
|
_set_conf_var "${MY_ID}_SYS_WATCHDOG_NIC" "$nic" "Default NIC"
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ── Storage mode (internal NVMe/SSD vs USB flash boot) ───────────────────────────────────────
|
||||||
|
# ==============================================================================================
|
||||||
|
|
||||||
|
boot_src=$(findmnt -n -o SOURCE /boot 2>/dev/null)
|
||||||
|
if [[ -n "$boot_src" ]]; then
|
||||||
|
boot_dev=$(lsblk -no PKNAME "$boot_src" 2>/dev/null | head -1)
|
||||||
|
if [[ "$boot_dev" =~ ^nvme ]]; then
|
||||||
|
storage_mode=true
|
||||||
|
else
|
||||||
|
boot_transport=$(cat "/sys/block/${boot_dev}/device/transport" 2>/dev/null)
|
||||||
|
[[ "$boot_transport" == "usb" ]] && storage_mode=false || storage_mode=true
|
||||||
|
fi
|
||||||
|
_set_conf_var "${MY_ID}_STORAGE_MODE_INTERNAL" "$storage_mode" \
|
||||||
|
"Storage mode (NVMe/SSD=true, USB=false)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ── Master conf: host identity + Gitea container ─────────────────────────────────────────────
|
||||||
|
# ==============================================================================================
|
||||||
|
|
||||||
|
if [[ -f "$MASTER_CONF" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo " ── Master conf ──"
|
||||||
|
_set_conf_var "$MY_ID" "$LOCAL_SERVER_NAME" "master.conf ${MY_ID} hostname" "$MASTER_CONF"
|
||||||
|
|
||||||
|
gitea_container=$(docker ps -a --format '{{.Names}}' 2>/dev/null | grep -im1 "gitea")
|
||||||
|
[[ -n "$gitea_container" ]] && \
|
||||||
|
_set_conf_var "GITEA_CONTAINER" "$gitea_container" "Gitea container" "$MASTER_CONF"
|
||||||
|
fi
|
||||||
|
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
# ── Summary + push ────────────────────────────────────────────────────────────────────────────
|
# ── Summary + push ────────────────────────────────────────────────────────────────────────────
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user