The service step called `systemctl enable --now`, which aborts under `set -e` when systemd is not PID 1. On MX Linux (SysVinit) this meant sshd was never started and the firewall and admin-key steps were never reached. Detect systemd via /run/systemd/system; otherwise fall back to `update-rc.d`/`chkconfig` + `service <name> start`, failing with a clear message if the service cannot be started. Found on the first real-machine run (ThinkCentre M71e, MX Linux 25.2). Co-Authored-By: Claude Sonnet 5 <[email protected]>
170 lines
7.1 KiB
Bash
Executable File
170 lines
7.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
# sshinstall.sh — SSH bootstrap (install + enable sshd + deploy admin key)
|
|
# Debian/Ubuntu / Arch / RHEL/Fedora
|
|
#
|
|
# curl -s https://git.edemilov.ru/edemilov/scripts/raw/branch/master/sshinstall.sh | sudo bash
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
|
|
set -e
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'; MAGENTA='\033[0;35m'; BOLD='\033[1m'; NC='\033[0m'
|
|
info() { echo -e "${CYAN}[•]${NC} $1"; }
|
|
success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
|
skip() { echo -e "${MAGENTA}[~]${NC} $1 (already done)"; }
|
|
die() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
|
|
header() { echo -e "\n${BOLD}${CYAN}── $1 ──────────────────────────────${NC}"; }
|
|
|
|
ADMIN_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH/hWD8YgjVzA/9V364W4w2HiEpuPjKMQ/Id3SRlyriM edemilov@laptop"
|
|
|
|
echo -e "${BOLD}"
|
|
echo " ╔══════════════════════════════════════════════╗"
|
|
echo " ║ sshinstall.sh — SSH bootstrap ║"
|
|
echo " ╚══════════════════════════════════════════════╝"
|
|
echo -e "${NC}"
|
|
|
|
# ── Require root ─────────────────────────────────────────────────
|
|
[[ "$EUID" -eq 0 ]] || die "Must be run as root — re-run with sudo"
|
|
|
|
# ── Detect distro ─────────────────────────────────────────────────
|
|
header "Detecting system"
|
|
[[ -f /etc/os-release ]] && . /etc/os-release || die "Cannot detect distro"
|
|
DISTRO_ID="${ID,,}"
|
|
DISTRO_LIKE="${ID_LIKE,,}"
|
|
info "Distro: ${PRETTY_NAME}"
|
|
|
|
if command -v pacman &>/dev/null; then
|
|
FAMILY="arch"
|
|
elif [[ "$DISTRO_ID" =~ ^(kali|parrot|debian|ubuntu|linuxmint|pop)$ ]] || \
|
|
[[ "$DISTRO_LIKE" =~ debian ]] || [[ "$DISTRO_LIKE" =~ ubuntu ]]; then
|
|
FAMILY="debian"
|
|
elif command -v dnf &>/dev/null || command -v yum &>/dev/null; then
|
|
FAMILY="fedora"
|
|
else
|
|
die "Unsupported distro: $DISTRO_ID"
|
|
fi
|
|
info "Family: $FAMILY"
|
|
|
|
# ── Install SSH server ────────────────────────────────────────────
|
|
header "SSH server package"
|
|
case $FAMILY in
|
|
arch)
|
|
SERVICE="sshd"
|
|
if pacman -Qi openssh &>/dev/null; then
|
|
skip "openssh"
|
|
else
|
|
info "Installing openssh..."
|
|
pacman -S --noconfirm --needed openssh
|
|
success "openssh installed"
|
|
fi
|
|
;;
|
|
debian)
|
|
SERVICE="ssh"
|
|
if dpkg -l openssh-server 2>/dev/null | grep -q "^ii"; then
|
|
skip "openssh-server"
|
|
else
|
|
info "Installing openssh-server..."
|
|
apt-get update -qq
|
|
apt-get install -y -qq openssh-server
|
|
success "openssh-server installed"
|
|
fi
|
|
;;
|
|
fedora)
|
|
SERVICE="sshd"
|
|
if rpm -q openssh-server &>/dev/null; then
|
|
skip "openssh-server"
|
|
else
|
|
info "Installing openssh-server..."
|
|
if command -v dnf &>/dev/null; then
|
|
dnf install -y -q openssh-server
|
|
else
|
|
yum install -y -q openssh-server
|
|
fi
|
|
success "openssh-server installed"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# ── Enable + start service ────────────────────────────────────────
|
|
header "SSH service"
|
|
if [[ -d /run/systemd/system ]]; then
|
|
# systemd is PID 1
|
|
if systemctl is-active --quiet "$SERVICE"; then
|
|
skip "$SERVICE service"
|
|
else
|
|
info "Enabling + starting $SERVICE..."
|
|
systemctl enable --now "$SERVICE"
|
|
success "$SERVICE running"
|
|
fi
|
|
else
|
|
# SysVinit / no systemd (e.g. MX Linux default) — use the classic tools
|
|
warn "systemd is not running — using SysV init scripts"
|
|
if service "$SERVICE" status &>/dev/null; then
|
|
skip "$SERVICE service"
|
|
else
|
|
info "Enabling + starting $SERVICE (SysV)..."
|
|
if command -v update-rc.d &>/dev/null; then
|
|
update-rc.d "$SERVICE" defaults &>/dev/null || true
|
|
update-rc.d "$SERVICE" enable &>/dev/null || true
|
|
elif command -v chkconfig &>/dev/null; then
|
|
chkconfig "$SERVICE" on || true
|
|
fi
|
|
service "$SERVICE" start || die "Could not start $SERVICE via 'service' — check /etc/init.d/$SERVICE"
|
|
success "$SERVICE running"
|
|
fi
|
|
fi
|
|
|
|
# ── Firewall ───────────────────────────────────────────────────────
|
|
header "Firewall"
|
|
if command -v ufw &>/dev/null && ufw status | grep -q "Status: active"; then
|
|
if ufw status | grep -qE "^22(/tcp)?[[:space:]]+ALLOW"; then
|
|
skip "ufw port 22"
|
|
else
|
|
info "Opening port 22 via ufw..."
|
|
ufw allow 22/tcp
|
|
success "ufw rule added"
|
|
fi
|
|
elif command -v firewall-cmd &>/dev/null && systemctl is-active --quiet firewalld; then
|
|
if firewall-cmd --list-services | grep -qw ssh; then
|
|
skip "firewalld ssh service"
|
|
else
|
|
info "Opening ssh via firewalld..."
|
|
firewall-cmd --add-service=ssh --permanent
|
|
firewall-cmd --reload
|
|
success "firewalld rule added"
|
|
fi
|
|
else
|
|
warn "No active ufw/firewalld found — skipping firewall step (port 22 may already be open, or another firewall manager is in use)"
|
|
fi
|
|
|
|
# ── Deploy admin key ───────────────────────────────────────────────
|
|
header "Admin key"
|
|
REAL_USER="${SUDO_USER:-$(logname 2>/dev/null || echo $USER)}"
|
|
REAL_HOME=$(eval echo "~$REAL_USER")
|
|
SSH_DIR="$REAL_HOME/.ssh"
|
|
AUTH_KEYS="$SSH_DIR/authorized_keys"
|
|
|
|
mkdir -p "$SSH_DIR"
|
|
chmod 700 "$SSH_DIR"
|
|
touch "$AUTH_KEYS"
|
|
chmod 600 "$AUTH_KEYS"
|
|
chown -R "$REAL_USER:$REAL_USER" "$SSH_DIR"
|
|
|
|
if [[ -s "$AUTH_KEYS" ]] && [[ -n "$(tail -c1 "$AUTH_KEYS")" ]]; then
|
|
echo >> "$AUTH_KEYS"
|
|
fi
|
|
|
|
if grep -qF "$ADMIN_KEY" "$AUTH_KEYS" 2>/dev/null; then
|
|
skip "admin key in $AUTH_KEYS"
|
|
else
|
|
echo "$ADMIN_KEY" >> "$AUTH_KEYS"
|
|
success "admin key added to $AUTH_KEYS"
|
|
fi
|
|
|
|
echo -e "${BOLD}${GREEN}"
|
|
echo " ╔══════════════════════════════════════════════╗"
|
|
echo " ║ Done — SSH ready, key deployed ║"
|
|
echo " ╚══════════════════════════════════════════════╝"
|
|
echo -e "${NC}"
|