259 lines
8.2 KiB
Bash
Executable File
259 lines
8.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# Setup a remote server for infmap monitoring.
|
|
# Run as root: curl -fsSL <url>/setup-remote.sh | bash -s <public-key-url>
|
|
#
|
|
# What this does:
|
|
# 1. Creates a locked-down 'infmap' user (no password, no login shell abuse)
|
|
# 2. Downloads your public key and installs it with SSH restrictions
|
|
# 3. Disables password auth for the infmap user
|
|
# 4. Installs lm-sensors, pciutils, iproute2, util-linux for full gather coverage
|
|
|
|
set -euo pipefail
|
|
|
|
BUILD_DATE="__BUILD_DATE__"
|
|
echo "infmap setup-remote (built: ${BUILD_DATE})"
|
|
|
|
# --- Args ---
|
|
|
|
KEY_URL="${1:-https://getbin.xyz/infmap-pub}"
|
|
|
|
# --- Must be root ---
|
|
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "Error: must run as root"
|
|
exit 1
|
|
fi
|
|
|
|
# --- Detect OS ---
|
|
|
|
detect_os() {
|
|
if [ -f /etc/os-release ]; then
|
|
. /etc/os-release
|
|
case "$ID" in
|
|
debian|ubuntu|raspbian) echo "debian" ;;
|
|
alpine) echo "alpine" ;;
|
|
openwrt) echo "openwrt" ;;
|
|
unraid-os|slackware) echo "unraid" ;;
|
|
*) echo "unknown" ;;
|
|
esac
|
|
elif [ -f /etc/openwrt_release ]; then
|
|
echo "openwrt"
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
OS=$(detect_os)
|
|
echo "Detected OS: $OS"
|
|
|
|
# --- Create user ---
|
|
|
|
USERNAME="infmap"
|
|
|
|
create_user() {
|
|
if id "$USERNAME" &>/dev/null; then
|
|
echo "User '$USERNAME' already exists"
|
|
else
|
|
case "$OS" in
|
|
debian)
|
|
adduser --system --group --shell /bin/bash --home "/home/$USERNAME" "$USERNAME"
|
|
;;
|
|
alpine)
|
|
adduser -D -s /bin/bash -h "/home/$USERNAME" "$USERNAME" 2>/dev/null || \
|
|
adduser -D -s /bin/sh -h "/home/$USERNAME" "$USERNAME"
|
|
;;
|
|
openwrt)
|
|
# OpenWrt uses busybox adduser
|
|
grep -q "^$USERNAME:" /etc/passwd || \
|
|
echo "$USERNAME:x:1000:1000:infmap:/home/$USERNAME:/bin/ash" >> /etc/passwd
|
|
mkdir -p "/home/$USERNAME"
|
|
chown "$USERNAME" "/home/$USERNAME"
|
|
;;
|
|
unraid)
|
|
useradd -m -s /bin/bash "$USERNAME" 2>/dev/null || true
|
|
;;
|
|
*)
|
|
useradd --system --create-home --shell /bin/bash "$USERNAME" 2>/dev/null || \
|
|
adduser --system --group --shell /bin/bash --home "/home/$USERNAME" "$USERNAME"
|
|
;;
|
|
esac
|
|
echo "Created user '$USERNAME'"
|
|
fi
|
|
|
|
# Lock password - prevents password login, key auth still works
|
|
case "$OS" in
|
|
openwrt)
|
|
sed -i "s|^$USERNAME:[^:]*:|$USERNAME:*:|" /etc/passwd
|
|
;;
|
|
*)
|
|
passwd -l "$USERNAME" 2>/dev/null || usermod -L "$USERNAME" 2>/dev/null || true
|
|
;;
|
|
esac
|
|
}
|
|
|
|
create_user
|
|
|
|
# --- Download and install public key ---
|
|
|
|
HOMEDIR=$(eval echo "~$USERNAME")
|
|
SSH_DIR="$HOMEDIR/.ssh"
|
|
AUTH_KEYS="$SSH_DIR/authorized_keys"
|
|
|
|
mkdir -p "$SSH_DIR"
|
|
chmod 700 "$SSH_DIR"
|
|
|
|
echo "Downloading public key from $KEY_URL ..."
|
|
PUBKEY=$(curl -fsSL "$KEY_URL") || { echo "Error: failed to download key from $KEY_URL"; exit 1; }
|
|
|
|
# Validate it looks like an SSH public key
|
|
if ! echo "$PUBKEY" | grep -qE '^(ssh-(ed25519|rsa)|ecdsa-sha2)'; then
|
|
echo "Error: downloaded content doesn't look like an SSH public key"
|
|
echo "Got: $(echo "$PUBKEY" | head -c 80)"
|
|
exit 1
|
|
fi
|
|
|
|
# Restrict: only allow bash -s (stdin script execution), no forwarding/pty
|
|
RESTRICTED_KEY="command=\"/bin/bash -s\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty $PUBKEY"
|
|
|
|
# Replace any existing infmap key or append
|
|
if [ -f "$AUTH_KEYS" ]; then
|
|
# Remove old entries for this key (match on key data)
|
|
KEY_DATA=$(echo "$PUBKEY" | awk '{print $2}')
|
|
grep -v "$KEY_DATA" "$AUTH_KEYS" > "$AUTH_KEYS.tmp" 2>/dev/null || true
|
|
mv "$AUTH_KEYS.tmp" "$AUTH_KEYS"
|
|
fi
|
|
|
|
echo "$RESTRICTED_KEY" >> "$AUTH_KEYS"
|
|
chmod 600 "$AUTH_KEYS"
|
|
chown -R "$USERNAME" "$SSH_DIR"
|
|
|
|
# If the OS uses a group, fix group ownership
|
|
GID=$(id -g "$USERNAME" 2>/dev/null) && chgrp -R "$GID" "$SSH_DIR" 2>/dev/null || true
|
|
|
|
echo "Public key installed with restrictions"
|
|
|
|
# --- Ensure key-only SSH for this user ---
|
|
|
|
SSHD_CONFIG="/etc/ssh/sshd_config"
|
|
if [ -f "$SSHD_CONFIG" ]; then
|
|
MATCH_BLOCK="Match User $USERNAME
|
|
PasswordAuthentication no
|
|
KbdInteractiveAuthentication no"
|
|
|
|
if grep -q "Match User $USERNAME" "$SSHD_CONFIG"; then
|
|
echo "SSH Match block for '$USERNAME' already exists"
|
|
else
|
|
printf '\n%s\n' "$MATCH_BLOCK" >> "$SSHD_CONFIG"
|
|
echo "Added SSH Match block: key-only auth for '$USERNAME'"
|
|
fi
|
|
|
|
# Reload sshd
|
|
if command -v systemctl &>/dev/null; then
|
|
systemctl reload sshd 2>/dev/null || systemctl reload ssh 2>/dev/null || true
|
|
elif command -v service &>/dev/null; then
|
|
service sshd reload 2>/dev/null || service ssh reload 2>/dev/null || true
|
|
elif [ -f /etc/init.d/sshd ]; then
|
|
/etc/init.d/sshd reload 2>/dev/null || true
|
|
fi
|
|
echo "sshd reloaded"
|
|
elif [ "$OS" = "openwrt" ] && [ -f /etc/config/dropbear ]; then
|
|
echo "Note: OpenWrt uses dropbear. Password auth is controlled via /etc/config/dropbear"
|
|
echo " Ensure 'option PasswordAuth off' or rely on the locked password."
|
|
fi
|
|
|
|
# --- Install dependencies ---
|
|
|
|
install_packages() {
|
|
echo "Installing dependencies..."
|
|
case "$OS" in
|
|
debian)
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -qq
|
|
apt-get install -y -qq sudo lm-sensors pciutils iproute2 util-linux intel-gpu-tools >/dev/null 2>&1 || \
|
|
apt-get install -y -qq sudo lm-sensors pciutils iproute2 util-linux >/dev/null
|
|
# Auto-detect sensor modules
|
|
sensors-detect --auto </dev/null >/dev/null 2>&1 || true
|
|
;;
|
|
alpine)
|
|
apk update --quiet
|
|
apk add --quiet sudo lm-sensors pciutils iproute2 util-linux bash intel-gpu-tools 2>/dev/null || \
|
|
apk add --quiet sudo lm-sensors pciutils iproute2 util-linux bash
|
|
# Auto-detect sensor modules
|
|
sensors-detect --auto </dev/null >/dev/null 2>&1 || true
|
|
;;
|
|
openwrt)
|
|
opkg update >/dev/null 2>&1
|
|
# Best-effort - not all packages exist on all architectures
|
|
opkg install sudo lm-sensors pciutils ip-full coreutils-stat 2>/dev/null || true
|
|
;;
|
|
unraid)
|
|
# Unraid ships with most tools pre-installed
|
|
echo "Unraid detected - tools are pre-installed"
|
|
;;
|
|
*)
|
|
echo "Warning: unknown OS, skipping package install"
|
|
echo "Manually install: lm-sensors pciutils iproute2 util-linux"
|
|
return
|
|
;;
|
|
esac
|
|
echo "Dependencies installed"
|
|
}
|
|
|
|
install_packages
|
|
|
|
# --- Grant read access to hardware info ---
|
|
|
|
# Some sensor/DMI files need group access
|
|
if [ "$OS" != "openwrt" ]; then
|
|
# Add infmap to common hardware-access groups if they exist
|
|
for group in i2c sensors docker; do
|
|
getent group "$group" &>/dev/null && usermod -aG "$group" "$USERNAME" 2>/dev/null || true
|
|
done
|
|
fi
|
|
|
|
# --- Sudoers for container/VM commands ---
|
|
|
|
SUDOERS_FILE="/etc/sudoers.d/infmap"
|
|
SUDO_CMDS=""
|
|
|
|
# Detect which hypervisor tools are present (check common sbin paths too)
|
|
for cmd in pct qm lxc virsh docker intel_gpu_top; do
|
|
cmd_path=$(command -v "$cmd" 2>/dev/null || true)
|
|
# Also check sbin paths not always in PATH
|
|
if [ -z "$cmd_path" ]; then
|
|
for p in /usr/sbin/$cmd /usr/local/sbin/$cmd /sbin/$cmd; do
|
|
if [ -x "$p" ]; then
|
|
cmd_path="$p"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
if [ -n "$cmd_path" ]; then
|
|
SUDO_CMDS="${SUDO_CMDS}${USERNAME} ALL=(root) NOPASSWD: ${cmd_path}\n"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$SUDO_CMDS" ]; then
|
|
printf "%b" "$SUDO_CMDS" > "$SUDOERS_FILE"
|
|
chmod 440 "$SUDOERS_FILE"
|
|
echo "Sudoers rules added for container/VM commands"
|
|
else
|
|
echo "No hypervisor tools found, skipping sudoers"
|
|
fi
|
|
|
|
# --- Summary ---
|
|
|
|
echo ""
|
|
echo "=== Setup complete ==="
|
|
echo " User: $USERNAME"
|
|
echo " Home: $HOMEDIR"
|
|
echo " Auth: key-only (password disabled)"
|
|
echo " SSH key: restricted to 'bash -s' (no shell, no forwarding)"
|
|
echo " Packages: lm-sensors, pciutils, iproute2"
|
|
if [ -n "$SUDO_CMDS" ]; then
|
|
echo " Sudo: container/VM commands (pct, qm, lxc, virsh)"
|
|
fi
|
|
echo ""
|
|
echo "Add to your infrastructure.conf:"
|
|
echo " $(hostname)"
|