#!/bin/bash # Setup a remote server for infmap monitoring. # Run as root: curl -fsSL /setup-remote.sh | bash -s # # 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" ;; *) 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" ;; *) 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 >/dev/null # Auto-detect sensor modules sensors-detect --auto >/dev/null 2>&1 || true ;; alpine) apk update --quiet apk add --quiet sudo lm-sensors pciutils iproute2 util-linux bash # Auto-detect sensor modules sensors-detect --auto >/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 ;; *) 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; do cmd_path=$(command -v "$cmd" 2>/dev/null) # 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)"