Add noexec /tmp detection — fall back to /usr/local/src for staging
Lint Scripts / powershell-lint (push) Failing after 13m25s
Lint Scripts / shellcheck (push) Failing after 17m44s

Scripts auto-detect noexec /tmp by attempting to execute a test script.
If /tmp is noexec, staging directory falls back to /usr/local/src.
Supports mixed fleets with both noexec and standard /tmp mounts.

Updated: deploy-exporter (1.1), install-node-exporter (1.2),
install-prometheus-stack (3.2), update-prometheus-stack (1.02),
install-snort (1.02), install-ntfy-server (1.1), install-bot-monitor (1.2)
This commit is contained in:
2026-05-26 16:16:33 +02:00
parent 166e07085a
commit d0d51be49a
7 changed files with 127 additions and 42 deletions
+15 -3
View File
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
################################################################################ ################################################################################
# Script Name: deploy-exporter.sh # Script Name: deploy-exporter.sh
# Version: 1.0 # Version: 1.1
# Description: Deployment tool for Prometheus exporters from mylinux.work. # Description: Deployment tool for Prometheus exporters from mylinux.work.
# Downloads, installs, configures cron jobs, validates output, # Downloads, installs, configures cron jobs, validates output,
# and manages lifecycle (install, update, remove, status) for # and manages lifecycle (install, update, remove, status) for
@@ -38,6 +38,18 @@ INSTALL_DIR="/usr/local/bin"
CRON_DIR="/etc/cron.d" CRON_DIR="/etc/cron.d"
TEXTFILE_DIR="/var/lib/node_exporter" TEXTFILE_DIR="/var/lib/node_exporter"
# Detect noexec /tmp — fall back to /usr/local/src for staging
STAGE_DIR="/tmp"
_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null)
if [[ -n "$_exec_test" ]]; then
printf '#!/bin/sh\nexit 0\n' > "$_exec_test"
chmod +x "$_exec_test"
"$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src"
rm -f "$_exec_test"
else
STAGE_DIR="/usr/local/src"
fi
# ============================================================================ # ============================================================================
# AVAILABLE EXPORTERS # AVAILABLE EXPORTERS
# ============================================================================ # ============================================================================
@@ -328,7 +340,7 @@ install_one() {
log "Installing ${name}..." log "Installing ${name}..."
temp_file=$(mktemp "/tmp/${name}.XXXXXX") temp_file=$(mktemp "${STAGE_DIR}/${name}.XXXXXX")
if ! download "$url" "$temp_file"; then if ! download "$url" "$temp_file"; then
rm -f "$temp_file" rm -f "$temp_file"
err "Failed to download ${url}" err "Failed to download ${url}"
@@ -503,7 +515,7 @@ cmd_update() {
local url="${BASE_URL}/${name}.sh" local url="${BASE_URL}/${name}.sh"
local temp_file local temp_file
temp_file=$(mktemp "/tmp/${name}.XXXXXX") temp_file=$(mktemp "${STAGE_DIR}/${name}.XXXXXX")
if ! download "$url" "$temp_file"; then if ! download "$url" "$temp_file"; then
rm -f "$temp_file" rm -f "$temp_file"
+21 -9
View File
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
################################################################################ ################################################################################
# Script Name: install-bot-monitor.sh # Script Name: install-bot-monitor.sh
# Version: 1.1 # Version: 1.2
# Description: Install the bot-monitor script, known agents whitelist, and # Description: Install the bot-monitor script, known agents whitelist, and
# daily cron job. Detects unknown user agents in web server logs # daily cron job. Detects unknown user agents in web server logs
# and sends alerts via ntfy and/or Prometheus textfile metrics. # and sends alerts via ntfy and/or Prometheus textfile metrics.
@@ -375,7 +375,19 @@ step "Installing bot-monitor script"
SCRIPT_FILE="/usr/local/bin/bot-monitor.sh" SCRIPT_FILE="/usr/local/bin/bot-monitor.sh"
cat > /tmp/bot-monitor.sh.tmp << 'SCRIPTEOF' # Detect noexec /tmp — fall back to /usr/local/src
STAGE_DIR="/tmp"
_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null)
if [[ -n "$_exec_test" ]]; then
printf '#!/bin/sh\nexit 0\n' > "$_exec_test"
chmod +x "$_exec_test"
"$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src"
rm -f "$_exec_test"
else
STAGE_DIR="/usr/local/src"
fi
cat > ${STAGE_DIR}/bot-monitor.sh.tmp << 'SCRIPTEOF'
#!/bin/bash #!/bin/bash
# /usr/local/bin/bot-monitor.sh # /usr/local/bin/bot-monitor.sh
# Detects unknown user agents in yesterday's web server logs. # Detects unknown user agents in yesterday's web server logs.
@@ -478,12 +490,12 @@ find "$STATE_DIR" -name "unknown-*.txt" -mtime +30 -delete 2>/dev/null || true
SCRIPTEOF SCRIPTEOF
# Replace placeholders with actual values # Replace placeholders with actual values
sed -i "s|__LOG_DIR__|${LOG_DIR}|g" /tmp/bot-monitor.sh.tmp sed -i "s|__LOG_DIR__|${LOG_DIR}|g" ${STAGE_DIR}/bot-monitor.sh.tmp
sed -i "s|__LOG_PATTERN__|${LOG_PATTERN}|g" /tmp/bot-monitor.sh.tmp sed -i "s|__LOG_PATTERN__|${LOG_PATTERN}|g" ${STAGE_DIR}/bot-monitor.sh.tmp
sed -i "s|__NTFY_URL__|${NTFY_URL}|g" /tmp/bot-monitor.sh.tmp sed -i "s|__NTFY_URL__|${NTFY_URL}|g" ${STAGE_DIR}/bot-monitor.sh.tmp
sed -i "s|__TEXTFILE_DIR__|${TEXTFILE_DIR}|g" /tmp/bot-monitor.sh.tmp sed -i "s|__TEXTFILE_DIR__|${TEXTFILE_DIR}|g" ${STAGE_DIR}/bot-monitor.sh.tmp
sed -i "s|__TEXTFILE_ENABLED__|${TEXTFILE_ENABLED}|g" /tmp/bot-monitor.sh.tmp sed -i "s|__TEXTFILE_ENABLED__|${TEXTFILE_ENABLED}|g" ${STAGE_DIR}/bot-monitor.sh.tmp
sed -i "s|__MIN_REQUESTS__|${MIN_REQUESTS}|g" /tmp/bot-monitor.sh.tmp sed -i "s|__MIN_REQUESTS__|${MIN_REQUESTS}|g" ${STAGE_DIR}/bot-monitor.sh.tmp
if [[ "$DRY_RUN" == "true" ]]; then if [[ "$DRY_RUN" == "true" ]]; then
echo " Would install: ${SCRIPT_FILE}" echo " Would install: ${SCRIPT_FILE}"
@@ -497,7 +509,7 @@ else
cp "$SCRIPT_FILE" "${SCRIPT_FILE}.bak.$(date +%s)" cp "$SCRIPT_FILE" "${SCRIPT_FILE}.bak.$(date +%s)"
warn "Existing script backed up" warn "Existing script backed up"
fi fi
mv /tmp/bot-monitor.sh.tmp "$SCRIPT_FILE" mv ${STAGE_DIR}/bot-monitor.sh.tmp "$SCRIPT_FILE"
chmod +x "$SCRIPT_FILE" chmod +x "$SCRIPT_FILE"
info "Installed: ${SCRIPT_FILE}" info "Installed: ${SCRIPT_FILE}"
fi fi
+15 -2
View File
@@ -9,7 +9,7 @@ set -euo pipefail
#### Author: Phil Connor #### #### Author: Phil Connor ####
#### Contact: contact@mylinux.work #### #### Contact: contact@mylinux.work ####
#### License: MIT #### #### License: MIT ####
#### Version: 1.1 #### #### Version: 1.2 ####
#### #### #### ####
#### Usage: ./install-node-exporter.sh [OPTIONS] #### #### Usage: ./install-node-exporter.sh [OPTIONS] ####
############################################################# #############################################################
@@ -208,7 +208,20 @@ create_service_user() {
download_and_install() { download_and_install() {
local version="$1" local version="$1"
TMPDIR=$(mktemp -d /tmp/node-exporter-install-XXXXXX) # Detect noexec /tmp — fall back to /usr/local/src
local stage_dir="/tmp"
local _exec_test
_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null)
if [[ -n "$_exec_test" ]]; then
printf '#!/bin/sh\nexit 0\n' > "$_exec_test"
chmod +x "$_exec_test"
"$_exec_test" 2>/dev/null || stage_dir="/usr/local/src"
rm -f "$_exec_test"
else
stage_dir="/usr/local/src"
fi
TMPDIR=$(mktemp -d "${stage_dir}/node-exporter-install-XXXXXX")
local tarball="node_exporter-${version}.linux-${ARCH}.tar.gz" local tarball="node_exporter-${version}.linux-${ARCH}.tar.gz"
local url="https://github.com/prometheus/node_exporter/releases/download/v${version}/${tarball}" local url="https://github.com/prometheus/node_exporter/releases/download/v${version}/${tarball}"
+19 -7
View File
@@ -7,7 +7,7 @@
#### Author: Phil Connor #### #### Author: Phil Connor ####
#### Contact: contact@mylinux.work #### #### Contact: contact@mylinux.work ####
#### License: MIT #### #### License: MIT ####
#### Version: 1.0 #### #### Version: 1.1 ####
#### #### #### ####
#### Usage: sudo ./install-ntfy-server.sh #### #### Usage: sudo ./install-ntfy-server.sh ####
############################################################# #############################################################
@@ -28,6 +28,18 @@ if [[ $EUID -ne 0 ]]; then
exit 1 exit 1
fi fi
# Detect noexec /tmp — fall back to /usr/local/src
STAGE_DIR="/tmp"
_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null)
if [[ -n "$_exec_test" ]]; then
printf '#!/bin/sh\nexit 0\n' > "$_exec_test"
chmod +x "$_exec_test"
"$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src"
rm -f "$_exec_test"
else
STAGE_DIR="/usr/local/src"
fi
echo "=== Installing ntfy v${NTFY_VERSION} ===" echo "=== Installing ntfy v${NTFY_VERSION} ==="
# Create ntfy user # Create ntfy user
@@ -43,13 +55,13 @@ chown "$NTFY_USER:$NTFY_USER" "$NTFY_DIR"
# Download and install ntfy # Download and install ntfy
echo "Downloading ntfy..." echo "Downloading ntfy..."
rm -rf /tmp/ntfy_extract rm -rf ${STAGE_DIR}/ntfy_extract
mkdir -p /tmp/ntfy_extract mkdir -p ${STAGE_DIR}/ntfy_extract
wget -q -O /tmp/ntfy.tar.gz "https://github.com/binwiederhier/ntfy/releases/download/v${NTFY_VERSION}/ntfy_${NTFY_VERSION}_linux_amd64.tar.gz" wget -q -O ${STAGE_DIR}/ntfy.tar.gz "https://github.com/binwiederhier/ntfy/releases/download/v${NTFY_VERSION}/ntfy_${NTFY_VERSION}_linux_amd64.tar.gz"
tar -xzf /tmp/ntfy.tar.gz -C /tmp/ntfy_extract tar -xzf ${STAGE_DIR}/ntfy.tar.gz -C ${STAGE_DIR}/ntfy_extract
find /tmp/ntfy_extract -name "ntfy" -type f -exec mv {} /usr/local/bin/ntfy \; find ${STAGE_DIR}/ntfy_extract -name "ntfy" -type f -exec mv {} /usr/local/bin/ntfy \;
chmod +x /usr/local/bin/ntfy chmod +x /usr/local/bin/ntfy
rm -rf /tmp/ntfy.tar.gz /tmp/ntfy_extract rm -rf ${STAGE_DIR}/ntfy.tar.gz ${STAGE_DIR}/ntfy_extract
# Verify installation # Verify installation
echo "Verifying installation..." echo "Verifying installation..."
+22 -10
View File
@@ -9,7 +9,7 @@ set -euo pipefail
#### Author: Phil Connor #### #### Author: Phil Connor ####
#### Contact: contact@mylinux.work #### #### Contact: contact@mylinux.work ####
#### License: MIT #### #### License: MIT ####
#### Version: 3.1 #### #### Version: 3.2 ####
#### #### #### ####
#### Usage: ./install-prometheus-stack.sh [OPTIONS] #### #### Usage: ./install-prometheus-stack.sh [OPTIONS] ####
############################################################# #############################################################
@@ -105,9 +105,21 @@ CONFIG FILE FORMAT:
EOF EOF
} }
# Detect noexec /tmp — fall back to /usr/local/src
STAGE_DIR="/tmp"
_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null)
if [[ -n "$_exec_test" ]]; then
printf '#!/bin/sh\nexit 0\n' > "$_exec_test"
chmod +x "$_exec_test"
"$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src"
rm -f "$_exec_test"
else
STAGE_DIR="/usr/local/src"
fi
cleanup() { cleanup() {
if [[ -d "/tmp/prometheus-install-$$" ]]; then if [[ -d "${STAGE_DIR}/prometheus-install-$$" ]]; then
rm -rf "/tmp/prometheus-install-$$" rm -rf "${STAGE_DIR}/prometheus-install-$$"
fi fi
} }
@@ -262,7 +274,7 @@ install_prometheus() {
return return
fi fi
local workdir="/tmp/prometheus-install-$$/prometheus" local workdir="${STAGE_DIR}/prometheus-install-$$/prometheus"
mkdir -p "$workdir" mkdir -p "$workdir"
cd "$workdir" cd "$workdir"
@@ -417,7 +429,7 @@ install_node_exporter() {
return return
fi fi
local workdir="/tmp/prometheus-install-$$/node_exporter" local workdir="${STAGE_DIR}/prometheus-install-$$/node_exporter"
mkdir -p "$workdir" mkdir -p "$workdir"
cd "$workdir" cd "$workdir"
@@ -494,7 +506,7 @@ install_blackbox() {
return return
fi fi
local workdir="/tmp/prometheus-install-$$/blackbox" local workdir="${STAGE_DIR}/prometheus-install-$$/blackbox"
mkdir -p "$workdir" mkdir -p "$workdir"
cd "$workdir" cd "$workdir"
@@ -686,7 +698,7 @@ install_loki() {
return return
fi fi
local workdir="/tmp/prometheus-install-$$/loki" local workdir="${STAGE_DIR}/prometheus-install-$$/loki"
mkdir -p "$workdir" mkdir -p "$workdir"
cd "$workdir" cd "$workdir"
@@ -830,7 +842,7 @@ install_alloy() {
return return
fi fi
local workdir="/tmp/prometheus-install-$$/alloy" local workdir="${STAGE_DIR}/prometheus-install-$$/alloy"
mkdir -p "$workdir" mkdir -p "$workdir"
cd "$workdir" cd "$workdir"
@@ -1243,7 +1255,7 @@ install_alertmanager() {
return return
fi fi
local workdir="/tmp/prometheus-install-$$/alertmanager" local workdir="${STAGE_DIR}/prometheus-install-$$/alertmanager"
mkdir -p "$workdir" mkdir -p "$workdir"
cd "$workdir" cd "$workdir"
@@ -1337,7 +1349,7 @@ install_mysql_exporter() {
return return
fi fi
local workdir="/tmp/prometheus-install-$$/mysql_exporter" local workdir="${STAGE_DIR}/prometheus-install-$$/mysql_exporter"
mkdir -p "$workdir" mkdir -p "$workdir"
cd "$workdir" cd "$workdir"
+21 -9
View File
@@ -8,7 +8,7 @@
# Contact: contact@mylinux.work # Contact: contact@mylinux.work
# Website: https://mylinux.work # Website: https://mylinux.work
# License: MIT # License: MIT
# Version: 1.01 # Version: 1.02
# #
# Usage: # Usage:
# sudo ./install-snort.sh # sudo ./install-snort.sh
@@ -39,6 +39,18 @@ DRY_RUN=false
UNINSTALL=false UNINSTALL=false
SKIP_BUILD=false SKIP_BUILD=false
# Detect noexec /tmp — fall back to /usr/local/src
STAGE_DIR="/tmp"
_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null)
if [[ -n "$_exec_test" ]]; then
printf '#!/bin/sh\nexit 0\n' > "$_exec_test"
chmod +x "$_exec_test"
"$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src"
rm -f "$_exec_test"
else
STAGE_DIR="/usr/local/src"
fi
# Colors # Colors
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
@@ -201,7 +213,7 @@ install_dependencies() {
build_libdaq() { build_libdaq() {
log_step "Building libdaq $DAQ_VERSION..." log_step "Building libdaq $DAQ_VERSION..."
local build_dir="/tmp/snort-build" local build_dir="${STAGE_DIR}/snort-build"
mkdir -p "$build_dir" mkdir -p "$build_dir"
cd "$build_dir" cd "$build_dir"
@@ -224,7 +236,7 @@ build_libdaq() {
build_snort() { build_snort() {
log_step "Building Snort $SNORT_VERSION..." log_step "Building Snort $SNORT_VERSION..."
local build_dir="/tmp/snort-build" local build_dir="${STAGE_DIR}/snort-build"
mkdir -p "$build_dir" mkdir -p "$build_dir"
cd "$build_dir" cd "$build_dir"
@@ -336,16 +348,16 @@ download_rules() {
if [[ "$COMMUNITY_RULES" == true ]]; then if [[ "$COMMUNITY_RULES" == true ]]; then
log_info "Downloading community rules..." log_info "Downloading community rules..."
local community_url="https://www.snort.org/downloads/community/snort3-community-rules.tar.gz" local community_url="https://www.snort.org/downloads/community/snort3-community-rules.tar.gz"
wget -q "$community_url" -O /tmp/snort3-community-rules.tar.gz || { wget -q "$community_url" -O ${STAGE_DIR}/snort3-community-rules.tar.gz || {
log_warn "Failed to download community rules — trying alternative URL" log_warn "Failed to download community rules — trying alternative URL"
wget -q "https://www.snort.org/downloads/community/community-rules.tar.gz" \ wget -q "https://www.snort.org/downloads/community/community-rules.tar.gz" \
-O /tmp/snort3-community-rules.tar.gz || { -O ${STAGE_DIR}/snort3-community-rules.tar.gz || {
log_error "Cannot download community rules" log_error "Cannot download community rules"
return 1 return 1
} }
} }
tar xzf /tmp/snort3-community-rules.tar.gz -C /tmp/ tar xzf ${STAGE_DIR}/snort3-community-rules.tar.gz -C ${STAGE_DIR}/
find /tmp/ -name '*.rules' -path '*community*' -exec cp {} "$RULE_DIR/" \; find ${STAGE_DIR}/ -name '*.rules' -path '*community*' -exec cp {} "$RULE_DIR/" \;
log_info "Community rules installed to $RULE_DIR/" log_info "Community rules installed to $RULE_DIR/"
fi fi
@@ -355,11 +367,11 @@ download_rules() {
else else
log_info "Downloading registered rules with Oinkcode..." log_info "Downloading registered rules with Oinkcode..."
local reg_url="https://www.snort.org/reg-rules/snortrules-snapshot-31840.tar.gz/$OINKCODE" local reg_url="https://www.snort.org/reg-rules/snortrules-snapshot-31840.tar.gz/$OINKCODE"
wget -q "$reg_url" -O /tmp/snort-registered-rules.tar.gz || { wget -q "$reg_url" -O ${STAGE_DIR}/snort-registered-rules.tar.gz || {
log_error "Failed to download registered rules (check Oinkcode)" log_error "Failed to download registered rules (check Oinkcode)"
return 1 return 1
} }
tar xzf /tmp/snort-registered-rules.tar.gz -C "$RULE_DIR/" tar xzf ${STAGE_DIR}/snort-registered-rules.tar.gz -C "$RULE_DIR/"
log_info "Registered rules installed to $RULE_DIR/" log_info "Registered rules installed to $RULE_DIR/"
fi fi
fi fi
+14 -2
View File
@@ -35,14 +35,26 @@ set -euo pipefail
## ## ## ##
## Author: Phil Connor ## ## Author: Phil Connor ##
## Contact: pconnor@ara.com ## ## Contact: pconnor@ara.com ##
## Version: 1.01 ## ## Version: 1.02 ##
########################################################################## ##########################################################################
BINDIR="/usr/local/bin" BINDIR="/usr/local/bin"
PROMDIR="/etc/prometheus" PROMDIR="/etc/prometheus"
BACKUPDIR="${PROMDIR}/backups" BACKUPDIR="${PROMDIR}/backups"
LOGFILE="/var/log/prometheus-update.log" LOGFILE="/var/log/prometheus-update.log"
TMPDIR_BASE="/tmp/prometheus-update-$$" # Detect noexec /tmp — fall back to /usr/local/src
STAGE_DIR="/tmp"
_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null)
if [[ -n "$_exec_test" ]]; then
printf '#!/bin/sh\nexit 0\n' > "$_exec_test"
chmod +x "$_exec_test"
"$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src"
rm -f "$_exec_test"
else
STAGE_DIR="/usr/local/src"
fi
TMPDIR_BASE="${STAGE_DIR}/prometheus-update-$$"
CHECK_ONLY=false CHECK_ONLY=false
BACKUP_ONLY=false BACKUP_ONLY=false
FORCE=false FORCE=false