Files
Scripts/sshinstall.sh
edemilovandClaude Sonnet 5 84929af184 fix(sshinstall.sh): support non-systemd init (SysVinit, e.g. MX Linux)
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]>
2026-09-19 18:45:20 +03:00

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}"