fix: TrueNAS SCALE 24.04+ has read-only /usr/local/bin
On TrueNAS SCALE 24.04+, the root filesystem including /usr/local/bin is read-only. The installer now tries multiple locations for the runtime binary: 1. Execute directly from /data (if no noexec mount) 2. /usr/local/bin (older TrueNAS versions) 3. /root/bin (TrueNAS SCALE 24.04+) 4. /var/tmp (last resort) The bootstrap script is also updated to use the determined runtime location rather than hardcoding /usr/local/bin. Related to #801
This commit is contained in:
parent
95ca0c0e67
commit
db9955e187
1 changed files with 56 additions and 16 deletions
|
|
@ -582,8 +582,8 @@ fi
|
||||||
# 4. TrueNAS SCALE (immutable root, uses systemd but needs special persistence)
|
# 4. TrueNAS SCALE (immutable root, uses systemd but needs special persistence)
|
||||||
# TrueNAS SCALE wipes /etc/systemd/system on upgrades, so we store the service
|
# TrueNAS SCALE wipes /etc/systemd/system on upgrades, so we store the service
|
||||||
# in /data and create an Init/Shutdown task to recreate the symlink on boot.
|
# in /data and create an Init/Shutdown task to recreate the symlink on boot.
|
||||||
# Note: /data may have exec=off on some TrueNAS systems, so we copy the binary
|
# Note: /data may have exec=off on some TrueNAS systems. On TrueNAS SCALE 24.04+,
|
||||||
# to /usr/local/bin (tmpfs, allows exec) at runtime while storing in /data for persistence.
|
# /usr/local/bin is also read-only. We try multiple runtime locations.
|
||||||
if [[ "$TRUENAS" == true ]]; then
|
if [[ "$TRUENAS" == true ]]; then
|
||||||
log_info "Configuring TrueNAS SCALE installation..."
|
log_info "Configuring TrueNAS SCALE installation..."
|
||||||
|
|
||||||
|
|
@ -591,10 +591,7 @@ if [[ "$TRUENAS" == true ]]; then
|
||||||
mkdir -p "$TRUENAS_STATE_DIR"
|
mkdir -p "$TRUENAS_STATE_DIR"
|
||||||
mkdir -p "$TRUENAS_LOG_DIR"
|
mkdir -p "$TRUENAS_LOG_DIR"
|
||||||
|
|
||||||
# TrueNAS stores binary in /data for persistence, but runs from /usr/local/bin
|
|
||||||
# because /data may have exec=off. The bootstrap script copies on each boot.
|
|
||||||
TRUENAS_STORED_BINARY="$TRUENAS_STATE_DIR/${BINARY_NAME}"
|
TRUENAS_STORED_BINARY="$TRUENAS_STATE_DIR/${BINARY_NAME}"
|
||||||
TRUENAS_RUNTIME_BINARY="/usr/local/bin/${BINARY_NAME}"
|
|
||||||
|
|
||||||
# Move binary to persistent storage location
|
# Move binary to persistent storage location
|
||||||
if [[ -f "${INSTALL_DIR}/${BINARY_NAME}" ]] && [[ "$INSTALL_DIR" == "$TRUENAS_STATE_DIR" ]]; then
|
if [[ -f "${INSTALL_DIR}/${BINARY_NAME}" ]] && [[ "$INSTALL_DIR" == "$TRUENAS_STATE_DIR" ]]; then
|
||||||
|
|
@ -605,9 +602,47 @@ if [[ "$TRUENAS" == true ]]; then
|
||||||
fi
|
fi
|
||||||
chmod +x "$TRUENAS_STORED_BINARY"
|
chmod +x "$TRUENAS_STORED_BINARY"
|
||||||
|
|
||||||
# Copy to runtime location (tmpfs, allows exec)
|
# Determine runtime binary location - try executing from /data first
|
||||||
cp "$TRUENAS_STORED_BINARY" "$TRUENAS_RUNTIME_BINARY"
|
# TrueNAS SCALE 24.04+ has read-only /usr/local/bin, so we need alternatives
|
||||||
chmod +x "$TRUENAS_RUNTIME_BINARY"
|
TRUENAS_RUNTIME_BINARY=""
|
||||||
|
|
||||||
|
# Test if /data allows execution (no noexec mount option)
|
||||||
|
if "$TRUENAS_STORED_BINARY" --version >/dev/null 2>&1; then
|
||||||
|
log_info "Binary can execute from /data - using direct execution."
|
||||||
|
TRUENAS_RUNTIME_BINARY="$TRUENAS_STORED_BINARY"
|
||||||
|
else
|
||||||
|
# /data has noexec, need to copy to an executable location
|
||||||
|
# Try locations in order of preference
|
||||||
|
for RUNTIME_DIR in "/usr/local/bin" "/root/bin" "/var/tmp"; do
|
||||||
|
if [[ "$RUNTIME_DIR" == "/root/bin" ]]; then
|
||||||
|
mkdir -p "$RUNTIME_DIR" 2>/dev/null || continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test if we can write and execute from this location
|
||||||
|
TEST_FILE="${RUNTIME_DIR}/.pulse-exec-test-$$"
|
||||||
|
if cp "$TRUENAS_STORED_BINARY" "$TEST_FILE" 2>/dev/null && \
|
||||||
|
chmod +x "$TEST_FILE" 2>/dev/null && \
|
||||||
|
"$TEST_FILE" --version >/dev/null 2>&1; then
|
||||||
|
rm -f "$TEST_FILE"
|
||||||
|
TRUENAS_RUNTIME_BINARY="${RUNTIME_DIR}/${BINARY_NAME}"
|
||||||
|
log_info "Using ${RUNTIME_DIR} for binary execution."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
rm -f "$TEST_FILE" 2>/dev/null
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$TRUENAS_RUNTIME_BINARY" ]]; then
|
||||||
|
log_error "Could not find a writable location that allows execution."
|
||||||
|
log_error "Tried: /data (noexec), /usr/local/bin (read-only), /root/bin, /var/tmp"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy to runtime location if different from storage location
|
||||||
|
if [[ "$TRUENAS_RUNTIME_BINARY" != "$TRUENAS_STORED_BINARY" ]]; then
|
||||||
|
cp "$TRUENAS_STORED_BINARY" "$TRUENAS_RUNTIME_BINARY"
|
||||||
|
chmod +x "$TRUENAS_RUNTIME_BINARY"
|
||||||
|
fi
|
||||||
|
|
||||||
# Build command line args
|
# Build command line args
|
||||||
build_exec_args
|
build_exec_args
|
||||||
|
|
@ -647,20 +682,20 @@ EOF
|
||||||
chmod 600 "$TRUENAS_ENV_FILE"
|
chmod 600 "$TRUENAS_ENV_FILE"
|
||||||
|
|
||||||
# Create bootstrap script that runs on boot
|
# Create bootstrap script that runs on boot
|
||||||
# This copies the binary from /data to /usr/local/bin and recreates the systemd symlink
|
# This script handles the runtime binary location and recreates the systemd symlink
|
||||||
cat > "$TRUENAS_BOOTSTRAP_SCRIPT" <<'BOOTSTRAP'
|
cat > "$TRUENAS_BOOTSTRAP_SCRIPT" <<'BOOTSTRAP'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Pulse Agent Bootstrap for TrueNAS SCALE
|
# Pulse Agent Bootstrap for TrueNAS SCALE
|
||||||
# This script is called by TrueNAS Init/Shutdown task on boot.
|
# This script is called by TrueNAS Init/Shutdown task on boot.
|
||||||
# It copies the binary from /data to /usr/local/bin (tmpfs, allows exec)
|
# It ensures the binary is in an executable location and recreates the
|
||||||
# and recreates the systemd symlink (which is wiped on TrueNAS upgrades).
|
# systemd symlink (which is wiped on TrueNAS upgrades).
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
SERVICE_NAME="pulse-agent"
|
SERVICE_NAME="pulse-agent"
|
||||||
STATE_DIR="STATE_DIR_PLACEHOLDER"
|
STATE_DIR="STATE_DIR_PLACEHOLDER"
|
||||||
STORED_BINARY="${STATE_DIR}/pulse-agent"
|
STORED_BINARY="${STATE_DIR}/pulse-agent"
|
||||||
RUNTIME_BINARY="/usr/local/bin/pulse-agent"
|
RUNTIME_BINARY="RUNTIME_BINARY_PLACEHOLDER"
|
||||||
SERVICE_STORAGE="${STATE_DIR}/pulse-agent.service"
|
SERVICE_STORAGE="${STATE_DIR}/pulse-agent.service"
|
||||||
SYSTEMD_LINK="/etc/systemd/system/${SERVICE_NAME}.service"
|
SYSTEMD_LINK="/etc/systemd/system/${SERVICE_NAME}.service"
|
||||||
|
|
||||||
|
|
@ -674,9 +709,13 @@ if [[ ! -f "$SERVICE_STORAGE" ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy binary from persistent storage to runtime location (tmpfs allows exec)
|
# If runtime binary is different from stored binary, copy it
|
||||||
cp "$STORED_BINARY" "$RUNTIME_BINARY"
|
if [[ "$RUNTIME_BINARY" != "$STORED_BINARY" ]]; then
|
||||||
chmod +x "$RUNTIME_BINARY"
|
# Ensure parent directory exists (e.g., /root/bin)
|
||||||
|
mkdir -p "$(dirname "$RUNTIME_BINARY")" 2>/dev/null || true
|
||||||
|
cp "$STORED_BINARY" "$RUNTIME_BINARY"
|
||||||
|
chmod +x "$RUNTIME_BINARY"
|
||||||
|
fi
|
||||||
|
|
||||||
# Create symlink (or update if exists)
|
# Create symlink (or update if exists)
|
||||||
ln -sf "$SERVICE_STORAGE" "$SYSTEMD_LINK"
|
ln -sf "$SERVICE_STORAGE" "$SYSTEMD_LINK"
|
||||||
|
|
@ -689,8 +728,9 @@ systemctl restart "$SERVICE_NAME"
|
||||||
echo "Pulse agent started successfully"
|
echo "Pulse agent started successfully"
|
||||||
BOOTSTRAP
|
BOOTSTRAP
|
||||||
|
|
||||||
# Replace placeholder
|
# Replace placeholders
|
||||||
sed -i "s|STATE_DIR_PLACEHOLDER|${TRUENAS_STATE_DIR}|g" "$TRUENAS_BOOTSTRAP_SCRIPT"
|
sed -i "s|STATE_DIR_PLACEHOLDER|${TRUENAS_STATE_DIR}|g" "$TRUENAS_BOOTSTRAP_SCRIPT"
|
||||||
|
sed -i "s|RUNTIME_BINARY_PLACEHOLDER|${TRUENAS_RUNTIME_BINARY}|g" "$TRUENAS_BOOTSTRAP_SCRIPT"
|
||||||
chmod +x "$TRUENAS_BOOTSTRAP_SCRIPT"
|
chmod +x "$TRUENAS_BOOTSTRAP_SCRIPT"
|
||||||
|
|
||||||
# Create systemd symlink now
|
# Create systemd symlink now
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue